diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/boot/compressed/head.S linux.2.5.47-ac4/arch/i386/boot/compressed/head.S --- linux.2.5.47/arch/i386/boot/compressed/head.S 2002-10-31 14:57:24.000000000 +0000 +++ linux.2.5.47-ac4/arch/i386/boot/compressed/head.S 2002-10-31 15:05:49.000000000 +0000 @@ -31,7 +31,7 @@ startup_32: cld cli - movl $(__KERNEL_DS),%eax + movl $(__BOOT_DS),%eax movl %eax,%ds movl %eax,%es movl %eax,%fs @@ -74,7 +74,7 @@ popl %esi # discard address popl %esi # real mode pointer xorl %ebx,%ebx - ljmp $(__KERNEL_CS), $0x100000 + ljmp $(__BOOT_CS), $0x100000 /* * We come here, if we were loaded high. @@ -101,7 +101,7 @@ popl %eax # hcount movl $0x100000,%edi cli # make sure we don't get interrupted - ljmp $(__KERNEL_CS), $0x1000 # and jump to the move routine + ljmp $(__BOOT_CS), $0x1000 # and jump to the move routine /* * Routine (template) for moving the decompressed kernel in place, @@ -124,5 +124,5 @@ movsl movl %ebx,%esi # Restore setup pointer xorl %ebx,%ebx - ljmp $(__KERNEL_CS), $0x100000 + ljmp $(__BOOT_CS), $0x100000 move_routine_end: diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/boot/compressed/misc.c linux.2.5.47-ac4/arch/i386/boot/compressed/misc.c --- linux.2.5.47/arch/i386/boot/compressed/misc.c 2002-10-31 14:57:24.000000000 +0000 +++ linux.2.5.47-ac4/arch/i386/boot/compressed/misc.c 2002-10-31 15:05:49.000000000 +0000 @@ -299,7 +299,7 @@ struct { long * a; short b; - } stack_start = { & user_stack [STACK_SIZE] , __KERNEL_DS }; + } stack_start = { & user_stack [STACK_SIZE] , __BOOT_DS }; static void setup_normal_output_buffer(void) { @@ -377,3 +377,7 @@ 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 -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/boot/setup.S linux.2.5.47-ac4/arch/i386/boot/setup.S --- linux.2.5.47/arch/i386/boot/setup.S 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.47-ac4/arch/i386/boot/setup.S 2002-10-31 15:17:17.000000000 +0000 @@ -476,6 +476,24 @@ movsb popw %ds no_mca: +#ifdef CONFIG_VOYAGER + movb $0xff, 0x40 # flag on config found + movb $0xc0, %al + mov $0xff, %ah + int $0x15 # put voyager config info at es:di + jc no_voyager + movw $0x40, %si # place voyager info in apm table + cld + movw $7, %cx +voyager_rep: + movb %es:(%di), %al + movb %al,(%si) + incw %di + incw %si + decw %cx + jnz voyager_rep +no_voyager: +#endif # Check for PS/2 pointing device movw %cs, %ax # aka SETUPSEG subw $DELTA_INITSEG, %ax # aka INITSEG @@ -740,6 +758,7 @@ A20_ENABLE_LOOPS = 255 # Total loops to try +#ifndef CONFIG_VOYAGER a20_try_loop: # First, see if we are on a system with no A20 gate. @@ -758,11 +777,14 @@ jnz a20_done # Try enabling A20 through the keyboard controller +#endif /* CONFIG_VOYAGER */ a20_kbc: call empty_8042 +#ifndef CONFIG_VOYAGER call a20_test # Just in case the BIOS worked jnz a20_done # but had a delayed reaction. +#endif movb $0xD1, %al # command write outb %al, $0x64 @@ -772,6 +794,7 @@ outb %al, $0x60 call empty_8042 +#ifndef CONFIG_VOYAGER # Wait until a20 really *is* enabled; it can take a fair amount of # time on certain systems; Toshiba Tecras are known to have this # problem. @@ -819,6 +842,7 @@ # If we get here, all is good a20_done: +#endif /* CONFIG_VOYAGER */ # set up gdt and idt lidt idt_48 # load idt with 0,0 xorl %eax, %eax # Compute gdt_base @@ -870,7 +894,7 @@ subw $DELTA_INITSEG, %si shll $4, %esi # Convert to 32-bit pointer # NOTE: For high loaded big kernels we need a -# jmpi 0x100000,__KERNEL_CS +# 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. @@ -881,7 +905,7 @@ .byte 0x66, 0xea # prefix + jmpi-opcode code32: .long 0x1000 # will be set to 0x100000 # for big kernels - .word __KERNEL_CS + .word __BOOT_CS # Here's a bunch of information about your current kernel.. kernel_version: .ascii UTS_RELEASE @@ -985,6 +1009,7 @@ .string "INT15 refuses to access high mem, giving up." +#ifndef CONFIG_VOYAGER # This routine tests whether or not A20 is enabled. If so, it # exits with zf = 0. # @@ -1015,6 +1040,8 @@ popw %cx ret +#endif /* CONFIG_VOYAGER */ + # This routine checks that the keyboard command queue is empty # (after emptying the output buffers) # @@ -1075,13 +1102,19 @@ # Descriptor tables # -# NOTE: if you think the GDT is large, you can make it smaller by just -# defining the KERNEL_CS and KERNEL_DS entries and shifting the gdt -# address down by GDT_ENTRY_KERNEL_CS*8. This puts bogus entries into -# the GDT, but those wont be used so it's not a problem. +# 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_KERNEL_CS,8,0 + .fill GDT_ENTRY_BOOT_CS,8,0 .word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb) .word 0 # base address = 0 @@ -1094,12 +1127,17 @@ .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 -gdt_48: - .word GDT_ENTRY_KERNEL_CS*8 + 16 - 1 # gdt limit + .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 diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/boot98/bootsect.S linux.2.5.47-ac4/arch/i386/boot98/bootsect.S --- linux.2.5.47/arch/i386/boot98/bootsect.S 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.47-ac4/arch/i386/boot98/bootsect.S 2002-10-31 15:05:52.000000000 +0000 @@ -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 -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/boot98/compressed/head.S linux.2.5.47-ac4/arch/i386/boot98/compressed/head.S --- linux.2.5.47/arch/i386/boot98/compressed/head.S 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.47-ac4/arch/i386/boot98/compressed/head.S 2002-10-31 15:05:52.000000000 +0000 @@ -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 $(__KERNEL_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 $(__KERNEL_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 $(__KERNEL_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 $(__KERNEL_CS), $0x100000 +move_routine_end: diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/boot98/compressed/Makefile linux.2.5.47-ac4/arch/i386/boot98/compressed/Makefile --- linux.2.5.47/arch/i386/boot98/compressed/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.47-ac4/arch/i386/boot98/compressed/Makefile 2002-10-31 15:05:52.000000000 +0000 @@ -0,0 +1,26 @@ +# +# 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 + +include $(TOPDIR)/Rules.make + +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 -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/boot98/compressed/misc.c linux.2.5.47-ac4/arch/i386/boot98/compressed/misc.c --- linux.2.5.47/arch/i386/boot98/compressed/misc.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.47-ac4/arch/i386/boot98/compressed/misc.c 2002-10-31 15:05:52.000000000 +0000 @@ -0,0 +1,375 @@ +/* + * 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] , __KERNEL_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; +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/boot98/compressed/vmlinux.scr linux.2.5.47-ac4/arch/i386/boot98/compressed/vmlinux.scr --- linux.2.5.47/arch/i386/boot98/compressed/vmlinux.scr 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.47-ac4/arch/i386/boot98/compressed/vmlinux.scr 2002-10-31 15:05:52.000000000 +0000 @@ -0,0 +1,9 @@ +SECTIONS +{ + .data : { + input_len = .; + LONG(input_data_end - input_data) input_data = .; + *(.data) + input_data_end = .; + } +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/boot98/install.sh linux.2.5.47-ac4/arch/i386/boot98/install.sh --- linux.2.5.47/arch/i386/boot98/install.sh 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.47-ac4/arch/i386/boot98/install.sh 2002-10-31 15:05:52.000000000 +0000 @@ -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 -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/boot98/Makefile linux.2.5.47-ac4/arch/i386/boot98/Makefile --- linux.2.5.47/arch/i386/boot98/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.47-ac4/arch/i386/boot98/Makefile 2002-10-31 15:05:52.000000000 +0000 @@ -0,0 +1,90 @@ +# +# 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 + +# Default + +boot: bzImage + +include $(TOPDIR)/Rules.make + +# --------------------------------------------------------------------------- + +$(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 $(echo_target) +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) + +$(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 + +@$(call descend,$(obj)/compressed,IMAGE_OFFSET=$(IMAGE_OFFSET) \ + $(obj)/compressed/vmlinux) + + +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)" + +archhelp: + @echo '* bzImage - Compressed kernel image (arch/$(ARCH)/boot/bzImage)' + @echo ' install - Install kernel using' + @echo ' (your) ~/bin/installkernel or' + @echo ' (distribution) /sbin/installkernel or' + @echo ' install to $$(INSTALL_PATH) and run lilo' + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/boot98/setup.S linux.2.5.47-ac4/arch/i386/boot98/setup.S --- linux.2.5.47/arch/i386/boot98/setup.S 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.47-ac4/arch/i386/boot98/setup.S 2002-10-31 15:05:52.000000000 +0000 @@ -0,0 +1,950 @@ +/* + * 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 doesnt 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,__KERNEL_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 __KERNEL_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: if you think the GDT is large, you can make it smaller by just +# defining the KERNEL_CS and KERNEL_DS entries and shifting the gdt +# address down by GDT_ENTRY_KERNEL_CS*8. This puts bogus entries into +# the GDT, but those wont be used so it's not a problem. +# +gdt: + .fill GDT_ENTRY_KERNEL_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) +idt_48: + .word 0 # idt limit = 0 + .word 0, 0 # idt base = 0L +gdt_48: + .word GDT_ENTRY_KERNEL_CS*8 + 16 - 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 -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/boot98/tools/build.c linux.2.5.47-ac4/arch/i386/boot98/tools/build.c --- linux.2.5.47/arch/i386/boot98/tools/build.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.47-ac4/arch/i386/boot98/tools/build.c 2002-10-31 15:05:52.000000000 +0000 @@ -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 -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/boot98/video.S linux.2.5.47-ac4/arch/i386/boot98/video.S --- linux.2.5.47/arch/i386/boot98/video.S 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.47-ac4/arch/i386/boot98/video.S 2002-10-31 15:05:52.000000000 +0000 @@ -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 -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/Kconfig linux.2.5.47-ac4/arch/i386/Kconfig --- linux.2.5.47/arch/i386/Kconfig 2002-11-11 16:39:08.000000000 +0000 +++ linux.2.5.47-ac4/arch/i386/Kconfig 2002-11-11 17:26:18.000000000 +0000 @@ -62,6 +62,7 @@ SL/SLC/SLC2/SLC3/SX/SX2 and UMC U5D or U5S. - "586" for generic Pentium CPUs lacking the TSC (time stamp counter) register. + - "MediaGX/Geode" for the NatSemi Geode and Cyrix MediaGX. - "Pentium-Classic" for the Intel Pentium. - "Pentium-MMX" for the Intel Pentium MMX. - "Pentium-Pro" for the Intel Pentium Pro/Celeron/Pentium II. @@ -126,6 +127,13 @@ treated almost like Pentium IIIs, but with a different cache shift. +config MGEODE + bool "MediaGX/Geode" + help + Select this option for a Cyrix MediaGX or National Semiconductor + Geode platform. This enables the user of some extended features + and passes the appropriate optimisation flags to GCC. + config MK6 bool "K6/K6-II/K6-III" help @@ -198,7 +206,7 @@ config X86_L1_CACHE_SHIFT int - default "5" if MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCRUSOE || MCYRIXIII || MK6 || MPENTIUMIII || M686 || M586MMX || M586TSC || M586 + default "5" if MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCRUSOE || MCYRIXIII || MK6 || MPENTIUMIII || M686 || M586MMX || M586TSC || M586 || GEODE default "4" if MELAN || M486 || M386 default "6" if MK7 default "7" if MPENTIUM4 @@ -215,7 +223,7 @@ config X86_PPRO_FENCE bool - depends on M686 || M586MMX || M586TSC || M586 || M486 || M386 + depends on M686 || M586MMX || M586TSC || M586 || M486 || M386 || MGEODE default y config X86_F00F_BUG @@ -245,17 +253,17 @@ config X86_USE_STRING_486 bool - depends on MELAN || M586MMX || M586TSC || M586 || M486 + depends on MELAN || M586MMX || M586TSC || M586 || M486 || MGEODE default y config X86_ALIGNMENT_16 bool - depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || MELAN || MK6 || M586MMX || M586TSC || M586 || M486 + depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || MELAN || MK6 || M586MMX || M586TSC || M586 || M486 || MGEODE default y config X86_TSC bool - depends on MWINCHIP3D || MWINCHIP2 || MCRUSOE || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMIII || M686 || M586MMX || M586TSC + depends on (MWINCHIP3D || MWINCHIP2 || MCRUSOE || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMIII || M686 || M586MMX || M586TSC || MGEODE)&& !X86_NUMAQ default y config X86_GOOD_APIC @@ -278,9 +286,16 @@ depends on MCYRIXIII || MK7 default y +config X86_HAVE_CMOV + depends on M686 || MPENTIUMIII || MPENTIUMIV || MK7 || MCRUSOE + default y + +config X86_HAVE_PIT + depends on M386 || M486 || M586 || MGEODE || X86_NUMAQ || VOYAGER || MWINCHIPC6 || MWINCHIP2 || MWINCHIP3D + config X86_OOSTORE bool - depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 + depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MGEODE default y config HUGETLB_PAGE @@ -365,12 +380,12 @@ config X86_LOCAL_APIC bool - depends on !SMP && X86_UP_APIC + depends on !SMP && X86_UP_APIC && !VOYAGER default y config X86_IO_APIC bool - depends on !SMP && X86_UP_IOAPIC + depends on !SMP && X86_UP_IOAPIC && !VOYAGER default y config NR_CPUS @@ -429,6 +444,10 @@ depends on NUMA default y +config X86_CYCLONE + bool "Cyclone Counter Support" + depends on X86_NUMA + config X86_MCE bool "Machine Check Exception" ---help--- @@ -455,8 +474,8 @@ Disable this if you don't want to see these messages. Seeing the messages this option prints out may be indicative of dying hardware, or out-of-spec (ie, overclocked) hardware. - This option only does something on certain CPUs. - (AMD Athlon/Duron and Intel Pentium 4) + This option only does something on certain CPUs. + (AMD Athlon/Duron and Intel Pentium 4) config X86_MCE_P4THERMAL bool "check for P4 thermal throttling interrupt." @@ -961,6 +980,18 @@ menu "Bus options (PCI, PCMCIA, EISA, MCA, ISA)" +config VOYAGER + bool "Support for the NCR Voyager Architecture" + depends on MCA + help + Voyager is a MCA based 32 way capable SMP architecture proprietary + to NCR Corp. Machine classes 345x/35xx/4100/51xx are voyager based. + + *** WARNING *** + + If you do not specifically know you have a Voyager based machine, + say N here otherwise the kernel you build will not be bootable. + # Visual Workstation support is utterly broken. # If you want to see it working mail an VW540 to hch@infradead.org 8) #bool 'SGI Visual Workstation support' CONFIG_VISWS @@ -1612,19 +1643,46 @@ symbolic stack backtraces. This increases the size of the kernel somewhat, as all symbols have to be loaded into the kernel image. +config X86_STACK_CHECK + bool "Check for stack overflows" + depends on DEBUG_KERNEL + help + Say Y here to have the kernel attempt to detect when the per-task + kernel stack overflows. + + Some older versions of gcc don't handle the -p option correctly. + Kernprof is affected by the same problem, which is described here: + http://oss.sgi.com/projects/kernprof/faq.html#Q9 + + Basically, if you get oopses in __free_pages_ok during boot when + you have this turned on, you need to fix gcc. The Redhat 2.96 + version and gcc-3.x seem to work. + + If not debugging a stack overflow problem, say N + +config FRAME_POINTER + bool + depends on X86_STACK_CHECK + default y + +config IOMMU_DEBUG + bool + depends on DEBUG_KERNEL + default y + config X86_EXTRA_IRQS bool - depends on X86_LOCAL_APIC + depends on X86_LOCAL_APIC || VOYAGER default y config X86_FIND_SMP_CONFIG bool - depends on X86_LOCAL_APIC + depends on X86_LOCAL_APIC || VOYAGER default y config X86_MPPARSE bool - depends on X86_LOCAL_APIC + depends on X86_LOCAL_APIC && !VOYAGER default y endmenu @@ -1642,10 +1700,14 @@ config X86_HT bool - depends on SMP + depends on SMP && !VOYAGER default y config X86_BIOS_REBOOT bool default y +config X86_TRAMPOLINE + bool + depends on SMP || (VOYAGER && SMP) || X86_LOCAL_APIC + default y diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/kernel/cpu/common.c linux.2.5.47-ac4/arch/i386/kernel/cpu/common.c --- linux.2.5.47/arch/i386/kernel/cpu/common.c 2002-11-11 16:39:08.000000000 +0000 +++ linux.2.5.47-ac4/arch/i386/kernel/cpu/common.c 2002-11-13 15:23:45.000000000 +0000 @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -15,8 +16,6 @@ struct cpu_dev * cpu_devs[X86_VENDOR_NUM] = {}; -extern void mcheck_init(struct cpuinfo_x86 *c); - static void default_init(struct cpuinfo_x86 * c) { /* Not much we can do here... */ @@ -50,16 +49,9 @@ tsc_disable = 1; return 1; } -#else -#define tsc_disable 0 -static int __init tsc_setup(char *str) -{ - printk("notsc: Kernel compiled with CONFIG_X86_TSC, cannot disable TSC.\n"); - return 1; -} -#endif __setup("notsc", tsc_setup); +#endif int __init get_model_name(struct cpuinfo_x86 *c) { @@ -310,8 +302,10 @@ */ /* TSC disabled? */ +#ifndef CONFIG_X86_TSC if ( tsc_disable ) clear_bit(X86_FEATURE_TSC, c->x86_capability); +#endif /* FXSR disabled? */ if (disable_x86_fxsr) { @@ -362,17 +356,6 @@ mcheck_init(c); #endif } -/* - * Perform early boot up checks for a valid TSC. See arch/i386/kernel/time.c - */ - -void __init dodgy_tsc(void) -{ - get_cpu_vendor(&boot_cpu_data); - if (( boot_cpu_data.x86_vendor == X86_VENDOR_CYRIX ) || - ( boot_cpu_data.x86_vendor == X86_VENDOR_NSC )) - cpu_devs[X86_VENDOR_CYRIX]->c_init(&boot_cpu_data); -} void __init print_cpu_info(struct cpuinfo_x86 *c) { @@ -449,12 +432,14 @@ if (cpu_has_vme || cpu_has_tsc || cpu_has_de) clear_in_cr4(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE); +#ifndef CONFIG_X86_TSC if (tsc_disable && cpu_has_tsc) { printk(KERN_NOTICE "Disabling TSC...\n"); /**** FIX-HPA: DOES THIS REALLY BELONG HERE? ****/ clear_bit(X86_FEATURE_TSC, boot_cpu_data.x86_capability); set_in_cr4(X86_CR4_TSD); } +#endif /* * Initialize the per-CPU GDT with the boot GDT, diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/kernel/cpu/cpufreq/longhaul.c linux.2.5.47-ac4/arch/i386/kernel/cpu/cpufreq/longhaul.c --- linux.2.5.47/arch/i386/kernel/cpu/cpufreq/longhaul.c 2002-10-31 14:57:23.000000000 +0000 +++ linux.2.5.47-ac4/arch/i386/kernel/cpu/cpufreq/longhaul.c 2002-11-12 15:30:54.000000000 +0000 @@ -1,5 +1,5 @@ /* - * $Id: longhaul.c,v 1.72 2002/09/29 23:43:10 db Exp $ + * $Id: longhaul.c,v 1.77 2002/10/31 21:17:40 db Exp $ * * (C) 2001 Dave Jones. * (C) 2002 Padraig Brady. @@ -436,8 +436,10 @@ switch (longhaul) { case 1: /* Ugh, Longhaul v1 didn't have the min/max MSRs. - Assume max = whatever we booted at. */ + Assume min=3.0x & max = whatever we booted at. */ + minmult = 30; maxmult = longhaul_get_cpu_mult(); + minfsb = maxfsb = current_fsb; break; case 2 ... 3: diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/kernel/cpu/cyrix.c linux.2.5.47-ac4/arch/i386/kernel/cpu/cyrix.c --- linux.2.5.47/arch/i386/kernel/cpu/cyrix.c 2002-11-11 16:39:08.000000000 +0000 +++ linux.2.5.47-ac4/arch/i386/kernel/cpu/cyrix.c 2002-11-15 02:02:21.000000000 +0000 @@ -106,6 +106,89 @@ } } + +static void __init set_cx86_reorder(void) +{ +#ifdef CONFIG_OOSTORE + u8 ccr3; + + printk(KERN_INFO "Enable Memory access reorder on Cyrix/NSC processor.\n"); + ccr3 = getCx86(CX86_CCR3); + setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* enable MAPEN  */ + + /* Load/Store Serialize to mem access disable (=reorder it)  */ + setCx86(CX86_PCR0, getCx86(CX86_PCR0) & ~0x80); +#ifdef CONFIG_NOHIGHMEM + /* set load/store serialize from 1GB to 4GB */ + ccr3 |= 0xe0; +#endif + setCx86(CX86_CCR3, ccr3); +#endif +} + +static void __init set_cx86_memwb(void) +{ + u32 cr0; + + printk(KERN_INFO "Enable Memory-Write-back mode on Cyrix/NSC processor.\n"); + + /* CCR2 bit 2: unlock NW bit */ + setCx86(CX86_CCR2, getCx86(CX86_CCR2) & ~0x04); + /* set 'Not Write-through' */ + cr0 = 0x20000000; + __asm__("movl %%cr0,%%eax\n\t" + "orl %0,%%eax\n\t" + "movl %%eax,%%cr0\n" + : : "r" (cr0) + :"ax"); + /* CCR2 bit 2: lock NW bit and set WT1 */ + setCx86(CX86_CCR2, getCx86(CX86_CCR2) | 0x14 ); +} + +static void __init set_cx86_inc(void) +{ + unsigned char ccr3; + + printk(KERN_INFO "Enable Incrementor on Cyrix/NSC processor.\n"); + + ccr3 = getCx86(CX86_CCR3); + setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* enable MAPEN  */ + /* PCR1 -- Performance Control */ + /* Incrementor on, whatever that is */ + setCx86(CX86_PCR1, getCx86(CX86_PCR1) | 0x02); + /* PCR0 -- Performance Control */ + /* Incrementor Margin 10 */ + setCx86(CX86_PCR0, getCx86(CX86_PCR0) | 0x04); + setCx86(CX86_CCR3, ccr3); /* disable MAPEN */ +} + +/* + * Configure later MediaGX and/or Geode processor. + */ + +static void __init geode_configure(void) +{ + unsigned long flags; + u8 ccr3, ccr4; + unsigned long cr0; + local_irq_save(flags); + + ccr3 = getCx86(CX86_CCR3); + setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* Enable */ + + ccr4 = getCx86(CX86_CCR4); + ccr4 |= 0x38; /* FPU fast, DTE cache, Mem bypass */ + + setCx86(CX86_CCR3, ccr3); + + set_cx86_memwb(); + set_cx86_reorder(); + set_cx86_inc(); + + local_irq_restore(flags); +} + + static void __init init_cyrix(struct cpuinfo_x86 *c) { unsigned char dir0, dir0_msn, dir0_lsn, dir1 = 0; @@ -201,7 +284,10 @@ if (c->cpuid_level == 2) { /* Enable cxMMX extensions (GX1 Datasheet 54) */ setCx86(CX86_CCR7, getCx86(CX86_CCR7)|1); - + + /* GXlv/GXm/GX1 */ + if((dir1 >= 0x50 && dir1 <= 0x54) || dir1 >= 0x63) + geode_configure(); get_model_name(c); /* get CPU marketing name */ return; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/kernel/cpu/proc.c linux.2.5.47-ac4/arch/i386/kernel/cpu/proc.c --- linux.2.5.47/arch/i386/kernel/cpu/proc.c 2002-11-05 13:54:42.000000000 +0000 +++ linux.2.5.47-ac4/arch/i386/kernel/cpu/proc.c 2002-11-05 15:41:50.000000000 +0000 @@ -83,7 +83,7 @@ #endif /* We use exception 16 if we have hardware math and we've either seen it or the CPU claims it is internal */ - fpu_exception = c->hard_math && (ignore_irq13 || cpu_has_fpu); + fpu_exception = c->hard_math && (ignore_fpu_irq || cpu_has_fpu); seq_printf(m, "fdiv_bug\t: %s\n" "hlt_bug\t\t: %s\n" "f00f_bug\t: %s\n" diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/kernel/dmi_scan.c linux.2.5.47-ac4/arch/i386/kernel/dmi_scan.c --- linux.2.5.47/arch/i386/kernel/dmi_scan.c 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.47-ac4/arch/i386/kernel/dmi_scan.c 2002-11-04 14:15:46.000000000 +0000 @@ -288,6 +288,23 @@ return 0; } + +/* + * Some BIOS32 PnP corrupt memory or just plain do not work + */ + +static __init int pnpbios_is_horked(struct dmi_blacklist *d) +{ + if (! (dmi_broken & BROKEN_PNP_BIOS)) + { + /* In the absence of the party responsible we'll have to + settle for just disabling the functionality */ + dmi_broken |= BROKEN_PNP_BIOS; + printk(KERN_INFO "%s machine detected. Disabling BIOS plug and play.\n", d->ident); + } + return 0; +} + /* * Some machines, usually laptops, can't handle an enabled local APIC. * The symptoms include hangs or reboots when suspending or resuming, @@ -773,7 +790,13 @@ MATCH(DMI_PRODUCT_VERSION, "HP Pavilion Notebook Model GE"), MATCH(DMI_BOARD_VERSION, "OmniBook N32N-736") } }, - + + { pnpbios_is_horked, "Gateway Solo 5300 seriels laptop", { /* PnPBIOS crashes */ + MATCH(DMI_SYS_VENDOR, "Gateway"), + MATCH(DMI_BIOS_VERSION, "22.07"), + MATCH(DMI_PRODUCT_NAME, "Solo5300"), + NO_MATCH + } }, /* * Generic per vendor APM settings diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/kernel/entry.S linux.2.5.47-ac4/arch/i386/kernel/entry.S --- linux.2.5.47/arch/i386/kernel/entry.S 2002-11-11 16:39:08.000000000 +0000 +++ linux.2.5.47-ac4/arch/i386/kernel/entry.S 2002-11-15 02:07:03.000000000 +0000 @@ -66,7 +66,9 @@ OLDSS = 0x38 CF_MASK = 0x00000001 +TF_MASK = 0x00000100 IF_MASK = 0x00000200 +DF_MASK = 0x00000400 NT_MASK = 0x00004000 VM_MASK = 0x00020000 @@ -134,9 +136,20 @@ movl %eax,EFLAGS(%esp) # movl %edx,EIP(%esp) # Now we move them to their "normal" places movl %ecx,CS(%esp) # + + # + # Call gates don't clear TF and NT in eflags like + # traps do, so we need to do it ourselves. + # %eax already contains eflags (but it may have + # DF set, clear that also) + # + andl $~(DF_MASK | TF_MASK | NT_MASK),%eax + pushl %eax + popfl + movl %esp, %ebx pushl %ebx - andl $-8192, %ebx # GET_THREAD_INFO + GET_THREAD_INFO_WITH_ESP(%ebx) # GET_THREAD_INFO movl TI_EXEC_DOMAIN(%ebx), %edx # Get the execution domain movl 4(%edx), %edx # Get the lcall7 handler for the domain pushl $0x7 @@ -156,9 +169,20 @@ movl %eax,EFLAGS(%esp) # movl %edx,EIP(%esp) # Now we move them to their "normal" places movl %ecx,CS(%esp) # + + # + # Call gates don't clear TF and NT in eflags like + # traps do, so we need to do it ourselves. + # %eax already contains eflags (but it may have + # DF set, clear that also) + # + andl $~(DF_MASK | TF_MASK | NT_MASK),%eax + pushl %eax + popfl + movl %esp, %ebx pushl %ebx - andl $-8192, %ebx # GET_THREAD_INFO + GET_THREAD_INFO_WITH_ESP(%ebx) # GET_THREAD_INFO movl TI_EXEC_DOMAIN(%ebx), %edx # Get the execution domain movl 4(%edx), %edx # Get the lcall7 handler for the domain pushl $0x27 @@ -334,7 +358,45 @@ ALIGN common_interrupt: SAVE_ALL + + + GET_THREAD_INFO(%ebx) + movl TI_IRQ_STACK(%ebx),%ecx + movl TI_TASK(%ebx),%edx + movl %esp,%eax + leal (THREAD_SIZE-4)(%ecx),%esi # %ecx+THREAD_SIZE is next stack + # -4 keeps us in the right one + testl %ecx,%ecx # is there a valid irq_stack? + + # switch to the irq stack +#ifdef CONFIG_X86_HAVE_CMOV + cmovnz %esi,%esp +#else + jz 1f + mov %esi,%esp +1: +#endif + + # update the task pointer in the irq stack + GET_THREAD_INFO(%esi) + movl %edx,TI_TASK(%esi) + + # update the preempt count in the irq stack + movl TI_PRE_COUNT(%ebx),%ecx + movl %ecx,TI_PRE_COUNT(%esi) + call do_IRQ + + movl %eax,%esp # potentially restore non-irq stack + + # copy flags from the irq stack back into the task's thread_info + # %esi is saved over the do_IRQ call and contains the irq stack + # thread_info pointer + # %ebx contains the original thread_info pointer + movl TI_FLAGS(%esi),%eax + movl $0,TI_FLAGS(%esi) + LOCK orl %eax,TI_FLAGS(%ebx) + jmp ret_from_intr #define BUILD_INTERRUPT(name, nr) \ @@ -483,6 +545,61 @@ pushl $do_spurious_interrupt_bug jmp error_code + +#ifdef CONFIG_X86_STACK_CHECK +.data + .globl stack_overflowed +stack_overflowed: + .long 0 +.text + +ENTRY(mcount) + push %eax + movl $(THREAD_SIZE - 1),%eax + andl %esp,%eax + cmpl $STACK_WARN,%eax /* more than half the stack is used*/ + jle 1f +2: + popl %eax + ret +1: + lock; btsl $0,stack_overflowed + jc 2b + + # switch to overflow stack + movl %esp,%eax + movl $(stack_overflow_stack + THREAD_SIZE - 4),%esp + + pushf + cli + pushl %eax + + # push eip then esp of error for stack_overflow_panic + pushl 4(%eax) + pushl %eax + + # update the task pointer and cpu in the overflow stack's thread_info. + GET_THREAD_INFO_WITH_ESP(%eax) + movl TI_TASK(%eax),%ebx + movl %ebx,stack_overflow_stack+TI_TASK + movl TI_CPU(%eax),%ebx + movl %ebx,stack_overflow_stack+TI_CPU + + call stack_overflow + + # pop off call arguments + addl $8,%esp + + popl %eax + popf + movl %eax,%esp + popl %eax + movl $0,stack_overflowed + ret + +#warning stack check enabled +#endif + .data ENTRY(sys_call_table) .long sys_ni_syscall /* 0 - old "setup()" system call*/ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/kernel/head.S linux.2.5.47-ac4/arch/i386/kernel/head.S --- linux.2.5.47/arch/i386/kernel/head.S 2002-10-31 14:57:24.000000000 +0000 +++ linux.2.5.47-ac4/arch/i386/kernel/head.S 2002-11-11 20:23:28.000000000 +0000 @@ -1,5 +1,5 @@ /* - * linux/arch/i386/head.S -- the 32-bit startup code. + * linux/arch/i386/kernel/head.S -- the 32-bit startup code. * * Copyright (C) 1991, 1992 Linus Torvalds * @@ -15,6 +15,8 @@ #include #include #include +#include +#include #define OLD_CL_MAGIC_ADDR 0x90020 #define OLD_CL_MAGIC 0xA33F @@ -46,7 +48,7 @@ * Set segments to known values */ cld - movl $(__KERNEL_DS),%eax + movl $(__BOOT_DS),%eax movl %eax,%ds movl %eax,%es movl %eax,%fs @@ -305,8 +307,8 @@ ret ENTRY(stack_start) - .long init_thread_union+8192 - .long __KERNEL_DS + .long init_thread_union+THREAD_SIZE + .long __BOOT_DS /* This is the default interrupt "handler" :-) */ int_msg: @@ -349,12 +351,12 @@ .long idt_table # boot GDT descriptor (later on used by CPU#0): - + .word 0 # 32 bit align gdt_desc.address cpu_gdt_descr: .word GDT_ENTRIES*8-1 .long cpu_gdt_table - .fill NR_CPUS-1,6,0 # space for the other GDT descriptors + .fill NR_CPUS-1,8,0 # space for the other GDT descriptors /* * This is initialized to create an identity-mapping at 0-8M (for bootup @@ -405,10 +407,21 @@ */ .data -ALIGN /* * The Global Descriptor Table contains 28 quadwords, per-CPU. */ +#ifdef CONFIG_SMP +/* + * The boot_gdt_table must mirror the equivalent in setup.S and is + * used only by the trampoline for booting other CPUs + */ + .align L1_CACHE_BYTES +ENTRY(boot_gdt_table) + .fill GDT_ENTRY_BOOT_CS,8,0 + .quad 0x00cf9a000000ffff /* kernel 4GB code at 0x00000000 */ + .quad 0x00cf92000000ffff /* kernel 4GB data at 0x00000000 */ +#endif + .align L1_CACHE_BYTES ENTRY(cpu_gdt_table) .quad 0x0000000000000000 /* NULL descriptor */ .quad 0x0000000000000000 /* 0x0b reserved */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/kernel/i386_ksyms.c linux.2.5.47-ac4/arch/i386/kernel/i386_ksyms.c --- linux.2.5.47/arch/i386/kernel/i386_ksyms.c 2002-11-05 13:54:42.000000000 +0000 +++ linux.2.5.47-ac4/arch/i386/kernel/i386_ksyms.c 2002-11-05 14:00:33.000000000 +0000 @@ -216,3 +216,8 @@ EXPORT_SYMBOL(edd); EXPORT_SYMBOL(eddnr); #endif + +#ifdef CONFIG_X86_STACK_CHECK +extern void mcount(void); +EXPORT_SYMBOL_NOVERS(mcount); +#endif diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/kernel/i8259.c linux.2.5.47-ac4/arch/i386/kernel/i8259.c --- linux.2.5.47/arch/i386/kernel/i8259.c 2002-10-31 14:57:24.000000000 +0000 +++ linux.2.5.47-ac4/arch/i386/kernel/i8259.c 2002-10-31 15:05:48.000000000 +0000 @@ -25,6 +25,8 @@ #include +#include "io_ports.h" + /* * This is the 'legacy' 8259A Programmable Interrupt Controller, * present in the majority of PC/AT boxes. @@ -74,8 +76,8 @@ static unsigned int cached_irq_mask = 0xffff; #define __byte(x,y) (((unsigned char *)&(y))[x]) -#define cached_21 (__byte(0,cached_irq_mask)) -#define cached_A1 (__byte(1,cached_irq_mask)) +#define cached_master_mask (__byte(0,cached_irq_mask)) +#define cached_slave_mask (__byte(1,cached_irq_mask)) /* * Not all IRQs can be routed through the IO-APIC, eg. on certain (older) @@ -96,9 +98,9 @@ spin_lock_irqsave(&i8259A_lock, flags); cached_irq_mask |= mask; if (irq & 8) - outb(cached_A1,0xA1); + outb(cached_slave_mask, PIC_SLAVE_IMR); else - outb(cached_21,0x21); + outb(cached_master_mask, PIC_MASTER_IMR); spin_unlock_irqrestore(&i8259A_lock, flags); } @@ -110,9 +112,9 @@ spin_lock_irqsave(&i8259A_lock, flags); cached_irq_mask &= mask; if (irq & 8) - outb(cached_A1,0xA1); + outb(cached_slave_mask, PIC_SLAVE_IMR); else - outb(cached_21,0x21); + outb(cached_master_mask, PIC_MASTER_IMR); spin_unlock_irqrestore(&i8259A_lock, flags); } @@ -124,9 +126,9 @@ spin_lock_irqsave(&i8259A_lock, flags); if (irq < 8) - ret = inb(0x20) & mask; + ret = inb(PIC_MASTER_CMD) & mask; else - ret = inb(0xA0) & (mask >> 8); + ret = inb(PIC_SLAVE_CMD) & (mask >> 8); spin_unlock_irqrestore(&i8259A_lock, flags); return ret; @@ -152,14 +154,14 @@ int irqmask = 1<> 8); - outb(0x0A,0xA0); /* back to the IRR register */ + outb(0x0B,PIC_SLAVE_CMD); /* ISR register */ + value = inb(PIC_SLAVE_CMD) & (irqmask >> 8); + outb(0x0A,PIC_SLAVE_CMD); /* back to the IRR register */ return value; } @@ -196,14 +198,14 @@ handle_real_irq: if (irq & 8) { - inb(0xA1); /* DUMMY - (do we need this?) */ - outb(cached_A1,0xA1); - outb(0x60+(irq&7),0xA0);/* 'Specific EOI' to slave */ - outb(0x62,0x20); /* 'Specific EOI' to master-IRQ2 */ + inb(PIC_SLAVE_IMR); /* DUMMY - (do we need this?) */ + outb(cached_slave_mask, PIC_SLAVE_IMR); + outb(0x60+(irq&7),PIC_SLAVE_CMD);/* 'Specific EOI' to slave */ + outb(0x60+PIC_CASCADE_IR,PIC_MASTER_CMD); /* 'Specific EOI' to master-IRQ2 */ } else { - inb(0x21); /* DUMMY - (do we need this?) */ - outb(cached_21,0x21); - outb(0x60+irq,0x20); /* 'Specific EOI' to master */ + inb(PIC_MASTER_IMR); /* DUMMY - (do we need this?) */ + outb(cached_master_mask, PIC_MASTER_IMR); + outb(0x60+irq,PIC_MASTER_CMD); /* 'Specific EOI to master */ } spin_unlock_irqrestore(&i8259A_lock, flags); return; @@ -275,26 +277,24 @@ spin_lock_irqsave(&i8259A_lock, flags); - outb(0xff, 0x21); /* mask all of 8259A-1 */ - outb(0xff, 0xA1); /* mask all of 8259A-2 */ + outb(0xff, PIC_MASTER_IMR); /* mask all of 8259A-1 */ + outb(0xff, PIC_SLAVE_IMR); /* mask all of 8259A-2 */ /* * outb_p - this has to work on a wide range of PC hardware. */ - outb_p(0x11, 0x20); /* ICW1: select 8259A-1 init */ - outb_p(0x20 + 0, 0x21); /* ICW2: 8259A-1 IR0-7 mapped to 0x20-0x27 */ - outb_p(0x04, 0x21); /* 8259A-1 (the master) has a slave on IR2 */ - if (auto_eoi) - outb_p(0x03, 0x21); /* master does Auto EOI */ - else - outb_p(0x01, 0x21); /* master expects normal EOI */ - - outb_p(0x11, 0xA0); /* ICW1: select 8259A-2 init */ - outb_p(0x20 + 8, 0xA1); /* ICW2: 8259A-2 IR0-7 mapped to 0x28-0x2f */ - outb_p(0x02, 0xA1); /* 8259A-2 is a slave on master's IR2 */ - outb_p(0x01, 0xA1); /* (slave's support for AEOI in flat mode - is to be investigated) */ - + outb_p(0x11, PIC_MASTER_CMD); /* ICW1: select 8259A-1 init */ + outb_p(0x20 + 0, PIC_MASTER_IMR); /* ICW2: 8259A-1 IR0-7 mapped to 0x20-0x27 */ + outb_p(1U << PIC_CASCADE_IR, PIC_MASTER_IMR); /* 8259A-1 (the master) has a slave on IR2 */ + if (auto_eoi) /* master does Auto EOI */ + outb_p(MASTER_ICW4_DEFAULT | PIC_ICW4_AEOI, PIC_MASTER_IMR); + else /* master expects normal EOI */ + outb_p(MASTER_ICW4_DEFAULT, PIC_MASTER_IMR); + + outb_p(0x11, PIC_SLAVE_CMD); /* ICW1: select 8259A-2 init */ + outb_p(0x20 + 8, PIC_SLAVE_IMR); /* ICW2: 8259A-2 IR0-7 mapped to 0x28-0x2f */ + outb_p(PIC_CASCADE_IR, PIC_SLAVE_IMR); /* 8259A-2 is a slave on master's IR2 */ + outb_p(SLAVE_ICW4_DEFAULT, PIC_SLAVE_IMR); /* (slave's support for AEOI in flat mode is to be investigated) */ if (auto_eoi) /* * in AEOI mode we just have to mask the interrupt @@ -306,8 +306,8 @@ udelay(100); /* wait for 8259A to initialize */ - outb(cached_21, 0x21); /* restore master IRQ mask */ - outb(cached_A1, 0xA1); /* restore slave IRQ mask */ + outb(cached_master_mask, PIC_MASTER_IMR); /* restore master IRQ mask */ + outb(cached_slave_mask, PIC_SLAVE_IMR); /* restore slave IRQ mask */ spin_unlock_irqrestore(&i8259A_lock, flags); } @@ -324,11 +324,17 @@ * be shot. */ +/* + * =PC9800NOTE= In NEC PC-9800, we use irq8 instead of irq13! + */ + static void math_error_irq(int cpl, void *dev_id, struct pt_regs *regs) { extern void math_error(void *); +#ifndef CONFIG_PC9800 outb(0,0xF0); - if (ignore_irq13 || !boot_cpu_data.hard_math) +#endif + if (ignore_fpu_irq || !boot_cpu_data.hard_math) return; math_error((void *)regs->eip); } @@ -337,7 +343,7 @@ * New motherboards sometimes make IRQ 13 be a PCI interrupt, * so allow interrupt sharing. */ -static struct irqaction irq13 = { math_error_irq, 0, 0, "fpu", NULL, NULL }; +static struct irqaction fpu_irq = { math_error_irq, 0, 0, "fpu", NULL, NULL }; void __init init_ISA_irqs (void) { @@ -393,14 +399,14 @@ * Set the clock to HZ Hz, we already have a valid * vector now: */ - outb_p(0x34,0x43); /* binary, mode 2, LSB/MSB, ch 0 */ - outb_p(LATCH & 0xff , 0x40); /* LSB */ - outb(LATCH >> 8 , 0x40); /* MSB */ + outb_p(0x34, PIT_MODE); /* binary, mode 2, LSB/MSB, ch 0 */ + outb_p(LATCH & 0xff, PIT_CH0); /* LSB */ + outb(LATCH >> 8 , PIT_CH0); /* MSB */ /* * External FPU? Set up irq13 if so, for * original braindamaged IBM FERR coupling. */ if (boot_cpu_data.hard_math && !cpu_has_fpu) - setup_irq(13, &irq13); + setup_irq(FPU_IRQ, &fpu_irq); } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/kernel/init_task.c linux.2.5.47-ac4/arch/i386/kernel/init_task.c --- linux.2.5.47/arch/i386/kernel/init_task.c 2002-10-31 14:57:24.000000000 +0000 +++ linux.2.5.47-ac4/arch/i386/kernel/init_task.c 2002-10-31 15:05:48.000000000 +0000 @@ -13,6 +13,14 @@ static struct signal_struct init_signals = INIT_SIGNALS(init_signals); struct mm_struct init_mm = INIT_MM(init_mm); +union thread_union init_irq_union + __attribute__((__section__(".data.init_task"))); + +#ifdef CONFIG_X86_STACK_CHECK +union thread_union stack_overflow_stack + __attribute__((__section__(".data.init_task"))); +#endif + /* * Initial thread structure. * diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/kernel/irq.c linux.2.5.47-ac4/arch/i386/kernel/irq.c --- linux.2.5.47/arch/i386/kernel/irq.c 2002-11-05 13:54:42.000000000 +0000 +++ linux.2.5.47-ac4/arch/i386/kernel/irq.c 2002-11-05 14:00:43.000000000 +0000 @@ -311,7 +311,8 @@ * SMP cross-CPU interrupts have their own specific * handlers). */ -asmlinkage unsigned int do_IRQ(struct pt_regs regs) +struct pt_regs *do_IRQ(struct pt_regs *regs) __attribute__((regparm(1))); +struct pt_regs *do_IRQ(struct pt_regs *regs) { /* * We ack quickly, we don't want the irq controller @@ -323,7 +324,7 @@ * 0 return value means that this irq is already being * handled by some other CPU. (or is disabled) */ - int irq = regs.orig_eax & 0xff; /* high bits used in ret_from_ code */ + int irq = regs->orig_eax & 0xff; /* high bits used in ret_from_ code */ int cpu = smp_processor_id(); irq_desc_t *desc = irq_desc + irq; struct irqaction * action; @@ -388,7 +389,7 @@ */ for (;;) { spin_unlock(&desc->lock); - handle_IRQ_event(irq, ®s, action); + handle_IRQ_event(irq, regs, action); spin_lock(&desc->lock); if (likely(!(desc->status & IRQ_PENDING))) @@ -407,7 +408,7 @@ irq_exit(); - return 1; + return regs; } /** diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/kernel/Makefile linux.2.5.47-ac4/arch/i386/kernel/Makefile --- linux.2.5.47/arch/i386/kernel/Makefile 2002-11-11 16:39:08.000000000 +0000 +++ linux.2.5.47-ac4/arch/i386/kernel/Makefile 2002-11-11 16:42:21.000000000 +0000 @@ -4,7 +4,7 @@ EXTRA_TARGETS := head.o init_task.o -export-objs := mca.o i386_ksyms.o time.o +export-objs := mca.o i386_ksyms.o time.o pci-dma.o obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o vm86.o \ ptrace.o i8259.o ioport.o ldt.o setup.o time.o sys_i386.o \ @@ -20,7 +20,8 @@ obj-$(CONFIG_APM) += apm.o obj-$(CONFIG_ACPI) += acpi.o obj-$(CONFIG_ACPI_SLEEP) += acpi_wakeup.o -obj-$(CONFIG_X86_SMP) += smp.o smpboot.o trampoline.o +obj-$(CONFIG_X86_SMP) += smp.o smpboot.o +obj-$(CONFIG_X86_TRAMPOLINE) += trampoline.o obj-$(CONFIG_X86_MPPARSE) += mpparse.o obj-$(CONFIG_X86_LOCAL_APIC) += apic.o nmi.o obj-$(CONFIG_X86_IO_APIC) += io_apic.o diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/kernel/pci-dma.c linux.2.5.47-ac4/arch/i386/kernel/pci-dma.c --- linux.2.5.47/arch/i386/kernel/pci-dma.c 2002-10-31 14:57:24.000000000 +0000 +++ linux.2.5.47-ac4/arch/i386/kernel/pci-dma.c 2002-10-31 15:05:48.000000000 +0000 @@ -11,6 +11,7 @@ #include #include #include +#include #include void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, @@ -24,6 +25,7 @@ ret = (void *)__get_free_pages(gfp, get_order(size)); if (ret != NULL) { + iommu_alloc(size); memset(ret, 0, size); *dma_handle = virt_to_phys(ret); } @@ -33,5 +35,35 @@ void pci_free_consistent(struct pci_dev *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle) { + iommu_free(size); free_pages((unsigned long)vaddr, get_order(size)); } + +atomic_t iommu_count; + +#define WARN_INTERVAL (3600*HZ) /* once a hour */ +static unsigned long last_warned = -WARN_INTERVAL; + +/* could print a backtrace because it's likely that the buggy driver + hits it. */ +void iommu_overflow(void) +{ + if (!time_before(last_warned + WARN_INTERVAL, jiffies)) + return; + last_warned = jiffies; + + printk("pci_map_* overflow. You likely have a buggy driver.\n"); +} + +void iommu_underflow(void) +{ + if (!time_before(last_warned + WARN_INTERVAL, jiffies)) + return; + last_warned = jiffies; + + printk("pci_map_* underflow. You likely have a buggy driver.\n"); +} + +EXPORT_SYMBOL(iommu_count); +EXPORT_SYMBOL(iommu_overflow); +EXPORT_SYMBOL(iommu_underflow); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/kernel/process.c linux.2.5.47-ac4/arch/i386/kernel/process.c --- linux.2.5.47/arch/i386/kernel/process.c 2002-11-11 16:39:08.000000000 +0000 +++ linux.2.5.47-ac4/arch/i386/kernel/process.c 2002-11-11 16:46:25.000000000 +0000 @@ -157,7 +157,25 @@ __setup("idle=", idle_setup); -void show_regs(struct pt_regs * regs) +void stack_overflow(unsigned long esp, unsigned long eip) +{ + int panicing = ((esp&(THREAD_SIZE-1)) <= STACK_PANIC); + + printk( "esp: 0x%lx masked: 0x%lx STACK_PANIC:0x%lx %d %d\n", + esp, (esp&(THREAD_SIZE-1)), STACK_PANIC, (((esp&(THREAD_SIZE-1)) <= STACK_PANIC)), panicing ); + + if (panicing) + print_symbol("stack overflow from %s\n", eip); + else + print_symbol("excessive stack use from %s\n", eip); + printk("esp: %p\n", (void*)esp); + show_trace((void*)esp); + + if (panicing) + panic("stack overflow\n"); +} + +asmlinkage void show_regs(struct pt_regs * regs) { unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L; @@ -434,6 +452,7 @@ /* never put a printk in __switch_to... printk() calls wake_up*() indirectly */ + next_p->thread_info->irq_stack = prev_p->thread_info->irq_stack; unlazy_fpu(prev_p); /* diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/kernel/reboot.c linux.2.5.47-ac4/arch/i386/kernel/reboot.c --- linux.2.5.47/arch/i386/kernel/reboot.c 2002-10-31 14:57:24.000000000 +0000 +++ linux.2.5.47-ac4/arch/i386/kernel/reboot.c 2002-10-31 15:05:48.000000000 +0000 @@ -8,6 +8,7 @@ #include #include #include +#include "mach_reboot.h" /* * Power off function, if any @@ -125,15 +126,6 @@ 0xea, 0x00, 0x00, 0xff, 0xff /* ljmp $0xffff,$0x0000 */ }; -static inline void kb_wait(void) -{ - int i; - - for (i=0; i<0x10000; i++) - if ((inb_p(0x64) & 0x02) == 0) - break; -} - /* * Switch to real mode and then execute the code * specified by the code and length parameters. @@ -264,13 +256,7 @@ /* rebooting needs to touch the page at absolute addr 0 */ *((unsigned short *)__va(0x472)) = reboot_mode; for (;;) { - int i; - for (i=0; i<100; i++) { - kb_wait(); - udelay(50); - outb(0xfe,0x64); /* pulse reset low */ - udelay(50); - } + mach_reboot(); /* That didn't work - force a triple fault.. */ __asm__ __volatile__("lidt %0": :"m" (no_idt)); __asm__ __volatile__("int3"); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/kernel/setup.c linux.2.5.47-ac4/arch/i386/kernel/setup.c --- linux.2.5.47/arch/i386/kernel/setup.c 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.47-ac4/arch/i386/kernel/setup.c 2002-10-31 15:05:48.000000000 +0000 @@ -47,7 +47,6 @@ * Machine setup.. */ -char ignore_irq13; /* set if exception 16 works */ struct cpuinfo_x86 boot_cpu_data = { 0, 0, 0, 0, -1, 1, 0, 0, -1 }; unsigned long mmu_cr4_features; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/kernel/smpboot.c linux.2.5.47-ac4/arch/i386/kernel/smpboot.c --- linux.2.5.47/arch/i386/kernel/smpboot.c 2002-11-05 13:54:42.000000000 +0000 +++ linux.2.5.47-ac4/arch/i386/kernel/smpboot.c 2002-11-05 18:27:04.000000000 +0000 @@ -70,6 +70,11 @@ /* Per CPU bogomips and other parameters */ struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned; +/* Per CPU interrupt stacks */ +extern union thread_union init_irq_union; +union thread_union *irq_stacks[NR_CPUS] __cacheline_aligned = + { &init_irq_union, }; + /* Set when the idlers are all forked */ int smp_threads_ready; @@ -159,10 +164,8 @@ goto valid_k7; /* If we get here, it's not a certified SMP capable AMD system. */ - printk (KERN_INFO "WARNING: This combination of AMD processors is not suitable for SMP.\n"); tainted |= TAINT_UNSAFE_SMP; } - valid_k7: ; } @@ -765,6 +768,28 @@ return (send_status | accept_status); } +static void __init setup_irq_stack(struct task_struct *p, int cpu) +{ + unsigned long stk; + + stk = __get_free_pages(GFP_KERNEL, THREAD_ORDER+1); + if (!stk) + panic("I can't seem to allocate my irq stack. Oh well, giving up."); + + irq_stacks[cpu] = (void *)stk; + memset(irq_stacks[cpu], 0, THREAD_SIZE); + irq_stacks[cpu]->thread_info.cpu = cpu; + irq_stacks[cpu]->thread_info.preempt_count = 1; + /* interrupts are not preemptable */ + p->thread_info->irq_stack = (void *)irq_stacks[cpu]; + + /* If we want to make the irq stack more than one unit + * deep, we can chain then off of the irq_stack pointer + * here. + */ +} + + extern unsigned long cpu_initialized; static void __init do_boot_cpu (int apicid) @@ -788,6 +813,8 @@ if (IS_ERR(idle)) panic("failed fork for CPU %d", cpu); + setup_irq_stack(idle, cpu); + /* * We remove it from the pidhash and the runqueue * once we got the process: @@ -805,7 +832,13 @@ /* So we see what's up */ printk("Booting processor %d/%d eip %lx\n", cpu, apicid, start_eip); - stack_start.esp = (void *) (1024 + PAGE_SIZE + (char *)idle->thread_info); + + /* The -4 is to correct for the fact that the stack pointer + * is used to find the location of the thread_info structure + * by masking off several of the LSBs. Without the -4, esp + * is pointing to the page after the one the stack is on. + */ + stack_start.esp = (void *)(THREAD_SIZE - 4 + (char *)idle->thread_info); /* * This grunge runs the startup process for @@ -1128,6 +1161,15 @@ if (smp_b_stepping) printk(KERN_WARNING "WARNING: SMP operation may be unreliable with B stepping processors.\n"); + + /* See if we found multiple Athons and not all are "MP" */ + if (tainted&TAINT_UNSAFE_SMP) + { + if(cpucount) + printk (KERN_INFO "WARNING: This combination of AMD processors is not suitable for SMP.\n"); + else /* Not SMP so ok */ + tainted &= ~TAINT_UNSAFE_SMP; + } Dprintk("Boot done.\n"); /* diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/kernel/timers/Makefile linux.2.5.47-ac4/arch/i386/kernel/timers/Makefile --- linux.2.5.47/arch/i386/kernel/timers/Makefile 2002-10-31 14:57:24.000000000 +0000 +++ linux.2.5.47-ac4/arch/i386/kernel/timers/Makefile 2002-10-31 15:05:48.000000000 +0000 @@ -4,8 +4,8 @@ obj-y := timer.o -obj-y += timer_tsc.o -obj-y += timer_pit.o -obj-$(CONFIG_X86_CYCLONE) += timer_cyclone.o +obj-$(CONFIG_X86_TSC) += timer_tsc.o +obj-$(CONFIG_X86_PIT) += timer_pit.o +obj-$(CONFIG_X86_CYCLONE) += timer_cyclone.o include $(TOPDIR)/Rules.make diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/kernel/timers/timer.c linux.2.5.47-ac4/arch/i386/kernel/timers/timer.c --- linux.2.5.47/arch/i386/kernel/timers/timer.c 2002-10-31 14:57:24.000000000 +0000 +++ linux.2.5.47-ac4/arch/i386/kernel/timers/timer.c 2002-10-31 15:05:48.000000000 +0000 @@ -7,8 +7,10 @@ /* list of timers, ordered by preference, NULL terminated */ static struct timer_opts* timers[] = { +#ifdef CONFIG_X86_TSC &timer_tsc, -#ifndef CONFIG_X86_TSC +#endif +#ifdef CONFIG_X86_PIT &timer_pit, #endif NULL, diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/kernel/timers/timer_pit.c linux.2.5.47-ac4/arch/i386/kernel/timers/timer_pit.c --- linux.2.5.47/arch/i386/kernel/timers/timer_pit.c 2002-11-05 13:54:42.000000000 +0000 +++ linux.2.5.47-ac4/arch/i386/kernel/timers/timer_pit.c 2002-11-05 14:01:02.000000000 +0000 @@ -9,7 +9,9 @@ #include #include #include +#include #include +#include extern spinlock_t i8259A_lock; extern spinlock_t i8253_lock; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/kernel/trampoline.S linux.2.5.47-ac4/arch/i386/kernel/trampoline.S --- linux.2.5.47/arch/i386/kernel/trampoline.S 2002-10-31 14:57:24.000000000 +0000 +++ linux.2.5.47-ac4/arch/i386/kernel/trampoline.S 2002-10-31 15:05:48.000000000 +0000 @@ -36,7 +36,7 @@ ENTRY(trampoline_data) r_base = . - wbinvd # Needed for NUMA-Q should be harmless for others + wbinvd mov %cs, %ax # Code and data in the same place mov %ax, %ds @@ -54,7 +54,7 @@ lmsw %ax # into protected mode jmp flush_instr flush_instr: - ljmpl $__KERNEL_CS, $0x00100000 + ljmpl $__BOOT_CS, $0x00100000 # jump to startup_32 in arch/i386/kernel/head.S idt_48: @@ -67,8 +67,8 @@ # gdt_48: - .word 0x0800 # gdt limit = 2048, 256 GDT entries - .long cpu_gdt_table-__PAGE_OFFSET # gdt base = gdt (first SMP CPU) + .word __BOOT_DS + 7 # gdt limit + .long boot_gdt_table-__PAGE_OFFSET # gdt base = gdt (first SMP CPU) .globl trampoline_end trampoline_end: diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/kernel/traps.c linux.2.5.47-ac4/arch/i386/kernel/traps.c --- linux.2.5.47/arch/i386/kernel/traps.c 2002-11-11 16:39:08.000000000 +0000 +++ linux.2.5.47-ac4/arch/i386/kernel/traps.c 2002-11-11 16:47:25.000000000 +0000 @@ -56,6 +56,9 @@ struct desc_struct default_ldt[] = { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }; +/* Do we ignore FPU interrupts ? */ +char ignore_fpu_irq = 0; + /* * The IDT has to be page-aligned to simplify the Pentium * F0 0F bug workaround.. We have a special link segment @@ -702,7 +705,7 @@ asmlinkage void do_coprocessor_error(struct pt_regs * regs, long error_code) { - ignore_irq13 = 1; + ignore_fpu_irq = 1; math_error((void *)regs->eip); } @@ -759,7 +762,7 @@ { if (cpu_has_xmm) { /* Handle SIMD FPU exceptions on PIII+ processors. */ - ignore_irq13 = 1; + ignore_fpu_irq = 1; simd_math_error((void *)regs->eip); } else { /* diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/kernel/vm86.c linux.2.5.47-ac4/arch/i386/kernel/vm86.c --- linux.2.5.47/arch/i386/kernel/vm86.c 2002-10-31 14:57:24.000000000 +0000 +++ linux.2.5.47-ac4/arch/i386/kernel/vm86.c 2002-10-31 15:05:48.000000000 +0000 @@ -30,6 +30,7 @@ * */ +#include #include #include #include @@ -735,7 +736,7 @@ static inline void handle_irq_zombies(void) { int i; - for (i=3; i<16; i++) { + for (i=FIRST_VM86_IRQ; i<=LAST_VM86_IRQ; i++) { if (vm86_irqs[i].tsk) { if (task_valid(vm86_irqs[i].tsk)) continue; free_vm86_irq(i); @@ -748,7 +749,7 @@ int bit; unsigned long flags; - if ( (irqnumber<3) || (irqnumber>15) ) return 0; + if (invalid_vm86_irq(irqnumber)) return 0; if (vm86_irqs[irqnumber].tsk != current) return 0; spin_lock_irqsave(&irqbits_lock, flags); bit = irqbits & (1 << irqnumber); @@ -774,7 +775,7 @@ handle_irq_zombies(); if (!capable(CAP_SYS_ADMIN)) return -EPERM; if (!((1 << sig) & ALLOWED_SIGS)) return -EPERM; - if ( (irq<3) || (irq>15) ) return -EPERM; + if (invalid_vm86_irq(irq)) return -EPERM; if (vm86_irqs[irq].tsk) return -EPERM; ret = request_irq(irq, &irq_handler, 0, VM86_IRQNAME, 0); if (ret) return ret; @@ -784,7 +785,7 @@ } case VM86_FREE_IRQ: { handle_irq_zombies(); - if ( (irqnumber<3) || (irqnumber>15) ) return -EPERM; + if (invalid_vm86_irq(irqnumber)) return -EPERM; if (!vm86_irqs[irqnumber].tsk) return 0; if (vm86_irqs[irqnumber].tsk != current) return -EPERM; free_vm86_irq(irqnumber); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/lib/mmx.c linux.2.5.47-ac4/arch/i386/lib/mmx.c --- linux.2.5.47/arch/i386/lib/mmx.c 2002-10-31 14:57:24.000000000 +0000 +++ linux.2.5.47-ac4/arch/i386/lib/mmx.c 2002-10-31 15:05:49.000000000 +0000 @@ -170,56 +170,17 @@ /* maybe the prefetch stuff can go before the expensive fnsave... * but that is for later. -AV */ - __asm__ __volatile__ ( - "1: prefetch (%0)\n" - " prefetch 64(%0)\n" - " prefetch 128(%0)\n" - " prefetch 192(%0)\n" - " prefetch 256(%0)\n" - "2: \n" - ".section .fixup, \"ax\"\n" - "3: movw $0x1AEB, 1b\n" /* jmp on 26 bytes */ - " jmp 2b\n" - ".previous\n" - ".section __ex_table,\"a\"\n" - " .align 4\n" - " .long 1b, 3b\n" - ".previous" - : : "r" (from) ); - - for(i=0; i<(4096-320)/64; i++) - { - __asm__ __volatile__ ( - "1: prefetch 320(%0)\n" - "2: movq (%0), %%mm0\n" - " movntq %%mm0, (%1)\n" - " movq 8(%0), %%mm1\n" - " movntq %%mm1, 8(%1)\n" - " movq 16(%0), %%mm2\n" - " movntq %%mm2, 16(%1)\n" - " movq 24(%0), %%mm3\n" - " movntq %%mm3, 24(%1)\n" - " movq 32(%0), %%mm4\n" - " movntq %%mm4, 32(%1)\n" - " movq 40(%0), %%mm5\n" - " movntq %%mm5, 40(%1)\n" - " movq 48(%0), %%mm6\n" - " movntq %%mm6, 48(%1)\n" - " movq 56(%0), %%mm7\n" - " movntq %%mm7, 56(%1)\n" - ".section .fixup, \"ax\"\n" - "3: movw $0x05EB, 1b\n" /* jmp on 5 bytes */ - " jmp 2b\n" - ".previous\n" - ".section __ex_table,\"a\"\n" - " .align 4\n" - " .long 1b, 3b\n" - ".previous" - : : "r" (from), "r" (to) : "memory"); - from+=64; - to+=64; + for (i=4096-256;i>0;i-=256) { + int scratch; + __asm__ __volatile( + "movl 192(%1,%2),%0\n" + "movl 128(%1,%2),%0\n" + "movl 64(%1,%2),%0\n" + "movl 0(%1,%2),%0\n" + : "=&r" (scratch) + : "r" (from), "r" (i)); } - for(i=(4096-320)/64; i<4096/64; i++) + for(i=0; i<4096/64; i++) { __asm__ __volatile__ ( "2: movq (%0), %%mm0\n" diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/mach-defaults/pci-functions.h linux.2.5.47-ac4/arch/i386/mach-defaults/pci-functions.h --- linux.2.5.47/arch/i386/mach-defaults/pci-functions.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.47-ac4/arch/i386/mach-defaults/pci-functions.h 2002-10-31 15:05:52.000000000 +0000 @@ -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 -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/mach-generic/io_ports.h linux.2.5.47-ac4/arch/i386/mach-generic/io_ports.h --- linux.2.5.47/arch/i386/mach-generic/io_ports.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.47-ac4/arch/i386/mach-generic/io_ports.h 2002-10-31 15:05:52.000000000 +0000 @@ -0,0 +1,30 @@ +/* + * arch/i386/mach-generic/io_ports.h + * + * Machine specific IO port address definition for generic. + * Written by Osamu Tomita + */ +#ifndef _MACH_IO_PORTS_H +#define _MACH_IO_PORTS_H + +/* i8253A PIT registers */ +#define PIT_MODE 0x43 +#define PIT_CH0 0x40 +#define PIT_CH2 0x42 + +/* i8259A PIC registers */ +#define PIC_MASTER_CMD 0x20 +#define PIC_MASTER_IMR 0x21 +#define PIC_MASTER_ISR PIC_MASTER_CMD +#define PIC_MASTER_POLL PIC_MASTER_ISR +#define PIC_MASTER_OCW3 PIC_MASTER_ISR +#define PIC_SLAVE_CMD 0xa0 +#define PIC_SLAVE_IMR 0xa1 + +/* i8259A PIC related value */ +#define PIC_CASCADE_IR 2 +#define MASTER_ICW4_DEFAULT 0x01 +#define SLAVE_ICW4_DEFAULT 0x01 +#define PIC_ICW4_AEOI 2 + +#endif /* !_MACH_IO_PORTS_H */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/mach-generic/irq_vectors.h linux.2.5.47-ac4/arch/i386/mach-generic/irq_vectors.h --- linux.2.5.47/arch/i386/mach-generic/irq_vectors.h 2002-10-31 14:57:24.000000000 +0000 +++ linux.2.5.47-ac4/arch/i386/mach-generic/irq_vectors.h 2002-10-31 15:05:52.000000000 +0000 @@ -82,4 +82,11 @@ #define NR_IRQS 16 #endif +#define FPU_IRQ 13 + +#define FIRST_VM86_IRQ 3 +#define LAST_VM86_IRQ 15 +#define invalid_vm86_irq(irq) ((irq) < 3 || (irq) > 15) + + #endif /* _ASM_IRQ_VECTORS_H */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/mach-generic/mach_reboot.h linux.2.5.47-ac4/arch/i386/mach-generic/mach_reboot.h --- linux.2.5.47/arch/i386/mach-generic/mach_reboot.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.47-ac4/arch/i386/mach-generic/mach_reboot.h 2002-10-31 15:05:52.000000000 +0000 @@ -0,0 +1,30 @@ +/* + * arch/i386/mach-generic/mach_reboot.h + * + * Machine specific reboot functions for generic. + * Split out from reboot.c by Osamu Tomita + */ +#ifndef _MACH_REBOOT_H +#define _MACH_REBOOT_H + +static inline void kb_wait(void) +{ + int i; + + for (i = 0; i < 0x10000; i++) + if ((inb_p(0x64) & 0x02) == 0) + break; +} + +static inline void mach_reboot(void) +{ + int i; + for (i = 0; i < 100; i++) { + kb_wait(); + udelay(50); + outb(0xfe, 0x64); /* pulse reset low */ + udelay(50); + } +} + +#endif /* !_MACH_REBOOT_H */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/mach-pc9800/entry_arch.h linux.2.5.47-ac4/arch/i386/mach-pc9800/entry_arch.h --- linux.2.5.47/arch/i386/mach-pc9800/entry_arch.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.47-ac4/arch/i386/mach-pc9800/entry_arch.h 2002-10-31 15:05:52.000000000 +0000 @@ -0,0 +1 @@ +#include "../mach-generic/entry_arch.h" diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/mach-pc9800/io_ports.h linux.2.5.47-ac4/arch/i386/mach-pc9800/io_ports.h --- linux.2.5.47/arch/i386/mach-pc9800/io_ports.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.47-ac4/arch/i386/mach-pc9800/io_ports.h 2002-10-31 15:05:52.000000000 +0000 @@ -0,0 +1,30 @@ +/* + * arch/i386/mach-pc9800/io_ports.h + * + * Machine specific IO port address definition for PC-9800. + * Written by Osamu Tomita + */ +#ifndef _MACH_IO_PORTS_H +#define _MACH_IO_PORTS_H + +/* i8253A PIT registers */ +#define PIT_MODE 0x77 +#define PIT_CH0 0x71 +#define PIT_CH2 0x75 + +/* i8259A PIC registers */ +#define PIC_MASTER_CMD 0x00 +#define PIC_MASTER_IMR 0x02 +#define PIC_MASTER_ISR PIC_MASTER_CMD +#define PIC_MASTER_POLL PIC_MASTER_ISR +#define PIC_MASTER_OCW3 PIC_MASTER_ISR +#define PIC_SLAVE_CMD 0x08 +#define PIC_SLAVE_IMR 0x0a + +/* i8259A PIC related values */ +#define PIC_CASCADE_IR 7 +#define MASTER_ICW4_DEFAULT 0x1d +#define SLAVE_ICW4_DEFAULT 0x09 +#define PIC_ICW4_AEOI 0x02 + +#endif /* !_MACH_IO_PORTS_H */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/mach-pc9800/irq_vectors.h linux.2.5.47-ac4/arch/i386/mach-pc9800/irq_vectors.h --- linux.2.5.47/arch/i386/mach-pc9800/irq_vectors.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.47-ac4/arch/i386/mach-pc9800/irq_vectors.h 2002-10-31 15:05:52.000000000 +0000 @@ -0,0 +1,93 @@ +/* + * This file should contain #defines for all of the interrupt vector + * numbers used by this architecture. + * + * In addition, there are some standard defines: + * + * FIRST_EXTERNAL_VECTOR: + * The first free place for external interrupts + * + * SYSCALL_VECTOR: + * The IRQ vector a syscall makes the user to kernel transition + * under. + * + * TIMER_IRQ: + * The IRQ number the timer interrupt comes in at. + * + * NR_IRQS: + * The total number of interrupt vectors (including all the + * architecture specific interrupts) needed. + * + */ +#ifndef _ASM_IRQ_VECTORS_H +#define _ASM_IRQ_VECTORS_H + +/* + * IDT vectors usable for external interrupt sources start + * at 0x20: + */ +#define FIRST_EXTERNAL_VECTOR 0x20 + +#define SYSCALL_VECTOR 0x80 + +/* + * Vectors 0x20-0x2f are used for ISA interrupts. + */ + +/* + * Special IRQ vectors used by the SMP architecture, 0xf0-0xff + * + * some of the following vectors are 'rare', they are merged + * into a single vector (CALL_FUNCTION_VECTOR) to save vector space. + * TLB, reschedule and local APIC vectors are performance-critical. + * + * Vectors 0xf0-0xfa are free (reserved for future Linux use). + */ +#define SPURIOUS_APIC_VECTOR 0xff +#define ERROR_APIC_VECTOR 0xfe +#define INVALIDATE_TLB_VECTOR 0xfd +#define RESCHEDULE_VECTOR 0xfc +#define CALL_FUNCTION_VECTOR 0xfb + +#define THERMAL_APIC_VECTOR 0xf0 +/* + * Local APIC timer IRQ vector is on a different priority level, + * to work around the 'lost local interrupt if more than 2 IRQ + * sources per level' errata. + */ +#define LOCAL_TIMER_VECTOR 0xef + +/* + * First APIC vector available to drivers: (vectors 0x30-0xee) + * we start at 0x31 to spread out vectors evenly between priority + * levels. (0x80 is the syscall vector) + */ +#define FIRST_DEVICE_VECTOR 0x31 +#define FIRST_SYSTEM_VECTOR 0xef + +#define TIMER_IRQ 0 + +/* + * 16 8259A IRQ's, 208 potential APIC interrupt sources. + * Right now the APIC is mostly only used for SMP. + * 256 vectors is an architectural limit. (we can have + * more than 256 devices theoretically, but they will + * have to use shared interrupts) + * Since vectors 0x00-0x1f are used/reserved for the CPU, + * the usable vector space is 0x20-0xff (224 vectors) + */ +#ifdef CONFIG_X86_IO_APIC +#define NR_IRQS 224 +#else +#define NR_IRQS 16 +#endif + +#define FPU_IRQ 8 + +#define FIRST_VM86_IRQ 2 +#define LAST_VM86_IRQ 15 +#define invalid_vm86_irq(irq) ((irq) < 2 || (irq) == 7 || (irq) > 15) + +#endif /* _ASM_IRQ_VECTORS_H */ + + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/mach-pc9800/mach_apic.h linux.2.5.47-ac4/arch/i386/mach-pc9800/mach_apic.h --- linux.2.5.47/arch/i386/mach-pc9800/mach_apic.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.47-ac4/arch/i386/mach-pc9800/mach_apic.h 2002-10-31 15:05:52.000000000 +0000 @@ -0,0 +1 @@ +#include "../mach-generic/mach_apic.h" diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/mach-pc9800/mach_reboot.h linux.2.5.47-ac4/arch/i386/mach-pc9800/mach_reboot.h --- linux.2.5.47/arch/i386/mach-pc9800/mach_reboot.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.47-ac4/arch/i386/mach-pc9800/mach_reboot.h 2002-10-31 15:05:52.000000000 +0000 @@ -0,0 +1,21 @@ +/* + * arch/i386/mach-pc9800/mach_reboot.h + * + * Machine specific reboot functions for PC-9800. + * Written by Osamu Tomita + */ +#ifndef _MACH_REBOOT_H +#define _MACH_REBOOT_H + +#ifdef CMOS_WRITE +#undef CMOS_WRITE +#define CMOS_WRITE(a,b) do{}while(0) +#endif + +static inline void mach_reboot(void) +{ + outb(0, 0xf0); /* signal CPU reset */ + mdelay(1); +} + +#endif /* !_MACH_REBOOT_H */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/mach-pc9800/Makefile linux.2.5.47-ac4/arch/i386/mach-pc9800/Makefile --- linux.2.5.47/arch/i386/mach-pc9800/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.47-ac4/arch/i386/mach-pc9800/Makefile 2002-10-31 15:05:52.000000000 +0000 @@ -0,0 +1,15 @@ +# +# Makefile for the linux kernel. +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# +# Note 2! The CFLAGS definitions are now in the main makefile... + +EXTRA_CFLAGS += -I../kernel +export-objs := + +obj-y := setup.o + +include $(TOPDIR)/Rules.make diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/mach-pc9800/pci-functions.h linux.2.5.47-ac4/arch/i386/mach-pc9800/pci-functions.h --- linux.2.5.47/arch/i386/mach-pc9800/pci-functions.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.47-ac4/arch/i386/mach-pc9800/pci-functions.h 2002-10-31 15:05:52.000000000 +0000 @@ -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 -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/mach-pc9800/setup_arch_post.h linux.2.5.47-ac4/arch/i386/mach-pc9800/setup_arch_post.h --- linux.2.5.47/arch/i386/mach-pc9800/setup_arch_post.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.47-ac4/arch/i386/mach-pc9800/setup_arch_post.h 2002-10-31 15:05:52.000000000 +0000 @@ -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 -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/mach-pc9800/setup_arch_pre.h linux.2.5.47-ac4/arch/i386/mach-pc9800/setup_arch_pre.h --- linux.2.5.47/arch/i386/mach-pc9800/setup_arch_pre.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.47-ac4/arch/i386/mach-pc9800/setup_arch_pre.h 2002-10-31 15:05:52.000000000 +0000 @@ -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; +unsigned long tick_usec; /* ACTHZ period (usec) */ +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 -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/mach-pc9800/setup.c linux.2.5.47-ac4/arch/i386/mach-pc9800/setup.c --- linux.2.5.47/arch/i386/mach-pc9800/setup.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.47-ac4/arch/i386/mach-pc9800/setup.c 2002-10-31 15:05:52.000000000 +0000 @@ -0,0 +1,117 @@ +/* + * Machine specific setup for generic + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +struct sys_desc_table_struct { + unsigned short length; + unsigned char table[0]; +}; + +/* Indicates PC-9800 architecture No:0 Yes:1 */ +extern int pc98; + +/** + * 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; + pc98 = 1; +} + +/** + * 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 Arcitecture) 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 -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/mach-summit/io_ports.h linux.2.5.47-ac4/arch/i386/mach-summit/io_ports.h --- linux.2.5.47/arch/i386/mach-summit/io_ports.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.47-ac4/arch/i386/mach-summit/io_ports.h 2002-10-31 15:05:52.000000000 +0000 @@ -0,0 +1 @@ +#include "../mach-generic/io_ports.h" diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/mach-summit/mach_reboot.h linux.2.5.47-ac4/arch/i386/mach-summit/mach_reboot.h --- linux.2.5.47/arch/i386/mach-summit/mach_reboot.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.47-ac4/arch/i386/mach-summit/mach_reboot.h 2002-10-31 15:05:52.000000000 +0000 @@ -0,0 +1 @@ +#include "../mach-generic/mach_reboot.h" diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/mach-visws/io_ports.h linux.2.5.47-ac4/arch/i386/mach-visws/io_ports.h --- linux.2.5.47/arch/i386/mach-visws/io_ports.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.47-ac4/arch/i386/mach-visws/io_ports.h 2002-10-31 15:05:52.000000000 +0000 @@ -0,0 +1 @@ +#include "../mach-generic/io_ports.h" diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/mach-visws/irq_vectors.h linux.2.5.47-ac4/arch/i386/mach-visws/irq_vectors.h --- linux.2.5.47/arch/i386/mach-visws/irq_vectors.h 2002-10-31 14:57:24.000000000 +0000 +++ linux.2.5.47-ac4/arch/i386/mach-visws/irq_vectors.h 2002-10-31 15:05:52.000000000 +0000 @@ -61,4 +61,6 @@ #define NR_IRQS 16 #endif +#define FPU_IRQ 13 + #endif /* _ASM_IRQ_VECTORS_H */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/mach-visws/mach_reboot.h linux.2.5.47-ac4/arch/i386/mach-visws/mach_reboot.h --- linux.2.5.47/arch/i386/mach-visws/mach_reboot.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.47-ac4/arch/i386/mach-visws/mach_reboot.h 2002-10-31 15:05:52.000000000 +0000 @@ -0,0 +1 @@ +#include "../mach-generic/mach_reboot.h" diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/mach-voyager/irq_vectors.h linux.2.5.47-ac4/arch/i386/mach-voyager/irq_vectors.h --- linux.2.5.47/arch/i386/mach-voyager/irq_vectors.h 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.47-ac4/arch/i386/mach-voyager/irq_vectors.h 2002-10-31 15:05:52.000000000 +0000 @@ -57,6 +57,12 @@ #define NR_IRQS 224 +#define FPU_IRQ 13 + +#define FIRST_VM86_IRQ 3 +#define LAST_VM86_IRQ 15 +#define invalid_vm86_irq(irq) ((irq) < 3 || (irq) > 15) + #ifndef __ASSEMBLY__ extern asmlinkage void vic_cpi_interrupt(void); extern asmlinkage void vic_sys_interrupt(void); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/Makefile linux.2.5.47-ac4/arch/i386/Makefile --- linux.2.5.47/arch/i386/Makefile 2002-11-11 16:39:08.000000000 +0000 +++ linux.2.5.47-ac4/arch/i386/Makefile 2002-11-11 16:42:21.000000000 +0000 @@ -49,8 +49,16 @@ ifdef CONFIG_VISWS MACHINE := mach-visws else +ifdef CONFIG_VOYAGER +MACHINE := mach-voyager +else MACHINE := mach-generic endif +endif + +ifdef CONFIG_X86_STACK_CHECK +CFLAGS += -p +endif HEAD := arch/i386/kernel/head.o arch/i386/kernel/init_task.o @@ -63,8 +71,8 @@ # FIXME: is drivers- right ? drivers-$(CONFIG_OPROFILE) += arch/i386/oprofile/ -CFLAGS += -Iarch/i386/$(MACHINE) -AFLAGS += -Iarch/i386/$(MACHINE) +CFLAGS += -Iarch/i386/$(MACHINE) -Iarch/i386/mach-defaults +AFLAGS += -Iarch/i386/$(MACHINE) -Iarch/i386/mach-defaults makeboot = $(call descend,arch/i386/boot,$(1)) @@ -91,6 +99,7 @@ +@$(call makeboot,BOOTIMAGE=$(BOOTIMAGE) install) archclean: - @$(MAKE) -f scripts/Makefile.clean obj=arch/i386/boot + $(MAKE) -f scripts/Makefile.clean obj=arch/i386/boot + $(MAKE) -f scripts/Makefile.clean obj=arch/i386/boot98 archmrproper: diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/pci/direct.c linux.2.5.47-ac4/arch/i386/pci/direct.c --- linux.2.5.47/arch/i386/pci/direct.c 2002-10-31 14:57:24.000000000 +0000 +++ linux.2.5.47-ac4/arch/i386/pci/direct.c 2002-10-31 15:05:49.000000000 +0000 @@ -261,7 +261,6 @@ } local_irq_restore(flags); - pci_root_ops = NULL; return 0; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/i386/pci/pcbios.c linux.2.5.47-ac4/arch/i386/pci/pcbios.c --- linux.2.5.47/arch/i386/pci/pcbios.c 2002-10-31 14:57:24.000000000 +0000 +++ linux.2.5.47-ac4/arch/i386/pci/pcbios.c 2002-10-31 15:05:49.000000000 +0000 @@ -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 -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/ia64/hp/sim/simscsi.c linux.2.5.47-ac4/arch/ia64/hp/sim/simscsi.c --- linux.2.5.47/arch/ia64/hp/sim/simscsi.c 2002-11-05 13:54:42.000000000 +0000 +++ linux.2.5.47-ac4/arch/ia64/hp/sim/simscsi.c 2002-11-11 20:22:07.000000000 +0000 @@ -115,6 +115,9 @@ { templ->proc_name = "simscsi"; host = scsi_register(templ, 0); + if(host == NULL) + return 0; + return 1; /* fake one SCSI host adapter */ } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/s390/boot/Makefile linux.2.5.47-ac4/arch/s390/boot/Makefile --- linux.2.5.47/arch/s390/boot/Makefile 2002-10-31 14:57:34.000000000 +0000 +++ linux.2.5.47-ac4/arch/s390/boot/Makefile 2002-10-31 15:05:57.000000000 +0000 @@ -1,28 +1,27 @@ # -# arch/s390/boot/Makefile +# Makefile for the linux s390-specific parts of the memory manager. # EXTRA_AFLAGS := -traditional include $(TOPDIR)/Rules.make -%.lnk: %.o - $(LD) $(LDFLAGS) -Ttext 0x0 -o $@ $< +quiet_cmd_listing = OBJDUMP $(echo_target) +cmd_listing = $(OBJDUMP) --disassemble --disassemble-all \ + --disassemble-zeroes --reloc vmlinux > $@ -%.boot: %.lnk - $(OBJCOPY) $(OBJCOPYFLAGS) $< $@ +$(obj)/image: vmlinux + $(call if_changed,objcopy) -image: $(TOPDIR)/vmlinux \ - iplfba.boot ipleckd.boot ipldump.boot - $(OBJCOPY) $(OBJCOPYFLAGS) $(TOPDIR)/vmlinux image - $(NM) $(TOPDIR)/vmlinux | grep -v '\(compiled\)\|\( [aUw] \)\|\(\.\)\|\(LASH[RL]DI\)' | sort > $(TOPDIR)/System.map +$(obj)/listing: vmlinux + $(call if_changed,listing) -listing: ../../../vmlinux - $(OBJDUMP) --disassemble --disassemble-all --disassemble-zeroes --reloc $(TOPDIR)/vmlinux > listing +image: $(obj)/image + +listing: $(obj)/listing clean: - rm -f image listing iplfba.boot ipleckd.boot ipldump.boot + rm -f $(obj)/image $(obj)/listing install: $(CONFIGURE) $(BOOTIMAGE) - sh -x ./install.sh $(KERNELRELEASE) $(BOOTIMAGE) $(TOPDIR)/System.map $(TOPDIR)/Kerntypes "$(INSTALL_PATH)" - + sh -x $(obj)/install.sh $(KERNELRELEASE) $(BOOTIMAGE) System.map Kerntypes "$(INSTALL_PATH)" diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/s390/defconfig linux.2.5.47-ac4/arch/s390/defconfig --- linux.2.5.47/arch/s390/defconfig 2002-10-31 14:57:35.000000000 +0000 +++ linux.2.5.47-ac4/arch/s390/defconfig 2002-11-01 11:32:19.000000000 +0000 @@ -39,7 +39,7 @@ # CONFIG_SMP=y CONFIG_MATHEMU=y -CONFIG_NR_CPUS=64 +CONFIG_NR_CPUS=32 # # I/O subsystem configuration @@ -147,7 +147,7 @@ CONFIG_DASD=y CONFIG_DASD_ECKD=y CONFIG_DASD_FBA=y -# CONFIG_DASD_DIAG is not set +CONFIG_DASD_DIAG=y # # Multi-device support (RAID and LVM) @@ -301,7 +301,7 @@ # CONFIG_NTFS_RW is not set # CONFIG_HPFS_FS is not set CONFIG_PROC_FS=y -CONFIG_DEVFS_FS=y +# CONFIG_DEVFS_FS is not set # CONFIG_DEVFS_MOUNT is not set # CONFIG_DEVFS_DEBUG is not set # CONFIG_DEVPTS_FS is not set @@ -325,13 +325,16 @@ # CONFIG_INTERMEZZO_FS is not set CONFIG_NFS_FS=y # CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set # CONFIG_ROOT_NFS is not set CONFIG_NFSD=y # CONFIG_NFSD_V3 is not set +# CONFIG_NFSD_V4 is not set # CONFIG_NFSD_TCP is not set CONFIG_SUNRPC=y CONFIG_LOCKD=y CONFIG_EXPORTFS=y +# CONFIG_CIFS is not set # CONFIG_SMB_FS is not set # CONFIG_NCP_FS is not set # CONFIG_NCPFS_PACKET_SIGNING is not set @@ -342,6 +345,7 @@ # CONFIG_NCPFS_SMALLDOS is not set # CONFIG_NCPFS_NLS is not set # CONFIG_NCPFS_EXTRAS is not set +# CONFIG_AFS_FS is not set # CONFIG_ZISOFS_FS is not set # diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/s390/Kconfig linux.2.5.47-ac4/arch/s390/Kconfig --- linux.2.5.47/arch/s390/Kconfig 2002-11-11 16:39:09.000000000 +0000 +++ linux.2.5.47-ac4/arch/s390/Kconfig 2002-11-11 16:50:46.000000000 +0000 @@ -115,6 +115,12 @@ int "Maximum number of CPUs (2-32)" depends on SMP default "32" + help + This allows you to specify the maximum number of CPUs which this + kernel will support. The maximum supported value is 32 and the + minimum value which makes sense is 2. + This is purely to save memory - each supported CPU adds + approximately eight kilobytes to the kernel image. comment "I/O subsystem configuration" @@ -153,6 +159,15 @@ config PREEMPT bool "Preemptible Kernel" + help + This option reduces the latency of the kernel when reacting to + real-time or interactive events by allowing a low priority process to + be preempted even if it is in kernel mode executing a system call. + This allows applications to run more reliably even when the system is + under load. + + Say Y here if you are building a kernel for a desktop, embedded + or real-time system. Say N if you are unsure. config IPL bool "Builtin IPL record support" diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/s390/lib/uaccess.S linux.2.5.47-ac4/arch/s390/lib/uaccess.S --- linux.2.5.47/arch/s390/lib/uaccess.S 2002-10-31 14:57:35.000000000 +0000 +++ linux.2.5.47-ac4/arch/s390/lib/uaccess.S 2002-11-01 11:32:36.000000000 +0000 @@ -1,9 +1,9 @@ /* * arch/s390/lib/uaccess.S - * fixup routines for copy_{from|to}_user functions. + * __copy_{from|to}_user functions. * * s390 - * Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Copyright (C) 2000,2002 IBM Deutschland Entwicklung GmbH, IBM Corporation * Authors(s): Martin Schwidefsky (schwidefsky@de.ibm.com) * * These functions have standard call interface @@ -22,17 +22,23 @@ 1: sacf 0 lr %r2,%r5 br %r14 -2: sll %r4,1 - srl %r4,1 - lhi %r3,-4096 - sll %r3,1 - srl %r3,1 - n %r3,__LC_TRANS_EXC_ADDR - sr %r3,%r4 - jm 1b - j 0b +2: lhi %r1,-4096 + lr %r3,%r4 + slr %r3,%r1 # %r3 = %r4 + 4096 + nr %r3,%r1 # %r3 = (%r4 + 4096) & -4096 + slr %r3,%r4 # %r3 = #bytes to next user page boundary + clr %r5,%r3 # copy crosses next page boundary ? + jnh 1b # no, this page fauled + # The page after the current user page might have faulted. + # We cant't find out which page because the program check handler + # might have callled schedule, destroying all lowcore information. + # We retry with the shortened length. +3: mvcle %r2,%r4,0 + jo 3b + j 1b .section __ex_table,"a" .long 0b,2b + .long 3b,1b .previous .align 4 @@ -46,17 +52,23 @@ 1: sacf 0 lr %r2,%r3 br %r14 -2: sll %r4,1 - srl %r4,1 - lhi %r5,-4096 - sll %r5,1 - srl %r5,1 - n %r5,__LC_TRANS_EXC_ADDR - sr %r5,%r4 - jm 1b - j 0b +2: lhi %r1,-4096 + lr %r5,%r4 + slr %r5,%r1 # %r5 = %r4 + 4096 + nr %r5,%r1 # %r5 = (%r4 + 4096) & -4096 + slr %r5,%r4 # %r5 = #bytes to next user page boundary + clr %r3,%r5 # copy crosses next page boundary ? + jnh 1b # no, the current page fauled + # The page after the current user page might have faulted. + # We cant't find out which page because the program check handler + # might have callled schedule, destroying all lowcore information. + # We retry with the shortened length. +3: mvcle %r4,%r2,0 + jo 3b + j 1b .section __ex_table,"a" - .long 0b,2b + .long 0b,2b + .long 3b,1b .previous .align 4 @@ -71,18 +83,26 @@ 0: mvcle %r4,%r2,0 jo 0b 1: sacf 0 - lr %r2,%r3 br %r14 -2: sll %r4,1 - srl %r4,1 - lhi %r5,-4096 - sll %r5,1 - srl %r5,1 - n %r5,__LC_TRANS_EXC_ADDR - sr %r5,%r4 - jm 1b - j 0b +2: lr %r2,%r5 + lhi %r1,-4096 + slr %r5,%r1 # %r5 = %r4 + 4096 + nr %r5,%r1 # %r5 = (%r4 + 4096) & -4096 + slr %r5,%r4 # %r5 = #bytes to next user page boundary + clr %r2,%r5 # copy crosses next page boundary ? + jnh 1b # no, the current page fauled + # The page after the current user page might have faulted. + # We cant't find out which page because the program check handler + # might have callled schedule, destroying all lowcore information. + # We retry with the shortened length. + slr %r2,%r5 +3: mvcle %r4,%r2,0 + jo 3b + j 1b +4: alr %r2,%r5 + j 1b .section __ex_table,"a" - .long 0b,2b + .long 0b,2b + .long 3b,4b .previous diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/s390/Makefile linux.2.5.47-ac4/arch/s390/Makefile --- linux.2.5.47/arch/s390/Makefile 2002-10-31 14:57:35.000000000 +0000 +++ linux.2.5.47-ac4/arch/s390/Makefile 2002-11-01 11:32:36.000000000 +0000 @@ -28,18 +28,14 @@ all: image listing -listing: vmlinux - @$(MAKEBOOT) listing +makeboot = $(call descend,arch/$(ARCH)/boot,$(1)) +BOOTIMAGE= arch/$(ARCH)/boot/image -MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot - -image: vmlinux - @$(MAKEBOOT) image - -install: vmlinux - @$(MAKEBOOT) BOOTIMAGE=image install +listing install image: vmlinux + +@$(call makeboot,BOOTIMAGE=$(BOOTIMAGE) $@) archclean: + +@$(call makeboot,clean) archmrproper: diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/s390x/boot/Makefile linux.2.5.47-ac4/arch/s390x/boot/Makefile --- linux.2.5.47/arch/s390x/boot/Makefile 2002-10-31 14:57:34.000000000 +0000 +++ linux.2.5.47-ac4/arch/s390x/boot/Makefile 2002-10-31 15:05:57.000000000 +0000 @@ -6,22 +6,22 @@ include $(TOPDIR)/Rules.make -%.lnk: %.o - $(LD) -Ttext 0x0 -o $@ $< +quiet_cmd_listing = OBJDUMP $(echo_target) +cmd_listing = $(OBJDUMP) --disassemble --disassemble-all \ + --disassemble-zeroes --reloc vmlinux > $@ -%.boot: %.lnk - $(OBJCOPY) $(OBJCOPYFLAGS) $< $@ +$(obj)/image: vmlinux + $(call if_changed,objcopy) -image: $(TOPDIR)/vmlinux \ - iplfba.boot ipleckd.boot ipldump.boot - $(OBJCOPY) $(OBJCOPYFLAGS) $< $@ - $(NM) $(TOPDIR)/vmlinux | grep -v '\(compiled\)\|\( [aUw] \)\|\(\.\)\|\(LASH[RL]DI\)' | sort > $(TOPDIR)/System.map +$(obj)/listing: vmlinux + $(call if_changed,listing) -listing: ../../../vmlinux - $(OBJDUMP) --disassemble --disassemble-all --disassemble-zeroes --reloc $(TOPDIR)/vmlinux > listing +image: $(obj)/image + +listing: $(obj)/listing clean: - rm -f image listing iplfba.boot ipleckd.boot ipldump.boot + rm -f $(obj)/image $(obj)/listing install: $(CONFIGURE) $(BOOTIMAGE) - sh -x ./install.sh $(KERNELRELEASE) $(BOOTIMAGE) $(TOPDIR)/System.map $(TOPDIR)/Kerntypes "$(INSTALL_PATH)" + sh -x $(obj)/install.sh $(KERNELRELEASE) $(BOOTIMAGE) System.map Kerntypes "$(INSTALL_PATH)" diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/s390x/defconfig linux.2.5.47-ac4/arch/s390x/defconfig --- linux.2.5.47/arch/s390x/defconfig 2002-10-31 14:57:34.000000000 +0000 +++ linux.2.5.47-ac4/arch/s390x/defconfig 2002-10-31 15:05:57.000000000 +0000 @@ -38,15 +38,15 @@ # Processor type and features # CONFIG_SMP=y +CONFIG_NR_CPUS=64 CONFIG_S390_SUPPORT=y CONFIG_BINFMT_ELF32=y -CONFIG_NR_CPUS=64 # # I/O subsystem configuration # CONFIG_MACHCHK_WARNING=y -CONFIG_QDIO=y +CONFIG_QDIO=m # CONFIG_QDIO_PERF_STATS is not set # @@ -301,7 +301,7 @@ # CONFIG_NTFS_RW is not set # CONFIG_HPFS_FS is not set CONFIG_PROC_FS=y -CONFIG_DEVFS_FS=y +# CONFIG_DEVFS_FS is not set # CONFIG_DEVFS_MOUNT is not set # CONFIG_DEVFS_DEBUG is not set # CONFIG_DEVPTS_FS is not set @@ -325,13 +325,16 @@ # CONFIG_INTERMEZZO_FS is not set CONFIG_NFS_FS=y # CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set # CONFIG_ROOT_NFS is not set CONFIG_NFSD=y # CONFIG_NFSD_V3 is not set +# CONFIG_NFSD_V4 is not set # CONFIG_NFSD_TCP is not set CONFIG_SUNRPC=y CONFIG_LOCKD=y CONFIG_EXPORTFS=y +# CONFIG_CIFS is not set # CONFIG_SMB_FS is not set # CONFIG_NCP_FS is not set # CONFIG_NCPFS_PACKET_SIGNING is not set @@ -342,6 +345,7 @@ # CONFIG_NCPFS_SMALLDOS is not set # CONFIG_NCPFS_NLS is not set # CONFIG_NCPFS_EXTRAS is not set +# CONFIG_AFS_FS is not set # CONFIG_ZISOFS_FS is not set # diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/s390x/Kconfig linux.2.5.47-ac4/arch/s390x/Kconfig --- linux.2.5.47/arch/s390x/Kconfig 2002-11-11 16:39:09.000000000 +0000 +++ linux.2.5.47-ac4/arch/s390x/Kconfig 2002-11-11 16:50:46.000000000 +0000 @@ -108,6 +108,12 @@ int "Maximum number of CPUs (2-64)" depends on SMP default "64" + This allows you to specify the maximum number of CPUs which this + kernel will support. The maximum supported value is 32 and the + minimum value which makes sense is 2. + + This is purely to save memory - each supported CPU adds + approximately eight kilobytes to the kernel image. config S390_SUPPORT bool "Kernel support for 31 bit emulation" @@ -161,6 +167,15 @@ config PREEMPT bool "Preemptible Kernel" + help + This option reduces the latency of the kernel when reacting to + real-time or interactive events by allowing a low priority process to + be preempted even if it is in kernel mode executing a system call. + This allows applications to run more reliably even when the system is + under load. + + Say Y here if you are building a kernel for a desktop, embedded + or real-time system. Say N if you are unsure. config IPL bool "Builtin IPL record support" diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/s390x/kernel/linux32.c linux.2.5.47-ac4/arch/s390x/kernel/linux32.c --- linux.2.5.47/arch/s390x/kernel/linux32.c 2002-10-31 14:57:34.000000000 +0000 +++ linux.2.5.47-ac4/arch/s390x/kernel/linux32.c 2002-11-02 21:33:06.000000000 +0000 @@ -2492,8 +2492,23 @@ CMSG32_ALIGN(sizeof(struct cmsghdr32))); kcmsg32->cmsg_len = clen32; + switch (kcmsg32->cmsg_type) { + /* + * The timestamp type's data needs to be converted + * from 64-bit time values to 32-bit time values + */ + case SO_TIMESTAMP: { + __kernel_time_t32* ptr_time32 = CMSG32_DATA(kcmsg32); + __kernel_time_t* ptr_time = CMSG_DATA(ucmsg); + get_user(*ptr_time32, ptr_time); + get_user(*(ptr_time32+1), ptr_time+1); + kcmsg32->cmsg_len -= 2*(sizeof(__kernel_time_t) - + sizeof(__kernel_time_t32)); + } + default:; + } ucmsg = (struct cmsghdr *) (((char *)ucmsg) + CMSG_ALIGN(clen64)); - wp = (((char *)kcmsg32) + CMSG32_ALIGN(clen32)); + wp = (((char *)kcmsg32) + CMSG32_ALIGN(kcmsg32->cmsg_len)); } /* Copy back fixed up data, and adjust pointers. */ @@ -2608,6 +2623,9 @@ err = sock->ops->recvmsg(&iocb, sock, &kern_msg, total_len, user_flags, si->scm); + if (err >= 0) + scm_recv32(sock, msg, &iocb, flags, cmsg_ptr); + if (-EIOCBQUEUED == err) err = wait_on_sync_kiocb(&iocb); @@ -2640,7 +2658,7 @@ sockfd_put(sock); } - if(uaddr != NULL && err >= 0) + if(uaddr != NULL && err >= 0 && kern_msg.msg_namelen) err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr, uaddr_len); if(cmsg_ptr != 0 && err >= 0) { unsigned long ucmsg_ptr = ((unsigned long)kern_msg.msg_control); @@ -2742,6 +2760,32 @@ return err; } +static __inline__ void +scm_recv32(struct socket *sock, struct msghdr *msg, + struct sock_iocb *si, int flags, unsigned long cmsg_ptr) +{ + if(!msg->msg_control) { + if(sock->passcred || si->scm->fp) + msg->msg_flags |= MSG_CTRUNC; + if(si->scm->fp) + __scm_destroy(si->scm); + } else { + /* If recvmsg processing itself placed some + * control messages into user space, it's is + * using 64-bit CMSG processing, so we need + * to fix it up before we tack on more stuff. + */ + if((unsigned long) msg->msg_control != cmsg_ptr) + cmsg32_recvmsg_fixup(msg, cmsg_ptr); + /* Wheee... */ + if(sock->passcred) + put_cmsg32(msg, SOL_SOCKET, SCM_CREDENTIALS, + sizeof(si->scm->creds), &si->scm->creds); + if(si->scm->fp != NULL) + scm_detach_fds32(msg, si->scm); + } +} + /* * BSD recvmsg interface */ @@ -2815,6 +2859,9 @@ err = sock->ops->recvmsg(&iocb, sock, &msg_sys, total_len, flags, si->scm); + if (err >= 0) + scm_recv32(sock, msg, &iocb, flags, cmsg_ptr); + if (-EIOCBQUEUED == err) err = wait_on_sync_kiocb(&iocb); if (err < 0) @@ -2828,27 +2875,13 @@ if (err < 0) goto out_freeiov; } - if(!msg_sys.msg_control) { - if(sock->passcred || si->scm->fp) - msg_sys.msg_flags |= MSG_CTRUNC; - if(si->scm->fp) - __scm_destroy(si->scm); - } else { - /* If recvmsg processing itself placed some - * control messages into user space, it's is - * using 64-bit CMSG processing, so we need - * to fix it up before we tack on more stuff. - */ - if((unsigned long) msg_sys.msg_control != cmsg_ptr) - cmsg32_recvmsg_fixup(&msg_sys, cmsg_ptr); - /* Wheee... */ - if(sock->passcred) - put_cmsg32(&msg_sys, - SOL_SOCKET, SCM_CREDENTIALS, - sizeof(si->scm->creds), &si->scm->creds); - if(si->scm->fp != NULL) - scm_detach_fds32(&msg_sys, si->scm); - } + err = __put_user(msg_sys.msg_flags, &msg->msg_flags); + if (err) + goto out_freeiov; + err = __put_user((__kernel_size_t32) ((unsigned long)msg_sys.msg_control - cmsg_ptr), &msg->msg_controllen); + if (err) + goto out_freeiov; + err = len; out_freeiov: if (iov != iovstack) @@ -2941,6 +2974,20 @@ if (level == SOL_ICMPV6 && optname == ICMPV6_FILTER) return do_set_icmpv6_filter(fd, level, optname, optval, optlen); + if (level == SOL_SOCKET && + (optname == SO_SNDTIMEO || optname == SO_RCVTIMEO)) { + long ret; + struct timeval tmp; + mm_segment_t old_fs; + + if (get_tv32(&tmp, (struct timeval32 *)optval )) + return -EFAULT; + old_fs = get_fs(); + set_fs(KERNEL_DS); + ret = sys_setsockopt(fd, level, optname, (char *) &tmp, sizeof(struct timeval)); + set_fs(old_fs); + return ret; + } return sys_setsockopt(fd, level, optname, optval, optlen); } @@ -4551,26 +4598,19 @@ sys32_futex(void *uaddr, int op, int val, struct timespec32 *timeout32) { - long ret; - struct timespec tmp, *timeout; - - ret = -ENOMEM; - timeout = kmalloc(sizeof(*timeout), GFP_USER); - if (!timeout) - goto out; + struct timespec tmp; + mm_segment_t old_fs; + int ret; - ret = -EINVAL; if (get_user (tmp.tv_sec, &timeout32->tv_sec) || - get_user (tmp.tv_nsec, &timeout32->tv_nsec) || - put_user (tmp.tv_sec, &timeout->tv_sec) || - put_user (tmp.tv_nsec, &timeout->tv_nsec)) - goto out_free; + get_user (tmp.tv_nsec, &timeout32->tv_nsec)) + return -EINVAL; - ret = sys_futex(uaddr, op, val, timeout); + old_fs = get_fs(); + set_fs(KERNEL_DS); + ret = sys_futex(uaddr, op, val, &tmp); + set_fs(old_fs); -out_free: - kfree(timeout); -out: return ret; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/s390x/lib/uaccess.S linux.2.5.47-ac4/arch/s390x/lib/uaccess.S --- linux.2.5.47/arch/s390x/lib/uaccess.S 2002-10-31 14:57:34.000000000 +0000 +++ linux.2.5.47-ac4/arch/s390x/lib/uaccess.S 2002-10-31 15:05:57.000000000 +0000 @@ -1,9 +1,9 @@ /* * arch/s390x/lib/uaccess.S - * fixup routines for copy_{from|to}_user functions. + * __copy_{from|to}_user functions. * - * S390 - * Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation + * s390 + * Copyright (C) 2000,2002 IBM Deutschland Entwicklung GmbH, IBM Corporation * Authors(s): Martin Schwidefsky (schwidefsky@de.ibm.com) * * These functions have standard call interface @@ -22,14 +22,23 @@ 1: sacf 0 lgr %r2,%r5 br %r14 -2: lghi %r3,-4096 - ng %r3,__LC_TRANS_EXC_ADDR - sgr %r3,%r4 - jm 1b - j 0b +2: lghi %r1,-4096 + lgr %r3,%r4 + slgr %r3,%r1 # %r3 = %r4 + 4096 + ngr %r3,%r1 # %r3 = (%r4 + 4096) & -4096 + slgr %r3,%r4 # %r3 = #bytes to next user page boundary + clgr %r5,%r3 # copy crosses next page boundary ? + jnh 1b # no, this page fauled + # The page after the current user page might have faulted. + # We cant't find out which page because the program check handler + # might have callled schedule, destroying all lowcore information. + # We retry with the shortened length. +3: mvcle %r2,%r4,0 + jo 3b + j 1b .section __ex_table,"a" - .align 8 .quad 0b,2b + .quad 3b,1b .previous .align 4 @@ -43,14 +52,23 @@ 1: sacf 0 lgr %r2,%r3 br %r14 -2: lghi %r5,-4096 - ng %r5,__LC_TRANS_EXC_ADDR - sgr %r5,%r4 - jm 1b - j 0b +2: lghi %r1,-4096 + lgr %r5,%r4 + slgr %r5,%r1 # %r5 = %r4 + 4096 + ngr %r5,%r1 # %r5 = (%r4 + 4096) & -4096 + slgr %r5,%r4 # %r5 = #bytes to next user page boundary + clgr %r3,%r5 # copy crosses next page boundary ? + jnh 1b # no, the current page fauled + # The page after the current user page might have faulted. + # We cant't find out which page because the program check handler + # might have callled schedule, destroying all lowcore information. + # We retry with the shortened length. +3: mvcle %r4,%r2,0 + jo 3b + j 1b .section __ex_table,"a" - .align 8 - .quad 0b,2b + .quad 0b,2b + .quad 3b,1b .previous .align 4 @@ -65,14 +83,25 @@ 0: mvcle %r4,%r2,0 jo 0b 1: sacf 0 - lgr %r2,%r5 br %r14 -2: lghi %r5,-4096 - ng %r5,__LC_TRANS_EXC_ADDR - sgr %r5,%r4 - jm 1b - j 0b +2: lgr %r2,%r5 + lghi %r1,-4096 + slgr %r5,%r1 # %r5 = %r4 + 4096 + ngr %r5,%r1 # %r5 = (%r4 + 4096) & -4096 + slgr %r5,%r4 # %r5 = #bytes to next user page boundary + clgr %r2,%r5 # copy crosses next page boundary ? + jnh 1b # no, the current page fauled + # The page after the current user page might have faulted. + # We cant't find out which page because the program check handler + # might have callled schedule, destroying all lowcore information. + # We retry with the shortened length. + slgr %r2,%r5 +3: mvcle %r4,%r2,0 + jo 3b + j 1b +4: algr %r2,%r5 + j 1b .section __ex_table,"a" - .align 8 - .quad 0b,2b + .quad 0b,2b + .quad 3b,4b .previous diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/s390x/Makefile linux.2.5.47-ac4/arch/s390x/Makefile --- linux.2.5.47/arch/s390x/Makefile 2002-10-31 14:57:34.000000000 +0000 +++ linux.2.5.47-ac4/arch/s390x/Makefile 2002-10-31 15:05:57.000000000 +0000 @@ -28,18 +28,14 @@ all: image listing -listing: vmlinux - @$(MAKEBOOT) listing +makeboot = $(call descend,arch/$(ARCH)/boot,$(1)) +BOOTIMAGE= arch/$(ARCH)/boot/image -MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot - -image: vmlinux - @$(MAKEBOOT) image - -install: vmlinux - @$(MAKEBOOT) BOOTIMAGE=image install +listing install image: vmlinux + +@$(call makeboot,BOOTIMAGE=$(BOOTIMAGE) $@) archclean: + +@$(call makeboot,clean) archmrproper: diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/sparc64/defconfig linux.2.5.47-ac4/arch/sparc64/defconfig --- linux.2.5.47/arch/sparc64/defconfig 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.47-ac4/arch/sparc64/defconfig 2002-11-05 16:08:04.000000000 +0000 @@ -569,7 +569,6 @@ # CONFIG_BAYCOM_SER_HDX is not set # CONFIG_BAYCOM_PAR is not set # CONFIG_BAYCOM_EPP is not set -# CONFIG_SOUNDMODEM is not set # CONFIG_YAM is not set # diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/um/defconfig linux.2.5.47-ac4/arch/um/defconfig --- linux.2.5.47/arch/um/defconfig 2002-10-31 14:57:35.000000000 +0000 +++ linux.2.5.47-ac4/arch/um/defconfig 2002-10-31 15:05:57.000000000 +0000 @@ -219,13 +219,16 @@ # CONFIG_INTERMEZZO_FS is not set # CONFIG_NFS_FS is not set # CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set # CONFIG_ROOT_NFS is not set # CONFIG_NFSD is not set # CONFIG_NFSD_V3 is not set +# CONFIG_NFSD_V4 is not set # CONFIG_NFSD_TCP is not set # CONFIG_SUNRPC is not set # CONFIG_LOCKD is not set # CONFIG_EXPORTFS is not set +# CONFIG_CIFS is not set # CONFIG_SMB_FS is not set # CONFIG_NCP_FS is not set # CONFIG_NCPFS_PACKET_SIGNING is not set @@ -236,6 +239,7 @@ # CONFIG_NCPFS_SMALLDOS is not set # CONFIG_NCPFS_NLS is not set # CONFIG_NCPFS_EXTRAS is not set +# CONFIG_AFS_FS is not set # CONFIG_ZISOFS_FS is not set # @@ -332,7 +336,9 @@ CONFIG_MTD=y # CONFIG_MTD_DEBUG is not set # CONFIG_MTD_PARTITIONS is not set +# CONFIG_MTD_CONCAT is not set # CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set # # User Modules And Translation Layers @@ -362,6 +368,8 @@ # Mapping drivers for chip access # # CONFIG_MTD_PHYSMAP is not set +# CONFIG_MTD_PCI is not set +# CONFIG_MTD_PCMCIA is not set # # Self-contained MTD device drivers diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/um/drivers/Makefile linux.2.5.47-ac4/arch/um/drivers/Makefile --- linux.2.5.47/arch/um/drivers/Makefile 2002-10-31 14:57:35.000000000 +0000 +++ linux.2.5.47-ac4/arch/um/drivers/Makefile 2002-10-31 15:05:57.000000000 +0000 @@ -15,7 +15,7 @@ # So, what this does is figure out by hand (crudely) what file -lpcap really # is and just use it. -PCAP = $(shell for f in echo {/lib,/usr/lib}/libpcap.{a,so}; do \ +PCAP = $(shell for f in echo {/lib,/usr/lib}/libpcap.a; do \ [ -f $$f ] && echo $$f ; done | head -1) slip-objs := slip_kern.o slip_user.o @@ -47,7 +47,7 @@ obj-$(CONFIG_PORT_CHAN) += port.o obj-$(CONFIG_PTY_CHAN) += pty.o obj-$(CONFIG_TTY_CHAN) += tty.o -obj-$(CONFIG_XTERM_CHAN) += xterm.o +obj-$(CONFIG_XTERM_CHAN) += xterm.o xterm_kern.o obj-$(CONFIG_UML_WATCHDOG) += harddog.o CFLAGS_pcap_user.o = -I/usr/include/pcap diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/um/drivers/mconsole_kern.c linux.2.5.47-ac4/arch/um/drivers/mconsole_kern.c --- linux.2.5.47/arch/um/drivers/mconsole_kern.c 2002-10-31 14:57:35.000000000 +0000 +++ linux.2.5.47-ac4/arch/um/drivers/mconsole_kern.c 2002-10-31 15:05:57.000000000 +0000 @@ -111,6 +111,8 @@ remove - Remove a device from UML sysrq - Performs the SysRq action controlled by the letter cad - invoke the Ctl-Alt-Del handler + stop - pause the UML; it will do nothing until it receives a 'go' + go - continue the UML after a 'stop' " void mconsole_help(struct mc_request *req) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/um/drivers/port_kern.c linux.2.5.47-ac4/arch/um/drivers/port_kern.c --- linux.2.5.47/arch/um/drivers/port_kern.c 2002-10-31 14:57:35.000000000 +0000 +++ linux.2.5.47-ac4/arch/um/drivers/port_kern.c 2002-10-31 15:05:57.000000000 +0000 @@ -20,6 +20,7 @@ struct port_list { struct list_head list; + int has_connection; struct semaphore sem; int port; int fd; @@ -49,28 +50,32 @@ struct connection *conn = data; int fd; - list_del(&conn->list); - fd = os_rcv_fd(conn->socket[0], &conn->helper_pid); if(fd < 0){ + if(fd == -EAGAIN) + return; + printk("os_rcv_fd returned %d\n", -fd); os_close_file(conn->fd); } + + list_del(&conn->list); + conn->fd = fd; list_add(&conn->list, &conn->port->connections); up(&conn->port->sem); } -static void port_interrupt(int irq, void *data, struct pt_regs *regs) +static int port_accept(struct port_list *port) { - struct port_list *port = data; struct connection *conn; - int fd, socket[2], pid; + int fd, socket[2], pid, ret = 0; fd = port_connection(port->fd, socket, &pid); if(fd < 0){ - printk("port_connection returned %d\n", -fd); + if(fd != -EAGAIN) + printk("port_connection returned %d\n", -fd); goto out; } @@ -94,6 +99,7 @@ } list_add(&conn->list, &port->pending); + ret = 1; goto out; out_free: @@ -102,17 +108,45 @@ os_close_file(fd); if(pid != -1) os_kill_process(pid); out: - reactivate_fd(port->fd, ACCEPT_IRQ); + return(ret); } DECLARE_MUTEX(ports_sem); struct list_head ports = LIST_HEAD_INIT(ports); +void port_work_proc(void *unused) +{ + struct port_list *port; + struct list_head *ele; + unsigned long flags; + + local_irq_save(flags); + list_for_each(ele, &ports){ + port = list_entry(ele, struct port_list, list); + if(!port->has_connection) + continue; + reactivate_fd(port->fd, ACCEPT_IRQ); + while(port_accept(port)) ; + port->has_connection = 0; + } + local_irq_restore(flags); +} + +DECLARE_WORK(port_work, port_work_proc, NULL); + +static void port_interrupt(int irq, void *data, struct pt_regs *regs) +{ + struct port_list *port = data; + + port->has_connection = 1; + schedule_work(&port_work); +} + void *port_data(int port_num) { struct list_head *ele; struct port_list *port; - struct port_dev *dev; + struct port_dev *dev = NULL; int fd; down(&ports_sem); @@ -140,13 +174,14 @@ } *port = ((struct port_list) - { list : LIST_HEAD_INIT(port->list), - sem : __SEMAPHORE_INITIALIZER(port->sem, 0), - lock : SPIN_LOCK_UNLOCKED, - port : port_num, - fd : fd, - pending : LIST_HEAD_INIT(port->pending), - connections : LIST_HEAD_INIT(port->connections) }); + { list : LIST_HEAD_INIT(port->list), + has_connection : 0, + sem : __SEMAPHORE_INITIALIZER(port->sem, 0), + lock : SPIN_LOCK_UNLOCKED, + port : port_num, + fd : fd, + pending : LIST_HEAD_INIT(port->pending), + connections : LIST_HEAD_INIT(port->connections) }); list_add(&port->list, &ports); found: @@ -159,8 +194,7 @@ *dev = ((struct port_dev) { port : port, fd : -1, helper_pid : -1 }); - up(&ports_sem); - return(dev); + goto out; out_free: kfree(port); @@ -168,7 +202,7 @@ os_close_file(fd); out: up(&ports_sem); - return(NULL); + return(dev); } void port_remove_dev(void *d) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/um/drivers/ssl.c linux.2.5.47-ac4/arch/um/drivers/ssl.c --- linux.2.5.47/arch/um/drivers/ssl.c 2002-10-31 14:57:35.000000000 +0000 +++ linux.2.5.47-ac4/arch/um/drivers/ssl.c 2002-10-31 15:05:57.000000000 +0000 @@ -44,6 +44,7 @@ xterm_title: "Serial Line #%d", raw: 1, tramp_stack : 0, + in_kernel : 1, }; static struct line_driver driver = { diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/um/drivers/stdio_console.c linux.2.5.47-ac4/arch/um/drivers/stdio_console.c --- linux.2.5.47/arch/um/drivers/stdio_console.c 2002-10-31 14:57:35.000000000 +0000 +++ linux.2.5.47-ac4/arch/um/drivers/stdio_console.c 2002-10-31 15:05:57.000000000 +0000 @@ -75,6 +75,7 @@ xterm_title: "Virtual Console #%d", raw: 1, tramp_stack : 0, + in_kernel : 1, }; static struct line_driver driver = { diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/um/drivers/ubd_kern.c linux.2.5.47-ac4/arch/um/drivers/ubd_kern.c --- linux.2.5.47/arch/um/drivers/ubd_kern.c 2002-10-31 14:57:35.000000000 +0000 +++ linux.2.5.47-ac4/arch/um/drivers/ubd_kern.c 2002-10-31 15:05:57.000000000 +0000 @@ -6,12 +6,15 @@ /* 2001-09-28...2002-04-17 * Partition stuff by James_McMechan@hotmail.com * old style ubd by setting UBD_SHIFT to 0 + * 2002-09-27...2002-10-18 massive tinkering for 2.5 + * partitions have changed in 2.5 */ #define MAJOR_NR UBD_MAJOR #define UBD_SHIFT 4 #include "linux/config.h" +#include "linux/module.h" #include "linux/blk.h" #include "linux/blkdev.h" #include "linux/hdreg.h" @@ -51,15 +54,17 @@ static int ubd_release(struct inode * inode, struct file * file); static int ubd_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg); -static int ubd_revalidate(struct gendisk *disk); #define MAX_DEV (8) +#define MAX_MINOR (MAX_DEV << UBD_SHIFT) + +#define DEVICE_NR(n) (minor(n) >> UBD_SHIFT) static struct block_device_operations ubd_blops = { + .owner = THIS_MODULE, .open = ubd_open, .release = ubd_release, .ioctl = ubd_ioctl, - .revalidate_disk= ubd_revalidate, }; /* Protected by the queue_lock */ @@ -169,8 +174,6 @@ struct proc_dir_entry *dir, *ent; char name[64]; - if(!fake_ide) return; - if(proc_ide_root == NULL) make_proc_ide(); dir = proc_mkdir(dev_name, proc_ide); @@ -415,88 +418,135 @@ return(os_file_size(file, size_out)); } -/* Initialized in an initcall, and unchanged thereafter */ -devfs_handle_t ubd_dir_handle; -devfs_handle_t ubd_fake_dir_handle; +static void ubd_close(struct ubd *dev) +{ + os_close_file(dev->fd); + if(dev->cow.file == NULL) + return; -static int ubd_add(int n) + os_close_file(dev->cow.fd); + vfree(dev->cow.bitmap); + dev->cow.bitmap = NULL; +} + +static int ubd_open_dev(struct ubd *dev) { - devfs_handle_t real, fake; - char name[sizeof("nnnnnn\0")]; - struct ubd *dev = &ubd_dev[n]; - struct gendisk *disk, *fake_disk = NULL; - u64 size; + struct openflags flags; + int err, n, create_cow, *create_ptr; - if (!dev->file) - goto out; + create_cow = 0; + create_ptr = (dev->cow.file != NULL) ? &create_cow : NULL; + dev->fd = open_ubd_file(dev->file, &dev->openflags, &dev->cow.file, + &dev->cow.bitmap_offset, &dev->cow.bitmap_len, + &dev->cow.data_offset, create_ptr); - disk = alloc_disk(1 << UBD_SHIFT); - if (!disk) - return -1; - disk->major = MAJOR_NR; - disk->first_minor = n << UBD_SHIFT; - disk->fops = &ubd_blops; - if (fakehd_set) - sprintf(disk->disk_name, "hd%c", n + 'a'); - else - sprintf(disk->disk_name, "ubd%d", n); - - if (fake_major) { - fake_disk = alloc_disk(1 << UBD_SHIFT); - if (!fake_disk) { - put_disk(disk); - return -1; + if((dev->fd == -ENOENT) && create_cow){ + n = dev - ubd_dev; + dev->fd = create_cow_file(dev->file, dev->cow.file, + dev->openflags, 1 << 9, + &dev->cow.bitmap_offset, + &dev->cow.bitmap_len, + &dev->cow.data_offset); + if(dev->fd >= 0){ + printk(KERN_INFO "Creating \"%s\" as COW file for " + "\"%s\"\n", dev->file, dev->cow.file); } - fake_disk->major = fake_major; - fake_disk->first_minor = n << UBD_SHIFT; - fake_disk->fops = &ubd_blops; - sprintf(fake_disk->disk_name, "ubd%d", n); - fake_gendisk[n] = fake_disk; } - ubd_gendisk[n] = disk; - - if (!dev->is_dir && ubd_file_size(dev, &size) == 0) { - set_capacity(disk, size/512); - if (fake_major) - set_capacity(fake_disk, size/512); - } - - sprintf(name, "%d", n); - real = devfs_register(ubd_dir_handle, name, DEVFS_FL_REMOVABLE, - MAJOR_NR, n << UBD_SHIFT, - S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP |S_IWGRP, - &ubd_blops, NULL); - if(real == NULL) - goto out; - ubd_dev[n].real = real; - - if (fake_major) { - fake = devfs_register(ubd_fake_dir_handle, name, - DEVFS_FL_REMOVABLE, fake_major, - n << UBD_SHIFT, - S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP | - S_IWGRP, &ubd_blops, NULL); - if(fake == NULL) - goto out_unregister; - - ubd_dev[n].fake = fake; - fake_disk->private_data = &ubd_dev[n]; - fake_disk->queue = &ubd_queue; - add_disk(fake_disk); + if(dev->fd < 0) return(dev->fd); + + if(dev->cow.file != NULL){ + err = -ENOMEM; + dev->cow.bitmap = (void *) vmalloc(dev->cow.bitmap_len); + if(dev->cow.bitmap == NULL) goto error; + flush_tlb_kernel_vm(); + + err = read_cow_bitmap(dev->fd, dev->cow.bitmap, + dev->cow.bitmap_offset, + dev->cow.bitmap_len); + if(err) goto error; + + flags = dev->openflags; + flags.w = 0; + err = open_ubd_file(dev->cow.file, &flags, NULL, NULL, NULL, + NULL, NULL); + if(err < 0) goto error; + dev->cow.fd = err; } - - disk->private_data = &ubd_dev[n]; + return(0); + error: + os_close_file(dev->fd); + return(err); +} + +static int ubd_new_disk(int major, u64 size, char *name, int unit, + struct gendisk **disk_out, devfs_handle_t dir_handle, + devfs_handle_t *handle_out) +{ + char devfs_name[sizeof("nnnnnn\0")]; + struct gendisk *disk; + int minor = unit << UBD_SHIFT; + + disk = alloc_disk(1 << UBD_SHIFT); + if(disk == NULL) + return(-ENOMEM); + + disk->major = major; + disk->first_minor = minor; + disk->fops = &ubd_blops; + set_capacity(disk, size / 512); + /* needs to be ubd -> /dev/ubd/discX/disc */ + sprintf(disk->disk_name, "ubd"); + *disk_out = disk; + + /* /dev/ubd/N style names */ + sprintf(devfs_name, "%d", unit); + *handle_out = devfs_register(dir_handle, devfs_name, + DEVFS_FL_REMOVABLE, major, minor, + S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP | + S_IWGRP, &ubd_blops, NULL); + disk->private_data = &ubd_dev[unit]; disk->queue = &ubd_queue; add_disk(disk); - make_ide_entries(disk->disk_name); return(0); +} - out_unregister: - devfs_unregister(real); - ubd_dev[n].real = NULL; - out: - return(-1); +/* Initialized in an initcall, and unchanged thereafter */ +devfs_handle_t ubd_dir_handle; +devfs_handle_t ubd_fake_dir_handle; + +static int ubd_add(int n) +{ + struct ubd *dev = &ubd_dev[n]; + int err; + + if (!dev->file || dev->is_dir) + return(-ENODEV); + + if (ubd_open_dev(dev)) + return(-ENODEV); + + err = ubd_file_size(dev, &dev->size); + if(err) + return(err); + + err = ubd_new_disk(MAJOR_NR, dev->size, "ubd", n, &ubd_gendisk[n], + ubd_dir_handle, &dev->real); + if(err) + return(err); + + if(fake_major) + ubd_new_disk(fake_major, dev->size, "ubd%d", n, + &fake_gendisk[n], ubd_fake_dir_handle, + &dev->fake); + + /* perhaps this should also be under the "if (fake_major)" above */ + /* using the fake_disk->disk_name and also the fakehd_set name */ + if (fake_ide) + make_ide_entries(ubd_gendisk[n]->disk_name); + + ubd_close(dev); + return 0; } static int ubd_config(char *str) @@ -527,34 +577,39 @@ static int ubd_remove(char *str) { struct ubd *dev; - int n, err; + int n, err = -ENODEV; + + if(!isdigit(*str)) + return(err); /* it should be a number 0-7/a-h */ - if(!isdigit(*str)) - return(-1); n = *str - '0'; if(n > MAX_DEV) - return(-1); + return(err); + dev = &ubd_dev[n]; + if(dev->count > 0) + return(-EBUSY); /* you cannot remove a open disk */ err = 0; spin_lock(&ubd_lock); + + if(ubd_gendisk[n] == NULL) + goto out; + del_gendisk(ubd_gendisk[n]); put_disk(ubd_gendisk[n]); ubd_gendisk[n] = NULL; - if (fake_major) { + if(dev->real != NULL) + devfs_unregister(dev->real); + + if(fake_gendisk[n] != NULL){ del_gendisk(fake_gendisk[n]); put_disk(fake_gendisk[n]); fake_gendisk[n] = NULL; + if(dev->fake != NULL) + devfs_unregister(dev->fake); } - if(dev->file == NULL) - goto out; - err = -1; - if(dev->count > 0) - goto out; - if(dev->real != NULL) - devfs_unregister(dev->real); - if(dev->fake != NULL) - devfs_unregister(dev->fake); + *dev = ((struct ubd) DEFAULT_UBD); err = 0; out: @@ -563,9 +618,9 @@ } static struct mc_device ubd_mc = { - name: "ubd", - config: ubd_config, - remove: ubd_remove, + .name = "ubd", + .config = ubd_config, + .remove = ubd_remove, }; static int ubd_mc_init(void) @@ -585,8 +640,10 @@ printk(KERN_ERR "ubd: unable to get major %d\n", MAJOR_NR); return -1; } + blk_init_queue(&ubd_queue, do_ubd_request, &ubd_io_lock); elevator_init(&ubd_queue, &elevator_noop); + if(fake_major != 0){ char name[sizeof("ubd_nnn\0")]; @@ -631,81 +688,23 @@ device_initcall(ubd_driver_init); -static void ubd_close(struct ubd *dev) -{ - os_close_file(dev->fd); - if(dev->cow.file != NULL) { - os_close_file(dev->cow.fd); - vfree(dev->cow.bitmap); - dev->cow.bitmap = NULL; - } -} - -static int ubd_open_dev(struct ubd *dev) -{ - struct openflags flags; - int err, n, create_cow, *create_ptr; - - create_cow = 0; - create_ptr = (dev->cow.file != NULL) ? &create_cow : NULL; - dev->fd = open_ubd_file(dev->file, &dev->openflags, &dev->cow.file, - &dev->cow.bitmap_offset, &dev->cow.bitmap_len, - &dev->cow.data_offset, create_ptr); - - if((dev->fd == -ENOENT) && create_cow){ - n = dev - ubd_dev; - dev->fd = create_cow_file(dev->file, dev->cow.file, - dev->openflags, 1 << 9, - &dev->cow.bitmap_offset, - &dev->cow.bitmap_len, - &dev->cow.data_offset); - if(dev->fd >= 0){ - printk(KERN_INFO "Creating \"%s\" as COW file for " - "\"%s\"\n", dev->file, dev->cow.file); - } - } - - if(dev->fd < 0) return(dev->fd); - - if(dev->cow.file != NULL){ - err = -ENOMEM; - dev->cow.bitmap = (void *) vmalloc(dev->cow.bitmap_len); - if(dev->cow.bitmap == NULL) goto error; - flush_tlb_kernel_vm(); - - err = read_cow_bitmap(dev->fd, dev->cow.bitmap, - dev->cow.bitmap_offset, - dev->cow.bitmap_len); - if(err) goto error; - - flags = dev->openflags; - flags.w = 0; - err = open_ubd_file(dev->cow.file, &flags, NULL, NULL, NULL, - NULL, NULL); - if(err < 0) goto error; - dev->cow.fd = err; - } - return(0); - error: - os_close_file(dev->fd); - return(err); -} - static int ubd_open(struct inode *inode, struct file *filp) { struct gendisk *disk = inode->i_bdev->bd_disk; struct ubd *dev = disk->private_data; - int err; + int err = -EISDIR; + if(dev->is_dir == 1) goto out; + err = 0; if(dev->count == 0){ dev->openflags = dev->boot_openflags; err = ubd_open_dev(dev); if(err){ - printk(KERN_ERR "%s: Can't open \"%s\": " - "errno = %d\n", disk->disk_name, dev->file, -err); + printk(KERN_ERR "%s: Can't open \"%s\": errno = %d\n", + disk->disk_name, dev->file, -err); goto out; } } @@ -722,7 +721,8 @@ { struct gendisk *disk = inode->i_bdev->bd_disk; struct ubd *dev = disk->private_data; - if(dev->count == 0) + + if(--dev->count == 0) ubd_close(dev); return(0); } @@ -772,7 +772,7 @@ __u64 block; int nsect; - if (req->rq_status == RQ_INACTIVE) return(1); + if(req->rq_status == RQ_INACTIVE) return(1); if(dev->is_dir){ strcpy(req->buffer, "HOSTFS:"); @@ -784,7 +784,8 @@ } if((rq_data_dir(req) == WRITE) && !dev->openflags.w){ - printk("Write attempted on readonly ubd device %s\n", disk->disk_name); + printk("Write attempted on readonly ubd device %s\n", + disk->disk_name); spin_lock(&ubd_io_lock); end_request(req, 0); spin_unlock(&ubd_io_lock); @@ -848,7 +849,6 @@ struct hd_geometry *loc = (struct hd_geometry *) arg; struct ubd *dev = inode->i_bdev->bd_disk->private_data; int err; - struct ubd *dev; struct hd_driveid ubd_id = { .cyls = 0, .heads = 128, @@ -868,7 +868,7 @@ case HDIO_SET_UNMASKINTR: if(!capable(CAP_SYS_ADMIN)) return(-EACCES); - if((arg > 1) || inode->i_bdev->bd_contains != inode->i_bdev) + if((arg > 1) || (inode->i_bdev->bd_contains != inode->i_bdev)) return(-EINVAL); return(0); @@ -888,7 +888,7 @@ case HDIO_SET_MULTCOUNT: if(!capable(CAP_SYS_ADMIN)) return(-EACCES); - if (inode->i_bdev->bd_contains != inode->i_bdev) + if(inode->i_bdev->bd_contains != inode->i_bdev) return(-EINVAL); return(0); @@ -913,27 +913,6 @@ return(-EINVAL); } -static int ubd_revalidate(struct gendisk *disk) -{ - __u64 size; - int err; - struct ubd *dev = disk->private_data; - - err = 0; - spin_lock(&ubd_lock); - if(dev->is_dir) - goto out; - - err = ubd_file_size(dev, &size); - if (!err) { - set_capacity(disk, size / 512); - dev->size = size; - } - out: - spin_unlock(&ubd_lock); - return err; -} - /* * Overrides for Emacs so that we follow Linus's tabbing style. * Emacs will notice this stuff at the end of the file and automatically diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/um/drivers/xterm.c linux.2.5.47-ac4/arch/um/drivers/xterm.c --- linux.2.5.47/arch/um/drivers/xterm.c 2002-10-31 14:57:35.000000000 +0000 +++ linux.2.5.47-ac4/arch/um/drivers/xterm.c 2002-10-31 15:05:57.000000000 +0000 @@ -19,6 +19,7 @@ #include "user_util.h" #include "user.h" #include "os.h" +#include "xterm.h" struct xterm_chan { int pid; @@ -28,6 +29,7 @@ int raw; struct termios tt; unsigned long stack; + int direct_rcv; }; void *xterm_init(char *str, int device, struct chan_opts *opts) @@ -40,7 +42,8 @@ device : device, title : opts->xterm_title, raw : opts->raw, - stack : opts->tramp_stack } ); + stack : opts->tramp_stack, + direct_rcv : !opts->in_kernel } ); return(data); } @@ -84,7 +87,7 @@ { struct xterm_chan *data = d; unsigned long stack; - int pid, fd, new; + int pid, fd, new, err; char title[256], file[] = "/tmp/xterm-pipeXXXXXX"; char *argv[] = { terminal_emulator, title_switch, title, exec_switch, "/usr/lib/uml/port-helper", "-uml-socket", @@ -105,21 +108,30 @@ fd = create_unix_socket(file, sizeof(file)); if(fd < 0){ printk("xterm_open : create_unix_socket failed, errno = %d\n", - errno); - return(-errno); + -fd); + return(-fd); } sprintf(title, data->title, data->device); stack = data->stack; pid = run_helper(NULL, NULL, argv, &stack); if(pid < 0){ - printk("xterm_open : run_helper failed\n"); - return(-1); + printk("xterm_open : run_helper failed, errno = %d\n", -pid); + return(pid); } if(data->stack == 0) free_stack(stack, 0); - new = os_rcv_fd(fd, &data->helper_pid); + if(data->direct_rcv) + new = os_rcv_fd(fd, &data->helper_pid); + else { + if((err = os_set_fd_block(fd, 0)) != 0){ + printk("xterm_open : failed to set descriptor " + "non-blocking, errno = %d\n", err); + return(err); + } + new = xterm_fd(fd, &data->helper_pid); + } if(new < 0){ printk("xterm_open : os_rcv_fd failed, errno = %d\n", -new); return(new); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/um/drivers/xterm.h linux.2.5.47-ac4/arch/um/drivers/xterm.h --- linux.2.5.47/arch/um/drivers/xterm.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.47-ac4/arch/um/drivers/xterm.h 2002-10-31 15:05:57.000000000 +0000 @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#ifndef __XTERM_H__ +#define __XTERM_H__ + +extern int xterm_fd(int socket, int *pid_out); + +#endif + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/um/drivers/xterm_kern.c linux.2.5.47-ac4/arch/um/drivers/xterm_kern.c --- linux.2.5.47/arch/um/drivers/xterm_kern.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.47-ac4/arch/um/drivers/xterm_kern.c 2002-10-31 15:05:57.000000000 +0000 @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#include "linux/errno.h" +#include "linux/slab.h" +#include "asm/semaphore.h" +#include "asm/irq.h" +#include "irq_user.h" +#include "kern_util.h" +#include "os.h" +#include "xterm.h" + +struct xterm_wait { + struct semaphore sem; + int fd; + int pid; + int new_fd; +}; + +static void xterm_interrupt(int irq, void *data, struct pt_regs *regs) +{ + struct xterm_wait *xterm = data; + + xterm->new_fd = os_rcv_fd(xterm->fd, &xterm->pid); + if(xterm->new_fd == -EAGAIN) + return; + + up(&xterm->sem); +} + +int xterm_fd(int socket, int *pid_out) +{ + struct xterm_wait *data; + int err, ret; + + data = kmalloc(sizeof(*data), GFP_KERNEL); + if(data == NULL){ + printk(KERN_ERR "xterm_fd - failed to allocate semaphore\n"); + return(-ENOMEM); + } + *data = ((struct xterm_wait) + { sem : __SEMAPHORE_INITIALIZER(data->sem, 0), + fd : socket, + pid : -1, + new_fd : -1 }); + + err = um_request_irq(XTERM_IRQ, socket, IRQ_READ, xterm_interrupt, + SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, + "xterm", data); + if(err){ + printk(KERN_ERR "Failed to get IRQ for xterm, err = %d\n", + err); + return(err); + } + down(&data->sem); + + free_irq(XTERM_IRQ, data); + + ret = data->new_fd; + *pid_out = data->pid; + kfree(data); + + return(ret); +} + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/um/include/chan_user.h linux.2.5.47-ac4/arch/um/include/chan_user.h --- linux.2.5.47/arch/um/include/chan_user.h 2002-10-31 14:57:35.000000000 +0000 +++ linux.2.5.47-ac4/arch/um/include/chan_user.h 2002-10-31 15:05:57.000000000 +0000 @@ -13,6 +13,7 @@ char *xterm_title; int raw; unsigned long tramp_stack; + int in_kernel; }; enum chan_init_pri { INIT_STATIC, INIT_ALL, INIT_ONE }; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/um/include/kern_util.h linux.2.5.47-ac4/arch/um/include/kern_util.h --- linux.2.5.47/arch/um/include/kern_util.h 2002-10-31 14:57:35.000000000 +0000 +++ linux.2.5.47-ac4/arch/um/include/kern_util.h 2002-10-31 15:05:57.000000000 +0000 @@ -6,6 +6,7 @@ #ifndef __KERN_UTIL_H__ #define __KERN_UTIL_H__ +#include "linux/threads.h" #include "sysdep/ptrace.h" extern int ncpus; @@ -14,6 +15,7 @@ extern int kmalloc_ok; extern int timer_irq_inited; extern int jail; +extern struct task_struct *idle_threads[NR_CPUS]; #define ROUND_DOWN(addr) ((void *)(((unsigned long) addr) & PAGE_MASK)) #define ROUND_UP(addr) ROUND_DOWN(((unsigned long) addr) + PAGE_SIZE - 1) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/um/Kconfig linux.2.5.47-ac4/arch/um/Kconfig --- linux.2.5.47/arch/um/Kconfig 2002-11-05 13:54:43.000000000 +0000 +++ linux.2.5.47-ac4/arch/um/Kconfig 2002-11-05 14:51:47.000000000 +0000 @@ -2,7 +2,6 @@ bool default y -# XXX: does UM have a mmu/swap? config MMU bool default y @@ -30,7 +29,6 @@ bool default y - menu "Code maturity level options" config EXPERIMENTAL diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/um/kernel/irq_user.c linux.2.5.47-ac4/arch/um/kernel/irq_user.c --- linux.2.5.47/arch/um/kernel/irq_user.c 2002-10-31 14:57:35.000000000 +0000 +++ linux.2.5.47-ac4/arch/um/kernel/irq_user.c 2002-10-31 15:05:58.000000000 +0000 @@ -209,7 +209,6 @@ out_unlock: irq_unlock(flags); - out_free: kfree(new_fd); out: return(err); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/um/kernel/ksyms.c linux.2.5.47-ac4/arch/um/kernel/ksyms.c --- linux.2.5.47/arch/um/kernel/ksyms.c 2002-10-31 14:57:35.000000000 +0000 +++ linux.2.5.47-ac4/arch/um/kernel/ksyms.c 2002-10-31 15:05:58.000000000 +0000 @@ -1,5 +1,9 @@ +#include "linux/config.h" #include "linux/module.h" #include "linux/string.h" +#include "linux/smp_lock.h" +#include "linux/spinlock.h" +#include #include "asm/current.h" #include "asm/delay.h" #include "asm/processor.h" @@ -36,12 +40,15 @@ EXPORT_SYMBOL(get_signals); EXPORT_SYMBOL(page_to_phys); EXPORT_SYMBOL(phys_to_page); +EXPORT_SYMBOL(high_physmem); EXPORT_SYMBOL(os_open_file); EXPORT_SYMBOL(os_read_file); EXPORT_SYMBOL(os_write_file); EXPORT_SYMBOL(os_seek_file); EXPORT_SYMBOL(os_pipe); +EXPORT_SYMBOL(os_file_type); +EXPORT_SYMBOL(os_close_file); EXPORT_SYMBOL(helper_wait); EXPORT_SYMBOL(os_shutdown_socket); EXPORT_SYMBOL(os_connect_socket); @@ -58,3 +65,23 @@ EXPORT_SYMBOL(sys_read); EXPORT_SYMBOL(sys_wait4); +#ifdef CONFIG_SMP + +/* required for SMP */ + +extern void FASTCALL( __write_lock_failed(rwlock_t *rw)); +EXPORT_SYMBOL_NOVERS(__write_lock_failed); + +extern void FASTCALL( __read_lock_failed(rwlock_t *rw)); +EXPORT_SYMBOL_NOVERS(__read_lock_failed); + +#endif + +#ifdef CONFIG_HIGHMEM +EXPORT_SYMBOL(kmap); +EXPORT_SYMBOL(kunmap); +EXPORT_SYMBOL(kmap_atomic); +EXPORT_SYMBOL(kunmap_atomic); +EXPORT_SYMBOL(kmap_atomic_to_page); +#endif + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/um/kernel/Makefile linux.2.5.47-ac4/arch/um/kernel/Makefile --- linux.2.5.47/arch/um/kernel/Makefile 2002-10-31 14:57:35.000000000 +0000 +++ linux.2.5.47-ac4/arch/um/kernel/Makefile 2002-10-31 15:05:57.000000000 +0000 @@ -1,4 +1,3 @@ - EXTRA_TARGETS := unmap_fin.o obj-y = config.o exec_kern.o exec_user.o exitcode.o frame_kern.o frame.o \ @@ -51,6 +50,9 @@ arch/um/kernel/unmap_fin.o : arch/um/kernel/unmap.o ld -r -o $@ $< -lc -L/usr/lib +# This has to be separate because it needs be compiled with frame pointers +# regardless of how the rest of the kernel is built. + arch/um/kernel/frame.o: arch/um/kernel/frame.c $(CC) $(CFLAGS_$(notdir $@)) -c -o $@ $< diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/um/kernel/process_kern.c linux.2.5.47-ac4/arch/um/kernel/process_kern.c --- linux.2.5.47/arch/um/kernel/process_kern.c 2002-10-31 14:57:35.000000000 +0000 +++ linux.2.5.47-ac4/arch/um/kernel/process_kern.c 2002-10-31 15:05:58.000000000 +0000 @@ -767,8 +767,8 @@ int smp_sigio_handler(void) { - int cpu = current->thread_info->cpu; #ifdef CONFIG_SMP + int cpu = current->thread_info->cpu; IPI_handler(cpu); if(cpu != 0) return(1); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/um/kernel/reboot.c linux.2.5.47-ac4/arch/um/kernel/reboot.c --- linux.2.5.47/arch/um/kernel/reboot.c 2002-10-31 14:57:35.000000000 +0000 +++ linux.2.5.47-ac4/arch/um/kernel/reboot.c 2002-10-31 15:05:58.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ @@ -9,6 +9,20 @@ #include "kern.h" #include "os.h" +#ifdef CONFIG_SMP +static void kill_idlers(int me) +{ + struct task_struct *p; + int i; + + for(i = 0; i < sizeof(idle_threads)/sizeof(idle_threads[0]); i++){ + p = idle_threads[i]; + if((p != NULL) && (p->thread.extern_pid != me)) + os_kill_process(p->thread.extern_pid); + } +} +#endif + static void kill_off_processes(void) { struct task_struct *p; @@ -21,6 +35,9 @@ } if(init_task.thread.extern_pid != me) os_kill_process(init_task.thread.extern_pid); +#ifdef CONFIG_SMP + kill_idlers(me); +#endif } void uml_cleanup(void) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/um/kernel/signal_user.c linux.2.5.47-ac4/arch/um/kernel/signal_user.c --- linux.2.5.47/arch/um/kernel/signal_user.c 2002-10-31 14:57:35.000000000 +0000 +++ linux.2.5.47-ac4/arch/um/kernel/signal_user.c 2002-10-31 15:05:58.000000000 +0000 @@ -84,13 +84,13 @@ #define SIGIO_BIT 0 #define SIGVTALRM_BIT 1 -static int disable_mask(sigset_t *mask) +static int enable_mask(sigset_t *mask) { int sigs; - sigs = sigismember(mask, SIGIO) ? 1 << SIGIO_BIT : 0; - sigs |= sigismember(mask, SIGVTALRM) ? 1 << SIGVTALRM_BIT : 0; - sigs |= sigismember(mask, SIGALRM) ? 1 << SIGVTALRM_BIT : 0; + sigs = sigismember(mask, SIGIO) ? 0 : 1 << SIGIO_BIT; + sigs |= sigismember(mask, SIGVTALRM) ? 0 : 1 << SIGVTALRM_BIT; + sigs |= sigismember(mask, SIGALRM) ? 0 : 1 << SIGVTALRM_BIT; return(sigs); } @@ -100,30 +100,28 @@ if(sigprocmask(SIG_SETMASK, NULL, &mask) < 0) panic("Failed to get signal mask"); - return(disable_mask(&mask)); + return(enable_mask(&mask)); } -int set_signals(int disable) +int set_signals(int enable) { sigset_t mask; int ret; sigemptyset(&mask); - if(!(disable & (1 << SIGIO_BIT))) + if(enable & (1 << SIGIO_BIT)) sigaddset(&mask, SIGIO); - if(!(disable & (1 << SIGVTALRM_BIT))){ + if(enable & (1 << SIGVTALRM_BIT)){ sigaddset(&mask, SIGVTALRM); sigaddset(&mask, SIGALRM); } if(sigprocmask(SIG_UNBLOCK, &mask, &mask) < 0) panic("Failed to enable signals"); - - ret = disable_mask(&mask); - + ret = enable_mask(&mask); sigemptyset(&mask); - if(disable & (1 << SIGIO_BIT)) + if((enable & (1 << SIGIO_BIT)) == 0) sigaddset(&mask, SIGIO); - if(disable & (1 << SIGVTALRM_BIT)){ + if((enable & (1 << SIGVTALRM_BIT)) == 0){ sigaddset(&mask, SIGVTALRM); sigaddset(&mask, SIGALRM); } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/um/kernel/smp.c linux.2.5.47-ac4/arch/um/kernel/smp.c --- linux.2.5.47/arch/um/kernel/smp.c 2002-10-31 14:57:35.000000000 +0000 +++ linux.2.5.47-ac4/arch/um/kernel/smp.c 2002-10-31 15:05:58.000000000 +0000 @@ -47,6 +47,9 @@ /* Small, random number, never changed */ unsigned long cache_decay_ticks = 5; +/* Not changed after boot */ +struct task_struct *idle_threads[NR_CPUS]; + void smp_send_reschedule(int cpu) { write(cpu_data[cpu].ipi_pipe[1], "R", 1); @@ -142,6 +145,7 @@ cpu_tasks[cpu] = ((struct cpu_task) { .pid = new_task->thread.extern_pid, .task = new_task } ); + idle_threads[cpu] = new_task; write(new_task->thread.switch_pipe[1], &c, sizeof(c)); return(new_task); } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/um/kernel/sys_call_table.c linux.2.5.47-ac4/arch/um/kernel/sys_call_table.c --- linux.2.5.47/arch/um/kernel/sys_call_table.c 2002-10-31 14:57:35.000000000 +0000 +++ linux.2.5.47-ac4/arch/um/kernel/sys_call_table.c 2002-10-31 15:05:58.000000000 +0000 @@ -229,6 +229,7 @@ extern syscall_handler_t sys_io_submit; extern syscall_handler_t sys_io_cancel; extern syscall_handler_t sys_exit_group; +extern syscall_handler_t sys_lookup_dcookie; #if CONFIG_NFSD #define NFSSERVCTL sys_nfsserctl @@ -240,7 +241,7 @@ extern syscall_handler_t um_time; extern syscall_handler_t um_stime; -#define LAST_GENERIC_SYSCALL __NR_exit_group +#define LAST_GENERIC_SYSCALL __NR_lookup_dcookie #if LAST_GENERIC_SYSCALL > LAST_ARCH_SYSCALL #define LAST_SYSCALL LAST_GENERIC_SYSCALL @@ -479,6 +480,7 @@ [ __NR_alloc_hugepages ] = sys_ni_syscall, [ __NR_free_hugepages ] = sys_ni_syscall, [ __NR_exit_group ] = sys_exit_group, + [ __NR_lookup_dcookie ] = sys_lookup_dcookie, ARCH_SYSCALLS [ LAST_SYSCALL + 1 ... NR_syscalls ] = diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/um/kernel/sysrq.c linux.2.5.47-ac4/arch/um/kernel/sysrq.c --- linux.2.5.47/arch/um/kernel/sysrq.c 2002-10-31 14:57:35.000000000 +0000 +++ linux.2.5.47-ac4/arch/um/kernel/sysrq.c 2002-10-31 15:05:58.000000000 +0000 @@ -76,6 +76,16 @@ printk("\n"); } +/* + * The architecture-independent dump_stack generator + */ +void dump_stack(void) +{ + unsigned long stack; + + show_trace(&stack); +} + void show_trace_task(struct task_struct *tsk) { unsigned long esp = PT_REGS_SP(&tsk->thread.regs); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/um/kernel/trap_kern.c linux.2.5.47-ac4/arch/um/kernel/trap_kern.c --- linux.2.5.47/arch/um/kernel/trap_kern.c 2002-10-31 14:57:35.000000000 +0000 +++ linux.2.5.47-ac4/arch/um/kernel/trap_kern.c 2002-10-31 15:05:58.000000000 +0000 @@ -211,6 +211,7 @@ xterm_title : "UML kernel debugger", raw : 0, tramp_stack : 0, + in_kernel : 0, }; /* Accessed by the tracing thread, which automatically serializes access */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/um/kernel/um_arch.c linux.2.5.47-ac4/arch/um/kernel/um_arch.c --- linux.2.5.47/arch/um/kernel/um_arch.c 2002-10-31 14:57:35.000000000 +0000 +++ linux.2.5.47-ac4/arch/um/kernel/um_arch.c 2002-10-31 15:05:58.000000000 +0000 @@ -349,7 +349,7 @@ void *unused2) { #ifdef CONFIG_SYSRQ - handle_sysrq('p', ¤t->thread.regs, NULL, NULL); + handle_sysrq('p', ¤t->thread.regs, NULL); #endif machine_halt(); return(0); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/um/Makefile linux.2.5.47-ac4/arch/um/Makefile --- linux.2.5.47/arch/um/Makefile 2002-10-31 14:57:35.000000000 +0000 +++ linux.2.5.47-ac4/arch/um/Makefile 2002-10-31 15:05:57.000000000 +0000 @@ -1,9 +1,6 @@ ARCH_DIR = arch/um OS := $(shell uname -s) -include $(ARCH_DIR)/Makefile-$(SUBARCH) -include $(ARCH_DIR)/Makefile-os-$(OS) - EXTRAVERSION := $(EXTRAVERSION)-1um include/linux/version.h: arch/$(ARCH)/Makefile @@ -59,6 +56,9 @@ GEN_HEADERS = $(ARCH_DIR)/include/task.h +include $(ARCH_DIR)/Makefile-$(SUBARCH) +include $(ARCH_DIR)/Makefile-os-$(OS) + $(ARCH_DIR)/vmlinux.lds.S : touch $@ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/um/Makefile-i386 linux.2.5.47-ac4/arch/um/Makefile-i386 --- linux.2.5.47/arch/um/Makefile-i386 2002-10-31 14:57:35.000000000 +0000 +++ linux.2.5.47-ac4/arch/um/Makefile-i386 2002-10-31 15:05:57.000000000 +0000 @@ -21,11 +21,14 @@ $(SYS_DIR)/thread.h: $(SYS_UTIL_DIR)/mk_thread $< > $@ -$(SYS_UTIL_DIR)/mk_sc $(SYS_UTIL_DIR)/mk_thread: $(SYS_UTIL_DIR) FORCE ; +$(SYS_UTIL_DIR)/mk_sc: FORCE ; + @$(call descend,$(SYS_UTIL_DIR),$@) + +$(SYS_UTIL_DIR)/mk_thread: $(ARCH_SYMLINKS) FORCE ; + @$(call descend,$(SYS_UTIL_DIR),$@) $(SYS_UTIL_DIR): include/asm FORCE @$(call descend,$@,) sysclean : rm -f $(SYS_HEADERS) - @$(call descend,$(SYS_DIR),clean) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/um/os-Linux/file.c linux.2.5.47-ac4/arch/um/os-Linux/file.c --- linux.2.5.47/arch/um/os-Linux/file.c 2002-10-31 14:57:36.000000000 +0000 +++ linux.2.5.47-ac4/arch/um/os-Linux/file.c 2002-10-31 15:05:58.000000000 +0000 @@ -283,10 +283,9 @@ msg.msg_flags = 0; n = recvmsg(fd, &msg, 0); - if(n < 0){ - printk("rcv_fd : recvmsg failed - errno = %d\n", errno); - return(-1); - } + if(n < 0) + return(-errno); + else if(n != sizeof(iov.iov_len)) *helper_pid_out = -1; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/um/sys-i386/Makefile linux.2.5.47-ac4/arch/um/sys-i386/Makefile --- linux.2.5.47/arch/um/sys-i386/Makefile 2002-10-31 14:57:36.000000000 +0000 +++ linux.2.5.47-ac4/arch/um/sys-i386/Makefile 2002-10-31 15:05:58.000000000 +0000 @@ -1,19 +1,21 @@ -obj-y = bugs.o checksum.o extable.o fault.o ksyms.o ldt.o old-checksum.o \ +obj-y = bugs.o checksum.o extable.o fault.o ksyms.o ldt.o \ ptrace.o ptrace_user.o semaphore.o sigcontext.o syscalls.o sysrq.o +obj-$(CONFIG_HIGHMEM) += highmem.o + export-objs = ksyms.o USER_OBJS := bugs.o ptrace_user.o sigcontext.o fault.o USER_OBJS := $(foreach file,$(USER_OBJS),arch/um/sys-i386/$(file)) -SYMLINKS = semaphore.c old-checksum.c checksum.S extable.c +SYMLINKS = semaphore.c checksum.S extable.c highmem.c include $(TOPDIR)/Rules.make $(USER_OBJS) : %.o: %.c $(CC) $(CFLAGS_$@) $(USER_CFLAGS) -c -o $@ $< -arch/um/sys-i386/checksum.S arch/um/sys-i386/old-checksum.c: +arch/um/sys-i386/checksum.S: -rm -f $@ -ln -s $(TOPDIR)/arch/i386/lib/$(notdir $@) $@ @@ -25,6 +27,9 @@ -rm -f $@ -ln -s $(TOPDIR)/arch/i386/mm/$(notdir $@) $@ +arch/um/sys-i386/highmem.c: + -rm -f $@ + -ln -s $(TOPDIR)/arch/i386/mm/$(notdir $@) $@ clean: $(MAKE) -C util clean diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/arch/um/uml.lds.S linux.2.5.47-ac4/arch/um/uml.lds.S --- linux.2.5.47/arch/um/uml.lds.S 2002-10-31 14:57:35.000000000 +0000 +++ linux.2.5.47-ac4/arch/um/uml.lds.S 2002-10-31 15:05:58.000000000 +0000 @@ -65,7 +65,7 @@ .uml.postsetup.init : { *(.uml.postsetup.init) } __uml_postsetup_end = .; __setup_start = .; - .setup.init : { *(.setup.init) } + .init.setup : { *(.init.setup) } __setup_end = .; __per_cpu_start = . ; .data.percpu : { *(.data.percpu) } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/CREDITS linux.2.5.47-ac4/CREDITS --- linux.2.5.47/CREDITS 2002-11-11 16:39:08.000000000 +0000 +++ linux.2.5.47-ac4/CREDITS 2002-11-11 20:30:22.000000000 +0000 @@ -156,6 +156,14 @@ S: Calgary, Alberta S: Canada +N: Miles Bader +E: miles@gnu.org +D: v850 port (uClinux) +S: NEC Corporation +S: 1753 Shimonumabe, Nakahara-ku +S: Kawasaki 211-8666 +S: Japan + N: Ralf Baechle E: ralf@gnu.org P: 1024/AF7B30C1 CF 97 C2 CC 6D AE A7 FE C8 BA 9C FC 88 DE 32 C3 @@ -2239,6 +2247,15 @@ S: Toronto, Ontario S: Canada +N: Zwane Mwaikambo +E: zwane@linuxpower.ca +W: http://function.linuxpower.ca +D: Various driver hacking +D: Lowlevel x86 kernel hacking +D: General debugging +S: (ask for current address) +S: Tanzania + N: Trond Myklebust E: trond.myklebust@fys.uio.no D: current NFS client hacker. @@ -2713,7 +2730,7 @@ N: Thomas Sailer E: t.sailer@alumni.ethz.ch E: HB9JNX@HB9W.CHE.EU (packet radio) -D: hfmodem, Baycom and sound card radio modem driver +D: Baycom driver S: Markusstrasse 18 S: 8006 Zuerich S: Switzerland @@ -3084,8 +3101,14 @@ S: Germany N: Greg Ungerer -E: gerg@moreton.com.au +E: gerg@snapgear.com +D: uClinux kernel hacker +D: Port uClinux to the Motorola ColdFire CPU D: Author of Stallion multiport serial drivers +S: SnapGear Inc. +S: 825 Stanley St +S: Woolloongabba. QLD. 4102 +S: Australia N: Jeffrey A. Uphoff E: juphoff@transmeta.com diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/Documentation/DriverFixers linux.2.5.47-ac4/Documentation/DriverFixers --- linux.2.5.47/Documentation/DriverFixers 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.47-ac4/Documentation/DriverFixers 2002-11-13 22:52:57.000000000 +0000 @@ -0,0 +1,69 @@ +People who fix drivers as a business - ie for money. (No recommendation, +business association or other relationship implied. This for the benefit of +American lawyers is just a list of people who have asked to be listed - nothing +more). + +Companies Who Will Do Small Contract Work +----------------------------------------- + +Company: BitWizard +Contact: Rogier Wolff +E-Mail: R.E.Wolff@BitWizard.nl + +Company: Caederus +Contact: Justin Mitchell +E-Mail: info@caederus.com +URL: http://www.caederus.com/ +Location: Swansea, Wales, UK + +Company: Calsoft Inc +Contact: Anupam Bhide +E-Mail: anupam@calsoftinc.com +URL: http://www.calsoftinc.com +Location: Pune, India + +Company: Hansen Partnership Inc +Location: 1, Partridge Square, Oswego, Illinois 60543, USA +Contact: James Bottomley +E-Mail: James.Bottomley@HansenPartnership.com + +Company: Linking +Contact: Elmer Joandi +E-Mail: elmer@linkingsoft.com + +Company: Penguru Consulting, LLC +Contact: Komron Takmil +E-Mail: komron@penguru.net +Location: Salt Lake City, UT USA + +Company: Weinigel Ingenjörsbyrå AB +Contact: Christer Weinigel +E-Mail: christer@weinigel.se +Location: Stockholm, Sweden + +Company: WildOpenSource +Contact: Martin Hicks +E-Mail: info@wildopensource.com + + +Companies Only Interested In Larger ($10000+) Jobs +-------------------------------------------------- + + + +Companies Only Interested In Very Large ($100000+) Jobs +------------------------------------------------------- + + +To be added to the list: email giving the +following information + +Company: CompanyName [Required] +Contact: ContactName [Required] +E-Mail: An email address [Required] +URL: Web site [Optional] +Location: Area/Country [Optional] +Telephone: Contact phone number [Optional] +Speciality: Any specific speciality [Optional] +Notes: Any other notes (eg certifications, specialities) + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/Documentation/kernel-parameters.txt linux.2.5.47-ac4/Documentation/kernel-parameters.txt --- linux.2.5.47/Documentation/kernel-parameters.txt 2002-10-31 14:57:48.000000000 +0000 +++ linux.2.5.47-ac4/Documentation/kernel-parameters.txt 2002-11-05 16:08:04.000000000 +0000 @@ -584,8 +584,6 @@ sound= [SOUND] - soundmodem= [HW,AX25,SOUND] Use sound card as packet radio modem. - specialix= [HW,SERIAL] Specialix multi-serial port adapter. sscape= [HW,SOUND] diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/Documentation/magic-number.txt linux.2.5.47-ac4/Documentation/magic-number.txt --- linux.2.5.47/Documentation/magic-number.txt 2002-10-31 14:57:48.000000000 +0000 +++ linux.2.5.47-ac4/Documentation/magic-number.txt 2002-11-11 20:32:58.000000000 +0000 @@ -43,57 +43,115 @@ 29 Jul 1998 +Updated the magic table to Linux 2.5.45. Right over the feature freeze, +but it is possible that some new magic numbers will sneak into the +kernel before 2.6.x yet. + + Petr Baudis + + 03 Nov 2002 + Magic Name Number Structure File =========================================================================== -PG_MAGIC 'P' pg_{read,write}_hdr include/linux/pg.h +PG_MAGIC 'P' pg_{read,write}_hdr include/linux/pg.h +CMAGIC 0x0111 user include/linux/a.out.h MKISS_DRIVER_MAGIC 0x04bf mkiss_channel drivers/net/mkiss.h RISCOM8_MAGIC 0x0907 riscom_port drivers/char/riscom8.h +SPECIALIX_MAGIC 0x0907 specialix_port drivers/char/specialix_io8.h +AURORA_MAGIC 0x0A18 Aurora_port drivers/sbus/char/aurora.h +HDLC_MAGIC 0x239e n_hdlc drivers/char/n_hdlc.c APM_BIOS_MAGIC 0x4101 apm_user arch/i386/kernel/apm.c CYCLADES_MAGIC 0x4359 cyclades_port include/linux/cyclades.h FASYNC_MAGIC 0x4601 fasync_struct include/linux/fs.h -PTY_MAGIC 0x5001 (none at the moment) - drivers/char/pty.c -PPP_MAGIC 0x5002 ppp include/linux/if_ppp.h +ISICOM_MAGIC 0x4d54 isi_port include/linux/isicom.h +PTY_MAGIC 0x5001 (none at the moment) + drivers/char/pty.c +PPP_MAGIC 0x5002 ppp include/linux/if_pppvar.h SERIAL_MAGIC 0x5301 async_struct include/linux/serial.h SSTATE_MAGIC 0x5302 serial_state include/linux/serial.h SLIP_MAGIC 0x5302 slip drivers/net/slip.h STRIP_MAGIC 0x5303 strip drivers/net/strip.c X25_ASY_MAGIC 0x5303 x25_asy drivers/net/x25_asy.h -SIXPACK_MAGIC 0x5304 sixpack drivers/net/hamradio/6pack.h +SIXPACK_MAGIC 0x5304 sixpack drivers/net/hamradio/6pack.h AX25_MAGIC 0x5316 ax_disp drivers/net/mkiss.h ESP_MAGIC 0x53ee esp_struct drivers/char/esp.h TTY_MAGIC 0x5401 tty_struct include/linux/tty.h +MGSL_MAGIC 0x5401 mgsl_info drivers/char/synclink.c TTY_DRIVER_MAGIC 0x5402 tty_driver include/linux/tty_driver.h +MGSLPC_MAGIC 0x5402 mgslpc_info drivers/char/pcmcia/synclink_cs.c TTY_LDISC_MAGIC 0x5403 tty_ldisc include/linux/tty_ldisc.h -SPECIALIX_MAGIC 0x0907 specialix_port drivers/char/specialix_io8.h -CG_MAGIC 0x090255 ufs_cylinder_group include/linux/ufs_fs.h -RPORT_MAGIC 0x525001 r_port drivers/char/rocket_int.h -GDTIOCTL_MAGIC 0x06030f07 gdth_iowr_str drivers/scsi/gdth_ioctl.h +USB_SERIAL_MAGIC 0x6702 usb_serial drivers/usb/serial/usb-serial.h +USB_BLUETOOTH_MAGIC 0x6d02 usb_bluetooth drivers/usb/class/bluetty.c +RFCOMM_TTY_MAGIC 0x6d02 (note at the moment) + net/bluetooth/rfcomm/tty.c +USB_SERIAL_PORT_MAGIC 0x7301 usb_serial_port drivers/usb/serial/usb-serial.h +CG_MAGIC 0x00090255 ufs_cylinder_group include/linux/ufs_fs.h +A2232_MAGIC 0x000a2232 gs_port drivers/char/ser_a2232.h +SOLARIS_SOCKET_MAGIC 0x000ADDED sol_socket_struct arch/sparc64/solaris/socksys.h +RPORT_MAGIC 0x00525001 r_port drivers/char/rocket_int.h +LSEMAGIC 0x05091998 lse drivers/fc4/fc.c +GDTIOCTL_MAGIC 0x06030f07 gdth_iowr_str drivers/scsi/gdth_ioctl.h +RIO_MAGIC 0x12345678 gs_port drivers/char/rio/rio_linux.c +SX_MAGIC 0x12345678 gs_port drivers/char/sx.h NBD_REQUEST_MAGIC 0x12560953 nbd_request include/linux/nbd.h -SLAB_RED_MAGIC2 0x170fc2a5 (any) mm/slab.c +RED_MAGIC2 0x170fc2a5 (any) mm/slab.c BAYCOM_MAGIC 0x19730510 baycom_state drivers/net/baycom_epp.c ISDN_X25IFACE_MAGIC 0x1e75a2b9 isdn_x25iface_proto_data drivers/isdn/isdn_x25iface.h ECP_MAGIC 0x21504345 cdkecpsig include/linux/cdk.h +LSOMAGIC 0x27091997 lso drivers/fc4/fc.c LSMAGIC 0x2a3b4d2a ls drivers/fc4/fc.c -LSOMAGIC 0x2a3c4e3c lso drivers/fc4/fc.c WANPIPE_MAGIC 0x414C4453 sdla_{dump,exec} include/linux/wanpipe.h -CODA_CNODE_MAGIC 0x47114711 coda_inode_info include/linux/coda_fs_i.h +CS_CARD_MAGIC 0x43525553 cs_card sound/oss/cs46xx.c +LABELCL_MAGIC 0x4857434c labelcl_info_s include/asm/ia64/sn/labelcl.h ISDN_ASYNC_MAGIC 0x49344C01 modem_info include/linux/isdn.h -ISDN_NET_MAGIC 0x49344C02 isdn_net_local_s include/linux/isdn.h +CTC_ASYNC_MAGIC 0x49344C01 ctc_tty_info drivers/s390/net/ctctty.c +ISDN_NET_MAGIC 0x49344C02 isdn_net_local_s drivers/isdn/i4l/isdn_net_lib.h +SAVEKMSG_MAGIC2 0x4B4D5347 savekmsg arch/*/amiga/config.c STLI_BOARDMAGIC 0x4bc6c825 stlibrd include/linux/istallion.h +CS_STATE_MAGIC 0x4c4f4749 cs_state sound/oss/cs46xx.c SLAB_C_MAGIC 0x4f17a36d kmem_cache_s mm/slab.c +COW_MAGIC 0x4f4f4f4d cow_header_v1 arch/um/drivers/ubd_user.c +I810_CARD_MAGIC 0x5072696E i810_card sound/oss/i810_audio.c +TRIDENT_CARD_MAGIC 0x5072696E trident_card sound/oss/trident.c ROUTER_MAGIC 0x524d4157 wan_device include/linux/wanrouter.h -SLAB_RED_MAGIC1 0x5a2cf071 (any) mm/slab.c +SCC_MAGIC 0x52696368 gs_port drivers/char/scc.h +SAVEKMSG_MAGIC1 0x53415645 savekmsg arch/*/amiga/config.c +GDA_MAGIC 0x58464552 gda include/asm-mips64/sn/gda.h +RED_MAGIC1 0x5a2cf071 (any) mm/slab.c STL_PORTMAGIC 0x5a7182c9 stlport include/linux/stallion.h HDLCDRV_MAGIC 0x5ac6e778 hdlcdrv_state include/linux/hdlcdrv.h -EPCA_MAGIC 0x5c6df104 channel include/linux/epca.h +EPCA_MAGIC 0x5c6df104 channel include/linux/epca.h PCXX_MAGIC 0x5c6df104 channel drivers/char/pcxx.h +KV_MAGIC 0x5f4b565f kernel_vars_s include/asm-mips64/sn/klkernvars.h +I810_STATE_MAGIC 0x63657373 i810_state sound/oss/i810_audio.c +TRIDENT_STATE_MAGIC 0x63657373 trient_state sound/oss/trident.c +M3_CARD_MAGIC 0x646e6f50 m3_card sound/oss/maestro3.c +SLOT_MAGIC 0x67267321 slot drivers/hotplug/cpqphp.h +SLOT_MAGIC 0x67267322 slot drivers/hotplug/acpiphp.h LO_MAGIC 0x68797548 nbd_device include/linux/nbd.h +M3_STATE_MAGIC 0x734d724d m3_state sound/oss/maestro3.c STL_PANELMAGIC 0x7ef621a1 stlpanel include/linux/stallion.h +VMALLOC_MAGIC 0x87654320 snd_alloc_track sound/core/memory.c +KMALLOC_MAGIC 0x87654321 snd_alloc_track sound/core/memory.c +PWC_MAGIC 0x89DC10AB pwc_device drivers/usb/media/pwc.h NBD_REPLY_MAGIC 0x96744668 nbd_reply include/linux/nbd.h STL_BOARDMAGIC 0xa2267f52 stlbrd include/linux/stallion.h -SLAB_MAGIC_ALLOC 0xa5c32f2b kmem_slab_s mm/slab.c -SLAB_MAGIC_DESTROYED 0xb2f23c5a kmem_slab_s mm/slab.c +SCI_MAGIC 0xbabeface gs_port drivers/char/sh-sci.h +CODA_MAGIC 0xC0DAC0DA coda_file_info include/linux/coda_fs_i.h STLI_PORTMAGIC 0xe671c7a1 stliport include/linux/istallion.h +YAM_MAGIC 0xF10A7654 yam_port drivers/net/hamradio/yam.c CCB_MAGIC 0xf2691ad2 ccb drivers/scsi/ncr53c8xx.c +HTB_CMAGIC 0xFEFAFEF1 htb_class net/sched/sch_htb.c +NMI_MAGIC 0x48414d4d455201 nmi_s include/asm-mips64/sn/nmi.h + +Note that there are also defined special per-driver magic numbers in sound +memory managment. See include/sound/sndmagic.h for complete list of them. Many +OSS sound drivers have their magic numbers constructed from the soundcard PCI +ID - these are not listed here as well. + +IrDA subsystem also uses large number of own magic numbers, see +include/net/irda/irda.h for a complete list of them. + +HFS is another larger user of magic numbers - you can find them in +fs/hfs/hfs.h. diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/Documentation/networking/00-INDEX linux.2.5.47-ac4/Documentation/networking/00-INDEX --- linux.2.5.47/Documentation/networking/00-INDEX 2002-10-31 14:57:47.000000000 +0000 +++ linux.2.5.47-ac4/Documentation/networking/00-INDEX 2002-11-05 16:08:04.000000000 +0000 @@ -104,8 +104,6 @@ - the driver for SMC's 9000 series of Ethernet cards smctr.txt - SMC TokenCard TokenRing Linux driver info. -soundmodem.txt - - Linux driver for sound cards as AX.25 modems tcp.txt - short blurb on how TCP output takes place. tlan.txt diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/Documentation/networking/soundmodem.txt linux.2.5.47-ac4/Documentation/networking/soundmodem.txt --- linux.2.5.47/Documentation/networking/soundmodem.txt 2002-10-31 14:57:47.000000000 +0000 +++ linux.2.5.47-ac4/Documentation/networking/soundmodem.txt 1970-01-01 01:00:00.000000000 +0100 @@ -1,90 +0,0 @@ - LINUX DRIVER FOR SOUNDCARDS AS AX.25 MODEMS - - Thomas M. Sailer, HB9JNX/AE4WA, - -This driver allows either SoundBlaster (sbc) or Windows Sound System (wss) -compatible soundcards to be used as either 1200 baud AFSK or 9600 baud FSK -AX.25 packet radio modems. Only half duplex operation is supported; an -attempt to include full duplex support failed because the hardware did -not support it (it appeared that the card only provides one DMA channel, -although the codec chip would support two channels). The driver needs -some processing power! A 66 MHz 486 DX2 is a minimum requirement. Otherwise -interactive performance of the computer may become sluggish. This driver -does *not* support telephone modem standards, it is intended for radio -use only. - - -The Interface of the driver - -The driver provides kernel network drivers named sm[0-3]. sethdlc -from the ax25 utilities may be used to set driver states etc. Users -of userland AX.25 stacks may use the net2kiss utility (also available -in the ax25 utilities package) to convert packets of a network interface -to a KISS stream on a pseudo tty. There's also a patch available from -me for WAMPES which allows attaching a kernel network interface directly. - - -Configuring the driver - -Some sound cards need to be initialized before they operate in either -SoundBlaster or WSS compatibility mode. The driver does _NOT_ do this; -you may use the standard linux sound driver to initialize the soundcard; -compile it as a module, and do - insmod sound - rmmod sound -The soundcard should then be initialized correctly. If this does not help, -you'll have to write your own initialization utility. - -Every time the driver is inserted into the kernel, it has to know which -modems it should access at which ports. This can be done with the setbaycom -utility. If you are only using one modem, you can also configure the -driver from the insmod command line (or by means of an option line in -/etc/modules.conf). - -Examples: - insmod soundmodem mode="sbc:afsk1200" iobase=0x220 irq=5 dma=1 - sethdlc -i sm0 -p mode "sbc:afsk1200" io 0x220 irq 5 dma 1 - -Both lines configure the first port to drive a soundblaster card -in 1200 baud AFSK mode. - -The channel access parameters can be set with sethdlc -a or kissparms. -Note that both utilities interpret the values slightly different. - - -Input and output levels - -It is important that the input and output levels are adjusted properly. -There are two utilities, available in the ax25 utilities distribution, -to facilitate this: smmixer and smdiag. smdiag allows you to display -the input signal in an oscilloscope like display or an eye diagram. -smmixer allows you to adjust input/output levels. See the respective -man pages. - - -Transmitter keying - -Since soundcards do not have a DC coupled output; PTT keying options include -the following: -* VOX circuitry -* Serial port pin -* Parallel port pin -* MPU401 MIDI output via a retriggerable monoflop. -Circuit schematics may be found at -http://www.ife.ee.ethz.ch/~sailer/pcf/ptt_circ/ptt.html. - - -Compatibility with the rest of the Linux kernel - -The sound driver and the soundcard modem driver compete for the same -hardware resources. Of course only one driver can access a given -interface at a time. Worse yet, the sound driver grabs the soundcard -at startup time. Therefore the soundcard modem driver subsequently won't -be able to access the soundcard. You might therefore find it necessary to -unload the sound driver before using the soundcard modem driver. - - - -vy 73s de -Tom Sailer, sailer@ife.ee.ethz.ch -hb9jnx @ hb9w.ampr.org diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/Documentation/README.nsp_cs.eng linux.2.5.47-ac4/Documentation/README.nsp_cs.eng --- linux.2.5.47/Documentation/README.nsp_cs.eng 2002-10-31 14:57:48.000000000 +0000 +++ linux.2.5.47-ac4/Documentation/README.nsp_cs.eng 1970-01-01 01:00:00.000000000 +0100 @@ -1,130 +0,0 @@ - - WorkBiT NinjaSCSI-3/32Bi driver for Linux - -1. Comment - This is Workbit corp.'s(http://www.workbit.co.jp/) NinjaSCSI-3 -(http://www.workbit.co.jp/ts/z_nj3r.html) and NinjaSCSI-32Bi -(http://www.workbit.co.jp/ts/z_njsc32bi.html) PCMCIA card driver module -for Linux. - -2. My Linux environment -Linux kernel: 2.4.7 / 2.2.19 -pcmcia-cs: 3.1.27 -gcc: gcc-2.95.4 -PC card: I-O data PCSC-F (NinjaSCSI-3) - I-O data CBSC-II in 16 bit mode (NinjaSCSI-32Bi) -SCSI device: I-O data CDPS-PX24 (CD-ROM drive) - Media Intelligent MMO-640GT (Optical disk drive) - -3. Install -[1] Check your PC card is true "NinjaSCSI-3" card. - If you installed pcmcia-cs already, pcmcia reports your card as UNKNOWN - card, and write ["WBT", "NinjaSCSI-3", "R1.0"] or some other string to - your console or log file. - You can also use "cardctl" program (this program is in pcmcia-cs source - code) to get more info. - -# cat /var/log/messgaes -... -Jan 2 03:45:06 lindberg cardmgr[78]: unsupported card in socket 1 -Jan 2 03:45:06 lindberg cardmgr[78]: product info: "WBT", "NinjaSCSI-3", "R1.0" -... -# cardctl ident -Socket 0: - no product info available -Socket 1: - product info: "IO DATA", "CBSC16 ", "1" - - -[2] Get Linux kernel source, and extract it to /usr/src. - Because NinjaSCSI driver requiers some SCSI header files in Linux kernel - source. - I recomend rebuilding your kernel. This eliminate some versioning problem. -$ cd /usr/src -$ tar -zxvf linux-x.x.x.tar.gz -$ cd linux -$ make config -... - -[3] If you use this driver with Kernel 2.2, Unpack pcmcia-cs in some directory - and make & install. This driver requies pcmcia-cs header file. -$ cd /usr/src -$ tar zxvf cs-pcmcia-cs-3.x.x.tar.gz -... - -[4] Extract this driver's archive somewhere, and edit Makefile, then do make. -$ tar -zxvf nsp_cs-x.x.tar.gz -$ cd nsp_cs-x.x -$ emacs Makefile -... -$ make - -[5] Copy nsp_cs.o to suitable plase, like /lib/modules//pcmcia/ . - -[6] Add these lines to /etc/pcmcia/config . - If you yse pcmcia-cs-3.1.8 or later, we can use "nsp_cs.conf" file. - So, you don't need to edit file. Just copy to /etc/pcmcia/ . - -------------------------------------- -device "nsp_cs" - class "scsi" module "nsp_cs" - -card "WorkBit NinjaSCSI-3" - version "WBT", "NinjaSCSI-3", "R1.0" - bind "nsp_cs" - -card "WorkBit NinjaSCSI-32Bi (16bit)" - version "WORKBIT", "UltraNinja-16", "1" - bind "nsp_cs" - -# OEM -card "WorkBit NinjaSCSI-32Bi (16bit) / IO-DATA" - version "IO DATA", "CBSC16 ", "1" - bind "nsp_cs" - -# OEM -card "WorkBit NinjaSCSI-32Bi (16bit) / KME-1" - version "KME ", "SCSI-CARD-001", "1" - bind "nsp_cs" -card "WorkBit NinjaSCSI-32Bi (16bit) / KME-2" - version "KME ", "SCSI-CARD-002", "1" - bind "nsp_cs" -card "WorkBit NinjaSCSI-32Bi (16bit) / KME-3" - version "KME ", "SCSI-CARD-003", "1" - bind "nsp_cs" -card "WorkBit NinjaSCSI-32Bi (16bit) / KME-4" - version "KME ", "SCSI-CARD-004", "1" - bind "nsp_cs" -------------------------------------- - -[7] Start (or restart) pcmcia-cs. -# /etc/rc.d/rc.pcmcia start (BSD style) -or -# /etc/init.d/pcmcia start (SYSV style) - - -4. History -See README.nin_cs . - -5. Caution - If you eject card when doing some operation for your SCSI device or suspend -your computer, you encount some *BAD* error like disk crash. - It works good when I using this driver right way. But I'm not guarantee -your data. Please backup your data when you use this driver. - -6. Known Bugs - In 2.4 kernel, you can't use 640MB Optical disk. This error comes from -high level SCSI driver. - -7. Testing - Please send me some reports(bug reports etc..) of this software. -When you send report, please tell me these or more. - card name - kernel version - your SCSI device name(hard drive, CD-ROM, etc...) - -8. Copyright - See GPL. - - -2001/08/08 yokota@netlab.is.tsukuba.ac.jp diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/Documentation/sysctl/kernel.txt linux.2.5.47-ac4/Documentation/sysctl/kernel.txt --- linux.2.5.47/Documentation/sysctl/kernel.txt 2002-10-31 14:57:47.000000000 +0000 +++ linux.2.5.47-ac4/Documentation/sysctl/kernel.txt 2002-10-31 15:06:24.000000000 +0000 @@ -17,29 +17,42 @@ Currently, these files might (depending on your configuration) show up in /proc/sys/kernel: - acct +- core_pattern +- core_uses_pid - ctrl-alt-del - dentry-state - domainname - hostname - htab-reclaim [ PPC only ] +- hotplug - java-appletviewer [ binfmt_java, obsolete ] - java-interpreter [ binfmt_java, obsolete ] - l2cr [ PPC only ] - modprobe ==> Documentation/kmod.txt +- msgmax +- msgmnb +- msgmni - osrelease - ostype - overflowgid - overflowuid - panic +- pid_max - powersave-nap [ PPC only ] - printk - real-root-dev ==> Documentation/initrd.txt - reboot-cmd [ SPARC only ] -- rtsig-nr - rtsig-max +- rtsig-nr +- sem - sg-big-buff [ generic SCSI device (sg) ] +- shmall - shmmax [ sysv ipc ] +- shmmni +- stop-a [ SPARC only ] +- sysrq ==> Documentation/sysrq.txt - tainted +- threads-max - version - zero-paged [ PPC only ] @@ -62,6 +75,41 @@ ============================================================== +core_pattern: + +core_pattern is used to specify a core dumpfile pattern name. +. max length 64 characters; default value is "core" +. core_pattern is used as a pattern template for the output filename; + certain string patterns (beginning with '%') are substituted with + their actual values. +. backward compatibility with core_uses_pid: + If core_pattern does not include "%p" (default does not) + and core_uses_pid is set, then .PID will be appended to + the filename. +. corename format specifiers: + % '%' is dropped + %% output one '%' + %p pid + %u uid + %g gid + %s signal number + %t UNIX time of dump + %h hostname + %e executable filename + % both are dropped + +============================================================== + +core_uses_pid: + +The default coredump filename is "core". By setting +core_uses_pid to 1, the coredump filename becomes core.PID. +If core_pattern does not include "%p" (default does not) +and core_uses_pid is set, then .PID will be appended to +the filename. + +============================================================== + ctrl-alt-del: When the value in this file is 0, ctrl-alt-del is trapped and @@ -105,6 +153,13 @@ ============================================================== +hotplug: + +Path for the hotplug policy agent. +Default value is "/sbin/hotplug". + +============================================================== + l2cr: (PPC only) This flag controls the L2 cache of G3 processor boards. If @@ -149,6 +204,14 @@ ============================================================== +pid_max: + +PID allocation wrap value. When the kenrel's next PID value +reaches this value, it wraps back to a minimum PID value. +PIDs of value pid_max or larger are not allocated. + +============================================================== + powersave-nap: (PPC only) If set, Linux-PPC will use the 'nap' mode of powersaving, @@ -195,7 +258,7 @@ of POSIX realtime (queued) signals that can be outstanding in the system. -Rtsig-nr shows the number of RT signals currently queued. +rtsig-nr shows the number of RT signals currently queued. ============================================================== @@ -231,6 +294,7 @@ Set by modutils >= 2.4.9. 2 - A module was force loaded by insmod -f. Set by modutils >= 2.4.9. + 4 - Unsafe SMP processors: SMP with CPUs not designed for SMP. ============================================================== diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/acorn/net/ether3.c linux.2.5.47-ac4/drivers/acorn/net/ether3.c --- linux.2.5.47/drivers/acorn/net/ether3.c 2002-10-31 14:57:10.000000000 +0000 +++ linux.2.5.47-ac4/drivers/acorn/net/ether3.c 2002-11-13 15:21:49.000000000 +0000 @@ -855,6 +855,7 @@ } priv = (struct dev_priv *) dev->priv; + init_timer(&priv->timer); /* Reset card... */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/acpi/ac.c linux.2.5.47-ac4/drivers/acpi/ac.c --- linux.2.5.47/drivers/acpi/ac.c 2002-10-31 14:57:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/acpi/ac.c 2002-11-13 01:18:36.000000000 +0000 @@ -159,12 +159,6 @@ ACPI_FUNCTION_TRACE("acpi_ac_add_fs"); - if (!acpi_ac_dir) { - acpi_ac_dir = proc_mkdir(ACPI_AC_CLASS, acpi_root_dir); - if (!acpi_ac_dir) - return_VALUE(-ENODEV); - } - if (!acpi_device_dir(device)) { acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), acpi_ac_dir); @@ -194,9 +188,6 @@ { ACPI_FUNCTION_TRACE("acpi_ac_remove_fs"); - if (!acpi_ac_dir) - return_VALUE(-ENODEV); - if (acpi_device_dir(device)) remove_proc_entry(acpi_device_bid(device), acpi_ac_dir); @@ -330,6 +321,10 @@ ACPI_FUNCTION_TRACE("acpi_ac_init"); + acpi_ac_dir = proc_mkdir(ACPI_AC_CLASS, acpi_root_dir); + if (!acpi_ac_dir) + return_VALUE(-ENODEV); + result = acpi_bus_register_driver(&acpi_ac_driver); if (result < 0) { remove_proc_entry(ACPI_AC_CLASS, acpi_root_dir); @@ -343,13 +338,11 @@ void __exit acpi_ac_exit (void) { - int result = 0; - ACPI_FUNCTION_TRACE("acpi_ac_exit"); - result = acpi_bus_unregister_driver(&acpi_ac_driver); - if (!result) - remove_proc_entry(ACPI_AC_CLASS, acpi_root_dir); + acpi_bus_unregister_driver(&acpi_ac_driver); + + remove_proc_entry(ACPI_AC_CLASS, acpi_root_dir); return_VOID; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/acpi/battery.c linux.2.5.47-ac4/drivers/acpi/battery.c --- linux.2.5.47/drivers/acpi/battery.c 2002-10-31 14:57:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/acpi/battery.c 2002-11-13 01:18:36.000000000 +0000 @@ -615,12 +615,6 @@ ACPI_FUNCTION_TRACE("acpi_battery_add_fs"); - if (!acpi_battery_dir) { - acpi_battery_dir = proc_mkdir(ACPI_BATTERY_CLASS, acpi_root_dir); - if (!acpi_battery_dir) - return_VALUE(-ENODEV); - } - if (!acpi_device_dir(device)) { acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), acpi_battery_dir); @@ -675,9 +669,6 @@ { ACPI_FUNCTION_TRACE("acpi_battery_remove_fs"); - if (!acpi_battery_dir) - return_VALUE(-ENODEV); - if (acpi_device_dir(device)) remove_proc_entry(acpi_device_bid(device), acpi_battery_dir); @@ -812,6 +803,10 @@ ACPI_FUNCTION_TRACE("acpi_battery_init"); + acpi_battery_dir = proc_mkdir(ACPI_BATTERY_CLASS, acpi_root_dir); + if (!acpi_battery_dir) + return_VALUE(-ENODEV); + result = acpi_bus_register_driver(&acpi_battery_driver); if (result < 0) { remove_proc_entry(ACPI_BATTERY_CLASS, acpi_root_dir); @@ -825,13 +820,11 @@ static void __exit acpi_battery_exit (void) { - int result = 0; - ACPI_FUNCTION_TRACE("acpi_battery_exit"); - result = acpi_bus_unregister_driver(&acpi_battery_driver); - if (!result) - remove_proc_entry(ACPI_BATTERY_CLASS, acpi_root_dir); + acpi_bus_unregister_driver(&acpi_battery_driver); + + remove_proc_entry(ACPI_BATTERY_CLASS, acpi_root_dir); return_VOID; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/acpi/bus.c linux.2.5.47-ac4/drivers/acpi/bus.c --- linux.2.5.47/drivers/acpi/bus.c 2002-11-05 13:54:43.000000000 +0000 +++ linux.2.5.47-ac4/drivers/acpi/bus.c 2002-11-13 01:18:36.000000000 +0000 @@ -27,6 +27,7 @@ #include #include #include +#include #include #ifdef CONFIG_X86 #include diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/acpi/button.c linux.2.5.47-ac4/drivers/acpi/button.c --- linux.2.5.47/drivers/acpi/button.c 2002-10-31 14:57:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/acpi/button.c 2002-11-13 01:18:36.000000000 +0000 @@ -141,12 +141,6 @@ button = acpi_driver_data(device); - if (!acpi_button_dir) { - acpi_button_dir = proc_mkdir(ACPI_BUTTON_CLASS, acpi_root_dir); - if (!acpi_button_dir) - return_VALUE(-ENODEV); - } - switch (button->type) { case ACPI_BUTTON_TYPE_POWER: case ACPI_BUTTON_TYPE_POWERF: @@ -190,9 +184,6 @@ { ACPI_FUNCTION_TRACE("acpi_button_remove_fs"); - if (!acpi_button_dir) - return_VALUE(-ENODEV); - if (acpi_device_dir(device)) remove_proc_entry(acpi_device_bid(device), acpi_button_dir); @@ -446,9 +437,15 @@ ACPI_FUNCTION_TRACE("acpi_button_init"); + acpi_button_dir = proc_mkdir(ACPI_BUTTON_CLASS, acpi_root_dir); + if (!acpi_button_dir) + return_VALUE(-ENODEV); + result = acpi_bus_register_driver(&acpi_button_driver); - if (result < 0) + if (result < 0) { + remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir); return_VALUE(-ENODEV); + } return_VALUE(0); } @@ -461,6 +458,8 @@ acpi_bus_unregister_driver(&acpi_button_driver); + remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir); + return_VOID; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/acpi/dispatcher/dsmethod.c linux.2.5.47-ac4/drivers/acpi/dispatcher/dsmethod.c --- linux.2.5.47/drivers/acpi/dispatcher/dsmethod.c 2002-10-31 14:57:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/acpi/dispatcher/dsmethod.c 2002-11-13 01:18:36.000000000 +0000 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: dsmethod - Parser/Interpreter interface - control method parsing - * $Revision: 88 $ + * $Revision: 89 $ * *****************************************************************************/ @@ -216,7 +216,7 @@ * interpreter if we block */ status = acpi_ex_system_wait_semaphore (obj_desc->method.semaphore, - WAIT_FOREVER); + ACPI_WAIT_FOREVER); } /* diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/acpi/dispatcher/dswstate.c linux.2.5.47-ac4/drivers/acpi/dispatcher/dswstate.c --- linux.2.5.47/drivers/acpi/dispatcher/dswstate.c 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.47-ac4/drivers/acpi/dispatcher/dswstate.c 2002-11-13 01:18:36.000000000 +0000 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: dswstate - Dispatcher parse tree walk management routines - * $Revision: 69 $ + * $Revision: 70 $ * *****************************************************************************/ @@ -345,7 +345,7 @@ * * RETURN: Status * - * DESCRIPTION: + * DESCRIPTION: Push an object onto the Walk_state result stack. * ******************************************************************************/ @@ -381,7 +381,7 @@ * * RETURN: Status * - * DESCRIPTION: + * DESCRIPTION: Pop an object off of the Walk_state result stack. * ******************************************************************************/ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/acpi/ec.c linux.2.5.47-ac4/drivers/acpi/ec.c --- linux.2.5.47/drivers/acpi/ec.c 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.47-ac4/drivers/acpi/ec.c 2002-11-13 01:18:36.000000000 +0000 @@ -477,12 +477,6 @@ ACPI_FUNCTION_TRACE("acpi_ec_add_fs"); - if (!acpi_ec_dir) { - acpi_ec_dir = proc_mkdir(ACPI_EC_CLASS, acpi_root_dir); - if (!acpi_ec_dir) - return_VALUE(-ENODEV); - } - if (!acpi_device_dir(device)) { acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), acpi_ec_dir); @@ -508,12 +502,6 @@ { ACPI_FUNCTION_TRACE("acpi_ec_remove_fs"); - if (!acpi_ec_dir) - return_VALUE(-ENODEV); - - if (acpi_device_dir(device)) - remove_proc_entry(acpi_device_bid(device), acpi_ec_dir); - return_VALUE(0); } @@ -789,13 +777,24 @@ if (acpi_disabled) return_VALUE(0); + acpi_ec_dir = proc_mkdir(ACPI_EC_CLASS, acpi_root_dir); + if (!acpi_ec_dir) + return_VALUE(-ENODEV); + /* Now register the driver for the EC */ result = acpi_bus_register_driver(&acpi_ec_driver); + if (result < 0) { + remove_proc_entry(ACPI_EC_CLASS, acpi_root_dir); + return_VALUE(-ENODEV); + } + return_VALUE(result); } subsys_initcall(acpi_ec_init); +/* EC driver currently not unloadable */ +#if 0 static void __exit acpi_ec_ecdt_exit (void) { @@ -813,17 +812,15 @@ static void __exit acpi_ec_exit (void) { - int result = 0; - ACPI_FUNCTION_TRACE("acpi_ec_exit"); - result = acpi_bus_unregister_driver(&acpi_ec_driver); - if (!result) - remove_proc_entry(ACPI_EC_CLASS, acpi_root_dir); + acpi_bus_unregister_driver(&acpi_ec_driver); + remove_proc_entry(ACPI_EC_CLASS, acpi_root_dir); acpi_ec_ecdt_exit(); return_VOID; } +#endif /* 0 */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/acpi/events/evevent.c linux.2.5.47-ac4/drivers/acpi/events/evevent.c --- linux.2.5.47/drivers/acpi/events/evevent.c 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.47-ac4/drivers/acpi/events/evevent.c 2002-11-13 01:18:37.000000000 +0000 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: evevent - Fixed and General Purpose Even handling and dispatch - * $Revision: 95 $ + * $Revision: 96 $ * *****************************************************************************/ @@ -503,9 +503,9 @@ ACPI_REPORT_INFO (("GPE Block%d defined as GPE%d to GPE%d\n", (s32) gpe_block, - acpi_gbl_gpe_block_info[gpe_block].block_base_number, - acpi_gbl_gpe_block_info[gpe_block].block_base_number + - ((acpi_gbl_gpe_block_info[gpe_block].register_count * 8) -1))); + (u32) acpi_gbl_gpe_block_info[gpe_block].block_base_number, + (u32) (acpi_gbl_gpe_block_info[gpe_block].block_base_number + + ((acpi_gbl_gpe_block_info[gpe_block].register_count * 8) -1)))); } } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/acpi/events/evmisc.c linux.2.5.47-ac4/drivers/acpi/events/evmisc.c --- linux.2.5.47/drivers/acpi/events/evmisc.c 2002-10-31 14:57:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/acpi/events/evmisc.c 2002-11-13 01:18:37.000000000 +0000 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: evmisc - Miscellaneous event manager support functions - * $Revision: 57 $ + * $Revision: 58 $ * *****************************************************************************/ @@ -433,7 +433,7 @@ acpi_status acpi_ev_acquire_global_lock ( - u32 timeout) + u16 timeout) { acpi_status status = AE_OK; u8 acquired = FALSE; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/acpi/events/evxface.c linux.2.5.47-ac4/drivers/acpi/events/evxface.c --- linux.2.5.47/drivers/acpi/events/evxface.c 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.47-ac4/drivers/acpi/events/evxface.c 2002-11-13 01:18:37.000000000 +0000 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: evxface - External interfaces for ACPI events - * $Revision: 131 $ + * $Revision: 132 $ * *****************************************************************************/ @@ -612,7 +612,7 @@ acpi_status acpi_acquire_global_lock ( - u32 timeout, + u16 timeout, u32 *handle) { acpi_status status; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/acpi/executer/exdump.c linux.2.5.47-ac4/drivers/acpi/executer/exdump.c --- linux.2.5.47/drivers/acpi/executer/exdump.c 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.47-ac4/drivers/acpi/executer/exdump.c 2002-11-13 01:18:37.000000000 +0000 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: exdump - Interpreter debug output routines - * $Revision: 162 $ + * $Revision: 163 $ * *****************************************************************************/ @@ -590,6 +590,7 @@ acpi_ex_out_integer ("Length", obj_desc->buffer.length); acpi_ex_out_pointer ("Pointer", obj_desc->buffer.pointer); + ACPI_DUMP_BUFFER (obj_desc->buffer.pointer, obj_desc->buffer.length); break; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/acpi/executer/exfield.c linux.2.5.47-ac4/drivers/acpi/executer/exfield.c --- linux.2.5.47/drivers/acpi/executer/exfield.c 2002-10-31 14:57:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/acpi/executer/exfield.c 2002-11-13 01:18:37.000000000 +0000 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: exfield - ACPI AML (p-code) execution - field manipulation - * $Revision: 112 $ + * $Revision: 113 $ * *****************************************************************************/ @@ -27,6 +27,8 @@ #include "acpi.h" #include "acdispat.h" #include "acinterp.h" +#include "acevents.h" +#include "amlcode.h" #define _COMPONENT ACPI_EXECUTER @@ -82,6 +84,45 @@ } } } + else if ((ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_LOCAL_REGION_FIELD) && + (obj_desc->field.region_obj->region.space_id == ACPI_ADR_SPACE_SMBUS)) { + /* + * This is an SMBus read. We must create a buffer to hold the data + * and directly access the region handler. + */ + buffer_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER); + if (!buffer_desc) { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* Create the actual read buffer */ + + buffer_desc->buffer.pointer = ACPI_MEM_CALLOCATE (ACPI_SMBUS_BUFFER_SIZE); + if (!buffer_desc->buffer.pointer) { + acpi_ut_remove_reference (buffer_desc); + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* Complete the buffer object initialization */ + + buffer_desc->common.flags = AOPOBJ_DATA_VALID; + buffer_desc->buffer.length = ACPI_SMBUS_BUFFER_SIZE; + buffer = buffer_desc->buffer.pointer; + + /* Lock entire transaction if requested */ + + locked = acpi_ex_acquire_global_lock (obj_desc->common_field.field_flags); + + /* + * Perform the read. + * Note: Smbus protocol value is passed in upper 16-bits of Function + */ + status = acpi_ex_access_region (obj_desc, 0, + (acpi_integer *) buffer_desc->buffer.pointer, + ACPI_READ | (obj_desc->field.attribute << 16)); + acpi_ex_release_global_lock (locked); + goto exit; + } /* * Allocate a buffer for the contents of the field. @@ -138,17 +179,17 @@ obj_desc->common_field.start_field_bit_offset, obj_desc->common_field.base_byte_offset)); + /* Lock entire transaction if requested */ + locked = acpi_ex_acquire_global_lock (obj_desc->common_field.field_flags); /* Read from the field */ status = acpi_ex_extract_from_field (obj_desc, buffer, length); - - /* - * Release global lock if we acquired it earlier - */ acpi_ex_release_global_lock (locked); + +exit: if (ACPI_FAILURE (status)) { acpi_ut_remove_reference (buffer_desc); } @@ -176,7 +217,8 @@ acpi_status acpi_ex_write_data_to_field ( acpi_operand_object *source_desc, - acpi_operand_object *obj_desc) + acpi_operand_object *obj_desc, + acpi_operand_object **result_desc) { acpi_status status; u32 length; @@ -184,6 +226,7 @@ void *buffer; void *new_buffer; u8 locked; + acpi_operand_object *buffer_desc; ACPI_FUNCTION_TRACE_PTR ("Ex_write_data_to_field", obj_desc); @@ -207,6 +250,64 @@ } } } + else if ((ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_LOCAL_REGION_FIELD) && + (obj_desc->field.region_obj->region.space_id == ACPI_ADR_SPACE_SMBUS)) { + /* + * This is an SMBus write. We will bypass the entire field mechanism + * and handoff the buffer directly to the handler. + * + * Source must be a buffer of sufficient size (ACPI_SMBUS_BUFFER_SIZE). + */ + if (ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_TYPE_BUFFER) { + ACPI_REPORT_ERROR (("SMBus write requires Buffer, found type %s\n", + acpi_ut_get_object_type_name (source_desc))); + return_ACPI_STATUS (AE_AML_OPERAND_TYPE); + } + + if (source_desc->buffer.length < ACPI_SMBUS_BUFFER_SIZE) { + ACPI_REPORT_ERROR (("SMBus write requires Buffer of length %X, found length %X\n", + ACPI_SMBUS_BUFFER_SIZE, source_desc->buffer.length)); + return_ACPI_STATUS (AE_AML_BUFFER_LIMIT); + } + + buffer_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER); + if (!buffer_desc) { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* Create the actual read buffer */ + + buffer_desc->buffer.pointer = ACPI_MEM_CALLOCATE (ACPI_SMBUS_BUFFER_SIZE); + if (!buffer_desc->buffer.pointer) { + acpi_ut_remove_reference (buffer_desc); + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* Complete the buffer object initialization */ + + buffer_desc->common.flags = AOPOBJ_DATA_VALID; + buffer_desc->buffer.length = ACPI_SMBUS_BUFFER_SIZE; + buffer = buffer_desc->buffer.pointer; + + + ACPI_MEMCPY (buffer, source_desc->buffer.pointer, ACPI_SMBUS_BUFFER_SIZE); + + /* Lock entire transaction if requested */ + + locked = acpi_ex_acquire_global_lock (obj_desc->common_field.field_flags); + + /* + * Perform the write (returns status and perhaps data in the same buffer) + * Note: SMBus protocol type is passed in upper 16-bits of Function. + */ + status = acpi_ex_access_region (obj_desc, 0, + (acpi_integer *) buffer, + ACPI_WRITE | (obj_desc->field.attribute << 16)); + acpi_ex_release_global_lock (locked); + + *result_desc = buffer_desc; + return_ACPI_STATUS (status); + } /* * Get a pointer to the data to be written @@ -267,16 +368,13 @@ obj_desc->common_field.start_field_bit_offset, obj_desc->common_field.base_byte_offset)); + /* Lock entire transaction if requested */ + locked = acpi_ex_acquire_global_lock (obj_desc->common_field.field_flags); - /* - * Write to the field - */ - status = acpi_ex_insert_into_field (obj_desc, buffer, length); + /* Write to the field */ - /* - * Release global lock if we acquired it earlier - */ + status = acpi_ex_insert_into_field (obj_desc, buffer, length); acpi_ex_release_global_lock (locked); /* Free temporary buffer if we used one */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/acpi/executer/exfldio.c linux.2.5.47-ac4/drivers/acpi/executer/exfldio.c --- linux.2.5.47/drivers/acpi/executer/exfldio.c 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.47-ac4/drivers/acpi/executer/exfldio.c 2002-11-13 01:18:37.000000000 +0000 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: exfldio - Aml Field I/O - * $Revision: 89 $ + * $Revision: 90 $ * *****************************************************************************/ @@ -64,6 +64,8 @@ rgn_desc = obj_desc->common_field.region_obj; + /* We must have a valid region */ + if (ACPI_GET_OBJECT_TYPE (rgn_desc) != ACPI_TYPE_REGION) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Needed Region, found type %X (%s)\n", ACPI_GET_OBJECT_TYPE (rgn_desc), @@ -83,6 +85,12 @@ } } + if (rgn_desc->region.space_id == ACPI_ADR_SPACE_SMBUS) { + /* SMBus has a non-linear address space */ + + return_ACPI_STATUS (AE_OK); + } + /* * Validate the request. The entire request from the byte offset for a * length of one field datum (access width) must fit within the region. @@ -127,8 +135,10 @@ * PARAMETERS: *Obj_desc - Field to be read * Field_datum_byte_offset - Byte offset of this datum within the * parent field - * *Value - Where to store value (must be 32 bits) - * Read_write - Read or Write flag + * *Value - Where to store value (must at least + * the size of acpi_integer) + * Function - Read or Write flag plus other region- + * dependent flags * * RETURN: Status * @@ -141,7 +151,7 @@ acpi_operand_object *obj_desc, u32 field_datum_byte_offset, acpi_integer *value, - u32 read_write) + u32 function) { acpi_status status; acpi_operand_object *rgn_desc; @@ -152,6 +162,15 @@ /* + * Ensure that the region operands are fully evaluated and verify + * the validity of the request + */ + status = acpi_ex_setup_region (obj_desc, field_datum_byte_offset); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + + /* * The physical address of this field datum is: * * 1) The base of the region, plus @@ -163,7 +182,7 @@ + obj_desc->common_field.base_byte_offset + field_datum_byte_offset; - if (read_write == ACPI_READ) { + if ((function & ACPI_IO_MASK) == ACPI_READ) { ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "[READ]")); } else { @@ -181,7 +200,7 @@ /* Invoke the appropriate Address_space/Op_region handler */ - status = acpi_ev_address_space_dispatch (rgn_desc, read_write, + status = acpi_ev_address_space_dispatch (rgn_desc, function, address, ACPI_MUL_8 (obj_desc->common_field.access_byte_width), value); if (ACPI_FAILURE (status)) { @@ -191,7 +210,6 @@ acpi_ut_get_region_name (rgn_desc->region.space_id), rgn_desc->region.space_id)); } - else if (status == AE_NOT_EXIST) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Region %s(%X) has no handler\n", @@ -371,11 +389,6 @@ * For simple Region_fields, we just directly access the owning * Operation Region. */ - status = acpi_ex_setup_region (obj_desc, field_datum_byte_offset); - if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); - } - status = acpi_ex_access_region (obj_desc, field_datum_byte_offset, value, read_write); break; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/acpi/executer/exoparg1.c linux.2.5.47-ac4/drivers/acpi/executer/exoparg1.c --- linux.2.5.47/drivers/acpi/executer/exoparg1.c 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.47-ac4/drivers/acpi/executer/exoparg1.c 2002-11-13 01:18:37.000000000 +0000 @@ -2,7 +2,7 @@ /****************************************************************************** * * Module Name: exoparg1 - AML execution - opcodes with 1 argument - * $Revision: 144 $ + * $Revision: 145 $ * *****************************************************************************/ @@ -389,14 +389,16 @@ return_ACPI_STATUS (status); } - /* - * Normally, we would remove a reference on the Operand[0] parameter; - * But since it is being used as the internal return object - * (meaning we would normally increment it), the two cancel out, - * and we simply don't do anything. - */ - walk_state->result_obj = operand[0]; - walk_state->operands[0] = NULL; /* Prevent deletion */ + if (!walk_state->result_obj) { + /* + * Normally, we would remove a reference on the Operand[0] parameter; + * But since it is being used as the internal return object + * (meaning we would normally increment it), the two cancel out, + * and we simply don't do anything. + */ + walk_state->result_obj = operand[0]; + walk_state->operands[0] = NULL; /* Prevent deletion */ + } return_ACPI_STATUS (status); @@ -461,7 +463,9 @@ cleanup: - walk_state->result_obj = return_desc; + if (!walk_state->result_obj) { + walk_state->result_obj = return_desc; + } /* Delete return object on error */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/acpi/executer/exoparg2.c linux.2.5.47-ac4/drivers/acpi/executer/exoparg2.c --- linux.2.5.47/drivers/acpi/executer/exoparg2.c 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.47-ac4/drivers/acpi/executer/exoparg2.c 2002-11-13 01:18:37.000000000 +0000 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: exoparg2 - AML execution - opcodes with 2 arguments - * $Revision: 113 $ + * $Revision: 114 $ * *****************************************************************************/ @@ -490,7 +490,9 @@ goto cleanup; } - walk_state->result_obj = return_desc; + if (!walk_state->result_obj) { + walk_state->result_obj = return_desc; + } } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/acpi/executer/exoparg3.c linux.2.5.47-ac4/drivers/acpi/executer/exoparg3.c --- linux.2.5.47/drivers/acpi/executer/exoparg3.c 2002-10-31 14:57:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/acpi/executer/exoparg3.c 2002-11-13 01:18:37.000000000 +0000 @@ -2,7 +2,7 @@ /****************************************************************************** * * Module Name: exoparg3 - AML execution - opcodes with 3 arguments - * $Revision: 14 $ + * $Revision: 15 $ * *****************************************************************************/ @@ -226,7 +226,9 @@ /* Set the return object and exit */ - walk_state->result_obj = return_desc; + if (!walk_state->result_obj) { + walk_state->result_obj = return_desc; + } return_ACPI_STATUS (status); } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/acpi/executer/exprep.c linux.2.5.47-ac4/drivers/acpi/executer/exprep.c --- linux.2.5.47/drivers/acpi/executer/exprep.c 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.47-ac4/drivers/acpi/executer/exprep.c 2002-11-13 01:18:37.000000000 +0000 @@ -2,7 +2,7 @@ /****************************************************************************** * * Module Name: exprep - ACPI AML (p-code) execution - field prep utilities - * $Revision: 120 $ + * $Revision: 121 $ * *****************************************************************************/ @@ -107,28 +107,24 @@ break; case AML_FIELD_ACCESS_BYTE: + case AML_FIELD_ACCESS_BUFFER: /* ACPI 2.0 (SMBus Buffer) */ byte_alignment = 1; - bit_length = 8; + bit_length = 8; break; case AML_FIELD_ACCESS_WORD: byte_alignment = 2; - bit_length = 16; + bit_length = 16; break; case AML_FIELD_ACCESS_DWORD: byte_alignment = 4; - bit_length = 32; + bit_length = 32; break; - case AML_FIELD_ACCESS_QWORD: /* ACPI 2.0 */ + case AML_FIELD_ACCESS_QWORD: /* ACPI 2.0 */ byte_alignment = 8; - bit_length = 64; - break; - - case AML_FIELD_ACCESS_BUFFER: /* ACPI 2.0 */ - byte_alignment = 8; - bit_length = 8; + bit_length = 64; break; default: diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/acpi/executer/exstore.c linux.2.5.47-ac4/drivers/acpi/executer/exstore.c --- linux.2.5.47/drivers/acpi/executer/exstore.c 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.47-ac4/drivers/acpi/executer/exstore.c 2002-11-13 01:18:37.000000000 +0000 @@ -2,7 +2,7 @@ /****************************************************************************** * * Module Name: exstore - AML Interpreter object store support - * $Revision: 173 $ + * $Revision: 174 $ * *****************************************************************************/ @@ -81,7 +81,7 @@ if (ACPI_GET_DESCRIPTOR_TYPE (dest_desc) == ACPI_DESC_TYPE_NAMED) { /* * Dest is a namespace node, - * Storing an object into a Name "container" + * Storing an object into a Named node. */ status = acpi_ex_store_object_to_node (source_desc, (acpi_namespace_node *) dest_desc, walk_state); @@ -435,7 +435,7 @@ /* * For fields, copy the source data to the target field. */ - status = acpi_ex_write_data_to_field (source_desc, target_desc); + status = acpi_ex_write_data_to_field (source_desc, target_desc, &walk_state->result_obj); break; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/acpi/executer/exsystem.c linux.2.5.47-ac4/drivers/acpi/executer/exsystem.c --- linux.2.5.47/drivers/acpi/executer/exsystem.c 2002-10-31 14:57:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/acpi/executer/exsystem.c 2002-11-13 01:18:37.000000000 +0000 @@ -2,7 +2,7 @@ /****************************************************************************** * * Module Name: exsystem - Interface to OS services - * $Revision: 73 $ + * $Revision: 74 $ * *****************************************************************************/ @@ -51,7 +51,7 @@ acpi_status acpi_ex_system_wait_semaphore ( acpi_handle semaphore, - u32 timeout) + u16 timeout) { acpi_status status; acpi_status status2; @@ -201,12 +201,12 @@ * Support for the _GL_ Mutex object -- go get the global lock */ if (obj_desc->mutex.semaphore == acpi_gbl_global_lock_semaphore) { - status = acpi_ev_acquire_global_lock ((u32) time_desc->integer.value); + status = acpi_ev_acquire_global_lock ((u16) time_desc->integer.value); return_ACPI_STATUS (status); } status = acpi_ex_system_wait_semaphore (obj_desc->mutex.semaphore, - (u32) time_desc->integer.value); + (u16) time_desc->integer.value); return_ACPI_STATUS (status); } @@ -312,7 +312,7 @@ if (obj_desc) { status = acpi_ex_system_wait_semaphore (obj_desc->event.semaphore, - (u32) time_desc->integer.value); + (u16) time_desc->integer.value); } return_ACPI_STATUS (status); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/acpi/executer/exutils.c linux.2.5.47-ac4/drivers/acpi/executer/exutils.c --- linux.2.5.47/drivers/acpi/executer/exutils.c 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.47-ac4/drivers/acpi/executer/exutils.c 2002-11-13 01:18:37.000000000 +0000 @@ -2,7 +2,7 @@ /****************************************************************************** * * Module Name: exutils - interpreter/scanner utilities - * $Revision: 105 $ + * $Revision: 106 $ * *****************************************************************************/ @@ -189,7 +189,7 @@ if (field_flags & AML_FIELD_LOCK_RULE_MASK) { /* We should attempt to get the lock, wait forever */ - status = acpi_ev_acquire_global_lock (ACPI_UINT32_MAX); + status = acpi_ev_acquire_global_lock (ACPI_WAIT_FOREVER); if (ACPI_SUCCESS (status)) { locked = TRUE; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/acpi/fan.c linux.2.5.47-ac4/drivers/acpi/fan.c --- linux.2.5.47/drivers/acpi/fan.c 2002-10-31 14:57:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/acpi/fan.c 2002-11-13 01:18:37.000000000 +0000 @@ -151,12 +151,6 @@ if (!device) return_VALUE(-EINVAL); - if (!acpi_fan_dir) { - acpi_fan_dir = proc_mkdir(ACPI_FAN_CLASS, acpi_root_dir); - if (!acpi_fan_dir) - return_VALUE(-ENODEV); - } - if (!acpi_device_dir(device)) { acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), acpi_fan_dir); @@ -187,9 +181,6 @@ { ACPI_FUNCTION_TRACE("acpi_fan_remove_fs"); - if (!acpi_fan_dir) - return_VALUE(-ENODEV); - if (acpi_device_dir(device)) remove_proc_entry(acpi_device_bid(device), acpi_fan_dir); @@ -276,9 +267,15 @@ ACPI_FUNCTION_TRACE("acpi_fan_init"); + acpi_fan_dir = proc_mkdir(ACPI_FAN_CLASS, acpi_root_dir); + if (!acpi_fan_dir) + return_VALUE(-ENODEV); + result = acpi_bus_register_driver(&acpi_fan_driver); - if (result < 0) + if (result < 0) { + remove_proc_entry(ACPI_FAN_CLASS, acpi_root_dir); return_VALUE(-ENODEV); + } return_VALUE(0); } @@ -287,13 +284,11 @@ void __exit acpi_fan_exit (void) { - int result = 0; - ACPI_FUNCTION_TRACE("acpi_fan_exit"); - result = acpi_bus_unregister_driver(&acpi_fan_driver); - if (!result) - remove_proc_entry(ACPI_FAN_CLASS, acpi_root_dir); + acpi_bus_unregister_driver(&acpi_fan_driver); + + remove_proc_entry(ACPI_FAN_CLASS, acpi_root_dir); return_VOID; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/acpi/include/acconfig.h linux.2.5.47-ac4/drivers/acpi/include/acconfig.h --- linux.2.5.47/drivers/acpi/include/acconfig.h 2002-11-05 13:54:43.000000000 +0000 +++ linux.2.5.47-ac4/drivers/acpi/include/acconfig.h 2002-11-13 01:18:37.000000000 +0000 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: acconfig.h - Global configuration constants - * $Revision: 115 $ + * $Revision: 117 $ * *****************************************************************************/ @@ -54,7 +54,7 @@ /* Version string */ -#define ACPI_CA_VERSION 0x20021101 +#define ACPI_CA_VERSION 0x20021111 /* Version of ACPI supported */ @@ -166,6 +166,10 @@ #define ACPI_RSDP_CHECKSUM_LENGTH 20 #define ACPI_RSDP_XCHECKSUM_LENGTH 36 +/* SMBus bidirectional buffer size */ + +#define ACPI_SMBUS_BUFFER_SIZE 34 + /****************************************************************************** * diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/acpi/include/acdisasm.h linux.2.5.47-ac4/drivers/acpi/include/acdisasm.h --- linux.2.5.47/drivers/acpi/include/acdisasm.h 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.47-ac4/drivers/acpi/include/acdisasm.h 2002-11-13 01:18:37.000000000 +0000 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: acdisasm.h - AML disassembler - * $Revision: 4 $ + * $Revision: 5 $ * *****************************************************************************/ @@ -239,6 +239,9 @@ acpi_dm_bit_list ( u16 mask); +void +acpi_dm_decode_attribute ( + u8 attribute); /* * dmresrcl diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/acpi/include/acevents.h linux.2.5.47-ac4/drivers/acpi/include/acevents.h --- linux.2.5.47/drivers/acpi/include/acevents.h 2002-10-31 14:57:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/acpi/include/acevents.h 2002-11-13 01:18:37.000000000 +0000 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: acevents.h - Event subcomponent prototypes and defines - * $Revision: 79 $ + * $Revision: 80 $ * *****************************************************************************/ @@ -63,7 +63,7 @@ acpi_status acpi_ev_acquire_global_lock( - u32 timeout); + u16 timeout); acpi_status acpi_ev_release_global_lock( diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/acpi/include/acinterp.h linux.2.5.47-ac4/drivers/acpi/include/acinterp.h --- linux.2.5.47/drivers/acpi/include/acinterp.h 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.47-ac4/drivers/acpi/include/acinterp.h 2002-11-13 01:18:37.000000000 +0000 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: acinterp.h - Interpreter subcomponent prototypes and defines - * $Revision: 140 $ + * $Revision: 142 $ * *****************************************************************************/ @@ -164,7 +164,8 @@ acpi_status acpi_ex_write_data_to_field ( acpi_operand_object *source_desc, - acpi_operand_object *obj_desc); + acpi_operand_object *obj_desc, + acpi_operand_object **result_desc); /* * exmisc - ACPI AML (p-code) execution - specific opcodes @@ -377,7 +378,7 @@ acpi_status acpi_ex_system_wait_semaphore ( acpi_handle semaphore, - u32 timeout); + u16 timeout); /* diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/acpi/include/aclocal.h linux.2.5.47-ac4/drivers/acpi/include/aclocal.h --- linux.2.5.47/drivers/acpi/include/aclocal.h 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.47-ac4/drivers/acpi/include/aclocal.h 2002-11-13 01:18:37.000000000 +0000 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: aclocal.h - Internal data types used across the ACPI subsystem - * $Revision: 178 $ + * $Revision: 179 $ * *****************************************************************************/ @@ -27,7 +27,7 @@ #define __ACLOCAL_H__ -#define WAIT_FOREVER ((u32) -1) +#define ACPI_WAIT_FOREVER 0xFFFF /* u16, as per ACPI spec */ typedef void* acpi_mutex; typedef u32 ACPI_MUTEX_HANDLE; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/acpi/include/acpiosxf.h linux.2.5.47-ac4/drivers/acpi/include/acpiosxf.h --- linux.2.5.47/drivers/acpi/include/acpiosxf.h 2002-10-31 14:57:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/acpi/include/acpiosxf.h 2002-11-13 01:18:37.000000000 +0000 @@ -117,7 +117,7 @@ acpi_os_wait_semaphore ( acpi_handle handle, u32 units, - u32 timeout); + u16 timeout); acpi_status acpi_os_signal_semaphore ( diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/acpi/include/acpixf.h linux.2.5.47-ac4/drivers/acpi/include/acpixf.h --- linux.2.5.47/drivers/acpi/include/acpixf.h 2002-10-31 14:57:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/acpi/include/acpixf.h 2002-11-13 01:18:37.000000000 +0000 @@ -281,7 +281,7 @@ acpi_status acpi_acquire_global_lock ( - u32 timeout, + u16 timeout, u32 *handle); acpi_status diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/acpi/include/actypes.h linux.2.5.47-ac4/drivers/acpi/include/actypes.h --- linux.2.5.47/drivers/acpi/include/actypes.h 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.47-ac4/drivers/acpi/include/actypes.h 2002-11-13 01:18:37.000000000 +0000 @@ -1,7 +1,7 @@ /****************************************************************************** * * Name: actypes.h - Common data types for the entire ACPI subsystem - * $Revision: 240 $ + * $Revision: 241 $ * *****************************************************************************/ @@ -499,6 +499,7 @@ */ #define ACPI_READ 0 #define ACPI_WRITE 1 +#define ACPI_IO_MASK 1 /* diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/acpi/include/amlcode.h linux.2.5.47-ac4/drivers/acpi/include/amlcode.h --- linux.2.5.47/drivers/acpi/include/amlcode.h 2002-10-31 14:57:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/acpi/include/amlcode.h 2002-11-13 01:18:37.000000000 +0000 @@ -3,7 +3,7 @@ * Name: amlcode.h - Definitions for AML, as included in "definition blocks" * Declarations and definitions contained herein are derived * directly from the ACPI specification. - * $Revision: 70 $ + * $Revision: 71 $ * *****************************************************************************/ @@ -462,7 +462,8 @@ AML_FIELD_ATTRIB_SMB_BYTE = 0x06, AML_FIELD_ATTRIB_SMB_WORD = 0x08, AML_FIELD_ATTRIB_SMB_BLOCK = 0x0A, - AML_FIELD_ATTRIB_SMB_CALL = 0x0E + AML_FIELD_ATTRIB_SMB_WORD_CALL = 0x0C, + AML_FIELD_ATTRIB_SMB_BLOCK_CALL = 0x0D } AML_ACCESS_ATTRIBUTE; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/acpi/namespace/nsdump.c linux.2.5.47-ac4/drivers/acpi/namespace/nsdump.c --- linux.2.5.47/drivers/acpi/namespace/nsdump.c 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.47-ac4/drivers/acpi/namespace/nsdump.c 2002-11-13 01:18:37.000000000 +0000 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: nsdump - table dumping routines for debug - * $Revision: 145 $ + * $Revision: 146 $ * *****************************************************************************/ @@ -180,7 +180,7 @@ /* Indent the object according to the level */ - acpi_os_printf ("%2d%*s", level - 1, level * 2, " "); + acpi_os_printf ("%2d%*s", (u32) level - 1, (int) level * 2, " "); /* Check the node type and name */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/acpi/namespace/nsobject.c linux.2.5.47-ac4/drivers/acpi/namespace/nsobject.c --- linux.2.5.47/drivers/acpi/namespace/nsobject.c 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.47-ac4/drivers/acpi/namespace/nsobject.c 2002-11-13 01:18:37.000000000 +0000 @@ -2,7 +2,7 @@ * * Module Name: nsobject - Utilities for objects attached to namespace * table entries - * $Revision: 84 $ + * $Revision: 85 $ * ******************************************************************************/ @@ -173,13 +173,13 @@ * * FUNCTION: Acpi_ns_detach_object * - * PARAMETERS: Node - An object whose Value will be deleted + * PARAMETERS: Node - An node whose object will be detached * * RETURN: None. * - * DESCRIPTION: Delete the Value associated with a namespace object. If the - * Value is an allocated object, it is freed. Otherwise, the - * field is simply cleared. + * DESCRIPTION: Detach/delete an object associated with a namespace node. + * if the object is an allocated object, it is freed. + * Otherwise, the field is simply cleared. * ******************************************************************************/ @@ -234,6 +234,8 @@ * RETURN: Current value of the object field from the Node whose * handle is passed * + * DESCRIPTION: Obtain the object attached to a namespace node. + * ******************************************************************************/ acpi_operand_object * @@ -266,7 +268,9 @@ * PARAMETERS: Node - Parent Node to be examined * * RETURN: Current value of the object field from the Node whose - * handle is passed + * handle is passed. + * + * DESCRIPTION: Obtain a secondary object associated with a namespace node. * ******************************************************************************/ @@ -292,11 +296,13 @@ * * FUNCTION: Acpi_ns_attach_data * - * PARAMETERS: + * PARAMETERS: Node - Namespace node + * Handler - Handler to be associated with the data + * Data - Data to be attached * * RETURN: Status * - * DESCRIPTION: + * DESCRIPTION: Low-level attach data. Create and attach a Data object. * ******************************************************************************/ @@ -311,7 +317,8 @@ acpi_operand_object *data_desc; - /* */ + /* We only allow one attachment per handler */ + prev_obj_desc = NULL; obj_desc = node->object; while (obj_desc) { @@ -324,7 +331,6 @@ obj_desc = obj_desc->common.next_object; } - /* Create an internal object for the data */ data_desc = acpi_ut_create_internal_object (ACPI_TYPE_LOCAL_DATA); @@ -335,7 +341,6 @@ data_desc->data.handler = handler; data_desc->data.pointer = data; - /* Install the data object */ if (prev_obj_desc) { @@ -353,11 +358,13 @@ * * FUNCTION: Acpi_ns_detach_data * - * PARAMETERS: + * PARAMETERS: Node - Namespace node + * Handler - Handler associated with the data * * RETURN: Status * - * DESCRIPTION: + * DESCRIPTION: Low-level detach data. Delete the data node, but the caller + * is responsible for the actual data. * ******************************************************************************/ @@ -398,11 +405,14 @@ * * FUNCTION: Acpi_ns_get_attached_data * - * PARAMETERS: + * PARAMETERS: Node - Namespace node + * Handler - Handler associated with the data + * Data - Where the data is returned * * RETURN: Status * - * DESCRIPTION: + * DESCRIPTION: Low level interface to obtain data previously associated with + * a namespace node. * ******************************************************************************/ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/acpi/namespace/nsutils.c linux.2.5.47-ac4/drivers/acpi/namespace/nsutils.c --- linux.2.5.47/drivers/acpi/namespace/nsutils.c 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.47-ac4/drivers/acpi/namespace/nsutils.c 2002-11-13 01:18:37.000000000 +0000 @@ -2,7 +2,7 @@ * * Module Name: nsutils - Utilities for accessing ACPI namespace, accessing * parents and siblings and Scope manipulation - * $Revision: 115 $ + * $Revision: 116 $ * *****************************************************************************/ @@ -45,7 +45,7 @@ * * RETURN: None * - * DESCRIPTION: Print warning message + * DESCRIPTION: Print warning message with full pathname * ******************************************************************************/ @@ -61,12 +61,16 @@ char *name; + /* Convert path to external format */ + status = acpi_ns_externalize_name (ACPI_UINT32_MAX, internal_name, NULL, &name); acpi_os_printf ("%8s-%04d: *** Error: Looking up ", module_name, line_number); - if (name) { + /* Print target name */ + + if (ACPI_SUCCESS (status)) { acpi_os_printf ("[%s]", name); } else { diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/acpi/namespace/nsxfeval.c linux.2.5.47-ac4/drivers/acpi/namespace/nsxfeval.c --- linux.2.5.47/drivers/acpi/namespace/nsxfeval.c 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.47-ac4/drivers/acpi/namespace/nsxfeval.c 2002-11-13 01:18:37.000000000 +0000 @@ -2,7 +2,7 @@ * * Module Name: nsxfeval - Public interfaces to the ACPI subsystem * ACPI Object evaluation interfaces - * $Revision: 3 $ + * $Revision: 4 $ * ******************************************************************************/ @@ -570,11 +570,13 @@ * * FUNCTION: Acpi_attach_data * - * PARAMETERS: + * PARAMETERS: Obj_handle - Namespace node + * Handler - Handler for this attachment + * Data - Pointer to data to be attached * * RETURN: Status * - * DESCRIPTION: + * DESCRIPTION: Attach arbitrary data and handler to a namespace node. * ******************************************************************************/ @@ -621,11 +623,12 @@ * * FUNCTION: Acpi_detach_data * - * PARAMETERS: + * PARAMETERS: Obj_handle - Namespace node handle + * Handler - Handler used in call to Acpi_attach_data * * RETURN: Status * - * DESCRIPTION: + * DESCRIPTION: Remove data that was previously attached to a node. * ******************************************************************************/ @@ -670,11 +673,13 @@ * * FUNCTION: Acpi_get_data * - * PARAMETERS: + * PARAMETERS: Obj_handle - Namespace node + * Handler - Handler used in call to Attach_data + * Data - Where the data is returned * * RETURN: Status * - * DESCRIPTION: + * DESCRIPTION: Retrieve data that was previously attached to a namespace node. * ******************************************************************************/ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/acpi/osl.c linux.2.5.47-ac4/drivers/acpi/osl.c --- linux.2.5.47/drivers/acpi/osl.c 2002-11-05 13:54:43.000000000 +0000 +++ linux.2.5.47-ac4/drivers/acpi/osl.c 2002-11-13 01:18:37.000000000 +0000 @@ -702,7 +702,7 @@ acpi_os_wait_semaphore( acpi_handle handle, u32 units, - u32 timeout) + u16 timeout) { acpi_status status = AE_OK; struct semaphore *sem = (struct semaphore*)handle; @@ -739,7 +739,7 @@ * Wait Indefinitely: * ------------------ */ - case WAIT_FOREVER: + case ACPI_WAIT_FOREVER: ret = down_interruptible(sem); if (ret < 0) status = AE_ERROR; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/acpi/power.c linux.2.5.47-ac4/drivers/acpi/power.c --- linux.2.5.47/drivers/acpi/power.c 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.47-ac4/drivers/acpi/power.c 2002-11-13 01:18:37.000000000 +0000 @@ -443,12 +443,6 @@ if (!device) return_VALUE(-EINVAL); - if (!acpi_power_dir) { - acpi_power_dir = proc_mkdir(ACPI_POWER_CLASS, acpi_root_dir); - if (!acpi_power_dir) - return_VALUE(-ENODEV); - } - if (!acpi_device_dir(device)) { acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), acpi_power_dir); @@ -478,9 +472,6 @@ { ACPI_FUNCTION_TRACE("acpi_power_remove_fs"); - if (!acpi_power_dir) - return_VALUE(-ENODEV); - if (acpi_device_dir(device)) remove_proc_entry(acpi_device_bid(device), acpi_power_dir); @@ -591,6 +582,10 @@ INIT_LIST_HEAD(&acpi_power_resource_list); + acpi_power_dir = proc_mkdir(ACPI_POWER_CLASS, acpi_root_dir); + if (!acpi_power_dir) + return_VALUE(-ENODEV); + result = acpi_bus_register_driver(&acpi_power_driver); if (result < 0) { remove_proc_entry(ACPI_POWER_CLASS, acpi_root_dir); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/acpi/processor.c linux.2.5.47-ac4/drivers/acpi/processor.c --- linux.2.5.47/drivers/acpi/processor.c 2002-11-05 13:54:43.000000000 +0000 +++ linux.2.5.47-ac4/drivers/acpi/processor.c 2002-11-13 01:18:37.000000000 +0000 @@ -2289,13 +2289,6 @@ ACPI_FUNCTION_TRACE("acpi_processor_add_fs"); - if (!acpi_processor_dir) { - acpi_processor_dir = proc_mkdir(ACPI_PROCESSOR_CLASS, - acpi_root_dir); - if (!acpi_processor_dir) - return_VALUE(-ENODEV); - } - if (!acpi_device_dir(device)) { acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), acpi_processor_dir); @@ -2378,9 +2371,6 @@ { ACPI_FUNCTION_TRACE("acpi_processor_remove_fs"); - if (!acpi_processor_dir) - return_VALUE(-ENODEV); - if (acpi_device_dir(device)) remove_proc_entry(acpi_device_bid(device), acpi_processor_dir); @@ -2640,9 +2630,15 @@ memset(&processors, 0, sizeof(processors)); memset(&errata, 0, sizeof(errata)); + acpi_processor_dir = proc_mkdir(ACPI_PROCESSOR_CLASS, acpi_root_dir); + if (!acpi_processor_dir) + return_VALUE(-ENODEV); + result = acpi_bus_register_driver(&acpi_processor_driver); - if (result < 0) + if (result < 0) { + remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir); return_VALUE(-ENODEV); + } return_VALUE(0); } @@ -2651,13 +2647,11 @@ static void __exit acpi_processor_exit (void) { - int result = 0; - ACPI_FUNCTION_TRACE("acpi_processor_exit"); - result = acpi_bus_unregister_driver(&acpi_processor_driver); - if (!result) - remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir); + acpi_bus_unregister_driver(&acpi_processor_driver); + + remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir); return_VOID; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/acpi/scan.c linux.2.5.47-ac4/drivers/acpi/scan.c --- linux.2.5.47/drivers/acpi/scan.c 2002-11-05 13:54:43.000000000 +0000 +++ linux.2.5.47-ac4/drivers/acpi/scan.c 2002-11-13 01:18:37.000000000 +0000 @@ -258,6 +258,8 @@ return_VALUE(result); } + device->driver = driver; + /* * TBD - Configuration Management: Assign resources to device based * upon possible configuration and currently allocated resources. diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/acpi/tables/tbconvrt.c linux.2.5.47-ac4/drivers/acpi/tables/tbconvrt.c --- linux.2.5.47/drivers/acpi/tables/tbconvrt.c 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.47-ac4/drivers/acpi/tables/tbconvrt.c 2002-11-13 01:18:37.000000000 +0000 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: tbconvrt - ACPI Table conversion utilities - * $Revision: 44 $ + * $Revision: 45 $ * *****************************************************************************/ @@ -36,11 +36,13 @@ * * FUNCTION: Acpi_tb_get_table_count * - * PARAMETERS: + * PARAMETERS: RSDP - Pointer to the RSDP + * RSDT - Pointer to the RSDT/XSDT * - * RETURN: + * RETURN: The number of tables pointed to by the RSDT or XSDT. * - * DESCRIPTION: Calculate the number of tables + * DESCRIPTION: Calculate the number of tables. Automatically handles either + * an RSDT or XSDT. * ******************************************************************************/ @@ -80,9 +82,9 @@ * * FUNCTION: Acpi_tb_convert_to_xsdt * - * PARAMETERS: + * PARAMETERS: Table_info - Info about the RSDT * - * RETURN: + * RETURN: Status * * DESCRIPTION: Convert an RSDT to an XSDT (internal common format) * @@ -311,13 +313,11 @@ * * RETURN: Status * - * DESCRIPTION: - * Converts a BIOS supplied ACPI 1.0 FADT to an intermediate - * ACPI 2.0 FADT. If the BIOS supplied a 2.0 FADT then it is simply - * copied to the intermediate FADT. The ACPI CA software uses this - * intermediate FADT. Thus a significant amount of special #ifdef - * type codeing is saved. This intermediate FADT will need to be - * freed at some point. + * DESCRIPTION: Converts a BIOS supplied ACPI 1.0 FADT to a local + * ACPI 2.0 FADT. If the BIOS supplied a 2.0 FADT then it is simply + * copied to the local FADT. The ACPI CA software uses this + * local FADT. Thus a significant amount of special #ifdef + * type codeing is saved. * ******************************************************************************/ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/acpi/tables/tbxfroot.c linux.2.5.47-ac4/drivers/acpi/tables/tbxfroot.c --- linux.2.5.47/drivers/acpi/tables/tbxfroot.c 2002-10-31 14:57:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/acpi/tables/tbxfroot.c 2002-11-13 01:18:37.000000000 +0000 @@ -1,7 +1,7 @@ /****************************************************************************** * * Module Name: tbxfroot - Find the root ACPI table (RSDT) - * $Revision: 64 $ + * $Revision: 65 $ * *****************************************************************************/ @@ -302,7 +302,8 @@ status = acpi_tb_find_rsdp (&table_info, flags); if (ACPI_FAILURE (status)) { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "RSDP structure not found\n")); + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "RSDP structure not found, %s Flags=%X\n", + acpi_format_exception (status), flags)); return_ACPI_STATUS (AE_NO_ACPI_TABLES); } @@ -406,6 +407,8 @@ status = acpi_os_map_memory ((u64) LO_RSDP_WINDOW_BASE, LO_RSDP_WINDOW_SIZE, (void **) &table_ptr); if (ACPI_FAILURE (status)) { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not map memory at %X for length %X\n", + LO_RSDP_WINDOW_BASE, LO_RSDP_WINDOW_SIZE)); return_ACPI_STATUS (status); } @@ -428,6 +431,8 @@ status = acpi_os_map_memory ((u64) HI_RSDP_WINDOW_BASE, HI_RSDP_WINDOW_SIZE, (void **) &table_ptr); if (ACPI_FAILURE (status)) { + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not map memory at %X for length %X\n", + HI_RSDP_WINDOW_BASE, HI_RSDP_WINDOW_SIZE)); return_ACPI_STATUS (status); } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/acpi/thermal.c linux.2.5.47-ac4/drivers/acpi/thermal.c --- linux.2.5.47/drivers/acpi/thermal.c 2002-10-31 14:57:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/acpi/thermal.c 2002-11-13 01:18:37.000000000 +0000 @@ -1060,13 +1060,6 @@ ACPI_FUNCTION_TRACE("acpi_thermal_add_fs"); - if (!acpi_thermal_dir) { - acpi_thermal_dir = proc_mkdir(ACPI_THERMAL_CLASS, - acpi_root_dir); - if (!acpi_thermal_dir) - return_VALUE(-ENODEV); - } - if (!acpi_device_dir(device)) { acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), acpi_thermal_dir); @@ -1147,9 +1140,6 @@ { ACPI_FUNCTION_TRACE("acpi_thermal_remove_fs"); - if (!acpi_thermal_dir) - return_VALUE(-ENODEV); - if (acpi_device_dir(device)) remove_proc_entry(acpi_device_bid(device), acpi_thermal_dir); @@ -1351,9 +1341,15 @@ ACPI_FUNCTION_TRACE("acpi_thermal_init"); + acpi_thermal_dir = proc_mkdir(ACPI_THERMAL_CLASS, acpi_root_dir); + if (!acpi_thermal_dir) + return_VALUE(-ENODEV); + result = acpi_bus_register_driver(&acpi_thermal_driver); - if (result < 0) + if (result < 0) { + remove_proc_entry(ACPI_THERMAL_CLASS, acpi_root_dir); return_VALUE(-ENODEV); + } return_VALUE(0); } @@ -1362,13 +1358,11 @@ static void __exit acpi_thermal_exit (void) { - int result = 0; - ACPI_FUNCTION_TRACE("acpi_thermal_exit"); - result = acpi_bus_unregister_driver(&acpi_thermal_driver); - if (!result) - remove_proc_entry(ACPI_THERMAL_CLASS, acpi_root_dir); + acpi_bus_unregister_driver(&acpi_thermal_driver); + + remove_proc_entry(ACPI_THERMAL_CLASS, acpi_root_dir); return_VOID; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/acpi/utilities/utmisc.c linux.2.5.47-ac4/drivers/acpi/utilities/utmisc.c --- linux.2.5.47/drivers/acpi/utilities/utmisc.c 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.47-ac4/drivers/acpi/utilities/utmisc.c 2002-11-13 01:18:37.000000000 +0000 @@ -1,7 +1,7 @@ /******************************************************************************* * * Module Name: utmisc - common utility procedures - * $Revision: 85 $ + * $Revision: 86 $ * ******************************************************************************/ @@ -685,7 +685,7 @@ this_thread_id, acpi_ut_get_mutex_name (mutex_id))); status = acpi_os_wait_semaphore (acpi_gbl_acpi_mutex_info[mutex_id].mutex, - 1, WAIT_FOREVER); + 1, ACPI_WAIT_FOREVER); if (ACPI_SUCCESS (status)) { ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %X acquired Mutex [%s]\n", this_thread_id, acpi_ut_get_mutex_name (mutex_id))); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/atm/idt77252.c linux.2.5.47-ac4/drivers/atm/idt77252.c --- linux.2.5.47/drivers/atm/idt77252.c 2002-10-31 14:57:18.000000000 +0000 +++ linux.2.5.47-ac4/drivers/atm/idt77252.c 2002-11-13 15:21:49.000000000 +0000 @@ -2148,9 +2148,9 @@ est->interval = 2; /* XXX: make this configurable */ est->ewma_log = 2; /* XXX: make this configurable */ + init_timer(&est->timer); est->timer.data = (unsigned long)vc; est->timer.function = idt77252_est_timer; - init_timer(&est->timer); est->timer.expires = jiffies + ((HZ / 4) << est->interval); add_timer(&est->timer); @@ -3745,9 +3745,9 @@ spin_lock_init(&card->cmd_lock); spin_lock_init(&card->tst_lock); + init_timer(&card->tst_timer); card->tst_timer.data = (unsigned long)card; card->tst_timer.function = tst_timer; - init_timer(&card->tst_timer); /* Do the I/O remapping... */ card->membase = (unsigned long) ioremap(membase, 1024); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/block/cciss.c linux.2.5.47-ac4/drivers/block/cciss.c --- linux.2.5.47/drivers/block/cciss.c 2002-11-11 16:39:09.000000000 +0000 +++ linux.2.5.47-ac4/drivers/block/cciss.c 2002-11-11 16:51:32.000000000 +0000 @@ -88,6 +88,9 @@ /* How long to wait (in millesconds) for board to go into simple mode */ #define MAX_CONFIG_WAIT 1000 +/*define how many times we will try a command because of bus resets */ +#define MAX_CMD_RETRIES 3 + #define READ_AHEAD 128 #define NR_CMDS 384 /* #commands that can be outstanding */ #define MAX_CTLR 8 @@ -113,6 +116,9 @@ static inline void addQ(CommandList_struct **Qptr, CommandList_struct *c); static void start_io( ctlr_info_t *h); +static int sendcmd( __u8 cmd, int ctlr, void *buff, size_t size, + unsigned int use_unit_num, unsigned int log_unit, __u8 page_code, + unsigned char *scsi3addr); #ifdef CONFIG_PROC_FS static int cciss_proc_get_info(char *buffer, char **start, off_t offset, @@ -352,7 +358,7 @@ * but I'm already using way to many device nodes to claim another one * for "raw controller". */ - if (inode->i_bdev->bd_inode->i_size == 0) { + if (hba[ctlr]->drv[dsk].nr_blocks == 0) { if (minor(inode->i_rdev) != 0) return -ENXIO; if (!capable(CAP_SYS_ADMIN)) @@ -571,6 +577,24 @@ case CCISS_REVALIDVOLS: return( revalidate_allvol(inode->i_rdev)); + case CCISS_GETLUNINFO: { + LogvolInfo_struct luninfo; + struct gendisk *disk = hba[ctlr]->gendisk[dsk]; + drive_info_struct *drv = &hba[ctlr]->drv[dsk]; + int i; + + luninfo.LunID = drv->LunID; + luninfo.num_opens = drv->usage_count; + luninfo.num_parts = 0; + /* count partitions 1 to 15 with sizes > 0 */ + for(i=1; i part[i].nr_sects != 0) + luninfo.num_parts++; + if (copy_to_user((void *) arg, &luninfo, + sizeof(LogvolInfo_struct))) + return -EFAULT; + return(0); + } case CCISS_DEREGDISK: return( deregister_disk(ctlr,dsk)); @@ -808,6 +832,7 @@ /* zero out the disk size info */ h->drv[logvol].nr_blocks = 0; h->drv[logvol].block_size = 0; + h->drv[logvol].cylinders = 0; h->drv[logvol].LunID = 0; return(0); } @@ -918,6 +943,7 @@ c->SG[0].Len = size; c->SG[0].Ext = 0; // we are not chaining } +resend_cmd2: c->waiting = &wait; /* Put the request on the tail of the queue and send it */ @@ -929,10 +955,6 @@ wait_for_completion(&wait); - /* unlock the buffers from DMA */ - pci_unmap_single( h->pdev, (dma_addr_t) buff_dma_handle.val, - size, PCI_DMA_BIDIRECTIONAL); - if(c->err_info->CommandStatus != 0) { /* an error has occurred */ switch(c->err_info->CommandStatus) @@ -986,6 +1008,16 @@ case CMD_UNSOLICITED_ABORT: printk(KERN_WARNING "cciss: cmd %p aborted " "do to an unsolicited abort\n", c); + if (c->retry_count < MAX_CMD_RETRIES) { + printk(KERN_WARNING "retrying cmd\n"); + c->retry_count++; + /* erase the old error information */ + memset(c->err_info, 0, + sizeof(ErrorInfo_struct)); + return_status = IO_OK; + INIT_COMPLETION(wait); + goto resend_cmd2; + } return_status = IO_ERROR; @@ -997,10 +1029,80 @@ return_status = IO_ERROR; } } + /* unlock the buffers from DMA */ + pci_unmap_single( h->pdev, (dma_addr_t) buff_dma_handle.val, + size, PCI_DMA_BIDIRECTIONAL); cmd_free(h, c, 0); return(return_status); } +static void cciss_geometry_inquiry(int ctlr, int logvol, + int withirq, unsigned int total_size, + unsigned int block_size, InquiryData_struct *inq_buff, + drive_info_struct *drv) +{ + int return_code; + memset(inq_buff, 0, sizeof(InquiryData_struct)); + if (withirq) + return_code = sendcmd_withirq(CISS_INQUIRY, ctlr, + inq_buff, sizeof(*inq_buff), 1, logvol ,0xC1); + else + return_code = sendcmd(CISS_INQUIRY, ctlr, inq_buff, + sizeof(*inq_buff), 1, logvol ,0xC1, NULL); + if (return_code == IO_OK) { + if(inq_buff->data_byte[8] == 0xFF) { + printk(KERN_WARNING + "cciss: reading geometry failed, volume " + "does not support reading geometry\n"); + drv->block_size = block_size; + drv->nr_blocks = total_size; + drv->heads = 255; + drv->sectors = 32; // Sectors per track + drv->cylinders = total_size / 255 / 32; + } else { + drv->block_size = block_size; + drv->nr_blocks = total_size; + drv->heads = inq_buff->data_byte[6]; + drv->sectors = inq_buff->data_byte[7]; + drv->cylinders = (inq_buff->data_byte[4] & 0xff) << 8; + drv->cylinders += inq_buff->data_byte[5]; + } + } else { /* Get geometry failed */ + printk(KERN_WARNING "cciss: reading geometry failed, " + "continuing with default geometry\n"); + drv->block_size = block_size; + drv->nr_blocks = total_size; + drv->heads = 255; + drv->sectors = 32; // Sectors per track + drv->cylinders = total_size / 255 / 32; + } + printk(KERN_INFO " heads= %d, sectors= %d, cylinders= %d\n\n", + drv->heads, drv->sectors, drv->cylinders); +} +static void +cciss_read_capacity(int ctlr, int logvol, ReadCapdata_struct *buf, + int withirq, unsigned int *total_size, unsigned int *block_size) +{ + int return_code; + memset(buf, 0, sizeof(*buf)); + if (withirq) + return_code = sendcmd_withirq(CCISS_READ_CAPACITY, + ctlr, buf, sizeof(*buf), 1, logvol, 0 ); + else + return_code = sendcmd(CCISS_READ_CAPACITY, + ctlr, buf, sizeof(*buf), 1, logvol, 0, NULL ); + if (return_code == IO_OK) { + *total_size = be32_to_cpu(*((__u32 *) &buf->total_size[0]))+1; + *block_size = be32_to_cpu(*((__u32 *) &buf->block_size[0])); + } else { /* read capacity command failed */ + printk(KERN_WARNING "cciss: read capacity failed\n"); + *total_size = 0; + *block_size = BLOCK_SIZE; + } + printk(KERN_INFO " blocks= %d block_size= %d\n", + *total_size, *block_size); + return; +} static int register_new_disk(int ctlr) { struct gendisk *disk; @@ -1147,85 +1249,10 @@ /* there could be gaps in lun numbers, track hightest */ if(hba[ctlr]->highest_lun < lunid) hba[ctlr]->highest_lun = logvol; - - memset(size_buff, 0, sizeof(ReadCapdata_struct)); - return_code = sendcmd_withirq(CCISS_READ_CAPACITY, ctlr, size_buff, - sizeof( ReadCapdata_struct), 1, logvol, 0 ); - if (return_code == IO_OK) - { - total_size = (0xff & - (unsigned int)(size_buff->total_size[0])) << 24; - total_size |= (0xff & - (unsigned int)(size_buff->total_size[1])) << 16; - total_size |= (0xff & - (unsigned int)(size_buff->total_size[2])) << 8; - total_size |= (0xff & (unsigned int) - (size_buff->total_size[3])); - total_size++; // command returns highest block address - - block_size = (0xff & - (unsigned int)(size_buff->block_size[0])) << 24; - block_size |= (0xff & - (unsigned int)(size_buff->block_size[1])) << 16; - block_size |= (0xff & - (unsigned int)(size_buff->block_size[2])) << 8; - block_size |= (0xff & - (unsigned int)(size_buff->block_size[3])); - } else /* read capacity command failed */ - { - printk(KERN_WARNING "cciss: read capacity failed\n"); - total_size = 0; - block_size = BLOCK_SIZE; - } - printk(KERN_INFO " blocks= %u block_size= %d\n", - total_size, block_size); - /* Execute the command to read the disk geometry */ - memset(inq_buff, 0, sizeof(InquiryData_struct)); - return_code = sendcmd_withirq(CISS_INQUIRY, ctlr, inq_buff, - sizeof(InquiryData_struct), 1, logvol ,0xC1 ); - if (return_code == IO_OK) - { - if(inq_buff->data_byte[8] == 0xFF) - { - printk(KERN_WARNING "cciss: reading geometry failed, " - "volume does not support reading geometry\n"); - - hba[ctlr]->drv[logvol].block_size = block_size; - hba[ctlr]->drv[logvol].nr_blocks = total_size; - hba[ctlr]->drv[logvol].heads = 255; - hba[ctlr]->drv[logvol].sectors = 32; // Sectors per track - hba[ctlr]->drv[logvol].cylinders = total_size / 255 / 32; - } else - { - - hba[ctlr]->drv[logvol].block_size = block_size; - hba[ctlr]->drv[logvol].nr_blocks = total_size; - hba[ctlr]->drv[logvol].heads = - inq_buff->data_byte[6]; - hba[ctlr]->drv[logvol].sectors = - inq_buff->data_byte[7]; - hba[ctlr]->drv[logvol].cylinders = - (inq_buff->data_byte[4] & 0xff) << 8; - hba[ctlr]->drv[logvol].cylinders += - inq_buff->data_byte[5]; - } - } - else /* Get geometry failed */ - { - - printk(KERN_WARNING "cciss: reading geometry failed, " - "continuing with default geometry\n"); - - hba[ctlr]->drv[logvol].block_size = block_size; - hba[ctlr]->drv[logvol].nr_blocks = total_size; - hba[ctlr]->drv[logvol].heads = 255; - hba[ctlr]->drv[logvol].sectors = 32; // Sectors per track - hba[ctlr]->drv[logvol].cylinders = total_size / 255 / 32; - } - printk(KERN_INFO " heads= %d, sectors= %d, cylinders= %d\n\n", - hba[ctlr]->drv[logvol].heads, - hba[ctlr]->drv[logvol].sectors, - hba[ctlr]->drv[logvol].cylinders); + cciss_read_capacity(ctlr, logvol, size_buff, 1, + &total_size, &block_size); + cciss_geometry_inquiry(ctlr, logvol, 1, total_size, block_size, + inq_buff, &hba[ctlr]->drv[logvol]); hba[ctlr]->drv[logvol].usage_count = 0; ++hba[ctlr]->num_luns; /* setup partitions per disk */ @@ -1241,24 +1268,25 @@ /* * Wait polling for a command to complete. * The memory mapped FIFO is polled for the completion. - * Used only at init time, interrupts disabled. + * Used only at init time, interrupts from the HBA are disabled. */ static unsigned long pollcomplete(int ctlr) { - unsigned long done; - int i; + unsigned long done; + int i; - /* Wait (up to 2 seconds) for a command to complete */ + /* Wait (up to 20 seconds) for a command to complete */ - for (i = 200000; i > 0; i--) { - done = hba[ctlr]->access.command_completed(hba[ctlr]); - if (done == FIFO_EMPTY) { - udelay(10); /* a short fixed delay */ - } else - return (done); - } - /* Invalid address to tell caller we ran out of time */ - return 1; + for (i = 20 * HZ; i > 0; i--) { + done = hba[ctlr]->access.command_completed(hba[ctlr]); + if (done == FIFO_EMPTY) { + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1); + } else + return (done); + } + /* Invalid address to tell caller we ran out of time */ + return 1; } /* * Send a command to the controller, and wait for it to complete. @@ -1281,6 +1309,7 @@ unsigned long complete; ctlr_info_t *info_p= hba[ctlr]; u64bit buff_dma_handle; + int status = IO_OK; c = cmd_alloc(info_p, 1); if (c == NULL) @@ -1394,6 +1423,7 @@ c->SG[0].Len = size; c->SG[0].Ext = 0; // we are not chaining } +resend_cmd1: /* * Disable interrupt */ @@ -1426,9 +1456,6 @@ printk(KERN_DEBUG "cciss: command completed\n"); #endif /* CCISS_DEBUG */ - /* unlock the data buffer from DMA */ - pci_unmap_single(info_p->pdev, (dma_addr_t) buff_dma_handle.val, - size, PCI_DMA_BIDIRECTIONAL); if (complete != 1) { if ( (complete & CISS_ERROR_BIT) && (complete & ~CISS_ERROR_BIT) == c->busaddr) @@ -1448,6 +1475,27 @@ complete = c->busaddr; } else { + if (c->err_info->CommandStatus == + CMD_UNSOLICITED_ABORT) { + printk(KERN_WARNING "cciss: " + "cmd %p aborted do " + "to an unsolicited abort \n", c); + if (c->retry_count < MAX_CMD_RETRIES) { + printk(KERN_WARNING + "retrying cmd\n"); + c->retry_count++; + /* erase the old error */ + /* information */ + memset(c->err_info, 0, + sizeof(ErrorInfo_struct)); + goto resend_cmd1; + } else { + printk(KERN_WARNING + "retried to many times\n"); + status = IO_ERROR; + goto cleanup1; + } + } printk(KERN_WARNING "ciss ciss%d: sendcmd" " Error %x \n", ctlr, c->err_info->CommandStatus); @@ -1457,27 +1505,31 @@ c->err_info->MoreErrInfo.Invalid_Cmd.offense_size, c->err_info->MoreErrInfo.Invalid_Cmd.offense_num, c->err_info->MoreErrInfo.Invalid_Cmd.offense_value); - cmd_free(info_p,c, 1); - return(IO_ERROR); + status = IO_ERROR; + goto cleanup1; } } if (complete != c->busaddr) { printk( KERN_WARNING "cciss cciss%d: SendCmd " "Invalid command list address returned! (%lx)\n", ctlr, complete); - cmd_free(info_p, c, 1); - return (IO_ERROR); + status = IO_ERROR; + goto cleanup1; } } else { printk( KERN_WARNING "cciss cciss%d: SendCmd Timeout out, " "No command list address returned!\n", ctlr); - cmd_free(info_p, c, 1); - return (IO_ERROR); + status = IO_ERROR; } + +cleanup1: + /* unlock the data buffer from DMA */ + pci_unmap_single(info_p->pdev, (dma_addr_t) buff_dma_handle.val, + size, PCI_DMA_BIDIRECTIONAL); cmd_free(info_p, c, 1); - return (IO_OK); + return (status); } /* * Map (physical) PCI mem into (virtual) kernel space @@ -1561,27 +1613,35 @@ } } +/* Assumes that CCISS_LOCK(h->ctlr) is held. */ +/* Zeros out the error record and then resends the command back */ +/* to the controller */ +static inline void resend_cciss_cmd( ctlr_info_t *h, CommandList_struct *c) +{ + /* erase the old error information */ + memset(c->err_info, 0, sizeof(ErrorInfo_struct)); + + /* add it to software queue and then send it to the controller */ + addQ(&(h->reqQ),c); + h->Qdepth++; + if(h->Qdepth > h->maxQsinceinit) + h->maxQsinceinit = h->Qdepth; + + start_io(h); +} /* checks the status of the job and calls complete buffers to mark all * buffers for the completed job. */ -static inline void complete_command( CommandList_struct *cmd, int timeout) +static inline void complete_command( ctlr_info_t *h, CommandList_struct *cmd, + int timeout) { int status = 1; int i; + int retry_cmd = 0; u64bit temp64; if (timeout) status = 0; - /* unmap the DMA mapping for all the scatter gather elements */ - for(i=0; iHeader.SGList; i++) - { - temp64.val32.lower = cmd->SG[i].Addr.lower; - temp64.val32.upper = cmd->SG[i].Addr.upper; - pci_unmap_page(hba[cmd->ctlr]->pdev, - temp64.val, cmd->SG[i].Len, - (cmd->Request.Type.Direction == XFER_READ) ? - PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE); - } if(cmd->err_info->CommandStatus != 0) { /* an error has occurred */ @@ -1655,8 +1715,20 @@ status=0; break; case CMD_UNSOLICITED_ABORT: - printk(KERN_WARNING "cciss: cmd %p aborted " - "do to an unsolicited abort\n", cmd); + printk(KERN_WARNING "cciss: cmd %p aborted do " + "to an unsolicited abort \n", + cmd); + if (cmd->retry_count < MAX_CMD_RETRIES) + { + retry_cmd=1; + printk(KERN_WARNING + "retrying cmd\n"); + cmd->retry_count++; + } else + { + printk(KERN_WARNING + "retried to many times\n"); + } status=0; break; case CMD_TIMEOUT: @@ -1671,7 +1743,21 @@ status=0; } } - + /* We need to return this command */ + if(retry_cmd) { + resend_cciss_cmd(h,cmd); + return; + } + /* command did not need to be retried */ + /* unmap the DMA mapping for all the scatter gather elements */ + for(i=0; iHeader.SGList; i++) { + temp64.val32.lower = cmd->SG[i].Addr.lower; + temp64.val32.upper = cmd->SG[i].Addr.upper; + pci_unmap_page(hba[cmd->ctlr]->pdev, + temp64.val, cmd->SG[i].Len, + (cmd->Request.Type.Direction == XFER_READ) ? + PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE); + } complete_buffers(cmd->rq->bio, status); #ifdef CCISS_DEBUG @@ -1679,6 +1765,7 @@ #endif /* CCISS_DEBUG */ end_that_request_last(cmd->rq); + cmd_free(h,cmd,1); } /* @@ -1825,8 +1912,7 @@ if (c->busaddr == a) { removeQ(&h->cmpQ, c); if (c->cmd_type == CMD_RWREQ) { - complete_command(c, 0); - cmd_free(h, c, 1); + complete_command(h, c, 0); } else if (c->cmd_type == CMD_IOCTL_PEND) { complete(c->waiting); } @@ -2173,83 +2259,10 @@ ld_buff->LUN[i][0], ld_buff->LUN[i][1],ld_buff->LUN[i][2], ld_buff->LUN[i][3], hba[cntl_num]->drv[i].LunID); #endif /* CCISS_DEBUG */ - - memset(size_buff, 0, sizeof(ReadCapdata_struct)); - return_code = sendcmd(CCISS_READ_CAPACITY, cntl_num, size_buff, - sizeof( ReadCapdata_struct), 1, i, 0, NULL ); - if (return_code == IO_OK) - { - total_size = (0xff & - (unsigned int)(size_buff->total_size[0])) << 24; - total_size |= (0xff & - (unsigned int)(size_buff->total_size[1])) << 16; - total_size |= (0xff & - (unsigned int)(size_buff->total_size[2])) << 8; - total_size |= (0xff & (unsigned int) - (size_buff->total_size[3])); - total_size++; // command returns highest block address - - block_size = (0xff & - (unsigned int)(size_buff->block_size[0])) << 24; - block_size |= (0xff & - (unsigned int)(size_buff->block_size[1])) << 16; - block_size |= (0xff & - (unsigned int)(size_buff->block_size[2])) << 8; - block_size |= (0xff & - (unsigned int)(size_buff->block_size[3])); - } else /* read capacity command failed */ - { - printk(KERN_WARNING "cciss: read capacity failed\n"); - total_size = 0; - block_size = BLOCK_SIZE; - } - printk(KERN_INFO " blocks= %d block_size= %d\n", - total_size, block_size); - - /* Execute the command to read the disk geometry */ - memset(inq_buff, 0, sizeof(InquiryData_struct)); - return_code = sendcmd(CISS_INQUIRY, cntl_num, inq_buff, - sizeof(InquiryData_struct), 1, i ,0xC1, NULL ); - if (return_code == IO_OK) - { - if(inq_buff->data_byte[8] == 0xFF) - { - printk(KERN_WARNING "cciss: reading geometry failed, volume does not support reading geometry\n"); - - hba[cntl_num]->drv[i].block_size = block_size; - hba[cntl_num]->drv[i].nr_blocks = total_size; - hba[cntl_num]->drv[i].heads = 255; - hba[cntl_num]->drv[i].sectors = 32; // Sectors per track - hba[cntl_num]->drv[i].cylinders = total_size / 255 / 32; } else - { - - hba[cntl_num]->drv[i].block_size = block_size; - hba[cntl_num]->drv[i].nr_blocks = total_size; - hba[cntl_num]->drv[i].heads = - inq_buff->data_byte[6]; - hba[cntl_num]->drv[i].sectors = - inq_buff->data_byte[7]; - hba[cntl_num]->drv[i].cylinders = - (inq_buff->data_byte[4] & 0xff) << 8; - hba[cntl_num]->drv[i].cylinders += - inq_buff->data_byte[5]; - } - } - else /* Get geometry failed */ - { - printk(KERN_WARNING "cciss: reading geometry failed, continuing with default geometry\n"); - - hba[cntl_num]->drv[i].block_size = block_size; - hba[cntl_num]->drv[i].nr_blocks = total_size; - hba[cntl_num]->drv[i].heads = 255; - hba[cntl_num]->drv[i].sectors = 32; // Sectors per track - hba[cntl_num]->drv[i].cylinders = total_size / 255 / 32; - } - printk(KERN_INFO " heads= %d, sectors= %d, cylinders= %d\n\n", - hba[cntl_num]->drv[i].heads, - hba[cntl_num]->drv[i].sectors, - hba[cntl_num]->drv[i].cylinders); - + cciss_read_capacity(cntl_num, i, size_buff, 0, + &total_size, &block_size); + cciss_geometry_inquiry(cntl_num, i, 0, total_size, block_size, + inq_buff, &hba[cntl_num]->drv[i]); } kfree(ld_buff); kfree(size_buff); @@ -2407,7 +2420,7 @@ cciss_getgeometry(i); - cciss_find_non_disk_devices(i); /* find our tape drives, if any */ + cciss_scsi_setup(i); /* Turn the interrupts on so we can service requests */ hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_ON); @@ -2445,9 +2458,6 @@ set_capacity(disk, drv->nr_blocks); add_disk(disk); } - - cciss_register_scsi(i, 1); /* hook ourself into SCSI subsystem */ - return(1); } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/block/cciss_cmd.h linux.2.5.47-ac4/drivers/block/cciss_cmd.h --- linux.2.5.47/drivers/block/cciss_cmd.h 2002-10-31 14:57:17.000000000 +0000 +++ linux.2.5.47-ac4/drivers/block/cciss_cmd.h 2002-10-31 15:05:41.000000000 +0000 @@ -240,6 +240,7 @@ struct _CommandList_struct *next; struct request * rq; struct completion *waiting; + int retry_count; #ifdef CONFIG_CISS_SCSI_TAPE void * scsi_cmd; #endif diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/block/cciss_scsi.c linux.2.5.47-ac4/drivers/block/cciss_scsi.c --- linux.2.5.47/drivers/block/cciss_scsi.c 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.47-ac4/drivers/block/cciss_scsi.c 2002-10-31 16:48:05.000000000 +0000 @@ -89,8 +89,10 @@ working even with the SCSI system. It's so scsi_unregister_host will differentiate the controllers. When register_scsi_module is called, each host template is - customized (name change) in cciss_register_scsi() - (that's called from cciss.c:cciss_init_one()) */ + customized (name change) in cciss_register_scsi() (that's + called from cciss_engage_scsi, called from + cciss.c:cciss_proc_write(), on "engage scsi" being received + from user space.) */ static Scsi_Host_Template driver_template[MAX_CTLR] = @@ -199,14 +201,12 @@ } static int -scsi_cmd_stack_setup(int ctlr) +scsi_cmd_stack_setup(int ctlr, struct cciss_scsi_adapter_data_t *sa) { int i; - struct cciss_scsi_adapter_data_t *sa; struct cciss_scsi_cmd_stack_t *stk; size_t size; - sa = (struct cciss_scsi_adapter_data_t *) hba[ctlr]->scsi_ctlr; stk = &sa->cmd_stack; size = sizeof(struct cciss_scsi_cmd_stack_elem_t) * CMD_STACK_SIZE; @@ -535,126 +535,24 @@ return -1; } - static void -cciss_find_non_disk_devices(int cntl_num) +cciss_scsi_setup(int cntl_num) { - ReportLunData_struct *ld_buff; - InquiryData_struct *inq_buff; - int return_code; - int i; - int listlength = 0; - int num_luns; - unsigned char scsi3addr[8]; - unsigned long flags; - int reportlunsize = sizeof(*ld_buff) + CISS_MAX_PHYS_LUN * 8; - - hba[cntl_num]->scsi_ctlr = (void *) - kmalloc(sizeof(struct cciss_scsi_adapter_data_t), - GFP_KERNEL); - if (hba[cntl_num]->scsi_ctlr == NULL) - return; + struct cciss_scsi_adapter_data_t * shba; - ((struct cciss_scsi_adapter_data_t *) - hba[cntl_num]->scsi_ctlr)->scsi_host = NULL; - ((struct cciss_scsi_adapter_data_t *) - hba[cntl_num]->scsi_ctlr)->lock = SPIN_LOCK_UNLOCKED; - ((struct cciss_scsi_adapter_data_t *) - hba[cntl_num]->scsi_ctlr)->registered = 0; - - if (scsi_cmd_stack_setup(cntl_num) != 0) { - printk("Trouble, returned non-zero!\n"); - return; - } - - ld_buff = kmalloc(reportlunsize, GFP_KERNEL); - if (ld_buff == NULL) { - printk(KERN_ERR "cciss: out of memory\n"); - return; - } - memset(ld_buff, 0, sizeof(ReportLunData_struct)); - inq_buff = kmalloc(sizeof( InquiryData_struct), GFP_KERNEL); - if (inq_buff == NULL) { - printk(KERN_ERR "cciss: out of memory\n"); - kfree(ld_buff); - return; - } - - /* Get the physical luns */ - return_code = sendcmd(CISS_REPORT_PHYS, cntl_num, ld_buff, - reportlunsize, 0, 0, 0, NULL ); - - if( return_code == IO_OK) { - unsigned char *c = &ld_buff->LUNListLength[0]; - listlength = (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | c[3]; - } - else { /* getting report of physical luns failed */ - printk(KERN_WARNING "cciss: report physical luns" - " command failed\n"); - listlength = 0; - } - - CPQ_TAPE_LOCK(cntl_num, flags); ccissscsi[cntl_num].ndevices = 0; - num_luns = listlength / 8; // 8 bytes pre entry - /* printk("Found %d LUNs\n", num_luns); */ - - if (num_luns > CISS_MAX_PHYS_LUN) - { - printk(KERN_WARNING - "cciss: Maximum physical LUNs (%d) exceeded. " - "%d LUNs ignored.\n", CISS_MAX_PHYS_LUN, - num_luns - CISS_MAX_PHYS_LUN); - num_luns = CISS_MAX_PHYS_LUN; - } - - for(i=0; iLUN[i], 8); /* ugly... */ - return_code = sendcmd(CISS_INQUIRY, cntl_num, inq_buff, - sizeof(InquiryData_struct), 2, 0 ,0, scsi3addr ); - if (return_code == IO_OK) { - if(inq_buff->data_byte[8] == 0xFF) - { - printk(KERN_WARNING "cciss: inquiry failed\n"); - } else { - int devtype; - - /* printk("Inquiry...\n"); - print_bytes((unsigned char *) inq_buff, 36, 1, 1); */ - devtype = (inq_buff->data_byte[0] & 0x1f); - - switch (devtype) - { - case 0x01: /* sequential access, (tape) */ - case 0x08: /* medium changer */ - /* this is the only kind of dev */ - /* we want to expose here. */ - if (cciss_scsi_add_entry(cntl_num, -1, - (unsigned char *) ld_buff->LUN[i], - devtype) != 0) - i=num_luns; // leave loop - break; - default: - break; - } - - } - } - else printk("cciss: inquiry failed.\n"); + shba = (struct cciss_scsi_adapter_data_t *) + kmalloc(sizeof(*shba), GFP_KERNEL); + if (shba == NULL) + return; + shba->scsi_host = NULL; + shba->lock = SPIN_LOCK_UNLOCKED; + shba->registered = 0; + if (scsi_cmd_stack_setup(cntl_num, shba) != 0) { + kfree(shba); + shba = NULL; } -#if 0 - for (i=0;iscsi_ctlr = (void *) shba; return; } @@ -913,7 +811,7 @@ memset(cp->Request.CDB, 0, sizeof(cp->Request.CDB)); memcpy(cp->Request.CDB, cdb, cdblen); - cp->Request.Timeout = 1000; // guarantee completion. + cp->Request.Timeout = 0; cp->Request.CDBLen = cdblen; cp->Request.Type.Type = TYPE_CMD; cp->Request.Type.Attribute = ATTR_SIMPLE; @@ -1262,7 +1160,6 @@ int buflen, datalen; struct Scsi_Host *sh; - int found; ctlr_info_t *ci; int cntl_num; @@ -1428,7 +1325,7 @@ // Fill in the request block... - cp->Request.Timeout = 1000; // guarantee completion + cp->Request.Timeout = 0; memset(cp->Request.CDB, 0, sizeof(cp->Request.CDB)); if (cmd->cmd_len > sizeof(cp->Request.CDB)) BUG(); cp->Request.CDBLen = cmd->cmd_len; @@ -1531,7 +1428,7 @@ } static int -cciss_register_scsi(int ctlr, int this_is_init_time) +cciss_register_scsi(int ctlr) { unsigned long flags; @@ -1541,15 +1438,10 @@ driver_template[ctlr].module = THIS_MODULE;; /* Since this is really a block driver, the SCSI core may not be - initialized yet, in which case, calling scsi_register_host - would hang. instead, we will do it later, via /proc filesystem + initialized at init time, in which case, calling scsi_register_host + would hang. Instead, we do it later, via /proc filesystem and rc scripts, when we know SCSI core is good to go. */ - if (this_is_init_time) { - CPQ_TAPE_UNLOCK(ctlr, flags); - return 0; - } - /* Only register if SCSI devices are detected. */ if (ccissscsi[ctlr].ndevices != 0) { ((struct cciss_scsi_adapter_data_t *) @@ -1583,7 +1475,7 @@ } spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); cciss_update_non_disk_devices(ctlr, -1); - cciss_register_scsi(ctlr, 0); + cciss_register_scsi(ctlr); return 0; } @@ -1607,9 +1499,9 @@ /* If no tape support, then these become defined out of existence */ -#define cciss_find_non_disk_devices(cntl_num) +#define cciss_scsi_setup(cntl_num) #define cciss_unregister_scsi(ctlr) -#define cciss_register_scsi(ctlr, this_is_init_time) +#define cciss_register_scsi(ctlr) #define cciss_proc_tape_report(ctlr, buffer, pos, len) #endif /* CONFIG_CISS_SCSI_TAPE */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/block/floppy98.c linux.2.5.47-ac4/drivers/block/floppy98.c --- linux.2.5.47/drivers/block/floppy98.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.47-ac4/drivers/block/floppy98.c 2002-10-31 15:05:41.000000000 +0000 @@ -0,0 +1,4639 @@ +/* + * linux/drivers/block/floppy.c + * + * Copyright (C) 1991, 1992 Linus Torvalds + * Copyright (C) 1993, 1994 Alain Knaff + * Copyright (C) 1998 Alan Cox + */ +/* + * 02.12.91 - Changed to static variables to indicate need for reset + * and recalibrate. This makes some things easier (output_byte reset + * checking etc), and means less interrupt jumping in case of errors, + * so the code is hopefully easier to understand. + */ + +/* + * This file is certainly a mess. I've tried my best to get it working, + * but I don't like programming floppies, and I have only one anyway. + * Urgel. I should check for more errors, and do more graceful error + * recovery. Seems there are problems with several drives. I've tried to + * correct them. No promises. + */ + +/* + * As with hd.c, all routines within this file can (and will) be called + * by interrupts, so extreme caution is needed. A hardware interrupt + * handler may not sleep, or a kernel panic will happen. Thus I cannot + * call "floppy-on" directly, but have to set a special timer interrupt + * etc. + */ + +/* + * 28.02.92 - made track-buffering routines, based on the routines written + * by entropy@wintermute.wpi.edu (Lawrence Foard). Linus. + */ + +/* + * Automatic floppy-detection and formatting written by Werner Almesberger + * (almesber@nessie.cs.id.ethz.ch), who also corrected some problems with + * the floppy-change signal detection. + */ + +/* + * 1992/7/22 -- Hennus Bergman: Added better error reporting, fixed + * FDC data overrun bug, added some preliminary stuff for vertical + * recording support. + * + * 1992/9/17: Added DMA allocation & DMA functions. -- hhb. + * + * TODO: Errors are still not counted properly. + */ + +/* 1992/9/20 + * Modifications for ``Sector Shifting'' by Rob Hooft (hooft@chem.ruu.nl) + * modeled after the freeware MS-DOS program fdformat/88 V1.8 by + * Christoph H. Hochst\"atter. + * I have fixed the shift values to the ones I always use. Maybe a new + * ioctl() should be created to be able to modify them. + * There is a bug in the driver that makes it impossible to format a + * floppy as the first thing after bootup. + */ + +/* + * 1993/4/29 -- Linus -- cleaned up the timer handling in the kernel, and + * this helped the floppy driver as well. Much cleaner, and still seems to + * work. + */ + +/* 1994/6/24 --bbroad-- added the floppy table entries and made + * minor modifications to allow 2.88 floppies to be run. + */ + +/* 1994/7/13 -- Paul Vojta -- modified the probing code to allow three or more + * disk types. + */ + +/* + * 1994/8/8 -- Alain Knaff -- Switched to fdpatch driver: Support for bigger + * format bug fixes, but unfortunately some new bugs too... + */ + +/* 1994/9/17 -- Koen Holtman -- added logging of physical floppy write + * errors to allow safe writing by specialized programs. + */ + +/* 1995/4/24 -- Dan Fandrich -- added support for Commodore 1581 3.5" disks + * by defining bit 1 of the "stretch" parameter to mean put sectors on the + * opposite side of the disk, leaving the sector IDs alone (i.e. Commodore's + * drives are "upside-down"). + */ + +/* + * 1995/8/26 -- Andreas Busse -- added Mips support. + */ + +/* + * 1995/10/18 -- Ralf Baechle -- Portability cleanup; move machine dependent + * features to asm/floppy.h. + */ + +/* + * 1998/05/07 -- Russell King -- More portability cleanups; moved definition of + * interrupt and dma channel to asm/floppy.h. Cleaned up some formatting & + * use of '0' for NULL. + */ + +/* + * 1998/06/07 -- Alan Cox -- Merged the 2.0.34 fixes for resource allocation + * failures. + */ + +/* + * 1998/09/20 -- David Weinehall -- Added slow-down code for buggy PS/2-drives. + */ + +/* + * 1999/01/19 -- N.Fujita & Linux/98 Project -- Added code for NEC PC-9800 + * series. + */ + +/* + * 1999/08/13 -- Paul Slootman -- floppy stopped working on Alpha after 24 + * days, 6 hours, 32 minutes and 32 seconds (i.e. MAXINT jiffies; ints were + * being used to store jiffies, which are unsigned longs). + */ + +/* + * 2000/08/28 -- Arnaldo Carvalho de Melo + * - get rid of check_region + * - s/suser/capable/ + */ + +/* + * 2001/08/26 -- Paul Gortmaker - fix insmod oops on machines with no + * floppy controller (lingering task on list after module is gone... boom.) + */ + +/* + * 2002/02/07 -- Anton Altaparmakov - Fix io ports reservation to correct range + * (0x3f2-0x3f5, 0x3f7). This fix is a bit of a hack but the proper fix + * requires many non-obvious changes in arch dependent code. + */ + +/* + * 2002/10/12 -- Osamu Tomita + * split code from floppy.c + * support NEC PC-9800 only + */ + +#define FLOPPY_SANITY_CHECK +#undef FLOPPY_SILENT_DCL_CLEAR + +/* +#define PC9800_DEBUG_FLOPPY +#define PC9800_DEBUG_FLOPPY2 +*/ + +#define REALLY_SLOW_IO + +#define DEBUGT 2 +#define DCL_DEBUG /* debug disk change line */ + +/* do print messages for unexpected interrupts */ +static int print_unex=1; +#include +#include +#include +#include +#include +#include +#define FDPATCHES +#include + +/* + * 1998/1/21 -- Richard Gooch -- devfs support + */ + + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include /* CMOS defines */ +#include +#include +#include +#include +#include +#include /* for invalidate_buffers() */ + +/* + * PS/2 floppies have much slower step rates than regular floppies. + * It's been recommended that take about 1/4 of the default speed + * in some more extreme cases. + */ +static int slow_floppy; + +#include +#include +#include +#include +#include + +#ifndef DEFAULT_FLOPPY_IRQ +# define DEFAULT_FLOPPY_IRQ 11 +#endif +#ifndef DEFAULT_FLOPPY_DMA +# define DEFAULT_FLOPPY_DMA 2 +#endif + +static int FLOPPY_IRQ=DEFAULT_FLOPPY_IRQ; +static int FLOPPY_DMA=DEFAULT_FLOPPY_DMA; +static int can_use_virtual_dma=2; +static int auto_detect_mode = 0; +static int retry_auto_detect = 0; +#define FD_AFTER_RESET_DELAY 1000 + +/* ======= + * can use virtual DMA: + * 0 = use of virtual DMA disallowed by config + * 1 = use of virtual DMA prescribed by config + * 2 = no virtual DMA preference configured. By default try hard DMA, + * but fall back on virtual DMA when not enough memory available + */ + +static int use_virtual_dma; +/* ======= + * use virtual DMA + * 0 using hard DMA + * 1 using virtual DMA + * This variable is set to virtual when a DMA mem problem arises, and + * reset back in floppy_grab_irq_and_dma. + * It is not safe to reset it in other circumstances, because the floppy + * driver may have several buffers in use at once, and we do currently not + * record each buffers capabilities + */ + +static spinlock_t floppy_lock = SPIN_LOCK_UNLOCKED; + +static unsigned short virtual_dma_port=0x3f0; +void floppy_interrupt(int irq, void *dev_id, struct pt_regs * regs); +static int set_mode(char mask, char data); +static void register_devfs_entries (int drive) __init; +static devfs_handle_t devfs_handle; + +#define K_64 0x10000 /* 64KB */ + +/* the following is the mask of allowed drives. By default units 2 and + * 3 of both floppy controllers are disabled, because switching on the + * motor of these drives causes system hangs on some PCI computers. drive + * 0 is the low bit (0x1), and drive 7 is the high bit (0x80). Bits are on if + * a drive is allowed. + * + * NOTE: This must come before we include the arch floppy header because + * some ports reference this variable from there. -DaveM + */ + +static int allowed_drive_mask = 0x0f; + +#include + +static int irqdma_allocated; + +#define LOCAL_END_REQUEST +#define MAJOR_NR FLOPPY_MAJOR +#define DEVICE_NAME "floppy" +#define DEVICE_NR(device) ( (minor(device) & 3) | ((minor(device) & 0x80 ) >> 5 )) +#include +#include +#include /* for the compatibility eject ioctl */ +#include + +static struct request *current_req; +static struct request_queue floppy_queue; + +#ifndef fd_get_dma_residue +#define fd_get_dma_residue() get_dma_residue(FLOPPY_DMA) +#endif + +/* Dma Memory related stuff */ + +#ifndef fd_dma_mem_free +#define fd_dma_mem_free(addr, size) free_pages(addr, get_order(size)) +#endif + +#ifndef fd_dma_mem_alloc +#define fd_dma_mem_alloc(size) __get_dma_pages(GFP_KERNEL,get_order(size)) +#endif + +static inline void fallback_on_nodma_alloc(char **addr, size_t l) +{ +#ifdef FLOPPY_CAN_FALLBACK_ON_NODMA + if (*addr) + return; /* we have the memory */ + if (can_use_virtual_dma != 2) + return; /* no fallback allowed */ + printk("DMA memory shortage. Temporarily falling back on virtual DMA\n"); + *addr = (char *) nodma_mem_alloc(l); +#else + return; +#endif +} + +/* End dma memory related stuff */ + +static unsigned long fake_change; +static int initialising=1; + +static inline int TYPE(kdev_t x) { + return (minor(x)>>2) & 0x1f; +} +static inline int DRIVE(kdev_t x) { + return (minor(x)&0x03) | ((minor(x)&0x80) >> 5); +} +#define ITYPE(x) (((x)>>2) & 0x1f) +#define TOMINOR(x) ((x & 3) | ((x & 4) << 5)) +#define UNIT(x) ((x) & 0x03) /* drive on fdc */ +#define FDC(x) (((x) & 0x04) >> 2) /* fdc of drive */ +#define REVDRIVE(fdc, unit) ((unit) + ((fdc) << 2)) + /* reverse mapping from unit and fdc to drive */ +#define DP (&drive_params[current_drive]) +#define DRS (&drive_state[current_drive]) +#define DRWE (&write_errors[current_drive]) +#define FDCS (&fdc_state[fdc]) +#define CLEARF(x) (clear_bit(x##_BIT, &DRS->flags)) +#define SETF(x) (set_bit(x##_BIT, &DRS->flags)) +#define TESTF(x) (test_bit(x##_BIT, &DRS->flags)) + +#define UDP (&drive_params[drive]) +#define UDRS (&drive_state[drive]) +#define UDRWE (&write_errors[drive]) +#define UFDCS (&fdc_state[FDC(drive)]) +#define UCLEARF(x) (clear_bit(x##_BIT, &UDRS->flags)) +#define USETF(x) (set_bit(x##_BIT, &UDRS->flags)) +#define UTESTF(x) (test_bit(x##_BIT, &UDRS->flags)) + +#define DPRINT(format, args...) printk(DEVICE_NAME "%d: " format, current_drive , ## args) + +#define PH_HEAD(floppy,head) (((((floppy)->stretch & 2) >>1) ^ head) << 2) +#define STRETCH(floppy) ((floppy)->stretch & FD_STRETCH) + +#define CLEARSTRUCT(x) memset((x), 0, sizeof(*(x))) + +/* read/write */ +#define COMMAND raw_cmd->cmd[0] +#define DR_SELECT raw_cmd->cmd[1] +#define TRACK raw_cmd->cmd[2] +#define HEAD raw_cmd->cmd[3] +#define SECTOR raw_cmd->cmd[4] +#define SIZECODE raw_cmd->cmd[5] +#define SECT_PER_TRACK raw_cmd->cmd[6] +#define GAP raw_cmd->cmd[7] +#define SIZECODE2 raw_cmd->cmd[8] +#define NR_RW 9 + +/* format */ +#define F_SIZECODE raw_cmd->cmd[2] +#define F_SECT_PER_TRACK raw_cmd->cmd[3] +#define F_GAP raw_cmd->cmd[4] +#define F_FILL raw_cmd->cmd[5] +#define NR_F 6 + +/* + * Maximum disk size (in kilobytes). This default is used whenever the + * current disk size is unknown. + * [Now it is rather a minimum] + */ +#define MAX_DISK_SIZE 4 /* 3984*/ + + +/* + * globals used by 'result()' + */ +#define MAX_REPLIES 16 +static unsigned char reply_buffer[MAX_REPLIES]; +static int inr; /* size of reply buffer, when called from interrupt */ +#define ST0 (reply_buffer[0]) +#define ST1 (reply_buffer[1]) +#define ST2 (reply_buffer[2]) +#define ST3 (reply_buffer[0]) /* result of GETSTATUS */ +#define R_TRACK (reply_buffer[3]) +#define R_HEAD (reply_buffer[4]) +#define R_SECTOR (reply_buffer[5]) +#define R_SIZECODE (reply_buffer[6]) + +#define SEL_DLY (2*HZ/100) + +/* + * this struct defines the different floppy drive types. + */ +static struct { + struct floppy_drive_params params; + const char *name; /* name printed while booting */ +} default_drive_params[]= { +/* NOTE: the time values in jiffies should be in msec! + CMOS drive type + | Maximum data rate supported by drive type + | | Head load time, msec + | | | Head unload time, msec (not used) + | | | | Step rate interval, usec + | | | | | Time needed for spinup time (jiffies) + | | | | | | Timeout for spinning down (jiffies) + | | | | | | | Spindown offset (where disk stops) + | | | | | | | | Select delay + | | | | | | | | | RPS + | | | | | | | | | | Max number of tracks + | | | | | | | | | | | Interrupt timeout + | | | | | | | | | | | | Max nonintlv. sectors + | | | | | | | | | | | | | -Max Errors- flags */ +{{0, 500, 16, 16, 8000, 1*HZ, 3*HZ, 0, SEL_DLY, 5, 80, 3*HZ, 20, {3,1,2,0,2}, 0, + 0, { 7, 4, 8, 2, 1, 5, 3,10}, 3*HZ/2, 0 }, "unknown" }, + +{{1, 300, 16, 16, 8000, 1*HZ, 3*HZ, 0, SEL_DLY, 5, 40, 3*HZ, 17, {3,1,2,0,2}, 0, + 0, { 1, 0, 0, 0, 0, 0, 0, 0}, 3*HZ/2, 1 }, "360K PC" }, /*5 1/4 360 KB PC*/ + +{{2, 500, 16, 16, 6000, 4*HZ/10, 3*HZ, 14, SEL_DLY, 6, 83, 3*HZ, 17, {3,1,2,0,2}, 0, + 0, { 2, 6, 4, 0, 0, 0, 0, 0}, 3*HZ/2, 2 }, "1.2M" }, /*5 1/4 HD AT*/ + +{{3, 250, 16, 16, 3000, 1*HZ, 3*HZ, 0, SEL_DLY, 5, 83, 3*HZ, 20, {3,1,2,0,2}, 0, + 0, { 4, 6, 0, 0, 0, 0, 0, 0}, 3*HZ/2, 4 }, "720k" }, /*3 1/2 DD*/ + +{{4, 500, 16, 16, 4000, 4*HZ/10, 3*HZ, 10, SEL_DLY, 5, 83, 3*HZ, 20, {3,1,2,0,2}, 0, + 0, { 7,10, 2, 4, 6, 0, 0, 0}, 3*HZ/2, 7 }, "1.44M" }, /*3 1/2 HD*/ + +{{5, 1000, 15, 8, 3000, 4*HZ/10, 3*HZ, 10, SEL_DLY, 5, 83, 3*HZ, 40, {3,1,2,0,2}, 0, + 0, { 7, 8, 4,25,28,22,31,21}, 3*HZ/2, 8 }, "2.88M AMI BIOS" }, /*3 1/2 ED*/ + +{{6, 1000, 15, 8, 3000, 4*HZ/10, 3*HZ, 10, SEL_DLY, 5, 83, 3*HZ, 40, {3,1,2,0,2}, 0, + 0, { 7, 8, 4,25,28,22,31,21}, 3*HZ/2, 8 }, "2.88M" } /*3 1/2 ED*/ +/* | --autodetected formats--- | | | + * read_track | | Name printed when booting + * | Native format + * Frequency of disk change checks */ +}; + +static struct floppy_drive_params drive_params[N_DRIVE]; +static struct floppy_drive_struct drive_state[N_DRIVE]; +static struct floppy_write_errors write_errors[N_DRIVE]; +static struct timer_list motor_off_timer[N_DRIVE]; +static struct gendisk *disks[N_DRIVE]; +static struct floppy_raw_cmd *raw_cmd, default_raw_cmd; + +/* + * This struct defines the different floppy types. + * + * Bit 0 of 'stretch' tells if the tracks need to be doubled for some + * types (e.g. 360kB diskette in 1.2MB drive, etc.). Bit 1 of 'stretch' + * tells if the disk is in Commodore 1581 format, which means side 0 sectors + * are located on side 1 of the disk but with a side 0 ID, and vice-versa. + * This is the same as the Sharp MZ-80 5.25" CP/M disk format, except that the + * 1581's logical side 0 is on physical side 1, whereas the Sharp's logical + * side 0 is on physical side 0 (but with the misnamed sector IDs). + * 'stretch' should probably be renamed to something more general, like + * 'options'. Other parameters should be self-explanatory (see also + * setfdprm(8)). + */ +/* + Size + | Sectors per track + | | Head + | | | Tracks + | | | | Stretch + | | | | | Gap 1 size + | | | | | | Data rate, | 0x40 for perp + | | | | | | | Spec1 (stepping rate, head unload + | | | | | | | | /fmt gap (gap2) */ +static struct floppy_struct floppy_type[32] = { + { 0, 0,0, 0,0,0x00,0x00,0x00,0x00,NULL }, /* 0 no testing */ +#if 0 + { 720, 9,2,40,0,0x2A,0x02,0xDF,0x50,"d360" }, /* 1 360KB PC */ +#else + { 2464,16,2,77,0,0x35,0x48,0xDF,0x74,"d360" }, /* 1 1.25MB 98 */ +#endif + { 2400,15,2,80,0,0x1B,0x00,0xDF,0x54,"h1200" }, /* 2 1.2MB AT */ + { 720, 9,1,80,0,0x2A,0x02,0xDF,0x50,"D360" }, /* 3 360KB SS 3.5" */ + { 1440, 9,2,80,0,0x2A,0x02,0xDF,0x50,"D720" }, /* 4 720KB 3.5" */ + { 720, 9,2,40,1,0x23,0x01,0xDF,0x50,"h360" }, /* 5 360KB AT */ + { 1440, 9,2,80,0,0x23,0x01,0xDF,0x50,"h720" }, /* 6 720KB AT */ + { 2880,18,2,80,0,0x1B,0x00,0xCF,0x6C,"H1440" }, /* 7 1.44MB 3.5" */ + { 5760,36,2,80,0,0x1B,0x43,0xAF,0x54,"E2880" }, /* 8 2.88MB 3.5" */ + { 6240,39,2,80,0,0x1B,0x43,0xAF,0x28,"E3120" }, /* 9 3.12MB 3.5" */ + + { 2880,18,2,80,0,0x25,0x00,0xDF,0x02,"h1440" }, /* 10 1.44MB 5.25" */ + { 3360,21,2,80,0,0x1C,0x00,0xCF,0x0C,"H1680" }, /* 11 1.68MB 3.5" */ + { 820,10,2,41,1,0x25,0x01,0xDF,0x2E,"h410" }, /* 12 410KB 5.25" */ + { 1640,10,2,82,0,0x25,0x02,0xDF,0x2E,"H820" }, /* 13 820KB 3.5" */ + { 2952,18,2,82,0,0x25,0x00,0xDF,0x02,"h1476" }, /* 14 1.48MB 5.25" */ + { 3444,21,2,82,0,0x25,0x00,0xDF,0x0C,"H1722" }, /* 15 1.72MB 3.5" */ + { 840,10,2,42,1,0x25,0x01,0xDF,0x2E,"h420" }, /* 16 420KB 5.25" */ + { 1660,10,2,83,0,0x25,0x02,0xDF,0x2E,"H830" }, /* 17 830KB 3.5" */ + { 2988,18,2,83,0,0x25,0x00,0xDF,0x02,"h1494" }, /* 18 1.49MB 5.25" */ + { 3486,21,2,83,0,0x25,0x00,0xDF,0x0C,"H1743" }, /* 19 1.74 MB 3.5" */ + + { 1760,11,2,80,0,0x1C,0x09,0xCF,0x00,"h880" }, /* 20 880KB 5.25" */ + { 2080,13,2,80,0,0x1C,0x01,0xCF,0x00,"D1040" }, /* 21 1.04MB 3.5" */ + { 2240,14,2,80,0,0x1C,0x19,0xCF,0x00,"D1120" }, /* 22 1.12MB 3.5" */ + { 3200,20,2,80,0,0x1C,0x20,0xCF,0x2C,"h1600" }, /* 23 1.6MB 5.25" */ + { 3520,22,2,80,0,0x1C,0x08,0xCF,0x2e,"H1760" }, /* 24 1.76MB 3.5" */ + { 3840,24,2,80,0,0x1C,0x20,0xCF,0x00,"H1920" }, /* 25 1.92MB 3.5" */ + { 6400,40,2,80,0,0x25,0x5B,0xCF,0x00,"E3200" }, /* 26 3.20MB 3.5" */ + { 7040,44,2,80,0,0x25,0x5B,0xCF,0x00,"E3520" }, /* 27 3.52MB 3.5" */ + { 7680,48,2,80,0,0x25,0x63,0xCF,0x00,"E3840" }, /* 28 3.84MB 3.5" */ + + { 3680,23,2,80,0,0x1C,0x10,0xCF,0x00,"H1840" }, /* 29 1.84MB 3.5" */ + { 1600,10,2,80,0,0x25,0x02,0xDF,0x2E,"D800" }, /* 30 800KB 3.5" */ + { 3200,20,2,80,0,0x1C,0x00,0xCF,0x2C,"H1600" }, /* 31 1.6MB 3.5" */ +}; + +#define NUMBER(x) (sizeof(x) / sizeof(*(x))) +#define SECTSIZE (_FD_SECTSIZE(*floppy)) + +/* Auto-detection: Disk type used until the next media change occurs. */ +static struct floppy_struct *current_type[N_DRIVE]; + +/* + * User-provided type information. current_type points to + * the respective entry of this array. + */ +static struct floppy_struct user_params[N_DRIVE]; + +static sector_t floppy_sizes[256]; + +/* + * The driver is trying to determine the correct media format + * while probing is set. rw_interrupt() clears it after a + * successful access. + */ +static int probing; + +/* Synchronization of FDC access. */ +#define FD_COMMAND_NONE -1 +#define FD_COMMAND_ERROR 2 +#define FD_COMMAND_OKAY 3 + +static volatile int command_status = FD_COMMAND_NONE; +static unsigned long fdc_busy; +static DECLARE_WAIT_QUEUE_HEAD(fdc_wait); +static DECLARE_WAIT_QUEUE_HEAD(command_done); + +#define NO_SIGNAL (!interruptible || !signal_pending(current)) +#define CALL(x) if ((x) == -EINTR) return -EINTR +#define ECALL(x) if ((ret = (x))) return ret; +#define _WAIT(x,i) CALL(ret=wait_til_done((x),i)) +#define WAIT(x) _WAIT((x),interruptible) +#define IWAIT(x) _WAIT((x),1) + +/* Errors during formatting are counted here. */ +static int format_errors; + +/* Format request descriptor. */ +static struct format_descr format_req; + +/* + * Rate is 0 for 500kb/s, 1 for 300kbps, 2 for 250kbps + * Spec1 is 0xSH, where S is stepping rate (F=1ms, E=2ms, D=3ms etc), + * H is head unload time (1=16ms, 2=32ms, etc) + */ + +/* + * Track buffer + * Because these are written to by the DMA controller, they must + * not contain a 64k byte boundary crossing, or data will be + * corrupted/lost. + */ +static char *floppy_track_buffer; +static int max_buffer_sectors; + +static int *errors; +typedef void (*done_f)(int); +static struct cont_t { + void (*interrupt)(void); /* this is called after the interrupt of the + * main command */ + void (*redo)(void); /* this is called to retry the operation */ + void (*error)(void); /* this is called to tally an error */ + done_f done; /* this is called to say if the operation has + * succeeded/failed */ +} *cont; + +static void floppy_ready(void); +static void floppy_start(void); +static void process_fd_request(void); +static void recalibrate_floppy(void); +static void floppy_shutdown(void); + +static int floppy_grab_irq_and_dma(void); +static void floppy_release_irq_and_dma(void); + +/* + * The "reset" variable should be tested whenever an interrupt is scheduled, + * after the commands have been sent. This is to ensure that the driver doesn't + * get wedged when the interrupt doesn't come because of a failed command. + * reset doesn't need to be tested before sending commands, because + * output_byte is automatically disabled when reset is set. + */ +#define CHECK_RESET { if (FDCS->reset){ reset_fdc(); return; } } +static void reset_fdc(void); + +/* + * These are global variables, as that's the easiest way to give + * information to interrupts. They are the data used for the current + * request. + */ +#define NO_TRACK -1 +#define NEED_1_RECAL -2 +#define NEED_2_RECAL -3 + +static int usage_count; + +/* buffer related variables */ +static int buffer_track = -1; +static int buffer_drive = -1; +static int buffer_min = -1; +static int buffer_max = -1; + +/* fdc related variables, should end up in a struct */ +static struct floppy_fdc_state fdc_state[N_FDC]; +static int fdc; /* current fdc */ + +static struct floppy_struct *_floppy = floppy_type; +static unsigned char current_drive; +static long current_count_sectors; +static unsigned char fsector_t; /* sector in track */ +static unsigned char in_sector_offset; /* offset within physical sector, + * expressed in units of 512 bytes */ + +#ifndef fd_eject +static inline int fd_eject(int drive) +{ + return -EINVAL; +} +#endif + +#ifdef DEBUGT +static long unsigned debugtimer; +#endif + +/* + * Debugging + * ========= + */ +static inline void set_debugt(void) +{ +#ifdef DEBUGT + debugtimer = jiffies; +#endif +} + +static inline void debugt(const char *message) +{ +#ifdef DEBUGT + if (DP->flags & DEBUGT) + printk("%s dtime=%lu\n", message, jiffies-debugtimer); +#endif +} + +typedef void (*timeout_fn)(unsigned long); +static struct timer_list fd_timeout ={ function: (timeout_fn) floppy_shutdown }; + +static const char *timeout_message; + +#ifdef FLOPPY_SANITY_CHECK +static void is_alive(const char *message) +{ + /* this routine checks whether the floppy driver is "alive" */ + if (fdc_busy && command_status < 2 && !timer_pending(&fd_timeout)){ + DPRINT("timeout handler died: %s\n",message); + } +} +#endif + +static void (*do_floppy)(void) = NULL; + +#ifdef FLOPPY_SANITY_CHECK + +#define OLOGSIZE 20 + +static void (*lasthandler)(void); +static unsigned long interruptjiffies; +static unsigned long resultjiffies; +static int resultsize; +static unsigned long lastredo; + +static struct output_log { + unsigned char data; + unsigned char status; + unsigned long jiffies; +} output_log[OLOGSIZE]; + +static int output_log_pos; +#endif + +#define current_reqD -1 +#define MAXTIMEOUT -2 + +static void reschedule_timeout(int drive, const char *message, int marg) +{ + if (drive == current_reqD) + drive = current_drive; + del_timer(&fd_timeout); + if (drive < 0 || drive > N_DRIVE) { + fd_timeout.expires = jiffies + 20UL*HZ; + drive=0; + } else + fd_timeout.expires = jiffies + UDP->timeout; + add_timer(&fd_timeout); + if (UDP->flags & FD_DEBUG){ + DPRINT("reschedule timeout "); + printk(message, marg); + printk("\n"); + } + timeout_message = message; +} + +static int maximum(int a, int b) +{ + if (a > b) + return a; + else + return b; +} +#define INFBOUND(a,b) (a)=maximum((a),(b)); + +static int minimum(int a, int b) +{ + if (a < b) + return a; + else + return b; +} +#define SUPBOUND(a,b) (a)=minimum((a),(b)); + + +/* + * Bottom half floppy driver. + * ========================== + * + * This part of the file contains the code talking directly to the hardware, + * and also the main service loop (seek-configure-spinup-command) + */ + +/* + * disk change. + * This routine is responsible for maintaining the FD_DISK_CHANGE flag, + * and the last_checked date. + * + * last_checked is the date of the last check which showed 'no disk change' + * FD_DISK_CHANGE is set under two conditions: + * 1. The floppy has been changed after some i/o to that floppy already + * took place. + * 2. No floppy disk is in the drive. This is done in order to ensure that + * requests are quickly flushed in case there is no disk in the drive. It + * follows that FD_DISK_CHANGE can only be cleared if there is a disk in + * the drive. + * + * For 1., maxblock is observed. Maxblock is 0 if no i/o has taken place yet. + * For 2., FD_DISK_NEWCHANGE is watched. FD_DISK_NEWCHANGE is cleared on + * each seek. If a disk is present, the disk change line should also be + * cleared on each seek. Thus, if FD_DISK_NEWCHANGE is clear, but the disk + * change line is set, this means either that no disk is in the drive, or + * that it has been removed since the last seek. + * + * This means that we really have a third possibility too: + * The floppy has been changed after the last seek. + */ + +static int disk_change(int drive) +{ + return UTESTF(FD_DISK_CHANGED); +} + +static int set_mode(char mask, char data) +{ + register unsigned char newdor, olddor; + + olddor = FDCS->dor; + newdor = (olddor & mask) | data; + if (newdor != olddor) { + FDCS->dor = newdor; + fd_outb(newdor, FD_MODE); + } + + if (newdor & FLOPPY_MOTOR_MASK) + floppy_grab_irq_and_dma(); + + if (olddor & FLOPPY_MOTOR_MASK) + floppy_release_irq_and_dma(); + + return olddor; +} + +static void twaddle(void) +{ + if (DP->select_delay) + return; + + fd_outb(FDCS->dor & 0xf7, FD_MODE); + fd_outb(FDCS->dor, FD_MODE); + DRS->select_date = jiffies; +} + +/* reset all driver information about the current fdc. This is needed after + * a reset, and after a raw command. */ +static void reset_fdc_info(int mode) +{ + int drive; + + FDCS->spec1 = FDCS->spec2 = -1; + FDCS->need_configure = 1; + FDCS->perp_mode = 1; + FDCS->rawcmd = 0; + for (drive = 0; drive < N_DRIVE; drive++) + if (FDC(drive) == fdc && + (mode || UDRS->track != NEED_1_RECAL)) + UDRS->track = NEED_2_RECAL; +} + +/* selects the fdc and drive, and enables the fdc's input/dma. */ +static void set_fdc(int drive) +{ + fdc = 0; + current_drive = drive; + set_mode(~0, 0x10); + if (FDCS->rawcmd == 2) + reset_fdc_info(1); + + if (fd_inb(FD_STATUS) != STATUS_READY) + FDCS->reset = 1; +} + +/* locks the driver */ +static int _lock_fdc(int drive, int interruptible, int line) +{ + if (!usage_count){ + printk(KERN_ERR "Trying to lock fdc while usage count=0 at line %d\n", line); + return -1; + } + if(floppy_grab_irq_and_dma()==-1) + return -EBUSY; + + if (test_and_set_bit(0, &fdc_busy)) { + DECLARE_WAITQUEUE(wait, current); + add_wait_queue(&fdc_wait, &wait); + + for (;;) { + set_current_state(TASK_INTERRUPTIBLE); + + if (!test_and_set_bit(0, &fdc_busy)) + break; + + schedule(); + + if (!NO_SIGNAL) { + remove_wait_queue(&fdc_wait, &wait); + return -EINTR; + } + } + + set_current_state(TASK_RUNNING); + remove_wait_queue(&fdc_wait, &wait); + } + command_status = FD_COMMAND_NONE; + + reschedule_timeout(drive, "lock fdc", 0); + set_fdc(drive); + return 0; +} + +#define lock_fdc(drive,interruptible) _lock_fdc(drive,interruptible, __LINE__) + +#define LOCK_FDC(drive,interruptible) \ +if (lock_fdc(drive,interruptible)) return -EINTR; + + +/* unlocks the driver */ +static inline void unlock_fdc(void) +{ + raw_cmd = 0; + if (!fdc_busy) + DPRINT("FDC access conflict!\n"); + + if (do_floppy) + DPRINT("device interrupt still active at FDC release: %p!\n", + do_floppy); + command_status = FD_COMMAND_NONE; + del_timer(&fd_timeout); + cont = NULL; + clear_bit(0, &fdc_busy); + floppy_release_irq_and_dma(); + wake_up(&fdc_wait); +} + +#ifndef CONFIG_PC9800_MOTOR_OFF /* tomita */ + +/* switches the motor off after a given timeout */ +static void motor_off_callback(unsigned long nr) +{ + printk(KERN_DEBUG "fdc%lu: turn off motor\n", nr); +} + +/* schedules motor off */ +static void floppy_off(unsigned int drive) +{ +} + +#else /* CONFIG_PC9800_MOTOR_OFF */ + +/* switches the motor off after a given timeout */ +static void motor_off_callback(unsigned long fdc) +{ + printk(KERN_DEBUG "fdc%u: turn off motor\n", (unsigned int) fdc); + + fd_outb(0, FD_MODE); /* MTON = 0 */ +} + +static struct timer_list motor_off_timer[N_FDC] = { + { data: 0, function: motor_off_callback }, +#if N_FDC > 1 + { data: 1, function: motor_off_callback }, +#endif +#if N_FDC > 2 +# error "N_FDC > 2; please fix initializer for motor_off_timer[]" +#endif +}; + +/* schedules motor off */ +static void floppy_off(unsigned int drive) +{ + unsigned long volatile delta; + register int fdc = FDC(drive); + + if (!(FDCS->dor & (0x10 << UNIT(drive)))) + return; + + del_timer(motor_off_timer + fdc); + +#if 0 + /* make spindle stop in a position which minimizes spinup time + * next time */ + if (UDP->rps){ + delta = jiffies - UDRS->first_read_date + HZ - + UDP->spindown_offset; + delta = ((delta * UDP->rps) % HZ) / UDP->rps; + motor_off_timer[drive].expires = jiffies + UDP->spindown - delta; + } +#else + if (UDP->rps) + motor_off_timer[drive].expires = jiffies + UDP->spindown; +#endif + + add_timer(motor_off_timer + fdc); +} + +#endif /* CONFIG_PC9800_MOTOR_OFF */ + +/* + * cycle through all N_DRIVE floppy drives, for disk change testing. + * stopping at current drive. This is done before any long operation, to + * be sure to have up to date disk change information. + */ +static void scandrives(void) +{ + int i, drive, saved_drive; + + if (DP->select_delay) + return; + + saved_drive = current_drive; + for (i=0; i < N_DRIVE; i++){ + drive = (saved_drive + i + 1) % N_DRIVE; + if (UDRS->fd_ref == 0 || UDP->select_delay != 0) + continue; /* skip closed drives */ + set_fdc(drive); + } + set_fdc(saved_drive); +} + +static void empty(void) +{ +} + +static DECLARE_WORK(floppy_work, NULL, NULL); + +static void schedule_bh( void (*handler)(void*) ) +{ + PREPARE_WORK(&floppy_work, handler, NULL); + schedule_work(&floppy_work); +} + +static struct timer_list fd_timer; + +static void cancel_activity(void) +{ + do_floppy = NULL; + PREPARE_WORK(&floppy_work, (void*)(void*)empty, NULL); + del_timer(&fd_timer); +} + +/* this function makes sure that the disk stays in the drive during the + * transfer */ +static void fd_watchdog(void) +{ +#ifdef DCL_DEBUG + if (DP->flags & FD_DEBUG){ + DPRINT("calling disk change from watchdog\n"); + } +#endif + + if (disk_change(current_drive)){ + DPRINT("disk removed during i/o\n"); + cancel_activity(); + cont->done(0); + reset_fdc(); + } else { + del_timer(&fd_timer); + fd_timer.function = (timeout_fn) fd_watchdog; + fd_timer.expires = jiffies + HZ / 10; + add_timer(&fd_timer); + } +} + +static void main_command_interrupt(void) +{ + del_timer(&fd_timer); + cont->interrupt(); +} + +/* waits for a delay (spinup or select) to pass */ +static int fd_wait_for_completion(unsigned long delay, timeout_fn function) +{ + if (FDCS->reset){ + reset_fdc(); /* do the reset during sleep to win time + * if we don't need to sleep, it's a good + * occasion anyways */ + return 1; + } + + if ((signed) (jiffies - delay) < 0){ + del_timer(&fd_timer); + fd_timer.function = function; + fd_timer.expires = delay; + add_timer(&fd_timer); + return 1; + } + return 0; +} + +static spinlock_t floppy_hlt_lock = SPIN_LOCK_UNLOCKED; +static int hlt_disabled; +static void floppy_disable_hlt(void) +{ + unsigned long flags; + + spin_lock_irqsave(&floppy_hlt_lock, flags); + if (!hlt_disabled) { + hlt_disabled=1; +#ifdef HAVE_DISABLE_HLT + disable_hlt(); +#endif + } + spin_unlock_irqrestore(&floppy_hlt_lock, flags); +} + +static void floppy_enable_hlt(void) +{ + unsigned long flags; + + spin_lock_irqsave(&floppy_hlt_lock, flags); + if (hlt_disabled){ + hlt_disabled=0; +#ifdef HAVE_DISABLE_HLT + enable_hlt(); +#endif + } + spin_unlock_irqrestore(&floppy_hlt_lock, flags); +} + + +static void setup_DMA(void) +{ + unsigned long f; + +#ifdef FLOPPY_SANITY_CHECK + if (raw_cmd->length == 0){ + int i; + + printk("zero dma transfer size:"); + for (i=0; i < raw_cmd->cmd_count; i++) + printk("%x,", raw_cmd->cmd[i]); + printk("\n"); + cont->done(0); + FDCS->reset = 1; + return; + } + if (((unsigned long) raw_cmd->kernel_data) % 512){ + printk("non aligned address: %p\n", raw_cmd->kernel_data); + cont->done(0); + FDCS->reset=1; + return; + } +#endif + f=claim_dma_lock(); + fd_disable_dma(); +#ifdef fd_dma_setup + if (fd_dma_setup(raw_cmd->kernel_data, raw_cmd->length, + (raw_cmd->flags & FD_RAW_READ)? + DMA_MODE_READ : DMA_MODE_WRITE, + FDCS->address) < 0) { + release_dma_lock(f); + cont->done(0); + FDCS->reset=1; + return; + } + release_dma_lock(f); +#else + fd_clear_dma_ff(); + fd_cacheflush(raw_cmd->kernel_data, raw_cmd->length); + fd_set_dma_mode((raw_cmd->flags & FD_RAW_READ)? + DMA_MODE_READ : DMA_MODE_WRITE); + fd_set_dma_addr(raw_cmd->kernel_data); + fd_set_dma_count(raw_cmd->length); + virtual_dma_port = FDCS->address; + fd_enable_dma(); + release_dma_lock(f); +#endif + floppy_disable_hlt(); +} + +static void show_floppy(void); + +/* waits until the fdc becomes ready */ + +#ifdef PC9800_DEBUG_FLOPPY +#define READY_DELAY 10000000 +#else +#define READY_DELAY 100000 +#endif + +static int wait_til_ready(void) +{ + int counter, status; + if (FDCS->reset) + return -1; + for (counter = 0; counter < READY_DELAY; counter++) { + status = fd_inb(FD_STATUS); + if (status & STATUS_READY) + return status; + } + if (!initialising) { + DPRINT("Getstatus times out (%x) on fdc %d\n", + status, fdc); + show_floppy(); + } + FDCS->reset = 1; + return -1; +} + +/* sends a command byte to the fdc */ +static int output_byte(char byte) +{ + int status; + + if ((status = wait_til_ready()) < 0) + return -1; + if ((status & (STATUS_READY|STATUS_DIR|STATUS_DMA)) == STATUS_READY){ + fd_outb(byte,FD_DATA); +#ifdef FLOPPY_SANITY_CHECK + output_log[output_log_pos].data = byte; + output_log[output_log_pos].status = status; + output_log[output_log_pos].jiffies = jiffies; + output_log_pos = (output_log_pos + 1) % OLOGSIZE; +#endif + return 0; + } + FDCS->reset = 1; + if (!initialising) { + DPRINT("Unable to send byte %x to FDC. Fdc=%x Status=%x\n", + byte, fdc, status); + show_floppy(); + } + return -1; +} +#define LAST_OUT(x) if (output_byte(x)<0){ reset_fdc();return;} + +/* gets the response from the fdc */ +static int result(void) +{ + int i, status=0; + + for(i=0; i < MAX_REPLIES; i++) { + if ((status = wait_til_ready()) < 0) + break; + status &= STATUS_DIR|STATUS_READY|STATUS_BUSY|STATUS_DMA; + if ((status & ~STATUS_BUSY) == STATUS_READY){ +#ifdef FLOPPY_SANITY_CHECK + resultjiffies = jiffies; + resultsize = i; +#endif + return i; + } + if (status == (STATUS_DIR|STATUS_READY|STATUS_BUSY)) + reply_buffer[i] = fd_inb(FD_DATA); + else + break; + } + if (!initialising) { + DPRINT("get result error. Fdc=%d Last status=%x Read bytes=%d\n", + fdc, status, i); + show_floppy(); + } + FDCS->reset = 1; + return -1; +} + +static int fifo_depth = 0xa; +static int no_fifo; + +#define NOMINAL_DTR 500 + +/* Issue a "SPECIFY" command to set the step rate time, head unload time, + * head load time, and DMA disable flag to values needed by floppy. + * + * The value "dtr" is the data transfer rate in Kbps. It is needed + * to account for the data rate-based scaling done by the 82072 and 82077 + * FDC types. This parameter is ignored for other types of FDCs (i.e. + * 8272a). + * + * Note that changing the data transfer rate has a (probably deleterious) + * effect on the parameters subject to scaling for 82072/82077 FDCs, so + * fdc_specify is called again after each data transfer rate + * change. + * + * srt: 1000 to 16000 in microseconds + * hut: 16 to 240 milliseconds + * hlt: 2 to 254 milliseconds + * + * These values are rounded up to the next highest available delay time. + */ +static void fdc_specify(void) +{ + output_byte(FD_SPECIFY); + output_byte(FDCS->spec1 = 0xdf); + output_byte(FDCS->spec2 = 0x24); +} + +static void tell_sector(void) +{ + printk(": track %d, head %d, sector %d, size %d", + R_TRACK, R_HEAD, R_SECTOR, R_SIZECODE); +} /* tell_sector */ + +static int auto_detect_mode_pc9800(void) +{ +#ifdef PC9800_DEBUG_FLOPPY + printk("auto_detect_mode_pc9800: retry_auto_detect=%d\n", + retry_auto_detect); +#endif + if (retry_auto_detect > 4) { + retry_auto_detect = 0; + return 1; + } + + switch ((int)(_floppy - floppy_type)) { + case 2: + _floppy = floppy_type + 4; + break; + + case 4: + case 6: + _floppy = floppy_type + 7; + break; + + case 7: + case 10: + _floppy = floppy_type + 2; + break; + + default: + _floppy = floppy_type + 7; + } + + retry_auto_detect++; + return 0; +} + +static void access_mode_change_pc9800(void); + +/* + * OK, this error interpreting routine is called after a + * DMA read/write has succeeded + * or failed, so we check the results, and copy any buffers. + * hhb: Added better error reporting. + * ak: Made this into a separate routine. + */ +static int interpret_errors(void) +{ + char bad; + + if (inr!=7) { + DPRINT("-- FDC reply error"); + FDCS->reset = 1; + return 1; + } + + /* check IC to find cause of interrupt */ + switch (ST0 & ST0_INTR) { + case 0x40: /* error occurred during command execution */ + if (ST1 & ST1_EOC) + return 0; /* occurs with pseudo-DMA */ + bad = 1; + if (ST1 & ST1_WP) { + DPRINT("Drive is write protected\n"); + CLEARF(FD_DISK_WRITABLE); + cont->done(0); + bad = 2; + } else if (ST1 & ST1_ND) { + SETF(FD_NEED_TWADDLE); + } else if (ST1 & ST1_OR) { + if (DP->flags & FTD_MSG) + DPRINT("Over/Underrun - retrying\n"); + bad = 0; + }else if (*errors >= DP->max_errors.reporting){ + if (ST0 & ST0_ECE) { + printk("Recalibrate failed!"); + } else if (ST2 & ST2_CRC) { + printk("data CRC error"); + tell_sector(); + } else if (ST1 & ST1_CRC) { + printk("CRC error"); + tell_sector(); + } else if ((ST1 & (ST1_MAM|ST1_ND)) || (ST2 & ST2_MAM)) { + if (auto_detect_mode) { + bad = (char)auto_detect_mode_pc9800(); + access_mode_change_pc9800(); + } + + if (bad) { + printk("floppy error: MA: _floppy - floppy_type=%d\n", (int)(_floppy - floppy_type)); + printk("bad=%d\n", (int)bad); + if (!probing) { + printk("sector not found"); + tell_sector(); + } else + printk("probe failed..."); + } + } else if (ST2 & ST2_WC) { /* seek error */ + printk("wrong cylinder"); + } else if (ST2 & ST2_BC) { /* cylinder marked as bad */ + printk("bad cylinder"); + } else { + printk("unknown error. ST[0..2] are: 0x%x 0x%x 0x%x", ST0, ST1, ST2); + tell_sector(); + } + printk("\n"); + + } + if (ST2 & ST2_WC || ST2 & ST2_BC) + /* wrong cylinder => recal */ + DRS->track = NEED_2_RECAL; + return bad; + case 0x80: /* invalid command given */ + DPRINT("Invalid FDC command given!\n"); + cont->done(0); + return 2; + case 0xc0: + SETF(FD_DISK_CHANGED); + SETF(FD_DISK_WRITABLE); + DPRINT("Abnormal termination caused by polling\n"); + cont->error(); + return 2; + default: /* (0) Normal command termination */ + auto_detect_mode = 0; + return 0; + } +} + +/* + * This routine is called when everything should be correctly set up + * for the transfer (i.e. floppy motor is on, the correct floppy is + * selected, and the head is sitting on the right track). + */ +static void setup_rw_floppy(void) +{ + int i,r, flags,dflags; + unsigned long ready_date; + timeout_fn function; + + access_mode_change_pc9800(); + flags = raw_cmd->flags; + if (flags & (FD_RAW_READ | FD_RAW_WRITE)) + flags |= FD_RAW_INTR; + + if ((flags & FD_RAW_SPIN) && !(flags & FD_RAW_NO_MOTOR)){ + ready_date = DRS->spinup_date + DP->spinup; + /* If spinup will take a long time, rerun scandrives + * again just before spinup completion. Beware that + * after scandrives, we must again wait for selection. + */ + if ((signed) (ready_date - jiffies) > DP->select_delay){ + ready_date -= DP->select_delay; + function = (timeout_fn) floppy_start; + } else + function = (timeout_fn) setup_rw_floppy; + + /* wait until the floppy is spinning fast enough */ + if (fd_wait_for_completion(ready_date,function)) + return; + } + dflags = DRS->flags; + + if ((flags & FD_RAW_READ) || (flags & FD_RAW_WRITE)) + setup_DMA(); + + if (flags & FD_RAW_INTR) + do_floppy = main_command_interrupt; + + r=0; + for (i=0; i< raw_cmd->cmd_count; i++) + r|=output_byte(raw_cmd->cmd[i]); + +#ifdef DEBUGT + debugt("rw_command: "); +#endif + if (r){ + cont->error(); + reset_fdc(); + return; + } + + if (!(flags & FD_RAW_INTR)){ + inr = result(); + cont->interrupt(); + } else if (flags & FD_RAW_NEED_DISK) + fd_watchdog(); +} + +static int blind_seek; + +/* + * This is the routine called after every seek (or recalibrate) interrupt + * from the floppy controller. + */ +static void seek_interrupt(void) +{ +#ifdef DEBUGT + debugt("seek interrupt:"); +#endif + if (inr != 2 || (ST0 & 0xF8) != 0x20) { + DRS->track = NEED_2_RECAL; + cont->error(); + cont->redo(); + return; + } + if (DRS->track >= 0 && DRS->track != ST1 && !blind_seek){ +#ifdef DCL_DEBUG + if (DP->flags & FD_DEBUG){ + DPRINT("clearing NEWCHANGE flag because of effective seek\n"); + DPRINT("jiffies=%lu\n", jiffies); + } +#endif + CLEARF(FD_DISK_NEWCHANGE); /* effective seek */ + CLEARF(FD_DISK_CHANGED); /* effective seek */ + DRS->select_date = jiffies; + } + DRS->track = ST1; + floppy_ready(); +} + +static void check_wp(void) +{ + if (TESTF(FD_VERIFY)) { + /* check write protection */ + output_byte(FD_GETSTATUS); + output_byte(UNIT(current_drive)); + if (result() != 1){ + FDCS->reset = 1; + return; + } + CLEARF(FD_VERIFY); + CLEARF(FD_NEED_TWADDLE); +#ifdef DCL_DEBUG + if (DP->flags & FD_DEBUG){ + DPRINT("checking whether disk is write protected\n"); + DPRINT("wp=%x\n",ST3 & 0x40); + } +#endif + if (!(ST3 & 0x40)) + SETF(FD_DISK_WRITABLE); + else + CLEARF(FD_DISK_WRITABLE); + } +} + +static void seek_floppy(void) +{ + int track; + + blind_seek=0; + +#ifdef DCL_DEBUG + if (DP->flags & FD_DEBUG){ + DPRINT("calling disk change from seek\n"); + } +#endif + + if (!TESTF(FD_DISK_NEWCHANGE) && + disk_change(current_drive) && + (raw_cmd->flags & FD_RAW_NEED_DISK)){ + /* the media changed flag should be cleared after the seek. + * If it isn't, this means that there is really no disk in + * the drive. + */ + SETF(FD_DISK_CHANGED); + cont->done(0); + cont->redo(); + return; + } + if (DRS->track <= NEED_1_RECAL){ + recalibrate_floppy(); + return; + } else if (TESTF(FD_DISK_NEWCHANGE) && + (raw_cmd->flags & FD_RAW_NEED_DISK) && + (DRS->track <= NO_TRACK || DRS->track == raw_cmd->track)) { + /* we seek to clear the media-changed condition. Does anybody + * know a more elegant way, which works on all drives? */ + if (raw_cmd->track) + track = raw_cmd->track - 1; + else { + if (DP->flags & FD_SILENT_DCL_CLEAR){ + blind_seek = 1; + raw_cmd->flags |= FD_RAW_NEED_SEEK; + } + track = 1; + } + } else { + check_wp(); + if (raw_cmd->track != DRS->track && + (raw_cmd->flags & FD_RAW_NEED_SEEK)) + track = raw_cmd->track; + else { + setup_rw_floppy(); + return; + } + } + + do_floppy = seek_interrupt; + output_byte(FD_SEEK); + output_byte(UNIT(current_drive)); + LAST_OUT(track); +#ifdef DEBUGT + debugt("seek command:"); +#endif +} + +static void recal_interrupt(void) +{ +#ifdef DEBUGT + debugt("recal interrupt:"); +#endif + if (inr !=2) + FDCS->reset = 1; + else if (ST0 & ST0_ECE) { + switch(DRS->track){ + case NEED_1_RECAL: +#ifdef DEBUGT + debugt("recal interrupt need 1 recal:"); +#endif + /* after a second recalibrate, we still haven't + * reached track 0. Probably no drive. Raise an + * error, as failing immediately might upset + * computers possessed by the Devil :-) */ + cont->error(); + cont->redo(); + return; + case NEED_2_RECAL: +#ifdef DEBUGT + debugt("recal interrupt need 2 recal:"); +#endif + /* If we already did a recalibrate, + * and we are not at track 0, this + * means we have moved. (The only way + * not to move at recalibration is to + * be already at track 0.) Clear the + * new change flag */ +#ifdef DCL_DEBUG + if (DP->flags & FD_DEBUG){ + DPRINT("clearing NEWCHANGE flag because of second recalibrate\n"); + } +#endif + + CLEARF(FD_DISK_NEWCHANGE); + DRS->select_date = jiffies; + /* fall through */ + default: +#ifdef DEBUGT + debugt("recal interrupt default:"); +#endif + /* Recalibrate moves the head by at + * most 80 steps. If after one + * recalibrate we don't have reached + * track 0, this might mean that we + * started beyond track 80. Try + * again. */ + DRS->track = NEED_1_RECAL; + break; + } + } else + DRS->track = ST1; + floppy_ready(); +} + +static void print_result(char *message, int inr) +{ + int i; + + DPRINT("%s ", message); + if (inr >= 0) + for (i=0; i= N_FDC || FDCS->address == -1){ + /* we don't even know which FDC is the culprit */ + printk("DOR0=%x\n", fdc_state[0].dor); + printk("floppy interrupt on bizarre fdc %d\n",fdc); + printk("handler=%p\n", handler); + is_alive("bizarre fdc"); + return; + } + + FDCS->reset = 0; + /* We have to clear the reset flag here, because apparently on boxes + * with level triggered interrupts (PS/2, Sparc, ...), it is needed to + * emit SENSEI's to clear the interrupt line. And FDCS->reset blocks the + * emission of the SENSEI's. + * It is OK to emit floppy commands because we are in an interrupt + * handler here, and thus we have to fear no interference of other + * activity. + */ + + do_print = !handler && !initialising; + + inr = result(); + if (inr && do_print) + print_result("unexpected interrupt", inr); + if (inr == 0){ + do { + output_byte(FD_SENSEI); + inr = result(); + if ((ST0 & ST0_INTR) == 0xC0) { + int drive = ST0 & ST0_DS; + + /* Attention Interrupt. */ + if (ST0 & ST0_NR) { +#ifdef PC9800_DEBUG_FLOPPY + if (do_print) + printk(KERN_DEBUG + "floppy debug: floppy ejected (drive %d)\n", + drive); +#endif + USETF(FD_DISK_CHANGED); + USETF(FD_VERIFY); + } else { +#ifdef PC9800_DEBUG_FLOPPY + if (do_print) + printk(KERN_DEBUG + "floppy debug: floppy inserted (drive %d)\n", + drive); +#endif + } + } /* Attention Interrupt */ +#ifdef PC9800_DEBUG_FLOPPY + else { + printk(KERN_DEBUG + "floppy debug : unknown interrupt\n"); + } +#endif + } while ((ST0 & 0x83) != UNIT(current_drive) && inr == 2); + } + if (handler) { + schedule_bh( (void *)(void *) handler); + } else { +#if 0 + FDCS->reset = 1; +#endif + } + is_alive("normal interrupt end"); +} + +static void recalibrate_floppy(void) +{ +#ifdef DEBUGT + debugt("recalibrate floppy:"); +#endif + do_floppy = recal_interrupt; + output_byte(FD_RECALIBRATE); + LAST_OUT(UNIT(current_drive)); +} + +/* + * Must do 4 FD_SENSEIs after reset because of ``drive polling''. + */ +static void reset_interrupt(void) +{ +#ifdef PC9800_DEBUG_FLOPPY + printk("floppy debug: reset interrupt\n"); +#endif +#ifdef DEBUGT + debugt("reset interrupt:"); +#endif + result(); /* get the status ready for set_fdc */ + if (FDCS->reset) { + printk("reset set in interrupt, calling %p\n", cont->error); + cont->error(); /* a reset just after a reset. BAD! */ + } + cont->redo(); +} + +/* + * reset is done by pulling bit 2 of DOR low for a while (old FDCs), + * or by setting the self clearing bit 7 of STATUS (newer FDCs) + */ +static void reset_fdc(void) +{ + unsigned long flags; + +#ifdef PC9800_DEBUG_FLOPPY + printk("floppy debug: reset_fdc\n"); +#endif + + do_floppy = reset_interrupt; + FDCS->reset = 0; + reset_fdc_info(0); + + /* Pseudo-DMA may intercept 'reset finished' interrupt. */ + /* Irrelevant for systems with true DMA (i386). */ + + flags=claim_dma_lock(); + fd_disable_dma(); + release_dma_lock(flags); + + fd_outb(FDCS->dor | 0x80, FD_MODE); + udelay(FD_RESET_DELAY); + fd_outb(FDCS->dor, FD_MODE); + udelay(FD_AFTER_RESET_DELAY); +} + +static void show_floppy(void) +{ + int i; + + printk("\n"); + printk("floppy driver state\n"); + printk("-------------------\n"); + printk("now=%lu last interrupt=%lu diff=%lu last called handler=%p\n", + jiffies, interruptjiffies, jiffies-interruptjiffies, lasthandler); + + +#ifdef FLOPPY_SANITY_CHECK + printk("timeout_message=%s\n", timeout_message); + printk("last output bytes:\n"); + for (i=0; i < OLOGSIZE; i++) + printk("%2x %2x %lu\n", + output_log[(i+output_log_pos) % OLOGSIZE].data, + output_log[(i+output_log_pos) % OLOGSIZE].status, + output_log[(i+output_log_pos) % OLOGSIZE].jiffies); + printk("last result at %lu\n", resultjiffies); + printk("last redo_fd_request at %lu\n", lastredo); + for (i=0; ireset = 1; + if (cont){ + cont->done(0); + cont->redo(); /* this will recall reset when needed */ + } else { + printk("no cont in shutdown!\n"); + process_fd_request(); + } + is_alive("floppy shutdown"); +} +/*typedef void (*timeout_fn)(unsigned long);*/ + +static void access_mode_change_pc9800(void) +{ + static int access_mode, mode_change_now, old_mode, new_set = 1; +#ifdef PC9800_DEBUG_FLOPPY2 + printk("enter access_mode_change\n"); +#endif + access_mode = mode_change_now = 0; + if (DP->cmos==4) { + switch ((int)(_floppy - &floppy_type[0])) { + case 1: + case 2: + new_set = 1; + access_mode = 2; + break; + + case 4: + case 6: + new_set = 1; + access_mode = 3; + break; + + case 7: + case 10: + new_set = 1; + access_mode = 1; + break; + + default: + access_mode = 1; + break; + } + + old_mode = fd_inb(FD_MODE_CHANGE) & 3; + + switch (access_mode) { + case 1: + if ((old_mode & 2) == 0) { + fd_outb(old_mode | 2, FD_MODE_CHANGE); + mode_change_now = 1; + } else { + fd_outb(current_drive << 5, FD_EMODE_CHANGE); + if (fd_inb(FD_EMODE_CHANGE) == 0xff) + return; + } + + fd_outb((current_drive << 5) | 0x11, FD_EMODE_CHANGE); + mode_change_now = 1; + break; + + case 2: + if ((old_mode & 2) == 0) { + fd_outb(old_mode | 2, FD_MODE_CHANGE); + mode_change_now = 1; + } else { + fd_outb(current_drive << 5, FD_EMODE_CHANGE); + if ((fd_inb(FD_EMODE_CHANGE) & 1) == 0) + return; + fd_outb((current_drive << 5) | 0x10, FD_EMODE_CHANGE); + mode_change_now = 1; + } + + break; + + case 3: + if ((old_mode & 2) == 0) + return; + fd_outb(current_drive << 5, FD_EMODE_CHANGE); + if (fd_inb(FD_EMODE_CHANGE) & 1) + fd_outb((current_drive << 5) | 0x10, FD_EMODE_CHANGE); + fd_outb(old_mode & 0xfd, FD_MODE_CHANGE); + mode_change_now = 1; + break; + + default: + break; + } + } else { + switch ((int)(_floppy - &floppy_type[0])) { + case 1: + case 2: + new_set = 1; + access_mode = 2; + break; + + case 4: + case 6: + new_set = 1; + access_mode = 3; + break; + + default: + switch (DP->cmos) { + case 2: + access_mode = 2; + break; + + case 3: + access_mode = 3; + break; + + default: + break; + } + + break; + } + + old_mode = fd_inb(FD_MODE_CHANGE) & 3; + + switch (access_mode) { + case 2: + if ((old_mode & 2) == 0) { + fd_outb(old_mode | 2, FD_MODE_CHANGE); + mode_change_now = 1; + } + + break; + + case 3: + if (old_mode & 2) { + fd_outb(old_mode & 0xfd, FD_MODE_CHANGE); + mode_change_now = 1; + } + + break; + + default: + break; + } + } +#ifdef PC9800_DEBUG_FLOPPY2 + printk("floppy debug: DP->cmos=%d\n", DP->cmos); + printk("floppy debug: mode_change_now=%d\n", mode_change_now); + printk("floppy debug: access_mode=%d\n", access_mode); + printk("floppy debug: old_mode=%d\n", old_mode); + printk("floppy debug: _floppy - &floppy_type[0]=%d\n", (int)(_floppy - &floppy_type[0])); +#endif /* PC9800_DEBUG_FLOPPY2 */ + if(mode_change_now) + reset_fdc(); +} + +/* start motor, check media-changed condition and write protection */ +static int start_motor(void (*function)(void) ) +{ + access_mode_change_pc9800(); + set_mode(~0, 0x8); + + /* wait_for_completion also schedules reset if needed. */ + return(fd_wait_for_completion(DRS->select_date+DP->select_delay, + (timeout_fn) function)); +} + +static void floppy_ready(void) +{ + CHECK_RESET; + if (start_motor(floppy_ready)) return; + +#ifdef DCL_DEBUG + if (DP->flags & FD_DEBUG){ + DPRINT("calling disk change from floppy_ready\n"); + } +#endif + if (!(raw_cmd->flags & FD_RAW_NO_MOTOR) && + disk_change(current_drive) && + !DP->select_delay) + twaddle(); /* this clears the dcl on certain drive/controller + * combinations */ + +#ifdef fd_chose_dma_mode + if ((raw_cmd->flags & FD_RAW_READ) || + (raw_cmd->flags & FD_RAW_WRITE)) + { + unsigned long flags = claim_dma_lock(); + fd_chose_dma_mode(raw_cmd->kernel_data, + raw_cmd->length); + release_dma_lock(flags); + } +#endif + +#if 0 + access_mode_change_pc9800(); +#endif + if (raw_cmd->flags & (FD_RAW_NEED_SEEK | FD_RAW_NEED_DISK)){ + fdc_specify(); /* must be done here because of hut, hlt ... */ + seek_floppy(); + } else { + if ((raw_cmd->flags & FD_RAW_READ) || + (raw_cmd->flags & FD_RAW_WRITE)) + fdc_specify(); + setup_rw_floppy(); + } +} + +static void floppy_start(void) +{ + reschedule_timeout(current_reqD, "floppy start", 0); + + scandrives(); +#ifdef DCL_DEBUG + if (DP->flags & FD_DEBUG){ + DPRINT("setting NEWCHANGE in floppy_start\n"); + } +#endif + SETF(FD_DISK_NEWCHANGE); + floppy_ready(); +} + +/* + * ======================================================================== + * here ends the bottom half. Exported routines are: + * floppy_start, floppy_off, floppy_ready, lock_fdc, unlock_fdc, set_fdc, + * start_motor, reset_fdc, reset_fdc_info, interpret_errors. + * Initialization also uses output_byte, result, set_dor, floppy_interrupt + * and set_dor. + * ======================================================================== + */ +/* + * General purpose continuations. + * ============================== + */ + +static void do_wakeup(void) +{ + reschedule_timeout(MAXTIMEOUT, "do wakeup", 0); + cont = 0; + command_status += 2; + wake_up(&command_done); +} + +static struct cont_t wakeup_cont={ + empty, + do_wakeup, + empty, + (done_f)empty +}; + + +static struct cont_t intr_cont={ + empty, + process_fd_request, + empty, + (done_f) empty +}; + +static int wait_til_done(void (*handler)(void), int interruptible) +{ + int ret; + + schedule_bh((void *)(void *)handler); + + if (command_status < 2 && NO_SIGNAL) { + DECLARE_WAITQUEUE(wait, current); + + add_wait_queue(&command_done, &wait); + for (;;) { + set_current_state(interruptible? + TASK_INTERRUPTIBLE: + TASK_UNINTERRUPTIBLE); + + if (command_status >= 2 || !NO_SIGNAL) + break; + + is_alive("wait_til_done"); + + schedule(); + } + + set_current_state(TASK_RUNNING); + remove_wait_queue(&command_done, &wait); + } + + if (command_status < 2){ + cancel_activity(); + cont = &intr_cont; + reset_fdc(); + return -EINTR; + } + +#ifdef PC9800_DEBUG_FLOPPY + if (command_status != FD_COMMAND_OKAY) + printk("floppy check: wait_til_done out:%d\n", command_status); +#endif + if (FDCS->reset) + command_status = FD_COMMAND_ERROR; + if (command_status == FD_COMMAND_OKAY) + ret=0; + else + ret=-EIO; + command_status = FD_COMMAND_NONE; + return ret; +} + +static void generic_done(int result) +{ + command_status = result; + cont = &wakeup_cont; +} + +static void generic_success(void) +{ + cont->done(1); +} + +static void generic_failure(void) +{ + cont->done(0); +} + +static void success_and_wakeup(void) +{ + generic_success(); + cont->redo(); +} + + +/* + * formatting and rw support. + * ========================== + */ + +static int next_valid_format(void) +{ + int probed_format; + + probed_format = DRS->probed_format; + while(1){ + if (probed_format >= 8 || + !DP->autodetect[probed_format]){ + DRS->probed_format = 0; + return 1; + } + if (floppy_type[DP->autodetect[probed_format]].sect){ + DRS->probed_format = probed_format; + return 0; + } + probed_format++; + } +} + +static void bad_flp_intr(void) +{ + if (probing){ + DRS->probed_format++; + if (!next_valid_format()) + return; + } + (*errors)++; + INFBOUND(DRWE->badness, *errors); + if (*errors > DP->max_errors.abort) + cont->done(0); + if (*errors > DP->max_errors.reset) + FDCS->reset = 1; + else if (*errors > DP->max_errors.recal) + DRS->track = NEED_2_RECAL; +} + +static void set_floppy(kdev_t device) +{ + if (TYPE(device)) { + auto_detect_mode = 0; + _floppy = TYPE(device) + floppy_type; + } else if (auto_detect_mode == 0) { + auto_detect_mode = 1; + retry_auto_detect = 0; + _floppy = current_type[DRIVE(device)]; + } +#ifdef PC9800_DEBUG_FLOPPY2 + printk("set_floppy: set floppy type=%d\n", (int)(_floppy - floppy_type)); +#endif +} + +/* + * formatting support. + * =================== + */ +static void format_interrupt(void) +{ + switch (interpret_errors()){ + case 1: + cont->error(); + case 2: + break; + case 0: + cont->done(1); + } + cont->redo(); +} + +#define CODE2SIZE (ssize = ((1 << SIZECODE) + 3) >> 2) +#define FM_MODE(x,y) ((y) & ~(((x)->rate & 0x80) >>1)) +#define CT(x) ((x) | 0xc0) +static void setup_format_params(int track) +{ + struct fparm { + unsigned char track,head,sect,size; + } *here = (struct fparm *)floppy_track_buffer; + int il,n; + int count,head_shift,track_shift; + + raw_cmd = &default_raw_cmd; + raw_cmd->track = track; + + raw_cmd->flags = FD_RAW_WRITE | FD_RAW_INTR | FD_RAW_SPIN | + FD_RAW_NEED_DISK | FD_RAW_NEED_SEEK; + raw_cmd->rate = _floppy->rate & 0x43; + raw_cmd->cmd_count = NR_F; + COMMAND = FM_MODE(_floppy,FD_FORMAT); + DR_SELECT = UNIT(current_drive) + PH_HEAD(_floppy,format_req.head); + F_SIZECODE = FD_SIZECODE(_floppy); + F_SECT_PER_TRACK = _floppy->sect << 2 >> F_SIZECODE; + F_GAP = _floppy->fmt_gap; + F_FILL = FD_FILL_BYTE; + + raw_cmd->kernel_data = floppy_track_buffer; + raw_cmd->length = 4 * F_SECT_PER_TRACK; + + /* allow for about 30ms for data transport per track */ + head_shift = (F_SECT_PER_TRACK + 5) / 6; + + /* a ``cylinder'' is two tracks plus a little stepping time */ + track_shift = 2 * head_shift + 3; + + /* position of logical sector 1 on this track */ + n = (track_shift * format_req.track + head_shift * format_req.head) + % F_SECT_PER_TRACK; + + /* determine interleave */ + il = 1; + if (_floppy->fmt_gap < 0x22) + il++; + + /* initialize field */ + for (count = 0; count < F_SECT_PER_TRACK; ++count) { + here[count].track = format_req.track; + here[count].head = format_req.head; + here[count].sect = 0; + here[count].size = F_SIZECODE; + } + /* place logical sectors */ + for (count = 1; count <= F_SECT_PER_TRACK; ++count) { + here[n].sect = count; + n = (n+il) % F_SECT_PER_TRACK; + if (here[n].sect) { /* sector busy, find next free sector */ + ++n; + if (n>= F_SECT_PER_TRACK) { + n-=F_SECT_PER_TRACK; + while (here[n].sect) ++n; + } + } + } +} + +static void redo_format(void) +{ + buffer_track = -1; + setup_format_params(format_req.track << STRETCH(_floppy)); + floppy_start(); +#ifdef DEBUGT + debugt("queue format request"); +#endif +} + +static struct cont_t format_cont={ + format_interrupt, + redo_format, + bad_flp_intr, + generic_done }; + +static int do_format(kdev_t device, struct format_descr *tmp_format_req) +{ + int ret; + int drive=DRIVE(device); + + LOCK_FDC(drive,1); + set_floppy(device); + if (!_floppy || + _floppy->track > DP->tracks || + tmp_format_req->track >= _floppy->track || + tmp_format_req->head >= _floppy->head || + (_floppy->sect << 2) % (1 << FD_SIZECODE(_floppy)) || + !_floppy->fmt_gap) { + process_fd_request(); + return -EINVAL; + } + format_req = *tmp_format_req; + format_errors = 0; + cont = &format_cont; + errors = &format_errors; + IWAIT(redo_format); + process_fd_request(); + return ret; +} + +/* + * Buffer read/write and support + * ============================= + */ + +static inline void end_request(struct request *req, int uptodate) +{ + if (end_that_request_first(req, uptodate, current_count_sectors)) + return; + add_blkdev_randomness(MAJOR_NR); + floppy_off((int)req->rq_disk->private_data); + blkdev_dequeue_request(req); + end_that_request_last(req); + + /* We're done with the request */ + current_req = NULL; +} + + +/* new request_done. Can handle physical sectors which are smaller than a + * logical buffer */ +static void request_done(int uptodate) +{ + struct request_queue *q = &floppy_queue; + struct request *req = current_req; + unsigned long flags; + int block; + + probing = 0; + reschedule_timeout(MAXTIMEOUT, "request done %d", uptodate); + + if (!req) { + printk("floppy.c: no request in request_done\n"); + return; + } + + if (uptodate){ + /* maintain values for invalidation on geometry + * change */ + block = current_count_sectors + req->sector; + INFBOUND(DRS->maxblock, block); + if (block > _floppy->sect) + DRS->maxtrack = 1; + + /* unlock chained buffers */ + spin_lock_irqsave(q->queue_lock, flags); + end_request(req, 1); + spin_unlock_irqrestore(q->queue_lock, flags); + } else { + if (rq_data_dir(req) == WRITE) { + /* record write error information */ + DRWE->write_errors++; + if (DRWE->write_errors == 1) { + DRWE->first_error_sector = req->sector; + DRWE->first_error_generation = DRS->generation; + } + DRWE->last_error_sector = req->sector; + DRWE->last_error_generation = DRS->generation; + } + spin_lock_irqsave(q->queue_lock, flags); + end_request(req, 0); + spin_unlock_irqrestore(q->queue_lock, flags); + } +} + +/* Interrupt handler evaluating the result of the r/w operation */ +static void rw_interrupt(void) +{ + int nr_sectors, ssize, eoc, heads; + + if (R_HEAD >= 2) { + /* some Toshiba floppy controllers occasionnally seem to + * return bogus interrupts after read/write operations, which + * can be recognized by a bad head number (>= 2) */ + return; + } + + if (!DRS->first_read_date) + DRS->first_read_date = jiffies; + + nr_sectors = 0; + CODE2SIZE; + + if (ST1 & ST1_EOC) + eoc = 1; + else + eoc = 0; + + if (COMMAND & 0x80) + heads = 2; + else + heads = 1; + + nr_sectors = (((R_TRACK-TRACK) * heads + + R_HEAD-HEAD) * SECT_PER_TRACK + + R_SECTOR-SECTOR + eoc) << SIZECODE >> 2; + +#ifdef FLOPPY_SANITY_CHECK + if (nr_sectors / ssize > + (in_sector_offset + current_count_sectors + ssize - 1) / ssize) { + DPRINT("long rw: %x instead of %lx\n", + nr_sectors, current_count_sectors); + printk("rs=%d s=%d\n", R_SECTOR, SECTOR); + printk("rh=%d h=%d\n", R_HEAD, HEAD); + printk("rt=%d t=%d\n", R_TRACK, TRACK); + printk("heads=%d eoc=%d\n", heads, eoc); + printk("spt=%d st=%d ss=%d\n", SECT_PER_TRACK, + fsector_t, ssize); + printk("in_sector_offset=%d\n", in_sector_offset); + } +#endif + + nr_sectors -= in_sector_offset; + INFBOUND(nr_sectors,0); + SUPBOUND(current_count_sectors, nr_sectors); + + switch (interpret_errors()){ + case 2: + cont->redo(); + return; + case 1: + if (!current_count_sectors){ + cont->error(); + cont->redo(); + return; + } + break; + case 0: + if (!current_count_sectors){ + cont->redo(); + return; + } + current_type[current_drive] = _floppy; + floppy_sizes[TOMINOR(current_drive) ]= _floppy->size; + break; + } + + if (probing) { + if (DP->flags & FTD_MSG) + DPRINT("Auto-detected floppy type %s in fd%d\n", + _floppy->name,current_drive); + current_type[current_drive] = _floppy; + floppy_sizes[TOMINOR(current_drive)] = _floppy->size; + probing = 0; + } + + if (CT(COMMAND) != FD_READ || + raw_cmd->kernel_data == current_req->buffer){ + /* transfer directly from buffer */ + cont->done(1); + } else if (CT(COMMAND) == FD_READ){ + buffer_track = raw_cmd->track; + buffer_drive = current_drive; + INFBOUND(buffer_max, nr_sectors + fsector_t); + } + cont->redo(); +} + +/* Compute maximal contiguous buffer size. */ +static int buffer_chain_size(void) +{ + struct bio *bio; + struct bio_vec *bv; + int size, i; + char *base; + + base = bio_data(current_req->bio); + size = 0; + + rq_for_each_bio(bio, current_req) { + bio_for_each_segment(bv, bio, i) { + if (page_address(bv->bv_page) + bv->bv_offset != base + size) + break; + + size += bv->bv_len; + } + } + + return size >> 9; +} + +/* Compute the maximal transfer size */ +static int transfer_size(int ssize, int max_sector, int max_size) +{ + SUPBOUND(max_sector, fsector_t + max_size); + + /* alignment */ + max_sector -= (max_sector % _floppy->sect) % ssize; + + /* transfer size, beginning not aligned */ + current_count_sectors = max_sector - fsector_t ; + + return max_sector; +} + +/* + * Move data from/to the track buffer to/from the buffer cache. + */ +static void copy_buffer(int ssize, int max_sector, int max_sector_2) +{ + int remaining; /* number of transferred 512-byte sectors */ + struct bio_vec *bv; + struct bio *bio; + char *buffer, *dma_buffer; + int size, i; + + max_sector = transfer_size(ssize, + minimum(max_sector, max_sector_2), + current_req->nr_sectors); + + if (current_count_sectors <= 0 && CT(COMMAND) == FD_WRITE && + buffer_max > fsector_t + current_req->nr_sectors) + current_count_sectors = minimum(buffer_max - fsector_t, + current_req->nr_sectors); + + remaining = current_count_sectors << 9; +#ifdef FLOPPY_SANITY_CHECK + if ((remaining >> 9) > current_req->nr_sectors && + CT(COMMAND) == FD_WRITE){ + DPRINT("in copy buffer\n"); + printk("current_count_sectors=%ld\n", current_count_sectors); + printk("remaining=%d\n", remaining >> 9); + printk("current_req->nr_sectors=%ld\n",current_req->nr_sectors); + printk("current_req->current_nr_sectors=%u\n", + current_req->current_nr_sectors); + printk("max_sector=%d\n", max_sector); + printk("ssize=%d\n", ssize); + } +#endif + + buffer_max = maximum(max_sector, buffer_max); + + dma_buffer = floppy_track_buffer + ((fsector_t - buffer_min) << 9); + + size = current_req->current_nr_sectors << 9; + + rq_for_each_bio(bio, current_req) { + bio_for_each_segment(bv, bio, i) { + if (!remaining) + break; + + size = bv->bv_len; + SUPBOUND(size, remaining); + + buffer = page_address(bv->bv_page) + bv->bv_offset; +#ifdef FLOPPY_SANITY_CHECK + if (dma_buffer + size > + floppy_track_buffer + (max_buffer_sectors << 10) || + dma_buffer < floppy_track_buffer){ + DPRINT("buffer overrun in copy buffer %d\n", + (int) ((floppy_track_buffer - dma_buffer) >>9)); + printk("fsector_t=%d buffer_min=%d\n", + fsector_t, buffer_min); + printk("current_count_sectors=%ld\n", + current_count_sectors); + if (CT(COMMAND) == FD_READ) + printk("read\n"); + if (CT(COMMAND) == FD_READ) + printk("write\n"); + break; + } + if (((unsigned long)buffer) % 512) + DPRINT("%p buffer not aligned\n", buffer); +#endif + if (CT(COMMAND) == FD_READ) + memcpy(buffer, dma_buffer, size); + else + memcpy(dma_buffer, buffer, size); + + remaining -= size; + dma_buffer += size; + } + } +#ifdef FLOPPY_SANITY_CHECK + if (remaining){ + if (remaining > 0) + max_sector -= remaining >> 9; + DPRINT("weirdness: remaining %d\n", remaining>>9); + } +#endif +} + +#if 0 +static inline int check_dma_crossing(char *start, + unsigned long length, char *message) +{ + if (CROSS_64KB(start, length)) { + printk("DMA xfer crosses 64KB boundary in %s %p-%p\n", + message, start, start+length); + return 1; + } else + return 0; +} +#endif + +/* work around a bug in pseudo DMA + * (on some FDCs) pseudo DMA does not stop when the CPU stops + * sending data. Hence we need a different way to signal the + * transfer length: We use SECT_PER_TRACK. Unfortunately, this + * does not work with MT, hence we can only transfer one head at + * a time + */ +static void virtualdmabug_workaround(void) +{ + int hard_sectors, end_sector; + + if(CT(COMMAND) == FD_WRITE) { + COMMAND &= ~0x80; /* switch off multiple track mode */ + + hard_sectors = raw_cmd->length >> (7 + SIZECODE); + end_sector = SECTOR + hard_sectors - 1; +#ifdef FLOPPY_SANITY_CHECK + if(end_sector > SECT_PER_TRACK) { + printk("too many sectors %d > %d\n", + end_sector, SECT_PER_TRACK); + return; + } +#endif + SECT_PER_TRACK = end_sector; /* make sure SECT_PER_TRACK points + * to end of transfer */ + } +} + +/* + * Formulate a read/write request. + * this routine decides where to load the data (directly to buffer, or to + * tmp floppy area), how much data to load (the size of the buffer, the whole + * track, or a single sector) + * All floppy_track_buffer handling goes in here. If we ever add track buffer + * allocation on the fly, it should be done here. No other part should need + * modification. + */ + +static int make_raw_rw_request(void) +{ + int aligned_sector_t; + int max_sector, max_size, tracksize, ssize; + + if(max_buffer_sectors == 0) { + printk("VFS: Block I/O scheduled on unopened device\n"); + return 0; + } + + set_fdc(DRIVE(current_req->rq_dev)); + + raw_cmd = &default_raw_cmd; + raw_cmd->flags = FD_RAW_SPIN | FD_RAW_NEED_DISK | FD_RAW_NEED_DISK | + FD_RAW_NEED_SEEK; + raw_cmd->cmd_count = NR_RW; + if (rq_data_dir(current_req) == READ) { + raw_cmd->flags |= FD_RAW_READ; + COMMAND = FM_MODE(_floppy,FD_READ); + } else if (rq_data_dir(current_req) == WRITE){ + raw_cmd->flags |= FD_RAW_WRITE; + COMMAND = FM_MODE(_floppy,FD_WRITE); + } else { + DPRINT("make_raw_rw_request: unknown command\n"); + return 0; + } + + max_sector = _floppy->sect * _floppy->head; + + TRACK = (int)current_req->sector / max_sector; + fsector_t = (int)current_req->sector % max_sector; + if (_floppy->track && TRACK >= _floppy->track) { + if (current_req->current_nr_sectors & 1) { + current_count_sectors = 1; + return 1; + } else + return 0; + } + HEAD = fsector_t / _floppy->sect; + + if (((_floppy->stretch & FD_SWAPSIDES) || TESTF(FD_NEED_TWADDLE)) && + fsector_t < _floppy->sect) + max_sector = _floppy->sect; + + /* 2M disks have phantom sectors on the first track */ + if ((_floppy->rate & FD_2M) && (!TRACK) && (!HEAD)){ + max_sector = 2 * _floppy->sect / 3; + if (fsector_t >= max_sector){ + current_count_sectors = minimum(_floppy->sect - fsector_t, + current_req->nr_sectors); + return 1; + } + SIZECODE = 2; + } else + SIZECODE = FD_SIZECODE(_floppy); + raw_cmd->rate = _floppy->rate & 0x43; + if ((_floppy->rate & FD_2M) && + (TRACK || HEAD) && + raw_cmd->rate == 2) + raw_cmd->rate = 1; + + if (SIZECODE) + SIZECODE2 = 0xff; + else + SIZECODE2 = 0x80; + raw_cmd->track = TRACK << STRETCH(_floppy); + DR_SELECT = UNIT(current_drive) + PH_HEAD(_floppy,HEAD); + GAP = _floppy->gap; + CODE2SIZE; + SECT_PER_TRACK = _floppy->sect << 2 >> SIZECODE; + SECTOR = ((fsector_t % _floppy->sect) << 2 >> SIZECODE) + 1; + + /* tracksize describes the size which can be filled up with sectors + * of size ssize. + */ + tracksize = _floppy->sect - _floppy->sect % ssize; + if (tracksize < _floppy->sect){ + SECT_PER_TRACK ++; + if (tracksize <= fsector_t % _floppy->sect) + SECTOR--; + + /* if we are beyond tracksize, fill up using smaller sectors */ + while (tracksize <= fsector_t % _floppy->sect){ + while(tracksize + ssize > _floppy->sect){ + SIZECODE--; + ssize >>= 1; + } + SECTOR++; SECT_PER_TRACK ++; + tracksize += ssize; + } + max_sector = HEAD * _floppy->sect + tracksize; + } else if (!TRACK && !HEAD && !(_floppy->rate & FD_2M) && probing) { + max_sector = _floppy->sect; + } else if (!HEAD && CT(COMMAND) == FD_WRITE) { + /* for virtual DMA bug workaround */ + max_sector = _floppy->sect; + } + + in_sector_offset = (fsector_t % _floppy->sect) % ssize; + aligned_sector_t = fsector_t - in_sector_offset; + max_size = current_req->nr_sectors; + if ((raw_cmd->track == buffer_track) && + (current_drive == buffer_drive) && + (fsector_t >= buffer_min) && (fsector_t < buffer_max)) { + /* data already in track buffer */ + if (CT(COMMAND) == FD_READ) { + copy_buffer(1, max_sector, buffer_max); + return 1; + } + } else if (in_sector_offset || current_req->nr_sectors < ssize){ + if (CT(COMMAND) == FD_WRITE){ + if (fsector_t + current_req->nr_sectors > ssize && + fsector_t + current_req->nr_sectors < ssize + ssize) + max_size = ssize + ssize; + else + max_size = ssize; + } + raw_cmd->flags &= ~FD_RAW_WRITE; + raw_cmd->flags |= FD_RAW_READ; + COMMAND = FM_MODE(_floppy,FD_READ); + } else if ((unsigned long)current_req->buffer < MAX_DMA_ADDRESS) { + unsigned long dma_limit; + int direct, indirect; + + indirect= transfer_size(ssize,max_sector,max_buffer_sectors*2) - + fsector_t; + + /* + * Do NOT use minimum() here---MAX_DMA_ADDRESS is 64 bits wide + * on a 64 bit machine! + */ + max_size = buffer_chain_size(); + dma_limit = (MAX_DMA_ADDRESS - ((unsigned long) current_req->buffer)) >> 9; + if ((unsigned long) max_size > dma_limit) { + max_size = dma_limit; + } + /* 64 kb boundaries */ + if (CROSS_64KB(current_req->buffer, max_size << 9)) + max_size = (K_64 - + ((unsigned long)current_req->buffer) % K_64)>>9; + direct = transfer_size(ssize,max_sector,max_size) - fsector_t; + /* + * We try to read tracks, but if we get too many errors, we + * go back to reading just one sector at a time. + * + * This means we should be able to read a sector even if there + * are other bad sectors on this track. + */ + if (!direct || + (indirect * 2 > direct * 3 && + *errors < DP->max_errors.read_track && + /*!TESTF(FD_NEED_TWADDLE) &&*/ + ((!probing || (DP->read_track&(1<probed_format)))))){ + max_size = current_req->nr_sectors; + } else { + raw_cmd->kernel_data = current_req->buffer; + raw_cmd->length = current_count_sectors << 9; + if (raw_cmd->length == 0){ + DPRINT("zero dma transfer attempted from make_raw_request\n"); + DPRINT("indirect=%d direct=%d fsector_t=%d", + indirect, direct, fsector_t); + return 0; + } +/* check_dma_crossing(raw_cmd->kernel_data, + raw_cmd->length, + "end of make_raw_request [1]");*/ + + virtualdmabug_workaround(); + return 2; + } + } + + if (CT(COMMAND) == FD_READ) + max_size = max_sector; /* unbounded */ + + /* claim buffer track if needed */ + if (buffer_track != raw_cmd->track || /* bad track */ + buffer_drive !=current_drive || /* bad drive */ + fsector_t > buffer_max || + fsector_t < buffer_min || + ((CT(COMMAND) == FD_READ || + (!in_sector_offset && current_req->nr_sectors >= ssize))&& + max_sector > 2 * max_buffer_sectors + buffer_min && + max_size + fsector_t > 2 * max_buffer_sectors + buffer_min) + /* not enough space */){ + buffer_track = -1; + buffer_drive = current_drive; + buffer_max = buffer_min = aligned_sector_t; + } + raw_cmd->kernel_data = floppy_track_buffer + + ((aligned_sector_t-buffer_min)<<9); + + if (CT(COMMAND) == FD_WRITE){ + /* copy write buffer to track buffer. + * if we get here, we know that the write + * is either aligned or the data already in the buffer + * (buffer will be overwritten) */ +#ifdef FLOPPY_SANITY_CHECK + if (in_sector_offset && buffer_track == -1) + DPRINT("internal error offset !=0 on write\n"); +#endif + buffer_track = raw_cmd->track; + buffer_drive = current_drive; + copy_buffer(ssize, max_sector, 2*max_buffer_sectors+buffer_min); + } else + transfer_size(ssize, max_sector, + 2*max_buffer_sectors+buffer_min-aligned_sector_t); + + /* round up current_count_sectors to get dma xfer size */ + raw_cmd->length = in_sector_offset+current_count_sectors; + raw_cmd->length = ((raw_cmd->length -1)|(ssize-1))+1; + raw_cmd->length <<= 9; +#ifdef FLOPPY_SANITY_CHECK + /*check_dma_crossing(raw_cmd->kernel_data, raw_cmd->length, + "end of make_raw_request");*/ + if ((raw_cmd->length < current_count_sectors << 9) || + (raw_cmd->kernel_data != current_req->buffer && + CT(COMMAND) == FD_WRITE && + (aligned_sector_t + (raw_cmd->length >> 9) > buffer_max || + aligned_sector_t < buffer_min)) || + raw_cmd->length % (128 << SIZECODE) || + raw_cmd->length <= 0 || current_count_sectors <= 0){ + DPRINT("fractionary current count b=%lx s=%lx\n", + raw_cmd->length, current_count_sectors); + if (raw_cmd->kernel_data != current_req->buffer) + printk("addr=%d, length=%ld\n", + (int) ((raw_cmd->kernel_data - + floppy_track_buffer) >> 9), + current_count_sectors); + printk("st=%d ast=%d mse=%d msi=%d\n", + fsector_t, aligned_sector_t, max_sector, max_size); + printk("ssize=%x SIZECODE=%d\n", ssize, SIZECODE); + printk("command=%x SECTOR=%d HEAD=%d, TRACK=%d\n", + COMMAND, SECTOR, HEAD, TRACK); + printk("buffer drive=%d\n", buffer_drive); + printk("buffer track=%d\n", buffer_track); + printk("buffer_min=%d\n", buffer_min); + printk("buffer_max=%d\n", buffer_max); + return 0; + } + + if (raw_cmd->kernel_data != current_req->buffer){ + if (raw_cmd->kernel_data < floppy_track_buffer || + current_count_sectors < 0 || + raw_cmd->length < 0 || + raw_cmd->kernel_data + raw_cmd->length > + floppy_track_buffer + (max_buffer_sectors << 10)){ + DPRINT("buffer overrun in schedule dma\n"); + printk("fsector_t=%d buffer_min=%d current_count=%ld\n", + fsector_t, buffer_min, + raw_cmd->length >> 9); + printk("current_count_sectors=%ld\n", + current_count_sectors); + if (CT(COMMAND) == FD_READ) + printk("read\n"); + if (CT(COMMAND) == FD_READ) + printk("write\n"); + return 0; + } + } else if (raw_cmd->length > current_req->nr_sectors << 9 || + current_count_sectors > current_req->nr_sectors){ + DPRINT("buffer overrun in direct transfer\n"); + return 0; + } else if (raw_cmd->length < current_count_sectors << 9){ + DPRINT("more sectors than bytes\n"); + printk("bytes=%ld\n", raw_cmd->length >> 9); + printk("sectors=%ld\n", current_count_sectors); + } + if (raw_cmd->length == 0){ + DPRINT("zero dma transfer attempted from make_raw_request\n"); + return 0; + } +#endif + + virtualdmabug_workaround(); + return 2; +} + +static void redo_fd_request(void) +{ +#define REPEAT {request_done(0); continue; } + kdev_t device; + int tmp; + + lastredo = jiffies; + if (current_drive < N_DRIVE) + floppy_off(current_drive); + + for (;;) { + if (!current_req) { + struct request *req = elv_next_request(&floppy_queue); + if (!req) { + do_floppy = NULL; + unlock_fdc(); + return; + } + current_req = req; + } + device = current_req->rq_dev; + set_fdc(DRIVE(device)); + reschedule_timeout(current_reqD, "redo fd request", 0); + + set_floppy(device); + raw_cmd = & default_raw_cmd; + raw_cmd->flags = 0; + if (start_motor(redo_fd_request)) return; + disk_change(current_drive); + if (test_bit(current_drive, &fake_change) || + TESTF(FD_DISK_CHANGED)){ + DPRINT("disk absent or changed during operation\n"); + REPEAT; + } + if (!_floppy) { /* Autodetection */ + if (!probing){ + DRS->probed_format = 0; + if (next_valid_format()){ + DPRINT("no autodetectable formats\n"); + _floppy = NULL; + REPEAT; + } + } + probing = 1; + _floppy = floppy_type+DP->autodetect[DRS->probed_format]; + } else + probing = 0; + errors = & (current_req->errors); + tmp = make_raw_rw_request(); + if (tmp < 2){ + request_done(tmp); + continue; + } + + if (TESTF(FD_NEED_TWADDLE)) + twaddle(); + schedule_bh( (void *)(void *) floppy_start); +#ifdef DEBUGT + debugt("queue fd request"); +#endif + return; + } +#undef REPEAT +} + +static struct cont_t rw_cont={ + rw_interrupt, + redo_fd_request, + bad_flp_intr, + request_done }; + +static void process_fd_request(void) +{ + cont = &rw_cont; + schedule_bh( (void *)(void *) redo_fd_request); +} + +static void do_fd_request(request_queue_t * q) +{ + if(max_buffer_sectors == 0) { + printk("VFS: do_fd_request called on non-open device\n"); + return; + } + + if (usage_count == 0) { + printk("warning: usage count=0, current_req=%p exiting\n", current_req); + printk("sect=%ld flags=%lx\n", (long)current_req->sector, current_req->flags); + return; + } + if (fdc_busy){ + /* fdc busy, this new request will be treated when the + current one is done */ + is_alive("do fd request, old request running"); + return; + } + lock_fdc(MAXTIMEOUT,0); + process_fd_request(); + is_alive("do fd request"); +} + +static struct cont_t poll_cont={ + success_and_wakeup, + floppy_ready, + generic_failure, + generic_done }; + +static int poll_drive(int interruptible, int flag) +{ + int ret; + /* no auto-sense, just clear dcl */ + raw_cmd = &default_raw_cmd; + raw_cmd->flags= flag; + raw_cmd->track=0; + raw_cmd->cmd_count=0; + cont = &poll_cont; +#ifdef DCL_DEBUG + if (DP->flags & FD_DEBUG){ + DPRINT("setting NEWCHANGE in poll_drive\n"); + } +#endif + SETF(FD_DISK_NEWCHANGE); + WAIT(floppy_ready); + return ret; +} + +/* + * User triggered reset + * ==================== + */ + +static void reset_intr(void) +{ + printk("weird, reset interrupt called\n"); +} + +static struct cont_t reset_cont={ + reset_intr, + success_and_wakeup, + generic_failure, + generic_done }; + +static int user_reset_fdc(int drive, int arg, int interruptible) +{ + int ret; + + ret=0; + LOCK_FDC(drive,interruptible); + if (arg == FD_RESET_ALWAYS) + FDCS->reset=1; + if (FDCS->reset){ + cont = &reset_cont; + WAIT(reset_fdc); + } + process_fd_request(); + return ret; +} + +/* + * Misc Ioctl's and support + * ======================== + */ +static inline int fd_copyout(void *param, const void *address, unsigned long size) +{ + return copy_to_user(param,address, size) ? -EFAULT : 0; +} + +static inline int fd_copyin(void *param, void *address, unsigned long size) +{ + return copy_from_user(address, param, size) ? -EFAULT : 0; +} + +#define _COPYOUT(x) (copy_to_user((void *)param, &(x), sizeof(x)) ? -EFAULT : 0) +#define _COPYIN(x) (copy_from_user(&(x), (void *)param, sizeof(x)) ? -EFAULT : 0) + +#define COPYOUT(x) ECALL(_COPYOUT(x)) +#define COPYIN(x) ECALL(_COPYIN(x)) + +static inline const char *drive_name(int type, int drive) +{ + struct floppy_struct *floppy; + + if (type) + floppy = floppy_type + type; + else { + if (UDP->native_format) + floppy = floppy_type + UDP->native_format; + else + return "(null)"; + } + if (floppy->name) + return floppy->name; + else + return "(null)"; +} + + +/* raw commands */ +static void raw_cmd_done(int flag) +{ + int i; + + if (!flag) { + raw_cmd->flags |= FD_RAW_FAILURE; + raw_cmd->flags |= FD_RAW_HARDFAILURE; + } else { + raw_cmd->reply_count = inr; + if (raw_cmd->reply_count > MAX_REPLIES) + raw_cmd->reply_count=0; + for (i=0; i< raw_cmd->reply_count; i++) + raw_cmd->reply[i] = reply_buffer[i]; + + if (raw_cmd->flags & (FD_RAW_READ | FD_RAW_WRITE)) + { + unsigned long flags; + flags=claim_dma_lock(); + raw_cmd->length = fd_get_dma_residue(); + release_dma_lock(flags); + } + + if ((raw_cmd->flags & FD_RAW_SOFTFAILURE) && + (!raw_cmd->reply_count || (raw_cmd->reply[0] & 0xc0))) + raw_cmd->flags |= FD_RAW_FAILURE; + + if (disk_change(current_drive)) + raw_cmd->flags |= FD_RAW_DISK_CHANGE; + else + raw_cmd->flags &= ~FD_RAW_DISK_CHANGE; + if (raw_cmd->flags & FD_RAW_NO_MOTOR_AFTER) + motor_off_callback(current_drive); + + if (raw_cmd->next && + (!(raw_cmd->flags & FD_RAW_FAILURE) || + !(raw_cmd->flags & FD_RAW_STOP_IF_FAILURE)) && + ((raw_cmd->flags & FD_RAW_FAILURE) || + !(raw_cmd->flags &FD_RAW_STOP_IF_SUCCESS))) { + raw_cmd = raw_cmd->next; + return; + } + } + generic_done(flag); +} + + +static struct cont_t raw_cmd_cont={ + success_and_wakeup, + floppy_start, + generic_failure, + raw_cmd_done +}; + +static inline int raw_cmd_copyout(int cmd, char *param, + struct floppy_raw_cmd *ptr) +{ + int ret; + + while(ptr) { + COPYOUT(*ptr); + param += sizeof(struct floppy_raw_cmd); + if ((ptr->flags & FD_RAW_READ) && ptr->buffer_length){ + if (ptr->length>=0 && ptr->length<=ptr->buffer_length) + ECALL(fd_copyout(ptr->data, + ptr->kernel_data, + ptr->buffer_length - + ptr->length)); + } + ptr = ptr->next; + } + return 0; +} + + +static void raw_cmd_free(struct floppy_raw_cmd **ptr) +{ + struct floppy_raw_cmd *next,*this; + + this = *ptr; + *ptr = 0; + while(this) { + if (this->buffer_length) { + fd_dma_mem_free((unsigned long)this->kernel_data, + this->buffer_length); + this->buffer_length = 0; + } + next = this->next; + kfree(this); + this = next; + } +} + + +static inline int raw_cmd_copyin(int cmd, char *param, + struct floppy_raw_cmd **rcmd) +{ + struct floppy_raw_cmd *ptr; + int ret; + int i; + + *rcmd = 0; + while(1) { + ptr = (struct floppy_raw_cmd *) + kmalloc(sizeof(struct floppy_raw_cmd), GFP_USER); + if (!ptr) + return -ENOMEM; + *rcmd = ptr; + COPYIN(*ptr); + ptr->next = 0; + ptr->buffer_length = 0; + param += sizeof(struct floppy_raw_cmd); + if (ptr->cmd_count > 33) + /* the command may now also take up the space + * initially intended for the reply & the + * reply count. Needed for long 82078 commands + * such as RESTORE, which takes ... 17 command + * bytes. Murphy's law #137: When you reserve + * 16 bytes for a structure, you'll one day + * discover that you really need 17... + */ + return -EINVAL; + + for (i=0; i< 16; i++) + ptr->reply[i] = 0; + ptr->resultcode = 0; + ptr->kernel_data = 0; + + if (ptr->flags & (FD_RAW_READ | FD_RAW_WRITE)) { + if (ptr->length <= 0) + return -EINVAL; + ptr->kernel_data =(char*)fd_dma_mem_alloc(ptr->length); + fallback_on_nodma_alloc(&ptr->kernel_data, + ptr->length); + if (!ptr->kernel_data) + return -ENOMEM; + ptr->buffer_length = ptr->length; + } + if (ptr->flags & FD_RAW_WRITE) + ECALL(fd_copyin(ptr->data, ptr->kernel_data, + ptr->length)); + rcmd = & (ptr->next); + if (!(ptr->flags & FD_RAW_MORE)) + return 0; + ptr->rate &= 0x43; + } +} + + +static int raw_cmd_ioctl(int cmd, void *param) +{ + int drive, ret, ret2; + struct floppy_raw_cmd *my_raw_cmd; + + if (FDCS->rawcmd <= 1) + FDCS->rawcmd = 1; + for (drive= 0; drive < N_DRIVE; drive++){ + if (FDC(drive) != fdc) + continue; + if (drive == current_drive){ + if (UDRS->fd_ref > 1){ + FDCS->rawcmd = 2; + break; + } + } else if (UDRS->fd_ref){ + FDCS->rawcmd = 2; + break; + } + } + + if (FDCS->reset) + return -EIO; + + ret = raw_cmd_copyin(cmd, param, &my_raw_cmd); + if (ret) { + raw_cmd_free(&my_raw_cmd); + return ret; + } + + raw_cmd = my_raw_cmd; + cont = &raw_cmd_cont; + ret=wait_til_done(floppy_start,1); +#ifdef DCL_DEBUG + if (DP->flags & FD_DEBUG){ + DPRINT("calling disk change from raw_cmd ioctl\n"); + } +#endif + + if (ret != -EINTR && FDCS->reset) + ret = -EIO; + + DRS->track = NO_TRACK; + + ret2 = raw_cmd_copyout(cmd, param, my_raw_cmd); + if (!ret) + ret = ret2; + raw_cmd_free(&my_raw_cmd); + return ret; +} + +static int invalidate_drive(struct block_device *bdev) +{ + /* invalidate the buffer track to force a reread */ + set_bit(DRIVE(to_kdev_t(bdev->bd_dev)), &fake_change); + process_fd_request(); + check_disk_change(bdev); + return 0; +} + + +static inline void clear_write_error(int drive) +{ + CLEARSTRUCT(UDRWE); +} + +static inline int set_geometry(unsigned int cmd, struct floppy_struct *g, + int drive, int type, struct block_device *bdev) +{ + int cnt; + + /* sanity checking for parameters.*/ + if (g->sect <= 0 || + g->head <= 0 || + g->track <= 0 || + g->track > UDP->tracks>>STRETCH(g) || + /* check if reserved bits are set */ + (g->stretch&~(FD_STRETCH|FD_SWAPSIDES)) != 0) + return -EINVAL; + if (type){ + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + LOCK_FDC(drive,1); + for (cnt = 0; cnt < N_DRIVE; cnt++){ + if (ITYPE(drive_state[cnt].fd_device) == type && + drive_state[cnt].fd_ref) + set_bit(drive, &fake_change); + } + floppy_type[type] = *g; + floppy_type[type].name="user format"; + for (cnt = type << 2; cnt < (type << 2) + 4; cnt++) + floppy_sizes[cnt]= floppy_sizes[cnt+0x80]= + floppy_type[type].size+1; + process_fd_request(); + for (cnt = 0; cnt < N_DRIVE; cnt++){ + if (ITYPE(drive_state[cnt].fd_device) == type && + drive_state[cnt].fd_ref) + __check_disk_change( + MKDEV(FLOPPY_MAJOR, + drive_state[cnt].fd_device)); + } + } else { + LOCK_FDC(drive,1); + if (cmd != FDDEFPRM) + /* notice a disk change immediately, else + * we lose our settings immediately*/ + CALL(poll_drive(1, FD_RAW_NEED_DISK)); + user_params[drive] = *g; + if (buffer_drive == drive) + SUPBOUND(buffer_max, user_params[drive].sect); + current_type[drive] = &user_params[drive]; + floppy_sizes[drive] = user_params[drive].size; + if (cmd == FDDEFPRM) + DRS->keep_data = -1; + else + DRS->keep_data = 1; + /* invalidation. Invalidate only when needed, i.e. + * when there are already sectors in the buffer cache + * whose number will change. This is useful, because + * mtools often changes the geometry of the disk after + * looking at the boot block */ + if (DRS->maxblock > user_params[drive].sect || DRS->maxtrack) + invalidate_drive(bdev); + else + process_fd_request(); + } + return 0; +} + +/* handle obsolete ioctl's */ +static int ioctl_table[]= { + FDCLRPRM, + FDSETPRM, + FDDEFPRM, + FDGETPRM, + FDMSGON, + FDMSGOFF, + FDFMTBEG, + FDFMTTRK, + FDFMTEND, + FDSETEMSGTRESH, + FDFLUSH, + FDSETMAXERRS, + FDGETMAXERRS, + FDGETDRVTYP, + FDSETDRVPRM, + FDGETDRVPRM, + FDGETDRVSTAT, + FDPOLLDRVSTAT, + FDRESET, + FDGETFDCSTAT, + FDWERRORCLR, + FDWERRORGET, + FDRAWCMD, + FDEJECT, + FDTWADDLE +}; + +static inline int normalize_ioctl(int *cmd, int *size) +{ + int i; + + for (i=0; i < ARRAY_SIZE(ioctl_table); i++) { + if ((*cmd & 0xffff) == (ioctl_table[i] & 0xffff)){ + *size = _IOC_SIZE(*cmd); + *cmd = ioctl_table[i]; + if (*size > _IOC_SIZE(*cmd)) { + printk("ioctl not yet supported\n"); + return -EFAULT; + } + return 0; + } + } + return -EINVAL; +} + +static int get_floppy_geometry(int drive, int type, struct floppy_struct **g) +{ + if (type) + *g = &floppy_type[type]; + else { + LOCK_FDC(drive,0); + CALL(poll_drive(0,0)); + process_fd_request(); + *g = current_type[drive]; + } + if (!*g) + return -ENODEV; + return 0; +} + +static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long param) +{ +#define FD_IOCTL_ALLOWED ((filp) && (filp)->private_data) +#define OUT(c,x) case c: outparam = (const char *) (x); break +#define IN(c,x,tag) case c: *(x) = inparam. tag ; return 0 + + int i,drive,type; + kdev_t device; + int ret; + int size; + union inparam { + struct floppy_struct g; /* geometry */ + struct format_descr f; + struct floppy_max_errors max_errors; + struct floppy_drive_params dp; + } inparam; /* parameters coming from user space */ + const char *outparam; /* parameters passed back to user space */ + + device = inode->i_rdev; + type = TYPE(device); + drive = DRIVE(device); + + /* convert compatibility eject ioctls into floppy eject ioctl. + * We do this in order to provide a means to eject floppy disks before + * installing the new fdutils package */ + if (cmd == CDROMEJECT || /* CD-ROM eject */ + cmd == 0x6470 /* SunOS floppy eject */) { + DPRINT("obsolete eject ioctl\n"); + DPRINT("please use floppycontrol --eject\n"); + cmd = FDEJECT; + } + + /* generic block device ioctls */ + switch(cmd) { + /* the following have been inspired by the corresponding + * code for other block devices. */ + struct floppy_struct *g; + case HDIO_GETGEO: + { + struct hd_geometry loc; + ECALL(get_floppy_geometry(drive, type, &g)); + loc.heads = g->head; + loc.sectors = g->sect; + loc.cylinders = g->track; + loc.start = 0; + return _COPYOUT(loc); + } + } + + /* convert the old style command into a new style command */ + if ((cmd & 0xff00) == 0x0200) { + ECALL(normalize_ioctl(&cmd, &size)); + } else + return -EINVAL; + + /* permission checks */ + if (((cmd & 0x40) && !FD_IOCTL_ALLOWED) || + ((cmd & 0x80) && !capable(CAP_SYS_ADMIN))) + return -EPERM; + + /* copyin */ + CLEARSTRUCT(&inparam); + if (_IOC_DIR(cmd) & _IOC_WRITE) + ECALL(fd_copyin((void *)param, &inparam, size)) + + switch (cmd) { + case FDEJECT: + if (UDRS->fd_ref != 1) + /* somebody else has this drive open */ + return -EBUSY; + LOCK_FDC(drive,1); + + /* do the actual eject. Fails on + * non-Sparc architectures */ + ret=fd_eject(UNIT(drive)); + + USETF(FD_DISK_CHANGED); + USETF(FD_VERIFY); + process_fd_request(); + return ret; + case FDCLRPRM: + LOCK_FDC(drive,1); + current_type[drive] = NULL; + floppy_sizes[drive] = MAX_DISK_SIZE << 1; + UDRS->keep_data = 0; + return invalidate_drive(inode->i_bdev); + case FDSETPRM: + case FDDEFPRM: + return set_geometry(cmd, & inparam.g, + drive, type, inode->i_bdev); + case FDGETPRM: + ECALL(get_floppy_geometry(drive, type, + (struct floppy_struct**) + &outparam)); + break; + + case FDMSGON: + UDP->flags |= FTD_MSG; + return 0; + case FDMSGOFF: + UDP->flags &= ~FTD_MSG; + return 0; + + case FDFMTBEG: + LOCK_FDC(drive,1); + CALL(poll_drive(1, FD_RAW_NEED_DISK)); + ret = UDRS->flags; + if (ret & FD_VERIFY) { + CALL(poll_drive(1, FD_RAW_NEED_DISK)); + ret = UDRS->flags; + } + + if (ret & FD_VERIFY) { + CALL(poll_drive(1, FD_RAW_NEED_DISK)); + ret = UDRS->flags; + } + + if (ret & FD_VERIFY) { + CALL(poll_drive(1, FD_RAW_NEED_DISK)); + ret = UDRS->flags; + } + + if (ret & FD_VERIFY) { + CALL(poll_drive(1, FD_RAW_NEED_DISK)); + ret = UDRS->flags; + } + + if(ret & FD_VERIFY){ + CALL(poll_drive(1, FD_RAW_NEED_DISK)); + ret = UDRS->flags; + } + process_fd_request(); + if (ret & FD_VERIFY) + return -ENODEV; + if (!(ret & FD_DISK_WRITABLE)) + return -EROFS; + return 0; + case FDFMTTRK: + if (UDRS->fd_ref != 1) + return -EBUSY; + return do_format(device, &inparam.f); + case FDFMTEND: + case FDFLUSH: + LOCK_FDC(drive,1); + return invalidate_drive(inode->i_bdev); + + case FDSETEMSGTRESH: + UDP->max_errors.reporting = + (unsigned short) (param & 0x0f); + return 0; + OUT(FDGETMAXERRS, &UDP->max_errors); + IN(FDSETMAXERRS, &UDP->max_errors, max_errors); + + case FDGETDRVTYP: + outparam = drive_name(type,drive); + SUPBOUND(size,strlen(outparam)+1); + break; + + IN(FDSETDRVPRM, UDP, dp); + OUT(FDGETDRVPRM, UDP); + + case FDPOLLDRVSTAT: + LOCK_FDC(drive,1); + CALL(poll_drive(1, FD_RAW_NEED_DISK)); + process_fd_request(); + /* fall through */ + OUT(FDGETDRVSTAT, UDRS); + + case FDRESET: + return user_reset_fdc(drive, (int)param, 1); + + OUT(FDGETFDCSTAT,UFDCS); + + case FDWERRORCLR: + CLEARSTRUCT(UDRWE); + return 0; + OUT(FDWERRORGET,UDRWE); + + case FDRAWCMD: + if (type) + return -EINVAL; + LOCK_FDC(drive,1); + set_floppy(device); + CALL(i = raw_cmd_ioctl(cmd,(void *) param)); + process_fd_request(); + return i; + + case FDTWADDLE: + LOCK_FDC(drive,1); + twaddle(); + process_fd_request(); + return 0; + + default: + return -EINVAL; + } + + if (_IOC_DIR(cmd) & _IOC_READ) + return fd_copyout((void *)param, outparam, size); + else + return 0; +#undef OUT +#undef IN +} + +static void __init config_types(void) +{ + int first=1; + int drive; + extern struct fd_info { + unsigned char dummy[4 * 6]; + unsigned char fd_types[8]; + } drive_info; + + for (drive = 0; drive < 4; drive++) + UDP->cmos = drive_info.fd_types[drive]; + + /* XXX */ + /* additional physical CMOS drive detection should go here */ + + for (drive=0; drive < N_DRIVE; drive++){ + unsigned int type = UDP->cmos; + struct floppy_drive_params *params; + const char *name = NULL; + static char temparea[32]; + + if (type < NUMBER(default_drive_params)) { + params = &default_drive_params[type].params; + if (type) { + name = default_drive_params[type].name; + allowed_drive_mask |= 1 << drive; + } + } else { + params = &default_drive_params[0].params; + sprintf(temparea, "unknown type %d (usb?)", type); + name = temparea; + } + if (name) { + const char * prepend = ","; + if (first) { + prepend = KERN_INFO "Floppy drive(s):"; + first = 0; + } + printk("%s fd%d is %s", prepend, drive, name); + register_devfs_entries (drive); + } + *UDP = *params; + } + if (!first) + printk("\n"); +} + +static int floppy_release(struct inode * inode, struct file * filp) +{ + int drive = DRIVE(inode->i_rdev); + + if (UDRS->fd_ref < 0) + UDRS->fd_ref=0; + else if (!UDRS->fd_ref--) { + DPRINT("floppy_release with fd_ref == 0"); + UDRS->fd_ref = 0; + } + floppy_release_irq_and_dma(); + return 0; +} + +/* + * floppy_open check for aliasing (/dev/fd0 can be the same as + * /dev/PS0 etc), and disallows simultaneous access to the same + * drive with different device numbers. + */ +#define RETERR(x) do{floppy_release(inode,filp); return -(x);}while(0) + +static int floppy_open(struct inode * inode, struct file * filp) +{ + int drive; + int old_dev; + int try; + char *tmp; + +#ifdef PC9800_DEBUG_FLOPPY + printk("floppy open: start\n"); +#endif + filp->private_data = (void*) 0; + + drive = DRIVE(inode->i_rdev); +#ifdef PC9800_DEBUG_FLOPPY + printk("floppy open: drive=%d, current_drive=%d, UDP->cmos=%d\n" + "floppy open: FDCS={spec1=%d, spec2=%d, dtr=%d, version=%d, dor=%d, address=%lu}\n", + drive, current_drive, UDP->cmos, FDCS->spec1, FDCS->spec2, + FDCS->dtr, FDCS->version, FDCS->dor, FDCS->address); + if (_floppy) { + printk("floppy open: _floppy={size=%d, sect=%d, head=%d, track=%d, spec1=%d}\n", + _floppy->size, _floppy->sect, _floppy->head, + _floppy->track, _floppy->spec1); + } else { + printk("floppy open: _floppy=NULL\n"); + } +#endif /* PC9800_DEBUG_FLOPPY */ + + if (drive >= N_DRIVE || + !(allowed_drive_mask & (1 << drive)) || + fdc_state[FDC(drive)].version == FDC_NONE) + return -ENXIO; + + if (TYPE(inode->i_rdev) >= NUMBER(floppy_type)) + return -ENXIO; + old_dev = UDRS->fd_device; + if (UDRS->fd_ref && old_dev != minor(inode->i_rdev)) + return -EBUSY; + + if (!UDRS->fd_ref && (UDP->flags & FD_BROKEN_DCL)){ + USETF(FD_DISK_CHANGED); + USETF(FD_VERIFY); + } + + if (UDRS->fd_ref == -1 || + (UDRS->fd_ref && (filp->f_flags & O_EXCL))) + return -EBUSY; + + if (floppy_grab_irq_and_dma()) + return -EBUSY; + + if (filp->f_flags & O_EXCL) + UDRS->fd_ref = -1; + else + UDRS->fd_ref++; + + if (!floppy_track_buffer){ + /* if opening an ED drive, reserve a big buffer, + * else reserve a small one */ + if ((UDP->cmos == 6) || (UDP->cmos == 5)) + try = 64; /* Only 48 actually useful */ + else + try = 32; /* Only 24 actually useful */ + + tmp=(char *)fd_dma_mem_alloc(1024 * try); + if (!tmp && !floppy_track_buffer) { + try >>= 1; /* buffer only one side */ + INFBOUND(try, 16); + tmp= (char *)fd_dma_mem_alloc(1024*try); + } + if (!tmp && !floppy_track_buffer) { + fallback_on_nodma_alloc(&tmp, 2048 * try); + } + if (!tmp && !floppy_track_buffer) { + DPRINT("Unable to allocate DMA memory\n"); + RETERR(ENXIO); + } + if (floppy_track_buffer) { + if (tmp) + fd_dma_mem_free((unsigned long)tmp,try*1024); + } else { + buffer_min = buffer_max = -1; + floppy_track_buffer = tmp; + max_buffer_sectors = try; + } + } + + UDRS->fd_device = minor(inode->i_rdev); + set_capacity(disks[drive], floppy_sizes[minor(inode->i_rdev)]); + if (old_dev != -1 && old_dev != minor(inode->i_rdev)) { + if (buffer_drive == drive) + buffer_track = -1; + /* umm, invalidate_buffers() in ->open?? --hch */ + invalidate_buffers(mk_kdev(FLOPPY_MAJOR,old_dev)); + } + +#ifdef PC9800_DEBUG_FLOPPY + printk("floppy open: floppy.c:%d passed\n", __LINE__); +#endif + + + /* Allow ioctls if we have write-permissions even if read-only open. + * Needed so that programs such as fdrawcmd still can work on write + * protected disks */ + if ((filp->f_mode & 2) || + (inode->i_sb && (permission(inode,2) == 0))) + filp->private_data = (void*) 8; + + if (UFDCS->rawcmd == 1) + UFDCS->rawcmd = 2; + +#ifdef PC9800_DEBUG_FLOPPY + printk("floppy open: floppy.c:%d passed\n", __LINE__); +#endif + + if (filp->f_flags & O_NDELAY) + return 0; + if (filp->f_mode & 3) { + UDRS->last_checked = 0; + check_disk_change(inode->i_bdev); + if (UTESTF(FD_DISK_CHANGED)) + RETERR(ENXIO); + } + if ((filp->f_mode & 2) && !(UTESTF(FD_DISK_WRITABLE))) + RETERR(EROFS); +#ifdef PC9800_DEBUG_FLOPPY + printk("floppy open: end normally\n"); +#endif + + return 0; +#undef RETERR +} + +/* + * Check if the disk has been changed or if a change has been faked. + */ +static int check_floppy_change(struct gendisk *disk) +{ + int drive = (int)disk->private_data; + +#ifdef PC9800_DEBUG_FLOPPY + printk("check_floppy_change: MINOR=%d\n", minor(dev)); +#endif + + if (UTESTF(FD_DISK_CHANGED) || UTESTF(FD_VERIFY)) + return 1; + + if (UDP->checkfreq < (int)(jiffies - UDRS->last_checked)) { + if(floppy_grab_irq_and_dma()) { + return 1; + } + + lock_fdc(drive,0); + poll_drive(0,0); + process_fd_request(); + floppy_release_irq_and_dma(); + } + + if (UTESTF(FD_DISK_CHANGED) || + UTESTF(FD_VERIFY) || + test_bit(drive, &fake_change) || + (!ITYPE(UDRS->fd_device) && !current_type[drive])) + return 1; + return 0; +} + +/* + * This implements "read block 0" for floppy_revalidate(). + * Needed for format autodetection, checking whether there is + * a disk in the drive, and whether that disk is writable. + */ + +static int floppy_rb0_complete(struct bio *bio, unsigned int bytes_done, int err) +{ + if (bio->bi_size) + return 1; + + complete((struct completion*)bio->bi_private); + return 0; +} + +static int __floppy_read_block_0(struct block_device *bdev) +{ + struct bio bio; + struct bio_vec bio_vec; + struct completion complete; + struct page *page; + size_t size; + + page = alloc_page(GFP_NOIO); + if (!page) { + process_fd_request(); + return -ENOMEM; + } + + size = bdev->bd_block_size; + if (!size) + size = 1024; + + bio_init(&bio); + bio.bi_io_vec = &bio_vec; + bio_vec.bv_page = page; + bio_vec.bv_len = size; + bio_vec.bv_offset = 0; + bio.bi_vcnt = 1; + bio.bi_idx = 0; + bio.bi_size = size; + bio.bi_bdev = bdev; + bio.bi_sector = 0; + init_completion(&complete); + bio.bi_private = &complete; + bio.bi_end_io = floppy_rb0_complete; + + submit_bio(READ, &bio); + generic_unplug_device(bdev_get_queue(bdev)); + process_fd_request(); + wait_for_completion(&complete); + + __free_page(page); + + return 0; +} + +static int floppy_read_block_0(struct gendisk *disk) +{ + struct block_device *bdev; + int ret; + + bdev = bdget(MKDEV(disk->major, disk->first_minor)); + if (!bdev) { + printk("No block device for %s\n", disk->disk_name); + BUG(); + } + bdev->bd_disk = disk; /* ewww */ + ret = __floppy_read_block_0(bdev); + atomic_dec(&bdev->bd_count); + return ret; +} + +/* revalidate the floppy disk, i.e. trigger format autodetection by reading + * the bootblock (block 0). "Autodetection" is also needed to check whether + * there is a disk in the drive at all... Thus we also do it for fixed + * geometry formats */ +static int floppy_revalidate(struct gendisk *disk) +{ + int drive=(int)disk->private_data; +#define NO_GEOM (!current_type[drive] && !ITYPE(UDRS->fd_device)) + int cf; + int res = 0; + + if (UTESTF(FD_DISK_CHANGED) || + UTESTF(FD_VERIFY) || + test_bit(drive, &fake_change) || + NO_GEOM){ + if(usage_count == 0) { + printk("VFS: revalidate called on non-open device.\n"); + return -EFAULT; + } + lock_fdc(drive,0); + cf = UTESTF(FD_DISK_CHANGED) || UTESTF(FD_VERIFY); + if (!(cf || test_bit(drive, &fake_change) || NO_GEOM)){ + process_fd_request(); /*already done by another thread*/ + return 0; + } + UDRS->maxblock = 0; + UDRS->maxtrack = 0; + if (buffer_drive == drive) + buffer_track = -1; + clear_bit(drive, &fake_change); + UCLEARF(FD_DISK_CHANGED); + if (cf) + UDRS->generation++; + if (NO_GEOM){ + /* auto-sensing */ + res = floppy_read_block_0(disk); + } else { + if (cf) + poll_drive(0, FD_RAW_NEED_DISK); + process_fd_request(); + } + } + set_capacity(disk, floppy_sizes[UDRS->fd_device]); + return res; +} + +static struct block_device_operations floppy_fops = { + .owner = THIS_MODULE, + .open = floppy_open, + .release = floppy_release, + .ioctl = fd_ioctl, + .media_changed = check_floppy_change, + .revalidate_disk= floppy_revalidate, +}; + +static void __init register_devfs_entries (int drive) +{ + int base_minor, i; + static char *table[] = + {"", +#if 0 + "d360", +#else + "h1232", +#endif + "h1200", "u360", "u720", "h360", "h720", + "u1440", "u2880", "CompaQ", "h1440", "u1680", "h410", + "u820", "h1476", "u1722", "h420", "u830", "h1494", "u1743", + "h880", "u1040", "u1120", "h1600", "u1760", "u1920", + "u3200", "u3520", "u3840", "u1840", "u800", "u1600", + NULL + }; + static int t360[] = {1,0}, t1200[] = {2,5,6,10,12,14,16,18,20,23,0}, + t3in[] = {8,9,26,27,28, 7,11,15,19,24,25,29,31, 3,4,13,17,21,22,30,0}; + static int *table_sup[] = + {NULL, t360, t1200, t3in+5+8, t3in+5, t3in, t3in}; + + base_minor = (drive < 4) ? drive : (124 + drive); + if (UDP->cmos < NUMBER(default_drive_params)) { + i = 0; + do { + char name[16]; + + sprintf (name, "%d%s", drive, table[table_sup[UDP->cmos][i]]); + devfs_register (devfs_handle, name, DEVFS_FL_DEFAULT, MAJOR_NR, + base_minor + (table_sup[UDP->cmos][i] << 2), + S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP |S_IWGRP, + &floppy_fops, NULL); + } while (table_sup[UDP->cmos][i++]); + } +} + +/* + * Floppy Driver initialization + * ============================= + */ + +static inline char __init get_fdc_version(void) +{ + return FDC_8272A; +} + +/* lilo configuration */ + +static void __init floppy_set_flags(int *ints,int param, int param2) +{ + int i; + + for (i=0; i < ARRAY_SIZE(default_drive_params); i++){ + if (param) + default_drive_params[i].params.flags |= param2; + else + default_drive_params[i].params.flags &= ~param2; + } + DPRINT("%s flag 0x%x\n", param2 ? "Setting" : "Clearing", param); +} + +static void __init daring(int *ints,int param, int param2) +{ + int i; + + for (i=0; i < ARRAY_SIZE(default_drive_params); i++){ + if (param){ + default_drive_params[i].params.select_delay = 0; + default_drive_params[i].params.flags |= FD_SILENT_DCL_CLEAR; + } else { + default_drive_params[i].params.select_delay = 2*HZ/100; + default_drive_params[i].params.flags &= ~FD_SILENT_DCL_CLEAR; + } + } + DPRINT("Assuming %s floppy hardware\n", param ? "standard" : "broken"); +} + +static void __init set_cmos(int *ints, int dummy, int dummy2) +{ + int current_drive=0; + + if (ints[0] != 2){ + DPRINT("wrong number of parameters for CMOS\n"); + return; + } + current_drive = ints[1]; + if (current_drive < 0 || current_drive >= 8){ + DPRINT("bad drive for set_cmos\n"); + return; + } +#if N_FDC > 1 + if (current_drive >= 4 && !FDC2) + FDC2 = 0x370; +#endif + DP->cmos = ints[2]; + DPRINT("setting CMOS code to %d\n", ints[2]); +} + +static struct param_table { + const char *name; + void (*fn)(int *ints, int param, int param2); + int *var; + int def_param; + int param2; +} config_params[]={ + { "allowed_drive_mask", 0, &allowed_drive_mask, 0xff, 0}, /* obsolete */ + { "all_drives", 0, &allowed_drive_mask, 0xff, 0 }, /* obsolete */ + { "irq", 0, &FLOPPY_IRQ, DEFAULT_FLOPPY_IRQ, 0 }, + { "dma", 0, &FLOPPY_DMA, DEFAULT_FLOPPY_DMA, 0 }, + + { "daring", daring, 0, 1, 0}, +#if N_FDC > 1 + { "two_fdc", 0, &FDC2, 0x370, 0 }, + { "one_fdc", 0, &FDC2, 0, 0 }, +#endif + { "broken_dcl", floppy_set_flags, 0, 1, FD_BROKEN_DCL }, + { "messages", floppy_set_flags, 0, 1, FTD_MSG }, + { "silent_dcl_clear", floppy_set_flags, 0, 1, FD_SILENT_DCL_CLEAR }, + { "debug", floppy_set_flags, 0, 1, FD_DEBUG }, + + { "nodma", 0, &can_use_virtual_dma, 1, 0 }, + { "yesdma", 0, &can_use_virtual_dma, 0, 0 }, + + { "fifo_depth", 0, &fifo_depth, 0xa, 0 }, + { "nofifo", 0, &no_fifo, 0x20, 0 }, + { "usefifo", 0, &no_fifo, 0, 0 }, + + { "cmos", set_cmos, 0, 0, 0 }, + { "slow", 0, &slow_floppy, 1, 0 }, + + { "unexpected_interrupts", 0, &print_unex, 1, 0 }, + { "no_unexpected_interrupts", 0, &print_unex, 0, 0 }, + + EXTRA_FLOPPY_PARAMS +}; + +static int __init floppy_setup(char *str) +{ + int i; + int param; + int ints[11]; + + str = get_options(str,ARRAY_SIZE(ints),ints); + if (str) { + for (i=0; i< ARRAY_SIZE(config_params); i++){ + if (strcmp(str,config_params[i].name) == 0){ + if (ints[0]) + param = ints[1]; + else + param = config_params[i].def_param; + if (config_params[i].fn) + config_params[i]. + fn(ints,param, + config_params[i].param2); + if (config_params[i].var) { + DPRINT("%s=%d\n", str, param); + *config_params[i].var = param; + } + return 1; + } + } + } + if (str) { + DPRINT("unknown floppy option [%s]\n", str); + + DPRINT("allowed options are:"); + for (i=0; i< ARRAY_SIZE(config_params); i++) + printk(" %s",config_params[i].name); + printk("\n"); + } else + DPRINT("botched floppy option\n"); + DPRINT("Read linux/Documentation/floppy.txt\n"); + return 0; +} + +static int have_no_fdc= -ENODEV; + +static struct platform_device floppy_device = { + .name = "floppy", + .id = 0, + .dev = { + .name = "Floppy Drive", + }, +}; + +static struct gendisk *floppy_find(dev_t dev, int *part, void *data) +{ + int drive = (*part&3) | ((*part&0x80) >> 5); + if (drive >= N_DRIVE || + !(allowed_drive_mask & (1 << drive)) || + fdc_state[FDC(drive)].version == FDC_NONE) + return NULL; + return get_disk(disks[drive]); +} + +int __init floppy_init(void) +{ + int i,unit,drive; + int err; + + raw_cmd = NULL; + + for (i=0; imajor = MAJOR_NR; + disks[i]->first_minor = TOMINOR(i); + disks[i]->fops = &floppy_fops; + sprintf(disks[i]->disk_name, "fd%d", i); + } + + blk_register_region(MKDEV(MAJOR_NR, 0), 256, THIS_MODULE, + floppy_find, NULL, NULL); + + for (i=0; i<256; i++) + if (ITYPE(i)) + floppy_sizes[i] = floppy_type[ITYPE(i)].size; + else + floppy_sizes[i] = MAX_DISK_SIZE << 1; + + blk_init_queue(&floppy_queue, do_fd_request, &floppy_lock); + reschedule_timeout(MAXTIMEOUT, "floppy init", MAXTIMEOUT); + config_types(); + + for (i = 0; i < N_FDC; i++) { + fdc = i; + CLEARSTRUCT(FDCS); + FDCS->dtr = -1; + FDCS->dor = 0; + } + + if ((fd_inb(FD_MODE_CHANGE) & 1) == 0) + FDC1 = 0xc8; + + use_virtual_dma = can_use_virtual_dma & 1; + fdc_state[0].address = FDC1; + if (fdc_state[0].address == -1) { + err = -ENODEV; + goto out1; + } +#if N_FDC > 1 + fdc_state[1].address = FDC2; +#endif + + fdc = 0; /* reset fdc in case of unexpected interrupt */ + if (floppy_grab_irq_and_dma()){ + err = -EBUSY; + goto out1; + } + + /* initialise drive state */ + for (drive = 0; drive < N_DRIVE; drive++) { + CLEARSTRUCT(UDRS); + CLEARSTRUCT(UDRWE); + USETF(FD_DISK_NEWCHANGE); + USETF(FD_DISK_CHANGED); + USETF(FD_VERIFY); + UDRS->fd_device = -1; + floppy_track_buffer = NULL; + max_buffer_sectors = 0; + } + + for (i = 0; i < N_FDC; i++) { + fdc = i; + FDCS->driver_version = FD_DRIVER_VERSION; + for (unit=0; unit<4; unit++) + FDCS->track[unit] = 0; + if (FDCS->address == -1) + continue; + FDCS->rawcmd = 2; + user_reset_fdc(-1, FD_RESET_ALWAYS, 0); + + /* Try to determine the floppy controller type */ + FDCS->version = get_fdc_version(); + if (FDCS->version == FDC_NONE){ + /* free ioports reserved by floppy_grab_irq_and_dma() */ + release_region(FDCS->address, 1); + release_region(FDCS->address + 2, 1); + release_region(FDCS->address + 4, 1); + release_region(0xbe, 1); + release_region(0x4be, 1); + FDCS->address = -1; + continue; + } + if (can_use_virtual_dma == 2 && FDCS->version < FDC_82072A) + can_use_virtual_dma = 0; + + have_no_fdc = 0; + /* Not all FDCs seem to be able to handle the version command + * properly, so force a reset for the standard FDC clones, + * to avoid interrupt garbage. + */ + user_reset_fdc(-1,FD_RESET_ALWAYS,0); + } + fdc=0; + del_timer(&fd_timeout); + current_drive = 0; + floppy_release_irq_and_dma(); +#if 0 /* no message */ + initialising=0; +#endif + if (have_no_fdc) { + DPRINT("no floppy controllers found\n"); + flush_scheduled_work(); + if (usage_count) + floppy_release_irq_and_dma(); + err = have_no_fdc; + goto out2; + } + + for (drive = 0; drive < N_DRIVE; drive++) { + motor_off_timer[drive].data = drive; + motor_off_timer[drive].function = motor_off_callback; + if (!(allowed_drive_mask & (1 << drive))) + continue; + if (fdc_state[FDC(drive)].version == FDC_NONE) + continue; + /* to be cleaned up... */ + disks[drive]->private_data = (void*)drive; + disks[drive]->queue = &floppy_queue; + add_disk(disks[drive]); + } + + platform_device_register(&floppy_device); + return 0; + +out1: + del_timer(&fd_timeout); +out2: + blk_unregister_region(MKDEV(MAJOR_NR, 0), 256); + unregister_blkdev(MAJOR_NR,"fd"); + blk_cleanup_queue(&floppy_queue); +out: + for (i=0; iaddress != -1){ + static char floppy[] = "floppy"; + if (!request_region(FDCS->address, 1, floppy)) + goto cleanup0; + + if (!request_region(FDCS->address + 2, 1, floppy)) { + release_region(FDCS->address, 1); + goto cleanup0; + } + + if (!request_region(FDCS->address + 4, 1, floppy)) { + release_region(FDCS->address, 1); + release_region(FDCS->address + 2, 1); + goto cleanup0; + } + + if (fdc == 0) { /* internal FDC */ + if (request_region(0xbe, 1, "floppy mode change")) { + if (request_region(0x4be, 1, "floppy ex. mode change")) + continue; + else + DPRINT("Floppy io-port 0x4be in use\n"); + + release_region(0xbe, 1); + } else + DPRINT("Floppy io-port 0xbe in use\n"); + + release_region(FDCS->address, 1); + release_region(FDCS->address + 2, 1); + release_region(FDCS->address + 4, 1); + } + + goto cleanup1; + } + } + for (fdc=0; fdc< N_FDC; fdc++){ + if (FDCS->address != -1){ + reset_fdc_info(1); + fd_outb(FDCS->dor, FD_MODE); + } + } + fdc = 0; + fd_outb((FDCS->dor & 8), FD_MODE); + + for (fdc = 0; fdc < N_FDC; fdc++) + if (FDCS->address != -1) + fd_outb(FDCS->dor, FD_MODE); + /* + * The driver will try and free resources and relies on us + * to know if they were allocated or not. + */ + fdc = 0; + irqdma_allocated = 1; + return 0; + +cleanup0: + DPRINT("Floppy io-port 0x%04lx in use\n", FDCS->address); +cleanup1: + fd_free_irq(); + fd_free_dma(); + while(--fdc >= 0) { + release_region(FDCS->address, 1); + release_region(FDCS->address + 2, 1); + release_region(FDCS->address + 4, 1); + if (fdc == 0) { + release_region(0x00be, 1); + release_region(0x04be, 1); + } + } + MOD_DEC_USE_COUNT; + spin_lock_irqsave(&floppy_usage_lock, flags); + usage_count--; + spin_unlock_irqrestore(&floppy_usage_lock, flags); + return -1; +} + +static void floppy_release_irq_and_dma(void) +{ + int old_fdc; +#ifdef FLOPPY_SANITY_CHECK + int drive; +#endif + long tmpsize; + unsigned long tmpaddr; + unsigned long flags; + + spin_lock_irqsave(&floppy_usage_lock, flags); + if (--usage_count){ + spin_unlock_irqrestore(&floppy_usage_lock, flags); + return; + } + spin_unlock_irqrestore(&floppy_usage_lock, flags); + if(irqdma_allocated) + { + fd_disable_dma(); + fd_free_dma(); + fd_free_irq(); + irqdma_allocated=0; + } + fd_outb(0, FD_MODE); + floppy_enable_hlt(); + + if (floppy_track_buffer && max_buffer_sectors) { + tmpsize = max_buffer_sectors*1024; + tmpaddr = (unsigned long)floppy_track_buffer; + floppy_track_buffer = NULL; + max_buffer_sectors = 0; + buffer_min = buffer_max = -1; + fd_dma_mem_free(tmpaddr, tmpsize); + } + +#ifdef FLOPPY_SANITY_CHECK + for (drive=0; drive < N_FDC * 4; drive++) + if (timer_pending(motor_off_timer + drive)) + printk("motor off timer %d still active\n", drive); + + if (timer_pending(&fd_timeout)) + printk("floppy timer still active:%s\n", timeout_message); + if (timer_pending(&fd_timer)) + printk("auxiliary floppy timer still active\n"); + if (floppy_work.pending) + printk("work still pending\n"); +#endif + old_fdc = fdc; + for (fdc = 0; fdc < N_FDC; fdc++) + if (FDCS->address != -1) { + release_region(FDCS->address, 1); + release_region(FDCS->address + 2, 1); + release_region(FDCS->address + 4, 1); + if (fdc == 0) { + release_region(0xbe, 1); + release_region(0x4be, 1); + } + } + fdc = old_fdc; + MOD_DEC_USE_COUNT; +} + + +#ifdef MODULE + +char *floppy; + +static void __init parse_floppy_cfg_string(char *cfg) +{ + char *ptr; + + while(*cfg) { + for(ptr = cfg;*cfg && *cfg != ' ' && *cfg != '\t'; cfg++); + if (*cfg) { + *cfg = '\0'; + cfg++; + } + if (*ptr) + floppy_setup(ptr); + } +} + +int init_module(void) +{ + printk(KERN_INFO "inserting floppy driver for " UTS_RELEASE "\n"); + + if (floppy) + parse_floppy_cfg_string(floppy); + return floppy_init(); +} + +void cleanup_module(void) +{ + int drive; + + platform_device_unregister(&floppy_device); + devfs_unregister (devfs_handle); + blk_unregister_region(MKDEV(MAJOR_NR, 0), 256); + unregister_blkdev(MAJOR_NR, "fd"); + for (drive = 0; drive < N_DRIVE; drive++) { + if ((allowed_drive_mask & (1 << drive)) && + fdc_state[FDC(drive)].version != FDC_NONE) + del_gendisk(disks[drive]); + put_disk(disks[drive]); + } + + blk_cleanup_queue(&floppy_queue); + /* eject disk, if any */ + fd_eject(0); +} + +MODULE_PARM(floppy,"s"); +MODULE_PARM(FLOPPY_IRQ,"i"); +MODULE_PARM(FLOPPY_DMA,"i"); +MODULE_AUTHOR("Osamu Tomita"); +MODULE_SUPPORTED_DEVICE("fd"); +MODULE_LICENSE("GPL"); + +#else + +__setup ("floppy=", floppy_setup); +module_init(floppy_init) +#endif diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/block/genhd.c linux.2.5.47-ac4/drivers/block/genhd.c --- linux.2.5.47/drivers/block/genhd.c 2002-11-11 16:39:09.000000000 +0000 +++ linux.2.5.47-ac4/drivers/block/genhd.c 2002-11-11 16:51:32.000000000 +0000 @@ -123,6 +123,7 @@ EXPORT_SYMBOL(add_disk); EXPORT_SYMBOL(del_gendisk); +EXPORT_SYMBOL(get_gendisk); void unlink_gendisk(struct gendisk *disk) { diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/block/loop.c linux.2.5.47-ac4/drivers/block/loop.c --- linux.2.5.47/drivers/block/loop.c 2002-11-11 16:39:09.000000000 +0000 +++ linux.2.5.47-ac4/drivers/block/loop.c 2002-11-13 15:24:26.000000000 +0000 @@ -304,21 +304,16 @@ { struct lo_read_data cookie; struct file *file; - int error; + int retval; cookie.lo = lo; cookie.data = kmap(bvec->bv_page) + bvec->bv_offset; cookie.bsize = bsize; - - /* umm, what does this lock actually try to protect? */ - spin_lock_irq(&lo->lo_lock); file = lo->lo_backing_file; - spin_unlock_irq(&lo->lo_lock); - - error = file->f_op->sendfile(file, &pos, bvec->bv_len, + retval = file->f_op->sendfile(file, &pos, bvec->bv_len, lo_read_actor, &cookie); kunmap(bvec->bv_page); - return error; + return (retval < 0)? retval: 0; } static int diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/block/Makefile linux.2.5.47-ac4/drivers/block/Makefile --- linux.2.5.47/drivers/block/Makefile 2002-10-31 14:57:17.000000000 +0000 +++ linux.2.5.47-ac4/drivers/block/Makefile 2002-10-31 15:05:41.000000000 +0000 @@ -14,7 +14,11 @@ obj-y := elevator.o ll_rw_blk.o ioctl.o genhd.o scsi_ioctl.o deadline-iosched.o obj-$(CONFIG_MAC_FLOPPY) += swim3.o +ifneq ($(CONFIG_PC9800),y) obj-$(CONFIG_BLK_DEV_FD) += floppy.o +else +obj-$(CONFIG_BLK_DEV_FD) += floppy98.o +endif obj-$(CONFIG_AMIGA_FLOPPY) += amiflop.o obj-$(CONFIG_ATARI_FLOPPY) += ataflop.o obj-$(CONFIG_BLK_DEV_SWIM_IOP) += swim_iop.o diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/bluetooth/bluecard_cs.c linux.2.5.47-ac4/drivers/bluetooth/bluecard_cs.c --- linux.2.5.47/drivers/bluetooth/bluecard_cs.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/bluetooth/bluecard_cs.c 2002-11-13 15:21:49.000000000 +0000 @@ -849,6 +849,7 @@ link = &info->link; link->priv = info; + init_timer(&link->release); link->release.function = &bluecard_release; link->release.data = (u_long)link; link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/bluetooth/bt3c_cs.c linux.2.5.47-ac4/drivers/bluetooth/bt3c_cs.c --- linux.2.5.47/drivers/bluetooth/bt3c_cs.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/bluetooth/bt3c_cs.c 2002-11-13 15:21:49.000000000 +0000 @@ -643,6 +643,7 @@ link = &info->link; link->priv = info; + init_timer(&link->release); link->release.function = &bt3c_release; link->release.data = (u_long)link; link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/bluetooth/dtl1_cs.c linux.2.5.47-ac4/drivers/bluetooth/dtl1_cs.c --- linux.2.5.47/drivers/bluetooth/dtl1_cs.c 2002-10-31 14:57:19.000000000 +0000 +++ linux.2.5.47-ac4/drivers/bluetooth/dtl1_cs.c 2002-11-13 15:21:49.000000000 +0000 @@ -582,6 +582,7 @@ link = &info->link; link->priv = info; + init_timer(&link->release); link->release.function = &dtl1_release; link->release.data = (u_long)link; link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/cdrom/cm206.c linux.2.5.47-ac4/drivers/cdrom/cm206.c --- linux.2.5.47/drivers/cdrom/cm206.c 2002-11-11 16:39:09.000000000 +0000 +++ linux.2.5.47-ac4/drivers/cdrom/cm206.c 2002-11-13 15:21:49.000000000 +0000 @@ -1514,6 +1514,7 @@ memset(cd, 0, sizeof(*cd)); /* give'm some reasonable value */ cd->sector_last = -1; /* flag no data buffered */ cd->adapter_last = -1; + init_timer(&cd->timer); cd->timer.function = cm206_timeout; cd->max_sectors = (inw(r_data_status) & ds_ram_size) ? 24 : 97; printk(KERN_INFO "%d kB adapter memory available, " diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/char/agp/agp.h linux.2.5.47-ac4/drivers/char/agp/agp.h --- linux.2.5.47/drivers/char/agp/agp.h 2002-10-31 14:57:09.000000000 +0000 +++ linux.2.5.47-ac4/drivers/char/agp/agp.h 2002-10-31 15:05:30.000000000 +0000 @@ -294,7 +294,14 @@ #define I810_DRAM_ROW_0 0x00000001 #define I810_DRAM_ROW_0_SDRAM 0x00000001 - +/* Intel 7505 registers */ +#define INTEL_I7505_NAPBASELO 0x10 +#define INTEL_I7505_APSIZE 0x74 +#define INTEL_I7505_NCAPID 0x60 +#define INTEL_I7505_NISTAT 0x6c +#define INTEL_I7505_ATTBASE 0x78 +#define INTEL_I7505_ERRSTS 0x42 +#define INTEL_I7505_AGPCTRL 0x70 /* VIA register */ #define VIA_APBASE 0x10 diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/char/Kconfig linux.2.5.47-ac4/drivers/char/Kconfig --- linux.2.5.47/drivers/char/Kconfig 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/char/Kconfig 2002-11-13 22:49:50.000000000 +0000 @@ -1053,6 +1053,7 @@ config RTC tristate "Enhanced Real Time Clock Support" + depends on PPC32 != y && PARISC != y ---help--- If you say Y here and create a character special file /dev/rtc with major number 10 and minor number 135 using mknod ("man mknod"), you diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/char/keyboard.c linux.2.5.47-ac4/drivers/char/keyboard.c --- linux.2.5.47/drivers/char/keyboard.c 2002-11-11 16:39:09.000000000 +0000 +++ linux.2.5.47-ac4/drivers/char/keyboard.c 2002-11-11 16:52:13.000000000 +0000 @@ -681,8 +681,8 @@ static void k_pad(struct vc_data *vc, unsigned char value, char up_flag) { - static const char *pad_chars = "0123456789+-*/\015,.?()"; - static const char *app_map = "pqrstuvwxylSRQMnnmPQ"; + static const char *pad_chars = "0123456789+-*/\015,.?()#"; + static const char *app_map = "pqrstuvwxylSRQMnnmPQS"; if (up_flag) return; /* no action, if this is a key release */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/char/pcmcia/synclink_cs.c linux.2.5.47-ac4/drivers/char/pcmcia/synclink_cs.c --- linux.2.5.47/drivers/char/pcmcia/synclink_cs.c 2002-10-31 14:57:09.000000000 +0000 +++ linux.2.5.47-ac4/drivers/char/pcmcia/synclink_cs.c 2002-11-13 15:21:49.000000000 +0000 @@ -582,6 +582,7 @@ link->priv = info; /* Initialize the dev_link_t structure */ + init_timer(&link->release); link->release.function = &mgslpc_release; link->release.data = (u_long)link; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/char/sx.c linux.2.5.47-ac4/drivers/char/sx.c --- linux.2.5.47/drivers/char/sx.c 2002-11-11 16:39:09.000000000 +0000 +++ linux.2.5.47-ac4/drivers/char/sx.c 2002-11-11 20:19:35.000000000 +0000 @@ -2197,6 +2197,23 @@ } } + /* Now we're pretty much convinced that there is an SI board here, + but to prevent trouble, we'd better double check that we don't + have an SI1 board when we're probing for an SI2 board.... */ + + write_sx_byte (board, SI2_ISA_ID_BASE,0x10); + if ( IS_SI1_BOARD(board)) { + /* This should be an SI1 board, which has this + location writable... */ + if (read_sx_byte (board, SI2_ISA_ID_BASE) != 0x10) + return 0; + } else { + /* This should be an SI2 board, which has the bottom + 3 bits non-writable... */ + if (read_sx_byte (board, SI2_ISA_ID_BASE) == 0x10) + return 0; + } + printheader (); printk (KERN_DEBUG "sx: Found an SI board at %lx\n", board->hw_base); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/char/tty_io.c linux.2.5.47-ac4/drivers/char/tty_io.c --- linux.2.5.47/drivers/char/tty_io.c 2002-11-11 16:39:09.000000000 +0000 +++ linux.2.5.47-ac4/drivers/char/tty_io.c 2002-11-11 16:52:39.000000000 +0000 @@ -155,6 +155,9 @@ extern void uart_console_init(void); extern void sgi_serial_console_init(void); extern void sci_console_init(void); +extern void m68328_console_init(void); +extern void mcfrs_console_init(void); +extern void rs_360_init(void); extern void tx3912_console_init(void); extern void tx3912_rs_init(void); extern void hvc_console_init(void); @@ -2227,6 +2230,15 @@ #ifdef CONFIG_ARC_CONSOLE arc_console_init(); #endif +#ifdef CONFIG_SERIAL_68328 + m68328_console_init(); +#endif +#ifdef CONFIG_SERIAL_COLDFIRE + mcfrs_console_init(); +#endif +#ifdef CONFIG_SERIAL_68360 + rs_360_init(); +#endif #ifdef CONFIG_SERIAL_TX3912_CONSOLE tx3912_console_init(); #endif diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/char/upd4990a.c linux.2.5.47-ac4/drivers/char/upd4990a.c --- linux.2.5.47/drivers/char/upd4990a.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.47-ac4/drivers/char/upd4990a.c 2002-10-31 15:05:31.000000000 +0000 @@ -0,0 +1,438 @@ +/* + * 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 + +#define BCD_TO_BINARY(val) (((val) >> 4) * 10 + ((val) & 0xF)) +#define BINARY_TO_BCD(val) ((((val) / 10) << 4) | ((val) % 10)) + +/* + * 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 long long rtc_llseek(struct file *file, loff_t offset, int origin); + +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 long long rtc_llseek(struct file *file, loff_t offset, int origin) +{ + return -ESPIPE; +} + +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 = BCD_TO_BINARY(raw.sec); + wtime.tm_min = BCD_TO_BINARY(raw.min); + wtime.tm_hour = BCD_TO_BINARY(raw.hour); + wtime.tm_mday = BCD_TO_BINARY(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 = BCD_TO_BINARY(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 = BINARY_TO_BCD(wtime.tm_sec); + raw.min = BINARY_TO_BCD(wtime.tm_min); + raw.hour = BINARY_TO_BCD(wtime.tm_hour); + raw.mday = BINARY_TO_BCD(wtime.tm_mday); + raw.mon = wtime.tm_mon + 1; + raw.wday = wtime.tm_wday; + raw.year = BINARY_TO_BCD(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, + llseek: rtc_llseek, + read: rtc_read, + poll: rtc_poll, + ioctl: rtc_ioctl, + open: rtc_open, + release: rtc_release, + fasync: rtc_fasync, +}; + +static struct miscdevice rtc_dev= +{ + RTC_MINOR, + "rtc", + &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); + +#ifdef MODULE +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); +#endif + +EXPORT_NO_SYMBOLS; + +/* + * 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 = BCD_TO_BINARY(data.year) + 1900) < 1995) + year += 100; + p += sprintf(p, + "rtc_time\t: %02d:%02d:%02d\n" + "rtc_date\t: %04d-%02d-%02d\n", + BCD_TO_BINARY(data.hour), BCD_TO_BINARY(data.min), + BCD_TO_BINARY(data.sec), + year, data.mon, BCD_TO_BINARY(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 -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/fc4/fc.c linux.2.5.47-ac4/drivers/fc4/fc.c --- linux.2.5.47/drivers/fc4/fc.c 2002-11-11 16:39:09.000000000 +0000 +++ linux.2.5.47-ac4/drivers/fc4/fc.c 2002-11-13 15:21:49.000000000 +0000 @@ -676,6 +676,7 @@ l.magic = LSOMAGIC; FCND(("FCP Force Offline for %d channels\n", count)) init_MUTEX_LOCKED(&l.sem); + init_timer(&l.timer); l.timer.function = fcp_login_timeout; l.timer.data = (unsigned long)&l; atomic_set (&l.todo, count); @@ -977,7 +978,7 @@ fc->rst_pkt->eh_state = SCSI_STATE_QUEUED; - + init_timer(&fc->rst_pkt->eh_timeout); fc->rst_pkt->eh_timeout.data = (unsigned long) fc->rst_pkt; fc->rst_pkt->eh_timeout.expires = jiffies + FCP_RESET_TIMEOUT; fc->rst_pkt->eh_timeout.function = (void (*)(unsigned long))fcp_scsi_reset_done; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/hotplug/cpqphp_nvram.c linux.2.5.47-ac4/drivers/hotplug/cpqphp_nvram.c --- linux.2.5.47/drivers/hotplug/cpqphp_nvram.c 2002-10-31 14:57:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/hotplug/cpqphp_nvram.c 2002-11-02 22:11:18.000000000 +0000 @@ -177,12 +177,12 @@ spin_lock_irqsave(&int15_lock, flags); __asm__ ( - "xorl %%ebx,%%ebx - xorl %%edx,%%edx - pushf - push %%cs - cli - call *%6" + "xorl %%ebx,%%ebx\n" \ + "xorl %%edx,%%edx\n" \ + "pushf\n" \ + "push %%cs\n" \ + "cli\n" \ + "call *%6\n" : "=c" (*buf_size), "=a" (ret_val) : "a" (op), "c" (*buf_size), "S" (ev_name), "D" (buffer), "m" (compaq_int15_entry_point) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/ide/ide.c linux.2.5.47-ac4/drivers/ide/ide.c --- linux.2.5.47/drivers/ide/ide.c 2002-11-11 16:39:10.000000000 +0000 +++ linux.2.5.47-ac4/drivers/ide/ide.c 2002-11-14 18:03:01.000000000 +0000 @@ -222,37 +222,6 @@ EXPORT_SYMBOL(idetape); EXPORT_SYMBOL(idescsi); -#if (DISK_RECOVERY_TIME > 0) - -Error So the User Has To Fix the Compilation And Stop Hacking Port 0x43 -Does anyone ever use this anyway ?? - -/* - * For really screwy hardware (hey, at least it *can* be used with Linux) - * we can enforce a minimum delay time between successive operations. - */ -static unsigned long read_timer (ide_hwif_t *hwif) -{ - unsigned long t, flags; - int i; - - /* FIXME this is completely unsafe! */ - local_irq_save(flags); - t = jiffies * 11932; - outb_p(0, 0x43); - i = inb_p(0x40); - i |= inb_p(0x40) << 8; - local_irq_restore(flags); - return (t - i); -} -#endif /* DISK_RECOVERY_TIME */ - -static inline void set_recovery_timer (ide_hwif_t *hwif) -{ -#if (DISK_RECOVERY_TIME > 0) - hwif->last_time = read_timer(hwif); -#endif /* DISK_RECOVERY_TIME */ -} /* * Do not even *think* about calling this! @@ -372,7 +341,7 @@ /* safe default value for VESA and PCI */ system_bus_speed = 50; } - printk("ide: Assuming %dMHz system bus speed " + printk(KERN_INFO "ide: Assuming %dMHz system bus speed " "for PIO modes%s\n", system_bus_speed, idebus_parameter ? "" : "; override with idebus=xx"); } @@ -380,48 +349,6 @@ } /* - * This is our end_request replacement function. - */ -int ide_end_request (ide_drive_t *drive, int uptodate, int nr_sectors) -{ - struct request *rq; - unsigned long flags; - int ret = 1; - - spin_lock_irqsave(&ide_lock, flags); - rq = HWGROUP(drive)->rq; - - BUG_ON(!(rq->flags & REQ_STARTED)); - - if (!nr_sectors) - nr_sectors = rq->hard_cur_sectors; - - /* - * decide whether to reenable DMA -- 3 is a random magic for now, - * if we DMA timeout more than 3 times, just stay in PIO - */ - if (drive->state == DMA_PIO_RETRY && drive->retry_pio <= 3) { - drive->state = 0; - HWGROUP(drive)->hwif->ide_dma_on(drive); - } - - if (!end_that_request_first(rq, uptodate, nr_sectors)) { - add_disk_randomness(rq->rq_disk); - if (!blk_rq_tagged(rq)) - blkdev_dequeue_request(rq); - else - blk_queue_end_tag(&drive->queue, rq); - HWGROUP(drive)->rq = NULL; - end_that_request_last(rq); - ret = 0; - } - spin_unlock_irqrestore(&ide_lock, flags); - return ret; -} - -EXPORT_SYMBOL(ide_end_request); - -/* * current_capacity() returns the capacity (in sectors) of a drive * according to its current geometry/LBA settings. */ @@ -444,82 +371,6 @@ } /* - * Clean up after success/failure of an explicit drive cmd - */ -void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err) -{ - ide_hwif_t *hwif = HWIF(drive); - unsigned long flags; - struct request *rq; - - spin_lock_irqsave(&ide_lock, flags); - rq = HWGROUP(drive)->rq; - spin_unlock_irqrestore(&ide_lock, flags); - - if (rq->flags & REQ_DRIVE_CMD) { - u8 *args = (u8 *) rq->buffer; - if (rq->errors == 0) - rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT); - - if (args) { - args[0] = stat; - args[1] = err; - args[2] = hwif->INB(IDE_NSECTOR_REG); - } - } else if (rq->flags & REQ_DRIVE_TASK) { - u8 *args = (u8 *) rq->buffer; - if (rq->errors == 0) - rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT); - - if (args) { - args[0] = stat; - args[1] = err; - args[2] = hwif->INB(IDE_NSECTOR_REG); - args[3] = hwif->INB(IDE_SECTOR_REG); - args[4] = hwif->INB(IDE_LCYL_REG); - args[5] = hwif->INB(IDE_HCYL_REG); - args[6] = hwif->INB(IDE_SELECT_REG); - } - } else if (rq->flags & REQ_DRIVE_TASKFILE) { - ide_task_t *args = (ide_task_t *) rq->special; - if (rq->errors == 0) - rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT); - - if (args) { - if (args->tf_in_flags.b.data) { - u16 data = hwif->INW(IDE_DATA_REG); - args->tfRegister[IDE_DATA_OFFSET] = (data) & 0xFF; - args->hobRegister[IDE_DATA_OFFSET_HOB] = (data >> 8) & 0xFF; - } - args->tfRegister[IDE_ERROR_OFFSET] = err; - args->tfRegister[IDE_NSECTOR_OFFSET] = hwif->INB(IDE_NSECTOR_REG); - args->tfRegister[IDE_SECTOR_OFFSET] = hwif->INB(IDE_SECTOR_REG); - args->tfRegister[IDE_LCYL_OFFSET] = hwif->INB(IDE_LCYL_REG); - args->tfRegister[IDE_HCYL_OFFSET] = hwif->INB(IDE_HCYL_REG); - args->tfRegister[IDE_SELECT_OFFSET] = hwif->INB(IDE_SELECT_REG); - args->tfRegister[IDE_STATUS_OFFSET] = stat; - - if (drive->addressing == 1) { - hwif->OUTB(drive->ctl|0x80, IDE_CONTROL_REG_HOB); - args->hobRegister[IDE_FEATURE_OFFSET_HOB] = hwif->INB(IDE_FEATURE_REG); - args->hobRegister[IDE_NSECTOR_OFFSET_HOB] = hwif->INB(IDE_NSECTOR_REG); - args->hobRegister[IDE_SECTOR_OFFSET_HOB] = hwif->INB(IDE_SECTOR_REG); - args->hobRegister[IDE_LCYL_OFFSET_HOB] = hwif->INB(IDE_LCYL_REG); - args->hobRegister[IDE_HCYL_OFFSET_HOB] = hwif->INB(IDE_HCYL_REG); - } - } - } - - spin_lock_irqsave(&ide_lock, flags); - blkdev_dequeue_request(rq); - HWGROUP(drive)->rq = NULL; - end_that_request_last(rq); - spin_unlock_irqrestore(&ide_lock, flags); -} - -EXPORT_SYMBOL(ide_end_drive_cmd); - -/* * Error reporting, in human readable form (luxurious, but a memory hog). */ u8 ide_dump_status (ide_drive_t *drive, const char *msg, u8 stat) @@ -529,7 +380,7 @@ u8 err = 0; local_irq_set(flags); - printk("%s: %s: status=0x%02x", drive->name, msg, stat); + printk(KERN_WARNING "%s: %s: status=0x%02x", drive->name, msg, stat); #if FANCY_STATUS_DUMPS printk(" { "); if (stat & BUSY_STAT) { @@ -602,967 +453,7 @@ EXPORT_SYMBOL(ide_dump_status); -/* - * try_to_flush_leftover_data() is invoked in response to a drive - * unexpectedly having its DRQ_STAT bit set. As an alternative to - * resetting the drive, this routine tries to clear the condition - * by read a sector's worth of data from the drive. Of course, - * this may not help if the drive is *waiting* for data from *us*. - */ -void try_to_flush_leftover_data (ide_drive_t *drive) -{ - int i = (drive->mult_count ? drive->mult_count : 1) * SECTOR_WORDS; - - if (drive->media != ide_disk) - return; - while (i > 0) { - u32 buffer[16]; - u32 wcount = (i > 16) ? 16 : i; - - i -= wcount; - HWIF(drive)->ata_input_data(drive, buffer, wcount); - } -} - -EXPORT_SYMBOL(try_to_flush_leftover_data); - -/* - * FIXME Add an ATAPI error - */ - -/* - * ide_error() takes action based on the error returned by the drive. - */ -ide_startstop_t ide_error (ide_drive_t *drive, const char *msg, u8 stat) -{ - ide_hwif_t *hwif; - struct request *rq; - u8 err; - - err = ide_dump_status(drive, msg, stat); - 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, stat, err); - return ide_stopped; - } - if (rq->flags & REQ_DRIVE_TASKFILE) { - rq->errors = 1; - ide_end_drive_cmd(drive, stat, err); -// ide_end_taskfile(drive, stat, err); - return ide_stopped; - } - - if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) { - /* other bits are useless when BUSY */ - rq->errors |= ERROR_RESET; - } else { - if (drive->media != ide_disk) - goto media_out; - - if (stat & ERR_STAT) { - /* err has different meaning on cdrom and tape */ - if (err == ABRT_ERR) { - if (drive->select.b.lba && - (hwif->INB(IDE_COMMAND_REG) == WIN_SPECIFY)) - /* some newer drives don't - * support WIN_SPECIFY - */ - return ide_stopped; - } else if ((err & BAD_CRC) == BAD_CRC) { - drive->crc_count++; - /* UDMA crc error -- just retry the operation */ - } else if (err & (BBD_ERR | ECC_ERR)) { - /* retries won't help these */ - rq->errors = ERROR_MAX; - } else if (err & TRK0_ERR) { - /* help it find track zero */ - rq->errors |= ERROR_RECAL; - } - } -media_out: - if ((stat & DRQ_STAT) && rq_data_dir(rq) != WRITE) - try_to_flush_leftover_data(drive); - } - if (hwif->INB(IDE_STATUS_REG) & (BUSY_STAT|DRQ_STAT)) { - /* force an abort */ - 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); - } else { - if ((rq->errors & ERROR_RESET) == ERROR_RESET) { - ++rq->errors; - return ide_do_reset(drive); - } - if ((rq->errors & ERROR_RECAL) == ERROR_RECAL) - drive->special.b.recalibrate = 1; - ++rq->errors; - } - return ide_stopped; -} -EXPORT_SYMBOL(ide_error); - -/* - * Issue a simple drive command - * The drive must be selected beforehand. - */ -void ide_cmd (ide_drive_t *drive, u8 cmd, u8 nsect, ide_handler_t *handler) -{ - ide_hwif_t *hwif = HWIF(drive); - if (HWGROUP(drive)->handler != NULL) - BUG(); - ide_set_handler(drive, handler, WAIT_CMD, NULL); - if (IDE_CONTROL_REG) - hwif->OUTB(drive->ctl,IDE_CONTROL_REG); /* clear nIEN */ - SELECT_MASK(drive,0); - hwif->OUTB(nsect,IDE_NSECTOR_REG); - hwif->OUTB(cmd,IDE_COMMAND_REG); -} - -EXPORT_SYMBOL(ide_cmd); - -/* - * drive_cmd_intr() is invoked on completion of a special DRIVE_CMD. - */ -ide_startstop_t drive_cmd_intr (ide_drive_t *drive) -{ - struct request *rq = HWGROUP(drive)->rq; - ide_hwif_t *hwif = HWIF(drive); - u8 *args = (u8 *) rq->buffer; - u8 stat = hwif->INB(IDE_STATUS_REG); - int retries = 10; - - local_irq_enable(); - if ((stat & DRQ_STAT) && args && args[3]) { - u8 io_32bit = drive->io_32bit; - drive->io_32bit = 0; - hwif->ata_input_data(drive, &args[4], args[3] * SECTOR_WORDS); - drive->io_32bit = io_32bit; - while (((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) && retries--) - udelay(100); - } - - if (!OK_STAT(stat, READY_STAT, BAD_STAT)) - return DRIVER(drive)->error(drive, "drive_cmd", stat); - /* calls ide_end_drive_cmd */ - ide_end_drive_cmd(drive, stat, hwif->INB(IDE_ERROR_REG)); - return ide_stopped; -} - -EXPORT_SYMBOL(drive_cmd_intr); - -/* - * do_special() is used to issue WIN_SPECIFY, WIN_RESTORE, and WIN_SETMULT - * commands to a drive. It used to do much more, but has been scaled back. - */ -ide_startstop_t do_special (ide_drive_t *drive) -{ - special_t *s = &drive->special; - -#ifdef DEBUG - printk("%s: do_special: 0x%02x\n", drive->name, s->all); -#endif - if (s->b.set_tune) { - 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("%s: bad special flag: 0x%02x\n", drive->name, s->all); - s->all = 0; - } - return ide_stopped; -} - -EXPORT_SYMBOL(do_special); - -/* - * execute_drive_cmd() issues a special drive command, - * usually initiated by ioctl() from the external hdparm program. - */ -ide_startstop_t execute_drive_cmd (ide_drive_t *drive, struct request *rq) -{ - ide_hwif_t *hwif = HWIF(drive); - if (rq->flags & REQ_DRIVE_TASKFILE) { - ide_task_t *args = rq->special; - - if (!args) - goto done; - - if (args->tf_out_flags.all != 0) - return flagged_taskfile(drive, args); - return do_rw_taskfile(drive, args); - } else if (rq->flags & REQ_DRIVE_TASK) { - u8 *args = rq->buffer; - u8 sel; - - if (!args) - goto done; -#ifdef DEBUG - printk("%s: DRIVE_TASK_CMD ", drive->name); - printk("cmd=0x%02x ", args[0]); - printk("fr=0x%02x ", args[1]); - printk("ns=0x%02x ", args[2]); - printk("sc=0x%02x ", args[3]); - printk("lcyl=0x%02x ", args[4]); - printk("hcyl=0x%02x ", args[5]); - printk("sel=0x%02x\n", args[6]); -#endif - hwif->OUTB(args[1], IDE_FEATURE_REG); - hwif->OUTB(args[3], IDE_SECTOR_REG); - hwif->OUTB(args[4], IDE_LCYL_REG); - hwif->OUTB(args[5], IDE_HCYL_REG); - sel = (args[6] & ~0x10); - if (drive->select.b.unit) - sel |= 0x10; - hwif->OUTB(sel, IDE_SELECT_REG); - ide_cmd(drive, args[0], args[2], &drive_cmd_intr); - return ide_started; - } else if (rq->flags & REQ_DRIVE_CMD) { - u8 *args = rq->buffer; - - if (!args) - goto done; -#ifdef DEBUG - printk("%s: DRIVE_CMD ", drive->name); - printk("cmd=0x%02x ", args[0]); - printk("sc=0x%02x ", args[1]); - printk("fr=0x%02x ", args[2]); - printk("xx=0x%02x\n", args[3]); -#endif - if (args[0] == WIN_SMART) { - hwif->OUTB(0x4f, IDE_LCYL_REG); - hwif->OUTB(0xc2, IDE_HCYL_REG); - hwif->OUTB(args[2],IDE_FEATURE_REG); - hwif->OUTB(args[1],IDE_SECTOR_REG); - ide_cmd(drive, args[0], args[3], &drive_cmd_intr); - return ide_started; - } - hwif->OUTB(args[2],IDE_FEATURE_REG); - ide_cmd(drive, args[0], args[1], &drive_cmd_intr); - return ide_started; - } - -done: - /* - * NULL is actually a valid way of waiting for - * all current requests to be flushed from the queue. - */ -#ifdef DEBUG - printk("%s: DRIVE_CMD (null)\n", drive->name); -#endif - ide_end_drive_cmd(drive, - hwif->INB(IDE_STATUS_REG), - hwif->INB(IDE_ERROR_REG)); - return ide_stopped; -} - -EXPORT_SYMBOL(execute_drive_cmd); - -/* - * start_request() initiates handling of a new I/O request - * needed to reverse the perverted changes anonymously made back - * 2.3.99-pre6 - */ -ide_startstop_t start_request (ide_drive_t *drive, struct request *rq) -{ - ide_startstop_t startstop; - unsigned long block; - - BUG_ON(!(rq->flags & REQ_STARTED)); - -#ifdef DEBUG - printk("%s: start_request: current=0x%08lx\n", - HWIF(drive)->name, (unsigned long) rq); -#endif - - /* bail early if we've exceeded max_failures */ - if (drive->max_failures && (drive->failures > drive->max_failures)) { - goto kill_rq; - } - - /* - * bail early if we've sent a device to sleep, however how to wake - * this needs to be a masked flag. FIXME for proper operations. - */ - if (drive->suspend_reset) - goto kill_rq; - - block = rq->sector; - if (blk_fs_request(rq) && - (drive->media == ide_disk || drive->media == ide_floppy)) { - block += drive->sect0; - } - /* Yecch - this will shift the entire interval, - possibly killing some innocent following sector */ - if (block == 0 && drive->remap_0_to_1 == 1) - block = 1; /* redirect MBR access to EZ-Drive partn table */ - -#if (DISK_RECOVERY_TIME > 0) - while ((read_timer() - HWIF(drive)->last_time) < DISK_RECOVERY_TIME); -#endif - - SELECT_DRIVE(drive); - if (ide_wait_stat(&startstop, drive, drive->ready_stat, BUSY_STAT|DRQ_STAT, WAIT_READY)) { - printk("%s: drive not ready for command\n", drive->name); - return startstop; - } - if (!drive->special.all) { - if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK)) - 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("%s: media type %d not supported\n", drive->name, drive->media); - goto kill_rq; - } - return do_special(drive); -kill_rq: - if (drive->driver != NULL) - DRIVER(drive)->end_request(drive, 0, 0); - else - ide_end_request(drive, 0, 0); - return ide_stopped; -} - -EXPORT_SYMBOL(start_request); - -int restart_request (ide_drive_t *drive, struct request *rq) -{ - (void) start_request(drive, rq); - return 0; -} - -EXPORT_SYMBOL(restart_request); - -/* - * ide_stall_queue() can be used by a drive to give excess bandwidth back - * to the hwgroup by sleeping for timeout jiffies. - */ -void ide_stall_queue (ide_drive_t *drive, unsigned long timeout) -{ - if (timeout > WAIT_WORSTCASE) - timeout = WAIT_WORSTCASE; - drive->sleep = timeout + jiffies; -} - -EXPORT_SYMBOL(ide_stall_queue); - -#define WAKEUP(drive) ((drive)->service_start + 2 * (drive)->service_time) - -/* - * choose_drive() selects the next drive which will be serviced. - */ -static inline ide_drive_t *choose_drive (ide_hwgroup_t *hwgroup) -{ - ide_drive_t *drive, *best; - -repeat: - best = NULL; - drive = hwgroup->drive; - do { - if (!blk_queue_empty(&drive->queue) && (!drive->sleep || time_after_eq(jiffies, drive->sleep))) { - if (!best - || (drive->sleep && (!best->sleep || 0 < (signed long)(best->sleep - drive->sleep))) - || (!best->sleep && 0 < (signed long)(WAKEUP(best) - WAKEUP(drive)))) - { - if (!blk_queue_plugged(&drive->queue)) - best = drive; - } - } - } while ((drive = drive->next) != hwgroup->drive); - if (best && best->nice1 && !best->sleep && best != hwgroup->drive && best->service_time > WAIT_MIN_SLEEP) { - long t = (signed long)(WAKEUP(best) - jiffies); - if (t >= WAIT_MIN_SLEEP) { - /* - * We *may* have some time to spare, but first let's see if - * someone can potentially benefit from our nice mood today.. - */ - drive = best->next; - do { - if (!drive->sleep - && 0 < (signed long)(WAKEUP(drive) - (jiffies - best->service_time)) - && 0 < (signed long)((jiffies + t) - WAKEUP(drive))) - { - ide_stall_queue(best, IDE_MIN(t, 10 * WAIT_MIN_SLEEP)); - goto repeat; - } - } while ((drive = drive->next) != best); - } - } - return best; -} - -/* - * Issue a new request to a drive from hwgroup - * Caller must have already done spin_lock_irqsave(&ide_lock, ..); - * - * A hwgroup is a serialized group of IDE interfaces. Usually there is - * exactly one hwif (interface) per hwgroup, but buggy controllers (eg. CMD640) - * may have both interfaces in a single hwgroup to "serialize" access. - * Or possibly multiple ISA interfaces can share a common IRQ by being grouped - * together into one hwgroup for serialized access. - * - * Note also that several hwgroups can end up sharing a single IRQ, - * possibly along with many other devices. This is especially common in - * PCI-based systems with off-board IDE controller cards. - * - * The IDE driver uses the single global ide_lock spinlock to protect - * access to the request queues, and to protect the hwgroup->busy flag. - * - * The first thread into the driver for a particular hwgroup sets the - * hwgroup->busy flag to indicate that this hwgroup is now active, - * and then initiates processing of the top request from the request queue. - * - * Other threads attempting entry notice the busy setting, and will simply - * queue their new requests and exit immediately. Note that hwgroup->busy - * remains set even when the driver is merely awaiting the next interrupt. - * Thus, the meaning is "this hwgroup is busy processing a request". - * - * When processing of a request completes, the completing thread or IRQ-handler - * will start the next request from the queue. If no more work remains, - * the driver will clear the hwgroup->busy flag and exit. - * - * The ide_lock (spinlock) is used to protect all access to the - * hwgroup->busy flag, but is otherwise not needed for most processing in - * the driver. This makes the driver much more friendlier to shared IRQs - * than previous designs, while remaining 100% (?) SMP safe and capable. - */ -/* --BenH: made non-static as ide-pmac.c uses it to kick the hwgroup back - * into life on wakeup from machine sleep. - */ -void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq) -{ - ide_drive_t *drive; - ide_hwif_t *hwif; - struct request *rq; - ide_startstop_t startstop; - - /* for atari only: POSSIBLY BROKEN HERE(?) */ - ide_get_lock(&ide_intr_lock, ide_intr, hwgroup); - - /* necessary paranoia: ensure IRQs are masked on local CPU */ - local_irq_disable(); - - while (!hwgroup->busy) { - hwgroup->busy = 1; - drive = choose_drive(hwgroup); - if (drive == NULL) { - unsigned long sleep = 0; - hwgroup->rq = NULL; - drive = hwgroup->drive; - do { - if (drive->sleep && (!sleep || 0 < (signed long)(sleep - drive->sleep))) - sleep = drive->sleep; - } while ((drive = drive->next) != hwgroup->drive); - if (sleep) { - /* - * Take a short snooze, and then wake up this hwgroup again. - * This gives other hwgroups on the same a chance to - * play fairly with us, just in case there are big differences - * in relative throughputs.. don't want to hog the cpu too much. - */ - if (time_before(sleep, jiffies + WAIT_MIN_SLEEP)) - sleep = jiffies + WAIT_MIN_SLEEP; -#if 1 - if (timer_pending(&hwgroup->timer)) - printk("ide_set_handler: timer already active\n"); -#endif - /* so that ide_timer_expiry knows what to do */ - hwgroup->sleeping = 1; - mod_timer(&hwgroup->timer, sleep); - /* we purposely leave hwgroup->busy==1 - * while sleeping */ - } else { - /* Ugly, but how can we sleep for the lock - * otherwise? perhaps from tq_disk? - */ - - /* for atari only */ - ide_release_lock(&ide_intr_lock); - hwgroup->busy = 0; - } - - /* no more work for this hwgroup (for now) */ - return; - } - hwif = HWIF(drive); - if (hwgroup->hwif->sharing_irq && - hwif != hwgroup->hwif && - hwif->io_ports[IDE_CONTROL_OFFSET]) { - /* set nIEN for previous hwif */ - SELECT_INTERRUPT(drive); - } - hwgroup->hwif = hwif; - hwgroup->drive = drive; - drive->sleep = 0; - drive->service_start = jiffies; - -queue_next: - if (!ata_can_queue(drive)) { - if (!ata_pending_commands(drive)) - hwgroup->busy = 0; - - break; - } - - if (blk_queue_plugged(&drive->queue)) { - if (drive->using_tcq) - break; - - printk("ide: huh? queue was plugged!\n"); - break; - } - - /* - * we know that the queue isn't empty, but this can happen - * if the q->prep_rq_fn() decides to kill a request - */ - rq = elv_next_request(&drive->queue); - if (!rq) { - hwgroup->busy = !!ata_pending_commands(drive); - break; - } - - if (!rq->bio && ata_pending_commands(drive)) - break; - - hwgroup->rq = rq; - - /* - * Some systems have trouble with IDE IRQs arriving while - * the driver is still setting things up. So, here we disable - * the IRQ used by this interface while the request is being started. - * This may look bad at first, but pretty much the same thing - * happens anyway when any interrupt comes in, IDE or otherwise - * -- the kernel masks the IRQ while it is being handled. - */ - if (masked_irq && hwif->irq != masked_irq) - disable_irq_nosync(hwif->irq); - spin_unlock(&ide_lock); - local_irq_enable(); - /* allow other IRQs while we start this request */ - startstop = start_request(drive, rq); - spin_lock_irq(&ide_lock); - if (masked_irq && hwif->irq != masked_irq) - enable_irq(hwif->irq); - if (startstop == ide_released) - goto queue_next; - if (startstop == ide_stopped) - hwgroup->busy = 0; - } -} - -EXPORT_SYMBOL(ide_do_request); - -/* - * Passes the stuff to ide_do_request - */ -void do_ide_request(request_queue_t *q) -{ - ide_do_request(q->queuedata, 0); -} - -/* - * un-busy the hwgroup etc, and clear any pending DMA status. we want to - * retry the current request in pio mode instead of risking tossing it - * all away - */ -void ide_dma_timeout_retry(ide_drive_t *drive) -{ - ide_hwif_t *hwif = HWIF(drive); - struct request *rq; - - /* - * end current dma transaction - */ - (void) hwif->ide_dma_end(drive); - - /* - * complain a little, later we might remove some of this verbosity - */ - printk("%s: timeout waiting for DMA\n", drive->name); - (void) hwif->ide_dma_timeout(drive); - - /* - * disable dma for now, but remember that we did so because of - * a timeout -- we'll reenable after we finish this next request - * (or rather the first chunk of it) in pio. - */ - drive->retry_pio++; - drive->state = DMA_PIO_RETRY; - (void) hwif->ide_dma_off_quietly(drive); - - /* - * un-busy drive etc (hwgroup->busy is cleared on return) and - * make sure request is sane - */ - rq = HWGROUP(drive)->rq; - HWGROUP(drive)->rq = NULL; - - rq->errors = 0; - rq->sector = rq->bio->bi_sector; - rq->current_nr_sectors = bio_iovec(rq->bio)->bv_len >> 9; - rq->hard_cur_sectors = rq->current_nr_sectors; - if (rq->bio) - rq->buffer = NULL; -} - -EXPORT_SYMBOL(ide_dma_timeout_retry); - -/* - * ide_timer_expiry() is our timeout function for all drive operations. - * But note that it can also be invoked as a result of a "sleep" operation - * triggered by the mod_timer() call in ide_do_request. - */ -void ide_timer_expiry (unsigned long data) -{ - ide_hwgroup_t *hwgroup = (ide_hwgroup_t *) data; - ide_handler_t *handler; - ide_expiry_t *expiry; - unsigned long flags; - unsigned long wait; - - spin_lock_irqsave(&ide_lock, flags); - del_timer(&hwgroup->timer); - - if ((handler = hwgroup->handler) == NULL) { - /* - * Either a marginal timeout occurred - * (got the interrupt just as timer expired), - * or we were "sleeping" to give other devices a chance. - * Either way, we don't really want to complain about anything. - */ - if (hwgroup->sleeping) { - hwgroup->sleeping = 0; - hwgroup->busy = 0; - } - } else { - ide_drive_t *drive = hwgroup->drive; - if (!drive) { - printk("ide_timer_expiry: hwgroup->drive was NULL\n"); - hwgroup->handler = NULL; - } else { - ide_hwif_t *hwif; - ide_startstop_t startstop = ide_stopped; - if (!hwgroup->busy) { - hwgroup->busy = 1; /* paranoia */ - printk("%s: ide_timer_expiry: hwgroup->busy was 0 ??\n", drive->name); - } - if ((expiry = hwgroup->expiry) != NULL) { - /* continue */ - if ((wait = expiry(drive)) != 0) { - /* reset timer */ - hwgroup->timer.expires = jiffies + wait; - add_timer(&hwgroup->timer); - spin_unlock_irqrestore(&ide_lock, flags); - return; - } - } - hwgroup->handler = NULL; - /* - * We need to simulate a real interrupt when invoking - * the handler() function, which means we need to - * globally mask the specific IRQ: - */ - spin_unlock(&ide_lock); - hwif = HWIF(drive); -#if DISABLE_IRQ_NOSYNC - disable_irq_nosync(hwif->irq); -#else - /* disable_irq_nosync ?? */ - disable_irq(hwif->irq); -#endif /* DISABLE_IRQ_NOSYNC */ - /* local CPU only, - * as if we were handling an interrupt */ - local_irq_disable(); - if (hwgroup->poll_timeout != 0) { - startstop = handler(drive); - } else if (drive_is_ready(drive)) { - if (drive->waiting_for_dma) - (void) hwgroup->hwif->ide_dma_lostirq(drive); - (void)ide_ack_intr(hwif); - printk("%s: lost interrupt\n", drive->name); - startstop = handler(drive); - } else { - if (drive->waiting_for_dma) { - startstop = ide_stopped; - ide_dma_timeout_retry(drive); - } else - startstop = DRIVER(drive)->error(drive, "irq timeout", hwif->INB(IDE_STATUS_REG)); - } - set_recovery_timer(hwif); - drive->service_time = jiffies - drive->service_start; - enable_irq(hwif->irq); - spin_lock_irq(&ide_lock); - if (startstop == ide_stopped) - hwgroup->busy = 0; - } - } - ide_do_request(hwgroup, 0); - spin_unlock_irqrestore(&ide_lock, flags); -} - -EXPORT_SYMBOL(ide_timer_expiry); - -/* - * There's nothing really useful we can do with an unexpected interrupt, - * other than reading the status register (to clear it), and logging it. - * There should be no way that an irq can happen before we're ready for it, - * so we needn't worry much about losing an "important" interrupt here. - * - * 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. - * - * This routine assumes __cli() is in effect when called. - * - * If an unexpected interrupt happens on irq15 while we are handling irq14 - * and if the two interfaces are "serialized" (CMD640), then it looks like - * we could screw up by interfering with a new request being set up for irq15. - * - * In reality, this is a non-issue. The new command is not sent unless the - * drive is ready to accept one, in which case we know the drive is not - * trying to interrupt us. And ide_set_handler() is always invoked before - * completing the issuance of any new drive command, so we will not be - * accidentally invoked as a result of any valid command completion interrupt. - * - */ -static void unexpected_intr (int irq, ide_hwgroup_t *hwgroup) -{ - u8 stat; - ide_hwif_t *hwif = hwgroup->hwif; - - /* - * handle the unexpected interrupt - */ - do { - if (hwif->irq == irq) { - stat = hwif->INB(hwif->io_ports[IDE_STATUS_OFFSET]); - if (!OK_STAT(stat, READY_STAT, BAD_STAT)) { - /* Try to not flood the console with msgs */ - static unsigned long last_msgtime, count; - ++count; - if (time_after(jiffies, last_msgtime + HZ)) { - last_msgtime = jiffies; - printk("%s%s: unexpected interrupt, " - "status=0x%02x, count=%ld\n", - hwif->name, - (hwif->next==hwgroup->hwif) ? "" : "(?)", stat, count); - } - } - } - } while ((hwif = hwif->next) != hwgroup->hwif); -} - -/* - * entry point for all interrupts, caller does __cli() for us - */ -void ide_intr (int irq, void *dev_id, struct pt_regs *regs) -{ - unsigned long flags; - ide_hwgroup_t *hwgroup = (ide_hwgroup_t *)dev_id; - ide_hwif_t *hwif; - ide_drive_t *drive; - ide_handler_t *handler; - ide_startstop_t startstop; - - spin_lock_irqsave(&ide_lock, flags); - hwif = hwgroup->hwif; - - if (!ide_ack_intr(hwif)) { - spin_unlock_irqrestore(&ide_lock, flags); - return; - } - - if ((handler = hwgroup->handler) == NULL || - hwgroup->poll_timeout != 0) { - /* - * Not expecting an interrupt from this drive. - * That means this could be: - * (1) an interrupt from another PCI device - * sharing the same PCI INT# as us. - * or (2) a drive just entered sleep or standby mode, - * and is interrupting to let us know. - * or (3) a spurious interrupt of unknown origin. - * - * For PCI, we cannot tell the difference, - * so in that case we just ignore it and hope it goes away. - */ -#ifdef CONFIG_BLK_DEV_IDEPCI - if (hwif->pci_dev && !hwif->pci_dev->vendor) -#endif /* CONFIG_BLK_DEV_IDEPCI */ - { - /* - * Probably not a shared PCI interrupt, - * so we can safely try to do something about it: - */ - unexpected_intr(irq, hwgroup); -#ifdef CONFIG_BLK_DEV_IDEPCI - } else { - /* - * Whack the status register, just in case - * we have a leftover pending IRQ. - */ - (void) hwif->INB(hwif->io_ports[IDE_STATUS_OFFSET]); -#endif /* CONFIG_BLK_DEV_IDEPCI */ - } - spin_unlock_irqrestore(&ide_lock, flags); - return; - } - drive = hwgroup->drive; - if (!drive) { - /* - * This should NEVER happen, and there isn't much - * we could do about it here. - */ - spin_unlock_irqrestore(&ide_lock, flags); - return; - } - if (!drive_is_ready(drive)) { - /* - * This happens regularly when we share a PCI IRQ with - * another device. Unfortunately, it can also happen - * with some buggy drives that trigger the IRQ before - * their status register is up to date. Hopefully we have - * enough advance overhead that the latter isn't a problem. - */ - spin_unlock_irqrestore(&ide_lock, flags); - return; - } - if (!hwgroup->busy) { - hwgroup->busy = 1; /* paranoia */ - printk("%s: ide_intr: hwgroup->busy was 0 ??\n", drive->name); - } - hwgroup->handler = NULL; - del_timer(&hwgroup->timer); - spin_unlock(&ide_lock); - - if (drive->unmask) - local_irq_enable(); - /* service this interrupt, may set handler for next interrupt */ - startstop = handler(drive); - spin_lock_irq(&ide_lock); - - /* - * Note that handler() may have set things up for another - * interrupt to occur soon, but it cannot happen until - * we exit from this routine, because it will be the - * same irq as is currently being serviced here, and Linux - * won't allow another of the same (on any CPU) until we return. - */ - set_recovery_timer(HWIF(drive)); - drive->service_time = jiffies - drive->service_start; - if (startstop == ide_stopped) { - if (hwgroup->handler == NULL) { /* paranoia */ - hwgroup->busy = 0; - ide_do_request(hwgroup, hwif->irq); - } else { - printk("%s: ide_intr: huh? expected NULL handler " - "on exit\n", drive->name); - } - } - spin_unlock_irqrestore(&ide_lock, flags); -} - -EXPORT_SYMBOL(ide_intr); - -/* - * This function is intended to be used prior to invoking ide_do_drive_cmd(). - */ -void ide_init_drive_cmd (struct request *rq) -{ - memset(rq, 0, sizeof(*rq)); - rq->flags = REQ_DRIVE_CMD; -} - -EXPORT_SYMBOL(ide_init_drive_cmd); - -/* - * This function issues a special IDE device request - * onto the request queue. - * - * If action is ide_wait, then the rq is queued at the end of the - * request queue, and the function sleeps until it has been processed. - * This is for use when invoked from an ioctl handler. - * - * If action is ide_preempt, then the rq is queued at the head of - * the request queue, displacing the currently-being-processed - * request and this function returns immediately without waiting - * for the new rq to be completed. This is VERY DANGEROUS, and is - * intended for careful use by the ATAPI tape/cdrom driver code. - * - * If action is ide_next, then the rq is queued immediately after - * the currently-being-processed-request (if any), and the function - * returns without waiting for the new rq to be completed. As above, - * This is VERY DANGEROUS, and is intended for careful use by the - * ATAPI tape/cdrom driver code. - * - * If action is ide_end, then the rq is queued at the end of the - * request queue, and the function returns immediately without waiting - * for the new rq to be completed. This is again intended for careful - * use by the ATAPI tape/cdrom driver code. - */ -int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t action) -{ - unsigned long flags; - ide_hwgroup_t *hwgroup = HWGROUP(drive); - DECLARE_COMPLETION(wait); - int insert_end = 1, err; - -#ifdef CONFIG_BLK_DEV_PDC4030 - if (HWIF(drive)->chipset == ide_pdc4030 && rq->buffer != NULL) - return -ENOSYS; /* special drive cmds not supported */ -#endif - rq->errors = 0; - rq->rq_status = RQ_ACTIVE; - - rq->rq_disk = drive->disk; - - /* - * we need to hold an extra reference to request for safe inspection - * after completion - */ - if (action == ide_wait) { - rq->ref_count++; - rq->waiting = &wait; - } - - spin_lock_irqsave(&ide_lock, flags); - if (action == ide_preempt) { - hwgroup->rq = NULL; - insert_end = 0; - } - __elv_add_request(&drive->queue, rq, insert_end, 0); - ide_do_request(hwgroup, 0); - spin_unlock_irqrestore(&ide_lock, flags); - - err = 0; - if (action == ide_wait) { - wait_for_completion(&wait); - if (rq->errors) - err = -EIO; - - blk_put_request(rq); - } - - return err; -} - -EXPORT_SYMBOL(ide_do_drive_cmd); void ide_probe_module (void) { @@ -1632,11 +523,18 @@ #define hwif_release_region(addr, num) \ ((hwif->mmio) ? release_mem_region((addr),(num)) : release_region((addr),(num))) -/* - * Note that we only release the standard ports, - * and do not even try to handle any extra ports - * allocated for weird IDE interface chipsets. +/** + * hwif_unregister - free IDE resources + * + * Note that we only release the standard ports, + * and do not even try to handle any extra ports + * allocated for weird IDE interface chipsets. + * + * Note also that we don't yet handle mmio resources here. More + * importantly our caller should be doing this so we need to + * restructure this as a helper function for drivers. */ + void hwif_unregister (ide_hwif_t *hwif) { u32 i = 0; @@ -1665,6 +563,28 @@ extern void init_hwif_data(unsigned int index); +/** + * ide_unregister - free an ide interface + * @index: index of interface (will change soon to a pointer) + * + * Perform the final unregister of an IDE interface. At the moment + * we don't refcount interfaces so this will also get split up. + * + * Locking: + * The caller must not hold the IDE locks + * The drive present/vanishing is not yet properly locked + * Take care with the callbacks. These have been split to avoid + * deadlocking the IDE layer. The shutdown callback is called + * before we take the lock and free resources. It is up to the + * caller to be sure there is no pending I/O here, and that + * the interfce will not be reopened (present/vanishing locking + * isnt yet done btw). After we commit to the final kill we + * call the cleanup callback with the ide locks held. + * + * Unregister restores the hwif structures to the default state. + * This is raving bonkers. + */ + void ide_unregister (unsigned int index) { ide_drive_t *drive, *d; @@ -1675,7 +595,8 @@ ide_hwif_t old_hwif; if (index >= MAX_HWIFS) - return; + BUG(); + spin_lock_irqsave(&ide_lock, flags); hwif = &ide_hwifs[index]; if (!hwif->present) @@ -1686,12 +607,21 @@ continue; if (drive->usage) goto abort; - if (drive->driver != NULL && DRIVER(drive)->cleanup(drive)) + if (drive->driver != NULL && DRIVER(drive)->shutdown(drive)) goto abort; } hwif->present = 0; spin_unlock_irqrestore(&ide_lock, flags); + + for (unit = 0; unit < MAX_DRIVES; ++unit) { + drive = &hwif->drives[unit]; + if (!drive->present) + continue; + if (drive->driver != NULL) + DRIVER(drive)->cleanup(drive); + } + #ifdef CONFIG_PROC_FS destroy_proc_ide_drives(hwif); #endif @@ -1752,7 +682,7 @@ else hwgroup->hwif = HWIF(hwgroup->drive); -#if defined(CONFIG_BLK_DEV_IDEDMA) && !defined(CONFIG_DMA_NONPCI) +#if !defined(CONFIG_DMA_NONPCI) if (hwif->dma_base) { (void) ide_release_dma(hwif); @@ -1764,7 +694,7 @@ hwif->dma_vendor3 = 0; hwif->dma_prdtable = 0; } -#endif /* (CONFIG_BLK_DEV_IDEDMA) && !(CONFIG_DMA_NONPCI) */ +#endif /* !(CONFIG_DMA_NONPCI) */ /* * Remove us from the kernel's knowledge @@ -1894,11 +824,21 @@ EXPORT_SYMBOL(ide_unregister); -/* - * Setup hw_regs_t structure described by parameters. You - * may set up the hw structure yourself OR use this routine to - * do it for you. +/** + * ide_setup_ports - set up IDE interface ports + * @hw: register descriptions + * @base: base register + * @offsets: table of register offsets + * @ctrl: control register + * @ack_irq: IRQ ack + * @irq: interrupt lie + * + * Setup hw_regs_t structure described by parameters. You + * may set up the hw structure yourself OR use this routine to + * do it for you. This is basically a helper + * */ + void ide_setup_ports ( hw_regs_t *hw, ide_ioreg_t base, int *offsets, ide_ioreg_t ctrl, ide_ioreg_t intr, @@ -2004,6 +944,27 @@ EXPORT_SYMBOL(ide_register); +/** + * ide_add_setting - attach an IDE setting + * drive: drive the setting is for + * name: name of setting + * rw: set if writable + * read_ioctl: read function + * write_ioctl: write function + * data_type: form expected + * min: minimum + * max: maximum + * mul_factor: multiply by + * div_factor: divide by + * data: value + * set: handling for setting + * + * Add a setting to the IDE drive. Support automatic removal and allow + * all the work to be done by plugged in handlers. This code is also + * rather short on locking, but the current plan is to do the locking + * internally to the function. + */ + void ide_add_setting (ide_drive_t *drive, const char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set) { ide_settings_t **p = (ide_settings_t **) &drive->settings, *setting = NULL; @@ -2038,6 +999,14 @@ EXPORT_SYMBOL(ide_add_setting); +/** + * ide_remove_setting - remove an ioctl setting + * @name: name of the property + * + * Remove a drive ioctl setting that was created by ide_add_setting. + * Again this needs the locking fixed + */ + void ide_remove_setting (ide_drive_t *drive, char *name) { ide_settings_t **p = (ide_settings_t **) &drive->settings, *setting; @@ -2053,6 +1022,16 @@ EXPORT_SYMBOL(ide_remove_setting); +/** + * ide_find_setting_by_ioctl - find a setting handler by its command + * @drive: drive to act for + * @cmd: ioctl command code + * + * Scan the drive handlers for an ioctl handler for this function. + * The handlers vary by drive and sometimes by drive state. + * Needs locking fixes. + */ + static ide_settings_t *ide_find_setting_by_ioctl (ide_drive_t *drive, int cmd) { ide_settings_t *setting = drive->settings; @@ -2065,6 +1044,16 @@ return setting; } +/** + * ide_find_setting_by_name - find a setting handler by its name + * @drive: drive to act for + * @cmd: ioctl command code + * + * Scan the drive handlers handler matching the name for this function. + * The handlers vary by drive and sometimes by drive state. + * Needs locking fixes. + */ + ide_settings_t *ide_find_setting_by_name (ide_drive_t *drive, char *name) { ide_settings_t *setting = drive->settings; @@ -2077,6 +1066,17 @@ return setting; } +/** + * auto_remove_settings - remove driver settings on a device + * @drive: drive to clean + * + * Called when we change the driver bindings for a device, for + * example if the device is hot plugged. We must scrub the driver + * bindings that are thus no longer relevant to the device in case + * it changes from say a CD-ROM to a disk + * Needs locking fixes + */ + static void auto_remove_settings (ide_drive_t *drive) { ide_settings_t *setting; @@ -2128,7 +1128,7 @@ local_irq_set(lflags); if (time_after(jiffies, timeout)) { local_irq_restore(lflags); - printk("%s: channel busy\n", drive->name); + printk(KERN_ERR "%s: channel busy\n", drive->name); return -EBUSY; } local_irq_restore(lflags); @@ -2229,8 +1229,7 @@ SETFEATURES_XFER, 0, NULL); if (!err && arg) { - if ((HWIF(drive)->speedproc) != NULL) - HWIF(drive)->speedproc(drive, (u8) arg); + ide_set_xfer_rate(drive, (u8) arg); ide_driveid_update(drive); } return err; @@ -2312,7 +1311,7 @@ */ int ide_replace_subdriver (ide_drive_t *drive, const char *driver) { - if (!drive->present || drive->usage) + if (!drive->present || drive->usage || drive->dead) goto abort; if (drive->driver != NULL && DRIVER(drive)->cleanup(drive)) goto abort; @@ -2487,7 +1486,7 @@ #if 1 spin_lock_irqsave(&ide_lock, flags); if ( HWGROUP(drive)->handler != NULL) { - printk("%s: ide_set_handler: handler not null; %p\n", drive->name, HWGROUP(drive)->handler); + 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; @@ -2702,7 +1701,7 @@ strncmp(s,"hd",2)) /* hdx= & hdxlun= */ return 0; - printk("ide_setup: %s", s); + printk(KERN_INFO "ide_setup: %s", s); init_ide_data (); #ifdef CONFIG_BLK_DEV_IDEDOUBLER @@ -3122,21 +2121,39 @@ #endif } -static int default_standby (ide_drive_t *drive) -{ - return 0; -} - -static int default_suspend (ide_drive_t *drive) +/* + * Actually unregister the subdriver. Called with the + * request lock dropped. + */ + +static int default_cleanup (ide_drive_t *drive) { - return 0; + return ide_unregister_subdriver(drive); } -static int default_resume (ide_drive_t *drive) +/* + * Check if we can unregister the subdriver. Called with the + * request lock held. + */ + +static int default_shutdown(ide_drive_t *drive) { + if (drive->usage || drive->driver == NULL || DRIVER(drive)->busy) { + return 1; + } + drive->dead = 1; return 0; } +/* + * Default function to use for the cache flush operation. This + * must be replaced for disk devices (see ATA specification + * documents on cache flush and drive suspend rules) + * + * If we have no device attached or the device is not writable + * this handler is sufficient. + */ + static int default_flushcache (ide_drive_t *drive) { return 0; @@ -3193,9 +2210,8 @@ { ide_driver_t *d = drive->driver; - if (d->standby == NULL) d->standby = default_standby; - if (d->suspend == NULL) d->suspend = default_suspend; - if (d->resume == NULL) d->resume = default_resume; + if (d->cleanup == NULL) d->cleanup = default_cleanup; + if (d->shutdown == NULL) d->shutdown = default_shutdown; if (d->flushcache == NULL) d->flushcache = default_flushcache; if (d->do_request == NULL) d->do_request = default_do_request; if (d->end_request == NULL) d->end_request = default_end_request; @@ -3213,7 +2229,7 @@ spin_lock_irqsave(&ide_lock, flags); if (version != IDE_SUBDRIVER_VERSION || !drive->present || - drive->driver != NULL || drive->usage) { + drive->driver != NULL || drive->usage || drive->dead) { spin_unlock_irqrestore(&ide_lock, flags); return 1; } @@ -3274,13 +2290,8 @@ ide_drive_t * drive = container_of(dev,ide_drive_t,gendev); ide_driver_t * driver = drive->driver; - if (driver) { - if (driver->standby) - driver->standby(drive); - if (driver->cleanup) - driver->cleanup(drive); - } - + if (driver && driver->cleanup) + driver->cleanup(drive); return 0; } @@ -3321,7 +2332,7 @@ while(!list_empty(&driver->drives)) { drive = list_entry(driver->drives.next, ide_drive_t, list); if (driver->cleanup(drive)) { - printk("%s: cleanup_module() called while still busy\n", drive->name); + printk(KERN_ERR "%s: cleanup_module() called while still busy\n", drive->name); BUG(); } /* We must remove proc entries defined in this module. @@ -3395,7 +2406,7 @@ if ((next = strchr(line,' ')) != NULL) *next++ = 0; if (!ide_setup(line)) - printk ("Unknown option '%s'\n", line); + printk (KERN_INFO "Unknown option '%s'\n", line); } } @@ -3411,10 +2422,10 @@ for (index = 0; index < MAX_HWIFS; ++index) { ide_unregister(index); -#if defined(CONFIG_BLK_DEV_IDEDMA) && !defined(CONFIG_DMA_NONPCI) +#if !defined(CONFIG_DMA_NONPCI) if (ide_hwifs[index].dma_base) (void) ide_release_dma(&ide_hwifs[index]); -#endif /* (CONFIG_BLK_DEV_IDEDMA) && !(CONFIG_DMA_NONPCI) */ +#endif /* !(CONFIG_DMA_NONPCI) */ } #ifdef CONFIG_PROC_FS diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/ide/ide-cd.c linux.2.5.47-ac4/drivers/ide/ide-cd.c --- linux.2.5.47/drivers/ide/ide-cd.c 2002-11-11 16:39:09.000000000 +0000 +++ linux.2.5.47-ac4/drivers/ide/ide-cd.c 2002-11-13 15:05:26.000000000 +0000 @@ -2965,10 +2965,8 @@ printk(", %dkB Cache", be16_to_cpu(cap.buffer_size)); -#ifdef CONFIG_BLK_DEV_IDEDMA if (drive->using_dma) (void) HWIF(drive)->ide_dma_verbose(drive); -#endif /* CONFIG_BLK_DEV_IDEDMA */ printk("\n"); return nslots; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/ide/ide-disk.c linux.2.5.47-ac4/drivers/ide/ide-disk.c --- linux.2.5.47/drivers/ide/ide-disk.c 2002-11-11 16:39:10.000000000 +0000 +++ linux.2.5.47-ac4/drivers/ide/ide-disk.c 2002-11-13 22:49:14.000000000 +0000 @@ -1412,24 +1412,6 @@ return call_idedisk_standby(drive, 0); } -static int call_idedisk_suspend (ide_drive_t *drive, int arg) -{ - ide_task_t args; - u8 suspend = (arg) ? WIN_SLEEPNOW2 : WIN_SLEEPNOW1; - memset(&args, 0, sizeof(ide_task_t)); - args.tfRegister[IDE_COMMAND_OFFSET] = suspend; - args.command_type = ide_cmd_type_parser(&args); - return ide_raw_taskfile(drive, &args, NULL); -} - -static int do_idedisk_suspend (ide_drive_t *drive) -{ - if (drive->suspend_reset) - return 1; - - return call_idedisk_suspend(drive, 0); -} - #if 0 static int call_idedisk_checkpower (ide_drive_t *drive, int arg) { @@ -1456,13 +1438,6 @@ } #endif -static int do_idedisk_resume (ide_drive_t *drive) -{ - if (!drive->suspend_reset) - return 1; - return 0; -} - static int do_idedisk_flushcache (ide_drive_t *drive) { ide_task_t args; @@ -1561,6 +1536,39 @@ #endif } +static int idedisk_suspend(struct device *dev, u32 state, u32 level) +{ + ide_drive_t *drive = dev->driver_data; + + printk("Suspending device %p\n", dev->driver_data); + + /* I hope that every freeze operation from the upper levels have + * already been done... + */ + + if (level != SUSPEND_SAVE_STATE) + return 0; + + /* set the drive to standby */ + printk(KERN_INFO "suspending: %s ", drive->name); + do_idedisk_standby(drive); + drive->blocked = 1; + + BUG_ON (HWGROUP(drive)->handler); + return 0; +} + +static int idedisk_resume(struct device *dev, u32 level) +{ + ide_drive_t *drive = dev->driver_data; + + if (level != RESUME_RESTORE_STATE) + return 0; + BUG_ON(!drive->blocked); + drive->blocked = 0; + return 0; +} + static void idedisk_setup (ide_drive_t *drive) { struct hd_driveid *id = drive->id; @@ -1641,10 +1649,8 @@ printk(", CHS=%d/%d/%d", drive->bios_cyl, drive->bios_head, drive->bios_sect); -#ifdef CONFIG_BLK_DEV_IDEDMA if (drive->using_dma) (void) HWIF(drive)->ide_dma_verbose(drive); -#endif /* CONFIG_BLK_DEV_IDEDMA */ printk("\n"); drive->mult_count = 0; @@ -1671,6 +1677,7 @@ { struct gendisk *g = drive->disk; + do_idedisk_standby(drive); if ((drive->id->cfs_enable_2 & 0x3000) && drive->wcache) if (do_idedisk_flushcache(drive)) printk (KERN_INFO "%s: Write Cache FAILED Flushing!\n", @@ -1696,9 +1703,6 @@ .supports_dma = 1, .supports_dsc_overlap = 0, .cleanup = idedisk_cleanup, - .standby = do_idedisk_standby, - .suspend = do_idedisk_suspend, - .resume = do_idedisk_resume, .flushcache = do_idedisk_flushcache, .do_request = do_rw_disk, .sense = idedisk_dump_status, @@ -1709,6 +1713,10 @@ .proc = idedisk_proc, .attach = idedisk_attach, .drives = LIST_HEAD_INIT(idedisk_driver.drives), + .gen_driver = { + .suspend = idedisk_suspend, + .resume = idedisk_resume, + } }; static int idedisk_open(struct inode *inode, struct file *filp) @@ -1835,8 +1843,7 @@ static int idedisk_init (void) { - ide_register_driver(&idedisk_driver); - return 0; + return ide_register_driver(&idedisk_driver); } module_init(idedisk_init); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/ide/ide-dma.c linux.2.5.47-ac4/drivers/ide/ide-dma.c --- linux.2.5.47/drivers/ide/ide-dma.c 2002-11-11 16:39:10.000000000 +0000 +++ linux.2.5.47-ac4/drivers/ide/ide-dma.c 2002-11-13 17:57:41.000000000 +0000 @@ -145,7 +145,16 @@ }; -int in_drive_list(struct hd_driveid *id, struct drive_list_entry * drive_table) +/** + * in_drive_list - look for drive in black/white list + * @id: drive identifier + * @drive_table: list to inspect + * + * Look for a drive in the blacklist and the whitelist tables + * Returns 1 if the drive is found in the table. + */ + +static int in_drive_list(struct hd_driveid *id, struct drive_list_entry * drive_table) { for ( ; drive_table->id_model ; drive_table++) if ((!strcmp(drive_table->id_model, id->model)) && @@ -189,9 +198,14 @@ #endif /* CONFIG_IDEDMA_NEW_DRIVE_LISTINGS */ -/* - * dma_intr() is the handler for disk read/write DMA interrupts +/** + * ide_dma_intr - IDE DMA interrupt handler + * @drive: the drive the interrupt is for + * + * Handle an interrupt completing a read/write DMA transfer on an + * IDE device */ + ide_startstop_t ide_dma_intr (ide_drive_t *drive) { u8 stat = 0, dma_stat = 0; @@ -205,7 +219,7 @@ DRIVER(drive)->end_request(drive, 1, rq->nr_sectors); return ide_stopped; } - printk("%s: dma_intr: bad DMA status (dma_stat=%x)\n", + printk(KERN_ERR "%s: dma_intr: bad DMA status (dma_stat=%x)\n", drive->name, dma_stat); } return DRIVER(drive)->error(drive, "dma_intr", stat); @@ -213,6 +227,17 @@ EXPORT_SYMBOL_GPL(ide_dma_intr); +/** + * ide_build_sglist - map IDE scatter gather for DMA I/O + * @drive: the drive to build the DMA table for + * @rq: the request holding the sg list + * + * Perform the PCI mapping magic neccessary to access the source or + * target buffers of a request via PCI DMA. The lower layers of the + * kernel provide the neccessary cache management so that we can + * operate in a portable fashion + */ + static int ide_build_sglist (ide_drive_t *drive, struct request *rq) { ide_hwif_t *hwif = HWIF(drive); @@ -232,6 +257,17 @@ return pci_map_sg(hwif->pci_dev, sg, nents, hwif->sg_dma_direction); } +/** + * ide_raw_build_sglist - map IDE scatter gather for DMA + * @drive: the drive to build the DMA table for + * @rq: the request holding the sg list + * + * Perform the PCI mapping magic neccessary to access the source or + * target buffers of a taskfile request via PCI DMA. The lower layers + * of the kernel provide the neccessary cache management so that we can + * operate in a portable fashion + */ + static int ide_raw_build_sglist (ide_drive_t *drive, struct request *rq) { ide_hwif_t *hwif = HWIF(drive); @@ -246,6 +282,9 @@ else hwif->sg_dma_direction = PCI_DMA_FROMDEVICE; #if 1 + if (sector_count > 256) + BUG(); + if (sector_count > 128) { memset(&sg[nents], 0, sizeof(*sg)); sg[nents].page = virt_to_page(virt_addr); @@ -279,11 +318,18 @@ return pci_map_sg(hwif->pci_dev, sg, nents, hwif->sg_dma_direction); } -/* - * ide_build_dmatable() prepares a dma request. - * Returns 0 if all went okay, returns 1 otherwise. - * May also be invoked from trm290.c +/** + * ide_build_dmatable - build IDE DMA table + * + * ide_build_dmatable() prepares a dma request. We map the command + * to get the pci bus addresses of the buffers and then build up + * the PRD table that the IDE layer wants to be fed. The code + * knows about the 64K wrap bug in the CS5530. + * + * Returns 0 if all went okay, returns 1 otherwise. + * May also be invoked from trm290.c */ + int ide_build_dmatable (ide_drive_t *drive, struct request *rq) { ide_hwif_t *hwif = HWIF(drive); @@ -317,7 +363,7 @@ while (cur_len) { if (count++ >= PRD_ENTRIES) { - printk("%s: DMA table too small\n", drive->name); + printk(KERN_ERR "%s: DMA table too small\n", drive->name); goto use_pio_instead; } else { u32 xcount, bcount = 0x10000 - (cur_addr & 0xffff); @@ -335,7 +381,7 @@ * So here we break the 64KB entry into two 32KB entries instead. */ if (count++ >= PRD_ENTRIES) { - printk("%s: DMA table too small\n", drive->name); + printk(KERN_ERR "%s: DMA table too small\n", drive->name); goto use_pio_instead; } *table++ = cpu_to_le32(0x8000); @@ -357,7 +403,7 @@ *--table |= cpu_to_le32(0x80000000); return count; } - printk("%s: empty DMA table?\n", drive->name); + printk(KERN_ERR "%s: empty DMA table?\n", drive->name); use_pio_instead: pci_unmap_sg(hwif->pci_dev, hwif->sg_table, @@ -369,7 +415,17 @@ EXPORT_SYMBOL_GPL(ide_build_dmatable); -/* Teardown mappings after DMA has completed. */ +/** + * ide_destroy_dmatable - clean up DMA mapping + * @drive: The drive to unmap + * + * Teardown mappings after DMA has completed. This must be called + * after the completion of each use of ide_build_dmatable and before + * the next use of ide_build_dmatable. Failure to do so will cause + * an oops as only one mapping can be live for each target at a given + * time. + */ + void ide_destroy_dmatable (ide_drive_t *drive) { struct pci_dev *dev = HWIF(drive)->pci_dev; @@ -382,6 +438,17 @@ EXPORT_SYMBOL_GPL(ide_destroy_dmatable); +/** + * config_drive_for_dma - attempt to activate IDE DMA + * @drive: the drive to place in DMA mode + * + * If the drive supports at least mode 2 DMA or UDMA of any kind + * then attempt to place it into DMA mode. Drives that are known to + * support DMA but predate the DMA properties or that are known + * to have DMA handling bugs are also set up appropriately based + * on the good/bad drive lists. + */ + static int config_drive_for_dma (ide_drive_t *drive) { struct hd_driveid *id = drive->id; @@ -415,15 +482,25 @@ return hwif->ide_dma_off_quietly(drive); } -/* - * 1 dmaing, 2 error, 4 intr +/** + * dma_timer_expiry - handle a DMA timeout + * @drive: Drive that timed out + * + * An IDE DMA transfer timed out. In the event of an error we ask + * the driver to resolve the problem, if a DMA transfer is still + * in progress we continue to wait (arguably we need to add a + * secondary 'I dont care what the drive thinks' timeout here) + * Finally if we have an interrupt but for some reason got the + * timeout first we complete the I/O. This can occur if an + * interrupt is lost or due to bugs. */ + static int dma_timer_expiry (ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); u8 dma_stat = hwif->INB(hwif->dma_status); - printk("%s: dma_timer_expiry: dma status == 0x%02x\n", + printk(KERN_WARNING "%s: dma_timer_expiry: dma status == 0x%02x\n", drive->name, dma_stat); if ((dma_stat & 0x18) == 0x18) /* BUSY Stupid Early Timer !! */ @@ -431,6 +508,8 @@ HWGROUP(drive)->expiry = NULL; /* one free ride for now */ + /* 1 dmaing, 2 error, 4 intr */ + if (dma_stat & 2) { /* ERROR */ (void) hwif->ide_dma_end(drive); return DRIVER(drive)->error(drive, @@ -445,6 +524,14 @@ return 0; } +/** + * __ide_dma_host_off - Generic DMA kill + * @drive: drive to control + * + * Perform the generic IDE controller DMA off operation. This + * works for most IDE bus mastering controllers + */ + int __ide_dma_host_off (ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); @@ -457,6 +544,13 @@ EXPORT_SYMBOL(__ide_dma_host_off); +/** + * __ide_dma_host_off_quietly - Generic DMA kill + * @drive: drive to control + * + * Turn off the current DMA on this IDE controller. + */ + int __ide_dma_off_quietly (ide_drive_t *drive) { drive->using_dma = 0; @@ -473,14 +567,30 @@ EXPORT_SYMBOL(__ide_dma_off_quietly); +/** + * __ide_dma_host_off - Generic DMA kill + * @drive: drive to control + * + * Turn off the current DMA on this IDE controller. Inform the + * user that DMA has been disabled. + */ + int __ide_dma_off (ide_drive_t *drive) { - printk("%s: DMA disabled\n", drive->name); + printk(KERN_INFO "%s: DMA disabled\n", drive->name); return HWIF(drive)->ide_dma_off_quietly(drive); } EXPORT_SYMBOL(__ide_dma_off); +/** + * __ide_dma_host_on - Enable DMA on a host + * @drive: drive to enable for DMA + * + * Enable DMA on an IDE controller following generic bus mastering + * IDE controller behaviour + */ + int __ide_dma_host_on (ide_drive_t *drive) { if (drive->using_dma) { @@ -496,6 +606,13 @@ EXPORT_SYMBOL(__ide_dma_host_on); +/** + * __ide_dma_on - Enable DMA on a device + * @drive: drive to enable DMA on + * + * Enable IDE DMA for a device on this IDE controller. + */ + int __ide_dma_on (ide_drive_t *drive) { drive->using_dma = 1; @@ -512,6 +629,13 @@ EXPORT_SYMBOL(__ide_dma_on); +/** + * __ide_dma_check - check DMA setup + * @drive: drive to check + * + * Don't use - due for extermination + */ + int __ide_dma_check (ide_drive_t *drive) { return config_drive_for_dma(drive); @@ -519,6 +643,21 @@ EXPORT_SYMBOL(__ide_dma_check); +/** + * ide_start_dma - begin a DMA phase + * @hwif: interface + * @drive: target device + * @reading: set if reading, clear if writing + * + * Build an IDE DMA PRD (IDE speak for scatter gather table) + * and then set up the DMA transfer registers for a device + * that follows generic IDE PCI DMA behaviour. Controllers can + * override this function if they need to + * + * Returns 0 on success. If a PIO fallback is required then 1 + * is returned. + */ + int ide_start_dma(ide_hwif_t *hwif, ide_drive_t *drive, int reading) { struct request *rq = HWGROUP(drive)->rq; @@ -791,9 +930,17 @@ EXPORT_SYMBOL(__ide_dma_verbose); +/** + * __ide_dma_retune - default retune handler + * @drive: drive to retune + * + * Default behaviour when we decide to return the IDE DMA setup. + * The default behaviour is "we don't" + */ + int __ide_dma_retune (ide_drive_t *drive) { - printk("%s: chipset supported call only\n", __FUNCTION__); + printk(KERN_WARNING "%s: chipset supported call only\n", __FUNCTION__); return 1; } @@ -809,7 +956,7 @@ int __ide_dma_timeout (ide_drive_t *drive) { - printk("%s: timeout waiting for DMA\n", drive->name); + printk(KERN_ERR "%s: timeout waiting for DMA\n", drive->name); if (HWIF(drive)->ide_dma_test_irq(drive)) return 0; @@ -882,7 +1029,7 @@ if ((hwif->dmatable_cpu) && (hwif->sg_table)) return 0; - printk("%s: -- Error, unable to allocate%s%s table(s).\n", + printk(KERN_ERR "%s: -- Error, unable to allocate%s%s table(s).\n", (hwif->dmatable_cpu == NULL) ? " CPU" : "", (hwif->sg_table == NULL) ? " SG DMA" : " DMA", hwif->cds->name); @@ -893,7 +1040,7 @@ int ide_mmio_dma (ide_hwif_t *hwif, unsigned long base, unsigned int ports) { - printk(" %s: MMIO-DMA at 0x%08lx-0x%08lx", + 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"); @@ -905,6 +1052,7 @@ request_region(base+16, hwif->cds->extra, hwif->cds->name); hwif->dma_extra = hwif->cds->extra; } + hwif->dma_master = (hwif->channel) ? hwif->mate->dma_base : base; if (hwif->dma_base2) { if (!check_mem_region(hwif->dma_base2, ports)) @@ -915,7 +1063,7 @@ int ide_iomio_dma (ide_hwif_t *hwif, unsigned long base, unsigned int ports) { - printk(" %s: BM-DMA at 0x%04lx-0x%04lx", + printk(KERN_INFO " %s: BM-DMA at 0x%04lx-0x%04lx", hwif->name, base, base + ports - 1); if (!request_region(base, ports, hwif->name)) { printk(" -- Error, ports in use.\n"); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/ide/ide-floppy.c linux.2.5.47-ac4/drivers/ide/ide-floppy.c --- linux.2.5.47/drivers/ide/ide-floppy.c 2002-11-05 13:54:43.000000000 +0000 +++ linux.2.5.47-ac4/drivers/ide/ide-floppy.c 2002-11-13 15:05:08.000000000 +0000 @@ -115,6 +115,12 @@ /* #define IDEFLOPPY_DEBUG(fmt, args...) printk(KERN_INFO fmt, ## args) */ #define IDEFLOPPY_DEBUG( fmt, args... ) +#ifndef IDEFLOPPY_DEBUG_LOG +#define debug_log(fmt, args... ) do {} while(0) +#else +#define debug_log printk +#endif + /* * Some drives require a longer irq timeout. @@ -543,9 +549,7 @@ struct request *rq = HWGROUP(drive)->rq; int error; -#if IDEFLOPPY_DEBUG_LOG - printk(KERN_INFO "Reached idefloppy_end_request\n"); -#endif /* IDEFLOPPY_DEBUG_LOG */ + debug_log(KERN_INFO "Reached idefloppy_end_request\n"); switch (uptodate) { case 0: error = IDEFLOPPY_ERROR_GENERAL; break; @@ -627,7 +631,6 @@ } } -#ifdef CONFIG_BLK_DEV_IDEDMA static void idefloppy_update_buffers (ide_drive_t *drive, idefloppy_pc_t *pc) { struct request *rq = pc->rq; @@ -636,7 +639,6 @@ while ((bio = rq->bio) != NULL) idefloppy_do_end_request(drive, 1, 0); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ /* * idefloppy_queue_pc_head generates a new packet command request in front @@ -682,25 +684,22 @@ floppy->ascq = result->ascq; floppy->progress_indication = result->sksv[0] & 0x80 ? (u16)get_unaligned((u16 *)(result->sksv+1)):0x10000; -#if IDEFLOPPY_DEBUG_LOG if (floppy->failed_pc) - printk(KERN_INFO "ide-floppy: pc = %x, sense key = %x, " + debug_log(KERN_INFO "ide-floppy: pc = %x, sense key = %x, " "asc = %x, ascq = %x\n", floppy->failed_pc->c[0], result->sense_key, result->asc, result->ascq); else - printk(KERN_INFO "ide-floppy: sense key = %x, asc = %x, " + debug_log(KERN_INFO "ide-floppy: sense key = %x, asc = %x, " "ascq = %x\n", result->sense_key, result->asc, result->ascq); -#endif /* IDEFLOPPY_DEBUG_LOG */ } static void idefloppy_request_sense_callback (ide_drive_t *drive) { idefloppy_floppy_t *floppy = drive->driver_data; -#if IDEFLOPPY_DEBUG_LOG - printk(KERN_INFO "ide-floppy: Reached %s\n", __FUNCTION__); -#endif /* IDEFLOPPY_DEBUG_LOG */ + debug_log(KERN_INFO "ide-floppy: Reached %s\n", __FUNCTION__); + if (!floppy->pc->error) { idefloppy_analyze_error(drive,(idefloppy_request_sense_result_t *) floppy->pc->buffer); idefloppy_do_end_request(drive, 1, 0); @@ -717,9 +716,7 @@ { idefloppy_floppy_t *floppy = drive->driver_data; -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "ide-floppy: Reached %s\n", __FUNCTION__); -#endif /* IDEFLOPPY_DEBUG_LOG */ + debug_log(KERN_INFO "ide-floppy: Reached %s\n", __FUNCTION__); idefloppy_do_end_request(drive, floppy->pc->error ? 0 : 1, 0); } @@ -781,12 +778,9 @@ struct request *rq = pc->rq; unsigned int temp; -#if IDEFLOPPY_DEBUG_LOG - printk(KERN_INFO "ide-floppy: Reached %s interrupt handler\n", + debug_log(KERN_INFO "ide-floppy: Reached %s interrupt handler\n", __FUNCTION__); -#endif /* IDEFLOPPY_DEBUG_LOG */ -#ifdef CONFIG_BLK_DEV_IDEDMA if (test_bit(PC_DMA_IN_PROGRESS, &pc->flags)) { if (HWIF(drive)->ide_dma_end(drive)) { set_bit(PC_DMA_ERROR, &pc->flags); @@ -794,30 +788,23 @@ pc->actually_transferred = pc->request_transfer; idefloppy_update_buffers(drive, pc); } -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "ide-floppy: DMA finished\n"); -#endif /* IDEFLOPPY_DEBUG_LOG */ + debug_log(KERN_INFO "ide-floppy: DMA finished\n"); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ /* Clear the interrupt */ status.all = HWIF(drive)->INB(IDE_STATUS_REG); if (!status.b.drq) { /* No more interrupts */ -#if IDEFLOPPY_DEBUG_LOG - printk(KERN_INFO "Packet command completed, %d bytes " + debug_log(KERN_INFO "Packet command completed, %d bytes " "transferred\n", pc->actually_transferred); -#endif /* IDEFLOPPY_DEBUG_LOG */ clear_bit(PC_DMA_IN_PROGRESS, &pc->flags); local_irq_enable(); if (status.b.check || test_bit(PC_DMA_ERROR, &pc->flags)) { /* Error detected */ -#if IDEFLOPPY_DEBUG_LOG - printk(KERN_INFO "ide-floppy: %s: I/O error\n", + debug_log(KERN_INFO "ide-floppy: %s: I/O error\n", drive->name); -#endif /* IDEFLOPPY_DEBUG_LOG */ rq->errors++; if (pc->c[0] == IDEFLOPPY_REQUEST_SENSE_CMD) { printk(KERN_ERR "ide-floppy: I/O error in " @@ -836,14 +823,14 @@ pc->callback(drive); return ide_stopped; } -#ifdef CONFIG_BLK_DEV_IDEDMA + if (test_and_clear_bit(PC_DMA_IN_PROGRESS, &pc->flags)) { printk(KERN_ERR "ide-floppy: The floppy wants to issue " "more interrupts in DMA mode\n"); (void) HWIF(drive)->ide_dma_off(drive); return ide_do_reset(drive); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ + /* Get the number of bytes to transfer */ bcount.b.high = HWIF(drive)->INB(IDE_BCOUNTH_REG); bcount.b.low = HWIF(drive)->INB(IDE_BCOUNTL_REG); @@ -879,11 +866,9 @@ NULL); return ide_started; } -#if IDEFLOPPY_DEBUG_LOG - printk(KERN_NOTICE "ide-floppy: The floppy wants to " + debug_log(KERN_NOTICE "ide-floppy: The floppy wants to " "send us more data than expected - " "allowing transfer\n"); -#endif /* IDEFLOPPY_DEBUG_LOG */ } } if (test_bit(PC_WRITING, &pc->flags)) { @@ -1047,9 +1032,8 @@ pc->callback(drive); return ide_stopped; } -#if IDEFLOPPY_DEBUG_LOG - printk(KERN_INFO "Retry number - %d\n",pc->retries); -#endif /* IDEFLOPPY_DEBUG_LOG */ + + debug_log(KERN_INFO "Retry number - %d\n",pc->retries); pc->retries++; /* We haven't transferred any data yet */ @@ -1057,13 +1041,11 @@ pc->current_position = pc->buffer; bcount.all = min(pc->request_transfer, 63 * 1024); -#ifdef CONFIG_BLK_DEV_IDEDMA if (test_and_clear_bit(PC_DMA_ERROR, &pc->flags)) { (void) HWIF(drive)->ide_dma_off(drive); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ feature.all = 0; -#ifdef CONFIG_BLK_DEV_IDEDMA + if (test_bit(PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma) { if (test_bit(PC_WRITING, &pc->flags)) { feature.b.dma = !HWIF(drive)->ide_dma_write(drive); @@ -1071,7 +1053,6 @@ feature.b.dma = !HWIF(drive)->ide_dma_read(drive); } } -#endif /* CONFIG_BLK_DEV_IDEDMA */ if (IDE_CONTROL_REG) HWIF(drive)->OUTB(drive->ctl, IDE_CONTROL_REG); @@ -1081,12 +1062,10 @@ HWIF(drive)->OUTB(bcount.b.low, IDE_BCOUNTL_REG); HWIF(drive)->OUTB(drive->select.all, IDE_SELECT_REG); -#ifdef CONFIG_BLK_DEV_IDEDMA if (feature.b.dma) { /* Begin DMA, if necessary */ set_bit(PC_DMA_IN_PROGRESS, &pc->flags); (void) (HWIF(drive)->ide_dma_begin(drive)); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ /* Can we transfer the packet when we get the interrupt or wait? */ if (test_bit(IDEFLOPPY_ZIP_DRIVE, &floppy->flags)) { @@ -1116,9 +1095,7 @@ static void idefloppy_rw_callback (ide_drive_t *drive) { -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "ide-floppy: Reached idefloppy_rw_callback\n"); -#endif /* IDEFLOPPY_DEBUG_LOG */ + debug_log(KERN_INFO "ide-floppy: Reached idefloppy_rw_callback\n"); idefloppy_do_end_request(drive, 1, 0); return; @@ -1126,10 +1103,8 @@ static void idefloppy_create_prevent_cmd (idefloppy_pc_t *pc, int prevent) { -#if IDEFLOPPY_DEBUG_LOG - printk(KERN_INFO "ide-floppy: creating prevent removal command, " + debug_log(KERN_INFO "ide-floppy: creating prevent removal command, " "prevent = %d\n", prevent); -#endif /* IDEFLOPPY_DEBUG_LOG */ idefloppy_init_pc(pc); pc->c[0] = IDEFLOPPY_PREVENT_REMOVAL_CMD; @@ -1212,11 +1187,9 @@ int blocks = rq->nr_sectors / floppy->bs_factor; int cmd = rq_data_dir(rq); -#if IDEFLOPPY_DEBUG_LOG - printk("create_rw1%d_cmd: block == %d, blocks == %d\n", + debug_log("create_rw1%d_cmd: block == %d, blocks == %d\n", 2 * test_bit (IDEFLOPPY_USE_READ12, &floppy->flags), block, blocks); -#endif /* IDEFLOPPY_DEBUG_LOG */ idefloppy_init_pc(pc); if (test_bit(IDEFLOPPY_USE_READ12, &floppy->flags)) { @@ -1262,14 +1235,12 @@ idefloppy_pc_t *pc; unsigned long block = (unsigned long)block_s; -#if IDEFLOPPY_DEBUG_LOG - printk(KERN_INFO "rq_status: %d, dev: %s, flags: %lx, errors: %d\n", + debug_log(KERN_INFO "rq_status: %d, dev: %s, flags: %lx, errors: %d\n", rq->rq_status, rq->rq_disk->disk_name, rq->flags, rq->errors); - printk(KERN_INFO "sector: %ld, nr_sectors: %ld, " + debug_log(KERN_INFO "sector: %ld, nr_sectors: %ld, " "current_nr_sectors: %ld\n", (long)rq->sector, rq->nr_sectors, rq->current_nr_sectors); -#endif /* IDEFLOPPY_DEBUG_LOG */ if (rq->errors >= ERROR_MAX) { if (floppy->failed_pc != NULL) @@ -1473,10 +1444,10 @@ } } if (!i) { - IDEFLOPPY_DEBUG( "Descriptor 0 Code: %d\n", + debug_log( "Descriptor 0 Code: %d\n", descriptor->dc); } - IDEFLOPPY_DEBUG( "Descriptor %d: %dkB, %d blocks, %d " + debug_log( "Descriptor %d: %dkB, %d blocks, %d " "sector size\n", i, blocks * length / 1024, blocks, length); } @@ -1909,9 +1880,7 @@ drive->usage++; -#if IDEFLOPPY_DEBUG_LOG - printk(KERN_INFO "Reached idefloppy_open\n"); -#endif /* IDEFLOPPY_DEBUG_LOG */ + debug_log(KERN_INFO "Reached idefloppy_open\n"); if (drive->usage == 1) { clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags); @@ -1958,9 +1927,7 @@ ide_drive_t *drive = inode->i_bdev->bd_disk->private_data; idefloppy_pc_t pc; -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "Reached idefloppy_release\n"); -#endif /* IDEFLOPPY_DEBUG_LOG */ + debug_log(KERN_INFO "Reached idefloppy_release\n"); if (drive->usage == 1) { idefloppy_floppy_t *floppy = drive->driver_data; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/ide/ide-io.c linux.2.5.47-ac4/drivers/ide/ide-io.c --- linux.2.5.47/drivers/ide/ide-io.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.47-ac4/drivers/ide/ide-io.c 2002-11-14 18:00:06.000000000 +0000 @@ -0,0 +1,1320 @@ +/* + * IDE I/O functions + * + * Basic PIO and command management functionality. + * + * This code was split off from ide.c. See ide.c for history and original + * copyrights. + * + * 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, 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. + * + * For the avoidance of doubt the "preferred form" of this code is one which + * is in an open non patent encumbered format. Where cryptographic key signing + * forms part of the process of creating an executable the information + * including keys needed to generate an equivalently functional executable + * are deemed to be part of the source code. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "ide_modes.h" + +#if (DISK_RECOVERY_TIME > 0) + +Error So the User Has To Fix the Compilation And Stop Hacking Port 0x43 +Does anyone ever use this anyway ?? + +/* + * For really screwy hardware (hey, at least it *can* be used with Linux) + * we can enforce a minimum delay time between successive operations. + */ +static unsigned long read_timer (ide_hwif_t *hwif) +{ + unsigned long t, flags; + int i; + + /* FIXME this is completely unsafe! */ + local_irq_save(flags); + t = jiffies * 11932; + outb_p(0, 0x43); + i = inb_p(0x40); + i |= inb_p(0x40) << 8; + local_irq_restore(flags); + return (t - i); +} +#endif /* DISK_RECOVERY_TIME */ + +static inline void set_recovery_timer (ide_hwif_t *hwif) +{ +#if (DISK_RECOVERY_TIME > 0) + hwif->last_time = read_timer(hwif); +#endif /* DISK_RECOVERY_TIME */ +} + +/** + * ide_end_request - complete an IDE I/O + * @drive: IDE device for the I/O + * @uptodate: + * @nr_sectors: number of sectors completed + * + * This is our end_request wrapper function. We complete the I/O + * update random number input and dequeue the request, which if + * it was tagged may be out of order. + */ + +int ide_end_request (ide_drive_t *drive, int uptodate, int nr_sectors) +{ + struct request *rq; + unsigned long flags; + int ret = 1; + + spin_lock_irqsave(&ide_lock, flags); + rq = HWGROUP(drive)->rq; + + BUG_ON(!(rq->flags & REQ_STARTED)); + + if (!nr_sectors) + nr_sectors = rq->hard_cur_sectors; + + /* + * decide whether to reenable DMA -- 3 is a random magic for now, + * if we DMA timeout more than 3 times, just stay in PIO + */ + if (drive->state == DMA_PIO_RETRY && drive->retry_pio <= 3) { + drive->state = 0; + HWGROUP(drive)->hwif->ide_dma_on(drive); + } + + if (!end_that_request_first(rq, uptodate, nr_sectors)) { + add_disk_randomness(rq->rq_disk); + if (!blk_rq_tagged(rq)) + blkdev_dequeue_request(rq); + else + blk_queue_end_tag(&drive->queue, rq); + HWGROUP(drive)->rq = NULL; + end_that_request_last(rq); + ret = 0; + } + spin_unlock_irqrestore(&ide_lock, flags); + return ret; +} + +EXPORT_SYMBOL(ide_end_request); + +/** + * ide_end_drive_cmd - end an explicit drive command + * @drive: command + * @stat: status bits + * @err: error bits + * + * Clean up after success/failure of an explicit drive command. + * These get thrown onto the queue so they are synchronized with + * real I/O operations on the drive. + * + * In LBA48 mode we have to read the register set twice to get + * all the extra information out. + */ + +void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err) +{ + ide_hwif_t *hwif = HWIF(drive); + unsigned long flags; + struct request *rq; + + spin_lock_irqsave(&ide_lock, flags); + rq = HWGROUP(drive)->rq; + spin_unlock_irqrestore(&ide_lock, flags); + + if (rq->flags & REQ_DRIVE_CMD) { + u8 *args = (u8 *) rq->buffer; + if (rq->errors == 0) + rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT); + + if (args) { + args[0] = stat; + args[1] = err; + args[2] = hwif->INB(IDE_NSECTOR_REG); + } + } else if (rq->flags & REQ_DRIVE_TASK) { + u8 *args = (u8 *) rq->buffer; + if (rq->errors == 0) + rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT); + + if (args) { + args[0] = stat; + args[1] = err; + args[2] = hwif->INB(IDE_NSECTOR_REG); + args[3] = hwif->INB(IDE_SECTOR_REG); + args[4] = hwif->INB(IDE_LCYL_REG); + args[5] = hwif->INB(IDE_HCYL_REG); + args[6] = hwif->INB(IDE_SELECT_REG); + } + } else if (rq->flags & REQ_DRIVE_TASKFILE) { + ide_task_t *args = (ide_task_t *) rq->special; + if (rq->errors == 0) + rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT); + + if (args) { + if (args->tf_in_flags.b.data) { + u16 data = hwif->INW(IDE_DATA_REG); + args->tfRegister[IDE_DATA_OFFSET] = (data) & 0xFF; + args->hobRegister[IDE_DATA_OFFSET_HOB] = (data >> 8) & 0xFF; + } + args->tfRegister[IDE_ERROR_OFFSET] = err; + args->tfRegister[IDE_NSECTOR_OFFSET] = hwif->INB(IDE_NSECTOR_REG); + args->tfRegister[IDE_SECTOR_OFFSET] = hwif->INB(IDE_SECTOR_REG); + args->tfRegister[IDE_LCYL_OFFSET] = hwif->INB(IDE_LCYL_REG); + args->tfRegister[IDE_HCYL_OFFSET] = hwif->INB(IDE_HCYL_REG); + args->tfRegister[IDE_SELECT_OFFSET] = hwif->INB(IDE_SELECT_REG); + args->tfRegister[IDE_STATUS_OFFSET] = stat; + + if (drive->addressing == 1) { + hwif->OUTB(drive->ctl|0x80, IDE_CONTROL_REG_HOB); + args->hobRegister[IDE_FEATURE_OFFSET_HOB] = hwif->INB(IDE_FEATURE_REG); + args->hobRegister[IDE_NSECTOR_OFFSET_HOB] = hwif->INB(IDE_NSECTOR_REG); + args->hobRegister[IDE_SECTOR_OFFSET_HOB] = hwif->INB(IDE_SECTOR_REG); + args->hobRegister[IDE_LCYL_OFFSET_HOB] = hwif->INB(IDE_LCYL_REG); + args->hobRegister[IDE_HCYL_OFFSET_HOB] = hwif->INB(IDE_HCYL_REG); + } + } + } + + spin_lock_irqsave(&ide_lock, flags); + blkdev_dequeue_request(rq); + HWGROUP(drive)->rq = NULL; + end_that_request_last(rq); + spin_unlock_irqrestore(&ide_lock, flags); +} + +EXPORT_SYMBOL(ide_end_drive_cmd); + +/** + * try_to_flush_leftover_data - flush junk + * @drive: drive to flush + * + * try_to_flush_leftover_data() is invoked in response to a drive + * unexpectedly having its DRQ_STAT bit set. As an alternative to + * resetting the drive, this routine tries to clear the condition + * by read a sector's worth of data from the drive. Of course, + * this may not help if the drive is *waiting* for data from *us*. + */ +void try_to_flush_leftover_data (ide_drive_t *drive) +{ + int i = (drive->mult_count ? drive->mult_count : 1) * SECTOR_WORDS; + + if (drive->media != ide_disk) + return; + while (i > 0) { + u32 buffer[16]; + u32 wcount = (i > 16) ? 16 : i; + + i -= wcount; + HWIF(drive)->ata_input_data(drive, buffer, wcount); + } +} + +EXPORT_SYMBOL(try_to_flush_leftover_data); + +/* + * FIXME Add an ATAPI error + */ + +/** + * ide_error - handle an error on the IDE + * @drive: drive the error occurred on + * @msg: message to report + * @stat: status bits + * + * ide_error() takes action based on the error returned by the drive. + * For normal I/O that may well include retries. We deal with + * both new-style (taskfile) and old style command handling here. + * In the case of taskfile command handling there is work left to + * do + */ + +ide_startstop_t ide_error (ide_drive_t *drive, const char *msg, u8 stat) +{ + ide_hwif_t *hwif; + struct request *rq; + u8 err; + + err = ide_dump_status(drive, msg, stat); + 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, stat, err); + return ide_stopped; + } + if (rq->flags & REQ_DRIVE_TASKFILE) { + rq->errors = 1; + ide_end_drive_cmd(drive, stat, err); +// ide_end_taskfile(drive, stat, err); + return ide_stopped; + } + + if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) { + /* other bits are useless when BUSY */ + rq->errors |= ERROR_RESET; + } else { + if (drive->media != ide_disk) + goto media_out; + + if (stat & ERR_STAT) { + /* err has different meaning on cdrom and tape */ + if (err == ABRT_ERR) { + if (drive->select.b.lba && + (hwif->INB(IDE_COMMAND_REG) == WIN_SPECIFY)) + /* some newer drives don't + * support WIN_SPECIFY + */ + return ide_stopped; + } else if ((err & BAD_CRC) == BAD_CRC) { + drive->crc_count++; + /* UDMA crc error -- just retry the operation */ + } else if (err & (BBD_ERR | ECC_ERR)) { + /* retries won't help these */ + rq->errors = ERROR_MAX; + } else if (err & TRK0_ERR) { + /* help it find track zero */ + rq->errors |= ERROR_RECAL; + } + } +media_out: + if ((stat & DRQ_STAT) && rq_data_dir(rq) != WRITE) + try_to_flush_leftover_data(drive); + } + if (hwif->INB(IDE_STATUS_REG) & (BUSY_STAT|DRQ_STAT)) { + /* force an abort */ + 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); + } else { + if ((rq->errors & ERROR_RESET) == ERROR_RESET) { + ++rq->errors; + return ide_do_reset(drive); + } + if ((rq->errors & ERROR_RECAL) == ERROR_RECAL) + drive->special.b.recalibrate = 1; + ++rq->errors; + } + return ide_stopped; +} + +EXPORT_SYMBOL(ide_error); + +/** + * ide_cmd - issue a simple drive command + * @drive: drive the command is for + * @cmd: command byte + * @nsect: sector byte + * @handler: handler for the command completion + * + * Issue a simple drive command with interrupts. + * The drive must be selected beforehand. + */ + +void ide_cmd (ide_drive_t *drive, u8 cmd, u8 nsect, ide_handler_t *handler) +{ + ide_hwif_t *hwif = HWIF(drive); + if (HWGROUP(drive)->handler != NULL) + BUG(); + ide_set_handler(drive, handler, WAIT_CMD, NULL); + if (IDE_CONTROL_REG) + hwif->OUTB(drive->ctl,IDE_CONTROL_REG); /* clear nIEN */ + SELECT_MASK(drive,0); + hwif->OUTB(nsect,IDE_NSECTOR_REG); + hwif->OUTB(cmd,IDE_COMMAND_REG); +} + +EXPORT_SYMBOL(ide_cmd); + +/** + * drive_cmd_intr - drive command completion interrupt + * @drive: drive the completion interrupt occurred on + * + * drive_cmd_intr() is invoked on completion of a special DRIVE_CMD. + * We do any neccessary daya reading and then wait for the drive to + * go non busy. At that point we may read the error data and complete + * the request + */ + +ide_startstop_t drive_cmd_intr (ide_drive_t *drive) +{ + struct request *rq = HWGROUP(drive)->rq; + ide_hwif_t *hwif = HWIF(drive); + u8 *args = (u8 *) rq->buffer; + u8 stat = hwif->INB(IDE_STATUS_REG); + int retries = 10; + + local_irq_enable(); + if ((stat & DRQ_STAT) && args && args[3]) { + u8 io_32bit = drive->io_32bit; + drive->io_32bit = 0; + hwif->ata_input_data(drive, &args[4], args[3] * SECTOR_WORDS); + drive->io_32bit = io_32bit; + while (((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) && retries--) + udelay(100); + } + + if (!OK_STAT(stat, READY_STAT, BAD_STAT)) + return DRIVER(drive)->error(drive, "drive_cmd", stat); + /* calls ide_end_drive_cmd */ + ide_end_drive_cmd(drive, stat, hwif->INB(IDE_ERROR_REG)); + return ide_stopped; +} + +EXPORT_SYMBOL(drive_cmd_intr); + +/** + * do_special - issue some special commands + * @drive: drive the command is for + * + * do_special() is used to issue WIN_SPECIFY, WIN_RESTORE, and WIN_SETMULT + * commands to a drive. It used to do much more, but has been scaled + * back. + */ + +ide_startstop_t do_special (ide_drive_t *drive) +{ + special_t *s = &drive->special; + +#ifdef DEBUG + printk("%s: do_special: 0x%02x\n", drive->name, s->all); +#endif + if (s->b.set_tune) { + 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; +} + +EXPORT_SYMBOL(do_special); + +/** + * execute_drive_command - issue special drive command + * @drive: the drive to issue th command on + * @rq: the request structure holding the command + * + * execute_drive_cmd() issues a special drive command, usually + * initiated by ioctl() from the external hdparm program. The + * command can be a drive command, drive task or taskfile + * operation. Weirdly you can call it with NULL to wait for + * all commands to finish. Don't do this as that is due to change + */ + +ide_startstop_t execute_drive_cmd (ide_drive_t *drive, struct request *rq) +{ + ide_hwif_t *hwif = HWIF(drive); + if (rq->flags & REQ_DRIVE_TASKFILE) { + ide_task_t *args = rq->special; + + if (!args) + goto done; + + if (args->tf_out_flags.all != 0) + return flagged_taskfile(drive, args); + return do_rw_taskfile(drive, args); + } else if (rq->flags & REQ_DRIVE_TASK) { + u8 *args = rq->buffer; + u8 sel; + + if (!args) + goto done; +#ifdef DEBUG + printk("%s: DRIVE_TASK_CMD ", drive->name); + printk("cmd=0x%02x ", args[0]); + printk("fr=0x%02x ", args[1]); + printk("ns=0x%02x ", args[2]); + printk("sc=0x%02x ", args[3]); + printk("lcyl=0x%02x ", args[4]); + printk("hcyl=0x%02x ", args[5]); + printk("sel=0x%02x\n", args[6]); +#endif + hwif->OUTB(args[1], IDE_FEATURE_REG); + hwif->OUTB(args[3], IDE_SECTOR_REG); + hwif->OUTB(args[4], IDE_LCYL_REG); + hwif->OUTB(args[5], IDE_HCYL_REG); + sel = (args[6] & ~0x10); + if (drive->select.b.unit) + sel |= 0x10; + hwif->OUTB(sel, IDE_SELECT_REG); + ide_cmd(drive, args[0], args[2], &drive_cmd_intr); + return ide_started; + } else if (rq->flags & REQ_DRIVE_CMD) { + u8 *args = rq->buffer; + + if (!args) + goto done; +#ifdef DEBUG + printk("%s: DRIVE_CMD ", drive->name); + printk("cmd=0x%02x ", args[0]); + printk("sc=0x%02x ", args[1]); + printk("fr=0x%02x ", args[2]); + printk("xx=0x%02x\n", args[3]); +#endif + if (args[0] == WIN_SMART) { + hwif->OUTB(0x4f, IDE_LCYL_REG); + hwif->OUTB(0xc2, IDE_HCYL_REG); + hwif->OUTB(args[2],IDE_FEATURE_REG); + hwif->OUTB(args[1],IDE_SECTOR_REG); + ide_cmd(drive, args[0], args[3], &drive_cmd_intr); + return ide_started; + } + hwif->OUTB(args[2],IDE_FEATURE_REG); + ide_cmd(drive, args[0], args[1], &drive_cmd_intr); + return ide_started; + } + +done: + /* + * NULL is actually a valid way of waiting for + * all current requests to be flushed from the queue. + */ +#ifdef DEBUG + printk("%s: DRIVE_CMD (null)\n", drive->name); +#endif + ide_end_drive_cmd(drive, + hwif->INB(IDE_STATUS_REG), + hwif->INB(IDE_ERROR_REG)); + return ide_stopped; +} + +EXPORT_SYMBOL(execute_drive_cmd); + +/** + * start_request - start of I/O and command issuing for IDE + * + * start_request() initiates handling of a new I/O request. It + * accepts commands and I/O (read/write) requests. It also does + * the final remapping for weird stuff like EZDrive. Once + * device mapper can work sector level the EZDrive stuff can go away + * + * FIXME: this function needs a rename + */ + +ide_startstop_t start_request (ide_drive_t *drive, struct request *rq) +{ + ide_startstop_t startstop; + unsigned long block; + + BUG_ON(!(rq->flags & REQ_STARTED)); + +#ifdef DEBUG + printk("%s: start_request: current=0x%08lx\n", + HWIF(drive)->name, (unsigned long) rq); +#endif + + /* bail early if we've exceeded max_failures */ + if (drive->max_failures && (drive->failures > drive->max_failures)) { + goto kill_rq; + } + + /* + * bail early if we've sent a device to sleep, however how to wake + * this needs to be a masked flag. FIXME for proper operations. + */ + if (drive->suspend_reset) + goto kill_rq; + + block = rq->sector; + if (blk_fs_request(rq) && + (drive->media == ide_disk || drive->media == ide_floppy)) { + block += drive->sect0; + } + /* Yecch - this will shift the entire interval, + possibly killing some innocent following sector */ + if (block == 0 && drive->remap_0_to_1 == 1) + block = 1; /* redirect MBR access to EZ-Drive partn table */ + +#if (DISK_RECOVERY_TIME > 0) + while ((read_timer() - HWIF(drive)->last_time) < DISK_RECOVERY_TIME); +#endif + + SELECT_DRIVE(drive); + if (ide_wait_stat(&startstop, drive, drive->ready_stat, BUSY_STAT|DRQ_STAT, WAIT_READY)) { + printk(KERN_ERR "%s: drive not ready for command\n", drive->name); + return startstop; + } + if (!drive->special.all) { + if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK)) + 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 do_special(drive); +kill_rq: + if (drive->driver != NULL) + DRIVER(drive)->end_request(drive, 0, 0); + else + ide_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) + * + * ide_stall_queue() can be used by a drive to give excess bandwidth back + * to the hwgroup by sleeping for timeout jiffies. + */ + +void ide_stall_queue (ide_drive_t *drive, unsigned long timeout) +{ + if (timeout > WAIT_WORSTCASE) + timeout = WAIT_WORSTCASE; + drive->sleep = timeout + jiffies; +} + +EXPORT_SYMBOL(ide_stall_queue); + +#define WAKEUP(drive) ((drive)->service_start + 2 * (drive)->service_time) + +/** + * choose_drive - select a drive to service + * @hwgroup: hardware group to select on + * + * choose_drive() selects the next drive which will be serviced. + * This is neccessary because the IDE layer can't issue commands + * to both drives on the same cable, unlike SCSI. + */ + +static inline ide_drive_t *choose_drive (ide_hwgroup_t *hwgroup) +{ + ide_drive_t *drive, *best; + +repeat: + best = NULL; + drive = hwgroup->drive; + do { + if (!blk_queue_empty(&drive->queue) && (!drive->sleep || time_after_eq(jiffies, drive->sleep))) { + if (!best + || (drive->sleep && (!best->sleep || 0 < (signed long)(best->sleep - drive->sleep))) + || (!best->sleep && 0 < (signed long)(WAKEUP(best) - WAKEUP(drive)))) + { + if (!blk_queue_plugged(&drive->queue)) + best = drive; + } + } + } while ((drive = drive->next) != hwgroup->drive); + if (best && best->nice1 && !best->sleep && best != hwgroup->drive && best->service_time > WAIT_MIN_SLEEP) { + long t = (signed long)(WAKEUP(best) - jiffies); + if (t >= WAIT_MIN_SLEEP) { + /* + * We *may* have some time to spare, but first let's see if + * someone can potentially benefit from our nice mood today.. + */ + drive = best->next; + do { + if (!drive->sleep + /* FIXME: use time_before */ + && 0 < (signed long)(WAKEUP(drive) - (jiffies - best->service_time)) + && 0 < (signed long)((jiffies + t) - WAKEUP(drive))) + { + ide_stall_queue(best, IDE_MIN(t, 10 * WAIT_MIN_SLEEP)); + goto repeat; + } + } while ((drive = drive->next) != best); + } + } + return best; +} + +/* + * Issue a new request to a drive from hwgroup + * Caller must have already done spin_lock_irqsave(&ide_lock, ..); + * + * A hwgroup is a serialized group of IDE interfaces. Usually there is + * exactly one hwif (interface) per hwgroup, but buggy controllers (eg. CMD640) + * may have both interfaces in a single hwgroup to "serialize" access. + * Or possibly multiple ISA interfaces can share a common IRQ by being grouped + * together into one hwgroup for serialized access. + * + * Note also that several hwgroups can end up sharing a single IRQ, + * possibly along with many other devices. This is especially common in + * PCI-based systems with off-board IDE controller cards. + * + * The IDE driver uses the single global ide_lock spinlock to protect + * access to the request queues, and to protect the hwgroup->busy flag. + * + * The first thread into the driver for a particular hwgroup sets the + * hwgroup->busy flag to indicate that this hwgroup is now active, + * and then initiates processing of the top request from the request queue. + * + * Other threads attempting entry notice the busy setting, and will simply + * queue their new requests and exit immediately. Note that hwgroup->busy + * remains set even when the driver is merely awaiting the next interrupt. + * Thus, the meaning is "this hwgroup is busy processing a request". + * + * When processing of a request completes, the completing thread or IRQ-handler + * will start the next request from the queue. If no more work remains, + * the driver will clear the hwgroup->busy flag and exit. + * + * The ide_lock (spinlock) is used to protect all access to the + * hwgroup->busy flag, but is otherwise not needed for most processing in + * the driver. This makes the driver much more friendlier to shared IRQs + * than previous designs, while remaining 100% (?) SMP safe and capable. + */ +/* --BenH: made non-static as ide-pmac.c uses it to kick the hwgroup back + * into life on wakeup from machine sleep. + */ +void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq) +{ + ide_drive_t *drive; + ide_hwif_t *hwif; + struct request *rq; + ide_startstop_t startstop; + + /* for atari only: POSSIBLY BROKEN HERE(?) */ + ide_get_lock(&ide_intr_lock, ide_intr, hwgroup); + + /* necessary paranoia: ensure IRQs are masked on local CPU */ + local_irq_disable(); + + while (!hwgroup->busy) { + hwgroup->busy = 1; + drive = choose_drive(hwgroup); + if (drive == NULL) { + unsigned long sleep = 0; + hwgroup->rq = NULL; + drive = hwgroup->drive; + do { + if (drive->sleep && (!sleep || 0 < (signed long)(sleep - drive->sleep))) + sleep = drive->sleep; + } while ((drive = drive->next) != hwgroup->drive); + if (sleep) { + /* + * Take a short snooze, and then wake up this hwgroup again. + * This gives other hwgroups on the same a chance to + * play fairly with us, just in case there are big differences + * in relative throughputs.. don't want to hog the cpu too much. + */ + if (time_before(sleep, jiffies + WAIT_MIN_SLEEP)) + sleep = jiffies + WAIT_MIN_SLEEP; +#if 1 + if (timer_pending(&hwgroup->timer)) + printk(KERN_CRIT "ide_set_handler: timer already active\n"); +#endif + /* so that ide_timer_expiry knows what to do */ + hwgroup->sleeping = 1; + mod_timer(&hwgroup->timer, sleep); + /* we purposely leave hwgroup->busy==1 + * while sleeping */ + } else { + /* Ugly, but how can we sleep for the lock + * otherwise? perhaps from tq_disk? + */ + + /* for atari only */ + ide_release_lock(&ide_intr_lock); + hwgroup->busy = 0; + } + + /* no more work for this hwgroup (for now) */ + return; + } + hwif = HWIF(drive); + if (hwgroup->hwif->sharing_irq && + hwif != hwgroup->hwif && + hwif->io_ports[IDE_CONTROL_OFFSET]) { + /* set nIEN for previous hwif */ + SELECT_INTERRUPT(drive); + } + hwgroup->hwif = hwif; + hwgroup->drive = drive; + drive->sleep = 0; + drive->service_start = jiffies; + +queue_next: + if (!ata_can_queue(drive)) { + if (!ata_pending_commands(drive)) + hwgroup->busy = 0; + + break; + } + + if (blk_queue_plugged(&drive->queue)) { + if (drive->using_tcq) + break; + + printk(KERN_ERR "ide: huh? queue was plugged!\n"); + break; + } + + /* + * we know that the queue isn't empty, but this can happen + * if the q->prep_rq_fn() decides to kill a request + */ + rq = elv_next_request(&drive->queue); + if (!rq) { + hwgroup->busy = !!ata_pending_commands(drive); + break; + } + + if (!rq->bio && ata_pending_commands(drive)) + break; + + hwgroup->rq = rq; + + /* + * Some systems have trouble with IDE IRQs arriving while + * the driver is still setting things up. So, here we disable + * the IRQ used by this interface while the request is being started. + * This may look bad at first, but pretty much the same thing + * happens anyway when any interrupt comes in, IDE or otherwise + * -- the kernel masks the IRQ while it is being handled. + */ + if (masked_irq && hwif->irq != masked_irq) + disable_irq_nosync(hwif->irq); + spin_unlock(&ide_lock); + local_irq_enable(); + /* allow other IRQs while we start this request */ + startstop = start_request(drive, rq); + spin_lock_irq(&ide_lock); + if (masked_irq && hwif->irq != masked_irq) + enable_irq(hwif->irq); + if (startstop == ide_released) + goto queue_next; + if (startstop == ide_stopped) + hwgroup->busy = 0; + } +} + +EXPORT_SYMBOL(ide_do_request); + +/* + * Passes the stuff to ide_do_request + */ +void do_ide_request(request_queue_t *q) +{ + ide_do_request(q->queuedata, 0); +} + +/* + * un-busy the hwgroup etc, and clear any pending DMA status. we want to + * retry the current request in pio mode instead of risking tossing it + * all away + */ +void ide_dma_timeout_retry(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + struct request *rq; + + /* + * end current dma transaction + */ + (void) hwif->ide_dma_end(drive); + + /* + * complain a little, later we might remove some of this verbosity + */ + printk(KERN_WARNING "%s: timeout waiting for DMA\n", drive->name); + (void) hwif->ide_dma_timeout(drive); + + /* + * disable dma for now, but remember that we did so because of + * a timeout -- we'll reenable after we finish this next request + * (or rather the first chunk of it) in pio. + */ + drive->retry_pio++; + drive->state = DMA_PIO_RETRY; + (void) hwif->ide_dma_off_quietly(drive); + + /* + * un-busy drive etc (hwgroup->busy is cleared on return) and + * make sure request is sane + */ + rq = HWGROUP(drive)->rq; + HWGROUP(drive)->rq = NULL; + + rq->errors = 0; + rq->sector = rq->bio->bi_sector; + rq->current_nr_sectors = bio_iovec(rq->bio)->bv_len >> 9; + rq->hard_cur_sectors = rq->current_nr_sectors; + if (rq->bio) + rq->buffer = NULL; +} + +EXPORT_SYMBOL(ide_dma_timeout_retry); + +/** + * ide_timer_expiry - handle lack of an IDE interrupt + * @data: timer callback magic (hwgroup) + * + * An IDE command has timed out before the expected drive return + * occurred. At this point we attempt to clean up the current + * mess. If the current handler includes an expiry handler then + * we invoke the expiry handler, and providing it is happy the + * work is done. If that fails we apply generic recovery rules + * invoking the handler and checking the drive DMA status. We + * have an excessively incestuous relationship with the DMA + * logic that wants cleaning up. + */ + +void ide_timer_expiry (unsigned long data) +{ + ide_hwgroup_t *hwgroup = (ide_hwgroup_t *) data; + ide_handler_t *handler; + ide_expiry_t *expiry; + unsigned long flags; + unsigned long wait; + + spin_lock_irqsave(&ide_lock, flags); + del_timer(&hwgroup->timer); + + if ((handler = hwgroup->handler) == NULL) { + /* + * Either a marginal timeout occurred + * (got the interrupt just as timer expired), + * or we were "sleeping" to give other devices a chance. + * Either way, we don't really want to complain about anything. + */ + if (hwgroup->sleeping) { + hwgroup->sleeping = 0; + hwgroup->busy = 0; + } + } else { + ide_drive_t *drive = hwgroup->drive; + if (!drive) { + printk(KERN_ERR "ide_timer_expiry: hwgroup->drive was NULL\n"); + hwgroup->handler = NULL; + } else { + ide_hwif_t *hwif; + ide_startstop_t startstop = ide_stopped; + if (!hwgroup->busy) { + hwgroup->busy = 1; /* paranoia */ + printk(KERN_ERR "%s: ide_timer_expiry: hwgroup->busy was 0 ??\n", drive->name); + } + if ((expiry = hwgroup->expiry) != NULL) { + /* continue */ + if ((wait = expiry(drive)) != 0) { + /* reset timer */ + hwgroup->timer.expires = jiffies + wait; + add_timer(&hwgroup->timer); + spin_unlock_irqrestore(&ide_lock, flags); + return; + } + } + hwgroup->handler = NULL; + /* + * We need to simulate a real interrupt when invoking + * the handler() function, which means we need to + * globally mask the specific IRQ: + */ + spin_unlock(&ide_lock); + hwif = HWIF(drive); +#if DISABLE_IRQ_NOSYNC + disable_irq_nosync(hwif->irq); +#else + /* disable_irq_nosync ?? */ + disable_irq(hwif->irq); +#endif /* DISABLE_IRQ_NOSYNC */ + /* local CPU only, + * as if we were handling an interrupt */ + local_irq_disable(); + if (hwgroup->poll_timeout != 0) { + startstop = handler(drive); + } else if (drive_is_ready(drive)) { + if (drive->waiting_for_dma) + (void) hwgroup->hwif->ide_dma_lostirq(drive); + (void)ide_ack_intr(hwif); + printk(KERN_WARNING "%s: lost interrupt\n", drive->name); + startstop = handler(drive); + } else { + if (drive->waiting_for_dma) { + startstop = ide_stopped; + ide_dma_timeout_retry(drive); + } else + startstop = DRIVER(drive)->error(drive, "irq timeout", hwif->INB(IDE_STATUS_REG)); + } + set_recovery_timer(hwif); + drive->service_time = jiffies - drive->service_start; + enable_irq(hwif->irq); + spin_lock_irq(&ide_lock); + if (startstop == ide_stopped) + hwgroup->busy = 0; + } + } + ide_do_request(hwgroup, 0); + spin_unlock_irqrestore(&ide_lock, flags); +} + +EXPORT_SYMBOL(ide_timer_expiry); + +/** + * unexpected_intr - handle an unexpected IDE interrupt + * @irq: interrupt line + * @hwgroup: hwgroup being processed + * + * There's nothing really useful we can do with an unexpected interrupt, + * other than reading the status register (to clear it), and logging it. + * There should be no way that an irq can happen before we're ready for it, + * so we needn't worry much about losing an "important" interrupt here. + * + * 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. + * + * This routine assumes __cli() is in effect when called. + * + * If an unexpected interrupt happens on irq15 while we are handling irq14 + * and if the two interfaces are "serialized" (CMD640), then it looks like + * we could screw up by interfering with a new request being set up for + * irq15. + * + * In reality, this is a non-issue. The new command is not sent unless + * the drive is ready to accept one, in which case we know the drive is + * not trying to interrupt us. And ide_set_handler() is always invoked + * before completing the issuance of any new drive command, so we will not + * be accidentally invoked as a result of any valid command completion + * interrupt. + * + * Note that we must walk the entire hwgroup here. We know which hwif + * is doing the current command, but we don't know which hwif burped + * mysteriously. + */ + +static void unexpected_intr (int irq, ide_hwgroup_t *hwgroup) +{ + u8 stat; + ide_hwif_t *hwif = hwgroup->hwif; + + /* + * handle the unexpected interrupt + */ + do { + if (hwif->irq == irq) { + stat = hwif->INB(hwif->io_ports[IDE_STATUS_OFFSET]); + if (!OK_STAT(stat, READY_STAT, BAD_STAT)) { + /* Try to not flood the console with msgs */ + static unsigned long last_msgtime, count; + ++count; + if (time_after(jiffies, last_msgtime + HZ)) { + last_msgtime = jiffies; + printk(KERN_ERR "%s%s: unexpected interrupt, " + "status=0x%02x, count=%ld\n", + hwif->name, + (hwif->next==hwgroup->hwif) ? "" : "(?)", stat, count); + } + } + } + } while ((hwif = hwif->next) != hwgroup->hwif); +} + +/** + * ide_intr - default IDE interrupt handler + * @irq: interrupt number + * @dev_id: hwif group + * @regs: unused weirdness from the kernel irq layer + * + * This is the default IRQ handler for the IDE layer. You should + * not need to override it. If you do be aware it is subtle in + * places + * + * hwgroup->hwif is the interface in the group currently performing + * a command. hwgroup->drive is the drive and hwgroup->handler is + * the IRQ handler to call. As we issue a command the handlers + * step through multiple states, reassigning the handler to the + * next step in the process. Unlike a smart SCSI controller IDE + * expects the main processor to sequence the various transfer + * stages. We also manage a poll timer to catch up with most + * timeout situations. There are still a few where the handlers + * don't ever decide to give up. + * + * The handler eventually returns ide_stopped to indicate the + * request completed. At this point we issue the next request + * on the hwgroup and the process begins again. + */ + +void ide_intr (int irq, void *dev_id, struct pt_regs *regs) +{ + unsigned long flags; + ide_hwgroup_t *hwgroup = (ide_hwgroup_t *)dev_id; + ide_hwif_t *hwif; + ide_drive_t *drive; + ide_handler_t *handler; + ide_startstop_t startstop; + + spin_lock_irqsave(&ide_lock, flags); + hwif = hwgroup->hwif; + + if (!ide_ack_intr(hwif)) { + spin_unlock_irqrestore(&ide_lock, flags); + return; + } + + if ((handler = hwgroup->handler) == NULL || + hwgroup->poll_timeout != 0) { + /* + * Not expecting an interrupt from this drive. + * That means this could be: + * (1) an interrupt from another PCI device + * sharing the same PCI INT# as us. + * or (2) a drive just entered sleep or standby mode, + * and is interrupting to let us know. + * or (3) a spurious interrupt of unknown origin. + * + * For PCI, we cannot tell the difference, + * so in that case we just ignore it and hope it goes away. + * + * FIXME: unexpected_intr should be hwif-> then we can + * remove all the ifdef PCI crap + */ +#ifdef CONFIG_BLK_DEV_IDEPCI + if (hwif->pci_dev && !hwif->pci_dev->vendor) +#endif /* CONFIG_BLK_DEV_IDEPCI */ + { + /* + * Probably not a shared PCI interrupt, + * so we can safely try to do something about it: + */ + unexpected_intr(irq, hwgroup); +#ifdef CONFIG_BLK_DEV_IDEPCI + } else { + /* + * Whack the status register, just in case + * we have a leftover pending IRQ. + */ + (void) hwif->INB(hwif->io_ports[IDE_STATUS_OFFSET]); +#endif /* CONFIG_BLK_DEV_IDEPCI */ + } + spin_unlock_irqrestore(&ide_lock, flags); + return; + } + drive = hwgroup->drive; + if (!drive) { + /* + * This should NEVER happen, and there isn't much + * we could do about it here. + * + * [Note - this can occur if the drive is hot unplugged] + */ + spin_unlock_irqrestore(&ide_lock, flags); + return; + } + if (!drive_is_ready(drive)) { + /* + * This happens regularly when we share a PCI IRQ with + * another device. Unfortunately, it can also happen + * with some buggy drives that trigger the IRQ before + * their status register is up to date. Hopefully we have + * enough advance overhead that the latter isn't a problem. + */ + spin_unlock_irqrestore(&ide_lock, flags); + return; + } + if (!hwgroup->busy) { + hwgroup->busy = 1; /* paranoia */ + printk(KERN_ERR "%s: ide_intr: hwgroup->busy was 0 ??\n", drive->name); + } + hwgroup->handler = NULL; + del_timer(&hwgroup->timer); + spin_unlock(&ide_lock); + + if (drive->unmask) + local_irq_enable(); + /* service this interrupt, may set handler for next interrupt */ + startstop = handler(drive); + spin_lock_irq(&ide_lock); + + /* + * Note that handler() may have set things up for another + * interrupt to occur soon, but it cannot happen until + * we exit from this routine, because it will be the + * same irq as is currently being serviced here, and Linux + * won't allow another of the same (on any CPU) until we return. + */ + set_recovery_timer(HWIF(drive)); + drive->service_time = jiffies - drive->service_start; + if (startstop == ide_stopped) { + if (hwgroup->handler == NULL) { /* paranoia */ + hwgroup->busy = 0; + ide_do_request(hwgroup, hwif->irq); + } else { + printk(KERN_ERR "%s: ide_intr: huh? expected NULL handler " + "on exit\n", drive->name); + } + } + spin_unlock_irqrestore(&ide_lock, flags); +} + +EXPORT_SYMBOL(ide_intr); + +/** + * ide_init_drive_cmd - initialize a drive command request + * @rq: request object + * + * Initialize a request before we fill it in and send it down to + * ide_do_drive_cmd. Commands must be set up by this function. Right + * now it doesn't do a lot, but if that changes abusers will have a + * nasty suprise. + */ + +void ide_init_drive_cmd (struct request *rq) +{ + memset(rq, 0, sizeof(*rq)); + rq->flags = REQ_DRIVE_CMD; +} + +EXPORT_SYMBOL(ide_init_drive_cmd); + +/** + * ide_do_drive_cmd - issue IDE special command + * @drive: device to issue command + * @rq: request to issue + * @action: action for processing + * + * This function issues a special IDE device request + * onto the request queue. + * + * If action is ide_wait, then the rq is queued at the end of the + * request queue, and the function sleeps until it has been processed. + * This is for use when invoked from an ioctl handler. + * + * If action is ide_preempt, then the rq is queued at the head of + * the request queue, displacing the currently-being-processed + * request and this function returns immediately without waiting + * for the new rq to be completed. This is VERY DANGEROUS, and is + * intended for careful use by the ATAPI tape/cdrom driver code. + * + * If action is ide_next, then the rq is queued immediately after + * the currently-being-processed-request (if any), and the function + * returns without waiting for the new rq to be completed. As above, + * This is VERY DANGEROUS, and is intended for careful use by the + * ATAPI tape/cdrom driver code. + * + * If action is ide_end, then the rq is queued at the end of the + * request queue, and the function returns immediately without waiting + * for the new rq to be completed. This is again intended for careful + * use by the ATAPI tape/cdrom driver code. + */ + +int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t action) +{ + unsigned long flags; + ide_hwgroup_t *hwgroup = HWGROUP(drive); + DECLARE_COMPLETION(wait); + int insert_end = 1, err; + +#ifdef CONFIG_BLK_DEV_PDC4030 + /* + * FIXME: there should be a drive or hwif->special + * handler that points here by default, not hacks + * in the ide-io.c code + */ + if (HWIF(drive)->chipset == ide_pdc4030 && rq->buffer != NULL) + return -ENOSYS; /* special drive cmds not supported */ +#endif + rq->errors = 0; + rq->rq_status = RQ_ACTIVE; + + rq->rq_disk = drive->disk; + + /* + * we need to hold an extra reference to request for safe inspection + * after completion + */ + if (action == ide_wait) { + rq->ref_count++; + rq->waiting = &wait; + } + + spin_lock_irqsave(&ide_lock, flags); + if (action == ide_preempt) { + hwgroup->rq = NULL; + insert_end = 0; + } + __elv_add_request(&drive->queue, rq, insert_end, 0); + ide_do_request(hwgroup, 0); + spin_unlock_irqrestore(&ide_lock, flags); + + err = 0; + if (action == ide_wait) { + wait_for_completion(&wait); + if (rq->errors) + err = -EIO; + + blk_put_request(rq); + } + + return err; +} + +EXPORT_SYMBOL(ide_do_drive_cmd); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/ide/ide-iops.c linux.2.5.47-ac4/drivers/ide/ide-iops.c --- linux.2.5.47/drivers/ide/ide-iops.c 2002-10-31 14:57:17.000000000 +0000 +++ linux.2.5.47-ac4/drivers/ide/ide-iops.c 2002-11-13 15:06:55.000000000 +0000 @@ -57,14 +57,14 @@ insl(port, addr, count); } -static void ide_outb (u8 addr, ide_ioreg_t port) +static void ide_outb (u8 value, ide_ioreg_t port) { - outb(addr, port); + outb(value, port); } -static void ide_outw (u16 addr, ide_ioreg_t port) +static void ide_outw (u16 value, ide_ioreg_t port) { - outw(addr, port); + outw(value, port); } static void ide_outsw (ide_ioreg_t port, void *addr, u32 count) @@ -72,9 +72,9 @@ outsw(port, addr, count); } -static void ide_outl (u32 addr, ide_ioreg_t port) +static void ide_outl (u32 value, ide_ioreg_t port) { - outl(addr, port); + outl(value, port); } static void ide_outsl (ide_ioreg_t port, void *addr, u32 count) @@ -819,9 +819,9 @@ // while (HWGROUP(drive)->busy) // ide_delay_50ms(); -#if defined(CONFIG_BLK_DEV_IDEDMA) && !defined(CONFIG_DMA_NONPCI) +#if !defined(CONFIG_DMA_NONPCI) hwif->ide_dma_host_off(drive); -#endif /* (CONFIG_BLK_DEV_IDEDMA) && !(CONFIG_DMA_NONPCI) */ +#endif /* !(CONFIG_DMA_NONPCI) */ /* * Don't use ide_wait_cmd here - it will @@ -887,12 +887,12 @@ drive->id->dma_mword &= ~0x0F00; drive->id->dma_1word &= ~0x0F00; -#if defined(CONFIG_BLK_DEV_IDEDMA) && !defined(CONFIG_DMA_NONPCI) +#if !defined(CONFIG_DMA_NONPCI) if (speed >= XFER_SW_DMA_0) hwif->ide_dma_host_on(drive); else hwif->ide_dma_off(drive); -#endif /* (CONFIG_BLK_DEV_IDEDMA) && !(CONFIG_DMA_NONPCI) */ +#endif /* !(CONFIG_DMA_NONPCI) */ switch(speed) { case XFER_UDMA_7: drive->id->dma_ultra |= 0x8080; break; @@ -1057,8 +1057,7 @@ { if (drive->crc_count) { (void) HWIF(drive)->ide_dma_off_quietly(drive); - if ((HWIF(drive)->speedproc) != NULL) - HWIF(drive)->speedproc(drive, ide_auto_reduce_xfer(drive)); + ide_set_xfer_rate(drive, ide_auto_reduce_xfer(drive)); if (drive->current_speed >= XFER_SW_DMA_0) (void) HWIF(drive)->ide_dma_on(drive); } else { diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/ide/ide-lib.c linux.2.5.47-ac4/drivers/ide/ide-lib.c --- linux.2.5.47/drivers/ide/ide-lib.c 2002-11-05 13:54:43.000000000 +0000 +++ linux.2.5.47-ac4/drivers/ide/ide-lib.c 2002-11-14 17:12:22.000000000 +0000 @@ -300,7 +300,7 @@ } /** - * ide_get_best_pio_mode - get PIO mode fro drive + * ide_get_best_pio_mode - get PIO mode from drive * @driver: drive to consider * @mode_wanted: preferred mode * @max_mode: highest allowed @@ -387,6 +387,15 @@ EXPORT_SYMBOL_GPL(ide_get_best_pio_mode); +/** + * ide_toggle_bounce - handle bounce buffering + * @drive: drive to update + * @on: on/off boolean + * + * Enable or disable bounce buffering for the device. Drives move + * between PIO and DMA and that changes the rules we need. + */ + void ide_toggle_bounce(ide_drive_t *drive, int on) { u64 addr = BLK_BOUNCE_HIGH; /* dma64_addr_t */ @@ -402,3 +411,28 @@ } EXPORT_SYMBOL(ide_toggle_bounce); + +/** + * ide_set_xfer_rate - set transfer rate + * @drive: drive to set + * @speed: speed to attempt to set + * + * General helper for setting the speed of an IDE device. This + * function knows about user enforced limits from the configuration + * which speedproc() does not. High level drivers should never + * invoke speedproc() directly. + */ + +int ide_set_xfer_rate(ide_drive_t *drive, u8 rate) +{ +#ifndef CONFIG_BLK_DEV_IDEDMA + rate = min(rate, (u8) XFER_PIO_4); +#endif + if(HWIF(drive)->speedproc) + return HWIF(drive)->speedproc(drive, rate); + else + return -1; +} + +EXPORT_SYMBOL_GPL(ide_set_xfer_rate); + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/ide/ide-probe.c linux.2.5.47-ac4/drivers/ide/ide-probe.c --- linux.2.5.47/drivers/ide/ide-probe.c 2002-11-11 16:39:10.000000000 +0000 +++ linux.2.5.47-ac4/drivers/ide/ide-probe.c 2002-11-13 22:49:14.000000000 +0000 @@ -144,6 +144,7 @@ id->model[sizeof(id->model)-1] = '\0'; printk("%s: %s, ", drive->name, id->model); drive->present = 1; + drive->dead = 0; /* * Check for an ATAPI device @@ -1059,6 +1060,7 @@ "%s","IDE Drive"); drive->gendev.parent = &hwif->gendev; drive->gendev.bus = &ide_bus_type; + drive->gendev.driver_data = drive; sprintf (name, "host%d/bus%d/target%d/lun%d", (hwif->channel && hwif->mate) ? hwif->mate->index : hwif->index, diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/ide/ide-tape.c linux.2.5.47-ac4/drivers/ide/ide-tape.c --- linux.2.5.47/drivers/ide/ide-tape.c 2002-11-05 13:54:43.000000000 +0000 +++ linux.2.5.47-ac4/drivers/ide/ide-tape.c 2002-11-13 15:00:24.000000000 +0000 @@ -1450,7 +1450,6 @@ } } -#ifdef CONFIG_BLK_DEV_IDEDMA static void idetape_update_buffers (idetape_pc_t *pc) { struct bio *bio = pc->bio; @@ -1475,7 +1474,6 @@ } pc->bio = bio; } -#endif /* CONFIG_BLK_DEV_IDEDMA */ /* * idetape_next_pc_storage returns a pointer to a place in which we can @@ -1580,7 +1578,6 @@ ide_stall_queue(drive, HZ / 2); return; } -#ifdef CONFIG_BLK_DEV_IDEDMA /* * Correct pc->actually_transferred by asking the tape. @@ -1589,7 +1586,7 @@ pc->actually_transferred = pc->request_transfer - tape->tape_block_size * ntohl(get_unaligned(&result->information)); idetape_update_buffers(pc); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ + if (pc->c[0] == IDETAPE_READ_CMD && result->filemark) { pc->error = IDETAPE_ERROR_FILEMARK; set_bit(PC_ABORT, &pc->flags); @@ -1982,7 +1979,6 @@ /* Clear the interrupt */ status.all = HWIF(drive)->INB(IDE_STATUS_REG); -#ifdef CONFIG_BLK_DEV_IDEDMA if (test_bit(PC_DMA_IN_PROGRESS, &pc->flags)) { if (HWIF(drive)->ide_dma_end(drive)) { /* @@ -2006,7 +2002,6 @@ printk(KERN_INFO "ide-tape: DMA finished\n"); #endif /* IDETAPE_DEBUG_LOG */ } -#endif /* CONFIG_BLK_DEV_IDEDMA */ /* No more interrupts */ if (!status.b.drq) { @@ -2061,7 +2056,6 @@ tape->failed_pc = NULL; return pc->callback(drive); /* Command finished - Call the callback function */ } -#ifdef CONFIG_BLK_DEV_IDEDMA if (test_and_clear_bit(PC_DMA_IN_PROGRESS, &pc->flags)) { printk(KERN_ERR "ide-tape: The tape wants to issue more " "interrupts in DMA mode\n"); @@ -2069,7 +2063,6 @@ (void) HWIF(drive)->ide_dma_off(drive); return ide_do_reset(drive); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ bcount.b.high = IN_BYTE(IDE_BCOUNTH_REG); /* Get the number of bytes to transfer */ bcount.b.low = IN_BYTE(IDE_BCOUNTL_REG); /* on this interrupt */ ireason.all = IN_BYTE(IDE_IREASON_REG); @@ -2264,7 +2257,6 @@ pc->current_position = pc->buffer; bcount.all = pc->request_transfer; /* Request to transfer the entire buffer at once */ -#ifdef CONFIG_BLK_DEV_IDEDMA if (test_and_clear_bit(PC_DMA_ERROR, &pc->flags)) { printk(KERN_WARNING "ide-tape: DMA disabled, " "reverting to PIO\n"); @@ -2276,7 +2268,6 @@ else dma_ok = !HWIF(drive)->ide_dma_read(drive); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ if (IDE_CONTROL_REG) OUT_BYTE(drive->ctl, IDE_CONTROL_REG); @@ -2284,12 +2275,10 @@ OUT_BYTE(bcount.b.high, IDE_BCOUNTH_REG); OUT_BYTE(bcount.b.low, IDE_BCOUNTL_REG); OUT_BYTE(drive->select.all, IDE_SELECT_REG); -#ifdef CONFIG_BLK_DEV_IDEDMA if (dma_ok) { /* Begin DMA, if necessary */ set_bit(PC_DMA_IN_PROGRESS, &pc->flags); (void) (HWIF(drive)->ide_dma_begin(drive)); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ if (test_bit(IDETAPE_DRQ_INTERRUPT, &tape->flags)) { if (HWGROUP(drive)->handler != NULL) /* paranoia check */ BUG(); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/ide/ide-taskfile.c linux.2.5.47-ac4/drivers/ide/ide-taskfile.c --- linux.2.5.47/drivers/ide/ide-taskfile.c 2002-11-05 13:54:43.000000000 +0000 +++ linux.2.5.47-ac4/drivers/ide/ide-taskfile.c 2002-11-13 15:06:17.000000000 +0000 @@ -1068,7 +1068,6 @@ case DISABLE_SEAGATE: case EXABYTE_ENABLE_NEST: return &task_no_data_intr; -#ifdef CONFIG_BLK_DEV_IDEDMA case WIN_READDMA: // case WIN_READDMA_ONCE: case WIN_IDENTIFY_DMA: @@ -1080,7 +1079,6 @@ case WIN_WRITEDMA_QUEUED: case WIN_WRITEDMA_EXT: case WIN_WRITEDMA_QUEUED_EXT: -#endif case WIN_FORMAT: case WIN_INIT: case WIN_DEVICE_RESET: @@ -1164,7 +1162,6 @@ default: return IDE_DRIVE_TASK_NO_DATA; } -#ifdef CONFIG_BLK_DEV_IDEDMA case WIN_READDMA: // case WIN_READDMA_ONCE: case WIN_IDENTIFY_DMA: @@ -1178,7 +1175,6 @@ case WIN_WRITEDMA_EXT: case WIN_WRITEDMA_QUEUED_EXT: return IDE_DRIVE_TASK_RAW_WRITE; -#endif case WIN_SETFEATURES: switch(args->tfRegister[IDE_FEATURE_OFFSET]) { case SETFEATURES_EN_8BIT: @@ -1669,8 +1665,7 @@ if (!err && xfer_rate) { /* active-retuning-calls future */ - if ((HWIF(drive)->speedproc) != NULL) - HWIF(drive)->speedproc(drive, xfer_rate); + ide_set_xfer_rate(drive, xfer_rate); ide_driveid_update(drive); } abort: @@ -1724,8 +1719,7 @@ if (!err && xfer_rate) { /* active-retuning-calls future */ - if ((HWIF(drive)->speedproc) != NULL) - HWIF(drive)->speedproc(drive, xfer_rate); + ide_set_xfer_rate(driver, xfer_rate); ide_driveid_update(drive); } abort: diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/ide/ide-tcq.c linux.2.5.47-ac4/drivers/ide/ide-tcq.c --- linux.2.5.47/drivers/ide/ide-tcq.c 2002-10-31 14:57:17.000000000 +0000 +++ linux.2.5.47-ac4/drivers/ide/ide-tcq.c 2002-11-12 00:04:36.000000000 +0000 @@ -148,14 +148,14 @@ ide_hwif_t *hwif = HWIF(drive); unsigned long flags; - printk("ide_tcq_intr_timeout: timeout waiting for %s interrupt\n", hwgroup->rq ? "completion" : "service"); + printk(KERN_ERR "ide_tcq_intr_timeout: timeout waiting for %s interrupt\n", hwgroup->rq ? "completion" : "service"); spin_lock_irqsave(&ide_lock, flags); if (!hwgroup->busy) - printk("ide_tcq_intr_timeout: hwgroup not busy\n"); + printk(KERN_ERR "ide_tcq_intr_timeout: hwgroup not busy\n"); if (hwgroup->handler == NULL) - printk("ide_tcq_intr_timeout: missing isr!\n"); + printk(KERN_ERR "ide_tcq_intr_timeout: missing isr!\n"); hwgroup->busy = 1; spin_unlock_irqrestore(&ide_lock, flags); @@ -261,7 +261,7 @@ hwif->OUTB(WIN_QUEUED_SERVICE, IDE_COMMAND_REG); if (ide_tcq_wait_altstat(drive, &stat, BUSY_STAT)) { - printk("ide_service: BUSY clear took too long\n"); + printk(KERN_ERR "ide_service: BUSY clear took too long\n"); ide_dump_status(drive, "ide_service", stat); ide_tcq_invalidate_queue(drive); return ide_stopped; @@ -284,7 +284,7 @@ feat = hwif->INB(IDE_NSECTOR_REG); if (feat & REL) { HWGROUP(drive)->rq = NULL; - printk("%s: release in service\n", drive->name); + printk(KERN_ERR "%s: release in service\n", drive->name); return ide_stopped; } @@ -307,7 +307,7 @@ return HWIF(drive)->ide_dma_queued_start(drive); } - printk("ide_service: missing request for tag %d\n", tag); + printk(KERN_ERR "ide_service: missing request for tag %d\n", tag); spin_unlock_irqrestore(&ide_lock, flags); return ide_stopped; } @@ -347,14 +347,14 @@ * must be end of I/O, check status and complete as necessary */ if (unlikely(!OK_STAT(stat, READY_STAT, drive->bad_wstat | DRQ_STAT))) { - printk("ide_dmaq_intr: %s: error status %x\n",drive->name,stat); + printk(KERN_ERR "ide_dmaq_intr: %s: error status %x\n",drive->name,stat); ide_dump_status(drive, "ide_dmaq_complete", stat); ide_tcq_invalidate_queue(drive); return ide_stopped; } if (dma_stat) - printk("%s: bad DMA status (dma_stat=%x)\n", drive->name, dma_stat); + printk(KERN_WARNING "%s: bad DMA status (dma_stat=%x)\n", drive->name, dma_stat); TCQ_PRINTK("ide_dmaq_complete: ending %p, tag %d\n", rq, rq->tag); ide_end_request(drive, 1, rq->nr_sectors); @@ -465,7 +465,7 @@ args->command_type = ide_cmd_type_parser(args); if (ide_raw_taskfile(drive, args, NULL)) { - printk("%s: failed to enable write cache\n", drive->name); + printk(KERN_WARNING "%s: failed to enable write cache\n", drive->name); goto err; } @@ -479,7 +479,7 @@ args->command_type = ide_cmd_type_parser(args); if (ide_raw_taskfile(drive, args, NULL)) { - printk("%s: disabling release interrupt fail\n", drive->name); + printk(KERN_ERR "%s: disabling release interrupt fail\n", drive->name); goto err; } @@ -493,7 +493,7 @@ args->command_type = ide_cmd_type_parser(args); if (ide_raw_taskfile(drive, args, NULL)) { - printk("%s: enabling service interrupt fail\n", drive->name); + printk(KERN_ERR "%s: enabling service interrupt fail\n", drive->name); goto err; } #endif @@ -518,7 +518,7 @@ */ if (!on) { if (drive->using_tcq) - printk("%s: TCQ disabled\n", drive->name); + printk(KERN_INFO "%s: TCQ disabled\n", drive->name); drive->using_tcq = 0; return 0; @@ -541,7 +541,7 @@ ide_tcq_check_autopoll(drive); if (depth != drive->queue_depth) - printk("%s: tagged command queueing enabled, command queue depth %d\n", drive->name, drive->queue_depth); + printk(KERN_INFO "%s: tagged command queueing enabled, command queue depth %d\n", drive->name, drive->queue_depth); drive->using_tcq = 1; return 0; @@ -588,7 +588,7 @@ return 1; if (ata_pending_commands(drive)) { - printk("ide-tcq; can't toggle tcq feature on busy drive\n"); + printk(KERN_WARNING "ide-tcq; can't toggle tcq feature on busy drive\n"); return 1; } @@ -692,10 +692,10 @@ TCQ_PRINTK("ide_dma: setting up queued tag=%d\n", rq->tag); if (!hwgroup->busy) - printk("queued_rw: hwgroup not busy\n"); + printk(KERN_ERR "queued_rw: hwgroup not busy\n"); if (ide_tcq_wait_dataphase(drive)) { - printk("timeout waiting for data phase\n"); + printk(KERN_WARNING "timeout waiting for data phase\n"); return ide_stopped; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/ide/Kconfig linux.2.5.47-ac4/drivers/ide/Kconfig --- linux.2.5.47/drivers/ide/Kconfig 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/ide/Kconfig 2002-11-12 15:14:16.000000000 +0000 @@ -524,6 +524,13 @@ ide-probe at boot. It is reported to support DVD II drives, by the manufacturer. +config BLK_DEV_SC1200 + tristate "National SCx200 chipset support" + depends on BLK_DEV_IDEDMA_PCI + help + This driver adds support for the built in IDE on the National + SCx200 series of embedded x86 "Geode" systems + config BLK_DEV_PIIX tristate "Intel PIIXn chipsets support" depends on BLK_DEV_IDEDMA_PCI diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/ide/legacy/ide-cs.c linux.2.5.47-ac4/drivers/ide/legacy/ide-cs.c --- linux.2.5.47/drivers/ide/legacy/ide-cs.c 2002-11-11 16:39:10.000000000 +0000 +++ linux.2.5.47-ac4/drivers/ide/legacy/ide-cs.c 2002-11-13 15:21:49.000000000 +0000 @@ -134,6 +134,7 @@ memset(info, 0, sizeof(*info)); link = &info->link; link->priv = info; + init_timer(&link->release); link->release.function = &ide_release; link->release.data = (u_long)link; link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; @@ -410,6 +411,8 @@ DEBUG(0, "ide_release(0x%p)\n", link); if (info->ndev) { + /* FIXME: if this fails we need to queue the cleanup somehow + -- need to investigate the required PCMCIA magic */ ide_unregister(info->hd); /* deal with brain dead IDE resource management */ request_region(link->io.BasePort1, link->io.NumPorts1, diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/ide/Makefile linux.2.5.47-ac4/drivers/ide/Makefile --- linux.2.5.47/drivers/ide/Makefile 2002-10-31 14:57:17.000000000 +0000 +++ linux.2.5.47-ac4/drivers/ide/Makefile 2002-11-13 14:58:53.000000000 +0000 @@ -7,14 +7,14 @@ # Note : at this point, these files are compiled on all systems. # In the future, some of these should be built conditionally. # -export-objs := ide-iops.o ide-taskfile.o ide-proc.o ide.o ide-probe.o ide-dma.o ide-lib.o setup-pci.o +export-objs := ide-iops.o ide-taskfile.o ide-proc.o ide.o ide-probe.o ide-dma.o ide-lib.o setup-pci.o ide-io.o # First come modules that register themselves with the core obj-$(CONFIG_BLK_DEV_IDEPCI) += pci/ # Core IDE code - must come before legacy -obj-$(CONFIG_BLK_DEV_IDE) += 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 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 -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/ide/pci/aec62xx.c linux.2.5.47-ac4/drivers/ide/pci/aec62xx.c --- linux.2.5.47/drivers/ide/pci/aec62xx.c 2002-10-31 14:57:17.000000000 +0000 +++ linux.2.5.47-ac4/drivers/ide/pci/aec62xx.c 2002-11-13 14:37:13.000000000 +0000 @@ -292,7 +292,6 @@ } } -#ifdef CONFIG_BLK_DEV_IDEDMA static int config_chipset_for_dma (ide_drive_t *drive) { u8 speed = ide_dma_speed(drive, aec62xx_ratemask(drive)); @@ -303,7 +302,6 @@ (void) aec62xx_tune_chipset(drive, speed); return ide_dma_enable(drive); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ static void aec62xx_tune_drive (ide_drive_t *drive, u8 pio) { @@ -321,7 +319,6 @@ (void) aec62xx_tune_chipset(drive, speed); } -#ifdef CONFIG_BLK_DEV_IDEDMA static int aec62xx_config_drive_xfer_rate (ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); @@ -405,7 +402,6 @@ #endif return 0; } -#endif /* CONFIG_BLK_DEV_IDEDMA */ static unsigned int __init init_chipset_aec62xx (struct pci_dev *dev, const char *name) { @@ -457,7 +453,6 @@ hwif->mwdma_mask = 0x07; hwif->swdma_mask = 0x07; -#ifdef CONFIG_BLK_DEV_IDEDMA hwif->ide_dma_check = &aec62xx_config_drive_xfer_rate; hwif->ide_dma_lostirq = &aec62xx_irq_timeout; hwif->ide_dma_timeout = &aec62xx_irq_timeout; @@ -465,7 +460,6 @@ hwif->autodma = 1; hwif->drives[0].autodma = hwif->autodma; hwif->drives[1].autodma = hwif->autodma; -#endif /* CONFIG_BLK_DEV_IDEDMA */ } static void __init init_dma_aec62xx (ide_hwif_t *hwif, unsigned long dmabase) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/ide/pci/aec62xx.h linux.2.5.47-ac4/drivers/ide/pci/aec62xx.h --- linux.2.5.47/drivers/ide/pci/aec62xx.h 2002-10-31 14:57:17.000000000 +0000 +++ linux.2.5.47-ac4/drivers/ide/pci/aec62xx.h 2002-11-13 14:37:27.000000000 +0000 @@ -14,7 +14,6 @@ }; struct chipset_bus_clock_list_entry aec6xxx_33_base [] = { -#ifdef CONFIG_BLK_DEV_IDEDMA { XFER_UDMA_6, 0x31, 0x07 }, { XFER_UDMA_5, 0x31, 0x06 }, { XFER_UDMA_4, 0x31, 0x05 }, @@ -26,7 +25,6 @@ { XFER_MW_DMA_2, 0x31, 0x00 }, { XFER_MW_DMA_1, 0x31, 0x00 }, { XFER_MW_DMA_0, 0x0a, 0x00 }, -#endif /* CONFIG_BLK_DEV_IDEDMA */ { XFER_PIO_4, 0x31, 0x00 }, { XFER_PIO_3, 0x33, 0x00 }, { XFER_PIO_2, 0x08, 0x00 }, @@ -36,7 +34,6 @@ }; struct chipset_bus_clock_list_entry aec6xxx_34_base [] = { -#ifdef CONFIG_BLK_DEV_IDEDMA { XFER_UDMA_6, 0x41, 0x06 }, { XFER_UDMA_5, 0x41, 0x05 }, { XFER_UDMA_4, 0x41, 0x04 }, @@ -48,7 +45,6 @@ { XFER_MW_DMA_2, 0x41, 0x00 }, { XFER_MW_DMA_1, 0x42, 0x00 }, { XFER_MW_DMA_0, 0x7a, 0x00 }, -#endif /* CONFIG_BLK_DEV_IDEDMA */ { XFER_PIO_4, 0x41, 0x00 }, { XFER_PIO_3, 0x43, 0x00 }, { XFER_PIO_2, 0x78, 0x00 }, diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/ide/pci/alim15x3.c linux.2.5.47-ac4/drivers/ide/pci/alim15x3.c --- linux.2.5.47/drivers/ide/pci/alim15x3.c 2002-10-31 14:57:17.000000000 +0000 +++ linux.2.5.47-ac4/drivers/ide/pci/alim15x3.c 2002-11-15 02:25:55.000000000 +0000 @@ -450,7 +450,6 @@ if (speed < XFER_SW_DMA_0) ali15x3_tune_drive(drive, speed); -#ifdef CONFIG_BLK_DEV_IDEDMA } else { pci_read_config_byte(dev, m5229_udma, &tmpbyte); tmpbyte &= (0x0f << ((1-unit) << 2)); @@ -464,12 +463,10 @@ tmpbyte |= 1; pci_write_config_byte(dev, 0x4b, tmpbyte); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ } return (ide_config_drive_speed(drive, speed)); } -#ifdef CONFIG_BLK_DEV_IDEDMA /** * config_chipset_for_dma - set up DMA mode @@ -562,7 +559,6 @@ return 1; /* try PIO instead of DMA */ return __ide_dma_write(drive); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ /** * init_chipset_ali15x3 - Initialise an ALi IDE controller @@ -756,7 +752,6 @@ hwif->mwdma_mask = 0x07; hwif->swdma_mask = 0x07; -#ifdef CONFIG_BLK_DEV_IDEDMA if (m5229_revision >= 0x20) { /* * M1543C or newer for DMAing @@ -770,7 +765,6 @@ } hwif->drives[0].autodma = hwif->autodma; hwif->drives[1].autodma = hwif->autodma; -#endif /* CONFIG_BLK_DEV_IDEDMA */ } /** @@ -854,6 +848,12 @@ static int __devinit alim15x3_init_one(struct pci_dev *dev, const struct pci_device_id *id) { ide_pci_device_t *d = &ali15x3_chipsets[id->driver_data]; + + if(pci_find_device(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_IGP, NULL)) + { + printk(KERN_ERR "Warning: ATI Radeon IGP Northbridge is not supported by Linux\n"); + return 1; + } #if defined(CONFIG_SPARC64) d->init_hwif = init_hwif_common_ali15x3; #endif /* CONFIG_SPARC64 */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/ide/pci/amd74xx.c linux.2.5.47-ac4/drivers/ide/pci/amd74xx.c --- linux.2.5.47/drivers/ide/pci/amd74xx.c 2002-10-31 14:57:17.000000000 +0000 +++ linux.2.5.47-ac4/drivers/ide/pci/amd74xx.c 2002-11-13 14:40:09.000000000 +0000 @@ -148,7 +148,6 @@ pio_timing &= ~(0x03 << drive->dn); switch(speed) { -#ifdef CONFIG_BLK_DEV_IDEDMA case XFER_UDMA_7: case XFER_UDMA_6: speed = XFER_UDMA_5; @@ -194,7 +193,6 @@ case XFER_SW_DMA_0: dma_pio_timing |= 0xA8; break; -#endif /* CONFIG_BLK_DEV_IDEDMA */ case XFER_PIO_4: dma_pio_timing |= 0x20; break; @@ -215,9 +213,7 @@ pio_timing |= (0x03 << drive->dn); -#ifdef CONFIG_BLK_DEV_IDEDMA pci_write_config_byte(dev, drive_pci[drive->dn], ultra_timing); -#endif /* CONFIG_BLK_DEV_IDEDMA */ pci_write_config_byte(dev, drive_pci2[drive->dn], dma_pio_timing); pci_write_config_byte(dev, 0x4c, pio_timing); @@ -230,7 +226,6 @@ (void) amd74xx_tune_chipset(drive, (XFER_PIO_0 + pio)); } -#ifdef CONFIG_BLK_DEV_IDEDMA /* * This allows the configuration of ide_pci chipset registers * for cards that learn about the drive's UDMA, DMA, PIO capabilities @@ -290,14 +285,11 @@ } return hwif->ide_dma_on(drive); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ static unsigned int __init init_chipset_amd74xx (struct pci_dev *dev, const char *name) { -#ifdef CONFIG_BLK_DEV_IDEDMA if (!amd74xx_swdma_check(dev)) printk("%s: disabling single-word DMA support (revision < C4)\n", name); -#endif /* CONFIG_BLK_DEV_IDEDMA */ #if defined(DISPLAY_VIPER_TIMINGS) && defined(CONFIG_PROC_FS) if (!amd74xx_proc) { @@ -348,11 +340,7 @@ default: break; } -#ifdef CONFIG_AMD74XX_OVERRIDE - return(1); -#else return (unsigned int) ata66; -#endif /* CONFIG_AMD74XX_OVERRIDE */ } static void __init init_hwif_amd74xx (ide_hwif_t *hwif) @@ -373,7 +361,6 @@ if (amd74xx_swdma_check(hwif->pci_dev)) hwif->swdma_mask = 0x07; -#ifdef CONFIG_BLK_DEV_IDEDMA if (!(hwif->udma_four)) hwif->udma_four = ata66_amd74xx(hwif); hwif->ide_dma_check = &amd74xx_config_drive_xfer_rate; @@ -381,7 +368,6 @@ hwif->autodma = 1; hwif->drives[0].autodma = hwif->autodma; hwif->drives[1].autodma = hwif->autodma; -#endif /* CONFIG_BLK_DEV_IDEDMA */ } static void __init init_dma_amd74xx (ide_hwif_t *hwif, unsigned long dmabase) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/ide/pci/cmd640.c linux.2.5.47-ac4/drivers/ide/pci/cmd640.c --- linux.2.5.47/drivers/ide/pci/cmd640.c 2002-10-31 14:57:17.000000000 +0000 +++ linux.2.5.47-ac4/drivers/ide/pci/cmd640.c 2002-11-15 00:29:04.000000000 +0000 @@ -751,7 +751,7 @@ */ put_cmd640_reg(0x5b, 0xbd); if (get_cmd640_reg(0x5b) != 0xbd) { - printk("ide: cmd640 init failed: wrong value in reg 0x5b\n"); + printk(KERN_ERR "ide: cmd640 init failed: wrong value in reg 0x5b\n"); return 0; } put_cmd640_reg(0x5b, 0); @@ -836,7 +836,7 @@ cmd_hwif1->tuneproc = &cmd640_tune_drive; #endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ } - printk("%s: %sserialized, secondary interface %s\n", cmd_hwif1->name, + printk(KERN_INFO "%s: %sserialized, secondary interface %s\n", cmd_hwif1->name, cmd_hwif0->serialized ? "" : "not ", port2); /* diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/ide/pci/cmd64x.c linux.2.5.47-ac4/drivers/ide/pci/cmd64x.c --- linux.2.5.47/drivers/ide/pci/cmd64x.c 2002-10-31 14:57:17.000000000 +0000 +++ linux.2.5.47-ac4/drivers/ide/pci/cmd64x.c 2002-11-13 15:55:39.000000000 +0000 @@ -383,18 +383,15 @@ static int cmd64x_tune_chipset (ide_drive_t *drive, u8 xferspeed) { -#ifdef CONFIG_BLK_DEV_IDEDMA ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; u8 unit = (drive->select.b.unit & 0x01); u8 regU = 0, pciU = (hwif->channel) ? UDIDETCR1 : UDIDETCR0; u8 regD = 0, pciD = (hwif->channel) ? BMIDESR1 : BMIDESR0; -#endif /* CONFIG_BLK_DEV_IDEDMA */ u8 speed = ide_rate_filter(cmd64x_ratemask(drive), xferspeed); -#ifdef CONFIG_BLK_DEV_IDEDMA if (speed > XFER_PIO_4) { (void) pci_read_config_byte(dev, pciD, ®D); (void) pci_read_config_byte(dev, pciU, ®U); @@ -405,10 +402,8 @@ (void) pci_read_config_byte(dev, pciD, ®D); (void) pci_read_config_byte(dev, pciU, ®U); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ switch(speed) { -#ifdef CONFIG_BLK_DEV_IDEDMA case XFER_UDMA_5: regU |= (unit ? 0x0A : 0x05); break; case XFER_UDMA_4: regU |= (unit ? 0x4A : 0x15); break; case XFER_UDMA_3: regU |= (unit ? 0x8A : 0x25); break; @@ -421,7 +416,6 @@ case XFER_SW_DMA_2: regD |= (unit ? 0x40 : 0x10); break; case XFER_SW_DMA_1: regD |= (unit ? 0x80 : 0x20); break; case XFER_SW_DMA_0: regD |= (unit ? 0xC0 : 0x30); break; -#endif /* CONFIG_BLK_DEV_IDEDMA */ case XFER_PIO_4: cmd64x_tuneproc(drive, 4); break; case XFER_PIO_3: cmd64x_tuneproc(drive, 3); break; case XFER_PIO_2: cmd64x_tuneproc(drive, 2); break; @@ -432,29 +426,26 @@ return 1; } -#ifdef CONFIG_BLK_DEV_IDEDMA if (speed > XFER_PIO_4) { (void) pci_write_config_byte(dev, pciU, regU); regD |= (unit ? 0x40 : 0x20); (void) pci_write_config_byte(dev, pciD, regD); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ return (ide_config_drive_speed(drive, speed)); } -#ifdef CONFIG_BLK_DEV_IDEDMA static int config_chipset_for_dma (ide_drive_t *drive) { u8 speed = ide_dma_speed(drive, cmd64x_ratemask(drive)); - config_chipset_for_pio(drive, (!(speed))); + config_chipset_for_pio(drive, !speed); - if ((!(speed))) + if (!speed) return 0; - if (HWIF(drive)->speedproc(drive, speed)) - return 0; + if(ide_set_xfer_rate(drive, speed)) + return 0; if (!drive->init_speed) drive->init_speed = speed; @@ -593,7 +584,6 @@ /* verify good DMA status */ return (dma_stat & 7) != 4; } -#endif /* CONFIG_BLK_DEV_IDEDMA */ static unsigned int __init init_chipset_cmd64x (struct pci_dev *dev, const char *name) { @@ -732,7 +722,6 @@ if (dev->device == PCI_DEVICE_ID_CMD_648) hwif->ultra_mask = 0x1f; -#ifdef CONFIG_BLK_DEV_IDEDMA hwif->ide_dma_check = &cmd64x_config_drive_for_dma; if (!(hwif->udma_four)) hwif->udma_four = ata66_cmd64x(hwif); @@ -755,7 +744,6 @@ hwif->autodma = 1; hwif->drives[0].autodma = hwif->autodma; hwif->drives[1].autodma = hwif->autodma; -#endif /* CONFIG_BLK_DEV_IDEDMA */ } static void __init init_dma_cmd64x (ide_hwif_t *hwif, unsigned long dmabase) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/ide/pci/cs5530.c linux.2.5.47-ac4/drivers/ide/pci/cs5530.c --- linux.2.5.47/drivers/ide/pci/cs5530.c 2002-10-31 14:57:17.000000000 +0000 +++ linux.2.5.47-ac4/drivers/ide/pci/cs5530.c 2002-11-13 14:41:55.000000000 +0000 @@ -135,8 +135,6 @@ } } -#ifdef CONFIG_BLK_DEV_IDEDMA - /** * cs5530_config_dma - select/set DMA and UDMA modes * @drive: drive to tune @@ -256,7 +254,6 @@ */ return hwif->ide_dma_on(drive); /* success */ } -#endif /* CONFIG_BLK_DEV_IDEDMA */ /** * init_chipset_5530 - set up 5530 bridge @@ -396,13 +393,11 @@ hwif->ultra_mask = 0x07; hwif->mwdma_mask = 0x07; -#ifdef CONFIG_BLK_DEV_IDEDMA hwif->ide_dma_check = &cs5530_config_dma; if (!noautodma) hwif->autodma = 1; hwif->drives[0].autodma = hwif->autodma; hwif->drives[1].autodma = hwif->autodma; -#endif /* CONFIG_BLK_DEV_IDEDMA */ } /** diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/ide/pci/cy82c693.c linux.2.5.47-ac4/drivers/ide/pci/cy82c693.c --- linux.2.5.47/drivers/ide/pci/cy82c693.c 2002-10-31 14:57:17.000000000 +0000 +++ linux.2.5.47-ac4/drivers/ide/pci/cy82c693.c 2002-11-13 14:42:21.000000000 +0000 @@ -123,10 +123,10 @@ p_pclk->time_8 = (u8)clk1; } -#ifdef CONFIG_BLK_DEV_IDEDMA /* * set DMA mode a specific channel for CY82C693 */ + static void cy82c693_dma_enable (ide_drive_t *drive, int mode, int single) { u8 index = 0, data = 0; @@ -213,7 +213,6 @@ } return __ide_dma_on(drive); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ /* * tune ide drive - set PIO mode @@ -405,13 +404,11 @@ hwif->mwdma_mask = 0x04; hwif->swdma_mask = 0x04; -#ifdef CONFIG_BLK_DEV_IDEDMA hwif->ide_dma_on = &cy82c693_ide_dma_on; if (!noautodma) hwif->autodma = 1; hwif->drives[0].autodma = hwif->autodma; hwif->drives[1].autodma = hwif->autodma; -#endif /* CONFIG_BLK_DEV_IDEDMA */ } static __initdata ide_hwif_t *primary; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/ide/pci/generic.c linux.2.5.47-ac4/drivers/ide/pci/generic.c --- linux.2.5.47/drivers/ide/pci/generic.c 2002-10-31 14:57:17.000000000 +0000 +++ linux.2.5.47-ac4/drivers/ide/pci/generic.c 2002-11-13 14:47:26.000000000 +0000 @@ -50,12 +50,10 @@ hwif->mwdma_mask = 0x07; hwif->swdma_mask = 0x07; -#ifdef CONFIG_BLK_DEV_IDEDMA if (!noautodma) hwif->autodma = 1; hwif->drives[0].autodma = hwif->autodma; hwif->drives[1].autodma = hwif->autodma; -#endif /* CONFIG_BLK_DEV_IDEDMA */ } static void init_dma_generic (ide_hwif_t *hwif, unsigned long dmabase) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/ide/pci/hpt34x.c linux.2.5.47-ac4/drivers/ide/pci/hpt34x.c --- linux.2.5.47/drivers/ide/pci/hpt34x.c 2002-10-31 14:57:17.000000000 +0000 +++ linux.2.5.47-ac4/drivers/ide/pci/hpt34x.c 2002-11-13 14:48:03.000000000 +0000 @@ -159,13 +159,13 @@ (void) hpt34x_tune_chipset(drive, (XFER_PIO_0 + pio)); } -#ifdef CONFIG_BLK_DEV_IDEDMA /* * This allows the configuration of ide_pci chipset registers * for cards that learn about the drive's UDMA, DMA, PIO capabilities * after the drive is reported by the OS. Initally for designed for * HPT343 UDMA chipset by HighPoint|Triones Technologies, Inc. */ + static int config_chipset_for_dma (ide_drive_t *drive) { u8 speed = ide_dma_speed(drive, hpt34x_ratemask(drive)); @@ -224,7 +224,6 @@ #endif /* CONFIG_HPT34X_AUTODMA */ return hwif->ide_dma_on(drive); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ /* * If the BIOS does not set the IO base addaress to XX00, 343 will fail. @@ -306,13 +305,11 @@ hwif->mwdma_mask = 0x07; hwif->swdma_mask = 0x07; -#ifdef CONFIG_BLK_DEV_IDEDMA hwif->ide_dma_check = &hpt34x_config_drive_xfer_rate; if (!noautodma) hwif->autodma = (pcicmd & PCI_COMMAND_MEMORY) ? 1 : 0; hwif->drives[0].autodma = hwif->autodma; hwif->drives[1].autodma = hwif->autodma; -#endif /* CONFIG_BLK_DEV_IDEDMA */ } static void __init init_dma_hpt34x (ide_hwif_t *hwif, unsigned long dmabase) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/ide/pci/hpt366.c linux.2.5.47-ac4/drivers/ide/pci/hpt366.c --- linux.2.5.47/drivers/ide/pci/hpt366.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/ide/pci/hpt366.c 2002-11-13 14:48:56.000000000 +0000 @@ -216,7 +216,6 @@ static u8 hpt3xx_ratefilter (ide_drive_t *drive, u8 speed) { -#ifdef CONFIG_BLK_DEV_IDEDMA struct pci_dev *dev = HWIF(drive)->pci_dev; u8 mode = hpt3xx_ratemask(drive); @@ -264,9 +263,6 @@ break; } return speed; -#else - return min(speed, (u8)XFER_PIO_4); -#endif /* CONFIG_BLK_DEV_IDEDMA */ } static int check_in_drive_lists (ide_drive_t *drive, const char **list) @@ -444,7 +440,6 @@ (void) hpt3xx_tune_chipset(drive, (XFER_PIO_0 + pio)); } -#ifdef CONFIG_BLK_DEV_IDEDMA /* * This allows the configuration of ide_pci chipset registers * for cards that learn about the drive's UDMA, DMA, PIO capabilities @@ -654,7 +649,6 @@ pci_write_config_byte(dev, mscreg, msc_stat|0x30); return __ide_dma_end(drive); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ /* * Since SUN Cobalt is attempting to do this operation, I should disclose @@ -1030,7 +1024,6 @@ hwif->ultra_mask = 0x7f; hwif->mwdma_mask = 0x07; -#ifdef CONFIG_BLK_DEV_IDEDMA if (!(hwif->udma_four)) hwif->udma_four = ((ata66 & regmask) ? 0 : 1); hwif->ide_dma_check = &hpt366_config_drive_xfer_rate; @@ -1053,7 +1046,6 @@ hwif->autodma = 1; hwif->drives[0].autodma = hwif->autodma; hwif->drives[1].autodma = hwif->autodma; -#endif /* CONFIG_BLK_DEV_IDEDMA */ } static void __init init_dma_hpt366 (ide_hwif_t *hwif, unsigned long dmabase) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/ide/pci/it8172.c linux.2.5.47-ac4/drivers/ide/pci/it8172.c --- linux.2.5.47/drivers/ide/pci/it8172.c 2002-10-31 14:57:17.000000000 +0000 +++ linux.2.5.47-ac4/drivers/ide/pci/it8172.c 2002-11-13 14:49:44.000000000 +0000 @@ -151,7 +151,6 @@ */ switch(speed) { -#ifdef CONFIG_BLK_DEV_IDEDMA case XFER_UDMA_4: case XFER_UDMA_2: //u_speed = 2 << (drive->dn * 4); break; case XFER_UDMA_5: @@ -162,7 +161,6 @@ case XFER_MW_DMA_1: case XFER_MW_DMA_0: case XFER_SW_DMA_2: break; -#endif /* CONFIG_BLK_DEV_IDEDMA */ case XFER_PIO_4: case XFER_PIO_3: case XFER_PIO_2: @@ -183,7 +181,6 @@ return (ide_config_drive_speed(drive, speed)); } -#ifdef CONFIG_BLK_DEV_IDEDMA static int it8172_config_chipset_for_dma (ide_drive_t *drive) { u8 speed = ide_dma_speed(drive, it8172_ratemask(drive)); @@ -239,7 +236,6 @@ } return hwif->ide_dma_on(drive); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ static unsigned int __init init_chipset_it8172 (struct pci_dev *dev, const char *name) { @@ -282,13 +278,11 @@ hwif->mwdma_mask = 0x06; hwif->swdma_mask = 0x04; -#ifdef CONFIG_BLK_DEV_IDEDMA hwif->ide_dma_check = &it8172_config_drive_xfer_rate; if (!noautodma) hwif->autodma = 1; hwif->drives[0].autodma = hwif->autodma; hwif->drives[1].autodma = hwif->autodma; -#endif /* !CONFIG_BLK_DEV_IDEDMA */ } static void __init init_dma_it8172 (ide_hwif_t *hwif, unsigned long dmabase) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/ide/pci/Makefile linux.2.5.47-ac4/drivers/ide/pci/Makefile --- linux.2.5.47/drivers/ide/pci/Makefile 2002-10-31 14:57:17.000000000 +0000 +++ linux.2.5.47-ac4/drivers/ide/pci/Makefile 2002-11-11 21:18:42.000000000 +0000 @@ -6,6 +6,7 @@ obj-$(CONFIG_BLK_DEV_CMD640) += cmd640.o obj-$(CONFIG_BLK_DEV_CMD64X) += cmd64x.o obj-$(CONFIG_BLK_DEV_CS5530) += cs5530.o +obj-$(CONFIG_BLK_DEV_SC1200) += sc1200.o obj-$(CONFIG_BLK_DEV_CY82C693) += cy82c693.o obj-$(CONFIG_BLK_DEV_HPT34X) += hpt34x.o obj-$(CONFIG_BLK_DEV_HPT366) += hpt366.o diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/ide/pci/ns87415.c linux.2.5.47-ac4/drivers/ide/pci/ns87415.c --- linux.2.5.47/drivers/ide/pci/ns87415.c 2002-10-31 14:57:17.000000000 +0000 +++ linux.2.5.47-ac4/drivers/ide/pci/ns87415.c 2002-11-13 14:50:10.000000000 +0000 @@ -83,7 +83,6 @@ ns87415_prepare_drive (drive, drive->using_dma); } -#ifdef CONFIG_BLK_DEV_IDEDMA static int ns87415_ide_dma_end (ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); @@ -132,7 +131,6 @@ return HWIF(drive)->ide_dma_off_quietly(drive); return __ide_dma_check(drive); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ static void __init init_hwif_ns87415 (ide_hwif_t *hwif) { @@ -209,7 +207,6 @@ if (!hwif->dma_base) return; -#ifdef CONFIG_BLK_DEV_IDEDMA hwif->OUTB(0x60, hwif->dma_status); hwif->ide_dma_read = &ns87415_ide_dma_read; hwif->ide_dma_write = &ns87415_ide_dma_write; @@ -220,7 +217,6 @@ hwif->autodma = 1; hwif->drives[0].autodma = hwif->autodma; hwif->drives[1].autodma = hwif->autodma; -#endif /* CONFIG_BLK_DEV_IDEDMA */ } static void __init init_dma_ns87415 (ide_hwif_t *hwif, unsigned long dmabase) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/ide/pci/nvidia.c linux.2.5.47-ac4/drivers/ide/pci/nvidia.c --- linux.2.5.47/drivers/ide/pci/nvidia.c 2002-10-31 14:57:17.000000000 +0000 +++ linux.2.5.47-ac4/drivers/ide/pci/nvidia.c 2002-11-13 14:51:04.000000000 +0000 @@ -109,7 +109,6 @@ pio_timing &= ~(0x03 << drive->dn); switch(speed) { -#ifdef CONFIG_BLK_DEV_IDEDMA case XFER_UDMA_7: case XFER_UDMA_6: speed = XFER_UDMA_5; @@ -155,7 +154,6 @@ case XFER_SW_DMA_0: dma_pio_timing |= 0xA8; break; -#endif /* CONFIG_BLK_DEV_IDEDMA */ case XFER_PIO_4: dma_pio_timing |= 0x20; break; @@ -176,9 +174,7 @@ pio_timing |= (0x03 << drive->dn); -#ifdef CONFIG_BLK_DEV_IDEDMA pci_write_config_byte(dev, drive_pci[drive->dn], ultra_timing); -#endif /* CONFIG_BLK_DEV_IDEDMA */ pci_write_config_byte(dev, drive_pci2[drive->dn], dma_pio_timing); pci_write_config_byte(dev, 0x5c, pio_timing); @@ -191,7 +187,6 @@ (void) nforce_tune_chipset(drive, (XFER_PIO_0 + pio)); } -#ifdef CONFIG_BLK_DEV_IDEDMA /* * This allows the configuration of ide_pci chipset registers * for cards that learn about the drive's UDMA, DMA, PIO capabilities @@ -251,9 +246,8 @@ } return hwif->ide_dma_on(drive); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ -unsigned int __init init_chipset_nforce (struct pci_dev *dev, const char *name) +static unsigned int __init init_chipset_nforce (struct pci_dev *dev, const char *name) { #if defined(DISPLAY_NFORCE_TIMINGS) && defined(CONFIG_PROC_FS) if (!nforce_proc) { @@ -318,7 +312,6 @@ hwif->mwdma_mask = 0x07; hwif->swdma_mask = 0x07; -#ifdef CONFIG_BLK_DEV_IDEDMA if (!(hwif->udma_four)) hwif->udma_four = ata66_nforce(hwif); hwif->ide_dma_check = &nforce_config_drive_xfer_rate; @@ -326,7 +319,6 @@ hwif->autodma = 1; hwif->drives[0].autodma = hwif->autodma; hwif->drives[1].autodma = hwif->autodma; -#endif /* CONFIG_BLK_DEV_IDEDMA */ } /* FIXME - not needed */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/ide/pci/opti621.c linux.2.5.47-ac4/drivers/ide/pci/opti621.c --- linux.2.5.47/drivers/ide/pci/opti621.c 2002-10-31 14:57:17.000000000 +0000 +++ linux.2.5.47-ac4/drivers/ide/pci/opti621.c 2002-11-13 14:51:16.000000000 +0000 @@ -343,13 +343,10 @@ hwif->mwdma_mask = 0x07; hwif->swdma_mask = 0x07; -#ifdef CONFIG_BLK_DEV_IDEDMA if (!noautodma) hwif->autodma = 1; hwif->drives[0].autodma = hwif->autodma; hwif->drives[1].autodma = hwif->autodma; -#endif /* CONFIG_BLK_DEV_IDEDMA */ - } static void __init init_dma_opti621 (ide_hwif_t *hwif, unsigned long dmabase) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/ide/pci/pdc202xx_new.c linux.2.5.47-ac4/drivers/ide/pci/pdc202xx_new.c --- linux.2.5.47/drivers/ide/pci/pdc202xx_new.c 2002-10-31 14:57:17.000000000 +0000 +++ linux.2.5.47-ac4/drivers/ide/pci/pdc202xx_new.c 2002-11-13 14:52:59.000000000 +0000 @@ -165,7 +165,6 @@ pci_read_config_byte(dev, (drive_pci), &AP); pci_read_config_byte(dev, (drive_pci)|0x01, &BP); } -#ifdef CONFIG_BLK_DEV_IDEDMA } else { if ((BP & 0xF0) && (CP & 0x0F)) { /* clear DMA modes of upper 842 bits of B Register */ @@ -177,7 +176,6 @@ pci_write_config_byte(dev, (drive_pci)|0x02, CP &~0x0F); pci_read_config_byte(dev, (drive_pci)|0x02, &CP); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ } pci_read_config_byte(dev, (drive_pci), &AP); @@ -185,7 +183,6 @@ pci_read_config_byte(dev, (drive_pci)|0x02, &CP); switch(speed) { -#ifdef CONFIG_BLK_DEV_IDEDMA case XFER_UDMA_6: speed = XFER_UDMA_5; case XFER_UDMA_5: case XFER_UDMA_4: TB = 0x20; TC = 0x01; break; @@ -199,7 +196,6 @@ case XFER_SW_DMA_2: TB = 0x60; TC = 0x05; break; case XFER_SW_DMA_1: TB = 0x80; TC = 0x06; break; case XFER_SW_DMA_0: TB = 0xC0; TC = 0x0B; break; -#endif /* CONFIG_BLK_DEV_IDEDMA */ case XFER_PIO_4: TA = 0x01; TB = 0x04; break; case XFER_PIO_3: TA = 0x02; TB = 0x06; break; case XFER_PIO_2: TA = 0x03; TB = 0x08; break; @@ -211,11 +207,9 @@ if (speed < XFER_SW_DMA_0) { pci_write_config_byte(dev, (drive_pci), AP|TA); pci_write_config_byte(dev, (drive_pci)|0x01, BP|TB); -#ifdef CONFIG_BLK_DEV_IDEDMA } else { pci_write_config_byte(dev, (drive_pci)|0x01, BP|TB); pci_write_config_byte(dev, (drive_pci)|0x02, CP|TC); -#endif /* CONFIG_BLK_DEV_IDEDMA */ } #if PDC202XX_DECODE_REGISTER_INFO @@ -243,28 +237,18 @@ static int pdcnew_new_tune_chipset (ide_drive_t *drive, u8 xferspeed) { ide_hwif_t *hwif = HWIF(drive); -#ifdef CONFIG_BLK_DEV_IDEDMA u32 indexreg = hwif->dma_vendor1; u32 datareg = hwif->dma_vendor3; -#else /* !CONFIG_BLK_DEV_IDEDMA */ - struct pci_dev *dev = hwif->pci_dev; - u32 high_16 = pci_resource_start(dev, 4); - u32 indexreg = high_16 + (hwif->channel ? 0x09 : 0x01); - u32 datareg = (indexreg + 2); -#endif /* CONFIG_BLK_DEV_IDEDMA */ u8 thold = 0x10; u8 adj = (drive->dn%2) ? 0x08 : 0x00; u8 speed = ide_rate_filter(pdcnew_ratemask(drive), xferspeed); -#ifdef CONFIG_BLK_DEV_IDEDMA if (speed == XFER_UDMA_2) { hwif->OUTB((thold + adj), indexreg); hwif->OUTB((hwif->INB(datareg) & 0x7f), datareg); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ switch (speed) { -#ifdef CONFIG_BLK_DEV_IDEDMA case XFER_UDMA_7: speed = XFER_UDMA_6; case XFER_UDMA_6: set_ultra(0x1a, 0x01, 0xcb); break; @@ -277,7 +261,6 @@ case XFER_MW_DMA_2: set_ata2(0x69, 0x25); break; case XFER_MW_DMA_1: set_ata2(0x6b, 0x27); break; case XFER_MW_DMA_0: set_ata2(0xdf, 0x5f); break; -#endif /* CONFIG_BLK_DEV_IDEDMA */ case XFER_PIO_4: set_pio(0x23, 0x09, 0x25); break; case XFER_PIO_3: set_pio(0x27, 0x0d, 0x35); break; case XFER_PIO_2: set_pio(0x23, 0x26, 0x64); break; @@ -312,8 +295,6 @@ (void) config_chipset_for_pio(drive, pio); } -#ifdef CONFIG_BLK_DEV_IDEDMA - static u8 pdcnew_new_cable_detect (ide_hwif_t *hwif) { hwif->OUTB(0x0b, hwif->dma_vendor1); @@ -458,8 +439,6 @@ return __ide_dma_timeout(drive); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ - static void pdcnew_new_reset (ide_drive_t *drive) { /* @@ -471,12 +450,8 @@ static void pdcnew_reset_host (ide_hwif_t *hwif) { -#ifdef CONFIG_BLK_DEV_IDEDMA // unsigned long high_16 = hwif->dma_base - (8*(hwif->channel)); unsigned long high_16 = hwif->dma_master; -#else /* !CONFIG_BLK_DEV_IDEDMA */ - unsigned long high_16 = pci_resource_start(hwif->pci_dev, 4); -#endif /* CONFIG_BLK_DEV_IDEDMA */ u8 udma_speed_flag = hwif->INB(high_16|0x001f); hwif->OUTB((udma_speed_flag | 0x10), (high_16|0x001f)); @@ -571,8 +546,6 @@ hwif->ultra_mask = 0x7f; hwif->mwdma_mask = 0x07; -#ifdef CONFIG_BLK_DEV_IDEDMA - hwif->ide_dma_check = &pdcnew_config_drive_xfer_rate; hwif->ide_dma_lostirq = &pdcnew_ide_dma_lostirq; hwif->ide_dma_timeout = &pdcnew_ide_dma_timeout; @@ -581,7 +554,6 @@ if (!noautodma) hwif->autodma = 1; hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma; -#endif /* CONFIG_BLK_DEV_IDEDMA */ #if PDC202_DEBUG_CABLE printk("%s: %s-pin cable\n", hwif->name, hwif->udma_four ? "80" : "40"); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/ide/pci/pdc202xx_old.c linux.2.5.47-ac4/drivers/ide/pci/pdc202xx_old.c --- linux.2.5.47/drivers/ide/pci/pdc202xx_old.c 2002-10-31 14:57:17.000000000 +0000 +++ linux.2.5.47-ac4/drivers/ide/pci/pdc202xx_old.c 2002-11-13 14:54:01.000000000 +0000 @@ -264,7 +264,6 @@ pci_read_config_byte(dev, (drive_pci), &AP); pci_read_config_byte(dev, (drive_pci)|0x01, &BP); } -#ifdef CONFIG_BLK_DEV_IDEDMA } else { if ((BP & 0xF0) && (CP & 0x0F)) { /* clear DMA modes of upper 842 bits of B Register */ @@ -276,7 +275,6 @@ pci_write_config_byte(dev, (drive_pci)|0x02, CP &~0x0F); pci_read_config_byte(dev, (drive_pci)|0x02, &CP); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ } pci_read_config_byte(dev, (drive_pci), &AP); @@ -284,7 +282,6 @@ pci_read_config_byte(dev, (drive_pci)|0x02, &CP); switch(speed) { -#ifdef CONFIG_BLK_DEV_IDEDMA case XFER_UDMA_6: speed = XFER_UDMA_5; case XFER_UDMA_5: case XFER_UDMA_4: TB = 0x20; TC = 0x01; break; @@ -298,7 +295,6 @@ case XFER_SW_DMA_2: TB = 0x60; TC = 0x05; break; case XFER_SW_DMA_1: TB = 0x80; TC = 0x06; break; case XFER_SW_DMA_0: TB = 0xC0; TC = 0x0B; break; -#endif /* CONFIG_BLK_DEV_IDEDMA */ case XFER_PIO_4: TA = 0x01; TB = 0x04; break; case XFER_PIO_3: TA = 0x02; TB = 0x06; break; case XFER_PIO_2: TA = 0x03; TB = 0x08; break; @@ -310,11 +306,9 @@ if (speed < XFER_SW_DMA_0) { pci_write_config_byte(dev, (drive_pci), AP|TA); pci_write_config_byte(dev, (drive_pci)|0x01, BP|TB); -#ifdef CONFIG_BLK_DEV_IDEDMA } else { pci_write_config_byte(dev, (drive_pci)|0x01, BP|TB); pci_write_config_byte(dev, (drive_pci)|0x02, CP|TC); -#endif /* CONFIG_BLK_DEV_IDEDMA */ } #if PDC202XX_DECODE_REGISTER_INFO @@ -362,8 +356,6 @@ (void) config_chipset_for_pio(drive, pio); } -#ifdef CONFIG_BLK_DEV_IDEDMA - static u8 pdc202xx_old_cable_detect (ide_hwif_t *hwif) { u16 CIS = 0, mask = (hwif->channel) ? (1<<11) : (1<<10); @@ -618,8 +610,6 @@ return __ide_dma_timeout(drive); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ - static void pdc202xx_reset_host (ide_hwif_t *hwif) { #ifdef CONFIG_BLK_DEV_IDEDMA @@ -692,12 +682,8 @@ static int pdc202xx_tristate (ide_drive_t * drive, int state) { ide_hwif_t *hwif = HWIF(drive); -#ifdef CONFIG_BLK_DEV_IDEDMA // unsigned long high_16 = hwif->dma_base - (8*(hwif->channel)); unsigned long high_16 = hwif->dma_master; -#else /* !CONFIG_BLK_DEV_IDEDMA */ - unsigned long high_16 = pci_resource_start(hwif->pci_dev, 4); -#endif /* CONFIG_BLK_DEV_IDEDMA */ u8 sc1f = hwif->INB(high_16|0x001f); if (!hwif) @@ -783,8 +769,6 @@ hwif->mwdma_mask = 0x07; hwif->swdma_mask = 0x07; -#ifdef CONFIG_BLK_DEV_IDEDMA - hwif->ide_dma_check = &pdc202xx_config_drive_xfer_rate; hwif->ide_dma_lostirq = &pdc202xx_ide_dma_lostirq; hwif->ide_dma_timeout = &pdc202xx_ide_dma_timeout; @@ -800,7 +784,6 @@ if (!noautodma) hwif->autodma = 1; hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma; -#endif /* CONFIG_BLK_DEV_IDEDMA */ #if PDC202_DEBUG_CABLE printk("%s: %s-pin cable\n", hwif->name, hwif->udma_four ? "80" : "40"); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/ide/pci/pdcadma.c linux.2.5.47-ac4/drivers/ide/pci/pdcadma.c --- linux.2.5.47/drivers/ide/pci/pdcadma.c 2002-10-31 14:57:17.000000000 +0000 +++ linux.2.5.47-ac4/drivers/ide/pci/pdcadma.c 2002-11-13 14:54:20.000000000 +0000 @@ -55,7 +55,6 @@ } #endif /* defined(DISPLAY_PDCADMA_TIMINGS) && defined(CONFIG_PROC_FS) */ -#ifdef CONFIG_BLK_DEV_IDEDMA /* * pdcadma_dma functions() initiates/aborts (U)DMA read/write * operations on a drive. @@ -82,8 +81,6 @@ #endif -#endif /* CONFIG_BLK_DEV_IDEDMA */ - static unsigned int __init init_chipset_pdcadma (struct pci_dev *dev, const char *name) { #if defined(DISPLAY_PDCADMA_TIMINGS) && defined(CONFIG_PROC_FS) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/ide/pci/piix.c linux.2.5.47-ac4/drivers/ide/pci/piix.c --- linux.2.5.47/drivers/ide/pci/piix.c 2002-10-31 14:57:17.000000000 +0000 +++ linux.2.5.47-ac4/drivers/ide/pci/piix.c 2002-11-13 14:36:38.000000000 +0000 @@ -373,7 +373,7 @@ ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; u8 maslave = hwif->channel ? 0x42 : 0x40; - u8 speed = ide_rate_filter(piix_ratemask(drive), xferspeed); + u8 speed = ide_rate_filter(piix_ratemask(drive), xferspeed); int a_speed = 3 << (drive->dn * 4); int u_flag = 1 << drive->dn; int v_flag = 0x01 << drive->dn; @@ -392,7 +392,6 @@ pci_read_config_byte(dev, 0x55, ®55); switch(speed) { -#ifdef CONFIG_BLK_DEV_IDEDMA case XFER_UDMA_4: case XFER_UDMA_2: u_speed = 2 << (drive->dn * 4); break; case XFER_UDMA_5: @@ -402,7 +401,6 @@ case XFER_MW_DMA_2: case XFER_MW_DMA_1: case XFER_SW_DMA_2: break; -#endif /* CONFIG_BLK_DEV_IDEDMA */ case XFER_PIO_4: case XFER_PIO_3: case XFER_PIO_2: @@ -444,8 +442,6 @@ return (ide_config_drive_speed(drive, speed)); } -#ifdef CONFIG_BLK_DEV_IDEDMA - /** * piix_config_drive_for_dma - configure drive for DMA * @drive: IDE drive to configure @@ -518,7 +514,6 @@ } return hwif->ide_dma_on(drive); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ /** * init_chipset_piix - set up the PIIX chipset @@ -570,10 +565,8 @@ static void __init init_hwif_piix (ide_hwif_t *hwif) { -#ifdef CONFIG_BLK_DEV_IDEDMA u8 reg54h = 0, reg55h = 0, ata66 = 0; u8 mask = hwif->channel ? 0xc0 : 0x30; -#endif /* !CONFIG_BLK_DEV_IDEDMA */ #ifndef CONFIG_IA64 if (!hwif->irq) @@ -599,7 +592,6 @@ hwif->mwdma_mask = 0x06; hwif->swdma_mask = 0x04; -#ifdef CONFIG_BLK_DEV_IDEDMA switch(hwif->pci_dev->device) { case PCI_DEVICE_ID_INTEL_82371MX: hwif->mwdma_mask = 0x80; @@ -630,7 +622,6 @@ hwif->drives[1].autodma = hwif->autodma; hwif->drives[0].autodma = hwif->autodma; -#endif /* !CONFIG_BLK_DEV_IDEDMA */ } /** diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/ide/pci/sc1200.c linux.2.5.47-ac4/drivers/ide/pci/sc1200.c --- linux.2.5.47/drivers/ide/pci/sc1200.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.47-ac4/drivers/ide/pci/sc1200.c 2002-11-13 22:49:14.000000000 +0000 @@ -0,0 +1,593 @@ +/* + * linux/drivers/ide/sc1200.c Version 0.9 24-Oct-2002 + * + * Copyright (C) 2000-2002 Mark Lord + * May be copied or modified under the terms of the GNU General Public License + * + * Development of this chipset driver was funded + * by the nice folks at National Semiconductor. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ide_modes.h" +#include "sc1200.h" + +#define DISPLAY_SC1200_TIMINGS + +#if defined(DISPLAY_SC1200_TIMINGS) && defined(CONFIG_PROC_FS) +#include +#include + +static int sc1200_get_info(char *, char **, off_t, int); +extern int (*sc1200_display_info)(char *, char **, off_t, int); /* ide-proc.c */ +extern char *ide_media_verbose(ide_drive_t *); +static u8 sc1200_proc = 0; + +#define SC1200_REV_A 0x00 +#define SC1200_REV_B1 0x01 +#define SC1200_REV_B3 0x02 +#define SC1200_REV_C1 0x03 +#define SC1200_REV_D1 0x04 + +#define PCI_CLK_33 0x00 +#define PCI_CLK_48 0x01 +#define PCI_CLK_66 0x02 +#define PCI_CLK_33A 0x03 + +static unsigned short sc1200_get_pci_clock (void) +{ + unsigned char chip_id, silicon_revision; + unsigned int pci_clock; + /* + * Check the silicon revision, as not all versions of the chip + * have the register with the fast PCI bus timings. + */ + chip_id = inb (0x903c); + silicon_revision = inb (0x903d); + + // Read the fast pci clock frequency + if (chip_id == 0x04 && silicon_revision < SC1200_REV_B1) { + pci_clock = PCI_CLK_33; + } else { + // check clock generator configuration (cfcc) + // the clock is in bits 8 and 9 of this word + + pci_clock = inw (0x901e); + pci_clock >>= 8; + pci_clock &= 0x03; + if (pci_clock == PCI_CLK_33A) + pci_clock = PCI_CLK_33; + } + return pci_clock; +} + +static struct pci_dev *bmide_dev; + +static int sc1200_get_info (char *buffer, char **addr, off_t offset, int count) +{ + char *p = buffer; + u32 bibma = pci_resource_start(bmide_dev, 4); + u8 c0 = 0, c1 = 0; + + /* + * at that point bibma+0x2 et bibma+0xa are byte registers + * to investigate: + */ + + c0 = inb_p((unsigned short)bibma + 0x02); + c1 = inb_p((unsigned short)bibma + 0x0a); + + p += sprintf(p, "\n National SCx200 Chipset.\n"); + p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n"); + p += sprintf(p, " %sabled %sabled\n", + (c0&0x80) ? "dis" : " en", + (c1&0x80) ? "dis" : " en"); + p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n"); + p += sprintf(p, "DMA enabled: %s %s %s %s\n", + (c0&0x20) ? "yes" : "no ", (c0&0x40) ? "yes" : "no ", + (c1&0x20) ? "yes" : "no ", (c1&0x40) ? "yes" : "no " ); + + p += sprintf(p, "UDMA\n"); + p += sprintf(p, "DMA\n"); + p += sprintf(p, "PIO\n"); + + return p-buffer; +} +#endif /* DISPLAY_SC1200_TIMINGS && CONFIG_PROC_FS */ + +extern char *ide_xfer_verbose (byte xfer_rate); + +/* + * Set a new transfer mode at the drive + */ +int sc1200_set_xfer_mode (ide_drive_t *drive, byte mode) +{ + printk("%s: sc1200_set_xfer_mode(%s)\n", drive->name, ide_xfer_verbose(mode)); + return ide_config_drive_speed(drive, mode); +} + +/* + * Here are the standard PIO mode 0-4 timings for each "format". + * Format-0 uses fast data reg timings, with slower command reg timings. + * Format-1 uses fast timings for all registers, but won't work with all drives. + */ +static const unsigned int sc1200_pio_timings[4][5] = + {{0x00009172, 0x00012171, 0x00020080, 0x00032010, 0x00040010}, // format0 33Mhz + {0xd1329172, 0x71212171, 0x30200080, 0x20102010, 0x00100010}, // format1, 33Mhz + {0xfaa3f4f3, 0xc23232b2, 0x513101c1, 0x31213121, 0x10211021}, // format1, 48Mhz + {0xfff4fff4, 0xf35353d3, 0x814102f1, 0x42314231, 0x11311131}}; // format1, 66Mhz + +/* + * After chip reset, the PIO timings are set to 0x00009172, which is not valid. + */ +//#define SC1200_BAD_PIO(timings) (((timings)&~0x80000000)==0x00009172) + +static int sc1200_autoselect_dma_mode (ide_drive_t *drive) +{ + int udma_ok = 1, mode = 0; + ide_hwif_t *hwif = HWIF(drive); + int unit = drive->select.b.unit; + ide_drive_t *mate = &hwif->drives[unit^1]; + struct hd_driveid *id = drive->id; + + /* + * The SC1200 specifies that two drives sharing a cable cannot + * mix UDMA/MDMA. It has to be one or the other, for the pair, + * though different timings can still be chosen for each drive. + * We could set the appropriate timing bits on the fly, + * but that might be a bit confusing. So, for now we statically + * handle this requirement by looking at our mate drive to see + * what it is capable of, before choosing a mode for our own drive. + */ + if (mate->present) { + struct hd_driveid *mateid = mate->id; + if (mateid && (mateid->capability & 1) && !hwif->ide_dma_bad_drive(mate)) { + if ((mateid->field_valid & 4) && (mateid->dma_ultra & 7)) + udma_ok = 1; + else if ((mateid->field_valid & 2) && (mateid->dma_mword & 7)) + udma_ok = 0; + else + udma_ok = 1; + } + } + /* + * Now see what the current drive is capable of, + * selecting UDMA only if the mate said it was ok. + */ + if (id && (id->capability & 1) && hwif->autodma && !hwif->ide_dma_bad_drive(drive)) { + if (udma_ok && (id->field_valid & 4) && (id->dma_ultra & 7)) { + if (id->dma_ultra & 4) + mode = XFER_UDMA_2; + else if (id->dma_ultra & 2) + mode = XFER_UDMA_1; + else if (id->dma_ultra & 1) + mode = XFER_UDMA_0; + } + if (!mode && (id->field_valid & 2) && (id->dma_mword & 7)) { + if (id->dma_mword & 4) + mode = XFER_MW_DMA_2; + else if (id->dma_mword & 2) + mode = XFER_MW_DMA_1; + else if (id->dma_mword & 1) + mode = XFER_MW_DMA_0; + } + } + return mode; +} + +/* + * sc1200_config_dma2() handles selection/setting of DMA/UDMA modes + * for both the chipset and drive. + */ +static int sc1200_config_dma2 (ide_drive_t *drive, int mode) +{ + ide_hwif_t *hwif = HWIF(drive); + int unit = drive->select.b.unit; + unsigned int reg, timings; + unsigned short pci_clock; + unsigned int basereg = hwif->channel ? 0x50 : 0x40; + + /* + * Default to DMA-off in case we run into trouble here. + */ + hwif->ide_dma_off_quietly(drive); /* turn off DMA while we fiddle */ + outb(inb(hwif->dma_base+2)&~(unit?0x40:0x20), hwif->dma_base+2); /* clear DMA_capable bit */ + + /* + * Tell the drive to switch to the new mode; abort on failure. + */ + if (!mode || sc1200_set_xfer_mode(drive, mode)) { + printk("SC1200: set xfer mode failure\n"); + return 1; /* failure */ + } + + pci_clock = sc1200_get_pci_clock(); + + /* + * Now tune the chipset to match the drive: + * + * Note that each DMA mode has several timings associated with it. + * The correct timing depends on the fast PCI clock freq. + */ + timings = 0; + switch (mode) { + case XFER_UDMA_0: + switch (pci_clock) { + case PCI_CLK_33: timings = 0x00921250; break; + case PCI_CLK_48: timings = 0x00932470; break; + case PCI_CLK_66: timings = 0x009436a1; break; + } + break; + case XFER_UDMA_1: + switch (pci_clock) { + case PCI_CLK_33: timings = 0x00911140; break; + case PCI_CLK_48: timings = 0x00922260; break; + case PCI_CLK_66: timings = 0x00933481; break; + } + break; + case XFER_UDMA_2: + switch (pci_clock) { + case PCI_CLK_33: timings = 0x00911030; break; + case PCI_CLK_48: timings = 0x00922140; break; + case PCI_CLK_66: timings = 0x00923261; break; + } + break; + case XFER_MW_DMA_0: + switch (pci_clock) { + case PCI_CLK_33: timings = 0x00077771; break; + case PCI_CLK_48: timings = 0x000bbbb2; break; + case PCI_CLK_66: timings = 0x000ffff3; break; + } + break; + case XFER_MW_DMA_1: + switch (pci_clock) { + case PCI_CLK_33: timings = 0x00012121; break; + case PCI_CLK_48: timings = 0x00024241; break; + case PCI_CLK_66: timings = 0x00035352; break; + } + break; + case XFER_MW_DMA_2: + switch (pci_clock) { + case PCI_CLK_33: timings = 0x00002020; break; + case PCI_CLK_48: timings = 0x00013131; break; + case PCI_CLK_66: timings = 0x00015151; break; + } + break; + } + + if (timings == 0) { + printk("%s: sc1200_config_dma: huh? mode=%02x clk=%x \n", drive->name, mode, pci_clock); + return 1; /* failure */ + } + + if (unit == 0) { /* are we configuring drive0? */ + pci_read_config_dword(hwif->pci_dev, basereg+4, ®); + timings |= reg & 0x80000000; /* preserve PIO format bit */ + pci_write_config_dword(hwif->pci_dev, basereg+4, timings); + } else { + pci_write_config_dword(hwif->pci_dev, basereg+12, timings); + } + + outb(inb(hwif->dma_base+2)|(unit?0x40:0x20), hwif->dma_base+2); /* set DMA_capable bit */ + + /* + * Finally, turn DMA on in software, and exit. + */ + return hwif->ide_dma_on(drive); /* success */ +} + +/* + * sc1200_config_dma() handles selection/setting of DMA/UDMA modes + * for both the chipset and drive. + */ +static int sc1200_config_dma (ide_drive_t *drive) +{ + return sc1200_config_dma2(drive, sc1200_autoselect_dma_mode(drive)); +} + + +/* Replacement for the standard ide_dma_end action in + * dma_proc. + * + * returns 1 on error, 0 otherwise + */ +int sc1200_ide_dma_end (ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + unsigned long dma_base = hwif->dma_base; + byte dma_stat; + + dma_stat = inb(dma_base+2); /* get DMA status */ + + if (!(dma_stat & 4)) + printk(" ide_dma_end dma_stat=%0x err=%x newerr=%x\n", + dma_stat, ((dma_stat&7)!=4), ((dma_stat&2)==2)); + + outb(dma_stat|0x1b, dma_base+2); /* clear the INTR & ERROR bits */ + outb(inb(dma_base)&~1, dma_base); /* !! DO THIS HERE !! stop DMA */ + + drive->waiting_for_dma = 0; + ide_destroy_dmatable(drive); /* purge DMA mappings */ + + return (dma_stat & 7) != 4; /* verify good DMA status */ +} + +/* + * sc1200_tuneproc() handles selection/setting of PIO modes + * for both the chipset and drive. + * + * All existing BIOSs for this chipset guarantee that all drives + * will have valid default PIO timings set up before we get here. + */ +static void sc1200_tuneproc (ide_drive_t *drive, byte pio) /* mode=255 means "autotune" */ +{ + ide_hwif_t *hwif = HWIF(drive); + unsigned int format; + static byte modes[5] = {XFER_PIO_0, XFER_PIO_1, XFER_PIO_2, XFER_PIO_3, XFER_PIO_4}; + int mode = -1; + + switch (pio) { + case 200: mode = XFER_UDMA_0; break; + case 201: mode = XFER_UDMA_1; break; + case 202: mode = XFER_UDMA_2; break; + case 100: mode = XFER_MW_DMA_0; break; + case 101: mode = XFER_MW_DMA_1; break; + case 102: mode = XFER_MW_DMA_2; break; + } + if (mode != -1) { + printk("SC1200: %s: changing (U)DMA mode\n", drive->name); + (void)sc1200_config_dma2(drive, mode); + return; + } + + pio = ide_get_best_pio_mode(drive, pio, 4, NULL); + printk("SC1200: %s: setting PIO mode%d\n", drive->name, pio); + if (!sc1200_set_xfer_mode(drive, modes[pio])) { + unsigned int basereg = hwif->channel ? 0x50 : 0x40; + pci_read_config_dword (hwif->pci_dev, basereg+4, &format); + format = (format >> 31) & 1; + if (format) + format += sc1200_get_pci_clock(); + pci_write_config_dword(hwif->pci_dev, basereg + (drive->select.b.unit << 3), sc1200_pio_timings[format][pio]); + } +} + +static ide_hwif_t *lookup_pci_dev (ide_hwif_t *prev, struct pci_dev *dev) +{ + int h; + + for (h = 0; h < MAX_HWIFS; h++) { + ide_hwif_t *hwif = &ide_hwifs[h]; + if (prev) { + if (hwif == prev) + prev = NULL; // found previous, now look for next match + } else { + if (hwif && hwif->pci_dev == dev) + return hwif; // found next match + } + } + return NULL; // not found +} + +typedef struct sc1200_saved_state_s { + __u32 regs[4]; +} sc1200_saved_state_t; + +static int sc1200_save_state (struct pci_dev *dev, u32 state) +{ + ide_hwif_t *hwif = NULL; + +printk("SC1200: save_state(%u)\n", state); + if (state != 0) + return 0; // we only save state when going from full power to less + // + // Loop over all interfaces that are part of this PCI device: + // + while ((hwif = lookup_pci_dev(hwif, dev)) != NULL) { + sc1200_saved_state_t *ss; + unsigned int basereg, r; + // + // allocate a permanent save area, if not already allocated + // + ss = (sc1200_saved_state_t *)hwif->config_data; + if (ss == NULL) { + ss = kmalloc(sizeof(sc1200_saved_state_t), GFP_KERNEL); + if (ss == NULL) + return -ENOMEM; + (sc1200_saved_state_t *)hwif->config_data = ss; + } + ss = (sc1200_saved_state_t *)hwif->config_data; + // + // Save timing registers: this may be unnecessary if BIOS also does it + // + basereg = hwif->channel ? 0x50 : 0x40; + for (r = 0; r < 4; ++r) { + pci_read_config_dword (hwif->pci_dev, basereg + (r<<2), &ss->regs[r]); + } + } + return 0; +} + +static int sc1200_suspend (struct pci_dev *dev, u32 state) +{ + ide_hwif_t *hwif = NULL; + + printk("SC1200: suspend(%u)\n", state); + /* You don't need to iterate over disks -- sysfs should have done that for you already */ + + pci_disable_device(dev); + pci_set_power_state(dev,state); + dev->current_state = state; + return 0; +} + +static int sc1200_resume (struct pci_dev *dev) +{ + ide_hwif_t *hwif = NULL; + +printk("SC1200: resume\n"); + pci_set_power_state(dev,0); // bring chip back from sleep state + dev->current_state = 0; + pci_enable_device(dev); + // + // loop over all interfaces that are part of this pci device: + // + while ((hwif = lookup_pci_dev(hwif, dev)) != NULL) { + unsigned int basereg, r, d, format; + sc1200_saved_state_t *ss = (sc1200_saved_state_t *)hwif->config_data; +printk("%s: SC1200: resume\n", hwif->name); + + // + // Restore timing registers: this may be unnecessary if BIOS also does it + // + basereg = hwif->channel ? 0x50 : 0x40; + if (ss != NULL) { + for (r = 0; r < 4; ++r) { + pci_write_config_dword(hwif->pci_dev, basereg + (r<<2), ss->regs[r]); + } + } + // + // Re-program drive PIO modes + // + pci_read_config_dword(hwif->pci_dev, basereg+4, &format); + format = (format >> 31) & 1; + if (format) + format += sc1200_get_pci_clock(); + for (d = 0; d < 2; ++d) { + ide_drive_t *drive = &(hwif->drives[d]); + if (drive->present) { + unsigned int pio, timings; + pci_read_config_dword(hwif->pci_dev, basereg+(drive->select.b.unit << 3), &timings); + for (pio = 0; pio <= 4; ++pio) { + if (sc1200_pio_timings[format][pio] == timings) + break; + } + if (pio > 4) + pio = 255; /* autotune */ + (void)sc1200_tuneproc(drive, pio); + } + } + // + // Re-program drive DMA modes + // + for (d = 0; d < MAX_DRIVES; ++d) { + ide_drive_t *drive = &(hwif->drives[d]); + if (drive->present && !hwif->ide_dma_bad_drive(drive)) { + int was_using_dma = drive->using_dma; + hwif->ide_dma_off_quietly(drive); + sc1200_config_dma(drive); + if (!was_using_dma && drive->using_dma) { + hwif->ide_dma_off_quietly(drive); + } + } + } + } + return 0; +} + +/* + * Initialize the sc1200 bridge for reliable IDE DMA operation. + */ +static unsigned int __init init_chipset_sc1200 (struct pci_dev *dev, const char *name) +{ +#if defined(DISPLAY_SC1200_TIMINGS) && defined(CONFIG_PROC_FS) + if (!bmide_dev) { + sc1200_proc = 1; + bmide_dev = dev; + ide_pci_register_host_proc(&sc1200_procs[0]); + } +#endif /* DISPLAY_SC1200_TIMINGS && CONFIG_PROC_FS */ + return 0; +} + +/* + * This gets invoked by the IDE driver once for each channel, + * and performs channel-specific pre-initialization before drive probing. + */ +static void __init init_hwif_sc1200 (ide_hwif_t *hwif) +{ + if (hwif->mate) + hwif->serialized = hwif->mate->serialized = 1; + hwif->autodma = 0; + if (hwif->dma_base) { + hwif->ide_dma_check = &sc1200_config_dma; + hwif->ide_dma_end = &sc1200_ide_dma_end; + if (!noautodma) + hwif->autodma = 1; + hwif->tuneproc = &sc1200_tuneproc; + } + hwif->atapi_dma = 1; + hwif->ultra_mask = 0x07; + hwif->mwdma_mask = 0x07; + + hwif->drives[0].autodma = hwif->autodma; + hwif->drives[1].autodma = hwif->autodma; +} + +static void __init init_dma_sc1200 (ide_hwif_t *hwif, unsigned long dmabase) +{ + ide_setup_dma(hwif, dmabase, 8); +} + +extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); + + +static int __devinit sc1200_init_one(struct pci_dev *dev, const struct pci_device_id *id) +{ + ide_pci_device_t *d = &sc1200_chipsets[id->driver_data]; + if (dev->device != d->device) + BUG(); + ide_setup_pci_device(dev, d); + MOD_INC_USE_COUNT; + return 0; +} + +static struct pci_device_id sc1200_pci_tbl[] __devinitdata = { + { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SCx200_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { 0, }, +}; + +static struct pci_driver driver = { + .name = "SC1200 IDE", + .id_table = sc1200_pci_tbl, + .probe = sc1200_init_one, + .save_state = sc1200_save_state, + .suspend = sc1200_suspend, + .resume = sc1200_resume, +}; + +static int sc1200_ide_init(void) +{ + return ide_pci_register_driver(&driver); +} + +static void sc1200_ide_exit(void) +{ + ide_pci_unregister_driver(&driver); +} + +module_init(sc1200_ide_init); +module_exit(sc1200_ide_exit); + +MODULE_AUTHOR("Mark Lord"); +MODULE_DESCRIPTION("PCI driver module for NS SC1200 IDE"); +MODULE_LICENSE("GPL"); + +EXPORT_NO_SYMBOLS; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/ide/pci/sc1200.h linux.2.5.47-ac4/drivers/ide/pci/sc1200.h --- linux.2.5.47/drivers/ide/pci/sc1200.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.47-ac4/drivers/ide/pci/sc1200.h 2002-11-11 21:18:42.000000000 +0000 @@ -0,0 +1,54 @@ +#ifndef SC1200_H +#define SC1200_H + +#include +#include +#include + +#define DISPLAY_SC1200_TIMINGS + +#if defined(DISPLAY_SC1200_TIMINGS) && defined(CONFIG_PROC_FS) +#include +#include + +static u8 sc1200_proc; + +static int sc1200_get_info(char *, char **, off_t, int); + +static ide_pci_host_proc_t sc1200_procs[] __initdata = { + { + name: "sc1200", + set: 1, + get_info: sc1200_get_info, + parent: NULL, + }, +}; +#endif /* DISPLAY_SC1200_TIMINGS && CONFIG_PROC_FS */ + +static unsigned int init_chipset_sc1200(struct pci_dev *, const char *); +static void init_hwif_sc1200(ide_hwif_t *); +static void init_dma_sc1200(ide_hwif_t *, unsigned long); + +static ide_pci_device_t sc1200_chipsets[] __devinitdata = { + { /* 0 */ + vendor: PCI_VENDOR_ID_NS, + device: PCI_DEVICE_ID_NS_SCx200_IDE, + name: "SC1200", + init_chipset: init_chipset_sc1200, + init_iops: NULL, + init_hwif: init_hwif_sc1200, + init_dma: init_dma_sc1200, + channels: 2, + autodma: AUTODMA, + enablebits: {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, + bootable: ON_BOARD, + extra: 0, + },{ + vendor: 0, + device: 0, + channels: 0, + bootable: EOL, + } +}; + +#endif /* SC1200_H */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/ide/pci/serverworks.c linux.2.5.47-ac4/drivers/ide/pci/serverworks.c --- linux.2.5.47/drivers/ide/pci/serverworks.c 2002-10-31 14:57:17.000000000 +0000 +++ linux.2.5.47-ac4/drivers/ide/pci/serverworks.c 2002-11-13 14:56:07.000000000 +0000 @@ -251,7 +251,7 @@ ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; - u8 speed = ide_rate_filter(svwks_ratemask(drive), xferspeed); + u8 speed = ide_rate_filter(svwks_ratemask(drive), xferspeed); u8 pio = ide_get_best_pio_mode(drive, 255, 5, NULL); u8 unit = (drive->select.b.unit & 0x01); u8 csb5 = svwks_csb_check(dev); @@ -259,6 +259,13 @@ u8 dma_timing = 0, pio_timing = 0; u16 csb5_pio = 0; + /* If we are about to put a disk into UDMA mode we screwed up. + Our code assumes we never _ever_ do this on an OSB4 */ + + if(dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4 && + drive->media != ide_disk && speed >= XFER_UDMA_0) + BUG(); + pci_read_config_byte(dev, drive_pci[drive->dn], &pio_timing); pci_read_config_byte(dev, drive_pci2[drive->dn], &dma_timing); pci_read_config_byte(dev, (0x56|hwif->channel), &ultra_timing); @@ -331,7 +338,6 @@ csb5_pio |= ((speed - XFER_PIO_0) << (4*drive->dn)); break; -#ifdef CONFIG_BLK_DEV_IDEDMA case XFER_MW_DMA_2: case XFER_MW_DMA_1: case XFER_MW_DMA_0: @@ -351,7 +357,6 @@ dma_timing |= dma_modes[2]; ultra_timing |= ((udma_modes[speed - XFER_UDMA_0]) << (4*unit)); ultra_enable |= (0x01 << drive->dn); -#endif default: break; } @@ -360,11 +365,9 @@ if (csb5) pci_write_config_word(dev, 0x4A, csb5_pio); -#ifdef CONFIG_BLK_DEV_IDEDMA pci_write_config_byte(dev, drive_pci2[drive->dn], dma_timing); pci_write_config_byte(dev, (0x56|hwif->channel), ultra_timing); pci_write_config_byte(dev, 0x54, ultra_enable); -#endif /* CONFIG_BLK_DEV_IDEDMA */ return (ide_config_drive_speed(drive, speed)); } @@ -412,7 +415,6 @@ (void) svwks_tune_chipset(drive, (XFER_PIO_0 + pio)); } -#ifdef CONFIG_BLK_DEV_IDEDMA static int config_chipset_for_dma (ide_drive_t *drive) { u8 speed = ide_dma_speed(drive, svwks_ratemask(drive)); @@ -470,6 +472,12 @@ static int svwks_ide_dma_end (ide_drive_t *drive) { + /* + * We never place the OSB4 into a UDMA mode with a disk + * medium, that means the UDMA "all my data is 4 byte shifted" + * problem cannot occur. + */ +#if 0 ide_hwif_t *hwif = HWIF(drive); u8 dma_stat = hwif->INB(hwif->dma_status); @@ -483,9 +491,9 @@ while(1) cpu_relax(); } +#endif return __ide_dma_end(drive); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ static unsigned int __init init_chipset_svwks (struct pci_dev *dev, const char *name) { @@ -703,7 +711,6 @@ return; } -#ifdef CONFIG_BLK_DEV_IDEDMA hwif->ide_dma_check = &svwks_config_drive_xfer_rate; if (hwif->pci_dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) hwif->ide_dma_end = &svwks_ide_dma_end; @@ -719,7 +726,6 @@ hwif->drives[1].autotune = (!(dma_stat & 0x40)); // hwif->drives[0].autodma = hwif->autodma; // hwif->drives[1].autodma = hwif->autodma; -#endif /* !CONFIG_BLK_DEV_IDEDMA */ } /* diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/ide/pci/siimage.c linux.2.5.47-ac4/drivers/ide/pci/siimage.c --- linux.2.5.47/drivers/ide/pci/siimage.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/ide/pci/siimage.c 2002-11-13 14:57:12.000000000 +0000 @@ -205,7 +205,6 @@ siimage_tuneproc(drive, (speed - XFER_PIO_0)); mode |= ((unit) ? 0x10 : 0x01); break; -#ifdef CONFIG_BLK_DEV_IDEDMA case XFER_MW_DMA_2: case XFER_MW_DMA_1: case XFER_MW_DMA_0: @@ -226,7 +225,6 @@ mode |= ((unit) ? 0x30 : 0x03); config_siimage_chipset_for_pio(drive, 0); break; -#endif /* CONFIG_BLK_DEV_IDEDMA */ default: return 1; } @@ -246,7 +244,6 @@ return (ide_config_drive_speed(drive, speed)); } -#ifdef CONFIG_BLK_DEV_IDEDMA static int config_chipset_for_dma (ide_drive_t *drive) { u8 speed = ide_dma_speed(drive, siimage_ratemask(drive)); @@ -256,7 +253,7 @@ if ((!(speed))) return 0; - if (HWIF(drive)->speedproc(drive, speed)) + if (ide_set_xfer_rate(drive, speed)) return 0; if (!drive->init_speed) @@ -392,7 +389,6 @@ #endif return temp; } -#endif /* CONFIG_BLK_DEV_IDEDMA */ static int siimage_busproc (ide_drive_t * drive, int state) { @@ -811,7 +807,6 @@ if (hwif->pci_dev->device != PCI_DEVICE_ID_SII_3112) hwif->atapi_dma = 1; -#ifdef CONFIG_BLK_DEV_IDEDMA hwif->ide_dma_check = &siimage_config_drive_for_dma; if (!(hwif->udma_four)) hwif->udma_four = ata66_siimage(hwif); @@ -827,7 +822,6 @@ hwif->autodma = 1; hwif->drives[0].autodma = hwif->autodma; hwif->drives[1].autodma = hwif->autodma; -#endif /* CONFIG_BLK_DEV_IDEDMA */ } static void __init init_dma_siimage (ide_hwif_t *hwif, unsigned long dmabase) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/ide/pci/siimage.h linux.2.5.47-ac4/drivers/ide/pci/siimage.h --- linux.2.5.47/drivers/ide/pci/siimage.h 2002-10-31 14:57:17.000000000 +0000 +++ linux.2.5.47-ac4/drivers/ide/pci/siimage.h 2002-11-12 15:30:00.000000000 +0000 @@ -62,14 +62,14 @@ // while (count--) { *(u32 *)addr = readl(port); addr += 4; } } -inline void sii_outb (u8 addr, u32 port) +inline void sii_outb (u8 value, u32 port) { - writeb(addr, port); + writeb(value, port); } -inline void sii_outw (u16 addr, u32 port) +inline void sii_outw (u16 value, u32 port) { - writew(addr, port); + writew(value, port); } inline void sii_outsw (u32 port, void *addr, u32 count) @@ -77,9 +77,9 @@ while (count--) { writew(*(u16 *)addr, port); addr += 2; } } -inline void sii_outl (u32 addr, u32 port) +inline void sii_outl (u32 value, u32 port) { - writel(addr, port); + writel(value, port); } inline void sii_outsl (u32 port, void *addr, u32 count) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/ide/pci/sis5513.c linux.2.5.47-ac4/drivers/ide/pci/sis5513.c --- linux.2.5.47/drivers/ide/pci/sis5513.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/ide/pci/sis5513.c 2002-11-13 14:57:39.000000000 +0000 @@ -703,7 +703,6 @@ /* Config chip for mode */ switch(speed) { -#ifdef CONFIG_BLK_DEV_IDEDMA case XFER_UDMA_6: case XFER_UDMA_5: case XFER_UDMA_4: @@ -745,7 +744,6 @@ case XFER_SW_DMA_1: case XFER_SW_DMA_0: break; -#endif /* CONFIG_BLK_DEV_IDEDMA */ case XFER_PIO_4: return((int) config_chipset_for_pio(drive, 4)); case XFER_PIO_3: return((int) config_chipset_for_pio(drive, 3)); case XFER_PIO_2: return((int) config_chipset_for_pio(drive, 2)); @@ -764,7 +762,6 @@ (void) config_chipset_for_pio(drive, pio); } -#ifdef CONFIG_BLK_DEV_IDEDMA /* * ((id->hw_config & 0x4000|0x2000) && (HWIF(drive)->udma_four)) */ @@ -835,8 +832,6 @@ return sis5513_config_drive_xfer_rate(drive); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ - /* Chip detection and general config */ static unsigned int __init init_chipset_sis5513 (struct pci_dev *dev, const char *name) { @@ -999,7 +994,6 @@ hwif->mwdma_mask = 0x07; hwif->swdma_mask = 0x07; -#ifdef CONFIG_BLK_DEV_IDEDMA if (!host_dev) return; @@ -1013,7 +1007,6 @@ } hwif->drives[0].autodma = hwif->autodma; hwif->drives[1].autodma = hwif->autodma; -#endif return; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/ide/pci/trm290.c linux.2.5.47-ac4/drivers/ide/pci/trm290.c --- linux.2.5.47/drivers/ide/pci/trm290.c 2002-10-31 14:57:17.000000000 +0000 +++ linux.2.5.47-ac4/drivers/ide/pci/trm290.c 2002-11-13 14:58:02.000000000 +0000 @@ -176,7 +176,6 @@ trm290_prepare_drive(drive, drive->using_dma); } -#ifdef CONFIG_BLK_DEV_IDEDMA static int trm290_ide_dma_write (ide_drive_t *drive /*, struct request *rq */) { ide_hwif_t *hwif = HWIF(drive); @@ -297,7 +296,6 @@ status = hwif->INW(hwif->dma_status); return (status == 0x00ff); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ /* * Invoked from ide-dma.c at boot time. @@ -344,13 +342,11 @@ ide_setup_dma(hwif, (hwif->config_data + 4) ^ (hwif->channel ? 0x0080 : 0x0000), 3); -#ifdef CONFIG_BLK_DEV_IDEDMA hwif->ide_dma_write = &trm290_ide_dma_write; hwif->ide_dma_read = &trm290_ide_dma_read; hwif->ide_dma_begin = &trm290_ide_dma_begin; hwif->ide_dma_end = &trm290_ide_dma_end; hwif->ide_dma_test_irq = &trm290_ide_dma_test_irq; -#endif /* CONFIG_BLK_DEV_IDEDMA */ hwif->selectproc = &trm290_selectproc; hwif->autodma = 0; /* play it safe for now */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/ide/pci/via82cxxx.c linux.2.5.47-ac4/drivers/ide/pci/via82cxxx.c --- linux.2.5.47/drivers/ide/pci/via82cxxx.c 2002-10-31 14:57:17.000000000 +0000 +++ linux.2.5.47-ac4/drivers/ide/pci/via82cxxx.c 2002-11-13 14:58:20.000000000 +0000 @@ -383,8 +383,6 @@ via_set_drive(drive, XFER_PIO_0 + MIN(pio, 5)); } -#ifdef CONFIG_BLK_DEV_IDEDMA - /** * via82cxxx_ide_dma_check - set up for DMA if possible * @drive: IDE drive to set up @@ -411,8 +409,6 @@ return HWIF(drive)->ide_dma_off_quietly(drive); } -#endif /* CONFIG_BLK_DEV_IDEDMA */ - /** * init_chipset_via82cxxx - initialization handler * @dev: PCI device @@ -608,7 +604,6 @@ hwif->mwdma_mask = 0x07; hwif->swdma_mask = 0x07; -#ifdef CONFIG_BLK_DEV_IDEDMA if (!(hwif->udma_four)) hwif->udma_four = ((via_enabled & via_80w) >> hwif->channel) & 1; hwif->ide_dma_check = &via82cxxx_ide_dma_check; @@ -616,7 +611,6 @@ hwif->autodma = 1; hwif->drives[0].autodma = hwif->autodma; hwif->drives[1].autodma = hwif->autodma; -#endif /* CONFIG_BLK_DEV_IDEDMA */ } /** diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/ide/setup-pci.c linux.2.5.47-ac4/drivers/ide/setup-pci.c --- linux.2.5.47/drivers/ide/setup-pci.c 2002-11-11 16:39:10.000000000 +0000 +++ linux.2.5.47-ac4/drivers/ide/setup-pci.c 2002-11-13 15:00:49.000000000 +0000 @@ -10,6 +10,7 @@ * Split the set up function into multiple functions * Use pci_set_master * Fix misreporting of I/O v MMIO problems + * Initial fixups for simplex devices */ /* @@ -42,6 +43,8 @@ * based on io_base port if possible. Return the matching hwif, * or a new hwif. If we find an error (clashing, out of devices, etc) * return NULL + * + * FIXME: we need to handle mmio matches here too */ static ide_hwif_t *ide_match_hwif(unsigned long io_base, u8 bootable, const char *name) @@ -144,34 +147,9 @@ return -EOPNOTSUPP; } } - -#if 0 - /* - * At this point we have enabled the device, but may previously - * have done a BAR4 enable alone. We should be prepared to assign - * resources here. - */ - - /* - * Setup base registers for IDE command/control - * spaces for each interface: - */ - for (reg = 0; reg < 4; reg++) { - struct resource *res = dev->resource + reg; - if ((res->flags & IORESOURCE_IO) == 0) - continue; - if (!res->start) { - if(pci_assign_resource(dev, reg)) { - printk(KERN_ERR "%s: Missing I/O address #%d\n", name, reg); - return -ENXIO; - } - } - } -#endif return 0; } -#ifdef CONFIG_BLK_DEV_IDEDMA #ifdef CONFIG_BLK_DEV_IDEDMA_FORCED /* * Long lost data from 2.0.34 that is now in 2.0.39 @@ -192,9 +170,6 @@ * Fetch the DMA Bus-Master-I/O-Base-Address (BMIBA) from PCI space: * If need be we set up the DMA base. Where a device has a partner that * is already in DMA mode we check and enforce IDE simplex rules. - * - * FIXME: currently we are sometimes enforicng simplex when it is not - * needed. We fail the safe way but why is it occurring ?? */ static unsigned long __init ide_get_or_set_dma_base (ide_hwif_t *hwif) @@ -274,7 +249,14 @@ simplex_stat = hwif->INB(dma_base + 2); if (simplex_stat & 0x80) { /* simplex device? */ - +#if 0 +/* + * At this point we haven't probed the drives so we can't make the + * appropriate decision. Really we should defer this problem + * until we tune the drive then try to grab DMA ownership if we want + * to be the DMA end. This has to be become dynamic to handle hot + * plug. + */ /* Don't enable DMA on a simplex channel with no drives */ if (!hwif->drives[0].present && !hwif->drives[1].present) { @@ -283,7 +265,9 @@ dma_base = 0; } /* If our other channel has DMA then we cannot */ - else if(hwif->mate && hwif->mate->dma_base) + else +#endif + if(hwif->mate && hwif->mate->dma_base) { printk(KERN_INFO "%s: simplex device: " "DMA disabled\n", @@ -295,7 +279,6 @@ } return dma_base; } -#endif /* CONFIG_BLK_DEV_IDEDMA */ static void ide_setup_pci_noise (struct pci_dev *dev, ide_pci_device_t *d) { @@ -500,8 +483,9 @@ * Set up BM-DMA capability * (PnP BIOS should have done this) */ - if ((d->device != PCI_DEVICE_ID_CYRIX_5530_IDE) - && (d->vendor != PCI_VENDOR_ID_CYRIX)) { + if (!((d->device == PCI_DEVICE_ID_CYRIX_5530_IDE && d->vendor == PCI_VENDOR_ID_CYRIX) + ||(d->device == PCI_DEVICE_ID_NS_SCx200_IDE && d->vendor == PCI_VENDOR_ID_NS))) + { /* * default DMA off if we had to * configure it here @@ -689,7 +673,6 @@ if (d->init_iops) d->init_iops(hwif); -#ifdef CONFIG_BLK_DEV_IDEDMA if (d->autodma == NODMA) goto bypass_legacy_dma; if (d->autodma == NOAUTODMA) @@ -698,7 +681,6 @@ hwif->autodma = 1; ide_hwif_setup_dma(dev, d, hwif); bypass_legacy_dma: -#endif /* CONFIG_BLK_DEV_IDEDMA */ drive0_tune = hwif->drives[0].autotune; drive1_tune = hwif->drives[1].autotune; @@ -708,7 +690,13 @@ * for each enabled hwif */ d->init_hwif(hwif); - + + /* + * This is in the wrong place. The driver may + * do set up based on the autotune value and this + * will then trash it. Torben please move it and + * propogate the fixes into the drivers + */ if (drive0_tune == IDE_TUNE_BIOS) /* biostimings */ hwif->drives[0].autotune = IDE_TUNE_BIOS; if (drive1_tune == IDE_TUNE_BIOS) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/input/mouse/psmouse.c linux.2.5.47-ac4/drivers/input/mouse/psmouse.c --- linux.2.5.47/drivers/input/mouse/psmouse.c 2002-10-31 14:57:18.000000000 +0000 +++ linux.2.5.47-ac4/drivers/input/mouse/psmouse.c 2002-10-31 15:05:42.000000000 +0000 @@ -312,6 +312,26 @@ return PSMOUSE_PS2; /* + * Try Synaptics TouchPad magic ID + */ + + param[0] = 0; + psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES); + psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES); + psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES); + psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES); + psmouse_command(psmouse, param, PSMOUSE_CMD_GETINFO); + + if (param[1] == 0x47) { + /* We could do more here. But it's sufficient just + to stop the subsequent probes from screwing the + thing up. */ + psmouse->vendor = "Synaptics"; + psmouse->name = "TouchPad"; + return PSMOUSE_PS2; + } + +/* * Try Genius NetMouse magic init. */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/isdn/hisax/bkm_a8.c linux.2.5.47-ac4/drivers/isdn/hisax/bkm_a8.c --- linux.2.5.47/drivers/isdn/hisax/bkm_a8.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/isdn/hisax/bkm_a8.c 2002-10-31 17:02:42.000000000 +0000 @@ -278,8 +278,6 @@ static struct pci_dev *dev_a8 __initdata = NULL; static u16 sub_vendor_id __initdata = 0; static u16 sub_sys_id __initdata = 0; -static u_char pci_bus __initdata = 0; -static u_char pci_device_fn __initdata = 0; static u_char pci_irq __initdata = 0; #endif /* CONFIG_PCI */ @@ -328,8 +326,6 @@ return(0); pci_ioaddr1 = pci_resource_start(dev_a8, 1); pci_irq = dev_a8->irq; - pci_bus = dev_a8->bus->number; - pci_device_fn = dev_a8->devfn; found = 1; break; } @@ -342,20 +338,17 @@ } #ifdef ATTEMPT_PCI_REMAPPING /* HACK: PLX revision 1 bug: PLX address bit 7 must not be set */ - pcibios_read_config_byte(pci_bus, pci_device_fn, - PCI_REVISION_ID, &pci_rev_id); + pci_read_config_byte(dev_a8, PCI_REVISION_ID, &pci_rev_id); if ((pci_ioaddr1 & 0x80) && (pci_rev_id == 1)) { printk(KERN_WARNING "HiSax: %s (%s): PLX rev 1, remapping required!\n", CardType[card->typ], sct_quadro_subtypes[cs->subtyp]); /* Restart PCI negotiation */ - pcibios_write_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_1, (u_int) - 1); + pci_write_config_dword(dev_a8, PCI_BASE_ADDRESS_1, (u_int) - 1); /* Move up by 0x80 byte */ pci_ioaddr1 += 0x80; pci_ioaddr1 &= PCI_BASE_ADDRESS_IO_MASK; - pcibios_write_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_1, pci_ioaddr1); + pci_write_config_dword(dev_a8, PCI_BASE_ADDRESS_1, pci_ioaddr1); dev_a8->resource[ 1].start = pci_ioaddr1; } #endif /* End HACK */ @@ -366,11 +359,11 @@ sct_quadro_subtypes[cs->subtyp]); return (0); } - pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_1, &pci_ioaddr1); - pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_2, &pci_ioaddr2); - pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_3, &pci_ioaddr3); - pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_4, &pci_ioaddr4); - pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_5, &pci_ioaddr5); + pci_read_config_dword(dev_a8, PCI_BASE_ADDRESS_1, &pci_ioaddr1); + pci_read_config_dword(dev_a8, PCI_BASE_ADDRESS_2, &pci_ioaddr2); + pci_read_config_dword(dev_a8, PCI_BASE_ADDRESS_3, &pci_ioaddr3); + pci_read_config_dword(dev_a8, PCI_BASE_ADDRESS_4, &pci_ioaddr4); + pci_read_config_dword(dev_a8, PCI_BASE_ADDRESS_5, &pci_ioaddr5); if (!pci_ioaddr1 || !pci_ioaddr2 || !pci_ioaddr3 || !pci_ioaddr4 || !pci_ioaddr5) { printk(KERN_WARNING "HiSax: %s (%s): No IO base address(es)\n", CardType[card->typ], diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/md/dm.c linux.2.5.47-ac4/drivers/md/dm.c --- linux.2.5.47/drivers/md/dm.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/md/dm.c 2002-11-13 01:15:07.000000000 +0000 @@ -15,7 +15,7 @@ #include static const char *_name = DM_NAME; -#define MAX_DEVICES 256 +#define MAX_DEVICES (1 << KDEV_MINOR_BITS) #define SECTOR_SHIFT 9 static int major = 0; @@ -41,8 +41,6 @@ struct mapped_device { struct rw_semaphore lock; - - kdev_t kdev; atomic_t holders; unsigned long flags; @@ -485,13 +483,25 @@ return 0; } +/*----------------------------------------------------------------- + * A bitset is used to keep track of allocated minor numbers. + *---------------------------------------------------------------*/ +static spinlock_t _minor_lock = SPIN_LOCK_UNLOCKED; +static unsigned long _minor_bits[MAX_DEVICES / BITS_PER_LONG]; + +static void free_minor(int minor) +{ + spin_lock(&_minor_lock); + clear_bit(minor, _minor_bits); + spin_unlock(&_minor_lock); +} + /* * See if the device with a specific minor # is free. */ -static int specific_dev(int minor, struct mapped_device *md) +static int specific_minor(int minor) { - struct gendisk *disk; - int part; + int r = -EBUSY; if (minor >= MAX_DEVICES) { DMWARN("request for a mapped_device beyond MAX_DEVICES (%d)", @@ -499,26 +509,27 @@ return -EINVAL; } - disk = get_gendisk(MKDEV(_major, minor), &part); - if (disk) { - put_disk(disk); - return -EBUSY; - } + spin_lock(&_minor_lock); + if (!test_and_set_bit(minor, _minor_bits)) + r = minor; + spin_unlock(&_minor_lock); - return minor; + return r; } -static int any_old_dev(struct mapped_device *md) +static int next_free_minor(void) { - int i; + int minor, r = -EBUSY; - for (i = 0; i < MAX_DEVICES; i++) - if (specific_dev(i, md) >= 0) { - DMWARN("allocating minor = %d", i); - return i; - } + spin_lock(&_minor_lock); + minor = find_first_zero_bit(_minor_bits, MAX_DEVICES); + if (minor != MAX_DEVICES) { + set_bit(minor, _minor_bits); + r = minor; + } + spin_unlock(&_minor_lock); - return -EBUSY; + return r; } /* @@ -534,15 +545,15 @@ } /* get a minor number for the dev */ - minor = (minor < 0) ? any_old_dev(md) : specific_dev(minor, md); + minor = (minor < 0) ? next_free_minor() : specific_minor(minor); if (minor < 0) { kfree(md); return NULL; } + DMWARN("allocating minor %d.", minor); memset(md, 0, sizeof(*md)); init_rwsem(&md->lock); - md->kdev = mk_kdev(_major, minor); atomic_set(&md->holders, 1); md->queue.queuedata = md; @@ -550,6 +561,7 @@ md->disk = alloc_disk(1); if (!md->disk) { + free_minor(md->disk->first_minor); kfree(md); return NULL; } @@ -569,6 +581,7 @@ static void free_dev(struct mapped_device *md) { + free_minor(md->disk->first_minor); del_gendisk(md->disk); put_disk(md->disk); kfree(md); @@ -749,15 +762,13 @@ return 0; } -kdev_t dm_kdev(struct mapped_device *md) +/* + * The gendisk is only valid as long as you have a reference + * count on 'md'. + */ +struct gendisk *dm_disk(struct mapped_device *md) { - kdev_t dev; - - down_read(&md->lock); - dev = md->kdev; - up_read(&md->lock); - - return dev; + return md->disk; } struct dm_table *dm_get_table(struct mapped_device *md) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/md/dm.h linux.2.5.47-ac4/drivers/md/dm.h --- linux.2.5.47/drivers/md/dm.h 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/md/dm.h 2002-11-13 01:14:58.000000000 +0000 @@ -77,7 +77,7 @@ /* * Info functions. */ -kdev_t dm_kdev(struct mapped_device *md); +struct gendisk *dm_disk(struct mapped_device *md); int dm_suspended(struct mapped_device *md); /*----------------------------------------------------------------- diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/md/dm-ioctl.c linux.2.5.47-ac4/drivers/md/dm-ioctl.c --- linux.2.5.47/drivers/md/dm-ioctl.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/md/dm-ioctl.c 2002-11-13 01:15:56.000000000 +0000 @@ -8,7 +8,6 @@ #include #include -#include #include #include #include @@ -16,6 +15,8 @@ #include #include +#include + #define DM_DRIVER_EMAIL "dm@uk.sistina.com" /*----------------------------------------------------------------- @@ -176,10 +177,11 @@ */ static int register_with_devfs(struct hash_cell *hc) { - kdev_t dev = dm_kdev(hc->md); + struct gendisk *disk = dm_disk(hc->md); + hc->devfs_entry = devfs_register(_dev_dir, hc->name, DEVFS_FL_CURRENT_OWNER, - major(dev), minor(dev), + disk->major, disk->first_minor, S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP, &dm_blk_dops, NULL); @@ -447,23 +449,24 @@ static int __info(struct mapped_device *md, struct dm_ioctl *param) { struct dm_table *table; + struct gendisk *disk = dm_disk(md); struct block_device *bdev; param->flags = DM_EXISTS_FLAG; if (dm_suspended(md)) param->flags |= DM_SUSPEND_FLAG; - param->dev = kdev_t_to_nr(dm_kdev(md)); + param->dev = MKDEV(disk->major, disk->first_minor); bdev = bdget(param->dev); if (!bdev) return -ENXIO; - if (bdev_read_only(bdev)) - param->flags |= DM_READONLY_FLAG; - param->open_count = bdev->bd_openers; bdput(bdev); + if (disk->policy) + param->flags |= DM_READONLY_FLAG; + table = dm_get_table(md); param->target_count = dm_table_get_num_targets(table); dm_table_put(table); @@ -558,6 +561,7 @@ { int r; struct dm_table *t; + struct gendisk *disk; struct mapped_device *md; int minor; @@ -585,7 +589,8 @@ } dm_table_put(t); /* md will have grabbed its own reference */ - set_device_ro(dm_kdev(md), (param->flags & DM_READONLY_FLAG)); + disk = dm_disk(md); + set_disk_ro(disk, (param->flags & DM_READONLY_FLAG)); r = dm_hash_insert(param->name, *param->uuid ? param->uuid : NULL, md); dm_put(md); @@ -845,6 +850,7 @@ static int reload(struct dm_ioctl *param, struct dm_ioctl *user) { int r; + struct gendisk *disk; struct mapped_device *md; struct dm_table *t; @@ -871,7 +877,8 @@ return r; } - set_device_ro(dm_kdev(md), (param->flags & DM_READONLY_FLAG)); + disk = dm_disk(md); + set_disk_ro(disk, (param->flags & DM_READONLY_FLAG)); dm_put(md); r = info(param, user); @@ -1077,7 +1084,6 @@ int __init dm_interface_init(void) { int r; - char rname[64]; r = dm_hash_init(); if (r) @@ -1090,25 +1096,12 @@ return r; } - r = devfs_generate_path(_dm_misc.devfs_handle, rname + 3, - sizeof rname - 3); - if (r == -ENOSYS) - return 0; /* devfs not present */ - - if (r < 0) { - DMERR("devfs_generate_path failed for control device"); - goto failed; - } - - strncpy(rname + r, "../", 3); - r = devfs_mk_symlink(NULL, DM_DIR "/control", - DEVFS_FL_DEFAULT, rname + r, &_ctl_handle, NULL); + r = devfs_mk_symlink(NULL, DM_DIR "/control", DEVFS_FL_DEFAULT, + "../misc/" DM_NAME, &_ctl_handle, NULL); if (r) { DMERR("devfs_mk_symlink failed for control device"); goto failed; } - devfs_auto_unregister(_dm_misc.devfs_handle, _ctl_handle); - DMINFO("%d.%d.%d%s initialised: %s", DM_VERSION_MAJOR, DM_VERSION_MINOR, DM_VERSION_PATCHLEVEL, DM_VERSION_EXTRA, DM_DRIVER_EMAIL); @@ -1124,6 +1117,8 @@ { dm_hash_exit(); + devfs_find_and_unregister(NULL, DM_DIR "/control", 0, 0, 0, 0); + if (misc_deregister(&_dm_misc) < 0) DMERR("misc_deregister failed for control device"); } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/md/dm-table.c linux.2.5.47-ac4/drivers/md/dm-table.c --- linux.2.5.47/drivers/md/dm-table.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/md/dm-table.c 2002-11-13 01:14:13.000000000 +0000 @@ -146,6 +146,25 @@ return 0; } +static void *dm_vcalloc(unsigned long nmemb, unsigned long elem_size) +{ + unsigned long size; + void *addr; + + /* + * Check that we're not going to overflow. + */ + if (nmemb > (ULONG_MAX / elem_size)) + return NULL; + + size = nmemb * elem_size; + addr = vmalloc(size); + if (addr) + memset(addr, 0, size); + + return addr; +} + /* * highs, and targets are managed as dynamic arrays during a * table load. @@ -159,9 +178,8 @@ /* * Allocate both the target array and offset array at once. */ - n_highs = (sector_t *) vcalloc(sizeof(struct dm_target) + - sizeof(sector_t), - num); + n_highs = (sector_t *) dm_vcalloc(sizeof(struct dm_target) + + sizeof(sector_t), num); if (!n_highs) return -ENOMEM; @@ -624,7 +642,7 @@ total += t->counts[i]; } - indexes = (sector_t *) vcalloc(total, (unsigned long) NODE_SIZE); + indexes = (sector_t *) dm_vcalloc(total, (unsigned long) NODE_SIZE); if (!indexes) return -ENOMEM; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/media/dvb/av7110/av7110.c linux.2.5.47-ac4/drivers/media/dvb/av7110/av7110.c --- linux.2.5.47/drivers/media/dvb/av7110/av7110.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/media/dvb/av7110/av7110.c 2002-11-13 01:26:41.000000000 +0000 @@ -89,7 +89,7 @@ static void SetMode(av7110_t *av7110, int mode); void pes_to_ts(u8 const *buf, long int length, u16 pid, p2t_t *p); -void p_to_t(u8 const *buf, long int length, u16 pid, u8 *counter, dvb_demux_feed_t *feed); +void p_to_t(u8 const *buf, long int length, u16 pid, u8 *counter, struct dvb_demux_feed *feed); static u32 vidmem = 0; static u32 vidlow = 0; @@ -392,9 +392,9 @@ static int -record_cb(pes2ts_t *p2t, u8 *buf, size_t len) +record_cb(dvb_filter_pes2ts_t *p2t, u8 *buf, size_t len) { - dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) p2t->priv; + struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) p2t->priv; if (!(dvbdmxfeed->ts_type & TS_PACKET)) return 0; @@ -404,13 +404,13 @@ return dvbdmxfeed->cb.ts(buf, len, 0, 0, &dvbdmxfeed->feed.ts, DMX_OK); else - return pes2ts(p2t, buf, len); + return dvb_filter_pes2ts(p2t, buf, len); } static int -pes2ts_cb(void *priv, unsigned char *data) +dvb_filter_pes2ts_cb(void *priv, unsigned char *data) { - dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) priv; + struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) priv; dvbdmxfeed->cb.ts(data, 188, 0, 0, &dvbdmxfeed->feed.ts, @@ -420,9 +420,9 @@ static int AV_StartRecord(av7110_t *av7110, int av, - dvb_demux_feed_t *dvbdmxfeed) + struct dvb_demux_feed *dvbdmxfeed) { - dvb_demux_t *dvbdmx=dvbdmxfeed->demux; + struct dvb_demux *dvbdmx=dvbdmxfeed->demux; if (av7110->playing||(av7110->rec_mode&av)) return -EBUSY; @@ -432,20 +432,30 @@ switch (av7110->rec_mode) { case RP_AUDIO: - pes2ts_init(&av7110->p2t[0], dvbdmx->pesfilter[0]->pid, - pes2ts_cb, (void *)dvbdmx->pesfilter[0]); + dvb_filter_pes2ts_init (&av7110->p2t[0], + dvbdmx->pesfilter[0]->pid, + dvb_filter_pes2ts_cb, + (void *)dvbdmx->pesfilter[0]); outcom(av7110, COMTYPE_REC_PLAY, __Record, 2, AudioPES, 0); break; + case RP_VIDEO: - pes2ts_init(&av7110->p2t[1], dvbdmx->pesfilter[1]->pid, - pes2ts_cb, (void *)dvbdmx->pesfilter[1]); + dvb_filter_pes2ts_init (&av7110->p2t[1], + dvbdmx->pesfilter[1]->pid, + dvb_filter_pes2ts_cb, + (void *)dvbdmx->pesfilter[1]); outcom(av7110, COMTYPE_REC_PLAY, __Record, 2, VideoPES, 0); break; + case RP_AV: - pes2ts_init(&av7110->p2t[0], dvbdmx->pesfilter[0]->pid, - pes2ts_cb, (void *)dvbdmx->pesfilter[0]); - pes2ts_init(&av7110->p2t[1], dvbdmx->pesfilter[1]->pid, - pes2ts_cb, (void *)dvbdmx->pesfilter[1]); + dvb_filter_pes2ts_init (&av7110->p2t[0], + dvbdmx->pesfilter[0]->pid, + dvb_filter_pes2ts_cb, + (void *)dvbdmx->pesfilter[0]); + dvb_filter_pes2ts_init (&av7110->p2t[1], + dvbdmx->pesfilter[1]->pid, + dvb_filter_pes2ts_cb, + (void *)dvbdmx->pesfilter[1]); outcom(av7110, COMTYPE_REC_PLAY, __Record, 2, AV_PES, 0); break; } @@ -463,8 +473,8 @@ outcom(av7110, COMTYPE_REC_PLAY, __Stop, 0); if (av7110->playing == RP_NONE) { - reset_ipack(&av7110->ipack[0]); - reset_ipack(&av7110->ipack[1]); + dvb_filter_ipack_reset(&av7110->ipack[0]); + dvb_filter_ipack_reset(&av7110->ipack[1]); } av7110->playing|=av; @@ -814,7 +824,7 @@ static inline int DvbDmxFilterCallback(u8 * buffer1, size_t buffer1_len, u8 * buffer2, size_t buffer2_len, - dvb_demux_filter_t *dvbdmxfilter, + struct dvb_demux_filter *dvbdmxfilter, dmx_success_t success, av7110_t *av7110) { @@ -896,7 +906,7 @@ // FIXME: use bottom half or tasklet if (av7110->feeding && mem[0]==0x47) - DvbDmxSWFilterPackets(&av7110->demux, mem, 512); + dvb_dmx_swfilter_packets(&av7110->demux, mem, 512); } #else static @@ -922,7 +932,7 @@ } else { if (av7110->ttbp>1000*188 && av7110->ttbp<1024*188) { if (av7110->feeding) - DvbDmxSWFilterPackets(&av7110->demux, + dvb_dmx_swfilter_packets(&av7110->demux, mem+av7110->ttbp, 1024- av7110->ttbp / 188); } @@ -937,7 +947,7 @@ // FIXME: use bottom half or tasklet if (av7110->feeding && mem[0]==0x47) - DvbDmxSWFilterPackets(&av7110->demux, mem, num); + dvb_dmx_swfilter_packets(&av7110->demux, mem, num); } #endif @@ -1001,7 +1011,7 @@ switch (type&0xff) { case DATA_TS_RECORD: - DvbDmxSWFilterPackets(&av7110->demux, + dvb_dmx_swfilter_packets(&av7110->demux, (const u8 *)av7110->debi_virt, av7110->debilen/188); spin_lock(&av7110->debilock); @@ -2008,8 +2018,8 @@ av7110->arm_app=(buf[6] << 16) + buf[7]; av7110->avtype=(buf[8] << 16) + buf[9]; - printk ("av7110 (%d): AV711%d - firm %08x, rtsl %08x, vid %08x, app %08x\n", - av7110->saa->dvb_adapter->num, av7110->avtype, av7110->arm_fw, + printk ("DVB: AV711%d(%d) - firm %08x, rtsl %08x, vid %08x, app %08x\n", + av7110->avtype, av7110->saa->dvb_adapter->num, av7110->arm_fw, av7110->arm_rtsl, av7110->arm_vid, av7110->arm_app); return; @@ -2483,9 +2493,12 @@ if (umem) { if (copy_from_user(av7110->kbuf[type], buf, n)) return -EFAULT; - instant_repack(av7110->kbuf[type], n, &av7110->ipack[type]); - } else - instant_repack((u8 *)buf, n, &av7110->ipack[type]); + dvb_filter_instant_repack(av7110->kbuf[type], n, + &av7110->ipack[type]); + } else { + dvb_filter_instant_repack((u8 *)buf, n, + &av7110->ipack[type]); + } todo -= n; buf += n; } @@ -2517,7 +2530,8 @@ n=IPACKS*2; if (copy_from_user(av7110->kbuf[type], buf, n)) return -EFAULT; - instant_repack(av7110->kbuf[type], n, &av7110->ipack[type]); + dvb_filter_instant_repack(av7110->kbuf[type], n, + &av7110->ipack[type]); // memcpy(dvb->kbuf[type], buf, n); todo -= n; buf += n; @@ -2525,7 +2539,7 @@ return count-todo; } -void init_p2t(p2t_t *p, dvb_demux_feed_t *feed) +void init_p2t(p2t_t *p, struct dvb_demux_feed *feed) { memset(p->pes,0,TS_SIZE); p->counter = 0; @@ -2721,7 +2735,7 @@ void p_to_t(u8 const *buf, long int length, u16 pid, u8 *counter, - dvb_demux_feed_t *feed) + struct dvb_demux_feed *feed) { int l, pes_start; @@ -3104,7 +3118,7 @@ static unsigned int dvb_audio_poll(struct file *file, poll_table *wait) { - dvb_device_t *dvbdev=(dvb_device_t *) file->private_data; + struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; av7110_t *av7110=(av7110_t *) dvbdev->priv; unsigned int mask=0; @@ -3124,24 +3138,24 @@ static struct file_operations dvb_fops = { - ioctl: dvb_ioctl, - mmap: dvb_mmap, - llseek: no_llseek + .ioctl = dvb_ioctl, + .mmap = dvb_mmap, + .llseek = no_llseek }; /* template for video_device-structure */ static struct video_device dvb_template = { - owner: THIS_MODULE, - name: "DVB Board", - type: VID_TYPE_TUNER | + .owner = THIS_MODULE, + .name = "DVB Board", + .type = VID_TYPE_TUNER | VID_TYPE_CAPTURE | VID_TYPE_OVERLAY | VID_TYPE_CLIPPING | VID_TYPE_FRAMERAM | VID_TYPE_SCALES, - hardware: VID_HARDWARE_SAA7146, - fops: &dvb_fops + .hardware = VID_HARDWARE_SAA7146, + .fops = &dvb_fops }; @@ -3182,9 +3196,9 @@ ******************************************************************************/ static int -StartHWFilter(dvb_demux_filter_t *dvbdmxfilter) +StartHWFilter(struct dvb_demux_filter *dvbdmxfilter) { - dvb_demux_feed_t *dvbdmxfeed=dvbdmxfilter->feed; + struct dvb_demux_feed *dvbdmxfeed=dvbdmxfilter->feed; av7110_t *av7110=(av7110_t *) dvbdmxfeed->demux->priv; u16 buf[20]; int ret, i; @@ -3220,7 +3234,7 @@ } static int -StopHWFilter(dvb_demux_filter_t *dvbdmxfilter) +StopHWFilter(struct dvb_demux_filter *dvbdmxfilter) { av7110_t *av7110=(av7110_t *) dvbdmxfilter->feed->demux->priv; u16 buf[3]; @@ -3252,9 +3266,9 @@ static int -dvb_write_to_decoder(dvb_demux_feed_t *dvbdmxfeed, u8 *buf, size_t count) +dvb_write_to_decoder(struct dvb_demux_feed *dvbdmxfeed, u8 *buf, size_t count) { - dvb_demux_t *dvbdmx=dvbdmxfeed->demux; + struct dvb_demux *dvbdmx=dvbdmxfeed->demux; av7110_t *av7110=(av7110_t *) dvbdmx->priv; ipack *ipack=&av7110->ipack[dvbdmxfeed->pes_type]; @@ -3277,7 +3291,7 @@ return -1; } if (buf[1]&0x40) - send_ipack_rest(ipack); + dvb_filter_ipack_flush(ipack); if (buf[3]&0x20) { // adaptation field? count-=buf[4]+1; @@ -3287,14 +3301,15 @@ } } - instant_repack(buf+4, count-4, &av7110->ipack[dvbdmxfeed->pes_type]); + dvb_filter_instant_repack(buf+4, count-4, + &av7110->ipack[dvbdmxfeed->pes_type]); return 0; } static void -dvb_feed_start_pid(dvb_demux_feed_t *dvbdmxfeed) +dvb_feed_start_pid(struct dvb_demux_feed *dvbdmxfeed) { - dvb_demux_t *dvbdmx=dvbdmxfeed->demux; + struct dvb_demux *dvbdmx=dvbdmxfeed->demux; av7110_t *av7110=(av7110_t *) dvbdmx->priv; u16 *pid=dvbdmx->pids, npids[5]; int i; @@ -3329,9 +3344,9 @@ } static void -dvb_feed_stop_pid(dvb_demux_feed_t *dvbdmxfeed) +dvb_feed_stop_pid(struct dvb_demux_feed *dvbdmxfeed) { - dvb_demux_t *dvbdmx=dvbdmxfeed->demux; + struct dvb_demux *dvbdmx=dvbdmxfeed->demux; av7110_t *av7110=(av7110_t *) dvbdmx->priv; u16 *pid=dvbdmx->pids, npids[5]; int i; @@ -3365,9 +3380,9 @@ } static int -dvb_start_feed(dvb_demux_feed_t *dvbdmxfeed) +dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed) { - dvb_demux_t *dvbdmx=dvbdmxfeed->demux; + struct dvb_demux *dvbdmx=dvbdmxfeed->demux; av7110_t *av7110=(av7110_t *) dvbdmx->priv; if (!dvbdmx->dmx.frontend) @@ -3425,9 +3440,9 @@ static int -dvb_stop_feed(dvb_demux_feed_t *dvbdmxfeed) +dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) { - dvb_demux_t *dvbdmx=dvbdmxfeed->demux; + struct dvb_demux *dvbdmx=dvbdmxfeed->demux; av7110_t *av7110=(av7110_t *) dvbdmx->priv; if (av7110->saa->card_type>=DVB_CARD_TT_BUDGET) @@ -3468,8 +3483,8 @@ static void restart_feeds(av7110_t *av7110) { - dvb_demux_t *dvbdmx=&av7110->demux; - dvb_demux_feed_t *feed; + struct dvb_demux *dvbdmx=&av7110->demux; + struct dvb_demux_feed *feed; int mode; int i; @@ -3660,7 +3675,7 @@ static int dvb_ca_open(struct inode *inode, struct file *file) { - dvb_device_t *dvbdev=(dvb_device_t *) file->private_data; + struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; av7110_t *av7110=(av7110_t *) dvbdev->priv; int err=dvb_generic_open(inode, file); @@ -3673,7 +3688,7 @@ static unsigned int dvb_ca_poll(struct file *file, poll_table *wait) { - dvb_device_t *dvbdev=(dvb_device_t *) file->private_data; + struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; av7110_t *av7110=(av7110_t *) dvbdev->priv; unsigned int mask=0; @@ -3702,7 +3717,7 @@ dvb_ca_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *parg) { - dvb_device_t *dvbdev=(dvb_device_t *) file->private_data; + struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; av7110_t *av7110=(av7110_t *) dvbdev->priv; unsigned long arg=(unsigned long) parg; @@ -3716,7 +3731,7 @@ case CA_GET_CAP: { - ca_cap_t cap; + ca_caps_t cap; cap.slot_num=2; #ifdef NEW_CI @@ -3788,7 +3803,7 @@ dvb_ca_write(struct file *file, const char *buf, size_t count, loff_t *ppos) { - dvb_device_t *dvbdev=(dvb_device_t *) file->private_data; + struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; av7110_t *av7110=(av7110_t *) dvbdev->priv; return ci_ll_write(&av7110->ci_wbuffer, file, buf, count, ppos); @@ -3797,7 +3812,7 @@ static ssize_t dvb_ca_read(struct file *file, char *buf, size_t count, loff_t *ppos) { - dvb_device_t *dvbdev=(dvb_device_t *) file->private_data; + struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; av7110_t *av7110=(av7110_t *) dvbdev->priv; return ci_ll_read(&av7110->ci_rbuffer, file, buf, count, ppos); @@ -3812,7 +3827,7 @@ static unsigned int dvb_video_poll(struct file *file, poll_table *wait) { - dvb_device_t *dvbdev=(dvb_device_t *) file->private_data; + struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; av7110_t *av7110=(av7110_t *) dvbdev->priv; unsigned int mask=0; @@ -3834,7 +3849,7 @@ dvb_video_write(struct file *file, const char *buf, size_t count, loff_t *ppos) { - dvb_device_t *dvbdev=(dvb_device_t *) file->private_data; + struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; av7110_t *av7110=(av7110_t *) dvbdev->priv; if (av7110->videostate.stream_source!=VIDEO_SOURCE_MEMORY) @@ -3847,7 +3862,7 @@ dvb_audio_write(struct file *file, const char *buf, size_t count, loff_t *ppos) { - dvb_device_t *dvbdev=(dvb_device_t *) file->private_data; + struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; av7110_t *av7110=(av7110_t *) dvbdev->priv; if (av7110->audiostate.stream_source!=AUDIO_SOURCE_MEMORY) { @@ -3876,7 +3891,7 @@ for (i=0; iipack[1]); + dvb_filter_ipack_flush(&av7110->ipack[1]); } @@ -3884,7 +3899,7 @@ dvb_video_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *parg) { - dvb_device_t *dvbdev=(dvb_device_t *) file->private_data; + struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; av7110_t *av7110=(av7110_t *) dvbdev->priv; unsigned long arg=(unsigned long) parg; int ret=0; @@ -4041,7 +4056,7 @@ case VIDEO_CLEAR_BUFFER: ring_buffer_flush(&av7110->avout); - reset_ipack(&av7110->ipack[1]); + dvb_filter_ipack_reset(&av7110->ipack[1]); if (av7110->playing==RP_AV) { outcom(av7110, COMTYPE_REC_PLAY, @@ -4073,7 +4088,7 @@ dvb_audio_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *parg) { - dvb_device_t *dvbdev=(dvb_device_t *) file->private_data; + struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; av7110_t *av7110=(av7110_t *) dvbdev->priv; unsigned long arg=(unsigned long) parg; int ret=0; @@ -4164,7 +4179,7 @@ case AUDIO_CLEAR_BUFFER: ring_buffer_flush(&av7110->aout); - reset_ipack(&av7110->ipack[0]); + dvb_filter_ipack_reset(&av7110->ipack[0]); if (av7110->playing==RP_AV) outcom(av7110, COMTYPE_REC_PLAY, __Play, 2, AV_PES, 0); @@ -4192,7 +4207,7 @@ dvb_osd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *parg) { - dvb_device_t *dvbdev=(dvb_device_t *) file->private_data; + struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; av7110_t *av7110=(av7110_t *) dvbdev->priv; #ifdef CONFIG_DVB_AV7110_OSD @@ -4204,7 +4219,7 @@ static int dvb_video_open(struct inode *inode, struct file *file) { - dvb_device_t *dvbdev=(dvb_device_t *) file->private_data; + struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; av7110_t *av7110=(av7110_t *) dvbdev->priv; int err; @@ -4220,7 +4235,7 @@ static int dvb_video_release(struct inode *inode, struct file *file) { - dvb_device_t *dvbdev=(dvb_device_t *) file->private_data; + struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; av7110_t *av7110=(av7110_t *) dvbdev->priv; AV_Stop(av7110, RP_VIDEO); @@ -4229,7 +4244,7 @@ static int dvb_audio_open(struct inode *inode, struct file *file) { - dvb_device_t *dvbdev=(dvb_device_t *) file->private_data; + struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; av7110_t *av7110=(av7110_t *) dvbdev->priv; int err=dvb_generic_open(inode, file); @@ -4242,7 +4257,7 @@ static int dvb_audio_release(struct inode *inode, struct file *file) { - dvb_device_t *dvbdev=(dvb_device_t *) file->private_data; + struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; av7110_t *av7110=(av7110_t *) dvbdev->priv; AV_Stop(av7110, RP_AUDIO); @@ -4256,75 +4271,70 @@ ******************************************************************************/ static struct file_operations dvb_video_fops = { - owner: THIS_MODULE, - read: 0, - write: dvb_video_write, - ioctl: dvb_generic_ioctl, - open: dvb_video_open, - release: dvb_video_release, - poll: dvb_video_poll, + .owner = THIS_MODULE, + .write = dvb_video_write, + .ioctl = dvb_generic_ioctl, + .open = dvb_video_open, + .release = dvb_video_release, + .poll = dvb_video_poll, }; -static dvb_device_t dvbdev_video = { - priv: 0, - users: 1, - writers: 1, - fops: &dvb_video_fops, - kernel_ioctl: dvb_video_ioctl, +static struct dvb_device dvbdev_video = { + .priv = 0, + .users = 1, + .writers = 1, + .fops = &dvb_video_fops, + .kernel_ioctl = dvb_video_ioctl, }; static struct file_operations dvb_audio_fops = { - owner: THIS_MODULE, - read: 0, - write: dvb_audio_write, - ioctl: dvb_generic_ioctl, - open: dvb_audio_open, - release: dvb_audio_release, - poll: dvb_audio_poll, + .owner = THIS_MODULE, + .write = dvb_audio_write, + .ioctl = dvb_generic_ioctl, + .open = dvb_audio_open, + .release = dvb_audio_release, + .poll = dvb_audio_poll, }; -static dvb_device_t dvbdev_audio = { - priv: 0, - users: 1, - writers: 1, - fops: &dvb_audio_fops, - kernel_ioctl: dvb_audio_ioctl, +static struct dvb_device dvbdev_audio = { + .priv = 0, + .users = 1, + .writers = 1, + .fops = &dvb_audio_fops, + .kernel_ioctl = dvb_audio_ioctl, }; static struct file_operations dvb_ca_fops = { - owner: THIS_MODULE, - read: dvb_ca_read, - write: dvb_ca_write, - ioctl: dvb_generic_ioctl, - open: dvb_ca_open, - release: dvb_generic_release, - poll: dvb_ca_poll, + .owner = THIS_MODULE, + .read = dvb_ca_read, + .write = dvb_ca_write, + .ioctl = dvb_generic_ioctl, + .open = dvb_ca_open, + .release = dvb_generic_release, + .poll = dvb_ca_poll, }; -static dvb_device_t dvbdev_ca = { - priv: 0, - users: 1, - writers: 1, - fops: &dvb_ca_fops, - kernel_ioctl: dvb_ca_ioctl, +static struct dvb_device dvbdev_ca = { + .priv = 0, + .users = 1, + .writers = 1, + .fops = &dvb_ca_fops, + .kernel_ioctl = dvb_ca_ioctl, }; static struct file_operations dvb_osd_fops = { - owner: THIS_MODULE, - read: 0, - write: 0, - ioctl: dvb_generic_ioctl, - open: dvb_generic_open, - release: dvb_generic_release, - poll: 0, + .owner = THIS_MODULE, + .ioctl = dvb_generic_ioctl, + .open = dvb_generic_open, + .release = dvb_generic_release, }; -static dvb_device_t dvbdev_osd = { - priv: 0, - users: 1, - writers: 1, - fops: &dvb_osd_fops, - kernel_ioctl: dvb_osd_ioctl, +static struct dvb_device dvbdev_osd = { + .priv = 0, + .users = 1, + .writers = 1, + .fops = &dvb_osd_fops, + .kernel_ioctl = dvb_osd_ioctl, }; @@ -4359,7 +4369,7 @@ { int ret, i; dmx_frontend_t *dvbfront=&av7110->hw_frontend; - dvb_demux_t *dvbdemux=&av7110->demux; + struct dvb_demux *dvbdemux=&av7110->demux; if (av7110->registered) return -1; @@ -4414,7 +4424,7 @@ DMX_SECTION_FILTERING| DMX_MEMORY_BASED_FILTERING); - DvbDmxInit(&av7110->demux); + dvb_dmx_init(&av7110->demux); dvbfront->id="hw_frontend"; @@ -4426,7 +4436,7 @@ av7110->dmxdev.demux=&dvbdemux->dmx; av7110->dmxdev.capabilities=0; - DmxDevInit(&av7110->dmxdev, av7110->dvb_adapter); + dvb_dmxdev_init(&av7110->dmxdev, av7110->dvb_adapter); } if (av7110->saa->card_type>=DVB_CARD_TT_BUDGET) { @@ -4443,7 +4453,7 @@ DMX_SECTION_FILTERING| DMX_MEMORY_BASED_FILTERING); - DvbDmxInit(&av7110->demux); + dvb_dmx_init(&av7110->demux); dvbfront->id="hw_frontend"; dvbfront->vendor="VLSI"; @@ -4454,7 +4464,7 @@ av7110->dmxdev.demux=&dvbdemux->dmx; av7110->dmxdev.capabilities=0; - DmxDevInit(&av7110->dmxdev, av7110->dvb_adapter); + dvb_dmxdev_init(&av7110->dmxdev, av7110->dvb_adapter); } ret=dvbdemux->dmx.add_frontend(&dvbdemux->dmx, @@ -4505,7 +4515,7 @@ static void dvb_unregister(av7110_t *av7110) { - dvb_demux_t *dvbdemux=&av7110->demux; + struct dvb_demux *dvbdemux=&av7110->demux; if (!av7110->registered) return; @@ -4516,8 +4526,8 @@ dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &av7110->hw_frontend); dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &av7110->mem_frontend); - DmxDevRelease(&av7110->dmxdev); - DvbDmxRelease(&av7110->demux); + dvb_dmxdev_release(&av7110->dmxdev); + dvb_dmx_release(&av7110->demux); if (av7110->saa->card_type==DVB_CARD_TT_SIEMENS) dvb_remove_frontend_notifier (av7110->dvb_adapter, @@ -4584,9 +4594,9 @@ av7110->vidmode=VIDEO_MODE_PAL; - init_ipack(&av7110->ipack[0], IPACKS, play_audio_cb); + dvb_filter_ipack_init(&av7110->ipack[0], IPACKS, play_audio_cb); av7110->ipack[0].data=(void *) av7110; - init_ipack(&av7110->ipack[1], IPACKS, play_video_cb); + dvb_filter_ipack_init(&av7110->ipack[1], IPACKS, play_video_cb); av7110->ipack[1].data=(void *) av7110; @@ -4705,8 +4715,8 @@ saa7146_write(av7110->saa_mem, ISR,(MASK_19 | MASK_03)); ci_ll_release(&av7110->ci_rbuffer, &av7110->ci_wbuffer); - free_ipack(&av7110->ipack[0]); - free_ipack(&av7110->ipack[1]); + dvb_filter_ipack_free(&av7110->ipack[0]); + dvb_filter_ipack_free(&av7110->ipack[1]); vfree(av7110->iobuf); pci_free_consistent(av7110->saa->device, 8192, av7110->debi_virt, av7110->debi_bus); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/media/dvb/av7110/av7110.h linux.2.5.47-ac4/drivers/media/dvb/av7110/av7110.h --- linux.2.5.47/drivers/media/dvb/av7110/av7110.h 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/media/dvb/av7110/av7110.h 2002-11-13 01:26:41.000000000 +0000 @@ -479,7 +479,7 @@ u8 counter; long int pos; int frags; - dvb_demux_feed_t *feed; + struct dvb_demux_feed *feed; } p2t_t; @@ -561,7 +561,7 @@ int vidmode; dmxdev_t dmxdev; - dvb_demux_t demux; + struct dvb_demux demux; char demux_id[16]; dmx_frontend_t hw_frontend; @@ -580,9 +580,9 @@ #define TRICK_FREEZE 3 struct audio_status audiostate; - dvb_demux_filter_t *handle2filter[32]; + struct dvb_demux_filter *handle2filter[32]; p2t_t p2t_filter[MAXFILT]; - pes2ts_t p2t[2]; + dvb_filter_pes2ts_t p2t[2]; struct ipack_s ipack[2]; u8 *kbuf[2]; @@ -621,11 +621,11 @@ ring_buffer_t ci_wbuffer; - dvb_adapter_t *dvb_adapter; - dvb_device_t *video_dev; - dvb_device_t *audio_dev; - dvb_device_t *ca_dev; - dvb_device_t *osd_dev; + struct dvb_adapter *dvb_adapter; + struct dvb_device *video_dev; + struct dvb_device *audio_dev; + struct dvb_device *ca_dev; + struct dvb_device *osd_dev; int dsp_dev; } av7110_t; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/media/dvb/av7110/Makefile linux.2.5.47-ac4/drivers/media/dvb/av7110/Makefile --- linux.2.5.47/drivers/media/dvb/av7110/Makefile 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/media/dvb/av7110/Makefile 2002-11-13 01:26:41.000000000 +0000 @@ -6,5 +6,7 @@ obj-$(CONFIG_DVB_AV7110) += dvb-ttpci.o +EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ + include $(TOPDIR)/Rules.make diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/media/dvb/av7110/saa7146.c linux.2.5.47-ac4/drivers/media/dvb/av7110/saa7146.c --- linux.2.5.47/drivers/media/dvb/av7110/saa7146.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/media/dvb/av7110/saa7146.c 2002-11-13 01:26:41.000000000 +0000 @@ -1399,7 +1399,7 @@ /* if any error is still present, a fatal error has occured ... */ if ( SAA7146_I2C_BBR != (status = i2c_status_check(saa)) ) { hprintk("saa7146: i2c_reset: fatal error, status:0x%08x\n",status); - return -1; + return -EIO; } return 0; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/media/dvb/av7110/saa7146_core.c linux.2.5.47-ac4/drivers/media/dvb/av7110/saa7146_core.c --- linux.2.5.47/drivers/media/dvb/av7110/saa7146_core.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/media/dvb/av7110/saa7146_core.c 2002-11-13 01:26:41.000000000 +0000 @@ -33,8 +33,8 @@ #include "saa7146_core.h" #include "saa7146_v4l.h" #include "av7110.h" -#include "../dvb-core/compat.h" -#include "../dvb-core/dvb_i2c.h" +#include "compat.h" +#include "dvb_i2c.h" /* insmod parameter: here you can specify the number of video-buffers to be allocated. for simple capturing 2 buffers (double-buffering) @@ -197,23 +197,23 @@ int do_master_xfer (struct dvb_i2c_bus *i2c, struct i2c_msg msgs[], int num) { struct saa7146 *a = i2c->data; - int result, count; + int count; int i = 0; dprintk(KERN_ERR "saa7146_core.o: master_xfer called, num:%d\n",num); /* prepare the message(s), get number of u32s to transfer */ count = prepare(msgs, num, a->i2c); - if ( 0 > count ) { - hprintk(KERN_ERR "saa7146_core.o: master_xfer: could not prepare i2c-message\n"); + + if (count < 0) { + hprintk(KERN_ERR "saa7146_core.o: could not prepare i2c-message\n"); return -EIO; } /* reset the i2c-device if necessary */ - result = i2c_reset( a ); - if ( 0 > result ) { - hprintk(KERN_ERR "saa7146_core.o: master_xfer: could not reset i2c-bus\n"); - return result; + if (i2c_reset(a) < 0) { + hprintk(KERN_ERR "saa7146_core.o: could not reset i2c-bus\n"); + return -EIO; } for(i = 0; i < count; i++) { @@ -222,31 +222,17 @@ * we do not start the whole rps1-engine... */ - result = i2c_write_out( a, &a->i2c[i], - SAA7146_I2C_TIMEOUT ); - - if ( 0 != result) { /* if address-error occured, don't retry */ - if ( result == -EREMOTEIO ) - { - hprintk(KERN_ERR "saa7146_core.o: master_xfer: error in address phase\n"); - return result; - } - hprintk(KERN_ERR "saa7146_core.o: master_xfer: error transferring, trying again\n"); - break; - } + if (i2c_write_out(a, &a->i2c[i], SAA7146_I2C_TIMEOUT) < 0) { + hprintk (KERN_ERR "saa7146_core.o: " + "i2c error in address phase\n"); + return -EREMOTEIO; } - - /* see if an error occured & the last retry failed */ - if (0 != result) { - hprintk(KERN_ERR "saa7146_core.o: master_xfer: could not transfer i2c-message\n"); - return -EIO; } /* if any things had to be read, get the results */ - result = clean_up(msgs, num, a->i2c); - if ( 0 > result ) { - hprintk(KERN_ERR "saa7146_core.o: master_xfer: could not cleanup\n"); + if (clean_up(msgs, num, a->i2c) < 0) { + hprintk(KERN_ERR "saa7146_core.o: i2c cleanup failed!\n"); return -EIO; } @@ -259,13 +245,19 @@ static int master_xfer (struct dvb_i2c_bus *i2c, struct i2c_msg msgs[], int num) { + struct saa7146 *saa = i2c->data; int retries = SAA7146_I2C_RETRIES; int ret; + if (down_interruptible (&saa->i2c_sem)) + return -ERESTARTSYS; + do { ret = do_master_xfer (i2c, msgs, num); } while (ret != num && retries--); + up (&saa->i2c_sem); + return ret; } @@ -273,6 +265,8 @@ /* registering functions to load algorithms at runtime */ int i2c_saa7146_add_bus (struct saa7146 *saa) { + init_MUTEX(&saa->i2c_sem); + /* enable i2c-port pins */ saa7146_write (saa->mem, MC1, (MASK_08 | MASK_24)); @@ -389,9 +383,9 @@ struct saa7146_debi_transfer *dt = arg; - printk("saa7146_core.o: SAA7146_DEBI_TRANSFER\n"); - printk("saa7146_core.o: timeout:%d, swap:%d, slave16:%d, increment:%d, intel:%d, tien:%d\n", dt->timeout, dt->swap, dt->slave16, dt->increment, dt->intel, dt->tien); - printk("saa7146_core.o: address:0x%04x, num_bytes:%d, direction:%d, mem:0x%08x\n",dt->address,dt->address,dt->direction,dt->mem); + dprintk("saa7146_core.o: SAA7146_DEBI_TRANSFER\n"); + dprintk("saa7146_core.o: timeout:%d, swap:%d, slave16:%d, increment:%d, intel:%d, tien:%d\n", dt->timeout, dt->swap, dt->slave16, dt->increment, dt->intel, dt->tien); + dprintk("saa7146_core.o: address:0x%04x, num_bytes:%d, direction:%d, mem:0x%08x\n",dt->address,dt->address,dt->direction,dt->mem); debi_transfer(saa, dt); break; @@ -622,7 +616,7 @@ } /* print status message */ - printk(KERN_ERR "saa7146_core.o: %s: bus:%d, rev:%d, mem:0x%08x.\n", saa->name, saa->device->bus->number, saa->revision, (unsigned int) saa->mem); + dprintk("saa7146_core.o: %s: bus:%d, rev:%d, mem:0x%08x.\n", saa->name, saa->device->bus->number, saa->revision, (unsigned int) saa->mem); /* enable bus-mastering */ pci_set_master( saa->device ); @@ -827,7 +821,7 @@ int __devinit saa7146_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) { - struct dvb_adapter_s *adap; + struct dvb_adapter *adap; struct saa7146 *saa; int card_type; struct card_info *cinfo= (struct card_info *) ent->driver_data; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/media/dvb/av7110/saa7146_core.h linux.2.5.47-ac4/drivers/media/dvb/av7110/saa7146_core.h --- linux.2.5.47/drivers/media/dvb/av7110/saa7146_core.h 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/media/dvb/av7110/saa7146_core.h 2002-11-13 01:26:41.000000000 +0000 @@ -1,17 +1,11 @@ #ifndef __SAA7146_CORE__ #define __SAA7146_CORE__ -#include /* definitions of u32 etc. */ -#include "../dvb-core/dvbdev.h" +#include +#include + +#include "dvbdev.h" -#if LINUX_VERSION_CODE < 0x020300 -#define DECLARE_MUTEX(foo) struct semaphore foo = MUTEX -#define DECLARE_MUTEX_LOCKED(foo) struct semaphore foo = MUTEX_LOCKED -#define WAIT_QUEUE struct wait_queue* -#define init_waitqueue_head(wq) *(wq) = NULL; -#else -#define WAIT_QUEUE wait_queue_head_t -#endif /* maximum number of capture frames we support */ #define SAA7146_MAX_BUF 5 @@ -37,12 +31,13 @@ char name[32]; /* give it a nice name */ struct list_head list_head; - - dvb_adapter_t *dvb_adapter; - struct dvb_i2c_bus *i2c_bus; struct pci_dev *device; int card_type; + struct dvb_adapter *dvb_adapter; + struct dvb_i2c_bus *i2c_bus; + struct semaphore i2c_sem; + void* data[SAA7146_MAX_EXTENSIONS]; /* data hooks for extensions */ int (*command) (struct dvb_i2c_bus *i, unsigned int cmd, void *arg); @@ -70,8 +65,8 @@ int grab_format[SAA7146_MAX_BUF]; /* video format of grabs */ int grab_port[SAA7146_MAX_BUF]; /* video port for grab */ - WAIT_QUEUE rps0_wq; /* rps0 interrupt queue (=> capture) */ - WAIT_QUEUE rps1_wq; /* rps1 interrupt queue (=> i2c, ...) */ + wait_queue_head_t rps0_wq; /* rps0 interrupt queue (=> capture) */ + wait_queue_head_t rps1_wq; /* rps1 interrupt queue (=> i2c, ...) */ }; #define SAA7146_IRQ_RPS0 diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/media/dvb/av7110/saa7146_v4l.c linux.2.5.47-ac4/drivers/media/dvb/av7110/saa7146_v4l.c --- linux.2.5.47/drivers/media/dvb/av7110/saa7146_v4l.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/media/dvb/av7110/saa7146_v4l.c 2002-11-13 01:26:41.000000000 +0000 @@ -320,7 +320,6 @@ /* set corresponding buffer to ´unused´ */ saa->frame_stat[i] = GBUFFER_UNUSED; -printk ("saa7146_v4l.o: SAA7146_V4L_CSYNC, frame %i done.\n", i); break; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/media/dvb/dvb-core/dmxdev.c linux.2.5.47-ac4/drivers/media/dvb/dvb-core/dmxdev.c --- linux.2.5.47/drivers/media/dvb/dvb-core/dmxdev.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/media/dvb/dvb-core/dmxdev.c 2002-11-13 01:26:41.000000000 +0000 @@ -24,6 +24,7 @@ #include #include #include +#include #include #include "dmxdev.h" @@ -40,19 +41,19 @@ #define dprintk if (debug) printk inline dmxdev_filter_t * -DmxDevFile2Filter(struct file *file) +dvb_dmxdev_file_to_filter(struct file *file) { return (dmxdev_filter_t *) file->private_data; } inline dmxdev_dvr_t * -DmxDevFile2DVR(dmxdev_t *dmxdev, struct file *file) +dvb_dmxdev_file_to_dvr(dmxdev_t *dmxdev, struct file *file) { return (dmxdev_dvr_t *) file->private_data; } static inline void -DmxDevBufferInit(dmxdev_buffer_t *buffer) +dvb_dmxdev_buffer_init(dmxdev_buffer_t *buffer) { buffer->data=0; buffer->size=8192; @@ -63,7 +64,7 @@ } static inline int -DmxDevBufferWrite(dmxdev_buffer_t *buf, uint8_t *src, int len) +dvb_dmxdev_buffer_write(dmxdev_buffer_t *buf, uint8_t *src, int len) { int split; int free; @@ -98,7 +99,7 @@ } static ssize_t -DmxDevBufferRead(dmxdev_buffer_t *src, int non_blocking, +dvb_dmxdev_buffer_read(dmxdev_buffer_t *src, int non_blocking, char *buf, size_t count, loff_t *ppos) { unsigned long todo=count; @@ -108,6 +109,7 @@ return 0; if ((error=src->error)) { + src->pwrite=src->pread; src->error=0; return error; } @@ -125,6 +127,7 @@ return count-todo; if ((error=src->error)) { + src->pwrite=src->pread; src->error=0; return error; } @@ -172,7 +175,7 @@ } static inline void -DmxDevDVRStateSet(dmxdev_dvr_t *dmxdevdvr, int state) +dvb_dmxdev_dvr_state_set(dmxdev_dvr_t *dmxdevdvr, int state) { spin_lock_irq(&dmxdevdvr->dev->lock); dmxdevdvr->state=state; @@ -181,7 +184,7 @@ static int dvb_dvr_open(struct inode *inode, struct file *file) { - dvb_device_t *dvbdev=(dvb_device_t *) file->private_data; + struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; dmxdev_t *dmxdev=(dmxdev_t *) dvbdev->priv; dmx_frontend_t *front; @@ -198,7 +201,7 @@ } if ((file->f_flags&O_ACCMODE)==O_RDONLY) { - DmxDevBufferInit(&dmxdev->dvr_buffer); + dvb_dmxdev_buffer_init(&dmxdev->dvr_buffer); dmxdev->dvr_buffer.size=DVR_BUFFER_SIZE; dmxdev->dvr_buffer.data=vmalloc(DVR_BUFFER_SIZE); if (!dmxdev->dvr_buffer.data) { @@ -230,7 +233,7 @@ static int dvb_dvr_release(struct inode *inode, struct file *file) { - dvb_device_t *dvbdev=(dvb_device_t *) file->private_data; + struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; dmxdev_t *dmxdev=(dmxdev_t *) dvbdev->priv; if (down_interruptible (&dmxdev->mutex)) @@ -258,7 +261,7 @@ static ssize_t dvb_dvr_write(struct file *file, const char *buf, size_t count, loff_t *ppos) { - dvb_device_t *dvbdev=(dvb_device_t *) file->private_data; + struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; dmxdev_t *dmxdev=(dmxdev_t *) dvbdev->priv; int ret; @@ -276,12 +279,12 @@ static ssize_t dvb_dvr_read(struct file *file, char *buf, size_t count, loff_t *ppos) { - dvb_device_t *dvbdev=(dvb_device_t *) file->private_data; + struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; dmxdev_t *dmxdev=(dmxdev_t *) dvbdev->priv; int ret; //down(&dmxdev->mutex); - ret= DmxDevBufferRead(&dmxdev->dvr_buffer, + ret= dvb_dmxdev_buffer_read(&dmxdev->dvr_buffer, file->f_flags&O_NONBLOCK, buf, count, ppos); //up(&dmxdev->mutex); @@ -289,7 +292,7 @@ } static inline void -DmxDevFilterStateSet(dmxdev_filter_t *dmxdevfilter, int state) +dvb_dmxdev_filter_state_set(dmxdev_filter_t *dmxdevfilter, int state) { spin_lock_irq(&dmxdevfilter->dev->lock); dmxdevfilter->state=state; @@ -297,7 +300,7 @@ } static int -DmxDevSetBufferSize(dmxdev_filter_t *dmxdevfilter, unsigned long size) +dvb_dmxdev_set_buffer_size(dmxdev_filter_t *dmxdevfilter, unsigned long size) { dmxdev_buffer_t *buf=&dmxdevfilter->buffer; void *mem; @@ -327,7 +330,7 @@ } static void -DmxDevFilterTimeout(unsigned long data) +dvb_dmxdev_filter_timeout(unsigned long data) { dmxdev_filter_t *dmxdevfilter=(dmxdev_filter_t *)data; @@ -339,13 +342,13 @@ } static void -DmxDevFilterTimer(dmxdev_filter_t *dmxdevfilter) +dvb_dmxdev_filter_timer(dmxdev_filter_t *dmxdevfilter) { struct dmx_sct_filter_params *para=&dmxdevfilter->params.sec; del_timer(&dmxdevfilter->timer); if (para->timeout) { - dmxdevfilter->timer.function=DmxDevFilterTimeout; + dmxdevfilter->timer.function=dvb_dmxdev_filter_timeout; dmxdevfilter->timer.data=(unsigned long) dmxdevfilter; dmxdevfilter->timer.expires=jiffies+1+(HZ/2+HZ*para->timeout)/1000; add_timer(&dmxdevfilter->timer); @@ -353,7 +356,7 @@ } static int -DmxDevSectionCallback(u8 *buffer1, size_t buffer1_len, +dvb_dmxdev_section_callback(u8 *buffer1, size_t buffer1_len, u8 *buffer2, size_t buffer2_len, dmx_section_filter_t *filter, dmx_success_t success) @@ -375,9 +378,9 @@ buffer1[0], buffer1[1], buffer1[2], buffer1[3], buffer1[4], buffer1[5]); - ret=DmxDevBufferWrite(&dmxdevfilter->buffer, buffer1, buffer1_len); + ret=dvb_dmxdev_buffer_write(&dmxdevfilter->buffer, buffer1, buffer1_len); if (ret==buffer1_len) { - ret=DmxDevBufferWrite(&dmxdevfilter->buffer, buffer2, buffer2_len); + ret=dvb_dmxdev_buffer_write(&dmxdevfilter->buffer, buffer2, buffer2_len); } if (ret<0) { dmxdevfilter->buffer.pwrite=dmxdevfilter->buffer.pread; @@ -391,7 +394,7 @@ } static int -DmxDevTSCallback(u8 *buffer1, size_t buffer1_len, +dvb_dmxdev_ts_callback(u8 *buffer1, size_t buffer1_len, u8 *buffer2, size_t buffer2_len, dmx_ts_feed_t *feed, dmx_success_t success) @@ -415,9 +418,9 @@ wake_up(&buffer->queue); return 0; } - ret=DmxDevBufferWrite(buffer, buffer1, buffer1_len); + ret=dvb_dmxdev_buffer_write(buffer, buffer1, buffer1_len); if (ret==buffer1_len) - ret=DmxDevBufferWrite(buffer, buffer2, buffer2_len); + ret=dvb_dmxdev_buffer_write(buffer, buffer2, buffer2_len); if (ret<0) { buffer->pwrite=buffer->pread; buffer->error=-EOVERFLOW; @@ -431,9 +434,9 @@ /* stop feed but only mark the specified filter as stopped (state set) */ static int -DmxDevFeedStop(dmxdev_filter_t *dmxdevfilter) +dvb_dmxdev_feed_stop(dmxdev_filter_t *dmxdevfilter) { - DmxDevFilterStateSet(dmxdevfilter, DMXDEV_STATE_SET); + dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_SET); switch (dmxdevfilter->type) { case DMXDEV_TYPE_SEC: @@ -453,9 +456,9 @@ /* start feed associated with the specified filter */ static int -DmxDevFeedStart(dmxdev_filter_t *dmxdevfilter) +dvb_dmxdev_feed_start(dmxdev_filter_t *dmxdevfilter) { - DmxDevFilterStateSet(dmxdevfilter, DMXDEV_STATE_GO); + dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_GO); switch (dmxdevfilter->type) { case DMXDEV_TYPE_SEC: @@ -475,7 +478,7 @@ otherwise release the feed */ static int -DmxDevFeedRestart(dmxdev_filter_t *dmxdevfilter) +dvb_dmxdev_feed_restart(dmxdev_filter_t *dmxdevfilter) { int i; dmxdev_t *dmxdev=dmxdevfilter->dev; @@ -485,7 +488,7 @@ if (dmxdev->filter[i].state>=DMXDEV_STATE_GO && dmxdev->filter[i].type==DMXDEV_TYPE_SEC && dmxdev->filter[i].pid==pid) { - DmxDevFeedStart(&dmxdev->filter[i]); + dvb_dmxdev_feed_start(&dmxdev->filter[i]); return 0; } @@ -497,7 +500,7 @@ } static int -DmxDevFilterStop(dmxdev_filter_t *dmxdevfilter) +dvb_dmxdev_filter_stop(dmxdev_filter_t *dmxdevfilter) { if (dmxdevfilter->statefeed.sec) break; - DmxDevFeedStop(dmxdevfilter); + dvb_dmxdev_feed_stop(dmxdevfilter); if (dmxdevfilter->filter.sec) dmxdevfilter->feed.sec-> release_filter(dmxdevfilter->feed.sec, dmxdevfilter->filter.sec); - DmxDevFeedRestart(dmxdevfilter); + dvb_dmxdev_feed_restart(dmxdevfilter); dmxdevfilter->feed.sec=0; break; case DMXDEV_TYPE_PES: if (!dmxdevfilter->feed.ts) break; - DmxDevFeedStop(dmxdevfilter); + dvb_dmxdev_feed_stop(dmxdevfilter); dmxdevfilter->dev->demux-> release_ts_feed(dmxdevfilter->dev->demux, dmxdevfilter->feed.ts); @@ -533,19 +536,19 @@ } static inline int -DmxDevFilterReset(dmxdev_filter_t *dmxdevfilter) +dvb_dmxdev_filter_reset(dmxdev_filter_t *dmxdevfilter) { if (dmxdevfilter->statetype=DMXDEV_TYPE_NONE; dmxdevfilter->pid=0xffff; - DmxDevFilterStateSet(dmxdevfilter, DMXDEV_STATE_ALLOCATED); + dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_ALLOCATED); return 0; } static int -DmxDevFilterStart(dmxdev_filter_t *dmxdevfilter) +dvb_dmxdev_filter_start(dmxdev_filter_t *dmxdevfilter) { dmxdev_t *dmxdev=dmxdevfilter->dev; void *mem; @@ -554,7 +557,7 @@ if (dmxdevfilter->statestate>=DMXDEV_STATE_GO) - DmxDevFilterStop(dmxdevfilter); + dvb_dmxdev_filter_stop(dmxdevfilter); mem=dmxdevfilter->buffer.data; if (!mem) { @@ -566,6 +569,8 @@ return -ENOMEM; } + dmxdevfilter->buffer.pwrite=dmxdevfilter->buffer.pread=0; + switch (dmxdevfilter->type) { case DMXDEV_TYPE_SEC: { @@ -588,10 +593,9 @@ /* if no feed found, try to allocate new one */ if (!*secfeed) { - ret=dmxdev->demux-> - allocate_section_feed(dmxdev->demux, + ret=dmxdev->demux->allocate_section_feed(dmxdev->demux, secfeed, - DmxDevSectionCallback); + dvb_dmxdev_section_callback); if (ret<0) { printk ("DVB (%s): could not alloc feed\n", __FUNCTION__); @@ -604,18 +608,17 @@ if (ret<0) { printk ("DVB (%s): could not set feed\n", __FUNCTION__); - DmxDevFeedRestart(dmxdevfilter); + dvb_dmxdev_feed_restart(dmxdevfilter); return ret; } } else - DmxDevFeedStop(dmxdevfilter); + dvb_dmxdev_feed_stop(dmxdevfilter); ret=(*secfeed)->allocate_filter(*secfeed, secfilter); if (ret<0) { - DmxDevFeedRestart(dmxdevfilter); - dmxdevfilter->feed.sec-> - start_filtering(*secfeed); + dvb_dmxdev_feed_restart(dmxdevfilter); + dmxdevfilter->feed.sec->start_filtering(*secfeed); dprintk ("could not get filter\n"); return ret; } @@ -636,15 +639,14 @@ (*secfilter)->filter_mask[2]=0; dmxdevfilter->todo=0; - dmxdevfilter->feed.sec-> - start_filtering(dmxdevfilter->feed.sec); - DmxDevFilterTimer(dmxdevfilter); + dmxdevfilter->feed.sec->start_filtering(dmxdevfilter->feed.sec); + dvb_dmxdev_filter_timer(dmxdevfilter); break; } case DMXDEV_TYPE_PES: { - struct timespec timeout = {0 }; + struct timespec timeout = { 0 }; struct dmx_pes_filter_params *para=&dmxdevfilter->params.pes; dmx_output_t otype; int ret; @@ -670,31 +672,29 @@ ret=dmxdev->demux->allocate_ts_feed(dmxdev->demux, tsfeed, - DmxDevTSCallback); + dvb_dmxdev_ts_callback); if (ret<0) return ret; (*tsfeed)->priv=(void *) dmxdevfilter; ret=(*tsfeed)->set(*tsfeed, para->pid, ts_type, ts_pes, 188, 32768, 0, timeout); if (ret<0) { - dmxdev->demux-> - release_ts_feed(dmxdev->demux, *tsfeed); + dmxdev->demux->release_ts_feed(dmxdev->demux, *tsfeed); return ret; } - dmxdevfilter->feed.ts-> - start_filtering(dmxdevfilter->feed.ts); + dmxdevfilter->feed.ts->start_filtering(dmxdevfilter->feed.ts); break; } default: return -EINVAL; } - DmxDevFilterStateSet(dmxdevfilter, DMXDEV_STATE_GO); + dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_GO); return 0; } static int dvb_demux_open(struct inode *inode, struct file *file) { - dvb_device_t *dvbdev=(dvb_device_t *) file->private_data; + struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; dmxdev_t *dmxdev=(dmxdev_t *) dvbdev->priv; int i; dmxdev_filter_t *dmxdevfilter; @@ -714,9 +714,9 @@ dmxdevfilter->dvbdev=dmxdev->dvbdev; file->private_data=dmxdevfilter; - DmxDevBufferInit(&dmxdevfilter->buffer); + dvb_dmxdev_buffer_init(&dmxdevfilter->buffer); dmxdevfilter->type=DMXDEV_TYPE_NONE; - DmxDevFilterStateSet(dmxdevfilter, DMXDEV_STATE_ALLOCATED); + dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_ALLOCATED); dmxdevfilter->feed.ts=0; init_timer(&dmxdevfilter->timer); @@ -725,13 +725,13 @@ } int -DmxDevFilterFree(dmxdev_t *dmxdev, dmxdev_filter_t *dmxdevfilter) +dvb_dmxdev_filter_free(dmxdev_t *dmxdev, dmxdev_filter_t *dmxdevfilter) { if (down_interruptible(&dmxdev->mutex)) return -ERESTARTSYS; - DmxDevFilterStop(dmxdevfilter); - DmxDevFilterReset(dmxdevfilter); + dvb_dmxdev_filter_stop(dmxdevfilter); + dvb_dmxdev_filter_reset(dmxdevfilter); if (dmxdevfilter->buffer.data) { void *mem=dmxdevfilter->buffer.data; @@ -741,7 +741,7 @@ spin_unlock_irq(&dmxdev->lock); vfree(mem); } - DmxDevFilterStateSet(dmxdevfilter, DMXDEV_STATE_FREE); + dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_FREE); wake_up(&dmxdevfilter->buffer.queue); up(&dmxdev->mutex); return 0; @@ -758,33 +758,33 @@ static int -DmxDevFilterSet(dmxdev_t *dmxdev, +dvb_dmxdev_filter_set(dmxdev_t *dmxdev, dmxdev_filter_t *dmxdevfilter, struct dmx_sct_filter_params *params) { dprintk ("function : %s\n", __FUNCTION__); - DmxDevFilterStop(dmxdevfilter); + dvb_dmxdev_filter_stop(dmxdevfilter); dmxdevfilter->type=DMXDEV_TYPE_SEC; dmxdevfilter->pid=params->pid; memcpy(&dmxdevfilter->params.sec, params, sizeof(struct dmx_sct_filter_params)); invert_mode(&dmxdevfilter->params.sec.filter); - DmxDevFilterStateSet(dmxdevfilter, DMXDEV_STATE_SET); + dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_SET); if (params->flags&DMX_IMMEDIATE_START) - return DmxDevFilterStart(dmxdevfilter); + return dvb_dmxdev_filter_start(dmxdevfilter); return 0; } static int -DmxDevPesFilterSet(dmxdev_t *dmxdev, +dvb_dmxdev_pes_filter_set(dmxdev_t *dmxdev, dmxdev_filter_t *dmxdevfilter, struct dmx_pes_filter_params *params) { - DmxDevFilterStop(dmxdevfilter); + dvb_dmxdev_filter_stop(dmxdevfilter); if (params->pes_type>DMX_PES_OTHER || params->pes_type<0) return -EINVAL; @@ -793,16 +793,16 @@ dmxdevfilter->pid=params->pid; memcpy(&dmxdevfilter->params, params, sizeof(struct dmx_pes_filter_params)); - DmxDevFilterStateSet(dmxdevfilter, DMXDEV_STATE_SET); + dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_SET); if (params->flags&DMX_IMMEDIATE_START) - return DmxDevFilterStart(dmxdevfilter); + return dvb_dmxdev_filter_start(dmxdevfilter); return 0; } static ssize_t -DmxDevReadSec(dmxdev_filter_t *dfil, struct file *file, +dvb_dmxdev_read_sec(dmxdev_filter_t *dfil, struct file *file, char *buf, size_t count, loff_t *ppos) { int result, hcount; @@ -812,7 +812,7 @@ hcount=3+dfil->todo; if (hcount>count) hcount=count; - result=DmxDevBufferRead(&dfil->buffer, file->f_flags&O_NONBLOCK, + result=dvb_dmxdev_buffer_read(&dfil->buffer, file->f_flags&O_NONBLOCK, buf, hcount, ppos); if (result<0) { dfil->todo=0; @@ -832,7 +832,7 @@ } if (count>dfil->todo) count=dfil->todo; - result=DmxDevBufferRead(&dfil->buffer, file->f_flags&O_NONBLOCK, + result=dvb_dmxdev_buffer_read(&dfil->buffer, file->f_flags&O_NONBLOCK, buf, count, ppos); if (result<0) return result; @@ -844,16 +844,16 @@ ssize_t dvb_demux_read(struct file *file, char *buf, size_t count, loff_t *ppos) { - dmxdev_filter_t *dmxdevfilter=DmxDevFile2Filter(file); + dmxdev_filter_t *dmxdevfilter=dvb_dmxdev_file_to_filter(file); //dmxdev_t *dmxdev=dmxdevfilter->dev; int ret=0; // semaphore should not be necessary (I hope ...) //down(&dmxdev->mutex); if (dmxdevfilter->type==DMXDEV_TYPE_SEC) - ret=DmxDevReadSec(dmxdevfilter, file, buf, count, ppos); + ret=dvb_dmxdev_read_sec(dmxdevfilter, file, buf, count, ppos); else - ret=DmxDevBufferRead(&dmxdevfilter->buffer, + ret=dvb_dmxdev_buffer_read(&dmxdevfilter->buffer, file->f_flags&O_NONBLOCK, buf, count, ppos); //up(&dmxdev->mutex); @@ -864,7 +864,7 @@ static int dvb_demux_do_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *parg) { - dmxdev_filter_t *dmxdevfilter=DmxDevFile2Filter(file); + dmxdev_filter_t *dmxdevfilter=dvb_dmxdev_file_to_filter(file); dmxdev_t *dmxdev=dmxdevfilter->dev; unsigned long arg=(unsigned long) parg; int ret=0; @@ -877,25 +877,25 @@ if (dmxdevfilter->statedev; - return DmxDevFilterFree(dmxdev, dmxdevfilter); + return dvb_dmxdev_filter_free(dmxdev, dmxdevfilter); } static struct file_operations dvb_demux_fops = { - owner: THIS_MODULE, - read: dvb_demux_read, - write: 0, - ioctl: dvb_demux_ioctl, - open: dvb_demux_open, - release: dvb_demux_release, - poll: dvb_demux_poll, + .owner = THIS_MODULE, + .read = dvb_demux_read, + .ioctl = dvb_demux_ioctl, + .open = dvb_demux_open, + .release = dvb_demux_release, + .poll = dvb_demux_poll, }; -static dvb_device_t dvbdev_demux = { - priv: 0, - users: 1, - writers: 1, - fops: &dvb_demux_fops +static struct dvb_device dvbdev_demux = { + .priv = 0, + .users = 1, + .writers = 1, + .fops = &dvb_demux_fops }; static int dvb_dvr_do_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *parg) { - dvb_device_t *dvbdev=(dvb_device_t *) file->private_data; + struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; dmxdev_t *dmxdev=(dmxdev_t *) dvbdev->priv; int ret=0; @@ -1008,13 +1007,13 @@ static int dvb_dvr_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - return generic_usercopy(inode, file, cmd, arg, dvb_dvr_do_ioctl); + return video_usercopy(inode, file, cmd, arg, dvb_dvr_do_ioctl); } static unsigned int dvb_dvr_poll(struct file *file, poll_table *wait) { - dvb_device_t *dvbdev=(dvb_device_t *) file->private_data; + struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; dmxdev_t *dmxdev=(dmxdev_t *) dvbdev->priv; dprintk ("function : %s\n", __FUNCTION__); @@ -1040,24 +1039,24 @@ } static struct file_operations dvb_dvr_fops = { - owner: THIS_MODULE, - read: dvb_dvr_read, - write: dvb_dvr_write, - ioctl: dvb_dvr_ioctl, - open: dvb_dvr_open, - release: dvb_dvr_release, - poll: dvb_dvr_poll, + .owner = THIS_MODULE, + .read = dvb_dvr_read, + .write = dvb_dvr_write, + .ioctl = dvb_dvr_ioctl, + .open = dvb_dvr_open, + .release = dvb_dvr_release, + .poll =dvb_dvr_poll, }; -static dvb_device_t dvbdev_dvr = { - priv: 0, - users: 1, - writers: 1, - fops: &dvb_dvr_fops +static struct dvb_device dvbdev_dvr = { + .priv = 0, + .users = 1, + .writers = 1, + .fops = &dvb_dvr_fops }; int -DmxDevInit(dmxdev_t *dmxdev, dvb_adapter_t *dvb_adapter) +dvb_dmxdev_init(dmxdev_t *dmxdev, struct dvb_adapter *dvb_adapter) { int i; @@ -1079,22 +1078,22 @@ for (i=0; ifilternum; i++) { dmxdev->filter[i].dev=dmxdev; dmxdev->filter[i].buffer.data=0; - DmxDevFilterStateSet(&dmxdev->filter[i], DMXDEV_STATE_FREE); + dvb_dmxdev_filter_state_set(&dmxdev->filter[i], DMXDEV_STATE_FREE); dmxdev->dvr[i].dev=dmxdev; dmxdev->dvr[i].buffer.data=0; - DmxDevFilterStateSet(&dmxdev->filter[i], DMXDEV_STATE_FREE); - DmxDevDVRStateSet(&dmxdev->dvr[i], DMXDEV_STATE_FREE); + dvb_dmxdev_filter_state_set(&dmxdev->filter[i], DMXDEV_STATE_FREE); + dvb_dmxdev_dvr_state_set(&dmxdev->dvr[i], DMXDEV_STATE_FREE); } dvb_register_device(dvb_adapter, &dmxdev->dvbdev, &dvbdev_demux, dmxdev, DVB_DEVICE_DEMUX); dvb_register_device(dvb_adapter, &dmxdev->dvr_dvbdev, &dvbdev_dvr, dmxdev, DVB_DEVICE_DVR); - DmxDevBufferInit(&dmxdev->dvr_buffer); + dvb_dmxdev_buffer_init(&dmxdev->dvr_buffer); MOD_INC_USE_COUNT; return 0; } void -DmxDevRelease(dmxdev_t *dmxdev) +dvb_dmxdev_release(dmxdev_t *dmxdev) { dvb_unregister_device(dmxdev->dvbdev); dvb_unregister_device(dmxdev->dvr_dvbdev); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/media/dvb/dvb-core/dmxdev.h linux.2.5.47-ac4/drivers/media/dvb/dvb-core/dmxdev.h --- linux.2.5.47/drivers/media/dvb/dvb-core/dmxdev.h 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/media/dvb/dvb-core/dmxdev.h 2002-11-13 01:26:41.000000000 +0000 @@ -64,7 +64,7 @@ typedef struct dmxdev_filter_s { - dvb_device_t *dvbdev; + struct dvb_device *dvbdev; union { dmx_section_filter_t *sec; @@ -102,8 +102,8 @@ typedef struct dmxdev_s { - dvb_device_t *dvbdev; - dvb_device_t *dvr_dvbdev; + struct dvb_device *dvbdev; + struct dvb_device *dvr_dvbdev; dmxdev_filter_t *filter; dmxdev_dvr_t *dvr; @@ -122,7 +122,7 @@ } dmxdev_t; -int DmxDevInit(dmxdev_t *dmxdev, dvb_adapter_t *); -void DmxDevRelease(dmxdev_t *dmxdev); +int dvb_dmxdev_init(dmxdev_t *dmxdev, struct dvb_adapter *); +void dvb_dmxdev_release(dmxdev_t *dmxdev); #endif /* _DMXDEV_H_ */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/media/dvb/dvb-core/dvb_demux.c linux.2.5.47-ac4/drivers/media/dvb/dvb-core/dvb_demux.c --- linux.2.5.47/drivers/media/dvb/dvb-core/dvb_demux.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/media/dvb/dvb-core/dvb_demux.c 2002-11-13 01:26:41.000000000 +0000 @@ -182,7 +182,7 @@ ******************************************************************************/ static inline int -DvbDmxSWFilterPayload(dvb_demux_feed_t *dvbdmxfeed, const u8 *buf) +dvb_dmx_swfilter_payload(struct dvb_demux_feed *dvbdmxfeed, const u8 *buf) { int p, count; //int ccok; @@ -208,8 +208,8 @@ static int -DvbDmxSWFilterSectionFilter(dvb_demux_feed_t *dvbdmxfeed, - dvb_demux_filter_t *f) +dvb_dmx_swfilter_sectionfilter(struct dvb_demux_feed *dvbdmxfeed, + struct dvb_demux_filter *f) { dmx_section_filter_t *filter=&f->filter; int i; @@ -229,10 +229,10 @@ } static inline int -DvbDmxSWFilterSectionFeed(dvb_demux_feed_t *dvbdmxfeed) +dvb_dmx_swfilter_section_feed(struct dvb_demux_feed *dvbdmxfeed) { u8 *buf=dvbdmxfeed->secbuf; - dvb_demux_filter_t *f; + struct dvb_demux_filter *f; if (dvbdmxfeed->secbufp!=dvbdmxfeed->seclen) return -1; @@ -241,7 +241,7 @@ if (!(f=dvbdmxfeed->filter)) return 0; do - if (DvbDmxSWFilterSectionFilter(dvbdmxfeed, f)<0) + if (dvb_dmx_swfilter_sectionfilter(dvbdmxfeed, f)<0) return -1; while ((f=f->next) && dvbdmxfeed->feed.sec.is_filtering); @@ -251,7 +251,7 @@ } static inline int -DvbDmxSWFilterSectionPacket(dvb_demux_feed_t *dvbdmxfeed, const u8 *buf) +dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *dvbdmxfeed, const u8 *buf) { int p, count; int ccok, rest; @@ -286,7 +286,7 @@ memcpy(dvbdmxfeed->secbuf+dvbdmxfeed->secbufp, buf+p+1, buf[p]); dvbdmxfeed->secbufp+=buf[p]; - DvbDmxSWFilterSectionFeed(dvbdmxfeed); + dvb_dmx_swfilter_section_feed(dvbdmxfeed); } } p+=buf[p]+1; // skip rest of last section @@ -301,7 +301,7 @@ dvbdmxfeed->secbufp=dvbdmxfeed->seclen; p+=dvbdmxfeed->seclen; count=188-p; - DvbDmxSWFilterSectionFeed(dvbdmxfeed); + dvb_dmx_swfilter_section_feed(dvbdmxfeed); // filling bytes until packet end? if (count && buf[p]==0xff) @@ -337,7 +337,7 @@ if (rest<=count) { // section completed in this TS packet memcpy(dvbdmxfeed->secbuf+dvbdmxfeed->secbufp, buf+p, rest); dvbdmxfeed->secbufp+=rest; - DvbDmxSWFilterSectionFeed(dvbdmxfeed); + dvb_dmx_swfilter_section_feed(dvbdmxfeed); } else { // section continues in following ts packet memcpy(dvbdmxfeed->secbuf+dvbdmxfeed->secbufp, buf+p, count); dvbdmxfeed->secbufp+=count; @@ -346,7 +346,7 @@ } static inline void -DvbDmxSWFilterPacketType(dvb_demux_feed_t *dvbdmxfeed, const u8 *buf) +dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *dvbdmxfeed, const u8 *buf) { switch(dvbdmxfeed->type) { case DMX_TYPE_TS: @@ -354,7 +354,7 @@ break; if (dvbdmxfeed->ts_type & TS_PACKET) { if (dvbdmxfeed->ts_type & TS_PAYLOAD_ONLY) - DvbDmxSWFilterPayload(dvbdmxfeed, buf); + dvb_dmx_swfilter_payload(dvbdmxfeed, buf); else dvbdmxfeed->cb.ts((u8 *)buf, 188, 0, 0, &dvbdmxfeed->feed.ts, DMX_OK); @@ -368,7 +368,7 @@ case DMX_TYPE_SEC: if (!dvbdmxfeed->feed.sec.is_filtering) break; - if (DvbDmxSWFilterSectionPacket(dvbdmxfeed, buf)<0) + if (dvb_dmx_swfilter_section_packet(dvbdmxfeed, buf)<0) dvbdmxfeed->seclen=dvbdmxfeed->secbufp=0; break; @@ -377,27 +377,27 @@ } } -void inline -DvbDmxSWFilterPacket(dvb_demux_t *dvbdmx, const u8 *buf) +void +dvb_dmx_swfilter_packet(struct dvb_demux *dvbdmx, const u8 *buf) { - dvb_demux_feed_t *dvbdmxfeed; + struct dvb_demux_feed *dvbdmxfeed; if (!(dvbdmxfeed=dvbdmx->pid2feed[ts_pid(buf)])) return; - DvbDmxSWFilterPacketType(dvbdmxfeed, buf); + dvb_dmx_swfilter_packet_type(dvbdmxfeed, buf); } void -DvbDmxSWFilterPackets(dvb_demux_t *dvbdmx, const u8 *buf, int count) +dvb_dmx_swfilter_packets(struct dvb_demux *dvbdmx, const u8 *buf, int count) { - dvb_demux_feed_t *dvbdmxfeed; + struct dvb_demux_feed *dvbdmxfeed; spin_lock(&dvbdmx->lock); if ((dvbdmxfeed=dvbdmx->pid2feed[0x2000])) dvbdmxfeed->cb.ts((u8 *)buf, count*188, 0, 0, &dvbdmxfeed->feed.ts, DMX_OK); while (count) { - DvbDmxSWFilterPacket(dvbdmx, buf); + dvb_dmx_swfilter_packet(dvbdmx, buf); count--; buf+=188; } @@ -405,7 +405,7 @@ } static inline void -DvbDmxSWFilter(dvb_demux_t *dvbdmx, const u8 *buf, size_t count) +dvb_dmx_swfilter(struct dvb_demux *dvbdmx, const u8 *buf, size_t count) { int p=0,i, j; @@ -416,7 +416,7 @@ return; } memcpy(&dvbdmx->tsbuf[i], buf, j); - DvbDmxSWFilterPacket(dvbdmx, dvbdmx->tsbuf); + dvb_dmx_swfilter_packet(dvbdmx, dvbdmx->tsbuf); dvbdmx->tsbufp=0; p+=j; } @@ -424,7 +424,7 @@ while (p=188) { - DvbDmxSWFilterPacket(dvbdmx, buf+p); + dvb_dmx_swfilter_packet(dvbdmx, buf+p); p+=188; } else { i=count-p; @@ -444,8 +444,8 @@ ****************************************************************************** ******************************************************************************/ -static dvb_demux_filter_t * -DvbDmxFilterAlloc(dvb_demux_t *dvbdmx) +static struct dvb_demux_filter * +dvb_dmx_filter_alloc(struct dvb_demux *dvbdmx) { int i; @@ -458,8 +458,8 @@ return &dvbdmx->filter[i]; } -static dvb_demux_feed_t * -DvbDmxFeedAlloc(dvb_demux_t *dvbdmx) +static struct dvb_demux_feed * +dvb_dmx_feed_alloc(struct dvb_demux *dvbdmx) { int i; @@ -478,10 +478,10 @@ ******************************************************************************/ static int -dmx_pid_set(u16 pid, dvb_demux_feed_t *dvbdmxfeed) +dmx_pid_set(u16 pid, struct dvb_demux_feed *dvbdmxfeed) { - dvb_demux_t *dvbdmx=dvbdmxfeed->demux; - dvb_demux_feed_t **pid2feed=dvbdmx->pid2feed; + struct dvb_demux *dvbdmx=dvbdmxfeed->demux; + struct dvb_demux_feed **pid2feed=dvbdmx->pid2feed; if (pid>DMX_MAX_PID) return -EINVAL; @@ -510,8 +510,8 @@ struct timespec timeout ) { - dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed; - dvb_demux_t *dvbdmx=dvbdmxfeed->demux; + struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) feed; + struct dvb_demux *dvbdmx=dvbdmxfeed->demux; int ret; if (down_interruptible (&dvbdmx->mutex)) @@ -576,8 +576,8 @@ static int dmx_ts_feed_start_filtering(struct dmx_ts_feed_s* feed) { - dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed; - dvb_demux_t *dvbdmx=dvbdmxfeed->demux; + struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) feed; + struct dvb_demux *dvbdmx=dvbdmxfeed->demux; int ret; if (down_interruptible (&dvbdmx->mutex)) @@ -608,8 +608,8 @@ static int dmx_ts_feed_stop_filtering(struct dmx_ts_feed_s* feed) { - dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed; - dvb_demux_t *dvbdmx=dvbdmxfeed->demux; + struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) feed; + struct dvb_demux *dvbdmx=dvbdmxfeed->demux; int ret; if (down_interruptible (&dvbdmx->mutex)) @@ -637,13 +637,13 @@ dmx_ts_feed_t **feed, dmx_ts_cb callback) { - dvb_demux_t *dvbdmx=(dvb_demux_t *) demux; - dvb_demux_feed_t *dvbdmxfeed; + struct dvb_demux *dvbdmx=(struct dvb_demux *) demux; + struct dvb_demux_feed *dvbdmxfeed; if (down_interruptible (&dvbdmx->mutex)) return -ERESTARTSYS; - if (!(dvbdmxfeed=DvbDmxFeedAlloc(dvbdmx))) { + if (!(dvbdmxfeed=dvb_dmx_feed_alloc(dvbdmx))) { up(&dvbdmx->mutex); return -EBUSY; } @@ -663,7 +663,7 @@ (*feed)->stop_filtering=dmx_ts_feed_stop_filtering; - if (!(dvbdmxfeed->filter=DvbDmxFilterAlloc(dvbdmx))) { + if (!(dvbdmxfeed->filter=dvb_dmx_filter_alloc(dvbdmx))) { dvbdmxfeed->state=DMX_STATE_FREE; up(&dvbdmx->mutex); return -EBUSY; @@ -679,8 +679,8 @@ static int dvbdmx_release_ts_feed(dmx_demux_t *demux, dmx_ts_feed_t *feed) { - dvb_demux_t *dvbdmx=(dvb_demux_t *) demux; - dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed; + struct dvb_demux *dvbdmx=(struct dvb_demux *) demux; + struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) feed; if (down_interruptible (&dvbdmx->mutex)) return -ERESTARTSYS; @@ -715,14 +715,14 @@ dmx_section_feed_allocate_filter(struct dmx_section_feed_s* feed, dmx_section_filter_t** filter) { - dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed; - dvb_demux_t *dvbdemux=dvbdmxfeed->demux; - dvb_demux_filter_t *dvbdmxfilter; + struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) feed; + struct dvb_demux *dvbdemux=dvbdmxfeed->demux; + struct dvb_demux_filter *dvbdmxfilter; if (down_interruptible (&dvbdemux->mutex)) return -ERESTARTSYS; - dvbdmxfilter=DvbDmxFilterAlloc(dvbdemux); + dvbdmxfilter=dvb_dmx_filter_alloc(dvbdemux); if (!dvbdmxfilter) { up(&dvbdemux->mutex); return -ENOSPC; @@ -747,8 +747,8 @@ u16 pid, size_t circular_buffer_size, int descramble, int check_crc) { - dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed; - dvb_demux_t *dvbdmx=dvbdmxfeed->demux; + struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) feed; + struct dvb_demux *dvbdmx=dvbdmxfeed->demux; if (pid>0x1fff) return -EINVAL; @@ -789,11 +789,11 @@ return 0; } -static void prepare_secfilters(dvb_demux_feed_t *dvbdmxfeed) +static void prepare_secfilters(struct dvb_demux_feed *dvbdmxfeed) { int i; dmx_section_filter_t *sf; - dvb_demux_filter_t *f; + struct dvb_demux_filter *f; u8 mask, mode, doneq; if (!(f=dvbdmxfeed->filter)) @@ -815,8 +815,8 @@ static int dmx_section_feed_start_filtering(dmx_section_feed_t *feed) { - dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed; - dvb_demux_t *dvbdmx=dvbdmxfeed->demux; + struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) feed; + struct dvb_demux *dvbdmx=dvbdmxfeed->demux; int ret; if (down_interruptible (&dvbdmx->mutex)) @@ -854,8 +854,8 @@ static int dmx_section_feed_stop_filtering(struct dmx_section_feed_s* feed) { - dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed; - dvb_demux_t *dvbdmx=dvbdmxfeed->demux; + struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) feed; + struct dvb_demux *dvbdmx=dvbdmxfeed->demux; int ret; if (down_interruptible (&dvbdmx->mutex)) @@ -878,9 +878,9 @@ dmx_section_feed_release_filter(dmx_section_feed_t *feed, dmx_section_filter_t* filter) { - dvb_demux_filter_t *dvbdmxfilter=(dvb_demux_filter_t *) filter, *f; - dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed; - dvb_demux_t *dvbdmx=dvbdmxfeed->demux; + struct dvb_demux_filter *dvbdmxfilter=(struct dvb_demux_filter *) filter, *f; + struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) feed; + struct dvb_demux *dvbdmx=dvbdmxfeed->demux; if (down_interruptible (&dvbdmx->mutex)) return -ERESTARTSYS; @@ -911,13 +911,13 @@ dmx_section_feed_t **feed, dmx_section_cb callback) { - dvb_demux_t *dvbdmx=(dvb_demux_t *) demux; - dvb_demux_feed_t *dvbdmxfeed; + struct dvb_demux *dvbdmx=(struct dvb_demux *) demux; + struct dvb_demux_feed *dvbdmxfeed; if (down_interruptible (&dvbdmx->mutex)) return -ERESTARTSYS; - if (!(dvbdmxfeed=DvbDmxFeedAlloc(dvbdmx))) { + if (!(dvbdmxfeed=dvb_dmx_feed_alloc(dvbdmx))) { up(&dvbdmx->mutex); return -EBUSY; } @@ -946,8 +946,8 @@ static int dvbdmx_release_section_feed(dmx_demux_t *demux, dmx_section_feed_t *feed) { - dvb_demux_feed_t *dvbdmxfeed=(dvb_demux_feed_t *) feed; - dvb_demux_t *dvbdmx=(dvb_demux_t *) demux; + struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) feed; + struct dvb_demux *dvbdmx=(struct dvb_demux *) demux; if (down_interruptible (&dvbdmx->mutex)) return -ERESTARTSYS; @@ -977,7 +977,7 @@ static int dvbdmx_open(dmx_demux_t *demux) { - dvb_demux_t *dvbdemux=(dvb_demux_t *) demux; + struct dvb_demux *dvbdemux=(struct dvb_demux *) demux; if (dvbdemux->users>=MAX_DVB_DEMUX_USERS) return -EUSERS; @@ -987,7 +987,7 @@ static int dvbdmx_close(struct dmx_demux_s *demux) { - dvb_demux_t *dvbdemux=(dvb_demux_t *) demux; + struct dvb_demux *dvbdemux=(struct dvb_demux *) demux; if (dvbdemux->users==0) return -ENODEV; @@ -998,7 +998,7 @@ static int dvbdmx_write(dmx_demux_t *demux, const char *buf, size_t count) { - dvb_demux_t *dvbdemux=(dvb_demux_t *) demux; + struct dvb_demux *dvbdemux=(struct dvb_demux *) demux; if ((!demux->frontend) || (demux->frontend->source!=DMX_MEMORY_FE)) @@ -1007,7 +1007,7 @@ if (down_interruptible (&dvbdemux->mutex)) return -ERESTARTSYS; - DvbDmxSWFilter(dvbdemux, buf, count); + dvb_dmx_swfilter(dvbdemux, buf, count); up(&dvbdemux->mutex); return count; } @@ -1016,7 +1016,7 @@ static int dvbdmx_add_frontend(dmx_demux_t *demux, dmx_frontend_t *frontend) { - dvb_demux_t *dvbdemux=(dvb_demux_t *) demux; + struct dvb_demux *dvbdemux=(struct dvb_demux *) demux; struct list_head *pos, *head=&dvbdemux->frontend_list; if (!(frontend->id && frontend->vendor && frontend->model)) @@ -1035,7 +1035,7 @@ dvbdmx_remove_frontend(dmx_demux_t *demux, dmx_frontend_t *frontend) { - dvb_demux_t *dvbdemux=(dvb_demux_t *) demux; + struct dvb_demux *dvbdemux=(struct dvb_demux *) demux; struct list_head *pos, *n, *head=&dvbdemux->frontend_list; list_for_each_safe (pos, n, head) @@ -1052,7 +1052,7 @@ static struct list_head * dvbdmx_get_frontends(dmx_demux_t *demux) { - dvb_demux_t *dvbdemux=(dvb_demux_t *) demux; + struct dvb_demux *dvbdemux=(struct dvb_demux *) demux; if (list_empty(&dvbdemux->frontend_list)) return NULL; @@ -1062,7 +1062,7 @@ static int dvbdmx_connect_frontend(dmx_demux_t *demux, dmx_frontend_t *frontend) { - dvb_demux_t *dvbdemux=(dvb_demux_t *) demux; + struct dvb_demux *dvbdemux=(struct dvb_demux *) demux; if (demux->frontend) return -EINVAL; @@ -1077,7 +1077,7 @@ static int dvbdmx_disconnect_frontend(dmx_demux_t *demux) { - dvb_demux_t *dvbdemux=(dvb_demux_t *) demux; + struct dvb_demux *dvbdemux=(struct dvb_demux *) demux; if (down_interruptible (&dvbdemux->mutex)) return -ERESTARTSYS; @@ -1089,24 +1089,24 @@ static int dvbdmx_get_pes_pids(dmx_demux_t *demux, u16 *pids) { - dvb_demux_t *dvbdemux=(dvb_demux_t *) demux; + struct dvb_demux *dvbdemux=(struct dvb_demux *) demux; memcpy(pids, dvbdemux->pids, 5*sizeof(u16)); return 0; } int -DvbDmxInit(dvb_demux_t *dvbdemux) +dvb_dmx_init(struct dvb_demux *dvbdemux) { int i; dmx_demux_t *dmx=&dvbdemux->dmx; dvbdemux->users=0; - dvbdemux->filter=vmalloc(dvbdemux->filternum*sizeof(dvb_demux_filter_t)); + dvbdemux->filter=vmalloc(dvbdemux->filternum*sizeof(struct dvb_demux_filter)); if (!dvbdemux->filter) return -ENOMEM; - dvbdemux->feed=vmalloc(dvbdemux->feednum*sizeof(dvb_demux_feed_t)); + dvbdemux->feed=vmalloc(dvbdemux->feednum*sizeof(struct dvb_demux_feed)); if (!dvbdemux->feed) { vfree(dvbdemux->filter); return -ENOMEM; @@ -1125,7 +1125,7 @@ dvbdemux->pids[i]=0xffff; } dvbdemux->playing=dvbdemux->recording=0; - memset(dvbdemux->pid2feed, 0, (DMX_MAX_PID+1)*sizeof(dvb_demux_feed_t *)); + memset(dvbdemux->pid2feed, 0, (DMX_MAX_PID+1)*sizeof(struct dvb_demux_feed *)); dvbdemux->tsbufp=0; dmx->frontend=0; @@ -1159,7 +1159,7 @@ } int -DvbDmxRelease(dvb_demux_t *dvbdemux) +dvb_dmx_release(struct dvb_demux *dvbdemux) { dmx_demux_t *dmx=&dvbdemux->dmx; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/media/dvb/dvb-core/dvb_demux.h linux.2.5.47-ac4/drivers/media/dvb/dvb-core/dvb_demux.h --- linux.2.5.47/drivers/media/dvb/dvb-core/dvb_demux.h 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/media/dvb/dvb-core/dvb_demux.h 2002-11-13 01:26:41.000000000 +0000 @@ -39,14 +39,14 @@ #define DVB_DEMUX_MASK_MAX 18 -typedef struct dvb_demux_filter_s { +struct dvb_demux_filter { dmx_section_filter_t filter; u8 maskandmode [DMX_MAX_FILTER_SIZE]; u8 maskandnotmode [DMX_MAX_FILTER_SIZE]; int doneq; - struct dvb_demux_filter_s *next; - struct dvb_demux_feed_s *feed; + struct dvb_demux_filter *next; + struct dvb_demux_feed *feed; int index; int state; int type; @@ -56,11 +56,10 @@ u16 hw_handle; struct timer_list timer; int ts_state; +}; - //u16 pid; //to be removed -} dvb_demux_filter_t; -typedef struct dvb_demux_feed_s { +struct dvb_demux_feed { union { dmx_ts_feed_t ts; dmx_section_feed_t sec; @@ -71,7 +70,7 @@ dmx_section_cb sec; } cb; - struct dvb_demux_s *demux; + struct dvb_demux *demux; int type; int state; u16 pid; @@ -81,7 +80,7 @@ int check_crc; struct timespec timeout; - dvb_demux_filter_t *filter; + struct dvb_demux_filter *filter; int cb_length; int ts_type; @@ -93,42 +92,43 @@ int cc; u16 peslen; -} dvb_demux_feed_t; +}; -typedef struct dvb_demux_s { +struct dvb_demux { dmx_demux_t dmx; void *priv; int filternum; int feednum; - int (*start_feed)(dvb_demux_feed_t *); - int (*stop_feed)(dvb_demux_feed_t *); - int (*write_to_decoder)(dvb_demux_feed_t *, u8 *, size_t); + int (*start_feed)(struct dvb_demux_feed *); + int (*stop_feed)(struct dvb_demux_feed *); + int (*write_to_decoder)(struct dvb_demux_feed *, u8 *, size_t); int users; #define MAX_DVB_DEMUX_USERS 10 - dvb_demux_filter_t *filter; - dvb_demux_feed_t *feed; + struct dvb_demux_filter *filter; + struct dvb_demux_feed *feed; struct list_head frontend_list; - dvb_demux_feed_t *pesfilter[DMX_TS_PES_OTHER]; + struct dvb_demux_feed *pesfilter[DMX_TS_PES_OTHER]; u16 pids[DMX_TS_PES_OTHER]; int playing; int recording; #define DMX_MAX_PID 0x2000 - dvb_demux_feed_t *pid2feed[DMX_MAX_PID+1]; + struct dvb_demux_feed *pid2feed[DMX_MAX_PID+1]; u8 tsbuf[188]; int tsbufp; struct semaphore mutex; spinlock_t lock; -} dvb_demux_t; +}; -int DvbDmxInit(dvb_demux_t *dvbdemux); -int DvbDmxRelease(dvb_demux_t *dvbdemux); -void DvbDmxSWFilterPackets(dvb_demux_t *dvbdmx, const u8 *buf, int count); +int dvb_dmx_init(struct dvb_demux *dvbdemux); +int dvb_dmx_release(struct dvb_demux *dvbdemux); +void dvb_dmx_swfilter_packet(struct dvb_demux *dvbdmx, const u8 *buf); +void dvb_dmx_swfilter_packets(struct dvb_demux *dvbdmx, const u8 *buf, int count); #endif /* _DVB_DEMUX_H_ */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/media/dvb/dvb-core/dvbdev.c linux.2.5.47-ac4/drivers/media/dvb/dvb-core/dvbdev.c --- linux.2.5.47/drivers/media/dvb/dvb-core/dvbdev.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/media/dvb/dvb-core/dvbdev.c 2002-11-13 01:26:41.000000000 +0000 @@ -37,6 +37,7 @@ #include #include #include +#include #include "compat.h" #include "dvbdev.h" @@ -69,17 +70,17 @@ static -dvb_device_t* dvbdev_find_device (int minor) +struct dvb_device* dvbdev_find_device (int minor) { struct list_head *entry; list_for_each (entry, &dvb_adapter_list) { struct list_head *entry0; - dvb_adapter_t *adap; - adap = list_entry (entry, dvb_adapter_t, list_head); + struct dvb_adapter *adap; + adap = list_entry (entry, struct dvb_adapter, list_head); list_for_each (entry0, &adap->device_list) { - dvb_device_t *dev; - dev = list_entry (entry0, dvb_device_t, list_head); + struct dvb_device *dev; + dev = list_entry (entry0, struct dvb_device, list_head); if (nums2minor(adap->num, dev->type, dev->id) == minor) return dev; } @@ -92,7 +93,7 @@ static int dvb_device_open(struct inode *inode, struct file *file) { - dvb_device_t *dvbdev; + struct dvb_device *dvbdev; dvbdev = dvbdev_find_device (minor(inode->i_rdev)); @@ -118,13 +119,8 @@ static struct file_operations dvb_device_fops = { - owner: THIS_MODULE, - read: NULL, - write: NULL, - ioctl: NULL, - open: dvb_device_open, - release: NULL, - poll: NULL, + .owner = THIS_MODULE, + .open = dvb_device_open, }; #endif /* CONFIG_DVB_DEVFS_ONLY */ @@ -132,7 +128,7 @@ int dvb_generic_open(struct inode *inode, struct file *file) { - dvb_device_t *dvbdev = file->private_data; + struct dvb_device *dvbdev = file->private_data; if (!dvbdev) return -ENODEV; @@ -153,7 +149,7 @@ int dvb_generic_release(struct inode *inode, struct file *file) { - dvb_device_t *dvbdev = file->private_data; + struct dvb_device *dvbdev = file->private_data; if (!dvbdev) return -ENODEV; @@ -166,73 +162,10 @@ } -/* - * helper function -- handles userspace copying for ioctl arguments - */ -int -generic_usercopy(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg, - int (*func)(struct inode *inode, struct file *file, - unsigned int cmd, void *arg)) -{ - char sbuf[128]; - void *mbuf = NULL; - void *parg = NULL; - int err = -EINVAL; - - /* Copy arguments into temp kernel buffer */ - switch (_IOC_DIR(cmd)) { - case _IOC_NONE: - parg = (void *)arg; - break; - case _IOC_READ: /* some v4l ioctls are marked wrong ... */ - case _IOC_WRITE: - case (_IOC_WRITE | _IOC_READ): - if (_IOC_SIZE(cmd) <= sizeof(sbuf)) { - parg = sbuf; - } else { - /* too big to allocate from stack */ - mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL); - if (NULL == mbuf) - return -ENOMEM; - parg = mbuf; - } - - err = -EFAULT; - if (copy_from_user(parg, (void *)arg, _IOC_SIZE(cmd))) - goto out; - break; - } - - /* call driver */ - if ((err = func(inode, file, cmd, parg)) == -ENOIOCTLCMD) - err = -EINVAL; - - if (err < 0) - goto out; - - /* Copy results into user buffer */ - switch (_IOC_DIR(cmd)) - { - case _IOC_READ: - case (_IOC_WRITE | _IOC_READ): - if (copy_to_user((void *)arg, parg, _IOC_SIZE(cmd))) - err = -EFAULT; - break; - } - -out: - if (mbuf) - kfree(mbuf); - - return err; -} - - int dvb_generic_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - dvb_device_t *dvbdev = file->private_data; + struct dvb_device *dvbdev = file->private_data; if (!dvbdev) return -ENODEV; @@ -240,20 +173,20 @@ if (!dvbdev->kernel_ioctl) return -EINVAL; - return generic_usercopy (inode, file, cmd, arg, dvbdev->kernel_ioctl); + return video_usercopy (inode, file, cmd, arg, dvbdev->kernel_ioctl); } static -int dvbdev_get_free_id (struct dvb_adapter_s *adap, int type) +int dvbdev_get_free_id (struct dvb_adapter *adap, int type) { u32 id = 0; while (id < DVB_MAX_IDS) { struct list_head *entry; list_for_each (entry, &adap->device_list) { - dvb_device_t *dev; - dev = list_entry (entry, dvb_device_t, list_head); + struct dvb_device *dev; + dev = list_entry (entry, struct dvb_device, list_head); if (dev->type == type && dev->id == id) goto skip; } @@ -265,12 +198,12 @@ } -int dvb_register_device(dvb_adapter_t *adap, dvb_device_t **pdvbdev, - dvb_device_t *template, void *priv, int type) +int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, + const struct dvb_device *template, void *priv, int type) { u32 id; char name [20]; - dvb_device_t *dvbdev; + struct dvb_device *dvbdev; if (down_interruptible (&dvbdev_register_lock)) return -ERESTARTSYS; @@ -282,7 +215,7 @@ return -ENFILE; } - *pdvbdev = dvbdev = kmalloc(sizeof(dvb_device_t), GFP_KERNEL); + *pdvbdev = dvbdev = kmalloc(sizeof(struct dvb_device), GFP_KERNEL); if (!dvbdev) { up(&dvbdev_register_lock); @@ -291,7 +224,7 @@ up (&dvbdev_register_lock); - memcpy(dvbdev, template, sizeof(dvb_device_t)); + memcpy(dvbdev, template, sizeof(struct dvb_device)); dvbdev->type = type; dvbdev->id = id; dvbdev->adapter = adap; @@ -307,15 +240,15 @@ S_IFCHR | S_IRUSR | S_IWUSR, dvbdev->fops, dvbdev); - dprintk("%s: register adapter%d/%s @ minor: %i (0x%02x) - dvbdev: %p\n", - __FUNCTION__, adap->num, name, nums2minor(adap->num, type, id), - nums2minor(adap->num, type, id), dvbdev); + dprintk("DVB: register adapter%d/%s @ minor: %i (0x%02x)\n", + adap->num, name, nums2minor(adap->num, type, id), + nums2minor(adap->num, type, id)); return 0; } -void dvb_unregister_device(dvb_device_t *dvbdev) +void dvb_unregister_device(struct dvb_device *dvbdev) { if (!dvbdev) return; @@ -334,8 +267,8 @@ while (1) { struct list_head *entry; list_for_each (entry, &dvb_adapter_list) { - dvb_adapter_t *adap; - adap = list_entry (entry, dvb_adapter_t, list_head); + struct dvb_adapter *adap; + adap = list_entry (entry, struct dvb_adapter, list_head); if (adap->num == num) goto skip; } @@ -348,10 +281,10 @@ } -int dvb_register_adapter(dvb_adapter_t **padap, char *name) +int dvb_register_adapter(struct dvb_adapter **padap, char *name) { char dirname[10]; - dvb_adapter_t *adap; + struct dvb_adapter *adap; int num; if (down_interruptible (&dvbdev_register_lock)) @@ -362,17 +295,17 @@ return -ENFILE; } - if (!(*padap = adap = kmalloc(sizeof(dvb_adapter_t), GFP_KERNEL))) { + if (!(*padap = adap = kmalloc(sizeof(struct dvb_adapter), GFP_KERNEL))) { up(&dvbdev_register_lock); return -ENOMEM; } - memset (adap, 0, sizeof(dvb_adapter_t)); + memset (adap, 0, sizeof(struct dvb_adapter)); INIT_LIST_HEAD (&adap->device_list); MOD_INC_USE_COUNT; - printk ("%s: registering new adapter (%s).\n", __FUNCTION__, name); + printk ("DVB: registering new adapter (%s).\n", name); sprintf(dirname, "adapter%d", num); adap->devfs_handle = devfs_mk_dir(dvb_devfs_handle, dirname, NULL); @@ -386,7 +319,7 @@ } -int dvb_unregister_adapter(dvb_adapter_t *adap) +int dvb_unregister_adapter(struct dvb_adapter *adap) { devfs_unregister (adap->devfs_handle); if (down_interruptible (&dvbdev_register_lock)) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/media/dvb/dvb-core/dvbdev.h linux.2.5.47-ac4/drivers/media/dvb/dvb-core/dvbdev.h --- linux.2.5.47/drivers/media/dvb/dvb-core/dvbdev.h 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/media/dvb/dvb-core/dvbdev.h 2002-11-13 01:26:41.000000000 +0000 @@ -43,49 +43,48 @@ #define DVB_DEVICE_OSD 8 -typedef struct dvb_adapter_s -{ +struct dvb_adapter { int num; devfs_handle_t devfs_handle; struct list_head list_head; struct list_head device_list; -} dvb_adapter_t; +}; -typedef struct dvb_device -{ +struct dvb_device { struct list_head list_head; struct file_operations *fops; devfs_handle_t devfs_handle; - dvb_adapter_t *adapter; + struct dvb_adapter *adapter; int type; u32 id; int users; int writers; - /* don't really need those !? */ + /* don't really need those !? -- FIXME: use video_usercopy */ int (*kernel_ioctl)(struct inode *inode, struct file *file, - unsigned int cmd, void *arg); // FIXME: use generic_usercopy() + unsigned int cmd, void *arg); void *priv; -} dvb_device_t; +}; -int dvb_register_device(dvb_adapter_t *adap, dvb_device_t **pdvbdev, - dvb_device_t *template, void *priv, int type); -void dvb_unregister_device(struct dvb_device *dvbdev); +extern int dvb_register_adapter (struct dvb_adapter **padap, char *name); +extern int dvb_unregister_adapter (struct dvb_adapter *adap); -int dvb_register_adapter(dvb_adapter_t **padap, char *name); -int dvb_unregister_adapter(dvb_adapter_t *adap); +extern int dvb_register_device (struct dvb_adapter *adap, + struct dvb_device **pdvbdev, + const struct dvb_device *template, + void *priv, + int type); -int dvb_generic_ioctl(struct inode *inode, struct file *file, +extern void dvb_unregister_device (struct dvb_device *dvbdev); + +extern int dvb_generic_open (struct inode *inode, struct file *file); +extern int dvb_generic_release (struct inode *inode, struct file *file); +extern int dvb_generic_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); -int dvb_generic_open(struct inode *inode, struct file *file); -int dvb_generic_release(struct inode *inode, struct file *file); -int generic_usercopy(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg, - int (*func)(struct inode *inode, struct file *file, - unsigned int cmd, void *arg)); -#endif /* #ifndef __DVBDEV_H */ +#endif /* #ifndef _DVBDEV_H_ */ + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/media/dvb/dvb-core/dvb_filter.c linux.2.5.47-ac4/drivers/media/dvb/dvb-core/dvb_filter.c --- linux.2.5.47/drivers/media/dvb/dvb-core/dvb_filter.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/media/dvb/dvb-core/dvb_filter.c 2002-11-13 01:26:41.000000000 +0000 @@ -24,939 +24,978 @@ -void pes2ts_init(pes2ts_t *p2ts, unsigned short pid, - pes2ts_cb_t *cb, void *priv) +#if 0 +static +void setup_ts2pes(ipack *pa, ipack *pv, u16 *pida, u16 *pidv, + void (*pes_write)(u8 *buf, int count, void *data), + void *priv) { - unsigned char *buf=p2ts->buf; - - buf[0]=0x47; - buf[1]=(pid>>8); - buf[2]=pid&0xff; - p2ts->cc=0; - p2ts->cb=cb; - p2ts->priv=priv; + dvb_filter_ipack_init(pa, IPACKS, pes_write); + dvb_filter_ipack_init(pv, IPACKS, pes_write); + pa->pid = pida; + pv->pid = pidv; + pa->data = priv; + pv->data = priv; } +#endif -int pes2ts(pes2ts_t *p2ts, unsigned char *pes, int len) +#if 0 +static +void ts_to_pes(ipack *p, u8 *buf) // don't need count (=188) { - unsigned char *buf=p2ts->buf; - int ret=0, rest; - - //len=6+((pes[4]<<8)|pes[5]); + u8 off = 0; - buf[1]|=0x40; - while (len>=184) { - buf[3]=0x10|((p2ts->cc++)&0x0f); - memcpy(buf+4, pes, 184); - if ((ret=p2ts->cb(p2ts->priv, buf))) - return ret; - len-=184; pes+=184; - buf[1]&=~0x40; - } - if (!len) - return 0; - buf[3]=0x30|((p2ts->cc++)&0x0f); - rest=183-len; - if (rest) { - buf[5]=0x00; - if (rest-1) - memset(buf+6, 0xff, rest-1); + if (!buf || !p ){ + printk("NULL POINTER IDIOT\n"); + return; } - buf[4]=rest; - memcpy(buf+5+rest, pes, len); - return p2ts->cb(p2ts->priv, buf); -} - -void reset_ipack(ipack *p) -{ + if (buf[1]&PAY_START) { + if (p->plength == MMAX_PLENGTH-6 && p->found>6){ + p->plength = p->found-6; p->found = 0; - p->cid = 0; - p->plength = 0; - p->flag1 = 0; - p->flag2 = 0; - p->hlength = 0; - p->mpeg = 0; - p->check = 0; - p->which = 0; - p->done = 0; - p->count = 0; -} - -void init_ipack(ipack *p, int size, - void (*func)(u8 *buf, int size, void *priv)) -{ - if ( !(p->buf = vmalloc(size*sizeof(u8))) ){ - printk ("Couldn't allocate memory for ipack\n"); + send_ipack(p); + dvb_filter_ipack_reset(p); } - p->size = size; - p->func = func; - p->repack_subids = 0; - reset_ipack(p); -} - -void free_ipack(ipack * p) -{ - if (p->buf) vfree(p->buf); + } + if (buf[3] & ADAPT_FIELD) { // adaptation field? + off = buf[4] + 1; + if (off+4 > 187) return; + } + dvb_filter_instant_repack(buf+4+off, TS_SIZE-4-off, p); } +#endif -void send_ipack(ipack *p) +#if 0 +/* needs 5 byte input, returns picture coding type*/ +static +int read_picture_header(uint8_t *headr, mpg_picture *pic, int field, int pr) { - int off; - AudioInfo ai; - int ac3_off = 0; - int streamid=0; - int nframes= 0; - int f=0; - - switch ( p->mpeg ){ - case 2: - if (p->count < 10) return; - p->buf[3] = p->cid; - - p->buf[4] = (u8)(((p->count-6) & 0xFF00) >> 8); - p->buf[5] = (u8)((p->count-6) & 0x00FF); - if (p->repack_subids && p->cid == PRIVATE_STREAM1){ + uint8_t pct; - off = 9+p->buf[8]; - streamid = p->buf[off]; - if ((streamid & 0xF8) == 0x80){ - ai.off = 0; - ac3_off = ((p->buf[off+2] << 8)| - p->buf[off+3]); - if (ac3_off < p->count) - f=get_ac3info(p->buf+off+3+ac3_off, - p->count-ac3_off, &ai,0); - if ( !f ){ - nframes = (p->count-off-3-ac3_off)/ - ai.framesize + 1; - p->buf[off+2] = (ac3_off >> 8)& 0xFF; - p->buf[off+3] = (ac3_off)& 0xFF; - p->buf[off+1] = nframes; + if (pr) printk( "Pic header: "); + pic->temporal_reference[field] = (( headr[0] << 2 ) | + (headr[1] & 0x03) )& 0x03ff; + if (pr) printk( " temp ref: 0x%04x", pic->temporal_reference[field]); - ac3_off += nframes * ai.framesize - - p->count; - } + pct = ( headr[1] >> 2 ) & 0x07; + pic->picture_coding_type[field] = pct; + if (pr) { + switch(pct){ + case I_FRAME: + printk( " I-FRAME"); + break; + case B_FRAME: + printk( " B-FRAME"); + break; + case P_FRAME: + printk( " P-FRAME"); + break; } } - p->func(p->buf, p->count, p->data); - p->buf[6] = 0x80; - p->buf[7] = 0x00; - p->buf[8] = 0x00; - p->count = 9; - if (p->repack_subids && p->cid == PRIVATE_STREAM1 - && (streamid & 0xF8)==0x80 ){ - p->count += 4; - p->buf[9] = streamid; - p->buf[10] = (ac3_off >> 8)& 0xFF; - p->buf[11] = (ac3_off)& 0xFF; - p->buf[12] = 0; - } - break; - case 1: - if (p->count < 8) return; - p->buf[3] = p->cid; + pic->vinfo.vbv_delay = (( headr[1] >> 5 ) | ( headr[2] << 3) | + ( (headr[3] & 0x1F) << 11) ) & 0xffff; - p->buf[4] = (u8)(((p->count-6) & 0xFF00) >> 8); - p->buf[5] = (u8)((p->count-6) & 0x00FF); - p->func(p->buf, p->count, p->data); + if (pr) printk( " vbv delay: 0x%04x", pic->vinfo.vbv_delay); - p->buf[6] = 0x0F; - p->count = 7; - break; + pic->picture_header_parameter = ( headr[3] & 0xe0 ) | + ((headr[4] & 0x80) >> 3); + + if ( pct == B_FRAME ){ + pic->picture_header_parameter |= ( headr[4] >> 3 ) & 0x0f; } -} + if (pr) printk( " pic head param: 0x%x", + pic->picture_header_parameter); -void send_ipack_rest(ipack *p) -{ - if (p->plength != MMAX_PLENGTH-6 || p->found<=6) - return; - p->plength = p->found-6; - p->found = 0; - send_ipack(p); - reset_ipack(p); + return pct; } +#endif -static void write_ipack(ipack *p, u8 *data, int count) +#if 0 +/* needs 4 byte input */ +static +int read_gop_header(uint8_t *headr, mpg_picture *pic, int pr) { - u8 headr[3] = { 0x00, 0x00, 0x01} ; + if (pr) printk("GOP header: "); - if (p->count < 6){ - memcpy(p->buf, headr, 3); - p->count = 6; + pic->time_code = (( headr[0] << 17 ) | ( headr[1] << 9) | + ( headr[2] << 1 ) | (headr[3] &0x01)) & 0x1ffffff; + + if (pr) printk(" time: %d:%d.%d ", (headr[0]>>2)& 0x1F, + ((headr[0]<<4)& 0x30)| ((headr[1]>>4)& 0x0F), + ((headr[1]<<3)& 0x38)| ((headr[2]>>5)& 0x0F)); + + if ( ( headr[3] & 0x40 ) != 0 ){ + pic->closed_gop = 1; + } else { + pic->closed_gop = 0; } + if (pr) printk("closed: %d", pic->closed_gop); - if (p->count + count < p->size){ - memcpy(p->buf+p->count, data, count); - p->count += count; + if ( ( headr[3] & 0x20 ) != 0 ){ + pic->broken_link = 1; } else { - int rest = p->size - p->count; - memcpy(p->buf+p->count, data, rest); - p->count += rest; - send_ipack(p); - if (count - rest > 0) - write_ipack(p, data+rest, count-rest); + pic->broken_link = 0; } + if (pr) printk(" broken: %d\n", pic->broken_link); + + return 0; } +#endif -int instant_repack(u8 *buf, int count, ipack *p) +#if 0 +/* needs 8 byte input */ +static +int read_sequence_header(uint8_t *headr, VideoInfo *vi, int pr) { - int l; - int c=0; + int sw; + int form = -1; - while (c < count && (p->mpeg == 0 || - (p->mpeg == 1 && p->found < 7) || - (p->mpeg == 2 && p->found < 9)) - && (p->found < 5 || !p->done)){ - switch ( p->found ){ - case 0: + if (pr) printk("Reading sequence header\n"); + + vi->horizontal_size = ((headr[1] &0xF0) >> 4) | (headr[0] << 4); + vi->vertical_size = ((headr[1] &0x0F) << 8) | (headr[2]); + + sw = (int)((headr[3]&0xF0) >> 4) ; + + switch( sw ){ case 1: - if (buf[c] == 0x00) p->found++; - else p->found = 0; - c++; + if (pr) + printk("Videostream: ASPECT: 1:1"); + vi->aspect_ratio = 100; break; case 2: - if (buf[c] == 0x01) p->found++; - else if (buf[c] == 0) { - p->found = 2; - } else p->found = 0; - c++; + if (pr) + printk("Videostream: ASPECT: 4:3"); + vi->aspect_ratio = 133; break; case 3: - p->cid = 0; - switch (buf[c]){ - case PROG_STREAM_MAP: - case PRIVATE_STREAM2: - case PROG_STREAM_DIR: - case ECM_STREAM : - case EMM_STREAM : - case PADDING_STREAM : - case DSM_CC_STREAM : - case ISO13522_STREAM: - p->done = 1; - case PRIVATE_STREAM1: - case VIDEO_STREAM_S ... VIDEO_STREAM_E: - case AUDIO_STREAM_S ... AUDIO_STREAM_E: - p->found++; - p->cid = buf[c]; - c++; + if (pr) + printk("Videostream: ASPECT: 16:9"); + vi->aspect_ratio = 177; break; - default: - p->found = 0; + case 4: + if (pr) + printk("Videostream: ASPECT: 2.21:1"); + vi->aspect_ratio = 221; break; - } + + case 5 ... 15: + if (pr) + printk("Videostream: ASPECT: reserved"); + vi->aspect_ratio = 0; break; - case 4: - if (count-c > 1){ - p->plen[0] = buf[c]; - c++; - p->plen[1] = buf[c]; - c++; - p->found+=2; - p->plength=(p->plen[0]<<8)|p->plen[1]; - } else { - p->plen[0] = buf[c]; - p->found++; - return count; + default: + vi->aspect_ratio = 0; + return -1; } + + if (pr) + printk(" Size = %dx%d",vi->horizontal_size,vi->vertical_size); + + sw = (int)(headr[3]&0x0F); + + switch ( sw ) { + case 1: + if (pr) + printk(" FRate: 23.976 fps"); + vi->framerate = 23976; + form = -1; + break; + case 2: + if (pr) + printk(" FRate: 24 fps"); + vi->framerate = 24000; + form = -1; + break; + case 3: + if (pr) + printk(" FRate: 25 fps"); + vi->framerate = 25000; + form = VIDEO_MODE_PAL; + break; + case 4: + if (pr) + printk(" FRate: 29.97 fps"); + vi->framerate = 29970; + form = VIDEO_MODE_NTSC; break; case 5: - p->plen[1] = buf[c]; - c++; - p->found++; - p->plength=(p->plen[0]<<8)|p->plen[1]; + if (pr) + printk(" FRate: 30 fps"); + vi->framerate = 30000; + form = VIDEO_MODE_NTSC; break; case 6: - if (!p->done){ - p->flag1 = buf[c]; - c++; - p->found++; - if ( (p->flag1 & 0xC0) == 0x80 ) p->mpeg = 2; - else { - p->hlength = 0; - p->which = 0; - p->mpeg = 1; - p->flag2 = 0; - } - } + if (pr) + printk(" FRate: 50 fps"); + vi->framerate = 50000; + form = VIDEO_MODE_PAL; break; - case 7: - if ( !p->done && p->mpeg == 2) { - p->flag2 = buf[c]; - c++; - p->found++; - } + if (pr) + printk(" FRate: 60 fps"); + vi->framerate = 60000; + form = VIDEO_MODE_NTSC; break; - - case 8: - if ( !p->done && p->mpeg == 2) { - p->hlength = buf[c]; - c++; - p->found++; } - break; - default: + vi->bit_rate = (headr[4] << 10) | (headr[5] << 2) | (headr[6] & 0x03); - break; - } + vi->vbv_buffer_size + = (( headr[6] & 0xF8) >> 3 ) | (( headr[7] & 0x1F )<< 5); + + if (pr){ + printk(" BRate: %d Mbit/s",4*(vi->bit_rate)/10000); + printk(" vbvbuffer %d",16*1024*(vi->vbv_buffer_size)); + printk("\n"); } - if (c == count) return count; + vi->video_format = form; - if (!p->plength) p->plength = MMAX_PLENGTH-6; + return 0; +} +#endif - if ( p->done || ((p->mpeg == 2 && p->found >= 9) || - (p->mpeg == 1 && p->found >= 7)) ){ - switch (p->cid){ - case AUDIO_STREAM_S ... AUDIO_STREAM_E: - case VIDEO_STREAM_S ... VIDEO_STREAM_E: - case PRIVATE_STREAM1: +#if 0 +static +int get_vinfo(uint8_t *mbuf, int count, VideoInfo *vi, int pr) +{ + uint8_t *headr; + int found = 0; + int c = 0; - if (p->mpeg == 2 && p->found == 9) { - write_ipack(p, &p->flag1, 1); - write_ipack(p, &p->flag2, 1); - write_ipack(p, &p->hlength, 1); + while (found < 4 && c+4 < count){ + uint8_t *b; + + b = mbuf+c; + if ( b[0] == 0x00 && b[1] == 0x00 && b[2] == 0x01 + && b[3] == 0xb3) found = 4; + else { + c++; + } } - if (p->mpeg == 1 && p->found == 7) - write_ipack(p, &p->flag1, 1); + if (! found) return -1; + c += 4; + if (c+12 >= count) return -1; + headr = mbuf+c; + if (read_sequence_header(headr, vi, pr) < 0) return -1; + vi->off = c-4; + return 0; +} +#endif - if (p->mpeg == 2 && (p->flag2 & PTS_ONLY) && - p->found < 14) { - while (c < count && p->found < 14) { - p->pts[p->found-9] = buf[c]; - write_ipack(p, buf+c, 1); + +#if 0 +static +int get_ainfo(uint8_t *mbuf, int count, AudioInfo *ai, int pr) +{ + uint8_t *headr; + int found = 0; + int c = 0; + int fr = 0; + + while (found < 2 && c < count){ + uint8_t b[2]; + memcpy( b, mbuf+c, 2); + + if ( b[0] == 0xff && (b[1] & 0xf8) == 0xf8) + found = 2; + else { c++; - p->found++; } - if (c == count) return count; } - if (p->mpeg == 1 && p->which < 2000) { + if (!found) return -1; - if (p->found == 7) { - p->check = p->flag1; - p->hlength = 1; + if (c+3 >= count) return -1; + headr = mbuf+c; + + ai->layer = (headr[1] & 0x06) >> 1; + + if (pr) + printk("Audiostream: Layer: %d", 4-ai->layer); + + + ai->bit_rate = bitrates[(3-ai->layer)][(headr[2] >> 4 )]*1000; + + if (pr){ + if (ai->bit_rate == 0) + printk(" Bit rate: free"); + else if (ai->bit_rate == 0xf) + printk(" BRate: reserved"); + else + printk(" BRate: %d kb/s", ai->bit_rate/1000); } - while (!p->which && c < count && - p->check == 0xFF){ - p->check = buf[c]; - write_ipack(p, buf+c, 1); - c++; - p->found++; - p->hlength++; + fr = (headr[2] & 0x0c ) >> 2; + ai->frequency = freq[fr]*100; + if (pr){ + if (ai->frequency == 3) + printk(" Freq: reserved\n"); + else + printk(" Freq: %d kHz\n",ai->frequency); + } + ai->off = c; + return 0; +} +#endif - if ( c == count) return count; +static +int get_ac3info(uint8_t *mbuf, int count, AudioInfo *ai, int pr) +{ + uint8_t *headr; + int found = 0; + int c = 0; + uint8_t frame = 0; + int fr = 0; - if ( (p->check & 0xC0) == 0x40 && !p->which){ - p->check = buf[c]; - write_ipack(p, buf+c, 1); - c++; - p->found++; - p->hlength++; + while ( !found && c < count){ + uint8_t *b = mbuf+c; - p->which = 1; - if ( c == count) return count; - p->check = buf[c]; - write_ipack(p, buf+c, 1); + if ( b[0] == 0x0b && b[1] == 0x77 ) + found = 1; + else { c++; - p->found++; - p->hlength++; - p->which = 2; - if ( c == count) return count; } - - if (p->which == 1){ - p->check = buf[c]; - write_ipack(p, buf+c, 1); - c++; - p->found++; - p->hlength++; - p->which = 2; - if ( c == count) return count; } - if ( (p->check & 0x30) && p->check != 0xFF){ - p->flag2 = (p->check & 0xF0) << 2; - p->pts[0] = p->check; - p->which = 3; - } - - if ( c == count) return count; - if (p->which > 2){ - if ((p->flag2 & PTS_DTS_FLAGS) - == PTS_ONLY){ - while (c < count && - p->which < 7){ - p->pts[p->which-2] = - buf[c]; - write_ipack(p,buf+c,1); - c++; - p->found++; - p->which++; - p->hlength++; - } - if ( c == count) return count; - } else if ((p->flag2 & PTS_DTS_FLAGS) - == PTS_DTS){ - while (c < count && - p->which< 12){ - if (p->which< 7) - p->pts[p->which - -2] = - buf[c]; - write_ipack(p,buf+c,1); - c++; - p->found++; - p->which++; - p->hlength++; - } - if ( c == count) return count; - } - p->which = 2000; - } + if (!found) return -1; + if (pr) + printk("Audiostream: AC3"); - } + ai->off = c; + if (c+5 >= count) return -1; - while (c < count && p->found < p->plength+6){ - l = count -c; - if (l+p->found > p->plength+6) - l = p->plength+6-p->found; - write_ipack(p, buf+c, l); - p->found += l; - c += l; - } + ai->layer = 0; // 0 for AC3 + headr = mbuf+c+2; - break; - } + frame = (headr[2]&0x3f); + ai->bit_rate = ac3_bitrates[frame >> 1]*1000; + if (pr) + printk(" BRate: %d kb/s", ai->bit_rate/1000); - if ( p->done ){ - if( p->found + count - c < p->plength+6){ - p->found += count-c; - c = count; - } else { - c += p->plength+6 - p->found; - p->found = p->plength+6; - } - } + ai->frequency = (headr[2] & 0xc0 ) >> 6; + fr = (headr[2] & 0xc0 ) >> 6; + ai->frequency = freq[fr]*100; + if (pr) printk (" Freq: %d Hz\n", ai->frequency); - if (p->plength && p->found == p->plength+6) { - send_ipack(p); - reset_ipack(p); - if (c < count) - instant_repack(buf+c, count-c, p); - } - } - return count; -} + ai->framesize = ac3_frames[fr][frame >> 1]; + if ((frame & 1) && (fr == 1)) ai->framesize++; + ai->framesize = ai->framesize << 1; + if (pr) printk (" Framesize %d\n", ai->framesize); -void setup_ts2pes(ipack *pa, ipack *pv, u16 *pida, u16 *pidv, - void (*pes_write)(u8 *buf, int count, void *data), - void *priv) -{ - init_ipack(pa, IPACKS, pes_write); - init_ipack(pv, IPACKS, pes_write); - pa->pid = pida; - pv->pid = pidv; - pa->data = priv; - pv->data = priv; + return 0; } -void ts_to_pes(ipack *p, u8 *buf) // don't need count (=188) -{ - u8 off = 0; - - if (!buf || !p ){ - printk("NULL POINTER IDIOT\n"); - return; - } - if (buf[1]&PAY_START) { - if (p->plength == MMAX_PLENGTH-6 && p->found>6){ - p->plength = p->found-6; - p->found = 0; - send_ipack(p); - reset_ipack(p); - } - } - if (buf[3] & ADAPT_FIELD) { // adaptation field? - off = buf[4] + 1; - if (off+4 > 187) return; - } - instant_repack(buf+4+off, TS_SIZE-4-off, p); -} -/* needs 5 byte input, returns picture coding type*/ -int read_picture_header(uint8_t *headr, mpg_picture *pic, int field, int pr) +#if 0 +static +uint8_t *skip_pes_header(uint8_t **bufp) { - uint8_t pct; + uint8_t *inbuf = *bufp; + uint8_t *buf = inbuf; + uint8_t *pts = NULL; + int skip = 0; - if (pr) printk( "Pic header: "); - pic->temporal_reference[field] = (( headr[0] << 2 ) | - (headr[1] & 0x03) )& 0x03ff; - if (pr) printk( " temp ref: 0x%04x", pic->temporal_reference[field]); + static const int mpeg1_skip_table[16] = { + 1, 0xffff, 5, 10, 0xffff, 0xffff, 0xffff, 0xffff, + 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff + }; - pct = ( headr[1] >> 2 ) & 0x07; - pic->picture_coding_type[field] = pct; - if (pr) { - switch(pct){ - case I_FRAME: - printk( " I-FRAME"); - break; - case B_FRAME: - printk( " B-FRAME"); - break; - case P_FRAME: - printk( " P-FRAME"); + + if ((inbuf[6] & 0xc0) == 0x80){ /* mpeg2 */ + if (buf[7] & PTS_ONLY) + pts = buf+9; + else pts = NULL; + buf = inbuf + 9 + inbuf[8]; + } else { /* mpeg1 */ + for (buf = inbuf + 6; *buf == 0xff; buf++) + if (buf == inbuf + 6 + 16) { break; } - } - - - pic->vinfo.vbv_delay = (( headr[1] >> 5 ) | ( headr[2] << 3) | - ( (headr[3] & 0x1F) << 11) ) & 0xffff; - - if (pr) printk( " vbv delay: 0x%04x", pic->vinfo.vbv_delay); - - pic->picture_header_parameter = ( headr[3] & 0xe0 ) | - ((headr[4] & 0x80) >> 3); + if ((*buf & 0xc0) == 0x40) + buf += 2; + skip = mpeg1_skip_table [*buf >> 4]; + if (skip == 5 || skip == 10) pts = buf; + else pts = NULL; - if ( pct == B_FRAME ){ - pic->picture_header_parameter |= ( headr[4] >> 3 ) & 0x0f; + buf += mpeg1_skip_table [*buf >> 4]; } - if (pr) printk( " pic head param: 0x%x", - pic->picture_header_parameter); - return pct; + *bufp = buf; + return pts; } +#endif - -/* needs 4 byte input */ -int read_gop_header(uint8_t *headr, mpg_picture *pic, int pr) +#if 0 +static +void initialize_quant_matrix( uint32_t *matrix ) { - if (pr) printk("GOP header: "); + int i; - pic->time_code = (( headr[0] << 17 ) | ( headr[1] << 9) | - ( headr[2] << 1 ) | (headr[3] &0x01)) & 0x1ffffff; + matrix[0] = 0x08101013; + matrix[1] = 0x10131616; + matrix[2] = 0x16161616; + matrix[3] = 0x1a181a1b; + matrix[4] = 0x1b1b1a1a; + matrix[5] = 0x1a1a1b1b; + matrix[6] = 0x1b1d1d1d; + matrix[7] = 0x2222221d; + matrix[8] = 0x1d1d1b1b; + matrix[9] = 0x1d1d2020; + matrix[10] = 0x22222526; + matrix[11] = 0x25232322; + matrix[12] = 0x23262628; + matrix[13] = 0x28283030; + matrix[14] = 0x2e2e3838; + matrix[15] = 0x3a454553; - if (pr) printk(" time: %d:%d.%d ", (headr[0]>>2)& 0x1F, - ((headr[0]<<4)& 0x30)| ((headr[1]>>4)& 0x0F), - ((headr[1]<<3)& 0x38)| ((headr[2]>>5)& 0x0F)); + for ( i = 16 ; i < 32 ; i++ ) + matrix[i] = 0x10101010; +} +#endif - if ( ( headr[3] & 0x40 ) != 0 ){ - pic->closed_gop = 1; - } else { - pic->closed_gop = 0; - } - if (pr) printk("closed: %d", pic->closed_gop); +#if 0 +static +void initialize_mpg_picture(mpg_picture *pic) +{ + int i; - if ( ( headr[3] & 0x20 ) != 0 ){ - pic->broken_link = 1; - } else { - pic->broken_link = 0; + /* set MPEG1 */ + pic->mpeg1_flag = 1; + pic->profile_and_level = 0x4A ; /* MP@LL */ + pic->progressive_sequence = 1; + pic->low_delay = 0; + + pic->sequence_display_extension_flag = 0; + for ( i = 0 ; i < 4 ; i++ ){ + pic->frame_centre_horizontal_offset[i] = 0; + pic->frame_centre_vertical_offset[i] = 0; } - if (pr) printk(" broken: %d\n", pic->broken_link); + pic->last_frame_centre_horizontal_offset = 0; + pic->last_frame_centre_vertical_offset = 0; - return 0; + pic->picture_display_extension_flag[0] = 0; + pic->picture_display_extension_flag[1] = 0; + pic->sequence_header_flag = 0; + pic->gop_flag = 0; + pic->sequence_end_flag = 0; } +#endif -/* needs 8 byte input */ -int read_sequence_header(uint8_t *headr, VideoInfo *vi, int pr) +#if 0 +static +void mpg_set_picture_parameter( int32_t field_type, mpg_picture *pic ) { - int sw; - int form = -1; + int16_t last_h_offset; + int16_t last_v_offset; - if (pr) printk("Reading sequence header\n"); + int16_t *p_h_offset; + int16_t *p_v_offset; - vi->horizontal_size = ((headr[1] &0xF0) >> 4) | (headr[0] << 4); - vi->vertical_size = ((headr[1] &0x0F) << 8) | (headr[2]); + if ( pic->mpeg1_flag ){ + pic->picture_structure[field_type] = VIDEO_FRAME_PICTURE; + pic->top_field_first = 0; + pic->repeat_first_field = 0; + pic->progressive_frame = 1; + pic->picture_coding_parameter = 0x000010; + } - sw = (int)((headr[3]&0xF0) >> 4) ; + /* Reset flag */ + pic->picture_display_extension_flag[field_type] = 0; - switch( sw ){ - case 1: - if (pr) - printk("Videostream: ASPECT: 1:1"); - vi->aspect_ratio = 100; - break; - case 2: - if (pr) - printk("Videostream: ASPECT: 4:3"); - vi->aspect_ratio = 133; - break; - case 3: - if (pr) - printk("Videostream: ASPECT: 16:9"); - vi->aspect_ratio = 177; - break; - case 4: - if (pr) - printk("Videostream: ASPECT: 2.21:1"); - vi->aspect_ratio = 221; - break; - - case 5 ... 15: - if (pr) - printk("Videostream: ASPECT: reserved"); - vi->aspect_ratio = 0; - break; - - default: - vi->aspect_ratio = 0; - return -1; + last_h_offset = pic->last_frame_centre_horizontal_offset; + last_v_offset = pic->last_frame_centre_vertical_offset; + if ( field_type == FIRST_FIELD ){ + p_h_offset = pic->frame_centre_horizontal_offset; + p_v_offset = pic->frame_centre_vertical_offset; + *p_h_offset = last_h_offset; + *(p_h_offset + 1) = last_h_offset; + *(p_h_offset + 2) = last_h_offset; + *p_v_offset = last_v_offset; + *(p_v_offset + 1) = last_v_offset; + *(p_v_offset + 2) = last_v_offset; + } else { + pic->frame_centre_horizontal_offset[3] = last_h_offset; + pic->frame_centre_vertical_offset[3] = last_v_offset; } +} +#endif - if (pr) - printk(" Size = %dx%d",vi->horizontal_size,vi->vertical_size); - - sw = (int)(headr[3]&0x0F); +#if 0 +static +void init_mpg_picture( mpg_picture *pic, int chan, int32_t field_type) +{ + pic->picture_header = 0; + pic->sequence_header_data + = ( INIT_HORIZONTAL_SIZE << 20 ) + | ( INIT_VERTICAL_SIZE << 8 ) + | ( INIT_ASPECT_RATIO << 4 ) + | ( INIT_FRAME_RATE ); + pic->mpeg1_flag = 0; + pic->vinfo.horizontal_size + = INIT_DISP_HORIZONTAL_SIZE; + pic->vinfo.vertical_size + = INIT_DISP_VERTICAL_SIZE; + pic->picture_display_extension_flag[field_type] + = 0; + pic->pts_flag[field_type] = 0; - switch ( sw ) { - case 1: - if (pr) - printk(" FRate: 23.976 fps"); - vi->framerate = 23976; - form = -1; - break; - case 2: - if (pr) - printk(" FRate: 24 fps"); - vi->framerate = 24000; - form = -1; - break; - case 3: - if (pr) - printk(" FRate: 25 fps"); - vi->framerate = 25000; - form = VIDEO_MODE_PAL; - break; - case 4: - if (pr) - printk(" FRate: 29.97 fps"); - vi->framerate = 29970; - form = VIDEO_MODE_NTSC; - break; - case 5: - if (pr) - printk(" FRate: 30 fps"); - vi->framerate = 30000; - form = VIDEO_MODE_NTSC; - break; - case 6: - if (pr) - printk(" FRate: 50 fps"); - vi->framerate = 50000; - form = VIDEO_MODE_PAL; - break; - case 7: - if (pr) - printk(" FRate: 60 fps"); - vi->framerate = 60000; - form = VIDEO_MODE_NTSC; - break; - } + pic->sequence_gop_header = 0; + pic->picture_header = 0; + pic->sequence_header_flag = 0; + pic->gop_flag = 0; + pic->sequence_end_flag = 0; + pic->sequence_display_extension_flag = 0; + pic->last_frame_centre_horizontal_offset = 0; + pic->last_frame_centre_vertical_offset = 0; + pic->channel = chan; +} +#endif - vi->bit_rate = (headr[4] << 10) | (headr[5] << 2) | (headr[6] & 0x03); +void dvb_filter_pes2ts_init(dvb_filter_pes2ts_t *p2ts, unsigned short pid, + dvb_filter_pes2ts_cb_t *cb, void *priv) +{ + unsigned char *buf=p2ts->buf; - vi->vbv_buffer_size - = (( headr[6] & 0xF8) >> 3 ) | (( headr[7] & 0x1F )<< 5); + buf[0]=0x47; + buf[1]=(pid>>8); + buf[2]=pid&0xff; + p2ts->cc=0; + p2ts->cb=cb; + p2ts->priv=priv; +} - if (pr){ - printk(" BRate: %d Mbit/s",4*(vi->bit_rate)/10000); - printk(" vbvbuffer %d",16*1024*(vi->vbv_buffer_size)); - printk("\n"); - } +int dvb_filter_pes2ts(dvb_filter_pes2ts_t *p2ts, unsigned char *pes, int len) +{ + unsigned char *buf=p2ts->buf; + int ret=0, rest; - vi->video_format = form; + //len=6+((pes[4]<<8)|pes[5]); + buf[1]|=0x40; + while (len>=184) { + buf[3]=0x10|((p2ts->cc++)&0x0f); + memcpy(buf+4, pes, 184); + if ((ret=p2ts->cb(p2ts->priv, buf))) + return ret; + len-=184; pes+=184; + buf[1]&=~0x40; + } + if (!len) return 0; + buf[3]=0x30|((p2ts->cc++)&0x0f); + rest=183-len; + if (rest) { + buf[5]=0x00; + if (rest-1) + memset(buf+6, 0xff, rest-1); + } + buf[4]=rest; + memcpy(buf+5+rest, pes, len); + return p2ts->cb(p2ts->priv, buf); } -int get_vinfo(uint8_t *mbuf, int count, VideoInfo *vi, int pr) +void dvb_filter_ipack_reset(ipack *p) { - uint8_t *headr; - int found = 0; - int c = 0; - - while (found < 4 && c+4 < count){ - uint8_t *b; + p->found = 0; + p->cid = 0; + p->plength = 0; + p->flag1 = 0; + p->flag2 = 0; + p->hlength = 0; + p->mpeg = 0; + p->check = 0; + p->which = 0; + p->done = 0; + p->count = 0; +} - b = mbuf+c; - if ( b[0] == 0x00 && b[1] == 0x00 && b[2] == 0x01 - && b[3] == 0xb3) found = 4; - else { - c++; - } +void dvb_filter_ipack_init(ipack *p, int size, + void (*func)(u8 *buf, int size, void *priv)) +{ + if ( !(p->buf = vmalloc(size*sizeof(u8))) ){ + printk ("Couldn't allocate memory for ipack\n"); } + p->size = size; + p->func = func; + p->repack_subids = 0; + dvb_filter_ipack_reset(p); +} - if (! found) return -1; - c += 4; - if (c+12 >= count) return -1; - headr = mbuf+c; - if (read_sequence_header(headr, vi, pr) < 0) return -1; - vi->off = c-4; - return 0; +void dvb_filter_ipack_free(ipack * p) +{ + if (p->buf) vfree(p->buf); } -int get_ainfo(uint8_t *mbuf, int count, AudioInfo *ai, int pr) +static +void send_ipack(ipack *p) { - uint8_t *headr; - int found = 0; - int c = 0; - int fr = 0; + int off; + AudioInfo ai; + int ac3_off = 0; + int streamid=0; + int nframes= 0; + int f=0; - while (found < 2 && c < count){ - uint8_t b[2]; - memcpy( b, mbuf+c, 2); + switch ( p->mpeg ){ + case 2: + if (p->count < 10) return; + p->buf[3] = p->cid; - if ( b[0] == 0xff && (b[1] & 0xf8) == 0xf8) - found = 2; - else { - c++; + p->buf[4] = (u8)(((p->count-6) & 0xFF00) >> 8); + p->buf[5] = (u8)((p->count-6) & 0x00FF); + if (p->repack_subids && p->cid == PRIVATE_STREAM1){ + + off = 9+p->buf[8]; + streamid = p->buf[off]; + if ((streamid & 0xF8) == 0x80){ + ai.off = 0; + ac3_off = ((p->buf[off+2] << 8)| + p->buf[off+3]); + if (ac3_off < p->count) + f=get_ac3info(p->buf+off+3+ac3_off, + p->count-ac3_off, &ai,0); + if ( !f ){ + nframes = (p->count-off-3-ac3_off)/ + ai.framesize + 1; + p->buf[off+2] = (ac3_off >> 8)& 0xFF; + p->buf[off+3] = (ac3_off)& 0xFF; + p->buf[off+1] = nframes; + + ac3_off += nframes * ai.framesize - + p->count; + } } } + p->func(p->buf, p->count, p->data); - if (!found) return -1; + p->buf[6] = 0x80; + p->buf[7] = 0x00; + p->buf[8] = 0x00; + p->count = 9; + if (p->repack_subids && p->cid == PRIVATE_STREAM1 + && (streamid & 0xF8)==0x80 ){ + p->count += 4; + p->buf[9] = streamid; + p->buf[10] = (ac3_off >> 8)& 0xFF; + p->buf[11] = (ac3_off)& 0xFF; + p->buf[12] = 0; + } - if (c+3 >= count) return -1; - headr = mbuf+c; + break; + case 1: + if (p->count < 8) return; + p->buf[3] = p->cid; - ai->layer = (headr[1] & 0x06) >> 1; + p->buf[4] = (u8)(((p->count-6) & 0xFF00) >> 8); + p->buf[5] = (u8)((p->count-6) & 0x00FF); + p->func(p->buf, p->count, p->data); - if (pr) - printk("Audiostream: Layer: %d", 4-ai->layer); + p->buf[6] = 0x0F; + p->count = 7; + break; + } +} +void dvb_filter_ipack_flush(ipack *p) +{ + if (p->plength != MMAX_PLENGTH-6 || p->found<=6) + return; + p->plength = p->found-6; + p->found = 0; + send_ipack(p); + dvb_filter_ipack_reset(p); +} - ai->bit_rate = bitrates[(3-ai->layer)][(headr[2] >> 4 )]*1000; +static +void write_ipack(ipack *p, u8 *data, int count) +{ + u8 headr[3] = { 0x00, 0x00, 0x01} ; - if (pr){ - if (ai->bit_rate == 0) - printk(" Bit rate: free"); - else if (ai->bit_rate == 0xf) - printk(" BRate: reserved"); - else - printk(" BRate: %d kb/s", ai->bit_rate/1000); + if (p->count < 6){ + memcpy(p->buf, headr, 3); + p->count = 6; } - fr = (headr[2] & 0x0c ) >> 2; - ai->frequency = freq[fr]*100; - if (pr){ - if (ai->frequency == 3) - printk(" Freq: reserved\n"); - else - printk(" Freq: %d kHz\n",ai->frequency); - + if (p->count + count < p->size){ + memcpy(p->buf+p->count, data, count); + p->count += count; + } else { + int rest = p->size - p->count; + memcpy(p->buf+p->count, data, rest); + p->count += rest; + send_ipack(p); + if (count - rest > 0) + write_ipack(p, data+rest, count-rest); } - ai->off = c; - return 0; } -int get_ac3info(uint8_t *mbuf, int count, AudioInfo *ai, int pr) + +int dvb_filter_instant_repack(u8 *buf, int count, ipack *p) { - uint8_t *headr; - int found = 0; - int c = 0; - uint8_t frame = 0; - int fr = 0; + int l; + int c=0; - while ( !found && c < count){ - uint8_t *b = mbuf+c; + while (c < count && (p->mpeg == 0 || + (p->mpeg == 1 && p->found < 7) || + (p->mpeg == 2 && p->found < 9)) + && (p->found < 5 || !p->done)){ + switch ( p->found ){ + case 0: + case 1: + if (buf[c] == 0x00) p->found++; + else p->found = 0; + c++; + break; + case 2: + if (buf[c] == 0x01) p->found++; + else if (buf[c] == 0) { + p->found = 2; + } else p->found = 0; + c++; + break; + case 3: + p->cid = 0; + switch (buf[c]){ + case PROG_STREAM_MAP: + case PRIVATE_STREAM2: + case PROG_STREAM_DIR: + case ECM_STREAM : + case EMM_STREAM : + case PADDING_STREAM : + case DSM_CC_STREAM : + case ISO13522_STREAM: + p->done = 1; + case PRIVATE_STREAM1: + case VIDEO_STREAM_S ... VIDEO_STREAM_E: + case AUDIO_STREAM_S ... AUDIO_STREAM_E: + p->found++; + p->cid = buf[c]; + c++; + break; + default: + p->found = 0; + break; + } + break; - if ( b[0] == 0x0b && b[1] == 0x77 ) - found = 1; - else { + case 4: + if (count-c > 1){ + p->plen[0] = buf[c]; c++; + p->plen[1] = buf[c]; + c++; + p->found+=2; + p->plength=(p->plen[0]<<8)|p->plen[1]; + } else { + p->plen[0] = buf[c]; + p->found++; + return count; } + break; + case 5: + p->plen[1] = buf[c]; + c++; + p->found++; + p->plength=(p->plen[0]<<8)|p->plen[1]; + break; + case 6: + if (!p->done){ + p->flag1 = buf[c]; + c++; + p->found++; + if ( (p->flag1 & 0xC0) == 0x80 ) p->mpeg = 2; + else { + p->hlength = 0; + p->which = 0; + p->mpeg = 1; + p->flag2 = 0; } + } + break; - if (!found) return -1; - if (pr) - printk("Audiostream: AC3"); - - ai->off = c; - if (c+5 >= count) return -1; - - ai->layer = 0; // 0 for AC3 - headr = mbuf+c+2; - - frame = (headr[2]&0x3f); - ai->bit_rate = ac3_bitrates[frame >> 1]*1000; - - if (pr) - printk(" BRate: %d kb/s", ai->bit_rate/1000); + case 7: + if ( !p->done && p->mpeg == 2) { + p->flag2 = buf[c]; + c++; + p->found++; + } + break; - ai->frequency = (headr[2] & 0xc0 ) >> 6; - fr = (headr[2] & 0xc0 ) >> 6; - ai->frequency = freq[fr]*100; - if (pr) printk (" Freq: %d Hz\n", ai->frequency); + case 8: + if ( !p->done && p->mpeg == 2) { + p->hlength = buf[c]; + c++; + p->found++; + } + break; + default: - ai->framesize = ac3_frames[fr][frame >> 1]; - if ((frame & 1) && (fr == 1)) ai->framesize++; - ai->framesize = ai->framesize << 1; - if (pr) printk (" Framesize %d\n", ai->framesize); + break; + } + } + if (c == count) return count; - return 0; -} + if (!p->plength) p->plength = MMAX_PLENGTH-6; -uint8_t *skip_pes_header(uint8_t **bufp) -{ - uint8_t *inbuf = *bufp; - uint8_t *buf = inbuf; - uint8_t *pts = NULL; - int skip = 0; + if ( p->done || ((p->mpeg == 2 && p->found >= 9) || + (p->mpeg == 1 && p->found >= 7)) ){ + switch (p->cid){ -int mpeg1_skip_table[16] = { - 1, 0xffff, 5, 10, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff -}; + case AUDIO_STREAM_S ... AUDIO_STREAM_E: + case VIDEO_STREAM_S ... VIDEO_STREAM_E: + case PRIVATE_STREAM1: + if (p->mpeg == 2 && p->found == 9) { + write_ipack(p, &p->flag1, 1); + write_ipack(p, &p->flag2, 1); + write_ipack(p, &p->hlength, 1); + } - if ((inbuf[6] & 0xc0) == 0x80){ /* mpeg2 */ - if (buf[7] & PTS_ONLY) - pts = buf+9; - else pts = NULL; - buf = inbuf + 9 + inbuf[8]; - } else { /* mpeg1 */ - for (buf = inbuf + 6; *buf == 0xff; buf++) - if (buf == inbuf + 6 + 16) { - break; - } - if ((*buf & 0xc0) == 0x40) - buf += 2; - skip = mpeg1_skip_table [*buf >> 4]; - if (skip == 5 || skip == 10) pts = buf; - else pts = NULL; + if (p->mpeg == 1 && p->found == 7) + write_ipack(p, &p->flag1, 1); - buf += mpeg1_skip_table [*buf >> 4]; + if (p->mpeg == 2 && (p->flag2 & PTS_ONLY) && + p->found < 14) { + while (c < count && p->found < 14) { + p->pts[p->found-9] = buf[c]; + write_ipack(p, buf+c, 1); + c++; + p->found++; + } + if (c == count) return count; } - *bufp = buf; - return pts; -} - + if (p->mpeg == 1 && p->which < 2000) { -void initialize_quant_matrix( uint32_t *matrix ) -{ - int i; + if (p->found == 7) { + p->check = p->flag1; + p->hlength = 1; + } - matrix[0] = 0x08101013; - matrix[1] = 0x10131616; - matrix[2] = 0x16161616; - matrix[3] = 0x1a181a1b; - matrix[4] = 0x1b1b1a1a; - matrix[5] = 0x1a1a1b1b; - matrix[6] = 0x1b1d1d1d; - matrix[7] = 0x2222221d; - matrix[8] = 0x1d1d1b1b; - matrix[9] = 0x1d1d2020; - matrix[10] = 0x22222526; - matrix[11] = 0x25232322; - matrix[12] = 0x23262628; - matrix[13] = 0x28283030; - matrix[14] = 0x2e2e3838; - matrix[15] = 0x3a454553; + while (!p->which && c < count && + p->check == 0xFF){ + p->check = buf[c]; + write_ipack(p, buf+c, 1); + c++; + p->found++; + p->hlength++; + } - for ( i = 16 ; i < 32 ; i++ ) - matrix[i] = 0x10101010; -} + if ( c == count) return count; -void initialize_mpg_picture(mpg_picture *pic) -{ - int i; + if ( (p->check & 0xC0) == 0x40 && !p->which){ + p->check = buf[c]; + write_ipack(p, buf+c, 1); + c++; + p->found++; + p->hlength++; - /* set MPEG1 */ - pic->mpeg1_flag = 1; - pic->profile_and_level = 0x4A ; /* MP@LL */ - pic->progressive_sequence = 1; - pic->low_delay = 0; + p->which = 1; + if ( c == count) return count; + p->check = buf[c]; + write_ipack(p, buf+c, 1); + c++; + p->found++; + p->hlength++; + p->which = 2; + if ( c == count) return count; + } - pic->sequence_display_extension_flag = 0; - for ( i = 0 ; i < 4 ; i++ ){ - pic->frame_centre_horizontal_offset[i] = 0; - pic->frame_centre_vertical_offset[i] = 0; + if (p->which == 1){ + p->check = buf[c]; + write_ipack(p, buf+c, 1); + c++; + p->found++; + p->hlength++; + p->which = 2; + if ( c == count) return count; } - pic->last_frame_centre_horizontal_offset = 0; - pic->last_frame_centre_vertical_offset = 0; - pic->picture_display_extension_flag[0] = 0; - pic->picture_display_extension_flag[1] = 0; - pic->sequence_header_flag = 0; - pic->gop_flag = 0; - pic->sequence_end_flag = 0; -} + if ( (p->check & 0x30) && p->check != 0xFF){ + p->flag2 = (p->check & 0xF0) << 2; + p->pts[0] = p->check; + p->which = 3; + } + if ( c == count) return count; + if (p->which > 2){ + if ((p->flag2 & PTS_DTS_FLAGS) + == PTS_ONLY){ + while (c < count && + p->which < 7){ + p->pts[p->which-2] = + buf[c]; + write_ipack(p,buf+c,1); + c++; + p->found++; + p->which++; + p->hlength++; + } + if ( c == count) return count; + } else if ((p->flag2 & PTS_DTS_FLAGS) + == PTS_DTS){ + while (c < count && + p->which< 12){ + if (p->which< 7) + p->pts[p->which + -2] = + buf[c]; + write_ipack(p,buf+c,1); + c++; + p->found++; + p->which++; + p->hlength++; + } + if ( c == count) return count; + } + p->which = 2000; + } -void mpg_set_picture_parameter( int32_t field_type, mpg_picture *pic ) -{ - int16_t last_h_offset; - int16_t last_v_offset; + } - int16_t *p_h_offset; - int16_t *p_v_offset; + while (c < count && p->found < p->plength+6){ + l = count -c; + if (l+p->found > p->plength+6) + l = p->plength+6-p->found; + write_ipack(p, buf+c, l); + p->found += l; + c += l; + } - if ( pic->mpeg1_flag ){ - pic->picture_structure[field_type] = VIDEO_FRAME_PICTURE; - pic->top_field_first = 0; - pic->repeat_first_field = 0; - pic->progressive_frame = 1; - pic->picture_coding_parameter = 0x000010; + break; } - /* Reset flag */ - pic->picture_display_extension_flag[field_type] = 0; - last_h_offset = pic->last_frame_centre_horizontal_offset; - last_v_offset = pic->last_frame_centre_vertical_offset; - if ( field_type == FIRST_FIELD ){ - p_h_offset = pic->frame_centre_horizontal_offset; - p_v_offset = pic->frame_centre_vertical_offset; - *p_h_offset = last_h_offset; - *(p_h_offset + 1) = last_h_offset; - *(p_h_offset + 2) = last_h_offset; - *p_v_offset = last_v_offset; - *(p_v_offset + 1) = last_v_offset; - *(p_v_offset + 2) = last_v_offset; + if ( p->done ){ + if( p->found + count - c < p->plength+6){ + p->found += count-c; + c = count; } else { - pic->frame_centre_horizontal_offset[3] = last_h_offset; - pic->frame_centre_vertical_offset[3] = last_v_offset; + c += p->plength+6 - p->found; + p->found = p->plength+6; + } } -} - -void init_mpg_picture( mpg_picture *pic, int chan, int32_t field_type) -{ - pic->picture_header = 0; - pic->sequence_header_data - = ( INIT_HORIZONTAL_SIZE << 20 ) - | ( INIT_VERTICAL_SIZE << 8 ) - | ( INIT_ASPECT_RATIO << 4 ) - | ( INIT_FRAME_RATE ); - pic->mpeg1_flag = 0; - pic->vinfo.horizontal_size - = INIT_DISP_HORIZONTAL_SIZE; - pic->vinfo.vertical_size - = INIT_DISP_VERTICAL_SIZE; - pic->picture_display_extension_flag[field_type] - = 0; - pic->pts_flag[field_type] = 0; - pic->sequence_gop_header = 0; - pic->picture_header = 0; - pic->sequence_header_flag = 0; - pic->gop_flag = 0; - pic->sequence_end_flag = 0; - pic->sequence_display_extension_flag = 0; - pic->last_frame_centre_horizontal_offset = 0; - pic->last_frame_centre_vertical_offset = 0; - pic->channel = chan; + if (p->plength && p->found == p->plength+6) { + send_ipack(p); + dvb_filter_ipack_reset(p); + if (c < count) + dvb_filter_instant_repack(buf+c, count-c, p); + } + } + return count; } + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/media/dvb/dvb-core/dvb_filter.h linux.2.5.47-ac4/drivers/media/dvb/dvb-core/dvb_filter.h --- linux.2.5.47/drivers/media/dvb/dvb-core/dvb_filter.h 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/media/dvb/dvb-core/dvb_filter.h 2002-11-13 01:26:41.000000000 +0000 @@ -6,18 +6,18 @@ #include "demux.h" -typedef int (pes2ts_cb_t) (void *, unsigned char *); +typedef int (dvb_filter_pes2ts_cb_t) (void *, unsigned char *); -typedef struct pes2ts_s { +typedef struct dvb_filter_pes2ts_s { unsigned char buf[188]; unsigned char cc; - pes2ts_cb_t *cb; + dvb_filter_pes2ts_cb_t *cb; void *priv; -} pes2ts_t; +} dvb_filter_pes2ts_t; -void pes2ts_init(pes2ts_t *p2ts, unsigned short pid, - pes2ts_cb_t *cb, void *priv); -int pes2ts(pes2ts_t *p2ts, unsigned char *pes, int len); +void dvb_filter_pes2ts_init(dvb_filter_pes2ts_t *p2ts, unsigned short pid, + dvb_filter_pes2ts_cb_t *cb, void *priv); +int dvb_filter_pes2ts(dvb_filter_pes2ts_t *p2ts, unsigned char *pes, int len); #define PROG_STREAM_MAP 0xBC @@ -224,26 +224,11 @@ } AudioInfo; -void reset_ipack(ipack *p); -int instant_repack(u8 *buf, int count, ipack *p); -void init_ipack(ipack *p, int size, +void dvb_filter_ipack_reset(ipack *p); +int dvb_filter_instant_repack(u8 *buf, int count, ipack *p); +void dvb_filter_ipack_init(ipack *p, int size, void (*func)(u8 *buf, int size, void *priv)); -void free_ipack(ipack * p); -void setup_ts2pes(ipack *pa, ipack *pv, u16 *pida, u16 *pidv, - void (*pes_write)(u8 *buf, int count, void *data), - void *priv); -void ts_to_pes(ipack *p, u8 *buf); -void send_ipack(ipack *p); -void send_ipack_rest(ipack *p); -int get_ainfo(uint8_t *mbuf, int count, AudioInfo *ai, int pr); -int get_ac3info(uint8_t *mbuf, int count, AudioInfo *ai, int pr); -int get_vinfo(uint8_t *mbuf, int count, VideoInfo *vi, int pr); -uint8_t *skip_pes_header(uint8_t **bufp); -void initialize_quant_matrix( uint32_t *matrix ); -void initialize_mpg_picture(mpg_picture *pic); -void init_mpg_picture( mpg_picture *pic, int chan, int32_t field_type); -void mpg_set_picture_parameter( int32_t field_type, mpg_picture *pic ); -int read_sequence_header(uint8_t *headr, VideoInfo *vi, int pr); -int read_gop_header(uint8_t *headr, mpg_picture *pic, int pr); -int read_picture_header(uint8_t *headr, mpg_picture *pic, int field, int pr); +void dvb_filter_ipack_free(ipack * p); +void dvb_filter_ipack_flush(ipack *p); + #endif diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/media/dvb/dvb-core/dvb_frontend.c linux.2.5.47-ac4/drivers/media/dvb/dvb-core/dvb_frontend.c --- linux.2.5.47/drivers/media/dvb/dvb-core/dvb_frontend.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/media/dvb/dvb-core/dvb_frontend.c 2002-11-13 01:26:41.000000000 +0000 @@ -83,7 +83,7 @@ struct dvb_frontend_ioctl_data { struct list_head list_head; - struct dvb_adapter_s *adapter; + struct dvb_adapter *adapter; int (*before_ioctl) (struct dvb_frontend *frontend, unsigned int cmd, void *arg); int (*after_ioctl) (struct dvb_frontend *frontend, @@ -336,9 +336,6 @@ struct dvb_frontend *frontend = &fe->frontend; int err; - dprintk ("%s: f == %i, drift == %i\n", - __FUNCTION__, param->frequency, fe->lnb_drift); - dvb_bend_frequency (fe, 0); if (first_trial) { @@ -352,6 +349,9 @@ sizeof (struct dvb_frontend_parameters)); } + dprintk ("%s: f == %i, drift == %i\n", + __FUNCTION__, param->frequency, fe->lnb_drift); + param->frequency += fe->lnb_drift + fe->bending; err = dvb_frontend_internal_ioctl (frontend, FE_SET_FRONTEND, param); param->frequency -= fe->lnb_drift + fe->bending; @@ -367,9 +367,8 @@ struct dvb_frontend *frontend = &fe->frontend; struct dvb_frontend_parameters *init_param; - printk ("%s: initialising frontend %i:%i (%s)...\n", __FUNCTION__, - frontend->i2c->adapter->num, frontend->i2c->id, - fe->info->name); + printk ("DVB: initialising frontend %i:%i (%s)...\n", + frontend->i2c->adapter->num, frontend->i2c->id, fe->info->name); dvb_frontend_internal_ioctl (frontend, FE_INIT, NULL); @@ -436,15 +435,20 @@ */ { int j = fe->lost_sync_count; - int stepsize = fe->info->frequency_stepsize; - - if (j % 32 == 0) - fe->lnb_drift = 0; + int stepsize; - if (j % 2) - fe->lnb_drift += stepsize * ((j+1)/2); + if (fe->info->type == FE_QPSK) + stepsize = fe->parameters.u.qpsk.symbol_rate / 16000; else + stepsize = fe->info->frequency_stepsize * 2; + + if (j % 32 == 0) { + fe->lnb_drift = 0; + } else { fe->lnb_drift = -fe->lnb_drift; + if (j % 2) + fe->lnb_drift += stepsize; + } dvb_frontend_set_parameters (fe, &fe->parameters, 0); } @@ -511,7 +515,8 @@ fe->lost_sync_count = 0; } else { fe->lost_sync_count++; - + if (fe->lost_sync_count < 10) /* XXX FIXME CHECKME! */ + continue; dvb_frontend_recover (fe); delay = HZ/5; if (jiffies - fe->lost_sync_jiffies > TIMEOUT) { @@ -627,7 +632,7 @@ static int dvb_frontend_open (struct inode *inode, struct file *file) { - dvb_device_t *dvbdev = file->private_data; + struct dvb_device *dvbdev = file->private_data; struct dvb_frontend_data *fe = dvbdev->priv; int ret; @@ -648,7 +653,7 @@ static int dvb_frontend_release (struct inode *inode, struct file *file) { - dvb_device_t *dvbdev = file->private_data; + struct dvb_device *dvbdev = file->private_data; struct dvb_frontend_data *fe = dvbdev->priv; dprintk ("%s\n", __FUNCTION__); @@ -661,7 +666,7 @@ int -dvb_add_frontend_ioctls (struct dvb_adapter_s *adapter, +dvb_add_frontend_ioctls (struct dvb_adapter *adapter, int (*before_ioctl) (struct dvb_frontend *frontend, unsigned int cmd, void *arg), int (*after_ioctl) (struct dvb_frontend *frontend, @@ -715,7 +720,7 @@ void -dvb_remove_frontend_ioctls (struct dvb_adapter_s *adapter, +dvb_remove_frontend_ioctls (struct dvb_adapter *adapter, int (*before_ioctl) (struct dvb_frontend *frontend, unsigned int cmd, void *arg), int (*after_ioctl) (struct dvb_frontend *frontend, @@ -748,7 +753,7 @@ int -dvb_add_frontend_notifier (struct dvb_adapter_s *adapter, +dvb_add_frontend_notifier (struct dvb_adapter *adapter, void (*callback) (fe_status_t s, void *data), void *data) { @@ -791,7 +796,7 @@ void -dvb_remove_frontend_notifier (struct dvb_adapter_s *adapter, +dvb_remove_frontend_notifier (struct dvb_adapter *adapter, void (*callback) (fe_status_t s, void *data)) { struct list_head *entry; @@ -827,11 +832,11 @@ static struct file_operations dvb_frontend_fops = { - owner: THIS_MODULE, - ioctl: dvb_generic_ioctl, - poll: dvb_frontend_poll, - open: dvb_frontend_open, - release: dvb_frontend_release + .owner = THIS_MODULE, + .ioctl = dvb_generic_ioctl, + .poll = dvb_frontend_poll, + .open = dvb_frontend_open, + .release = dvb_frontend_release }; @@ -845,9 +850,11 @@ { struct list_head *entry; struct dvb_frontend_data *fe; - dvb_device_t dvbdev_template = { users: 1, writers: 1, - fops: &dvb_frontend_fops, - kernel_ioctl: dvb_frontend_ioctl + static const struct dvb_device dvbdev_template = { + .users = 1, + .writers = 1, + .fops = &dvb_frontend_fops, + .kernel_ioctl = dvb_frontend_ioctl }; dprintk ("%s\n", __FUNCTION__); @@ -878,7 +885,9 @@ list_for_each (entry, &frontend_ioctl_list) { struct dvb_frontend_ioctl_data *ioctl; - ioctl = list_entry (entry, struct dvb_frontend_ioctl_data, list_head); + ioctl = list_entry (entry, + struct dvb_frontend_ioctl_data, + list_head); if (ioctl->adapter == i2c->adapter) { fe->frontend.before_ioctl = ioctl->before_ioctl; @@ -936,3 +945,4 @@ MODULE_PARM(dvb_shutdown_timeout,"i"); MODULE_PARM_DESC(dvb_frontend_debug, "enable verbose debug messages"); MODULE_PARM_DESC(dvb_shutdown_timeout, "wait seconds after close() before suspending hardware"); + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/media/dvb/dvb-core/dvb_frontend.h linux.2.5.47-ac4/drivers/media/dvb/dvb-core/dvb_frontend.h --- linux.2.5.47/drivers/media/dvb/dvb-core/dvb_frontend.h 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/media/dvb/dvb-core/dvb_frontend.h 2002-11-13 01:26:41.000000000 +0000 @@ -90,7 +90,7 @@ * Return value: number of frontends where the ioctl's were applied. */ extern int -dvb_add_frontend_ioctls (struct dvb_adapter_s *adapter, +dvb_add_frontend_ioctls (struct dvb_adapter *adapter, int (*before_ioctl) (struct dvb_frontend *frontend, unsigned int cmd, void *arg), int (*after_ioctl) (struct dvb_frontend *frontend, @@ -99,18 +99,18 @@ extern void -dvb_remove_frontend_ioctls (struct dvb_adapter_s *adapter, +dvb_remove_frontend_ioctls (struct dvb_adapter *adapter, int (*before_ioctl) (struct dvb_frontend *frontend, unsigned int cmd, void *arg), int (*after_ioctl) (struct dvb_frontend *frontend, unsigned int cmd, void *arg)); extern int -dvb_add_frontend_notifier (struct dvb_adapter_s *adapter, +dvb_add_frontend_notifier (struct dvb_adapter *adapter, void (*callback) (fe_status_t s, void *data), void *data); extern void -dvb_remove_frontend_notifier (struct dvb_adapter_s *adapter, +dvb_remove_frontend_notifier (struct dvb_adapter *adapter, void (*callback) (fe_status_t s, void *data)); #endif diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/media/dvb/dvb-core/dvb_i2c.c linux.2.5.47-ac4/drivers/media/dvb/dvb-core/dvb_i2c.c --- linux.2.5.47/drivers/media/dvb/dvb-core/dvb_i2c.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/media/dvb/dvb-core/dvb_i2c.c 2002-11-13 01:26:41.000000000 +0000 @@ -173,7 +173,7 @@ dvb_register_i2c_bus (int (*xfer) (struct dvb_i2c_bus *i2c, struct i2c_msg msgs[], int num), void *data, - struct dvb_adapter_s *adapter, + struct dvb_adapter *adapter, int id) { struct dvb_i2c_bus *i2c; @@ -200,7 +200,7 @@ struct dvb_i2c_bus* dvb_find_i2c_bus (int (*xfer) (struct dvb_i2c_bus *i2c, struct i2c_msg msgs[], int num), - struct dvb_adapter_s *adapter, + struct dvb_adapter *adapter, int id) { struct list_head *entry; @@ -231,7 +231,7 @@ void dvb_unregister_i2c_bus (int (*xfer) (struct dvb_i2c_bus *i2c, struct i2c_msg msgs[], int num), - struct dvb_adapter_s *adapter, + struct dvb_adapter *adapter, int id) { struct dvb_i2c_bus *i2c = dvb_find_i2c_bus (xfer, adapter, id); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/media/dvb/dvb-core/dvb_i2c.h linux.2.5.47-ac4/drivers/media/dvb/dvb-core/dvb_i2c.h --- linux.2.5.47/drivers/media/dvb/dvb-core/dvb_i2c.h 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/media/dvb/dvb-core/dvb_i2c.h 2002-11-13 01:26:41.000000000 +0000 @@ -32,7 +32,7 @@ struct list_head list_head; int (*xfer) (struct dvb_i2c_bus *i2c, struct i2c_msg msgs[], int num); void *data; - struct dvb_adapter_s *adapter; + struct dvb_adapter *adapter; int id; struct list_head client_list; }; @@ -43,13 +43,13 @@ struct i2c_msg msgs[], int num), void *data, - struct dvb_adapter_s *adapter, + struct dvb_adapter *adapter, int id); extern void dvb_unregister_i2c_bus (int (*xfer) (struct dvb_i2c_bus *i2c, struct i2c_msg msgs[], int num), - struct dvb_adapter_s *adapter, + struct dvb_adapter *adapter, int id); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/media/dvb/dvb-core/dvb_ksyms.c linux.2.5.47-ac4/drivers/media/dvb/dvb-core/dvb_ksyms.c --- linux.2.5.47/drivers/media/dvb/dvb-core/dvb_ksyms.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/media/dvb/dvb-core/dvb_ksyms.c 2002-11-13 01:26:41.000000000 +0000 @@ -9,11 +9,12 @@ #include "dvb_net.h" -EXPORT_SYMBOL(DmxDevInit); -EXPORT_SYMBOL(DmxDevRelease); -EXPORT_SYMBOL(DvbDmxInit); -EXPORT_SYMBOL(DvbDmxRelease); -EXPORT_SYMBOL(DvbDmxSWFilterPackets); +EXPORT_SYMBOL(dvb_dmxdev_init); +EXPORT_SYMBOL(dvb_dmxdev_release); +EXPORT_SYMBOL(dvb_dmx_init); +EXPORT_SYMBOL(dvb_dmx_release); +EXPORT_SYMBOL(dvb_dmx_swfilter_packet); +EXPORT_SYMBOL(dvb_dmx_swfilter_packets); EXPORT_SYMBOL(dvb_register_frontend); EXPORT_SYMBOL(dvb_unregister_frontend); @@ -37,13 +38,12 @@ EXPORT_SYMBOL(dvb_generic_ioctl); EXPORT_SYMBOL(dvb_generic_open); EXPORT_SYMBOL(dvb_generic_release); -EXPORT_SYMBOL(generic_usercopy); -EXPORT_SYMBOL(init_ipack); -EXPORT_SYMBOL(reset_ipack); -EXPORT_SYMBOL(free_ipack); -EXPORT_SYMBOL(send_ipack_rest); -EXPORT_SYMBOL(instant_repack); -EXPORT_SYMBOL(pes2ts_init); -EXPORT_SYMBOL(pes2ts); +EXPORT_SYMBOL(dvb_filter_ipack_init); +EXPORT_SYMBOL(dvb_filter_ipack_reset); +EXPORT_SYMBOL(dvb_filter_ipack_free); +EXPORT_SYMBOL(dvb_filter_ipack_flush); +EXPORT_SYMBOL(dvb_filter_instant_repack); +EXPORT_SYMBOL(dvb_filter_pes2ts_init); +EXPORT_SYMBOL(dvb_filter_pes2ts); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/media/dvb/dvb-core/dvb_net.c linux.2.5.47-ac4/drivers/media/dvb/dvb-core/dvb_net.c --- linux.2.5.47/drivers/media/dvb/dvb-core/dvb_net.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/media/dvb/dvb-core/dvb_net.c 2002-11-13 01:26:41.000000000 +0000 @@ -435,7 +435,7 @@ int dvb_net_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *parg) { - dvb_device_t *dvbdev=(dvb_device_t *) file->private_data; + struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; dvb_net_t *dvbnet=(dvb_net_t *) dvbdev->priv; if (((file->f_flags&O_ACCMODE)==O_RDONLY)) @@ -462,21 +462,18 @@ } static struct file_operations dvb_net_fops = { - owner: THIS_MODULE, - read: 0, - write: 0, - ioctl: dvb_generic_ioctl, - open: dvb_generic_open, - release: dvb_generic_release, - poll: 0, + .owner = THIS_MODULE, + .ioctl = dvb_generic_ioctl, + .open = dvb_generic_open, + .release = dvb_generic_release, }; -static dvb_device_t dvbdev_net = { - priv: 0, - users: 1, - writers: 1, - fops: &dvb_net_fops, - kernel_ioctl: dvb_net_ioctl, +static struct dvb_device dvbdev_net = { + .priv = 0, + .users = 1, + .writers = 1, + .fops = &dvb_net_fops, + .kernel_ioctl = dvb_net_ioctl, }; void @@ -493,7 +490,7 @@ } int -dvb_net_init(dvb_adapter_t *adap, dvb_net_t *dvbnet, dmx_demux_t *demux) +dvb_net_init(struct dvb_adapter *adap, dvb_net_t *dvbnet, dmx_demux_t *demux) { int i; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/media/dvb/dvb-core/dvb_net.h linux.2.5.47-ac4/drivers/media/dvb/dvb-core/dvb_net.h --- linux.2.5.47/drivers/media/dvb/dvb-core/dvb_net.h 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/media/dvb/dvb-core/dvb_net.h 2002-11-13 01:26:41.000000000 +0000 @@ -47,7 +47,7 @@ } dvb_net_priv_t; typedef struct dvb_net_s { - dvb_device_t *dvbdev; + struct dvb_device *dvbdev; int card_num; int dev_num; @@ -58,6 +58,6 @@ void dvb_net_release(dvb_net_t *); -int dvb_net_init(dvb_adapter_t *, dvb_net_t *, dmx_demux_t *); +int dvb_net_init(struct dvb_adapter *, dvb_net_t *, dmx_demux_t *); #endif diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/media/dvb/frontends/alps_bsru6.c linux.2.5.47-ac4/drivers/media/dvb/frontends/alps_bsru6.c --- linux.2.5.47/drivers/media/dvb/frontends/alps_bsru6.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/media/dvb/frontends/alps_bsru6.c 2002-11-13 01:26:51.000000000 +0000 @@ -1,8 +1,9 @@ /* - Alps BSRU6 DVB QPSK frontend driver + Alps BSRU6 and LG TDQB-S00x DVB QPSK frontend driver Copyright (C) 2001-2002 Convergence Integrated Media GmbH - , + , , + 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 @@ -32,12 +33,16 @@ #define M_CLK (88000000UL) - /* M=21, K=0, P=0, f_VCO = 4MHz*4*(M+1)/(K+1) = 352 MHz */ + static struct dvb_frontend_info bsru6_info = { +#ifdef CONFIG_ALPS_BSRU6_IS_LG_TDQBS00X + name: "LG TDQB-S00x", +#else name: "Alps BSRU6", +#endif type: FE_QPSK, frequency_min: 950000, frequency_max: 2150000, @@ -63,7 +68,8 @@ 0x05, 0x35, // SDAT:0 SCLT:0 I2CT:1 0x06, 0x00, // DAC mode and MSB 0x07, 0x00, // DAC LSB - 0x08, 0x43, // DiSEqC +// 0x08, 0x43, // DiSEqC + 0x08, 0x03, // DiSEqC 0x09, 0x00, 0x0a, 0x42, 0x0c, 0x51, // QPSK reverse:1 Nyquist:0 OP0 val:1 OP0 con:1 OP1 val:1 OP1 con:1 @@ -79,17 +85,20 @@ 0x15, 0xc9, // lock detector threshold 0x16, 0x1d, - 0x17, 0x0, + 0x17, 0x00, 0x18, 0x14, 0x19, 0xf2, 0x1a, 0x11, 0x1b, 0x9c, - 0x1c, 0x0, - 0x1d, 0x0, - 0x1e, 0xb, + 0x1c, 0x00, + 0x1d, 0x00, + 0x1e, 0x0b, + 0x1f, 0x50, + 0x20, 0x00, + 0x21, 0x00, 0x22, 0x00, 0x23, 0x00, 0x24, 0xff, @@ -110,16 +119,37 @@ 0x33, 0xfc, // rs control 0x34, 0x93, // error control - 0x0b, 0x00, - 0x27, 0x00, 0x2f, 0x00, 0x30, 0x00, - 0x35, 0x00, 0x36, 0x00, 0x37, 0x00, - 0x38, 0x00, 0x39, 0x00, 0x3a, 0x00, 0x3b, 0x00, - 0x3c, 0x00, 0x3d, 0x00, 0x3e, 0x00, 0x3f, 0x00, - 0x40, 0x00, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, - 0x44, 0x00, 0x45, 0x00, 0x46, 0x00, 0x47, 0x00, - 0x48, 0x00, 0x49, 0x00, 0x4a, 0x00, 0x4b, 0x00, - 0x4c, 0x00, 0x4d, 0x00, 0x4e, 0x00, 0x4f, 0x00 + 0x27, 0x00, + 0x2f, 0x00, + 0x30, 0x00, + 0x35, 0x00, + 0x36, 0x00, + 0x37, 0x00, + 0x38, 0x00, + 0x39, 0x00, + 0x3a, 0x00, + 0x3b, 0x00, + 0x3c, 0x00, + 0x3d, 0x00, + 0x3e, 0x00, + 0x3f, 0x00, + 0x40, 0x00, + 0x41, 0x00, + 0x42, 0x00, + 0x43, 0x00, + 0x44, 0x00, + 0x45, 0x00, + 0x46, 0x00, + 0x47, 0x00, + 0x48, 0x00, + 0x49, 0x00, + 0x4a, 0x00, + 0x4b, 0x00, + 0x4c, 0x00, + 0x4d, 0x00, + 0x4e, 0x00, + 0x4f, 0x00 }; @@ -231,12 +261,27 @@ static -int stv0299_set_inversion (struct dvb_i2c_bus *i2c, int inversion) +int stv0299_set_inversion (struct dvb_i2c_bus *i2c, + fe_spectral_inversion_t inversion) { u8 val; dprintk ("%s\n", __FUNCTION__); +#ifdef CONFIG_ALPS_BSRU6_IS_LG_TDQBS00X /* reversed I/Q pins */ + switch (inversion) { + case INVERSION_AUTO: + return -EOPNOTSUPP; + case INVERSION_OFF: + val = stv0299_readreg (i2c, 0x0c); + return stv0299_writereg (i2c, 0x0c, val & 0xfe); + case INVERSION_ON: + val = stv0299_readreg (i2c, 0x0c); + return stv0299_writereg (i2c, 0x0c, val | 0x01); + default: + return -EINVAL; + }; +#else switch (inversion) { case INVERSION_AUTO: return -EOPNOTSUPP; @@ -248,7 +293,8 @@ return stv0299_writereg (i2c, 0x0c, val & 0xfe); default: return -EINVAL; - } + }; +#endif } @@ -277,9 +323,10 @@ static -fe_code_rate_t stv0299_get_FEC (struct dvb_i2c_bus *i2c) +fe_code_rate_t stv0299_get_fec (struct dvb_i2c_bus *i2c) { - static fe_code_rate_t fec_tab [] = { FEC_2_3, FEC_3_4, FEC_5_6, FEC_7_8, FEC_1_2 }; + static fe_code_rate_t fec_tab [] = { FEC_2_3, FEC_3_4, FEC_5_6, + FEC_7_8, FEC_1_2 }; u8 index; dprintk ("%s\n", __FUNCTION__); @@ -343,6 +390,9 @@ dprintk ("%s\n", __FUNCTION__); + if (stv0299_wait_diseqc_idle (i2c, 100) < 0) + return -ETIMEDOUT; + val = stv0299_readreg (i2c, 0x08); if (stv0299_writereg (i2c, 0x08, (val & ~0x7) | 0x6)) /* DiSEqC mode */ @@ -356,12 +406,7 @@ return -EREMOTEIO; } - /* Shouldn't we wait for idle state (FE=1, FF=0) here to - make certain all bytes have been sent ? - Hmm, actually we should do that before all mode changes too ... - if (stv0299_wait_diseqc_idle (i2c, 100) < 0) */ - - if (stv0299_wait_diseqc_fifo (i2c, 100) < 0) + if (stv0299_wait_diseqc_idle (i2c, 100) < 0) return -ETIMEDOUT; return 0; @@ -375,18 +420,18 @@ dprintk ("%s\n", __FUNCTION__); - val = stv0299_readreg (i2c, 0x08); - - if (stv0299_wait_diseqc_fifo (i2c, 100) < 0) + if (stv0299_wait_diseqc_idle (i2c, 100) < 0) return -ETIMEDOUT; + val = stv0299_readreg (i2c, 0x08); + if (stv0299_writereg (i2c, 0x08, (val & ~0x7) | 0x2)) /* burst mode */ return -EREMOTEIO; if (stv0299_writereg (i2c, 0x09, burst == SEC_MINI_A ? 0x00 : 0xff)) return -EREMOTEIO; - if (stv0299_wait_diseqc_fifo (i2c, 100) < 0) + if (stv0299_wait_diseqc_idle (i2c, 100) < 0) return -ETIMEDOUT; if (stv0299_writereg (i2c, 0x08, val)) @@ -403,6 +448,9 @@ dprintk ("%s\n", __FUNCTION__); + if (stv0299_wait_diseqc_idle (i2c, 100) < 0) + return -ETIMEDOUT; + val = stv0299_readreg (i2c, 0x08); switch (tone) { @@ -445,8 +493,6 @@ u32 tmp; u8 aclk = 0xb4, bclk = 0x51; - dprintk ("%s\n", __FUNCTION__); - if (srate > M_CLK) srate = M_CLK; if (srate < 500000) @@ -479,7 +525,6 @@ } - static int stv0299_get_symbolrate (struct dvb_i2c_bus *i2c) { @@ -608,7 +653,7 @@ p->frequency += derot_freq; p->inversion = (stv0299_readreg (i2c, 0x0c) & 1) ? INVERSION_OFF : INVERSION_ON; - p->u.qpsk.fec_inner = stv0299_get_FEC (i2c); + p->u.qpsk.fec_inner = stv0299_get_fec (i2c); p->u.qpsk.symbol_rate = stv0299_get_symbolrate (i2c); break; } @@ -694,7 +739,7 @@ MODULE_PARM(debug,"i"); MODULE_PARM_DESC(debug, "enable verbose debug messages"); -MODULE_DESCRIPTION("BSRU6 DVB Frontend driver"); +MODULE_DESCRIPTION("Alps BSRU6/LG TDQB-S00x DVB Frontend driver"); MODULE_AUTHOR("Ralph Metzler, Holger Waechtler"); MODULE_LICENSE("GPL"); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/media/dvb/frontends/alps_bsrv2.c linux.2.5.47-ac4/drivers/media/dvb/frontends/alps_bsrv2.c --- linux.2.5.47/drivers/media/dvb/frontends/alps_bsrv2.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/media/dvb/frontends/alps_bsrv2.c 2002-11-13 01:26:51.000000000 +0000 @@ -342,7 +342,7 @@ *ber = ves1893_readreg (i2c, 0x15); *ber |= (ves1893_readreg (i2c, 0x16) << 8); - *ber |= (ves1893_readreg (i2c, 0x17) << 16); + *ber |= ((ves1893_readreg (i2c, 0x17) & 0x0f) << 16); *ber *= 10; break; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/media/dvb/frontends/alps_tdlb7.c linux.2.5.47-ac4/drivers/media/dvb/frontends/alps_tdlb7.c --- linux.2.5.47/drivers/media/dvb/frontends/alps_tdlb7.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.47-ac4/drivers/media/dvb/frontends/alps_tdlb7.c 2002-11-13 01:26:51.000000000 +0000 @@ -0,0 +1,437 @@ +/* + Driver for Alps TDLB7 Frontend + + Copyright (C) 1999 Juergen Peitz + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + + +/* + + Wrote this code mainly to get my own card running. It's working for me, but I + hope somebody who knows more about linux programming and the DVB driver can + improve it. + + Reused a lot from the existing driver and tuner code. + Thanks to everybody who worked on it! + + This driver needs a copy of the microcode file 'Sc_main.mc' from the Haupauge + windows driver in the 'usr/lib/DVB/driver/frontends' directory. + You can also pass the complete file name with the module parameter 'mcfile'. + + The code only needs to be loaded once after a power on. Because loading the + microcode to the card takes some time, you can use the 'loadcode=0' module + parameter, if you only want to reload the dvb driver. + + Juergen Peitz + +*/ + + + +#define __KERNEL_SYSCALLS__ +#include +#include +#include +#include +#include + +#include "compat.h" +#include "dvb_frontend.h" + +static int debug = 0; + +static int loadcode = 1; + +static char * mcfile = "/usr/lib/DVB/driver/frontends/Sc_main.mc"; + +#define dprintk if (debug) printk + +/* microcode size for sp8870 */ +#define SP8870_CODE_SIZE 16384 + +/* starting point for microcode in file 'Sc_main.mc' */ +#define SP8870_CODE_OFFSET 0x0A + + +static int errno; + +static +struct dvb_frontend_info tdlb7_info = { + name: "Alps TDLB7", + type: FE_OFDM, + frequency_min: 470000000, + frequency_max: 860000000, + frequency_stepsize: 166666, +#if 0 + frequency_tolerance: ???, + symbol_rate_min: ???, + symbol_rate_max: ???, + symbol_rate_tolerance: ???, + notifier_delay: 0, +#endif + caps: FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | + FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | + FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 +}; + + +static +int sp8870_writereg (struct dvb_i2c_bus *i2c, u16 reg, u16 data) +{ + u8 buf [] = { reg >> 8, reg & 0xff, data >> 8, data & 0xff }; + struct i2c_msg msg = { addr: 0x71, flags: 0, buf: buf, len: 4 }; + int err; + + if ((err = i2c->xfer (i2c, &msg, 1)) != 1) { + dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __FUNCTION__, err, reg, data); + return -EREMOTEIO; + } + + return 0; +} + + +static +u16 sp8870_readreg (struct dvb_i2c_bus *i2c, u16 reg) +{ + int ret; + u8 b0 [] = { reg >> 8 , reg & 0xff }; + u8 b1 [] = { 0, 0 }; + struct i2c_msg msg [] = { { addr: 0x71, flags: 0, buf: b0, len: 2 }, + { addr: 0x71, flags: I2C_M_RD, buf: b1, len: 2 } }; + + ret = i2c->xfer (i2c, msg, 2); + + if (ret != 2) + dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret); + + return (b1[0] << 8 | b1[1]); +} + + +static +int sp5659_write (struct dvb_i2c_bus *i2c, u8 data [4]) +{ + int ret; + struct i2c_msg msg = { addr: 0x60, flags: 0, buf: data, len: 4 }; + + ret = i2c->xfer (i2c, &msg, 1); + + if (ret != 1) + printk("%s: i/o error (ret == %i)\n", __FUNCTION__, ret); + + return (ret != 1) ? -1 : 0; +} + + +static +int sp5659_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq, u8 pwr) +{ + u32 div = (freq + 36200000) / 166666; + u8 buf [4] = { (div >> 8) & 0x7f, div & 0xff, 0x85, (pwr << 5) | 0x30 }; + + return sp5659_write (i2c, buf); +} + + +static +int sp8870_read_code(const char *fn, char **fp) +{ + int fd; + loff_t l; + char *dp; + + fd = open(fn, 0, 0); + if (fd == -1) { + printk(KERN_INFO "%s: Unable to load '%s'.\n", __FUNCTION__, fn); + return -1; + } + l = lseek(fd, 0L, 2); + if (l <= 0 || l < SP8870_CODE_OFFSET+SP8870_CODE_SIZE) { + printk(KERN_INFO "%s: code file too small '%s'\n", __FUNCTION__, fn); + sys_close(fd); + return -1; + } + lseek(fd, SP8870_CODE_OFFSET, 0); + *fp= dp = vmalloc(SP8870_CODE_SIZE); + if (dp == NULL) { + printk(KERN_INFO "%s: Out of memory loading '%s'.\n", __FUNCTION__, fn); + sys_close(fd); + return -1; + } + if (read(fd, dp, SP8870_CODE_SIZE) != SP8870_CODE_SIZE) { + printk(KERN_INFO "%s: Failed to read '%s'.\n",__FUNCTION__, fn); + vfree(dp); + sys_close(fd); + return -1; + } + sys_close(fd); + *fp = dp; + return 0; +} + + +static +int sp8870_load_code(struct dvb_i2c_bus *i2c) +{ + /* this takes a long time. is there a way to do it faster? */ + char *lcode; + struct i2c_msg msg; + unsigned char buf[255]; + int err; + int p=0; + int c; + mm_segment_t fs = get_fs(); + + sp8870_writereg(i2c,0x8F08,0x1FFF); + sp8870_writereg(i2c,0x8F0A,0x0000); + + set_fs(get_ds()); + if (sp8870_read_code(mcfile,(char**) &lcode)<0) return -1; + set_fs(fs); + while (pxfer (i2c, &msg, 1)) != 1) { + dprintk ("%s: i2c error (err == %i)\n", __FUNCTION__, err); + vfree(lcode); + return -EREMOTEIO; + } + + p+=252; + } + vfree(lcode); + return 0; +}; + + +static +int sp8870_init (struct dvb_i2c_bus *i2c) +{ + + dprintk ("%s\n", __FUNCTION__); + + sp8870_readreg(i2c,0x200); + sp8870_readreg(i2c,0x200); + sp8870_readreg(i2c,0x0F00); /* system controller stop */ + sp8870_readreg(i2c,0x0301); /* ???????? */ + sp8870_readreg(i2c,0x0309); /* integer carrier offset */ + sp8870_readreg(i2c,0x030A); /* fractional carrier offset */ + sp8870_readreg(i2c,0x0311); /* filter for 8 Mhz channel */ + sp8870_readreg(i2c,0x0319); /* sample rate correction bit [23..17] */ + sp8870_readreg(i2c,0x031A); /* sample rate correction bit [16..0] */ + sp8870_readreg(i2c,0x0338); /* ???????? */ + sp8870_readreg(i2c,0x0F00); + sp8870_readreg(i2c,0x0200); + + if (loadcode) { + dprintk("%s: loading mcfile '%s' !\n", __FUNCTION__, mcfile); + if (sp8870_load_code(i2c)==0) + dprintk("%s: microcode loaded!\n", __FUNCTION__); + }else{ + dprintk("%s: without loading mcfile!\n", __FUNCTION__); + } + + return 0; +} + + +static +int sp8870_reset (struct dvb_i2c_bus *i2c) +{ + dprintk("%s\n", __FUNCTION__); + sp8870_writereg(i2c,0x0F00,0x0000); /* system controller stop */ + sp8870_writereg(i2c,0x0301,0x0003); /* ???????? */ + sp8870_writereg(i2c,0x0309,0x0400); /* integer carrier offset */ + sp8870_writereg(i2c,0x030A,0x0000); /* fractional carrier offset */ + sp8870_writereg(i2c,0x0311,0x0000); /* filter for 8 Mhz channel */ + sp8870_writereg(i2c,0x0319,0x000A); /* sample rate correction bit [23..17] */ + sp8870_writereg(i2c,0x031A,0x0AAB); /* sample rate correction bit [16..0] */ + sp8870_writereg(i2c,0x0338,0x0000); /* ???????? */ + sp8870_writereg(i2c,0x0201,0x0000); /* interrupts for change of lock or tuner adjustment disabled */ + sp8870_writereg(i2c,0x0F00,0x0001); /* system controller start */ + + return 0; +} + +static +int tdlb7_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) +{ + struct dvb_i2c_bus *i2c = fe->i2c; + + switch (cmd) { + case FE_GET_INFO: + memcpy (arg, &tdlb7_info, sizeof(struct dvb_frontend_info)); + break; + + case FE_READ_STATUS: + { + fe_status_t *status = arg; + int sync = sp8870_readreg (i2c, 0x0200); + + *status=0; + + if (sync&0x04) // FIXME: find criteria for having signal + *status |= FE_HAS_SIGNAL; + + if (sync&0x04) // FIXME: find criteria + *status |= FE_HAS_CARRIER; + + if (sync&0x04) // FIXME + *status |= FE_HAS_VITERBI; + + if (sync&0x08) // FIXME + *status |= FE_HAS_SYNC; + + if (sync&0x04) + *status |= FE_HAS_LOCK; + break; + + } + + case FE_READ_BER: + { + u32 *ber=(u32 *) arg; + *ber=sp8870_readreg(i2c,0x0C07); // bit error rate before Viterbi + break; + + } + + case FE_READ_SIGNAL_STRENGTH: // not supported by hardware? + { + s32 *signal=(s32 *) arg; + *signal=0; + break; + } + + case FE_READ_SNR: // not supported by hardware? + { + s32 *snr=(s32 *) arg; + *snr=0; + break; + } + + case FE_READ_UNCORRECTED_BLOCKS: // not supported by hardware? + { + u32 *ublocks=(u32 *) arg; + *ublocks=0; + break; + } + + case FE_SET_FRONTEND: + { + struct dvb_frontend_parameters *p = arg; + sp5659_set_tv_freq (i2c, p->frequency, 0); + // all other parameters are set by the on card + // system controller. Don't know how to pass + // distinct values to the card. + break; + } + + case FE_GET_FRONTEND: // how to do this? + { + break; + } + + case FE_SLEEP: // is this supported by hardware? + return -EOPNOTSUPP; + + case FE_INIT: + return sp8870_init (i2c); + + case FE_RESET: + return sp8870_reset (i2c); + + default: + return -EOPNOTSUPP; + }; + + return 0; +} + + +static +int tdlb7_attach (struct dvb_i2c_bus *i2c) +{ + + struct i2c_msg msg = { addr: 0x71, flags: 0, buf: NULL, len: 0 }; + + dprintk ("%s\n", __FUNCTION__); + + if (i2c->xfer (i2c, &msg, 1) != 1) + return -ENODEV; + + dvb_register_frontend (tdlb7_ioctl, i2c, NULL, &tdlb7_info); + + return 0; +} + + +static +void tdlb7_detach (struct dvb_i2c_bus *i2c) +{ + dprintk ("%s\n", __FUNCTION__); + + dvb_unregister_frontend (tdlb7_ioctl, i2c); +} + + +static +int __init init_tdlb7 (void) +{ + dprintk ("%s\n", __FUNCTION__); + + return dvb_register_i2c_device (THIS_MODULE, tdlb7_attach, tdlb7_detach); +} + + +static +void __exit exit_tdlb7 (void) +{ + dprintk ("%s\n", __FUNCTION__); + + dvb_unregister_i2c_device (tdlb7_attach); +} + + +module_init(init_tdlb7); +module_exit(exit_tdlb7); + + +MODULE_PARM(debug,"i"); +MODULE_PARM_DESC(debug, "enable verbose debug messages"); + +MODULE_PARM(loadcode,"i"); +MODULE_PARM_DESC(loadcode, "load tuner microcode"); + +MODULE_PARM(mcfile,"s"); +MODULE_PARM_DESC(mcfile, "where to find the microcode file"); + +MODULE_DESCRIPTION("TDLB7 DVB-T Frontend"); +MODULE_AUTHOR("Juergen Peitz"); +MODULE_LICENSE("GPL"); + + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/media/dvb/frontends/alps_tdmb7.c linux.2.5.47-ac4/drivers/media/dvb/frontends/alps_tdmb7.c --- linux.2.5.47/drivers/media/dvb/frontends/alps_tdmb7.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.47-ac4/drivers/media/dvb/frontends/alps_tdmb7.c 2002-11-13 01:26:51.000000000 +0000 @@ -0,0 +1,468 @@ +/* + Alps TDMB7 DVB OFDM frontend driver + + Copyright (C) 2001-2002 Convergence Integrated Media GmbH + Holger Waechtler + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include +#include + +#include "compat.h" +#include "dvb_frontend.h" + + +static int debug = 0; +#define dprintk if (debug) printk + + +static +struct dvb_frontend_info tdmb7_info = { + name: "Alps TDMB7", + type: FE_OFDM, + frequency_min: 470000000, + frequency_max: 860000000, + frequency_stepsize: 166667, +#if 0 + frequency_tolerance: ???, + symbol_rate_min: ???, + symbol_rate_max: ???, + symbol_rate_tolerance: 500, /* ppm */ + notifier_delay: 0, +#endif + caps: FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | + FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | + FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 +}; + + +static +inline void ddelay (int timeout) +{ + current->state=TASK_INTERRUPTIBLE; + schedule_timeout(timeout); +} + + +static +u8 init_tab [] = { + 0x04, 0x10, + 0x05, 0x09, + 0x06, 0x00, + 0x08, 0x04, + 0x09, 0x00, + 0x0a, 0x01, + 0x15, 0x40, + 0x16, 0x10, + 0x17, 0x87, + 0x18, 0x17, + 0x1a, 0x10, + 0x25, 0x04, + 0x2e, 0x00, + 0x39, 0x00, + 0x3a, 0x04, + 0x45, 0x08, + 0x46, 0x02, + 0x47, 0x05, +}; + + +static +int cx22700_writereg (struct dvb_i2c_bus *i2c, u8 reg, u8 data) +{ + int ret; + u8 buf [] = { reg, data }; + struct i2c_msg msg = { addr: 0x43, flags: 0, buf: buf, len: 2 }; + + dprintk ("%s\n", __FUNCTION__); + + ret = i2c->xfer (i2c, &msg, 1); + + if (ret != 1) + printk("%s: writereg error (reg == 0x%02x, val == 0x%02x, ret == %i)\n", + __FUNCTION__, reg, data, ret); + + return (ret != 1) ? -1 : 0; +} + + +static +u8 cx22700_readreg (struct dvb_i2c_bus *i2c, u8 reg) +{ + int ret; + u8 b0 [] = { reg }; + u8 b1 [] = { 0 }; + struct i2c_msg msg [] = { { addr: 0x43, flags: 0, buf: b0, len: 1 }, + { addr: 0x43, flags: I2C_M_RD, buf: b1, len: 1 } }; + + dprintk ("%s\n", __FUNCTION__); + + ret = i2c->xfer (i2c, msg, 2); + + if (ret != 2) + printk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret); + + return b1[0]; +} + + +static +int pll_write (struct dvb_i2c_bus *i2c, u8 data [4]) +{ + struct i2c_msg msg = { addr: 0x61, flags: 0, buf: data, len: 4 }; + int ret; + + cx22700_writereg (i2c, 0x0a, 0x00); /* open i2c bus switch */ + ret = i2c->xfer (i2c, &msg, 1); + cx22700_writereg (i2c, 0x0a, 0x01); /* close i2c bus switch */ + + if (ret != 1) + printk("%s: i/o error (addr == 0x%02x, ret == %i)\n", __FUNCTION__, msg.addr, ret); + + return (ret != 1) ? -1 : 0; +} + + +/** + * set up the downconverter frequency divisor for a + * reference clock comparision frequency of 125 kHz. + */ +static +int pll_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq) +{ + u32 div = (freq + 36166667) / 166667; +#if 1 //ALPS_SETTINGS + u8 buf [4] = { (div >> 8) & 0x7f, div & 0xff, ((div >> 10) & 0x60) | 0x85, + freq < 592000000 ? 0x40 : 0x80 }; +#else + u8 buf [4] = { (div >> 8) & 0x7f, div & 0xff, ((div >> 10) & 0x60) | 0x85, + freq < 470000000 ? 0x42 : freq < 862000000 ? 0x41 : 0x81 }; +#endif + + dprintk ("%s: freq == %i, div == %i\n", __FUNCTION__, freq, div); + + return pll_write (i2c, buf); +} + + +static +int cx22700_init (struct dvb_i2c_bus *i2c) +{ + int i; + + dprintk("cx22700_init: init chip\n"); + + cx22700_writereg (i2c, 0x00, 0x02); /* soft reset */ + cx22700_writereg (i2c, 0x00, 0x00); + + ddelay (HZ/100); + + for (i=0; icode_rate_HP < FEC_1_2 || p->code_rate_HP > FEC_7_8) + return -EINVAL; + + if (p->code_rate_LP < FEC_1_2 || p->code_rate_LP > FEC_7_8) + + if (p->code_rate_HP == FEC_4_5 || p->code_rate_LP == FEC_4_5) + return -EINVAL; + + if (p->guard_interval < GUARD_INTERVAL_1_32 || + p->guard_interval > GUARD_INTERVAL_1_4) + return -EINVAL; + + if (p->transmission_mode != TRANSMISSION_MODE_2K && + p->transmission_mode != TRANSMISSION_MODE_8K) + return -EINVAL; + + if (p->constellation != QPSK && + p->constellation != QAM_16 && + p->constellation != QAM_64) + return -EINVAL; + + if (p->hierarchy_information < HIERARCHY_NONE || + p->hierarchy_information > HIERARCHY_4) + return -EINVAL; + + if (p->bandwidth < BANDWIDTH_8_MHZ && p->bandwidth > BANDWIDTH_6_MHZ) + return -EINVAL; + + if (p->bandwidth == BANDWIDTH_7_MHZ) + cx22700_writereg (i2c, 0x09, cx22700_readreg (i2c, 0x09 | 0x10)); + else + cx22700_writereg (i2c, 0x09, cx22700_readreg (i2c, 0x09 & ~0x10)); + + val = qam_tab[p->constellation - QPSK]; + val |= p->hierarchy_information - HIERARCHY_NONE; + + cx22700_writereg (i2c, 0x04, val); + + val = fec_tab[p->code_rate_HP - FEC_1_2] << 3; + val |= fec_tab[p->code_rate_LP - FEC_1_2]; + + cx22700_writereg (i2c, 0x05, val); + + val = (p->guard_interval - GUARD_INTERVAL_1_32) << 2; + val |= p->transmission_mode - TRANSMISSION_MODE_2K; + + cx22700_writereg (i2c, 0x06, val); + + cx22700_writereg (i2c, 0x08, 0x04 | 0x02); /* use user tps parameters */ + cx22700_writereg (i2c, 0x08, 0x04); /* restart aquisition */ + + return 0; +} + + +static +int cx22700_get_tps (struct dvb_i2c_bus *i2c, struct dvb_ofdm_parameters *p) +{ + static const fe_modulation_t qam_tab [3] = { QPSK, QAM_16, QAM_64 }; + static const fe_code_rate_t fec_tab [5] = { FEC_1_2, FEC_2_3, FEC_3_4, + FEC_5_6, FEC_7_8 }; + u8 val; + + dprintk ("%s\n", __FUNCTION__); + + if (!(cx22700_readreg(i2c, 0x07) & 0x20)) /* tps valid? */ + return -EAGAIN; + + val = cx22700_readreg (i2c, 0x01); + + if ((val & 0x7) > 4) + p->hierarchy_information = HIERARCHY_AUTO; + else + p->hierarchy_information = HIERARCHY_NONE + (val & 0x7); + + if (((val >> 3) & 0x3) > 2) + p->constellation = QAM_AUTO; + else + p->constellation = qam_tab[(val >> 3) & 0x3]; + + + val = cx22700_readreg (i2c, 0x02); + + if ((val >> 3) > 4) + p->code_rate_HP = FEC_AUTO; + else + p->code_rate_HP = fec_tab[val >> 3]; + + if ((val & 0x7) > 4) + p->code_rate_LP = FEC_AUTO; + else + p->code_rate_LP = fec_tab[val >> 3]; + + + val = cx22700_readreg (i2c, 0x03); + + p->guard_interval = GUARD_INTERVAL_1_32 + ((val >> 6) & 0x3); + p->transmission_mode = TRANSMISSION_MODE_2K + ((val >> 5) & 0x1); + + return 0; +} + + +static +int tdmb7_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) +{ + struct dvb_i2c_bus *i2c = fe->i2c; + + dprintk ("%s\n", __FUNCTION__); + + switch (cmd) { + case FE_GET_INFO: + memcpy (arg, &tdmb7_info, sizeof(struct dvb_frontend_info)); + break; + + case FE_READ_STATUS: + { + fe_status_t *status = (fe_status_t *) arg; + u16 rs_ber = (cx22700_readreg (i2c, 0x0d) << 9) + | (cx22700_readreg (i2c, 0x0e) << 1); + u8 sync = cx22700_readreg (i2c, 0x07); + + *status = 0; + + if (rs_ber < 0xff00) + *status |= FE_HAS_SIGNAL; + + if (sync & 0x20) + *status |= FE_HAS_CARRIER; + + if (sync & 0x10) + *status |= FE_HAS_VITERBI; + + if (sync & 0x10) + *status |= FE_HAS_SYNC; + + if (sync & 0x10) + *status |= FE_HAS_LOCK; + + break; + } + + case FE_READ_BER: + *((uint32_t*) arg) = cx22700_readreg (i2c, 0x0c) & 0x7f; + break; + + case FE_READ_SIGNAL_STRENGTH: + { + u16 rs_ber = (cx22700_readreg (i2c, 0x0d) << 9) + | (cx22700_readreg (i2c, 0x0e) << 1); + *((uint16_t*) arg) = ~rs_ber; + break; + } + case FE_READ_SNR: + { + u16 rs_ber = (cx22700_readreg (i2c, 0x0d) << 9) + | (cx22700_readreg (i2c, 0x0e) << 1); + *((uint16_t*) arg) = ~rs_ber; + break; + } + case FE_READ_UNCORRECTED_BLOCKS: + *((uint32_t*) arg) = cx22700_readreg (i2c, 0x0f); + break; + + case FE_SET_FRONTEND: + { + struct dvb_frontend_parameters *p = arg; + + cx22700_writereg (i2c, 0x00, 0x02); /* XXX CHECKME: soft reset*/ + cx22700_writereg (i2c, 0x00, 0x00); + + pll_set_tv_freq (i2c, p->frequency); + cx22700_set_inversion (i2c, p->inversion); + cx22700_set_tps (i2c, &p->u.ofdm); + cx22700_writereg (i2c, 0x37, 0x01); /* PAL loop filter off */ + cx22700_writereg (i2c, 0x00, 0x01); /* restart aquire */ + break; + } + + case FE_GET_FRONTEND: + { + struct dvb_frontend_parameters *p = arg; + u8 reg09 = cx22700_readreg (i2c, 0x09); + + p->inversion = reg09 & 0x1 ? INVERSION_ON : INVERSION_OFF; + return cx22700_get_tps (i2c, &p->u.ofdm); + } + + case FE_INIT: + return cx22700_init (i2c); + + case FE_RESET: + break; + + default: + return -EOPNOTSUPP; + }; + + return 0; +} + + + +static +int tdmb7_attach (struct dvb_i2c_bus *i2c) +{ + struct i2c_msg msg = { addr: 0x43, flags: 0, buf: NULL, len: 0 }; + + dprintk ("%s\n", __FUNCTION__); + + if (i2c->xfer (i2c, &msg, 1) != 1) + return -ENODEV; + + dvb_register_frontend (tdmb7_ioctl, i2c, NULL, &tdmb7_info); + + return 0; +} + + +static +void tdmb7_detach (struct dvb_i2c_bus *i2c) +{ + dprintk ("%s\n", __FUNCTION__); + + dvb_unregister_frontend (tdmb7_ioctl, i2c); +} + + +static +int __init init_tdmb7 (void) +{ + dprintk ("%s\n", __FUNCTION__); + + return dvb_register_i2c_device (THIS_MODULE, tdmb7_attach, tdmb7_detach); +} + + +static +void __exit exit_tdmb7 (void) +{ + dprintk ("%s\n", __FUNCTION__); + + dvb_unregister_i2c_device (tdmb7_attach); +} + +module_init (init_tdmb7); +module_exit (exit_tdmb7); + +MODULE_PARM(debug,"i"); +MODULE_PARM_DESC(debug, "enable verbose debug messages"); +MODULE_DESCRIPTION("TDMB7 DVB Frontend driver"); +MODULE_AUTHOR("Holger Waechtler"); +MODULE_LICENSE("GPL"); + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/media/dvb/frontends/Kconfig linux.2.5.47-ac4/drivers/media/dvb/frontends/Kconfig --- linux.2.5.47/drivers/media/dvb/frontends/Kconfig 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/media/dvb/frontends/Kconfig 2002-11-13 01:29:47.000000000 +0000 @@ -23,6 +23,30 @@ DVB adapter simply enable all supported frontends, the right one will get autodetected. +config DVB_ALPS_TDLB7 + tristate "Alps TDLB7 (OFDM)" + depends on DVB_CORE + help + A DVB-T tuner module. Say Y when you want to support this frontend. + + This tuner module needs some microcode located in a file called + "Sc_main.mc" in the windows driver. Please pass the module parameter + mcfile="/PATH/FILENAME" when loading alps_tdlb7.o. + + If you don't know what tuner module is soldered on your + DVB adapter simply enable all supported frontends, the + right one will get autodetected. + +config DVB_ALPS_TDMB7 + tristate "Alps BSRV2 (OFDM)" + depends on DVB_CORE + help + A DVB-S tuner module. Say Y when you want to support this frontend. + + If you don't know what tuner module is soldered on your + DVB adapter simply enable all supported frontends, the + right one will get autodetected. + config DVB_GRUNDIG_29504_491 tristate "Grundig 29504-491 (QPSK)" depends on DVB_CORE diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/media/dvb/frontends/Makefile linux.2.5.47-ac4/drivers/media/dvb/frontends/Makefile --- linux.2.5.47/drivers/media/dvb/frontends/Makefile 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/media/dvb/frontends/Makefile 2002-11-13 01:26:51.000000000 +0000 @@ -6,6 +6,8 @@ obj-$(CONFIG_DVB_ALPS_BSRU6) += alps_bsru6.o obj-$(CONFIG_DVB_ALPS_BSRV2) += alps_bsrv2.o +obj-$(CONFIG_DVB_ALPS_TDLB7) += alps_tdlb7.o +obj-$(CONFIG_DVB_ALPS_TDMB7) += alps_tdmb7.o obj-$(CONFIG_DVB_GRUNDIG_29504_491) += grundig_29504-491.o obj-$(CONFIG_DVB_GRUNDIG_29504_401) += grundig_29504-401.o obj-$(CONFIG_DVB_VES1820) += ves1820.o diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/media/dvb/frontends/ves1820.c linux.2.5.47-ac4/drivers/media/dvb/frontends/ves1820.c --- linux.2.5.47/drivers/media/dvb/frontends/ves1820.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/media/dvb/frontends/ves1820.c 2002-11-13 01:26:51.000000000 +0000 @@ -199,8 +199,8 @@ u8 b0 [] = { 0xff }; u8 pwm; int i; - struct i2c_msg msg [] = { { addr: 0x28, flags: 0, buf: b0, len: 1 }, - { addr: 0x28, flags: I2C_M_RD, buf: &pwm, len: 1 } }; + struct i2c_msg msg [] = { { addr: 0x50, flags: 0, buf: b0, len: 1 }, + { addr: 0x50, flags: I2C_M_RD, buf: &pwm, len: 1 } }; dprintk("VES1820: init chip\n"); @@ -433,12 +433,13 @@ } case FE_READ_BER: - *((u32*) arg) = ves1820_readreg(frontend->i2c, 0x14) | + { + u32 ber = ves1820_readreg(frontend->i2c, 0x14) | (ves1820_readreg(frontend->i2c, 0x15) << 8) | - (ves1820_readreg(frontend->i2c, 0x16) << 16); - /* XXX FIXME: scale!!*/ + ((ves1820_readreg(frontend->i2c, 0x16) & 0x0f) << 16); + *((u32*) arg) = 10 * ber; break; - + } case FE_READ_SIGNAL_STRENGTH: { u8 gain = ves1820_readreg(frontend->i2c, 0x17); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/media/video/audiochip.h linux.2.5.47-ac4/drivers/media/video/audiochip.h --- linux.2.5.47/drivers/media/video/audiochip.h 2002-10-31 14:57:08.000000000 +0000 +++ linux.2.5.47-ac4/drivers/media/video/audiochip.h 2002-11-11 20:24:45.000000000 +0000 @@ -67,4 +67,7 @@ #define AUDC_SWITCH_MUTE _IO('m',16) /* turn on mute */ #endif +/* misc stuff to pass around config info to i2c chips */ +#define AUDC_CONFIG_PINNACLE _IOW('m',32,int) + #endif /* AUDIOCHIP_H */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/media/video/bttv-driver.c linux.2.5.47-ac4/drivers/media/video/bttv-driver.c --- linux.2.5.47/drivers/media/video/bttv-driver.c 2002-11-05 13:54:43.000000000 +0000 +++ linux.2.5.47-ac4/drivers/media/video/bttv-driver.c 2002-11-12 15:28:58.000000000 +0000 @@ -833,11 +833,9 @@ i2c_mux = mux = (btv->audio & AUDIO_MUTE) ? AUDIO_OFF : btv->audio; if (btv->opt_automute && !signal && !btv->radio_user) mux = AUDIO_OFF; -#if 0 - printk("bttv%d: amux: mode=%d audio=%d signal=%s mux=%d/%d irq=%s\n", + dprintk(KERN_DEBUG "bttv%d: amux: mode=%d audio=%d signal=%s mux=%d/%d irq=%s\n", btv->nr, mode, btv->audio, signal ? "yes" : "no", mux, i2c_mux, in_interrupt() ? "yes" : "no"); -#endif val = bttv_tvcards[btv->type].audiomux[mux]; btaor(val,~bttv_tvcards[btv->type].gpiomask, BT848_GPIO_DATA); @@ -3225,6 +3223,7 @@ INIT_LIST_HEAD(&btv->capture); INIT_LIST_HEAD(&btv->vcapture); + init_timer(&btv->timeout); btv->timeout.function = bttv_irq_timeout; btv->timeout.data = (unsigned long)btv; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/media/video/Makefile linux.2.5.47-ac4/drivers/media/video/Makefile --- linux.2.5.47/drivers/media/video/Makefile 2002-11-05 13:54:43.000000000 +0000 +++ linux.2.5.47-ac4/drivers/media/video/Makefile 2002-11-11 19:39:54.000000000 +0000 @@ -35,7 +35,7 @@ obj-$(CONFIG_VIDEO_CPIA_PP) += cpia_pp.o obj-$(CONFIG_VIDEO_CPIA_USB) += cpia_usb.o obj-$(CONFIG_VIDEO_MEYE) += meye.o -obj-$(CONFIG_VIDEO_SAA7134) += saa7134/ tuner.o tda9887.o +obj-$(CONFIG_VIDEO_SAA7134) += saa7134/ tuner.o #tda9887.o obj-$(CONFIG_TUNER_3036) += tuner-3036.o include $(TOPDIR)/Rules.make diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/media/video/meye.c linux.2.5.47-ac4/drivers/media/video/meye.c --- linux.2.5.47/drivers/media/video/meye.c 2002-10-31 14:57:08.000000000 +0000 +++ linux.2.5.47-ac4/drivers/media/video/meye.c 2002-11-11 19:39:31.000000000 +0000 @@ -861,7 +861,7 @@ mchip_free_frame(); } -out: +out: ; } /****************************************************************************/ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/message/fusion/mptbase.c linux.2.5.47-ac4/drivers/message/fusion/mptbase.c --- linux.2.5.47/drivers/message/fusion/mptbase.c 2002-10-31 14:57:19.000000000 +0000 +++ linux.2.5.47-ac4/drivers/message/fusion/mptbase.c 2002-11-13 01:12:10.000000000 +0000 @@ -49,7 +49,7 @@ * (mailto:sjralston1@netscape.net) * (mailto:Pam.Delaney@lsil.com) * - * $Id: mptbase.c,v 1.122 2002/10/03 13:10:11 pdelaney Exp $ + * $Id: mptbase.c,v 1.123 2002/10/17 20:15:56 pdelaney Exp $ */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* @@ -1156,7 +1156,7 @@ dprintk((KERN_INFO MYNAM ": Checking for MPT adapters...\n")); /* - * NOTE: The 929, 929X and 1030 will appear as 2 separate PCI devices, + * NOTE: The 929, 929X, 1030 and 1035 will appear as 2 separate PCI devices, * one for each channel. */ pci_for_each_dev(pdev) { @@ -1170,18 +1170,14 @@ (pdev->device != MPI_MANUFACTPAGE_DEVICEID_FC929X) && (pdev->device != MPI_MANUFACTPAGE_DEVICEID_FC919X) && (pdev->device != MPI_MANUFACTPAGE_DEVID_53C1030) && -#if 0 - /* FIXME! C103x family */ - (pdev->device != MPI_MANUFACTPAGE_DEVID_53C1030_ZC) && - (pdev->device != MPI_MANUFACTPAGE_DEVID_53C1035) && -#endif + (pdev->device != MPI_MANUFACTPAGE_DEVID_1030_53C1035) && 1) { dprintk((KERN_INFO MYNAM ": Skipping LSI device=%04xh\n", pdev->device)); continue; } /* GRRRRR - * dual function devices (929, 929X, 1030) may be presented in Func 1,0 order, + * dual function devices (929, 929X, 1030, 1035) may be presented in Func 1,0 order, * but we'd really really rather have them in Func 0,1 order. * Do some kind of look ahead here... */ @@ -1445,15 +1441,24 @@ ioc->chip_type = C1030; ioc->prod_name = "LSI53C1030"; { + u8 revision; + /* 1030 Chip Fix. Disable Split transactions - * for PCIX. Set bits 4 - 6 to zero. + * for PCIX. Set bits 4 - 6 to zero if Rev < C0( = 8) */ - u16 pcixcmd = 0; - pci_read_config_word(pdev, 0x6a, &pcixcmd); - pcixcmd &= 0xFF8F; - pci_write_config_word(pdev, 0x6a, pcixcmd); + pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); + if (revision < 0x08) { + u16 pcixcmd = 0; + pci_read_config_word(pdev, 0x6a, &pcixcmd); + pcixcmd &= 0xFF8F; + pci_write_config_word(pdev, 0x6a, pcixcmd); + } } } + else if (pdev->device == MPI_MANUFACTPAGE_DEVID_1030_53C1035) { + ioc->chip_type = C1035; + ioc->prod_name = "LSI53C1035"; + } sprintf(ioc->name, "ioc%d", ioc->id); @@ -1500,9 +1505,10 @@ mpt_adapters[ioc->id] = ioc; /* NEW! 20010220 -sralston - * Check for "bound ports" (929, 929X, 1030) to reduce redundant resets. + * Check for "bound ports" (929, 929X, 1030, 1035) to reduce redundant resets. */ - if ((ioc->chip_type == FC929) || (ioc->chip_type == C1030) || (ioc->chip_type == FC929X)) + if ((ioc->chip_type == FC929) || (ioc->chip_type == C1030) + || (ioc->chip_type == C1035) || (ioc->chip_type == FC929X)) mpt_detect_bound_ports(ioc, pdev); if ((r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP, CAN_SLEEP)) != 0) { @@ -1746,7 +1752,7 @@ /* * mpt_detect_bound_ports - Search for PCI bus/dev_function * which matches PCI bus/dev_function (+/-1) for newly discovered 929, - * 929X or 1030. + * 929X, 1030 or 1035. * @ioc: Pointer to MPT adapter structure * @pdev: Pointer to (struct pci_dev) structure * @@ -1806,8 +1812,7 @@ /* Disable the FW */ state = mpt_GetIocState(this, 1); if (state == MPI_IOC_STATE_OPERATIONAL) { - if (SendIocReset(this, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, NO_SLEEP) != 0) - (void) KickStart(this, 1, NO_SLEEP); + SendIocReset(this, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, NO_SLEEP); } if (this->cached_fw != NULL) { @@ -1819,7 +1824,6 @@ } } - /* Disable adapter interrupts! */ CHIPREG_WRITE32(&this->chip->IntMask, 0xFFFFFFFF); this->active = 0; @@ -2291,9 +2295,6 @@ ioc->reply_sz = ioc->req_sz; ioc->reply_depth = MIN(MPT_DEFAULT_REPLY_DEPTH, facts->ReplyQueueDepth); - /* 1030 - should we use a smaller DEFAULT_REPLY_DEPTH? - * FIX - */ dprintk((MYIOC_s_INFO_FMT "reply_sz=%3d, reply_depth=%4d\n", ioc->name, ioc->reply_sz, ioc->reply_depth)); dprintk((MYIOC_s_INFO_FMT "req_sz =%3d, req_depth =%4d\n", @@ -2891,6 +2892,7 @@ */ diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); while ((diag0val & MPI_DIAG_DRWE) == 0) { + CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF); CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE); CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE); CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE); @@ -3126,6 +3128,18 @@ int cnt = 0; dprintk((KERN_WARNING MYNAM ": KickStarting %s!\n", ioc->name)); + if ((int)ioc->chip_type > (int)FC929) { + /* Always issue a Msg Unit Reset first. This will clear some + * SCSI bus hang conditions. + */ + SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag); + + if (sleepFlag == CAN_SLEEP) { + schedule_timeout(HZ); + } else { + mdelay (1000); + } + } hard_reset_done = mpt_diag_reset(ioc, force, sleepFlag); if (hard_reset_done < 0) @@ -5841,6 +5855,15 @@ while (! Q_IS_EMPTY(&MptAdapters)) { this = MptAdapters.head; + + /* Disable interrupts! */ + CHIPREG_WRITE32(&this->chip->IntMask, 0xFFFFFFFF); + + this->active = 0; + + /* Clear any lingering interrupt */ + CHIPREG_WRITE32(&this->chip->IntStatus, 0); + Q_DEL_ITEM(this); mpt_adapter_dispose(this); } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/message/fusion/mptbase.h linux.2.5.47-ac4/drivers/message/fusion/mptbase.h --- linux.2.5.47/drivers/message/fusion/mptbase.h 2002-10-31 14:57:19.000000000 +0000 +++ linux.2.5.47-ac4/drivers/message/fusion/mptbase.h 2002-11-13 01:12:10.000000000 +0000 @@ -13,7 +13,7 @@ * (mailto:sjralston1@netscape.net) * (mailto:Pam.Delaney@lsil.com) * - * $Id: mptbase.h,v 1.134 2002/10/03 13:10:12 pdelaney Exp $ + * $Id: mptbase.h,v 1.136 2002/10/21 13:51:54 pdelaney Exp $ */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* @@ -80,8 +80,8 @@ #define COPYRIGHT "Copyright (c) 1999-2002 " MODULEAUTHOR #endif -#define MPT_LINUX_VERSION_COMMON "2.02.01.07" -#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-2.02.01.07" +#define MPT_LINUX_VERSION_COMMON "2.03.00.01" +#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-2.03.00.01" #define WHAT_MAGIC_STRING "@" "(" "#" ")" #define show_mptmod_ver(s,ver) \ @@ -301,6 +301,7 @@ FC919 = 0x0919, FC929 = 0x0929, C1030 = 0x1030, + C1035 = 0x1035, FCUNK = 0xFBAD } CHIP_TYPE; @@ -368,6 +369,7 @@ typedef struct _VirtDevice { struct _VirtDevice *forw; struct _VirtDevice *back; + struct scsi_device *device; rwlock_t VdevLock; int ref_cnt; u8 tflags; @@ -912,6 +914,10 @@ MPT_FRAME_HDR *cmdPtr; /* Ptr to nonOS request */ struct scsi_cmnd *abortSCpnt; MPT_LOCAL_REPLY localReply; /* internal cmd reply struct */ + unsigned long hard_resets; /* driver forced bus resets count */ + unsigned long soft_resets; /* fw/external bus resets count */ + unsigned long timeouts; /* cmd timeouts */ + ushort sel_timeout[MPT_MAX_FC_DEVICES]; } MPT_SCSI_HOST; /* diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/message/fusion/mptctl.c linux.2.5.47-ac4/drivers/message/fusion/mptctl.c --- linux.2.5.47/drivers/message/fusion/mptctl.c 2002-10-31 14:57:19.000000000 +0000 +++ linux.2.5.47-ac4/drivers/message/fusion/mptctl.c 2002-11-13 01:12:10.000000000 +0000 @@ -34,7 +34,7 @@ * (mailto:sjralston1@netscape.net) * (mailto:Pam.Delaney@lsil.com) * - * $Id: mptctl.c,v 1.60 2002/10/03 13:10:13 pdelaney Exp $ + * $Id: mptctl.c,v 1.61 2002/10/17 20:15:57 pdelaney Exp $ */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* @@ -136,14 +136,8 @@ static int mptctl_replace_fw (unsigned long arg); static int mptctl_do_reset(unsigned long arg); - -static int mptctl_compaq_ioctl(struct file *file, unsigned int cmd, unsigned long arg); -static int mptctl_cpq_getpciinfo(unsigned long arg); -static int mptctl_cpq_getdriver(unsigned long arg); -static int mptctl_cpq_ctlr_status(unsigned long arg); -static int mptctl_cpq_target_address(unsigned long arg); -static int mptctl_cpq_passthru(unsigned long arg); -static int mptctl_compaq_scsiio(VENDOR_IOCTL_REQ *pVenReq, cpqfc_passthru_t *pPass); +static int mptctl_hp_hostinfo(unsigned long arg); +static int mptctl_hp_targetinfo(unsigned long arg); /* * Private function calls. @@ -415,7 +409,7 @@ /* Send request */ if ((mf = mpt_get_msg_frame(mptctl_id, ioctl->ioc->id)) == NULL) { - dtmprintk((MYIOC_s_WARN_FMT "IssueTaskMgmt, no msg frames!!\n", + dctlprintk((MYIOC_s_WARN_FMT "IssueTaskMgmt, no msg frames!!\n", ioctl->ioc->name)); mptctl_free_tm_flags(ioctl->ioc); @@ -623,21 +617,13 @@ } ret = -ENXIO; /* (-6) No such device or address */ - - /* Test for Compaq-specific IOCTL's. - */ - if ((cmd == CPQFCTS_GETPCIINFO) || (cmd == CPQFCTS_CTLR_STATUS) || - (cmd == CPQFCTS_GETDRIVVER) || (cmd == CPQFCTS_SCSI_PASSTHRU) || - (cmd == CPQFCTS_SCSI_IOCTL_FC_TARGET_ADDRESS)) - return mptctl_compaq_ioctl(file, cmd, arg); - /* Verify intended MPT adapter - set iocnum and the adapter * pointer (iocp) */ iocnumX = khdr.iocnum & 0xFF; if (((iocnum = mpt_verify_adapter(iocnumX, &iocp)) < 0) || (iocp == NULL)) { - dtmprintk((KERN_ERR "%s::mptctl_ioctl() @%d - ioc%d not found!\n", + dctlprintk((KERN_ERR "%s::mptctl_ioctl() @%d - ioc%d not found!\n", __FILE__, __LINE__, iocnumX)); return -ENODEV; } @@ -683,6 +669,12 @@ case MPTHARDRESET: ret = mptctl_do_reset(arg); break; + case HP_GETHOSTINFO: + ret = mptctl_hp_hostinfo(arg); + break; + case HP_GETTARGETINFO: + ret = mptctl_hp_targetinfo(arg); + break; default: ret = -EINVAL; } @@ -708,7 +700,7 @@ } if (mpt_verify_adapter(krinfo.hdr.iocnum, &iocp) < 0) { - dtmprintk((KERN_ERR "%s@%d::mptctl_do_reset - ioc%d not found!\n", + dctlprintk((KERN_ERR "%s@%d::mptctl_do_reset - ioc%d not found!\n", __FILE__, __LINE__, krinfo.hdr.iocnum)); return -ENODEV; /* (-6) No such device or address */ } @@ -816,7 +808,7 @@ dctlprintk((KERN_INFO "DbG: kfwdl.ioc = %04xh\n", ioc)); if ((ioc = mpt_verify_adapter(ioc, &iocp)) < 0) { - dtmprintk(("%s@%d::_ioctl_fwdl - ioc%d not found!\n", + dctlprintk(("%s@%d::_ioctl_fwdl - ioc%d not found!\n", __FILE__, __LINE__, ioc)); return -ENODEV; /* (-6) No such device or address */ } @@ -1252,7 +1244,7 @@ if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { - dtmprintk((KERN_ERR "%s::mptctl_getiocinfo() @%d - ioc%d not found!\n", + dctlprintk((KERN_ERR "%s::mptctl_getiocinfo() @%d - ioc%d not found!\n", __FILE__, __LINE__, iocnum)); return -ENODEV; } @@ -1379,7 +1371,7 @@ if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { - dtmprintk((KERN_ERR "%s::mptctl_gettargetinfo() @%d - ioc%d not found!\n", + dctlprintk((KERN_ERR "%s::mptctl_gettargetinfo() @%d - ioc%d not found!\n", __FILE__, __LINE__, iocnum)); return -ENODEV; } @@ -1510,7 +1502,7 @@ if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { - dtmprintk((KERN_ERR "%s::mptctl_readtest() @%d - ioc%d not found!\n", + dctlprintk((KERN_ERR "%s::mptctl_readtest() @%d - ioc%d not found!\n", __FILE__, __LINE__, iocnum)); return -ENODEV; } @@ -1568,7 +1560,7 @@ if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { - dtmprintk((KERN_ERR "%s::mptctl_eventquery() @%d - ioc%d not found!\n", + dctlprintk((KERN_ERR "%s::mptctl_eventquery() @%d - ioc%d not found!\n", __FILE__, __LINE__, iocnum)); return -ENODEV; } @@ -1606,7 +1598,7 @@ if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { - dtmprintk((KERN_ERR "%s::mptctl_eventenable() @%d - ioc%d not found!\n", + dctlprintk((KERN_ERR "%s::mptctl_eventenable() @%d - ioc%d not found!\n", __FILE__, __LINE__, iocnum)); return -ENODEV; } @@ -1654,7 +1646,7 @@ if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { - dtmprintk((KERN_ERR "%s::mptctl_eventreport() @%d - ioc%d not found!\n", + dctlprintk((KERN_ERR "%s::mptctl_eventreport() @%d - ioc%d not found!\n", __FILE__, __LINE__, iocnum)); return -ENODEV; } @@ -1708,7 +1700,7 @@ if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { - dtmprintk((KERN_ERR "%s::mptctl_replace_fw() @%d - ioc%d not found!\n", + dctlprintk((KERN_ERR "%s::mptctl_replace_fw() @%d - ioc%d not found!\n", __FILE__, __LINE__, iocnum)); return -ENODEV; } @@ -1794,7 +1786,7 @@ if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { - dtmprintk((KERN_ERR "%s::mptctl_mpt_command() @%d - ioc%d not found!\n", + dctlprintk((KERN_ERR "%s::mptctl_mpt_command() @%d - ioc%d not found!\n", __FILE__, __LINE__, iocnum)); return -ENODEV; } @@ -1842,7 +1834,7 @@ if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { - dtmprintk((KERN_ERR "%s::mptctl_do_mpt_command() @%d - ioc%d not found!\n", + dctlprintk((KERN_ERR "%s::mptctl_do_mpt_command() @%d - ioc%d not found!\n", __FILE__, __LINE__, iocnum)); return -ENODEV; } @@ -1926,6 +1918,14 @@ int target = (int) pScsiReq->TargetID; int dataSize; + if ((target < 0) || (target >= ioc->sh->max_id)) { + printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " + "Target ID out of bounds. \n", + __FILE__, __LINE__); + rc = -ENODEV; + goto done_free_mem; + } + pScsiReq->MsgFlags = mpt_msg_flags(); /* verify that app has not requested @@ -2049,9 +2049,37 @@ } break; + case MPI_FUNCTION_IOC_INIT: + { + IOCInit_t *pInit = (IOCInit_t *) mf; + u32 high_addr, sense_high; + + /* Verify that all entries in the IOC INIT match + * existing setup (and in LE format). + */ + if (sizeof(dma_addr_t) == sizeof(u64)) { + high_addr = cpu_to_le32((u32)((u64)ioc->req_frames_dma >> 32)); + sense_high= cpu_to_le32((u32)((u64)ioc->sense_buf_pool_dma >> 32)); + } else { + high_addr = 0; + sense_high= 0; + } + + if ((pInit->Flags != 0) || (pInit->MaxDevices != ioc->facts.MaxDevices) || + (pInit->MaxBuses != ioc->facts.MaxBuses) || + (pInit->ReplyFrameSize != cpu_to_le16(ioc->reply_sz)) || + (pInit->HostMfaHighAddr != high_addr) || + (pInit->SenseBufferHighAddr != sense_high)) { + printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " + "IOC_INIT issued with 1 or more incorrect parameters. Rejected.\n", + __FILE__, __LINE__); + rc = -EFAULT; + goto done_free_mem; + } + } + break; default: /* - * MPI_FUNCTION_IOC_INIT * MPI_FUNCTION_PORT_ENABLE * MPI_FUNCTION_TARGET_CMD_BUFFER_POST * MPI_FUNCTION_TARGET_ASSIST @@ -2357,131 +2385,85 @@ } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* Routine for the Compaq IOCTL commands. +/* Prototype Routine for the HP HOST INFO command. * * Outputs: None. * Return: 0 if successful - * -EBUSY if previous command timout and IOC reset is not complete. * -EFAULT if data unavailable - * -ENODEV if no such device/adapter - * -ETIME if timer expires - * -ENOMEM if memory allocation error - */ -static int -mptctl_compaq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - int iocnum = 0; - unsigned iocnumX = 0; - int ret; - int nonblock = (file->f_flags & O_NONBLOCK); - MPT_ADAPTER *iocp = NULL; - - if (cmd == CPQFCTS_SCSI_PASSTHRU) { - /* Update the iocnum */ - if (copy_from_user(&iocnumX, (int *)arg, sizeof(int))) { - printk(KERN_ERR "%s::mptctl_compaq_ioctl() @%d - " - "Unable to read controller number @ %p\n", - __FILE__, __LINE__, (void*)arg); - return -EFAULT; - } - iocnumX &= 0xFF; - } - - if (((iocnum = mpt_verify_adapter(iocnumX, &iocp)) < 0) || - (iocp == NULL)) { - dtmprintk((KERN_ERR "%s::mptctl_compaq_ioctl() @%d - ioc%d not found!\n", - __FILE__, __LINE__, iocnumX)); - return -ENODEV; - } - - /* All of these commands require an interrupt or - * are unknown/illegal. - */ - if ((ret = mptctl_syscall_down(iocp, nonblock)) != 0) - return ret; - - dctlprintk((MYIOC_s_INFO_FMT ": mptctl_compaq_ioctl()\n", iocp->name)); - - switch(cmd) { - case CPQFCTS_GETPCIINFO: - ret = mptctl_cpq_getpciinfo(arg); - break; - case CPQFCTS_GETDRIVVER: - ret = mptctl_cpq_getdriver(arg); - break; - case CPQFCTS_CTLR_STATUS: - ret = mptctl_cpq_ctlr_status(arg); - break; - case CPQFCTS_SCSI_IOCTL_FC_TARGET_ADDRESS: - ret = mptctl_cpq_target_address(arg); - break; - case CPQFCTS_SCSI_PASSTHRU: - ret = mptctl_cpq_passthru(arg); - break; - default: - ret = -EINVAL; - } - - up(&mptctl_syscall_sem_ioc[iocp->id]); - - return ret; - -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* mptctl_cpq_getpciinfo - Get PCI Information in format desired by Compaq - * - * Outputs: None. - * Return: 0 if successful * -EBUSY if previous command timout and IOC reset is not complete. - * -EFAULT if data unavailable * -ENODEV if no such device/adapter * -ETIME if timer expires + * -ENOMEM if memory allocation error */ static int -mptctl_cpq_getpciinfo(unsigned long arg) +mptctl_hp_hostinfo(unsigned long arg) { - cpqfc_pci_info_struct *uarg = (cpqfc_pci_info_struct *) arg; - cpqfc_pci_info_struct karg; + hp_host_info_t *uarg = (hp_host_info_t *) arg; MPT_ADAPTER *ioc; struct pci_dev *pdev; + char *pbuf; + dma_addr_t buf_dma; + hp_host_info_t karg; CONFIGPARMS cfg; ConfigPageHeader_t hdr; - int iocnum = 0, iocnumX = 0; - dma_addr_t buf_dma; - u8 *pbuf = NULL; - int failed; + int iocnum; + int rc; - dctlprintk((": mptctl_cpq_pciinfo called.\n")); - if (copy_from_user(&karg, uarg, sizeof(cpqfc_pci_info_struct))) { - printk(KERN_ERR "%s@%d::mptctl_cpq_pciinfo - " - "Unable to read in cpqfc_pci_info_struct @ %p\n", + dctlprintk((": mptctl_hp_hostinfo called.\n")); + if (copy_from_user(&karg, uarg, sizeof(hp_host_info_t))) { + printk(KERN_ERR "%s@%d::mptctl_hp_host_info - " + "Unable to read in hp_host_info struct @ %p\n", __FILE__, __LINE__, (void*)uarg); - return -EINVAL; + return -EFAULT; } - if (((iocnum = mpt_verify_adapter(iocnumX, &ioc)) < 0) || + if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { - dtmprintk((KERN_ERR "%s::mptctl_pciinfo() @%d - ioc%d not found!\n", + dctlprintk((KERN_ERR "%s::mptctl_hp_hostinfo() @%d - ioc%d not found!\n", __FILE__, __LINE__, iocnum)); return -ENODEV; } + /* Fill in the data and return the structure to the calling + * program + */ pdev = (struct pci_dev *) ioc->pcidev; - /* Populate the structure. */ - karg.bus = pdev->bus->number; - karg.bus_type = 1; /* 1 = PCI; 4 = unknown */ - karg.device_fn = PCI_FUNC(pdev->devfn); - karg.slot_number = PCI_SLOT(pdev->devfn); - karg.vendor_id = pdev->vendor; - karg.device_id = pdev->device; - karg.board_id = (karg.device_id | (karg.vendor_id << 16)); - karg.class_code = pdev->class; + karg.vendor = pdev->vendor; + karg.device = pdev->device; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - karg.sub_vendor_id = pdev->subsystem_vendor; - karg.sub_device_id = pdev->subsystem_device; + karg.subsystem_id = pdev->subsystem_device; + karg.subsystem_vendor = pdev->subsystem_vendor; #endif + karg.devfn = pdev->devfn; + karg.bus = pdev->bus->number; + + /* Save the SCSI host no. if + * SCSI driver loaded + */ + if (ioc->sh != NULL) + karg.host_no = ioc->sh->host_no; + else + karg.host_no = -1; + + /* Reformat the fw_version into a string + */ + karg.fw_version[0] = ioc->facts.FWVersion.Struct.Major >= 10 ? + ((ioc->facts.FWVersion.Struct.Major / 10) + '0') : '0'; + karg.fw_version[1] = (ioc->facts.FWVersion.Struct.Major % 10 ) + '0'; + karg.fw_version[2] = '.'; + karg.fw_version[3] = ioc->facts.FWVersion.Struct.Minor >= 10 ? + ((ioc->facts.FWVersion.Struct.Minor / 10) + '0') : '0'; + karg.fw_version[4] = (ioc->facts.FWVersion.Struct.Minor % 10 ) + '0'; + karg.fw_version[5] = '.'; + karg.fw_version[6] = ioc->facts.FWVersion.Struct.Unit >= 10 ? + ((ioc->facts.FWVersion.Struct.Unit / 10) + '0') : '0'; + karg.fw_version[7] = (ioc->facts.FWVersion.Struct.Unit % 10 ) + '0'; + karg.fw_version[8] = '.'; + karg.fw_version[9] = ioc->facts.FWVersion.Struct.Dev >= 10 ? + ((ioc->facts.FWVersion.Struct.Dev / 10) + '0') : '0'; + karg.fw_version[10] = (ioc->facts.FWVersion.Struct.Dev % 10 ) + '0'; + karg.fw_version[11] = '\0'; /* Issue a config request to get the device serial number */ @@ -2496,8 +2478,7 @@ cfg.dir = 0; /* read */ cfg.timeout = 10; - failed = 1; - + strncpy(karg.serial_number, " ", 24); if (mpt_config(ioc, &cfg) == 0) { if (cfg.hdr->PageLength > 0) { /* Issue the second config page request */ @@ -2508,242 +2489,207 @@ cfg.physAddr = buf_dma; if (mpt_config(ioc, &cfg) == 0) { ManufacturingPage0_t *pdata = (ManufacturingPage0_t *) pbuf; - strncpy(karg.serial_number, pdata->BoardTracerNumber, 17); - failed = 0; + if (strlen(pdata->BoardTracerNumber) > 1) + strncpy(karg.serial_number, pdata->BoardTracerNumber, 24); } pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, pbuf, buf_dma); pbuf = NULL; } } } - if (failed) - strncpy(karg.serial_number, " ", 17); - - /* Copy the data from kernel memory to user memory - */ - if (copy_to_user((char *)arg, &karg, - sizeof(cpqfc_pci_info_struct))) { - printk(KERN_ERR "%s@%d::mptctl_cpq_pciinfo - " - "Unable to write out cpqfc_pci_info_struct @ %p\n", - __FILE__, __LINE__, (void*)uarg); - return -EFAULT; - } + rc = mpt_GetIocState(ioc, 1); + switch (rc) { + case MPI_IOC_STATE_OPERATIONAL: + karg.ioc_status = HP_STATUS_OK; + break; - return 0; -} + case MPI_IOC_STATE_FAULT: + karg.ioc_status = HP_STATUS_FAILED; + break; -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* mptctl_cpq_getdriver - Get Driver Version in format desired by Compaq - * - * Outputs: None. - * Return: 0 if successful - * -EFAULT if data unavailable - * -ENODEV if no such device/adapter - */ -static int -mptctl_cpq_getdriver(unsigned long arg) -{ - int *uarg = (int *)arg; - int karg; - MPT_ADAPTER *ioc = NULL; - int iocnum = 0, iocnumX = 0; - int ii, jj; - char version[10]; - char val; - char *vptr = NULL; - char *pptr = NULL; - - dctlprintk((": mptctl_cpq_getdriver called.\n")); - if (copy_from_user(&karg, uarg, sizeof(int))) { - printk(KERN_ERR "%s@%d::mptctl_cpq_getdriver - " - "Unable to read in struct @ %p\n", - __FILE__, __LINE__, (void*)uarg); - return -EFAULT; + case MPI_IOC_STATE_RESET: + case MPI_IOC_STATE_READY: + default: + karg.ioc_status = HP_STATUS_OTHER; + break; } - if (((iocnum = mpt_verify_adapter(iocnumX, &ioc)) < 0) || - (ioc == NULL)) { - dtmprintk((KERN_ERR "%s::mptctl_cpq_getdriver() @%d - ioc%d not found!\n", - __FILE__, __LINE__, iocnum)); - return -ENODEV; - } + karg.base_io_addr = pdev->PCI_BASEADDR_START(0); - strncpy(version, MPT_LINUX_VERSION_COMMON, 8); + if ((int)ioc->chip_type <= (int) FC929) + karg.bus_phys_width = HP_BUS_WIDTH_UNK; + else + karg.bus_phys_width = HP_BUS_WIDTH_16; - karg = 0; - vptr = version; - ii = 3; - while (ii > 0) { - pptr = strchr(vptr, '.'); - if (pptr) { - *pptr = '\0'; - val = 0; - for (jj=0; vptr[jj]>='0' && vptr[jj]<='9'; jj++) - val = 10 * val + (vptr[jj] - '0'); - karg |= (val << (8*ii)); - pptr++; - vptr = pptr; - } else - break; - ii--; + karg.hard_resets = 0; + karg.soft_resets = 0; + karg.timeouts = 0; + if (ioc->sh != NULL) { + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)ioc->sh->hostdata; + + if (hd) { + karg.hard_resets = hd->hard_resets; + karg.soft_resets = hd->soft_resets; + karg.timeouts = hd->timeouts; + } } /* Copy the data from kernel memory to user memory */ if (copy_to_user((char *)arg, &karg, - sizeof(int))) { - printk(KERN_ERR "%s@%d::mptctl_cpq_getdriver - " - "Unable to write out stuct @ %p\n", + sizeof(hp_host_info_t))) { + printk(KERN_ERR "%s@%d::mptctl_hpgethostinfo - " + "Unable to write out hp_host_info @ %p\n", __FILE__, __LINE__, (void*)uarg); return -EFAULT; } return 0; + } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* mptctl_cpq_ctlr_status - Get controller status in format desired by Compaq +/* Prototype Routine for the HP TARGET INFO command. * * Outputs: None. * Return: 0 if successful * -EFAULT if data unavailable + * -EBUSY if previous command timout and IOC reset is not complete. * -ENODEV if no such device/adapter + * -ETIME if timer expires + * -ENOMEM if memory allocation error */ static int -mptctl_cpq_ctlr_status(unsigned long arg) +mptctl_hp_targetinfo(unsigned long arg) { - cpqfc_ctlr_status *uarg = (cpqfc_ctlr_status *) arg; - cpqfc_ctlr_status karg; + hp_target_info_t *uarg = (hp_target_info_t *) arg; + SCSIDevicePage0_t *pg0_alloc; + SCSIDevicePage3_t *pg3_alloc; MPT_ADAPTER *ioc; - int iocnum = 0, iocnumX = 0; + MPT_SCSI_HOST *hd = NULL; + hp_target_info_t karg; + int iocnum; + int data_sz; + dma_addr_t page_dma; + CONFIGPARMS cfg; + ConfigPageHeader_t hdr; + int tmp, np, rc = 0; - dctlprintk((": mptctl_cpq_pciinfo called.\n")); - if (copy_from_user(&karg, uarg, sizeof(cpqfc_ctlr_status))) { - printk(KERN_ERR "%s@%d::mptctl_cpq_ctlr_status - " - "Unable to read in cpqfc_ctlr_status @ %p\n", + dctlprintk((": mptctl_hp_targetinfo called.\n")); + if (copy_from_user(&karg, uarg, sizeof(hp_target_info_t))) { + printk(KERN_ERR "%s@%d::mptctl_hp_targetinfo - " + "Unable to read in hp_host_targetinfo struct @ %p\n", __FILE__, __LINE__, (void*)uarg); return -EFAULT; } - - if (((iocnum = mpt_verify_adapter(iocnumX, &ioc)) < 0) || - (ioc == NULL)) { - dtmprintk((KERN_ERR "%s::mptctl_cpq_ctlr_status() @%d - ioc%d not found!\n", + + if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || + (ioc == NULL)) { + dctlprintk((KERN_ERR "%s::mptctl_hp_targetinfo() @%d - ioc%d not found!\n", __FILE__, __LINE__, iocnum)); return -ENODEV; } - karg.status = ioc->last_state; - karg.offline_reason = 0; - - /* Copy the data from kernel memory to user memory + /* There is nothing to do for FCP parts. */ - if (copy_to_user((char *)arg, &karg, - sizeof(cpqfc_ctlr_status))) { - printk(KERN_ERR "%s@%d::mptctl_cpq_ctlr_status - " - "Unable to write out cpqfc_ctlr_status @ %p\n", - __FILE__, __LINE__, (void*)uarg); - return -EFAULT; - } - - return 0; -} + if ((int) ioc->chip_type <= (int) FC929) + return 0; -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* mptctl_cpq_target_address - Get WWN Information in format desired by Compaq - * - * Outputs: None. - * Return: 0 if successful - * -EBUSY if previous command timout and IOC reset is not complete. - * -EFAULT if data unavailable - * -ENODEV if no such device/adapter - * -ETIME if timer expires - */ -static int -mptctl_cpq_target_address(unsigned long arg) -{ - Scsi_FCTargAddress *uarg = (Scsi_FCTargAddress *) arg; - Scsi_FCTargAddress karg; - MPT_ADAPTER *ioc; - int iocnum = 0, iocnumX = 0; - CONFIGPARMS cfg; - ConfigPageHeader_t hdr; - dma_addr_t buf_dma; - u8 *pbuf = NULL; - FCPortPage0_t *ppp0; - int ii, failed; - u32 low, high; - - dctlprintk((": mptctl_cpq_target_address called.\n")); - if (copy_from_user(&karg, uarg, sizeof(Scsi_FCTargAddress))) { - printk(KERN_ERR "%s@%d::mptctl_cpq_target_address - " - "Unable to read in Scsi_FCTargAddress @ %p\n", - __FILE__, __LINE__, (void*)uarg); - return -EFAULT; - } + if ((ioc->spi_data.sdp0length == 0) || (ioc->sh == NULL)) + return 0; - if (((iocnum = mpt_verify_adapter(iocnumX, &ioc)) < 0) || - (ioc == NULL)) { - dtmprintk((KERN_ERR "%s::mptctl_cpq_target_address() @%d - ioc%d not found!\n", - __FILE__, __LINE__, iocnum)); + if (ioc->sh->host_no != karg.hdr.host) return -ENODEV; - } - - karg.host_port_id = 0; + + /* Get the data transfer speeds + */ + data_sz = ioc->spi_data.sdp0length * 4; + pg0_alloc = (SCSIDevicePage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page_dma); + if (pg0_alloc) { + hdr.PageVersion = ioc->spi_data.sdp0version; + hdr.PageLength = data_sz; + hdr.PageNumber = 0; + hdr.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE; + + cfg.hdr = &hdr; + cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; + cfg.dir = 0; + cfg.timeout = 0; + cfg.physAddr = page_dma; + + cfg.pageAddr = (karg.hdr.channel << 8) | karg.hdr.id; + + if ((rc = mpt_config(ioc, &cfg)) == 0) { + np = le32_to_cpu(pg0_alloc->NegotiatedParameters); + karg.negotiated_width = np & MPI_SCSIDEVPAGE0_NP_WIDE ? + HP_BUS_WIDTH_16 : HP_BUS_WIDTH_8; + + if (np & MPI_SCSIDEVPAGE0_NP_NEG_SYNC_OFFSET_MASK) { + tmp = (np & MPI_SCSIDEVPAGE0_NP_NEG_SYNC_PERIOD_MASK) >> 8; + if (tmp < 0x09) + karg.negotiated_speed = HP_DEV_SPEED_ULTRA320; + else if (tmp <= 0x09) + karg.negotiated_speed = HP_DEV_SPEED_ULTRA160; + else if (tmp <= 0x0A) + karg.negotiated_speed = HP_DEV_SPEED_ULTRA2; + else if (tmp <= 0x0C) + karg.negotiated_speed = HP_DEV_SPEED_ULTRA; + else if (tmp <= 0x25) + karg.negotiated_speed = HP_DEV_SPEED_FAST; + else + karg.negotiated_speed = HP_DEV_SPEED_ASYNC; + } else + karg.negotiated_speed = HP_DEV_SPEED_ASYNC; + } + + pci_free_consistent(ioc->pcidev, data_sz, (u8 *) pg0_alloc, page_dma); + } + + /* Set defaults + */ + karg.message_rejects = -1; + karg.phase_errors = -1; + karg.parity_errors = -1; + karg.select_timeouts = -1; - /* Issue a config request to get the device wwn + /* Get the target error parameters */ hdr.PageVersion = 0; hdr.PageLength = 0; - hdr.PageNumber = 0; - hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT; + hdr.PageNumber = 3; + hdr.PageType = MPI_CONFIG_PAGETYPE_SCSI_DEVICE; + cfg.hdr = &hdr; - cfg.physAddr = -1; - cfg.pageAddr = 0; cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; - cfg.dir = 0; /* read */ - cfg.timeout = 10; - - failed = 1; - - if (mpt_config(ioc, &cfg) == 0) { - if (cfg.hdr->PageLength > 0) { - /* Issue the second config page request */ - cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; - - pbuf = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4, &buf_dma); - if (pbuf) { - cfg.physAddr = buf_dma; - if (mpt_config(ioc, &cfg) == 0) { - ppp0 = (FCPortPage0_t *) pbuf; - - low = le32_to_cpu(ppp0->WWNN.Low); - high = le32_to_cpu(ppp0->WWNN.High); - - for (ii = 0; ii < 4; ii++) { - karg.host_wwn[7-ii] = low & 0xFF; - karg.host_wwn[3-ii] = high & 0xFF; - low = (low >> 8); - high = (high >> 8); - } - failed = 0; - } - pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, pbuf, buf_dma); - pbuf = NULL; + cfg.dir = 0; + cfg.timeout = 0; + cfg.physAddr = -1; + if ((mpt_config(ioc, &cfg) == 0) && (cfg.hdr->PageLength > 0)) { + /* Issue the second config page request */ + cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; + data_sz = (int) cfg.hdr->PageLength * 4; + pg3_alloc = (SCSIDevicePage3_t *) pci_alloc_consistent( + ioc->pcidev, data_sz, &page_dma); + if (pg3_alloc) { + cfg.physAddr = page_dma; + cfg.pageAddr = (karg.hdr.channel << 8) | karg.hdr.id; + if ((rc = mpt_config(ioc, &cfg)) == 0) { + karg.message_rejects = (u32) le16_to_cpu(pg3_alloc->MsgRejectCount); + karg.phase_errors = (u32) le16_to_cpu(pg3_alloc->PhaseErrorCount); + karg.parity_errors = (u32) le16_to_cpu(pg3_alloc->ParityErrorCount); } + pci_free_consistent(ioc->pcidev, data_sz, (u8 *) pg3_alloc, page_dma); } } - - if (failed) { - for (ii = 7; ii >= 0; ii--) - karg.host_wwn[ii] = 0; - } + hd = (MPT_SCSI_HOST *) ioc->sh->hostdata; + if (hd != NULL) + karg.select_timeouts = hd->sel_timeout[karg.hdr.id]; /* Copy the data from kernel memory to user memory */ - if (copy_to_user((char *)arg, &karg, - sizeof(Scsi_FCTargAddress))) { - printk(KERN_ERR "%s@%d::mptctl_cpq_target_address - " - "Unable to write out Scsi_FCTargAddress @ %p\n", + if (copy_to_user((char *)arg, &karg, sizeof(hp_target_info_t))) { + printk(KERN_ERR "%s@%d::mptctl_hp_target_info - " + "Unable to write out mpt_ioctl_targetinfo struct @ %p\n", __FILE__, __LINE__, (void*)uarg); return -EFAULT; } @@ -2752,161 +2698,6 @@ } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* mptctl_cpq_passthru - Construct and issue a SCSI IO Passthru - * - * Requires the SCSI host driver to be loaded. - * I386 version. - * - * Outputs: None. - * Return: 0 if successful - * -EBUSY if previous command timout and IOC reset is not complete. - * -EFAULT if data unavailable - * -ENODEV if no such device/adapter - * -ETIME if timer expires - */ -static int -mptctl_cpq_passthru(unsigned long arg) -{ - VENDOR_IOCTL_REQ *uarg = (VENDOR_IOCTL_REQ *) arg; - VENDOR_IOCTL_REQ karg; - cpqfc_passthru_t kpass; - MPT_ADAPTER *ioc; - int iocnum = 0, iocnumX = 0; - int rc; - - dctlprintk((": mptctl_cpq_passthru called.\n")); - if (copy_from_user(&karg, uarg, sizeof(VENDOR_IOCTL_REQ))) { - printk(KERN_ERR "%s@%d::mptctl_cpq_passthru - " - "Unable to read in VENDOR_IOCTL_REQ @ %p\n", - __FILE__, __LINE__, (void*)uarg); - return -EFAULT; - } - - /* Set the IOC number */ - iocnumX = karg.lc & 0xFF; - if (((iocnum = mpt_verify_adapter(iocnumX, &ioc)) < 0) || - (ioc == NULL)) { - dtmprintk((KERN_ERR "%s::mptctl_cpq_passthru() @%d - ioc%d not found!\n", - __FILE__, __LINE__, iocnum)); - return -ENODEV; - } - - if (ioc->sh == NULL) { - printk(KERN_ERR "%s::mptctl_cpq_passthru() @%d - SCSI Host driver not loaded!\n", - __FILE__, __LINE__); - return -EFAULT; - } - - /* Read in the second buffer */ - if (copy_from_user(&kpass, uarg->argp, sizeof(cpqfc_passthru_t))) { - printk(KERN_ERR "%s@%d::mptctl_cpq_passthru - " - "Unable to read in cpqfc_passthru_t @ %p\n", - __FILE__, __LINE__, (void*)uarg); - return -EFAULT; - } - - - /* Generate the SCSI IO command and issue */ - rc = mptctl_compaq_scsiio(&karg, &kpass); - return rc; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* mptctl_compaq_scsiio - Reformat Compaq structures into driver structures - * Call the generic _do_mpt_command function. - * - * Requires the SCSI host driver to be loaded. - * I386 version. - * - * Outputs: None. - * Return: 0 if successful - * -EBUSY if previous command timout and IOC reset is not complete. - * -EFAULT if data unavailable - * -ENODEV if no such device/adapter - * -ETIME if timer expires - */ -static int -mptctl_compaq_scsiio(VENDOR_IOCTL_REQ *pVenReq, cpqfc_passthru_t *pPass) -{ - struct mpt_ioctl_command karg; - SCSIIORequest_t request ; - SCSIIORequest_t *pMf; - int ii, rc; - u8 opcode; - - /* Fill in parameters to karg */ - karg.hdr.iocnum = pVenReq->lc; - karg.hdr.port = 0; - karg.hdr.maxDataSize = 0; /* not used */ - karg.timeout = 0; /* use default */ - - karg.replyFrameBufPtr = NULL; /* no reply data */ - karg.maxReplyBytes = 0; - - karg.senseDataPtr = pPass->sense_data; - karg.maxSenseBytes = pPass->sense_len; /* max is 40 */ - - if (pPass->rw_flag == MPT_COMPAQ_WRITE) { - karg.dataOutBufPtr = pPass->bufp; - karg.dataOutSize = pPass->len; - karg.dataInBufPtr = NULL; - karg.dataInSize = 0; - } else { - karg.dataInBufPtr = pPass->bufp; - karg.dataInSize = pPass->len; - karg.dataOutBufPtr = NULL; - karg.dataOutSize = 0; - } - - karg.dataSgeOffset = (sizeof(SCSIIORequest_t) - sizeof(SGE_IO_UNION))/4; - - /* Construct the Message frame */ - pMf = &request; - - pMf->TargetID = (u8) pVenReq->ld; /* ???? FIXME */ - pMf->Bus = (u8) pPass->bus; - pMf->ChainOffset = 0; - pMf->Function = MPI_FUNCTION_SCSI_IO_REQUEST; - - /* May need some tweaking here */ - opcode = (u8) pPass->cdb[0]; - if (opcode < 0x20) - pMf->CDBLength = 6; - else if (opcode < 0x60) - pMf->CDBLength = 10; - else if ((opcode < 0xC0) && (opcode >= 0xA0)) - pMf->CDBLength = 12; - else - pMf->CDBLength = 16; - - pMf->SenseBufferLength = karg.maxSenseBytes; /* max is 40 */ - pMf->Reserved = 0; - pMf->MsgFlags = 0; /* set later */ - pMf->MsgContext = 0; /* set later */ - - for (ii = 0; ii < 8; ii++) - pMf->LUN[ii] = 0; - pMf->LUN[1] = 0; /* ???? FIXME */ - - /* Tag values set by _do_mpt_command */ - if (pPass->rw_flag == MPT_COMPAQ_WRITE) - pMf->Control = MPI_SCSIIO_CONTROL_WRITE; - else - pMf->Control = MPI_SCSIIO_CONTROL_READ; - - for (ii = 0; ii < 16; ii++) - pMf->CDB[ii] = pPass->cdb[ii]; - - pMf->DataLength = pPass->len; - - /* All remaining fields are set by the next function - */ - rc = mptctl_do_mpt_command (karg, (char *)pMf, 1); - return rc; -} - - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,51) #define owner_THIS_MODULE owner: THIS_MODULE, @@ -2971,7 +2762,7 @@ iocnumX = kfw32.iocnum & 0xFF; if (((iocnum = mpt_verify_adapter(iocnumX, &iocp)) < 0) || (iocp == NULL)) { - dtmprintk((KERN_ERR MYNAM "::sparc32_mptfwxfer_ioctl @%d - ioc%d not found!\n", + dctlprintk((KERN_ERR MYNAM "::sparc32_mptfwxfer_ioctl @%d - ioc%d not found!\n", __LINE__, iocnumX)); return -ENODEV; } @@ -3011,7 +2802,7 @@ iocnumX = karg32.hdr.iocnum & 0xFF; if (((iocnum = mpt_verify_adapter(iocnumX, &iocp)) < 0) || (iocp == NULL)) { - dtmprintk((KERN_ERR MYNAM "::sparc32_mpt_command @%d - ioc%d not found!\n", + dctlprintk((KERN_ERR MYNAM "::sparc32_mpt_command @%d - ioc%d not found!\n", __LINE__, iocnumX)); return -ENODEV; } @@ -3044,70 +2835,6 @@ return ret; } -static int -sparc32_mptctl_cpq_passthru(unsigned int fd, unsigned int cmd, - unsigned long arg, struct file *filp) -{ - VENDOR_IOCTL_REQ32 *uarg = (VENDOR_IOCTL_REQ32 *) arg; - VENDOR_IOCTL_REQ32 karg32; - VENDOR_IOCTL_REQ karg; - cpqfc_passthru32_t kpass32; - cpqfc_passthru_t kpass; - MPT_ADAPTER *ioc; - int nonblock = (filp->f_flags & O_NONBLOCK); - int iocnum = 0, iocnumX = 0; - int rc; - int ii; - - dctlprintk((KERN_INFO MYNAM "::sparc32_mptctl_cpq_passthru() called\n")); - - if (copy_from_user(&karg32, (char *)arg, sizeof(karg32))) - return -EFAULT; - - /* Verify intended MPT adapter */ - iocnumX = karg32.lc & 0xFF; - if (((iocnum = mpt_verify_adapter(iocnumX, &ioc)) < 0) || - (ioc == NULL)) { - dtmprintk((KERN_ERR MYNAM "::sparc32_mpt_command @%d - ioc%d not found!\n", - __LINE__, iocnumX)); - return -ENODEV; - } - - if ((rc = mptctl_syscall_down(ioc, nonblock)) != 0) - return rc; - - /* Copy data to karg */ - karg.ld = karg32.ld; - karg.node = karg32.node; - karg.lc = karg32.lc; - karg.nexus = karg32.nexus; - karg.argp = (void *)(unsigned long)karg32.argp; - - /* Read in the second buffer */ - if (copy_from_user(&kpass32, karg.argp, sizeof(cpqfc_passthru32_t))) { - printk(KERN_ERR "%s@%d::sparc32_mptctl_cpq_passthru - " - "Unable to read in cpqfc_passthru_t @ %p\n", - __FILE__, __LINE__, (void*)uarg); - return -EFAULT; - } - - /* Copy the 32bit buffer to kpass */ - for (ii = 0; ii < 16; ii++) - kpass.cdb[ii] = kpass32.cdb[ii]; - kpass.bus = kpass32.bus; - kpass.pdrive = kpass32.pdrive; - kpass.len = kpass32.len; - kpass.sense_len = kpass32.sense_len; - kpass.bufp = (void *)(unsigned long)kpass32.bufp; - kpass.rw_flag = kpass32.rw_flag; - - /* Generate the SCSI IO command and issue */ - rc = mptctl_compaq_scsiio(&karg, &kpass); - - up(&mptctl_syscall_sem_ioc[ioc->id]); - return rc; -} - #endif /*} linux >= 2.3.x */ #endif /*} sparc */ @@ -3176,15 +2903,9 @@ err = register_ioctl32_conversion(MPTFWDOWNLOAD32, sparc32_mptfwxfer_ioctl); if (++where && err) goto out_fail; - err = register_ioctl32_conversion(CPQFCTS_GETPCIINFO, NULL); - if (++where && err) goto out_fail; - err = register_ioctl32_conversion(CPQFCTS_CTLR_STATUS, NULL); - if (++where && err) goto out_fail; - err = register_ioctl32_conversion(CPQFCTS_GETDRIVVER, NULL); - if (++where && err) goto out_fail; - err = register_ioctl32_conversion(CPQFCTS_SCSI_IOCTL_FC_TARGET_ADDRESS, NULL); + err = register_ioctl32_conversion(HP_GETHOSTINFO, NULL); if (++where && err) goto out_fail; - err = register_ioctl32_conversion(CPQFCTS_SCSI_PASSTHRU32, sparc32_mptctl_cpq_passthru); + err = register_ioctl32_conversion(HP_GETTARGETINFO, NULL); if (++where && err) goto out_fail; #endif /*} linux >= 2.3.x */ #endif /*} sparc */ @@ -3233,11 +2954,8 @@ unregister_ioctl32_conversion(MPTHARDRESET); unregister_ioctl32_conversion(MPTCOMMAND32); unregister_ioctl32_conversion(MPTFWDOWNLOAD32); - unregister_ioctl32_conversion(CPQFCTS_GETPCIINFO); - unregister_ioctl32_conversion(CPQFCTS_GETDRIVVER); - unregister_ioctl32_conversion(CPQFCTS_CTLR_STATUS); - unregister_ioctl32_conversion(CPQFCTS_SCSI_IOCTL_FC_TARGET_ADDRESS); - unregister_ioctl32_conversion(CPQFCTS_SCSI_PASSTHRU32); + unregister_ioctl32_conversion(HP_GETHOSTINFO); + unregister_ioctl32_conversion(HP_GETTARGETINFO); #endif /*} linux >= 2.3.x */ #endif /*} sparc */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/message/fusion/mptctl.h linux.2.5.47-ac4/drivers/message/fusion/mptctl.h --- linux.2.5.47/drivers/message/fusion/mptctl.h 2002-10-31 14:57:19.000000000 +0000 +++ linux.2.5.47-ac4/drivers/message/fusion/mptctl.h 2002-11-13 01:12:10.000000000 +0000 @@ -20,7 +20,7 @@ * (mailto:sjralston1@netscape.net) * (mailto:Pam.Delaney@lsil.com) * - * $Id: mptctl.h,v 1.11 2002/10/03 13:10:13 pdelaney Exp $ + * $Id: mptctl.h,v 1.12 2002/10/17 20:15:58 pdelaney Exp $ */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* @@ -310,95 +310,91 @@ #endif /*}*/ - /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ - /* - * COMPAQ Specific IOCTL Defines and Structures - */ +/* + * HP Specific IOCTL Defines and Structures + */ #define CPQFCTS_IOC_MAGIC 'Z' +#define HP_IOC_MAGIC 'Z' +#define HP_GETHOSTINFO _IOR(HP_IOC_MAGIC, 20, hp_host_info_t) +#define HP_GETTARGETINFO _IOR(HP_IOC_MAGIC, 21, hp_target_info_t) -#define CPQFCTS_GETPCIINFO _IOR(CPQFCTS_IOC_MAGIC, 1, cpqfc_pci_info_struct) -#define CPQFCTS_GETDRIVVER _IOR(CPQFCTS_IOC_MAGIC, 9, int) -#define CPQFCTS_CTLR_STATUS _IOR(CPQFCTS_IOC_MAGIC, 3, struct _cpqfc_ctlr_status) -#define CPQFCTS_SCSI_IOCTL_FC_TARGET_ADDRESS _IOR(CPQFCTS_IOC_MAGIC, 13, struct scsi_fctargaddress) -#define CPQFCTS_SCSI_PASSTHRU _IOWR(CPQFCTS_IOC_MAGIC, 11, VENDOR_IOCTL_REQ) -#if defined(__sparc__) && defined(__sparc_v9__) -#define CPQFCTS_SCSI_PASSTHRU32 _IOWR(CPQFCTS_IOC_MAGIC, 11, VENDOR_IOCTL_REQ32) -#endif - -typedef struct { - unsigned short bus; - unsigned short bus_type; - unsigned short device_fn; - u32 board_id; - u32 slot_number; - unsigned short vendor_id; - unsigned short device_id; - unsigned short class_code; - unsigned short sub_vendor_id; - unsigned short sub_device_id; - u8 serial_number[81]; -} cpqfc_pci_info_struct; - - -typedef struct scsi_fctargaddress { - unsigned int host_port_id; - u8 host_wwn[8]; /* WW Network Name */ -} Scsi_FCTargAddress; - -typedef struct _cpqfc_ctlr_status { - u32 status; - u32 offline_reason; -} cpqfc_ctlr_status; - - -/* Compaq SCSI I/O Passthru structures. +/* All HP IOCTLs must include this header */ -#define MPT_COMPAQ_READ 0x26 -#define MPT_COMPAQ_WRITE 0x27 - -typedef struct { - int lc; /* controller number */ - int node; /* node number */ - int ld; /* target logical id */ - u32 nexus; - void *argp; -} VENDOR_IOCTL_REQ; - -#if defined(__KERNEL__) && defined(__sparc__) && defined(__sparc_v9__) /*{*/ -typedef struct { - int lc; /* controller number */ - int node; /* node number */ - int ld; /* target logical id */ - u32 nexus; - u32 argp; -} VENDOR_IOCTL_REQ32; -#endif - -typedef struct { - char cdb[16]; /* cdb */ - unsigned short bus; /* bus number */ - unsigned short pdrive; /* physical drive */ - int len; /* data area size */ - int sense_len; /* sense size */ - char sense_data[40]; /* sense buffer */ - void *bufp; /* data buffer pointer */ - char rw_flag; -} cpqfc_passthru_t; - -#if defined(__KERNEL__) && defined(__sparc__) && defined(__sparc_v9__) /*{*/ -typedef struct { - char cdb[16]; /* cdb */ - unsigned short bus; /* bus number */ - unsigned short pdrive; /* physical drive */ - int len; /* data area size */ - int sense_len; /* sense size */ - char sense_data[40]; /* sense buffer */ - u32 bufp; /* data buffer pointer */ - char rw_flag; -} cpqfc_passthru32_t; -#endif +typedef struct _hp_header { + unsigned int iocnum; + unsigned int host; + unsigned int channel; + unsigned int id; + unsigned int lun; +} hp_header_t; + +/* + * Header: + * iocnum required (input) + * host ignored + * channe ignored + * id ignored + * lun ignored + */ +typedef struct _hp_host_info { + hp_header_t hdr; + u16 vendor; + u16 device; + u16 subsystem_vendor; + u16 subsystem_id; + u8 devfn; + u8 bus; + ushort host_no; /* SCSI Host number, if scsi driver not loaded*/ + u8 fw_version[16]; /* string */ + u8 serial_number[24]; /* string */ + u32 ioc_status; + u32 bus_phys_width; + u32 base_io_addr; + u32 rsvd; + unsigned long hard_resets; /* driver initiated resets */ + unsigned long soft_resets; /* ioc, external resets */ + unsigned long timeouts; /* num timeouts */ +} hp_host_info_t; + +/* + * Header: + * iocnum required (input) + * host required + * channel required (bus number) + * id required + * lun ignored + * + * All error values between 0 and 0xFFFF in size. + */ +typedef struct _hp_target_info { + hp_header_t hdr; + u32 parity_errors; + u32 phase_errors; + u32 select_timeouts; + u32 message_rejects; + u32 negotiated_speed; + u8 negotiated_width; + u8 rsvd[7]; /* 8 byte alignment */ +} hp_target_info_t; + +#define HP_STATUS_OTHER 1 +#define HP_STATUS_OK 2 +#define HP_STATUS_FAILED 3 + +#define HP_BUS_WIDTH_UNK 1 +#define HP_BUS_WIDTH_8 2 +#define HP_BUS_WIDTH_16 3 +#define HP_BUS_WIDTH_32 4 + +#define HP_DEV_SPEED_ASYNC 2 +#define HP_DEV_SPEED_FAST 3 +#define HP_DEV_SPEED_ULTRA 4 +#define HP_DEV_SPEED_ULTRA2 5 +#define HP_DEV_SPEED_ULTRA160 6 +#define HP_DEV_SPEED_SCSI1 7 +#define HP_DEV_SPEED_ULTRA320 8 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/message/fusion/mptlan.c linux.2.5.47-ac4/drivers/message/fusion/mptlan.c --- linux.2.5.47/drivers/message/fusion/mptlan.c 2002-10-31 14:57:19.000000000 +0000 +++ linux.2.5.47-ac4/drivers/message/fusion/mptlan.c 2002-11-13 01:12:10.000000000 +0000 @@ -26,7 +26,7 @@ * Copyright (c) 2000-2002 LSI Logic Corporation * Originally By: Noah Romer * - * $Id: mptlan.c,v 1.52 2002/05/06 13:45:07 sshirron Exp $ + * $Id: mptlan.c,v 1.53 2002/10/17 20:15:58 pdelaney Exp $ */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/message/fusion/mptlan.h linux.2.5.47-ac4/drivers/message/fusion/mptlan.h --- linux.2.5.47/drivers/message/fusion/mptlan.h 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/message/fusion/mptlan.h 2002-11-13 01:12:10.000000000 +0000 @@ -8,7 +8,6 @@ #include #endif -#include #include #include // #include diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/message/fusion/mptscsih.c linux.2.5.47-ac4/drivers/message/fusion/mptscsih.c --- linux.2.5.47/drivers/message/fusion/mptscsih.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/message/fusion/mptscsih.c 2002-11-13 01:12:10.000000000 +0000 @@ -26,7 +26,7 @@ * (mailto:sjralston1@netscape.net) * (mailto:Pam.Delaney@lsil.com) * - * $Id: mptscsih.c,v 1.102 2002/10/03 13:10:14 pdelaney Exp $ + * $Id: mptscsih.c,v 1.103 2002/10/17 20:15:59 pdelaney Exp $ */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* @@ -78,6 +78,9 @@ #include /* notifier code */ #include "../../scsi/scsi.h" #include "../../scsi/hosts.h" +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,45) +#include "../../scsi/sd.h" +#endif #include "mptbase.h" #include "mptscsih.h" @@ -198,7 +201,7 @@ static int mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io); static void mptscsih_domainValidation(void *hd); static int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id); -static void mptscsih_qas_check(MPT_SCSI_HOST *hd); +static void mptscsih_qas_check(MPT_SCSI_HOST *hd, int id); static int mptscsih_doDv(MPT_SCSI_HOST *hd, int portnum, int target); static void mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage); static void mptscsih_fillbuf(char *buffer, int size, int index, int width); @@ -399,6 +402,9 @@ case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: /* 0x0043 */ /* Spoof to SCSI Selection Timeout! */ sc->result = DID_NO_CONNECT << 16; + + if (hd->sel_timeout[pScsiReq->TargetID] < 0xFFFF) + hd->sel_timeout[pScsiReq->TargetID]++; break; case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */ @@ -1289,11 +1295,17 @@ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7) sh->max_sectors = MPT_SCSI_MAX_SECTORS; #endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,1) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,1) || defined CONFIG_HIGHIO sh->highmem_io = 1; #endif sh->this_id = this->pfacts[portnum].PortSCSIID; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,44) + /* OS entry to allow host drivers to force + * a queue depth on a per device basis. + */ + sh->select_queue_depths = mptscsih_select_queue_depths; +#endif /* Required entry. */ sh->unique_id = this->id; @@ -2546,14 +2558,13 @@ /* Isse the Task Mgmt request. */ + if (hd->hard_resets < -1) + hd->hard_resets++; rc = mptscsih_IssueTaskMgmt(hd, type, target, lun, ctx2abort, sleepFlag); if (rc) { -#ifdef MPT_SCSI_USE_NEW_EH - hd->tmState = TM_STATE_ERROR; -#endif printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt failed!\n", hd->ioc->name); } else { - printk(MYIOC_s_INFO_FMT "Issue of TaskMgmt Successful!\n", hd->ioc->name); + dtmprintk((MYIOC_s_INFO_FMT "Issue of TaskMgmt Successful!\n", hd->ioc->name)); } } #ifdef DROP_TEST @@ -2681,7 +2692,6 @@ { MPT_SCSI_HOST *hd; MPT_FRAME_HDR *mf; - unsigned long flags; u32 ctx2abort; int scpnt_idx; @@ -2696,10 +2706,11 @@ return FAILED; } - printk(KERN_WARNING MYNAM ": %s: >> Attempting task abort! (sc=%p)\n", - hd->ioc->name, SCpnt); - printk(KERN_WARNING MYNAM ": %s: IOs outstanding = %d\n", - hd->ioc->name, atomic_read(&queue_depth)); + printk(KERN_WARNING MYNAM ": %s: >> Attempting task abort! (sc=%p, numIOs=%d)\n", + hd->ioc->name, SCpnt, atomic_read(&queue_depth)); + + if (hd->timeouts < -1) + hd->timeouts++; /* Find this command */ @@ -2753,11 +2764,9 @@ ctx2abort = mf->u.frame.hwhdr.msgctxu.MsgContext; hd->abortSCpnt = SCpnt; - if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK, - SCpnt->target, SCpnt->lun, ctx2abort, CAN_SLEEP) - < 0 - || hd->tmState == TM_STATE_ERROR) { + SCpnt->target, SCpnt->lun, ctx2abort, NO_SLEEP) + < 0) { /* The TM request failed and the subsequent FW-reload failed! * Fatal error case. @@ -2765,14 +2774,6 @@ printk(MYIOC_s_WARN_FMT "Error issuing abort task! (sc=%p)\n", hd->ioc->name, SCpnt); - /* If command not found, do not do callback, - * just return failed. CHECKME - */ - if (hd->ScsiLookup[scpnt_idx] != NULL) { - SCpnt->result = STS_BUSY; - SCpnt->scsi_done(SCpnt); - } - /* We must clear our pending flag before clearing our state. */ hd->tmPending = 0; @@ -2780,34 +2781,8 @@ return FAILED; } + return FAILED; - /* Our task management request will either complete or time out. So we - * spin until tmPending is != 1. If tmState is set to TM_STATE_ERROR, - * we encountered an error executing the task management request. - */ - while (hd->tmPending == 1){ - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ/4); - } - spin_lock_irqsave(&hd->ioc->FreeQlock, flags); - if (hd->tmState == TM_STATE_ERROR){ - hd->tmState = TM_STATE_NONE; - spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); - nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_abort: " - "TM timeout error! (sc=%p)\n", - hd->ioc->name, - SCpnt)); - return FAILED; - } - hd->tmState = TM_STATE_NONE; - spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); - - nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_abort: " - "Abort was successful! (sc=%p)\n", - hd->ioc->name, - SCpnt)); - - return SUCCESS; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -2823,7 +2798,6 @@ mptscsih_dev_reset(Scsi_Cmnd * SCpnt) { MPT_SCSI_HOST *hd; - unsigned long flags; /* If we can't locate our host adapter structure, return FAILED status. */ @@ -2834,10 +2808,13 @@ return FAILED; } - printk(KERN_WARNING MYNAM ": %s: >> Attempting target reset! (sc=%p)\n", - hd->ioc->name, SCpnt); - printk(KERN_WARNING MYNAM ": %s: IOs outstanding = %d\n", - hd->ioc->name, atomic_read(&queue_depth)); + printk(KERN_WARNING MYNAM ": %s: >> Attempting target reset! (sc=%p, numIOs=%d)\n", + hd->ioc->name, SCpnt, atomic_read(&queue_depth)); + + /* Unsupported for SCSI. Suppored for FCP + */ + if (hd->is_spi) + return FAILED; /* Wait a fixed amount of time for the TM pending flag to be cleared. * If we time out, then we return a FAILED status to the caller. This @@ -2853,7 +2830,7 @@ } if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, - SCpnt->target, 0, 0, CAN_SLEEP) + SCpnt->target, 0, 0, NO_SLEEP) < 0){ /* The TM request failed and the subsequent FW-reload failed! * Fatal error case. @@ -2864,34 +2841,8 @@ hd->tmState = TM_STATE_NONE; return FAILED; } - - /* Our task management request will either complete or time out. So we - * spin until tmPending is != 1. If tmState is set to TM_STATE_ERROR, - * we encountered an error executing the task management request. - */ - while (hd->tmPending == 1){ - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ/4); - } - spin_lock_irqsave(&hd->ioc->FreeQlock, flags); - if (hd->tmState == TM_STATE_ERROR){ - hd->tmState = TM_STATE_NONE; - spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); - nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_dev_reset: " - "TM timeout error! (sc=%p)\n", - hd->ioc->name, - SCpnt)); - return FAILED; - } - hd->tmState = TM_STATE_NONE; - spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); - - nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_dev_reset: " - "Device reset was successful! (sc=%p)\n", - hd->ioc->name, - SCpnt)); - return SUCCESS; + } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -2907,7 +2858,6 @@ mptscsih_bus_reset(Scsi_Cmnd * SCpnt) { MPT_SCSI_HOST *hd; - unsigned long flags; /* If we can't locate our host adapter structure, return FAILED status. */ @@ -2918,10 +2868,11 @@ return FAILED; } - printk(KERN_WARNING MYNAM ": %s: >> Attempting bus reset! (sc=%p)\n", - hd->ioc->name, SCpnt); - printk(KERN_WARNING MYNAM ": %s: IOs outstanding = %d\n", - hd->ioc->name, atomic_read(&queue_depth)); + printk(KERN_WARNING MYNAM ": %s: >> Attempting bus reset! (sc=%p, numIOs=%d)\n", + hd->ioc->name, SCpnt, atomic_read(&queue_depth)); + + if (hd->timeouts < -1) + hd->timeouts++; /* Wait a fixed amount of time for the TM pending flag to be cleared. * If we time out, then we return a FAILED status to the caller. This @@ -2932,13 +2883,13 @@ nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_bus_reset: " "Timed out waiting for previous TM to complete! " "(sc = %p)\n", - hd->ioc->name, SCpnt ) ); + hd->ioc->name, SCpnt)); return FAILED; } /* We are now ready to execute the task management request. */ if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, - 0, 0, 0, CAN_SLEEP) + 0, 0, 0, NO_SLEEP) < 0){ /* The TM request failed and the subsequent FW-reload failed! @@ -2952,32 +2903,6 @@ return FAILED; } - /* Our task management request will either complete or time out. So we - * spin until tmPending is != 1. If tmState is set to TM_STATE_ERROR, - * we encountered an error executing the task management request. - */ - while (hd->tmPending == 1){ - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ/4); - } - spin_lock_irqsave(&hd->ioc->FreeQlock, flags); - if (hd->tmState == TM_STATE_ERROR){ - hd->tmState = TM_STATE_NONE; - spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); - nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_bus_reset: " - "TM timeout error! (sc=%p)\n", - hd->ioc->name, - SCpnt)); - return FAILED; - } - hd->tmState = TM_STATE_NONE; - spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); - - nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_bus_reset: " - "Bus reset was successful! (sc=%p)\n", - hd->ioc->name, - SCpnt)); - return SUCCESS; } @@ -3013,7 +2938,7 @@ /* If our attempts to reset the host failed, then return a failed * status. The host will be taken off line by the SCSI mid-layer. */ - if (mpt_HardResetHandler(hd->ioc, CAN_SLEEP) < 0){ + if (mpt_HardResetHandler(hd->ioc, NO_SLEEP) < 0){ status = FAILED; } else { /* Make sure TM pending is cleared and TM state is set to @@ -3056,9 +2981,7 @@ break; } spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ/4); - + mdelay(250); } while (--loop_count); return status; @@ -3093,6 +3016,9 @@ return SCSI_ABORT_NOT_RUNNING; } + if (hd->timeouts < -1) + hd->timeouts++; + if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) { /* Cmd not found in ScsiLookup. * If found in doneQ, delete from Q. @@ -3166,7 +3092,7 @@ SCpnt->host_scribble = (u8 *) MPT_INDEX_2_MFPTR (hd->ioc, scpnt_idx); /* For the time being, force bus reset on any abort - * requests for the 1030 FW. + * requests for the 1030/1035 FW. */ if (hd->is_spi) mf->u.frame.linkage.arg1 = MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS; @@ -3226,6 +3152,9 @@ return SCSI_RESET_SUCCESS; } + if (hd->timeouts < -1) + hd->timeouts++; + if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) { /* Cmd not found in ScsiLookup. * If found in doneQ, delete from Q. @@ -3583,9 +3512,6 @@ } } } -#ifdef MPT_SCSI_USE_NEW_EH - hd->tmState = TM_STATE_ERROR; -#endif } else { dtmprintk((KERN_INFO " SCSI TaskMgmt SUCCESS!\n")); @@ -3629,6 +3555,9 @@ spin_lock_irqsave(&ioc->FreeQlock, flags); hd->tmPending = 0; spin_unlock_irqrestore(&ioc->FreeQlock, flags); +#ifdef MPT_SCSI_USE_NEW_EH + hd->tmState = TM_STATE_NONE; +#endif return 1; } @@ -3638,10 +3567,14 @@ * This is anyones guess quite frankly. */ int -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,44) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,45) mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev, sector_t capacity, int *ip) { +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,28) +mptscsih_bios_param(Disk * disk, struct block_device *bdev, int *ip) +{ + sector_t capacity = disk->capacity; #else mptscsih_bios_param(Disk * disk, kdev_t dev, int *ip) { @@ -3666,20 +3599,63 @@ * Called once per device the bus scan. Use it to force the queue_depth * member to 1 if a device does not support Q tags. */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,44) int mptscsih_slave_attach(Scsi_Device *device) { + struct Scsi_Host *host = device->host; VirtDevice *pTarget; - pTarget = device->hostdata; - if (!device->tagged_supported || - !(pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)) { - scsi_adjust_queue_depth(device, 0, 1); - } else { - scsi_adjust_queue_depth(device, MSG_SIMPLE_TAG, - device->host->can_queue >> 1); + MPT_SCSI_HOST *hd; + + hd = (MPT_SCSI_HOST *)host->hostdata; + if (hd && (hd->Targets != NULL)) { + pTarget = hd->Targets[device->id]; + if (pTarget) { + if (!device->tagged_supported || + !(pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)) { + scsi_adjust_queue_depth(device, 0, 1); + } else { + scsi_adjust_queue_depth(device, MSG_SIMPLE_TAG, + device->host->can_queue >> 1); + } + } } return 0; } +#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,44) */ +void +mptscsih_select_queue_depths(struct Scsi_Host *sh, Scsi_Device *sdList) +{ + struct scsi_device *device; + VirtDevice *pTarget; + MPT_SCSI_HOST *hd; + int ii, max; + + for (device = sdList; device != NULL; device = device->next) { + + if (device->host != sh) + continue; + + hd = (MPT_SCSI_HOST *) sh->hostdata; + if (hd == NULL) + continue; + + if (hd->Targets != NULL) { + if (hd->is_spi) + max = MPT_MAX_SCSI_DEVICES; + else + max = MPT_MAX_FC_DEVICES<256 ? MPT_MAX_FC_DEVICES : 255; + + for (ii=0; ii < max; ii++) { + pTarget = hd->Targets[ii]; + if (pTarget && !(pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)) { + device->queue_depth = 1; + } + } + } + } +} +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,44) */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* @@ -4126,6 +4102,9 @@ spin_unlock_irqrestore(&ioc->FreeQlock, flags); hd->resetPending = 0; hd->numTMrequests = 0; +#ifdef MPT_SCSI_USE_NEW_EH + hd->tmState = TM_STATE_NONE; +#endif /* 6. If there was an internal command, * wake this process up. @@ -4167,10 +4146,13 @@ /* FIXME! */ break; case MPI_EVENT_IOC_BUS_RESET: /* 04 */ - /* FIXME! */ - break; case MPI_EVENT_EXT_BUS_RESET: /* 05 */ - /* FIXME! */ + hd = NULL; + if (ioc->sh) { + hd = (MPT_SCSI_HOST *) ioc->sh->hostdata; + if (hd && (hd->is_spi) && (hd->soft_resets < -1)) + hd->soft_resets++; + } break; case MPI_EVENT_LOGOUT: /* 09 */ /* FIXME! */ @@ -4804,9 +4786,10 @@ } if (vdev) { - if (hd->ioc->spi_data.isRaid & (1 << target_id)) + if (hd->ioc->spi_data.isRaid & (1 << target_id)) { vdev->raidVolume = 1; - else + ddvtprintk((KERN_INFO "RAID Volume @ id %d\n", target_id)); + } else vdev->raidVolume = 0; } @@ -4868,6 +4851,8 @@ u8 version, nfactor; u8 noQas = 1; + ddvtprintk((KERN_INFO "set Target: (id %d) byte56 0x%x\n", id, byte56)); + /* Set flags based on Inquiry data */ if (target->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) { @@ -4886,12 +4871,18 @@ */ if ((byte56 & 0x04) == 0) factor = MPT_ULTRA2; + else if ((byte56 & 0x03) == 0) + factor = MPT_ULTRA160; else factor = MPT_ULTRA320; - /* bit 1 QAS support, non-raid only + /* If RAID, never disable QAS + * else if non RAID, do not disable + * QAS if bit 1 is set + * bit 1 QAS support, non-raid only + * bit 0 IU support */ - if ((target->raidVolume == 0) && (byte56 & 0x02) != 0) + if ((target->raidVolume == 1) || ((byte56 & 0x02) != 0)) noQas = 0; offset = pspi_data->maxSyncOffset; @@ -4976,6 +4967,7 @@ VirtDevice *vdev; int ii; + ddvtprintk((KERN_INFO "Disabling QAS!\n")); pspi_data->noQas = MPT_TARGET_NO_NEGO_QAS; for (ii = 0; ii < id; ii++) { vdev = hd->Targets[id]; @@ -5204,6 +5196,17 @@ //negoFlags = MPT_TARGET_NO_NEGO_SYNC; } +#ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION + /* Force to async and narrow if DV has not been executed + * for this ID + */ + if ((hd->ioc->spi_data.dvStatus[id] & MPT_SCSICFG_DV_NOT_DONE) != 0) { + width = 0; + factor = MPT_ASYNC; + offset = 0; + } +#endif + /* If id is not a raid volume, get the updated * transmission settings from the target structure. */ @@ -5313,13 +5316,6 @@ */ del_timer(&hd->TMtimer); -#ifdef MPT_SCSI_USE_NEW_EH - /* Set the error flag to 1 so that the function that started the - * task management request knows it timed out. - */ - hd->tmState = TM_STATE_ERROR; -#endif - /* Call the reset handler. Already had a TM request * timeout - so issue a diagnostic reset */ @@ -5853,6 +5849,12 @@ else pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED); + if (cmd == CMD_RequestSense) { + pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED); + ddvprintk((MYIOC_s_INFO_FMT "Untagged! 0x%2x\n", + hd->ioc->name, cmd)); + } + for (ii=0; ii < 16; ii++) pScsiReq->CDB[ii] = CDB[ii]; @@ -6184,7 +6186,7 @@ post_pendingQ_commands(hd); if (hd->ioc->spi_data.noQas) - mptscsih_qas_check(hd); + mptscsih_qas_check(hd, id); } } } @@ -6218,7 +6220,7 @@ /* Write SDP1 if no QAS has been enabled */ -static void mptscsih_qas_check(MPT_SCSI_HOST *hd) +static void mptscsih_qas_check(MPT_SCSI_HOST *hd, int id) { VirtDevice *pTarget = NULL; int ii; @@ -6227,6 +6229,9 @@ return; for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) { + if (ii == id) + continue; + if ((hd->ioc->spi_data.dvStatus[ii] & MPT_SCSICFG_DV_NOT_DONE) != 0) continue; @@ -6510,6 +6515,7 @@ rc = hd->pLocal->completion; if ((rc == MPT_SCANDV_GOOD) || (rc == MPT_SCANDV_SENSE)) { dv.max.width = 0; + doFallback = 0; } else goto target_done; } @@ -7059,6 +7065,10 @@ dv.cmd = MPT_SAVE; mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data); +#if 0 + /* Double writes to SDP1 can cause problems, + * skip here since unnecessary + */ /* Save the final negotiated settings to * SCSI device page 1. */ @@ -7067,13 +7077,14 @@ cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; cfg.dir = 1; mpt_config(hd->ioc, &cfg); +#endif } /* If this is a RAID Passthrough, enable internal IOs */ if (iocmd.flags & MPT_ICFLAG_PHYS_DISK) { if (mptscsih_do_raid(hd, MPI_RAID_ACTION_ENABLE_PHYS_IO, &iocmd) < 0) - ddvprintk((MYIOC_s_ERR_FMT "RAID Queisce FAILED!\n", ioc->name)); + ddvprintk((MYIOC_s_ERR_FMT "RAID Enable FAILED!\n", ioc->name)); } /* Done with the DV scan of the current target @@ -7227,8 +7238,7 @@ pPage1->Configuration = le32_to_cpu(configuration); } ddvprintk(("width %d, factor %x, offset %x request %x config %x\n", - dv->now.width, dv->now.factor, - dv->now.offset, val, configuration)); + width, factor, offset, val, configuration)); break; case MPT_FALLBACK: diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/message/fusion/mptscsih.h linux.2.5.47-ac4/drivers/message/fusion/mptscsih.h --- linux.2.5.47/drivers/message/fusion/mptscsih.h 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/message/fusion/mptscsih.h 2002-11-13 01:12:10.000000000 +0000 @@ -20,7 +20,7 @@ * (mailto:netscape.net) * (mailto:Pam.Delaney@lsil.com) * - * $Id: mptscsih.h,v 1.19 2002/10/03 13:10:15 pdelaney Exp $ + * $Id: mptscsih.h,v 1.20 2002/10/17 20:16:00 pdelaney Exp $ */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* @@ -206,12 +206,15 @@ #define x_scsi_dev_reset mptscsih_dev_reset #define x_scsi_host_reset mptscsih_host_reset #define x_scsi_bios_param mptscsih_bios_param -#define x_scsi_slave_attach mptscsih_slave_attach #define x_scsi_taskmgmt_bh mptscsih_taskmgmt_bh #define x_scsi_old_abort mptscsih_old_abort #define x_scsi_old_reset mptscsih_old_reset +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,44) #define x_scsi_slave_attach mptscsih_slave_attach +#else +#define x_scsi_select_queue_depths mptscsih_select_queue_depths +#endif /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* @@ -230,14 +233,20 @@ extern int x_scsi_old_abort(Scsi_Cmnd *); extern int x_scsi_old_reset(Scsi_Cmnd *, unsigned int); #endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,28) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,45) +extern int x_bios_param(struct scsi_device * sdev, struct block_device *bdev, + sector_t capacity, int *ip); +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,28) extern int x_scsi_bios_param(Disk *, struct block_device *, int *); #else extern int x_scsi_bios_param(Disk *, kdev_t, int *); #endif -extern int x_scsi_slave_attach(Scsi_Device *); extern void x_scsi_taskmgmt_bh(void *); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,45) extern int x_scsi_slave_attach(Scsi_Device *); +#else +extern void x_scsi_select_queue_depths(struct Scsi_Host *, Scsi_Device *); +#endif #if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) #define PROC_SCSI_DECL @@ -247,7 +256,7 @@ #ifdef MPT_SCSI_USE_NEW_EH -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,1) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,44) #define MPT_SCSIHOST { \ PROC_SCSI_DECL \ @@ -255,8 +264,35 @@ .detect = x_scsi_detect, \ .release = x_scsi_release, \ .info = x_scsi_info, \ + .command = NULL, \ .queuecommand = x_scsi_queuecommand, \ .slave_attach = x_scsi_slave_attach, \ + .eh_strategy_handler = NULL, \ + .eh_abort_handler = x_scsi_abort, \ + .eh_device_reset_handler = x_scsi_dev_reset, \ + .eh_bus_reset_handler = x_scsi_bus_reset, \ + .eh_host_reset_handler = x_scsi_host_reset, \ + .bios_param = x_scsi_bios_param, \ + .can_queue = MPT_SCSI_CAN_QUEUE, \ + .this_id = -1, \ + .sg_tablesize = MPT_SCSI_SG_DEPTH, \ + .max_sectors = MPT_SCSI_MAX_SECTORS, \ + .cmd_per_lun = MPT_SCSI_CMD_PER_LUN, \ + .unchecked_isa_dma = 0, \ + .use_clustering = ENABLE_CLUSTERING, \ +} + +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,1) + +#define MPT_SCSIHOST { \ + PROC_SCSI_DECL \ + .name = "MPT SCSI Host", \ + .detect = x_scsi_detect, \ + .release = x_scsi_release, \ + .info = x_scsi_info, \ + .command = NULL, \ + .queuecommand = x_scsi_queuecommand, \ + .eh_strategy_handler = NULL, \ .eh_abort_handler = x_scsi_abort, \ .eh_device_reset_handler = x_scsi_dev_reset, \ .eh_bus_reset_handler = x_scsi_bus_reset, \ @@ -267,27 +303,32 @@ .sg_tablesize = MPT_SCSI_SG_DEPTH, \ .max_sectors = MPT_SCSI_MAX_SECTORS, \ .cmd_per_lun = MPT_SCSI_CMD_PER_LUN, \ + .unchecked_isa_dma = 0, \ .use_clustering = ENABLE_CLUSTERING, \ - .slave_attach x_scsi_slave_attach, \ } #else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,1) */ #define MPT_SCSIHOST { \ + .next = NULL, \ PROC_SCSI_DECL \ .name = "MPT SCSI Host", \ .detect = x_scsi_detect, \ .release = x_scsi_release, \ .info = x_scsi_info, \ + .command = NULL, \ .queuecommand = x_scsi_queuecommand, \ + .eh_strategy_handler = NULL, \ .eh_abort_handler = x_scsi_abort, \ .eh_device_reset_handler = x_scsi_dev_reset, \ .eh_bus_reset_handler = x_scsi_bus_reset, \ + .eh_host_reset_handler = NULL, \ .bios_param = x_scsi_bios_param, \ .can_queue = MPT_SCSI_CAN_QUEUE, \ .this_id = -1, \ .sg_tablesize = MPT_SCSI_SG_DEPTH, \ .cmd_per_lun = MPT_SCSI_CMD_PER_LUN, \ + .unchecked_isa_dma = 0, \ .use_clustering = ENABLE_CLUSTERING, \ .use_new_eh_code = 1 \ } @@ -297,11 +338,13 @@ #else /* MPT_SCSI_USE_NEW_EH */ #define MPT_SCSIHOST { \ + .next = NULL, \ PROC_SCSI_DECL \ .name = "MPT SCSI Host", \ .detect = x_scsi_detect, \ .release = x_scsi_release, \ .info = x_scsi_info, \ + .command = NULL, \ .queuecommand = x_scsi_queuecommand, \ .abort = x_scsi_old_abort, \ .reset = x_scsi_old_reset, \ @@ -310,6 +353,7 @@ .this_id = -1, \ .sg_tablesize = MPT_SCSI_SG_DEPTH, \ .cmd_per_lun = MPT_SCSI_CMD_PER_LUN, \ + .unchecked_isa_dma = 0, \ .use_clustering = ENABLE_CLUSTERING \ } #endif /* MPT_SCSI_USE_NEW_EH */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/message/i2o/i2o_block.c linux.2.5.47-ac4/drivers/message/i2o/i2o_block.c --- linux.2.5.47/drivers/message/i2o/i2o_block.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/message/i2o/i2o_block.c 2002-11-02 21:48:00.000000000 +0000 @@ -1669,7 +1669,6 @@ if(i2o_install_handler(&i2o_block_handler)<0) { unregister_blkdev(MAJOR_NR, "i2o_block"); - blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); printk(KERN_ERR "i2o_block: unable to register OSM.\n"); return -EINVAL; } @@ -1682,8 +1681,7 @@ evt_pid = kernel_thread(i2ob_evt, NULL, CLONE_SIGHAND); if(evt_pid < 0) { - printk(KERN_ERR - "i2o_block: Could not initialize event thread. Aborting\n"); + printk(KERN_ERR "i2o_block: Could not initialize event thread. Aborting\n"); i2o_remove_handler(&i2o_block_handler); return 0; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/message/i2o/i2o_scsi.c linux.2.5.47-ac4/drivers/message/i2o/i2o_scsi.c --- linux.2.5.47/drivers/message/i2o/i2o_scsi.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/message/i2o/i2o_scsi.c 2002-11-02 23:58:17.000000000 +0000 @@ -57,7 +57,6 @@ #include #include "../../scsi/scsi.h" #include "../../scsi/hosts.h" -#include "../../scsi/sd.h" #if BITS_PER_LONG == 64 #error FIXME: driver does not support 64-bit platforms @@ -918,6 +917,7 @@ unsigned long msg; u32 m; int tid; + unsigned long timeout; printk(KERN_WARNING "i2o_scsi: Aborting command block.\n"); @@ -930,21 +930,21 @@ return FAILED; } c = hostdata->controller; - - /* - * Obtain an I2O message. Right now we _have_ to obtain one - * until the scsi layer stuff is cleaned up. - * - * FIXME: we are in error context so we could sleep retry - * a bit and then bail in the improved scsi layer. - */ - + + spin_unlock_irq(host->host_lock); + + timeout = jiffies+2*HZ; do { - mb(); m = le32_to_cpu(I2O_POST_READ32(c)); + if(m != 0xFFFFFFFF) + break; + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1); + mb(); } - while(m==0xFFFFFFFF); + while(time_before(jiffies, timeout)); + msg = c->mem_offset + m; i2o_raw_writel(FIVE_WORD_MSG_SIZE, msg); @@ -955,6 +955,8 @@ wmb(); i2o_post_message(c,m); wmb(); + + spin_lock_irq(host->host_lock); return SUCCESS; } @@ -977,14 +979,20 @@ struct i2o_scsi_host *hostdata; u32 m; unsigned long msg; + unsigned long timeout; + /* * Find the TID for the bus */ - printk(KERN_WARNING "i2o_scsi: Attempting to reset the bus.\n"); host = SCpnt->host; + + spin_unlock_irq(host->host_lock); + + printk(KERN_WARNING "i2o_scsi: Attempting to reset the bus.\n"); + hostdata = (struct i2o_scsi_host *)host->hostdata; tid = hostdata->bus_task; c = hostdata->controller; @@ -994,15 +1002,19 @@ * will be aborted by the IOP. We need to catch the reply * possibly ? */ - - m = le32_to_cpu(I2O_POST_READ32(c)); + + timeout = jiffies+2*HZ; + do + { + m = le32_to_cpu(I2O_POST_READ32(c)); + if(m != 0xFFFFFFFF) + break; + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1); + mb(); + } + while(time_before(jiffies, timeout)); - /* - * No free messages, try again next time - no big deal - */ - - if(m == 0xFFFFFFFF) - return SCSI_RESET_PUNT; msg = c->mem_offset + m; i2o_raw_writel(FOUR_WORD_MSG_SIZE|SGL_OFFSET_0, msg); @@ -1012,7 +1024,12 @@ /* Now store unit,tid so we can tie the completion back to a specific device */ __raw_writel(c->unit << 16 | tid, msg+12); wmb(); + + /* We want the command to complete after we return */ + spin_lock_irq(host->host_lock); i2o_post_message(c,m); + + /* Should we wait for the reset to complete ? */ return SUCCESS; } @@ -1044,8 +1061,9 @@ /** * i2o_scsi_bios_param - Invent disk geometry - * @disk: device + * @sdev: scsi device * @dev: block layer device + * @capacity: size in sectors * @ip: geometry array * * This is anyones guess quite frankly. We use the same rules everyone diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/net/hamradio/baycom_epp.c linux.2.5.47-ac4/drivers/net/hamradio/baycom_epp.c --- linux.2.5.47/drivers/net/hamradio/baycom_epp.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/net/hamradio/baycom_epp.c 2002-11-11 19:55:15.000000000 +0000 @@ -54,7 +54,6 @@ #include #include #include -#include #if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) /* prototypes for ax25_encapsulate and ax25_rebuild_header */ #include @@ -1200,7 +1199,6 @@ struct baycom_state *bc; struct baycom_ioctl bi; struct hdlcdrv_ioctl hi; - struct sm_ioctl si; baycom_paranoia_check(dev, "baycom_ioctl", -EINVAL); bc = (struct baycom_state *)dev->priv; @@ -1208,28 +1206,6 @@ return -ENOIOCTLCMD; if (get_user(cmd, (int *)ifr->ifr_data)) return -EFAULT; -#ifdef BAYCOM_DEBUG - if (cmd == BAYCOMCTL_GETDEBUG) { - bi.data.dbg.debug1 = bc->ptt_keyed; - bi.data.dbg.debug2 = bc->debug_vals.last_intcnt; - bi.data.dbg.debug3 = bc->debug_vals.last_pllcorr; - bc->debug_vals.last_intcnt = 0; - if (copy_to_user(ifr->ifr_data, &bi, sizeof(bi))) - return -EFAULT; - return 0; - } - if (cmd == SMCTL_GETDEBUG) { - si.data.dbg.int_rate = bc->debug_vals.last_intcnt; - si.data.dbg.mod_cycles = bc->debug_vals.mod_cycles; - si.data.dbg.demod_cycles = bc->debug_vals.demod_cycles; - si.data.dbg.dma_residue = 0; - bc->debug_vals.mod_cycles = bc->debug_vals.demod_cycles = 0; - bc->debug_vals.last_intcnt = 0; - if (copy_to_user(ifr->ifr_data, &si, sizeof(si))) - return -EFAULT; - return 0; - } -#endif /* BAYCOM_DEBUG */ if (copy_from_user(&hi, ifr->ifr_data, sizeof(hi))) return -EFAULT; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/net/hamradio/Kconfig linux.2.5.47-ac4/drivers/net/hamradio/Kconfig --- linux.2.5.47/drivers/net/hamradio/Kconfig 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/net/hamradio/Kconfig 2002-11-05 16:08:04.000000000 +0000 @@ -185,120 +185,6 @@ say M here and read . This is recommended. The module will be called baycom_par.o. -config SOUNDMODEM - tristate "Soundcard modem driver" - depends on PARPORT && AX25 - ---help--- - This experimental driver allows a standard Sound Blaster or - WindowsSoundSystem compatible sound card to be used as a packet - radio modem (NOT as a telephone modem!), to send digital traffic - over amateur radio. - - To configure the driver, use the sethdlc, smdiag and smmixer - utilities available in the standard ax25 utilities package. For - information on how to key the transmitter, see - and - . - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . This is - recommended. The module will be called soundmodem.o. - -config SOUNDMODEM_SBC - bool "soundmodem support for Soundblaster and compatible cards" - depends on SOUNDMODEM - help - This option enables the soundmodem driver to use Sound Blaster and - compatible cards. If you have a dual mode card (i.e. a WSS cards - with a Sound Blaster emulation) you should say N here and Y to - "Sound card modem support for WSS and Crystal cards", below, because - this usually results in better performance. This option also - supports SB16/32/64 in full-duplex mode. - -config SOUNDMODEM_WSS - bool "soundmodem support for WSS and Crystal cards" - depends on SOUNDMODEM - help - This option enables the soundmodem driver to use WindowsSoundSystem - compatible cards. These cards feature a codec chip from either - Analog Devices (such as AD1848, AD1845, AD1812) or Crystal - Semiconductors (such as CS4248, CS423x). This option also supports - the WSS full-duplex operation which currently works with Crystal - CS423x chips. If you don't need full-duplex operation, do not enable - it to save performance. - -config SOUNDMODEM_AFSK1200 - bool "soundmodem support for 1200 baud AFSK modulation" - depends on SOUNDMODEM - help - This option enables the soundmodem driver 1200 baud AFSK modem, - compatible to popular modems using TCM3105 or AM7911. The - demodulator requires about 12% of the CPU power of a Pentium 75 CPU - per channel. - -config SOUNDMODEM_AFSK2400_7 - bool "soundmodem support for 2400 baud AFSK modulation (7.3728MHz crystal)" - depends on SOUNDMODEM - help - This option enables the soundmodem driver 2400 baud AFSK modem, - compatible to TCM3105 modems (over-)clocked with a 7.3728MHz - crystal. Note that the availability of this driver does _not_ imply - that I recommend building such links. It is only here since users - especially in eastern Europe have asked me to do so. In fact this - modulation scheme has many disadvantages, mainly its incompatibility - with many transceiver designs and the fact that the TCM3105 (if - used) is operated widely outside its specifications. - -config SOUNDMODEM_AFSK2400_8 - bool "soundmodem support for 2400 baud AFSK modulation (8MHz crystal)" - depends on SOUNDMODEM - help - This option enables the soundmodem driver 2400 baud AFSK modem, - compatible to TCM3105 modems (over-)clocked with an 8MHz crystal. - Note that the availability of this driver does _not_ imply that I - recommend building such links. It is only here since users - especially in eastern Europe have asked me to do so. In fact this - modulation scheme has many disadvantages, mainly its incompatibility - with many transceiver designs and the fact that the TCM3105 (if - used) is operated widely outside its specifications. - -config SOUNDMODEM_AFSK2666 - bool "soundmodem support for 2666 baud AFSK modulation" - depends on SOUNDMODEM - help - This option enables the soundmodem driver 2666 baud AFSK modem. - This modem is experimental, and not compatible to anything - else I know of. - -config SOUNDMODEM_HAPN4800 - bool "soundmodem support for 4800 baud HAPN-1 modulation" - depends on SOUNDMODEM - help - This option enables the soundmodem driver 4800 baud HAPN-1 - compatible modem. This modulation seems to be widely used 'down - under' and in the Netherlands. Here, nobody uses it, so I could not - test if it works. It is compatible to itself, however :-) - -config SOUNDMODEM_PSK4800 - bool "soundmodem support for 4800 baud PSK modulation" - depends on SOUNDMODEM - help - This option enables the soundmodem driver 4800 baud 8PSK modem. - This modem is experimental, and not compatible to anything - else I know of. - -config SOUNDMODEM_FSK9600 - bool "soundmodem support for 9600 baud FSK G3RUH modulation" - depends on SOUNDMODEM - help - This option enables the soundmodem driver 9600 baud FSK modem, - compatible to the G3RUH standard. The demodulator requires about 4% - of the CPU power of a Pentium 75 CPU per channel. You can say Y to - both 1200 baud AFSK and 9600 baud FSK if you want (but obviously you - can only use one protocol at a time, depending on what the other end - can understand). - config YAM tristate "YAM driver for AX.25" depends on AX25 diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/net/hamradio/Makefile linux.2.5.47-ac4/drivers/net/hamradio/Makefile --- linux.2.5.47/drivers/net/hamradio/Makefile 2002-10-31 14:57:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/net/hamradio/Makefile 2002-11-05 16:08:04.000000000 +0000 @@ -22,6 +22,5 @@ obj-$(CONFIG_BAYCOM_SER_HDX) += baycom_ser_hdx.o hdlcdrv.o obj-$(CONFIG_BAYCOM_PAR) += baycom_par.o hdlcdrv.o obj-$(CONFIG_BAYCOM_EPP) += baycom_epp.o hdlcdrv.o -obj-$(CONFIG_SOUNDMODEM) += soundmodem/ hdlcdrv.o include $(TOPDIR)/Rules.make diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/net/hamradio/soundmodem/gentbl.c linux.2.5.47-ac4/drivers/net/hamradio/soundmodem/gentbl.c --- linux.2.5.47/drivers/net/hamradio/soundmodem/gentbl.c 2002-10-31 14:57:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/net/hamradio/soundmodem/gentbl.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,689 +0,0 @@ -/*****************************************************************************/ - -/* - * gentbl.c -- soundcard radio modem driver table generator. - * - * Copyright (C) 1996 Thomas Sailer (sailer@ife.ee.ethz.ch) - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Please note that the GPL allows you to use the driver, NOT the radio. - * In order to use the radio, you need a license from the communications - * authority of your country. - * - */ - -#include -#include -#include -#include - -/* -------------------------------------------------------------------- */ - -static void gentbl_offscostab(FILE *f, unsigned int nbits) -{ - int i; - - fprintf(f, "\n/*\n * small cosine table in U8 format\n */\n" - "#define OFFSCOSTABBITS %u\n" - "#define OFFSCOSTABSIZE (1<>%d)&0x%x]\n\n", - 16-nbits, (1<>%d)&0x%x]\n" - "#define SIN(x) COS((x)+0xc000)\n\n", 16-nbits, - (1< max) - max = s; - if (s < min) - min = s; - fprintf(f, "%4d", (int)(128+127*s)); - if (i < 3 || j < 255) - fprintf(f, ",%s", (j & 7) == 7 - ? "\n\t" : ""); - } - } -#ifdef VERBOSE - fprintf(stderr, "fsk9600: txfilt4: min = %f; max = %f\n", min, max); -#endif - fprintf(f, "\n};\n\n"); - min = max = 0; - memset(c, 0, sizeof(c)); -#if 0 - memcpy(c+2, fsk96_tx_coeff_5, sizeof(fsk96_tx_coeff_5)); -#else - for (i = 0; i < 36; i++) - c[4+i] = sinc(1.2*((i-17.5)/5.0))*hamming(i/35.0)/4.5; -#endif - fprintf(f, "static unsigned char fsk96_txfilt_5[] = {\n\t"); - for (i = 0; i < 5; i++) { - for (j = 0; j < 256; j++) { - for (k = 1, s = 0, l = i; k < 256; k <<= 1) { - if (j & k) { - for (m = 0; m < 5; m++, l++) - s += c[l]; - } else { - for (m = 0; m < 5; m++, l++) - s -= c[l]; - } - } - s *= 0.75; - if (s > max) - max = s; - if (s < min) - min = s; - fprintf(f, "%4d", (int)(128+127*s)); - if (i < 4 || j < 255) - fprintf(f, ",%s", (j & 7) == 7 - ? "\n\t" : ""); - } - } -#ifdef VERBOSE - fprintf(stderr, "fsk9600: txfilt5: min = %f; max = %f\n", min, max); -#endif - fprintf(f, "\n};\n\n"); -} - -/* -------------------------------------------------------------------- */ - -#define AFSK26_SAMPLERATE 16000 - -#define AFSK26_NUMCAR 2 -#define AFSK26_FIRSTCAR 2000 -#define AFSK26_MSK_LEN 6 -#define AFSK26_RXOVER 2 - -#define AFSK26_DEMCORRLEN (2*AFSK26_MSK_LEN) - -#define AFSK26_WINDOW(x) ((1-cos(2.0*M_PI*(x)))/2.0) - -#define AFSK26_AMPL(x) (((x)?1.0:0.7)) - -#undef AFSK26_AMPL -#define AFSK26_AMPL(x) 1 - -static void gentbl_afsk2666(FILE *f) -{ - int i, j, k, l, o, v, sumi, sumq; - float window[AFSK26_DEMCORRLEN*AFSK26_RXOVER]; - int cfreq[AFSK26_NUMCAR]; - - fprintf(f, "\n/*\n * afsk2666 specific tables\n */\n" - "#define AFSK26_DEMCORRLEN %d\n" - "#define AFSK26_SAMPLERATE %d\n\n", AFSK26_DEMCORRLEN, - AFSK26_SAMPLERATE); - fprintf(f, "static const unsigned int afsk26_carfreq[%d] = { ", - AFSK26_NUMCAR); - for (i = 0; i < AFSK26_NUMCAR; i++) { - cfreq[i] = 0x10000*AFSK26_FIRSTCAR/AFSK26_SAMPLERATE+ - 0x10000*i/AFSK26_MSK_LEN/2; - fprintf(f, "0x%x", cfreq[i]); - if (i < AFSK26_NUMCAR-1) - fprintf(f, ", "); - } - fprintf(f, " };\n\n"); - for (i = 0; i < AFSK26_DEMCORRLEN*AFSK26_RXOVER; i++) - window[i] = AFSK26_WINDOW(((float)i)/(AFSK26_DEMCORRLEN* - AFSK26_RXOVER)) * 127.0; - fprintf(f, "\nstatic const struct {\n\t" - "int i[%d];\n\tint q[%d];\n} afsk26_dem_tables[%d][%d] = {\n", - AFSK26_DEMCORRLEN, AFSK26_DEMCORRLEN, AFSK26_RXOVER, AFSK26_NUMCAR); - for (o = AFSK26_RXOVER-1; o >= 0; o--) { - fprintf(f, "\t{\n"); - for (i = 0; i < AFSK26_NUMCAR; i++) { - j = cfreq[i]; - fprintf(f, "\t\t{{ "); - for (l = AFSK26_DEMCORRLEN-1, k = (j * o)/AFSK26_RXOVER, sumi = 0; l >= 0; - l--, k = (k+j)&0xffffu) { - sumi += (v = AFSK26_AMPL(i)*window[l*AFSK26_RXOVER+o]* - cos(M_PI*k/32768.0)); - fprintf(f, "%6d%s", v, l ? ", " : " }, { "); - } - for (l = AFSK26_DEMCORRLEN-1, k = (j * o)/AFSK26_RXOVER, sumq = 0; l >= 0; - l--, k = (k+j)&0xffffu) { - sumq += (v = AFSK26_AMPL(i)*window[l*AFSK26_RXOVER+o]* - sin(M_PI*k/32768.0)); - fprintf(f, "%6d%s", v, l ? ", " : " }}"); - } - if (i < 1) - fprintf(f, ","); - fprintf(f, "\n#define AFSK26_DEM_SUM_I_%d_%d %d\n" - "#define AFSK26_DEM_SUM_Q_%d_%d %d\n", - AFSK26_RXOVER-1-o, i, sumi, AFSK26_RXOVER-1-o, i, sumq); - } - fprintf(f, "\t}%s\n", o ? "," : ""); - } - fprintf(f, "};\n\n"); -} - -/* -------------------------------------------------------------------- */ - -#define ATAN_TABLEN 1024 - -static void gentbl_atantab(FILE *f) -{ - int i; - short x; - - fprintf(f, "\n/*\n" - " * arctan table (indexed by i/q; should really be indexed by i/(i+q)\n" - " */\n""#define ATAN_TABLEN %d\n\n" - "static const unsigned short atan_tab[ATAN_TABLEN+2] = {", - ATAN_TABLEN); - for (i = 0; i <= ATAN_TABLEN; i++) { - if (!(i & 7)) - fprintf(f, "\n\t"); - x = atan(i / (float)ATAN_TABLEN) / M_PI * 0x8000; - fprintf(f, "%6d, ", x); - } - fprintf(f, "%6d\n};\n\n", x); - -} - -/* -------------------------------------------------------------------- */ - -#define PSK48_TXF_OVERSAMPLING 5 -#define PSK48_TXF_NUMSAMPLES 16 -#define PSK48_RXF_LEN 64 - -static const float psk48_tx_coeff[80] = { - -0.000379, -0.000640, -0.000000, 0.000772, - 0.000543, -0.000629, -0.001187, -0.000000, - 0.001634, 0.001183, -0.001382, -0.002603, - -0.000000, 0.003481, 0.002472, -0.002828, - -0.005215, -0.000000, 0.006705, 0.004678, - -0.005269, -0.009584, -0.000000, 0.012065, - 0.008360, -0.009375, -0.017028, -0.000000, - 0.021603, 0.015123, -0.017229, -0.032012, - -0.000000, 0.043774, 0.032544, -0.040365, - -0.084963, -0.000000, 0.201161, 0.374060, - 0.374060, 0.201161, -0.000000, -0.084963, - -0.040365, 0.032544, 0.043774, -0.000000, - -0.032012, -0.017229, 0.015123, 0.021603, - -0.000000, -0.017028, -0.009375, 0.008360, - 0.012065, -0.000000, -0.009584, -0.005269, - 0.004678, 0.006705, -0.000000, -0.005215, - -0.002828, 0.002472, 0.003481, -0.000000, - -0.002603, -0.001382, 0.001183, 0.001634, - -0.000000, -0.001187, -0.000629, 0.000543, - 0.000772, -0.000000, -0.000640, -0.000379 -}; - -static const float psk48_rx_coeff[PSK48_RXF_LEN] = { - -0.000219, 0.000360, 0.000873, 0.001080, - 0.000747, -0.000192, -0.001466, -0.002436, - -0.002328, -0.000699, 0.002101, 0.004809, - 0.005696, 0.003492, -0.001633, -0.007660, - -0.011316, -0.009627, -0.001780, 0.009712, - 0.019426, 0.021199, 0.011342, -0.008583, - -0.030955, -0.044093, -0.036634, -0.002651, - 0.054742, 0.123101, 0.184198, 0.220219, - 0.220219, 0.184198, 0.123101, 0.054742, - -0.002651, -0.036634, -0.044093, -0.030955, - -0.008583, 0.011342, 0.021199, 0.019426, - 0.009712, -0.001780, -0.009627, -0.011316, - -0.007660, -0.001633, 0.003492, 0.005696, - 0.004809, 0.002101, -0.000699, -0.002328, - -0.002436, -0.001466, -0.000192, 0.000747, - 0.001080, 0.000873, 0.000360, -0.000219 -}; - -static void gentbl_psk4800(FILE *f) -{ - int i, j, k; - short x; - - fprintf(f, "\n/*\n * psk4800 specific tables\n */\n" - "#define PSK48_TXF_OVERSAMPLING %d\n" - "#define PSK48_TXF_NUMSAMPLES %d\n\n" - "#define PSK48_SAMPLERATE 8000\n" - "#define PSK48_CAR_FREQ 2000\n" - "#define PSK48_PSK_LEN 5\n" - "#define PSK48_RXF_LEN %u\n" - "#define PSK48_PHASEINC (0x10000*PSK48_CAR_FREQ/PSK48_SAMPLERATE)\n" - "#define PSK48_SPHASEINC (0x10000/(2*PSK48_PSK_LEN))\n\n" - "static const short psk48_tx_table[PSK48_TXF_OVERSAMPLING*" - "PSK48_TXF_NUMSAMPLES*8*2] = {", - PSK48_TXF_OVERSAMPLING, PSK48_TXF_NUMSAMPLES, PSK48_RXF_LEN); - for (i = 0; i < PSK48_TXF_OVERSAMPLING; i++) { - for (j = 0; j < PSK48_TXF_NUMSAMPLES; j++) { - fprintf(f, "\n\t"); - for (k = 0; k < 8; k++) { - x = 32767.0 * cos(k*M_PI/4.0) * - psk48_tx_coeff[j * PSK48_TXF_OVERSAMPLING + i]; - fprintf(f, "%6d, ", x); - } - fprintf(f, "\n\t"); - for (k = 0; k < 8; k++) { - x = 32767.0 * sin(k*M_PI/4.0) * - psk48_tx_coeff[j * PSK48_TXF_OVERSAMPLING + i]; - fprintf(f, "%6d", x); - if (k != 7 || j != PSK48_TXF_NUMSAMPLES-1 || - i != PSK48_TXF_OVERSAMPLING-1) - fprintf(f, ", "); - } - } - } - fprintf(f, "\n};\n\n"); - - fprintf(f, "static const short psk48_rx_coeff[PSK48_RXF_LEN] = {\n\t"); - for (i = 0; i < PSK48_RXF_LEN; i++) { - fprintf(f, "%6d", (int)(psk48_rx_coeff[i]*32767.0)); - if (i < PSK48_RXF_LEN-1) - fprintf(f, ",%s", (i & 7) == 7 ? "\n\t" : ""); - } - fprintf(f, "\n};\n\n"); -} - -/* -------------------------------------------------------------------- */ - -static void gentbl_hapn4800(FILE *f) -{ - int i, j, k, l; - float s; - float c[44]; - float min, max; - - fprintf(f, "\n/*\n * hapn4800 specific tables\n */\n\n"); - /* - * firstly generate tables for the FM transmitter modulator - */ - min = max = 0; - memset(c, 0, sizeof(c)); - for (i = 0; i < 24; i++) - c[8+i] = sinc(1.5*((i-11.5)/8.0))*hamming(i/23.0)/2.4; - for (i = 0; i < 24; i++) - c[i] -= c[i+8]; - fprintf(f, "static unsigned char hapn48_txfilt_8[] = {\n\t"); - for (i = 0; i < 8; i++) { - for (j = 0; j < 16; j++) { - for (k = 1, s = 0, l = i; k < 16; k <<= 1, l += 8) { - if (j & k) - s += c[l]; - else - s -= c[l]; - } - if (s > max) - max = s; - if (s < min) - min = s; - fprintf(f, "%4d", (int)(128+127*s)); - if (i < 7 || j < 15) - fprintf(f, ",%s", (j & 7) == 7 - ? "\n\t" : ""); - } - } -#ifdef VERBOSE - fprintf(stderr, "hapn4800: txfilt8: min = %f; max = %f\n", min, max); -#endif - fprintf(f, "\n};\n\n"); - min = max = 0; - memset(c, 0, sizeof(c)); - for (i = 0; i < 30; i++) - c[10+i] = sinc(1.5*((i-14.5)/10.0))*hamming(i/29.0)/2.4; - for (i = 0; i < 30; i++) - c[i] -= c[i+10]; - fprintf(f, "static unsigned char hapn48_txfilt_10[] = {\n\t"); - for (i = 0; i < 10; i++) { - for (j = 0; j < 16; j++) { - for (k = 1, s = 0, l = i; k < 16; k <<= 1, l += 10) { - if (j & k) - s += c[l]; - else - s -= c[l]; - } - if (s > max) - max = s; - if (s < min) - min = s; - fprintf(f, "%4d", (int)(128+127*s)); - if (i < 9 || j < 15) - fprintf(f, ",%s", (j & 7) == 7 - ? "\n\t" : ""); - } - } -#ifdef VERBOSE - fprintf(stderr, "hapn4800: txfilt10: min = %f; max = %f\n", min, max); -#endif - fprintf(f, "\n};\n\n"); - /* - * secondly generate tables for the PM transmitter modulator - */ - min = max = 0; - memset(c, 0, sizeof(c)); - for (i = 0; i < 25; i++) - c[i] = sinc(1.4*((i-12.0)/8.0))*hamming(i/24.0)/6.3; - for (i = 0; i < 25; i++) - for (j = 1; j < 8; j++) - c[i] += c[i+j]; - fprintf(f, "static unsigned char hapn48_txfilt_pm8[] = {\n\t"); - for (i = 0; i < 8; i++) { - for (j = 0; j < 16; j++) { - for (k = 1, s = 0, l = i; k < 16; k <<= 1, l += 8) { - if (j & k) - s += c[l]; - else - s -= c[l]; - } - if (s > max) - max = s; - if (s < min) - min = s; - fprintf(f, "%4d", (int)(128+127*s)); - if (i < 7 || j < 15) - fprintf(f, ",%s", (j & 7) == 7 - ? "\n\t" : ""); - } - } -#ifdef VERBOSE - fprintf(stderr, "hapn4800: txfiltpm8: min = %f; max = %f\n", min, max); -#endif - fprintf(f, "\n};\n\n"); - min = max = 0; - memset(c, 0, sizeof(c)); - for (i = 0; i < 31; i++) - c[10+i] = sinc(1.4*((i-15.0)/10.0))*hamming(i/30.0)/7.9; - for (i = 0; i < 31; i++) - for (j = 1; j < 10; j++) - c[i] += c[i+j]; - fprintf(f, "static unsigned char hapn48_txfilt_pm10[] = {\n\t"); - for (i = 0; i < 10; i++) { - for (j = 0; j < 16; j++) { - for (k = 1, s = 0, l = i; k < 16; k <<= 1, l += 10) { - if (j & k) - s += c[l]; - else - s -= c[l]; - } - if (s > max) - max = s; - if (s < min) - min = s; - fprintf(f, "%4d", (int)(128+127*s)); - if (i < 9 || j < 15) - fprintf(f, ",%s", (j & 7) == 7 - ? "\n\t" : ""); - } - } -#ifdef VERBOSE - fprintf(stderr, "hapn4800: txfiltpm10: min = %f; max = %f\n", min, max); -#endif - fprintf(f, "\n};\n\n"); - -} - -/* -------------------------------------------------------------------- */ - -#define AFSK24_SAMPLERATE 16000 -#define AFSK24_CORRLEN 14 - -static void gentbl_afsk2400(FILE *f, float tcm3105clk) -{ - int i, sum, v; - - fprintf(f, "\n/*\n * afsk2400 specific tables (tcm3105 clk %7fHz)\n */\n" - "#define AFSK24_TX_FREQ_LO %d\n" - "#define AFSK24_TX_FREQ_HI %d\n" - "#define AFSK24_BITPLL_INC %d\n" - "#define AFSK24_SAMPLERATE %d\n\n", tcm3105clk, - (int)(tcm3105clk/3694.0), (int)(tcm3105clk/2015.0), - 0x10000*2400/AFSK24_SAMPLERATE, AFSK24_SAMPLERATE); - -#define ARGLO(x) 2.0*M_PI*(double)x*(tcm3105clk/3694.0)/(double)AFSK24_SAMPLERATE -#define ARGHI(x) 2.0*M_PI*(double)x*(tcm3105clk/2015.0)/(double)AFSK24_SAMPLERATE -#define WINDOW(x) hamming((float)(x)/(AFSK24_CORRLEN-1.0)) - - fprintf(f, "static const int afsk24_tx_lo_i[] = {\n\t"); - for(sum = i = 0; i < AFSK24_CORRLEN; i++) { - sum += (v = 127.0*cos(ARGLO(i))*WINDOW(i)); - fprintf(f, " %4i%c", v, (i < AFSK24_CORRLEN-1) ? ',' : ' '); - } - fprintf(f, "\n};\n#define SUM_AFSK24_TX_LO_I %d\n\n" - "static const int afsk24_tx_lo_q[] = {\n\t", sum); - for(sum = i = 0; i < AFSK24_CORRLEN; i++) { - sum += (v = 127.0*sin(ARGLO(i))*WINDOW(i)); - fprintf(f, " %4i%c", v, (i < AFSK24_CORRLEN-1) ? ',' : ' '); - } - fprintf(f, "\n};\n#define SUM_AFSK24_TX_LO_Q %d\n\n" - "static const int afsk24_tx_hi_i[] = {\n\t", sum); - for(sum = i = 0; i < AFSK24_CORRLEN; i++) { - sum += (v = 127.0*cos(ARGHI(i))*WINDOW(i)); - fprintf(f, " %4i%c", v, (i < AFSK24_CORRLEN-1) ? ',' : ' '); - } - fprintf(f, "\n};\n#define SUM_AFSK24_TX_HI_I %d\n\n" - "static const int afsk24_tx_hi_q[] = {\n\t", sum); - for(sum = i = 0; i < AFSK24_CORRLEN; i++) { - sum += (v = 127.0*sin(ARGHI(i))*WINDOW(i)); - fprintf(f, " %4i%c", v, (i < AFSK24_CORRLEN-1) ? ',' : ' '); - } - fprintf(f, "\n};\n#define SUM_AFSK24_TX_HI_Q %d\n\n", sum); -#undef ARGLO -#undef ARGHI -#undef WINDOW -} - -/* -------------------------------------------------------------------- */ - -static char *progname; - -static void gentbl_banner(FILE *f) -{ - fprintf(f, "/*\n * THIS FILE IS GENERATED AUTOMATICALLY BY %s, " - "DO NOT EDIT!\n */\n\n", progname); -} - -/* -------------------------------------------------------------------- */ - -int main(int argc, char *argv[]) -{ - FILE *f; - - progname = argv[0]; - if (!(f = fopen("sm_tbl_afsk1200.h", "w"))) - exit(1); - gentbl_banner(f); - gentbl_offscostab(f, 6); - gentbl_costab(f, 6); - gentbl_afsk1200(f); - fclose(f); - if (!(f = fopen("sm_tbl_afsk2666.h", "w"))) - exit(1); - gentbl_banner(f); - gentbl_offscostab(f, 6); - gentbl_costab(f, 6); - gentbl_afsk2666(f); - fclose(f); - if (!(f = fopen("sm_tbl_psk4800.h", "w"))) - exit(1); - gentbl_banner(f); - gentbl_psk4800(f); - gentbl_costab(f, 8); - gentbl_atantab(f); - fclose(f); - if (!(f = fopen("sm_tbl_hapn4800.h", "w"))) - exit(1); - gentbl_banner(f); - gentbl_hapn4800(f); - fclose(f); - if (!(f = fopen("sm_tbl_fsk9600.h", "w"))) - exit(1); - gentbl_banner(f); - gentbl_fsk9600(f); - fclose(f); - if (!(f = fopen("sm_tbl_afsk2400_8.h", "w"))) - exit(1); - gentbl_banner(f); - gentbl_offscostab(f, 6); - gentbl_costab(f, 6); - gentbl_afsk2400(f, 8000000); - fclose(f); - if (!(f = fopen("sm_tbl_afsk2400_7.h", "w"))) - exit(1); - gentbl_banner(f); - gentbl_offscostab(f, 6); - gentbl_costab(f, 6); - gentbl_afsk2400(f, 7372800); - fclose(f); - exit(0); -} - - -/* -------------------------------------------------------------------- */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/net/hamradio/soundmodem/Makefile linux.2.5.47-ac4/drivers/net/hamradio/soundmodem/Makefile --- linux.2.5.47/drivers/net/hamradio/soundmodem/Makefile 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/net/hamradio/soundmodem/Makefile 1970-01-01 01:00:00.000000000 +0100 @@ -1,42 +0,0 @@ -# -# Makefile for the soundmodem device driver. -# - -obj-$(CONFIG_SOUNDMODEM) += soundmodem.o - -soundmodem-y := sm.o -soundmodem-$(CONFIG_SOUNDMODEM_SBC) += sm_sbc.o -soundmodem-$(CONFIG_SOUNDMODEM_WSS) += sm_wss.o -soundmodem-$(CONFIG_SOUNDMODEM_AFSK1200) += sm_afsk1200.o -soundmodem-$(CONFIG_SOUNDMODEM_AFSK2400_7) += sm_afsk2400_7.o -soundmodem-$(CONFIG_SOUNDMODEM_AFSK2400_8) += sm_afsk2400_8.o -soundmodem-$(CONFIG_SOUNDMODEM_AFSK2666) += sm_afsk2666.o -soundmodem-$(CONFIG_SOUNDMODEM_HAPN4800) += sm_hapn4800.o -soundmodem-$(CONFIG_SOUNDMODEM_PSK4800) += sm_psk4800.o -soundmodem-$(CONFIG_SOUNDMODEM_FSK9600) += sm_fsk9600.o -soundmodem-objs := $(soundmodem-y) - -host-progs := gentbl -HOST_LOADLIBES := -lm - -# Files generated that shall be removed upon make clean -clean-files := sm_tbl_afsk1200.h sm_tbl_afsk2400_7.h \ - sm_tbl_afsk2400_8.h sm_tbl_afsk2666.h \ - sm_tbl_psk4800.h sm_tbl_hapn4800.h \ - sm_tbl_fsk9600.h - -include $(TOPDIR)/Rules.make - -# Dependencies on generates files need to be listed explicitly - -$(obj)/sm_afsk1200.o: $(obj)/sm_tbl_afsk1200.h -$(obj)/sm_afsk2400_7.o: $(obj)/sm_tbl_afsk2400_7.h -$(obj)/sm_afsk2400_8.o: $(obj)/sm_tbl_afsk2400_8.h -$(obj)/sm_afsk2666.o: $(obj)/sm_tbl_afsk2666.h -$(obj)/sm_psk4800.o: $(obj)/sm_tbl_psk4800.h -$(obj)/sm_hapn4800.o: $(obj)/sm_tbl_hapn4800.h -$(obj)/sm_fsk9600.o: $(obj)/sm_tbl_fsk9600.h - -$(obj)/sm_tbl_%: $(obj)/gentbl - cd $(obj) && ./gentbl - diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/net/hamradio/soundmodem/sm_afsk1200.c linux.2.5.47-ac4/drivers/net/hamradio/soundmodem/sm_afsk1200.c --- linux.2.5.47/drivers/net/hamradio/soundmodem/sm_afsk1200.c 2002-10-31 14:57:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/net/hamradio/soundmodem/sm_afsk1200.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,272 +0,0 @@ -/*****************************************************************************/ - -/* - * sm_afsk1200.c -- soundcard radio modem driver, 1200 baud AFSK modem - * - * Copyright (C) 1996 Thomas Sailer (sailer@ife.ee.ethz.ch) - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Please note that the GPL allows you to use the driver, NOT the radio. - * In order to use the radio, you need a license from the communications - * authority of your country. - * - */ - -#include "sm.h" -#include "sm_tbl_afsk1200.h" - -/* --------------------------------------------------------------------- */ - -struct demod_state_afsk12 { - unsigned int shreg; - unsigned int bit_pll; - unsigned char last_sample; - unsigned int dcd_shreg; - int dcd_sum0, dcd_sum1, dcd_sum2; - unsigned int dcd_time; - unsigned char last_rxbit; -}; - -struct mod_state_afsk12 { - unsigned int shreg; - unsigned char tx_bit; - unsigned int bit_pll; - unsigned int dds_inc; - unsigned int txphase; -}; - -/* --------------------------------------------------------------------- */ - -static const int dds_inc[2] = { - AFSK12_TX_FREQ_LO*0x10000/AFSK12_SAMPLE_RATE, - AFSK12_TX_FREQ_HI*0x10000/AFSK12_SAMPLE_RATE -}; - -static void modulator_1200_u8(struct sm_state *sm, unsigned char *buf, - unsigned int buflen) -{ - struct mod_state_afsk12 *st = (struct mod_state_afsk12 *)(&sm->m); - - for (; buflen > 0; buflen--) { - if (!((st->txphase++) & 7)) { - if (st->shreg <= 1) - st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; - st->tx_bit = (st->tx_bit ^ (!(st->shreg & 1))) & 1; - st->shreg >>= 1; - } - st->dds_inc = dds_inc[st->tx_bit & 1]; - *buf++ = OFFSCOS(st->bit_pll); - st->bit_pll += st->dds_inc; - } -} - -/* --------------------------------------------------------------------- */ - -static void modulator_1200_s16(struct sm_state *sm, short *buf, unsigned int buflen) -{ - struct mod_state_afsk12 *st = (struct mod_state_afsk12 *)(&sm->m); - - for (; buflen > 0; buflen--) { - if (!((st->txphase++) & 7)) { - if (st->shreg <= 1) - st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; - st->tx_bit = (st->tx_bit ^ (!(st->shreg & 1))) & 1; - st->shreg >>= 1; - } - st->dds_inc = dds_inc[st->tx_bit & 1]; - *buf++ = COS(st->bit_pll); - st->bit_pll += st->dds_inc; - } -} - -/* --------------------------------------------------------------------- */ - -static __inline__ int convolution8_u8(const unsigned char *st, const int *coeff, int csum) -{ - int sum = -0x80 * csum; - - sum += (st[0] * coeff[0]); - sum += (st[-1] * coeff[1]); - sum += (st[-2] * coeff[2]); - sum += (st[-3] * coeff[3]); - sum += (st[-4] * coeff[4]); - sum += (st[-5] * coeff[5]); - sum += (st[-6] * coeff[6]); - sum += (st[-7] * coeff[7]); - - sum >>= 7; - return sum * sum; -} - -static __inline__ int convolution8_s16(const short *st, const int *coeff, int csum) -{ - int sum = 0; - - sum += (st[0] * coeff[0]); - sum += (st[-1] * coeff[1]); - sum += (st[-2] * coeff[2]); - sum += (st[-3] * coeff[3]); - sum += (st[-4] * coeff[4]); - sum += (st[-5] * coeff[5]); - sum += (st[-6] * coeff[6]); - sum += (st[-7] * coeff[7]); - - sum >>= 15; - return sum * sum; -} - -static __inline__ int do_filter_1200_u8(const unsigned char *buf) -{ - int sum = convolution8_u8(buf, afsk12_tx_lo_i, SUM_AFSK12_TX_LO_I); - sum += convolution8_u8(buf, afsk12_tx_lo_q, SUM_AFSK12_TX_LO_Q); - sum -= convolution8_u8(buf, afsk12_tx_hi_i, SUM_AFSK12_TX_HI_I); - sum -= convolution8_u8(buf, afsk12_tx_hi_q, SUM_AFSK12_TX_HI_Q); - return sum; -} - -static __inline__ int do_filter_1200_s16(const short *buf) -{ - int sum = convolution8_s16(buf, afsk12_tx_lo_i, SUM_AFSK12_TX_LO_I); - sum += convolution8_s16(buf, afsk12_tx_lo_q, SUM_AFSK12_TX_LO_Q); - sum -= convolution8_s16(buf, afsk12_tx_hi_i, SUM_AFSK12_TX_HI_I); - sum -= convolution8_s16(buf, afsk12_tx_hi_q, SUM_AFSK12_TX_HI_Q); - return sum; -} - -/* --------------------------------------------------------------------- */ - -static const int pll_corr[2] = { -0x1000, 0x1000 }; - -static void demodulator_1200_u8(struct sm_state *sm, const unsigned char *buf, unsigned int buflen) -{ - struct demod_state_afsk12 *st = (struct demod_state_afsk12 *)(&sm->d); - int j; - int sum; - unsigned char newsample; - - for (; buflen > 0; buflen--, buf++) { - sum = do_filter_1200_u8(buf); - st->dcd_shreg <<= 1; - st->bit_pll += 0x2000; - newsample = (sum > 0); - if (st->last_sample ^ newsample) { - st->last_sample = newsample; - st->dcd_shreg |= 1; - st->bit_pll += pll_corr - [st->bit_pll < 0x9000]; - j = 4 * hweight8(st->dcd_shreg & 0x38) - - hweight16(st->dcd_shreg & 0x7c0); - st->dcd_sum0 += j; - } - hdlcdrv_channelbit(&sm->hdrv, st->last_sample); - if ((--st->dcd_time) <= 0) { - hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + - st->dcd_sum1 + - st->dcd_sum2) < 0); - st->dcd_sum2 = st->dcd_sum1; - st->dcd_sum1 = st->dcd_sum0; - st->dcd_sum0 = 2; /* slight bias */ - st->dcd_time = 120; - } - if (st->bit_pll >= 0x10000) { - st->bit_pll &= 0xffff; - st->shreg >>= 1; - st->shreg |= (!(st->last_rxbit ^ - st->last_sample)) << 16; - st->last_rxbit = st->last_sample; - diag_trigger(sm); - if (st->shreg & 1) { - hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1); - st->shreg = 0x10000; - } - } - diag_add(sm, (((int)*buf)-0x80) << 8, sum); - } -} - -/* --------------------------------------------------------------------- */ - -static void demodulator_1200_s16(struct sm_state *sm, const short *buf, unsigned int buflen) -{ - struct demod_state_afsk12 *st = (struct demod_state_afsk12 *)(&sm->d); - int j; - int sum; - unsigned char newsample; - - for (; buflen > 0; buflen--, buf++) { - sum = do_filter_1200_s16(buf); - st->dcd_shreg <<= 1; - st->bit_pll += 0x2000; - newsample = (sum > 0); - if (st->last_sample ^ newsample) { - st->last_sample = newsample; - st->dcd_shreg |= 1; - st->bit_pll += pll_corr - [st->bit_pll < 0x9000]; - j = 4 * hweight8(st->dcd_shreg & 0x38) - - hweight16(st->dcd_shreg & 0x7c0); - st->dcd_sum0 += j; - } - hdlcdrv_channelbit(&sm->hdrv, st->last_sample); - if ((--st->dcd_time) <= 0) { - hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + - st->dcd_sum1 + - st->dcd_sum2) < 0); - st->dcd_sum2 = st->dcd_sum1; - st->dcd_sum1 = st->dcd_sum0; - st->dcd_sum0 = 2; /* slight bias */ - st->dcd_time = 120; - } - if (st->bit_pll >= 0x10000) { - st->bit_pll &= 0xffff; - st->shreg >>= 1; - st->shreg |= (!(st->last_rxbit ^ - st->last_sample)) << 16; - st->last_rxbit = st->last_sample; - diag_trigger(sm); - if (st->shreg & 1) { - hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1); - st->shreg = 0x10000; - } - } - diag_add(sm, *buf, sum); - } -} - -/* --------------------------------------------------------------------- */ - -static void demod_init_1200(struct sm_state *sm) -{ - struct demod_state_afsk12 *st = (struct demod_state_afsk12 *)(&sm->d); - - st->dcd_time = 120; - st->dcd_sum0 = 2; -} - -/* --------------------------------------------------------------------- */ - -const struct modem_tx_info sm_afsk1200_tx = { - "afsk1200", sizeof(struct mod_state_afsk12), - AFSK12_SAMPLE_RATE, 1200, modulator_1200_u8, modulator_1200_s16, NULL -}; - -const struct modem_rx_info sm_afsk1200_rx = { - "afsk1200", sizeof(struct demod_state_afsk12), - AFSK12_SAMPLE_RATE, 1200, 8, AFSK12_SAMPLE_RATE/1200, - demodulator_1200_u8, demodulator_1200_s16, demod_init_1200 -}; - -/* --------------------------------------------------------------------- */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/net/hamradio/soundmodem/sm_afsk2400_7.c linux.2.5.47-ac4/drivers/net/hamradio/soundmodem/sm_afsk2400_7.c --- linux.2.5.47/drivers/net/hamradio/soundmodem/sm_afsk2400_7.c 2002-10-31 14:57:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/net/hamradio/soundmodem/sm_afsk2400_7.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,296 +0,0 @@ -/*****************************************************************************/ - -/* - * sm_afsk2400_7.c -- soundcard radio modem driver, 2400 baud AFSK modem - * - * Copyright (C) 1996 Thomas Sailer (sailer@ife.ee.ethz.ch) - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Please note that the GPL allows you to use the driver, NOT the radio. - * In order to use the radio, you need a license from the communications - * authority of your country. - * - */ - -/* - * This driver is intended to be compatible with TCM3105 modems - * overclocked to 7.3728MHz. The mark and space frequencies therefore - * lie at 3658 and 1996 Hz. - * Note that I do _not_ recommend the building of such links, I provide - * this only for the users who live in the coverage area of such - * a "legacy" link. - */ - -#include "sm.h" -#include "sm_tbl_afsk2400_7.h" - -/* --------------------------------------------------------------------- */ - -struct demod_state_afsk24 { - unsigned int shreg; - unsigned int bit_pll; - unsigned char last_sample; - unsigned int dcd_shreg; - int dcd_sum0, dcd_sum1, dcd_sum2; - unsigned int dcd_time; - unsigned char last_rxbit; -}; - -struct mod_state_afsk24 { - unsigned int shreg; - unsigned char tx_bit; - unsigned int bit_pll; - unsigned int tx_seq; - unsigned int phinc; -}; - -/* --------------------------------------------------------------------- */ - -static const int dds_inc[2] = { AFSK24_TX_FREQ_LO*0x10000/AFSK24_SAMPLERATE, - AFSK24_TX_FREQ_HI*0x10000/AFSK24_SAMPLERATE }; - -static void modulator_2400_u8(struct sm_state *sm, unsigned char *buf, unsigned int buflen) -{ - struct mod_state_afsk24 *st = (struct mod_state_afsk24 *)(&sm->m); - - for (; buflen > 0; buflen--, buf++) { - if (st->tx_seq < 0x5555) { - if (st->shreg <= 1) - st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; - st->tx_bit = (st->tx_bit ^ (!(st->shreg & 1))) & 1; - st->shreg >>= 1; - st->phinc = dds_inc[st->tx_bit & 1]; - } - st->tx_seq += 0x5555; - st->tx_seq &= 0xffff; - *buf = OFFSCOS(st->bit_pll); - st->bit_pll += st->phinc; - } -} - -/* --------------------------------------------------------------------- */ - -static void modulator_2400_s16(struct sm_state *sm, short *buf, unsigned int buflen) -{ - struct mod_state_afsk24 *st = (struct mod_state_afsk24 *)(&sm->m); - - for (; buflen > 0; buflen--, buf++) { - if (st->tx_seq < 0x5555) { - if (st->shreg <= 1) - st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; - st->tx_bit = (st->tx_bit ^ (!(st->shreg & 1))) & 1; - st->shreg >>= 1; - st->phinc = dds_inc[st->tx_bit & 1]; - } - st->tx_seq += 0x5555; - st->tx_seq &= 0xffff; - *buf = COS(st->bit_pll); - st->bit_pll += st->phinc; - } -} - -/* --------------------------------------------------------------------- */ - -static __inline__ int convolution14_u8(const unsigned char *st, const int *coeff, int csum) -{ - int sum = -0x80 * csum; - - sum += (st[0] * coeff[0]); - sum += (st[-1] * coeff[1]); - sum += (st[-2] * coeff[2]); - sum += (st[-3] * coeff[3]); - sum += (st[-4] * coeff[4]); - sum += (st[-5] * coeff[5]); - sum += (st[-6] * coeff[6]); - sum += (st[-7] * coeff[7]); - sum += (st[-8] * coeff[8]); - sum += (st[-9] * coeff[9]); - sum += (st[-10] * coeff[10]); - sum += (st[-11] * coeff[11]); - sum += (st[-12] * coeff[12]); - sum += (st[-13] * coeff[13]); - - sum >>= 7; - return sum * sum; -} - -static __inline__ int convolution14_s16(const short *st, const int *coeff, int csum) -{ - int sum = 0; - - sum += (st[0] * coeff[0]); - sum += (st[-1] * coeff[1]); - sum += (st[-2] * coeff[2]); - sum += (st[-3] * coeff[3]); - sum += (st[-4] * coeff[4]); - sum += (st[-5] * coeff[5]); - sum += (st[-6] * coeff[6]); - sum += (st[-7] * coeff[7]); - sum += (st[-8] * coeff[8]); - sum += (st[-9] * coeff[9]); - sum += (st[-10] * coeff[10]); - sum += (st[-11] * coeff[11]); - sum += (st[-12] * coeff[12]); - sum += (st[-13] * coeff[13]); - - sum >>= 15; - return sum * sum; -} - -static __inline__ int do_filter_2400_u8(const unsigned char *buf) -{ - int sum = convolution14_u8(buf, afsk24_tx_lo_i, SUM_AFSK24_TX_LO_I); - sum += convolution14_u8(buf, afsk24_tx_lo_q, SUM_AFSK24_TX_LO_Q); - sum -= convolution14_u8(buf, afsk24_tx_hi_i, SUM_AFSK24_TX_HI_I); - sum -= convolution14_u8(buf, afsk24_tx_hi_q, SUM_AFSK24_TX_HI_Q); - return sum; -} - -static __inline__ int do_filter_2400_s16(const short *buf) -{ - int sum = convolution14_s16(buf, afsk24_tx_lo_i, SUM_AFSK24_TX_LO_I); - sum += convolution14_s16(buf, afsk24_tx_lo_q, SUM_AFSK24_TX_LO_Q); - sum -= convolution14_s16(buf, afsk24_tx_hi_i, SUM_AFSK24_TX_HI_I); - sum -= convolution14_s16(buf, afsk24_tx_hi_q, SUM_AFSK24_TX_HI_Q); - return sum; -} - -/* --------------------------------------------------------------------- */ - -static void demodulator_2400_u8(struct sm_state *sm, const unsigned char *buf, unsigned int buflen) -{ - struct demod_state_afsk24 *st = (struct demod_state_afsk24 *)(&sm->d); - int j; - int sum; - unsigned char newsample; - - for (; buflen > 0; buflen--, buf++) { - sum = do_filter_2400_u8(buf); - st->dcd_shreg <<= 1; - st->bit_pll += AFSK24_BITPLL_INC; - newsample = (sum > 0); - if (st->last_sample ^ newsample) { - st->last_sample = newsample; - st->dcd_shreg |= 1; - if (st->bit_pll < (0x8000+AFSK24_BITPLL_INC/2)) - st->bit_pll += AFSK24_BITPLL_INC/2; - else - st->bit_pll -= AFSK24_BITPLL_INC/2; - j = /* 2 * */ hweight8(st->dcd_shreg & 0x1c) - - hweight16(st->dcd_shreg & 0x1e0); - st->dcd_sum0 += j; - } - hdlcdrv_channelbit(&sm->hdrv, st->last_sample); - if ((--st->dcd_time) <= 0) { - hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + - st->dcd_sum1 + - st->dcd_sum2) < 0); - st->dcd_sum2 = st->dcd_sum1; - st->dcd_sum1 = st->dcd_sum0; - st->dcd_sum0 = 2; /* slight bias */ - st->dcd_time = 120; - } - if (st->bit_pll >= 0x10000) { - st->bit_pll &= 0xffff; - st->shreg >>= 1; - st->shreg |= (!(st->last_rxbit ^ - st->last_sample)) << 16; - st->last_rxbit = st->last_sample; - diag_trigger(sm); - if (st->shreg & 1) { - hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1); - st->shreg = 0x10000; - } - } - diag_add(sm, (((int)*buf)-0x80) << 8, sum); - } -} - -/* --------------------------------------------------------------------- */ - -static void demodulator_2400_s16(struct sm_state *sm, const short *buf, unsigned int buflen) -{ - struct demod_state_afsk24 *st = (struct demod_state_afsk24 *)(&sm->d); - int j; - int sum; - unsigned char newsample; - - for (; buflen > 0; buflen--, buf++) { - sum = do_filter_2400_s16(buf); - st->dcd_shreg <<= 1; - st->bit_pll += AFSK24_BITPLL_INC; - newsample = (sum > 0); - if (st->last_sample ^ newsample) { - st->last_sample = newsample; - st->dcd_shreg |= 1; - if (st->bit_pll < (0x8000+AFSK24_BITPLL_INC/2)) - st->bit_pll += AFSK24_BITPLL_INC/2; - else - st->bit_pll -= AFSK24_BITPLL_INC/2; - j = /* 2 * */ hweight8(st->dcd_shreg & 0x1c) - - hweight16(st->dcd_shreg & 0x1e0); - st->dcd_sum0 += j; - } - hdlcdrv_channelbit(&sm->hdrv, st->last_sample); - if ((--st->dcd_time) <= 0) { - hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + - st->dcd_sum1 + - st->dcd_sum2) < 0); - st->dcd_sum2 = st->dcd_sum1; - st->dcd_sum1 = st->dcd_sum0; - st->dcd_sum0 = 2; /* slight bias */ - st->dcd_time = 120; - } - if (st->bit_pll >= 0x10000) { - st->bit_pll &= 0xffff; - st->shreg >>= 1; - st->shreg |= (!(st->last_rxbit ^ - st->last_sample)) << 16; - st->last_rxbit = st->last_sample; - diag_trigger(sm); - if (st->shreg & 1) { - hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1); - st->shreg = 0x10000; - } - } - diag_add(sm, *buf, sum); - } -} - -/* --------------------------------------------------------------------- */ - -static void demod_init_2400(struct sm_state *sm) -{ - struct demod_state_afsk24 *st = (struct demod_state_afsk24 *)(&sm->d); - - st->dcd_time = 120; - st->dcd_sum0 = 2; -} - -/* --------------------------------------------------------------------- */ - -const struct modem_tx_info sm_afsk2400_7_tx = { - "afsk2400_7", sizeof(struct mod_state_afsk24), AFSK24_SAMPLERATE, 2400, - modulator_2400_u8, modulator_2400_s16, NULL -}; - -const struct modem_rx_info sm_afsk2400_7_rx = { - "afsk2400_7", sizeof(struct demod_state_afsk24), - AFSK24_SAMPLERATE, 2400, 14, AFSK24_SAMPLERATE/2400, - demodulator_2400_u8, demodulator_2400_s16, demod_init_2400 -}; - -/* --------------------------------------------------------------------- */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/net/hamradio/soundmodem/sm_afsk2400_8.c linux.2.5.47-ac4/drivers/net/hamradio/soundmodem/sm_afsk2400_8.c --- linux.2.5.47/drivers/net/hamradio/soundmodem/sm_afsk2400_8.c 2002-10-31 14:57:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/net/hamradio/soundmodem/sm_afsk2400_8.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,296 +0,0 @@ -/*****************************************************************************/ - -/* - * sm_afsk2400_8.c -- soundcard radio modem driver, 2400 baud AFSK modem - * - * Copyright (C) 1996 Thomas Sailer (sailer@ife.ee.ethz.ch) - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Please note that the GPL allows you to use the driver, NOT the radio. - * In order to use the radio, you need a license from the communications - * authority of your country. - * - */ - -/* - * This driver is intended to be compatible with TCM3105 modems - * overclocked to 8MHz. The mark and space frequencies therefore - * lie at 3970 and 2165 Hz. - * Note that I do _not_ recommend the building of such links, I provide - * this only for the users who live in the coverage area of such - * a "legacy" link. - */ - -#include "sm.h" -#include "sm_tbl_afsk2400_8.h" - -/* --------------------------------------------------------------------- */ - -struct demod_state_afsk24 { - unsigned int shreg; - unsigned int bit_pll; - unsigned char last_sample; - unsigned int dcd_shreg; - int dcd_sum0, dcd_sum1, dcd_sum2; - unsigned int dcd_time; - unsigned char last_rxbit; -}; - -struct mod_state_afsk24 { - unsigned int shreg; - unsigned char tx_bit; - unsigned int bit_pll; - unsigned int tx_seq; - unsigned int phinc; -}; - -/* --------------------------------------------------------------------- */ - -static const int dds_inc[2] = { AFSK24_TX_FREQ_LO*0x10000/AFSK24_SAMPLERATE, - AFSK24_TX_FREQ_HI*0x10000/AFSK24_SAMPLERATE }; - -static void modulator_2400_u8(struct sm_state *sm, unsigned char *buf, unsigned int buflen) -{ - struct mod_state_afsk24 *st = (struct mod_state_afsk24 *)(&sm->m); - - for (; buflen > 0; buflen--, buf++) { - if (st->tx_seq < 0x5555) { - if (st->shreg <= 1) - st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; - st->tx_bit = (st->tx_bit ^ (!(st->shreg & 1))) & 1; - st->shreg >>= 1; - st->phinc = dds_inc[st->tx_bit & 1]; - } - st->tx_seq += 0x5555; - st->tx_seq &= 0xffff; - *buf = OFFSCOS(st->bit_pll); - st->bit_pll += st->phinc; - } -} - -/* --------------------------------------------------------------------- */ - -static void modulator_2400_s16(struct sm_state *sm, short *buf, unsigned int buflen) -{ - struct mod_state_afsk24 *st = (struct mod_state_afsk24 *)(&sm->m); - - for (; buflen > 0; buflen--, buf++) { - if (st->tx_seq < 0x5555) { - if (st->shreg <= 1) - st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; - st->tx_bit = (st->tx_bit ^ (!(st->shreg & 1))) & 1; - st->shreg >>= 1; - st->phinc = dds_inc[st->tx_bit & 1]; - } - st->tx_seq += 0x5555; - st->tx_seq &= 0xffff; - *buf = COS(st->bit_pll); - st->bit_pll += st->phinc; - } -} - -/* --------------------------------------------------------------------- */ - -static __inline__ int convolution14_u8(const unsigned char *st, const int *coeff, int csum) -{ - int sum = -0x80 * csum; - - sum += (st[0] * coeff[0]); - sum += (st[-1] * coeff[1]); - sum += (st[-2] * coeff[2]); - sum += (st[-3] * coeff[3]); - sum += (st[-4] * coeff[4]); - sum += (st[-5] * coeff[5]); - sum += (st[-6] * coeff[6]); - sum += (st[-7] * coeff[7]); - sum += (st[-8] * coeff[8]); - sum += (st[-9] * coeff[9]); - sum += (st[-10] * coeff[10]); - sum += (st[-11] * coeff[11]); - sum += (st[-12] * coeff[12]); - sum += (st[-13] * coeff[13]); - - sum >>= 7; - return sum * sum; -} - -static __inline__ int convolution14_s16(const short *st, const int *coeff, int csum) -{ - int sum = 0; - - sum += (st[0] * coeff[0]); - sum += (st[-1] * coeff[1]); - sum += (st[-2] * coeff[2]); - sum += (st[-3] * coeff[3]); - sum += (st[-4] * coeff[4]); - sum += (st[-5] * coeff[5]); - sum += (st[-6] * coeff[6]); - sum += (st[-7] * coeff[7]); - sum += (st[-8] * coeff[8]); - sum += (st[-9] * coeff[9]); - sum += (st[-10] * coeff[10]); - sum += (st[-11] * coeff[11]); - sum += (st[-12] * coeff[12]); - sum += (st[-13] * coeff[13]); - - sum >>= 15; - return sum * sum; -} - -static __inline__ int do_filter_2400_u8(const unsigned char *buf) -{ - int sum = convolution14_u8(buf, afsk24_tx_lo_i, SUM_AFSK24_TX_LO_I); - sum += convolution14_u8(buf, afsk24_tx_lo_q, SUM_AFSK24_TX_LO_Q); - sum -= convolution14_u8(buf, afsk24_tx_hi_i, SUM_AFSK24_TX_HI_I); - sum -= convolution14_u8(buf, afsk24_tx_hi_q, SUM_AFSK24_TX_HI_Q); - return sum; -} - -static __inline__ int do_filter_2400_s16(const short *buf) -{ - int sum = convolution14_s16(buf, afsk24_tx_lo_i, SUM_AFSK24_TX_LO_I); - sum += convolution14_s16(buf, afsk24_tx_lo_q, SUM_AFSK24_TX_LO_Q); - sum -= convolution14_s16(buf, afsk24_tx_hi_i, SUM_AFSK24_TX_HI_I); - sum -= convolution14_s16(buf, afsk24_tx_hi_q, SUM_AFSK24_TX_HI_Q); - return sum; -} - -/* --------------------------------------------------------------------- */ - -static void demodulator_2400_u8(struct sm_state *sm, const unsigned char *buf, unsigned int buflen) -{ - struct demod_state_afsk24 *st = (struct demod_state_afsk24 *)(&sm->d); - int j; - int sum; - unsigned char newsample; - - for (; buflen > 0; buflen--, buf++) { - sum = do_filter_2400_u8(buf); - st->dcd_shreg <<= 1; - st->bit_pll += AFSK24_BITPLL_INC; - newsample = (sum > 0); - if (st->last_sample ^ newsample) { - st->last_sample = newsample; - st->dcd_shreg |= 1; - if (st->bit_pll < (0x8000+AFSK24_BITPLL_INC/2)) - st->bit_pll += AFSK24_BITPLL_INC/2; - else - st->bit_pll -= AFSK24_BITPLL_INC/2; - j = /* 2 * */ hweight8(st->dcd_shreg & 0x1c) - - hweight16(st->dcd_shreg & 0x1e0); - st->dcd_sum0 += j; - } - hdlcdrv_channelbit(&sm->hdrv, st->last_sample); - if ((--st->dcd_time) <= 0) { - hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + - st->dcd_sum1 + - st->dcd_sum2) < 0); - st->dcd_sum2 = st->dcd_sum1; - st->dcd_sum1 = st->dcd_sum0; - st->dcd_sum0 = 2; /* slight bias */ - st->dcd_time = 120; - } - if (st->bit_pll >= 0x10000) { - st->bit_pll &= 0xffff; - st->shreg >>= 1; - st->shreg |= (!(st->last_rxbit ^ - st->last_sample)) << 16; - st->last_rxbit = st->last_sample; - diag_trigger(sm); - if (st->shreg & 1) { - hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1); - st->shreg = 0x10000; - } - } - diag_add(sm, (((int)*buf)-0x80) << 8, sum); - } -} - -/* --------------------------------------------------------------------- */ - -static void demodulator_2400_s16(struct sm_state *sm, const short *buf, unsigned int buflen) -{ - struct demod_state_afsk24 *st = (struct demod_state_afsk24 *)(&sm->d); - int j; - int sum; - unsigned char newsample; - - for (; buflen > 0; buflen--, buf++) { - sum = do_filter_2400_s16(buf); - st->dcd_shreg <<= 1; - st->bit_pll += AFSK24_BITPLL_INC; - newsample = (sum > 0); - if (st->last_sample ^ newsample) { - st->last_sample = newsample; - st->dcd_shreg |= 1; - if (st->bit_pll < (0x8000+AFSK24_BITPLL_INC/2)) - st->bit_pll += AFSK24_BITPLL_INC/2; - else - st->bit_pll -= AFSK24_BITPLL_INC/2; - j = /* 2 * */ hweight8(st->dcd_shreg & 0x1c) - - hweight16(st->dcd_shreg & 0x1e0); - st->dcd_sum0 += j; - } - hdlcdrv_channelbit(&sm->hdrv, st->last_sample); - if ((--st->dcd_time) <= 0) { - hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + - st->dcd_sum1 + - st->dcd_sum2) < 0); - st->dcd_sum2 = st->dcd_sum1; - st->dcd_sum1 = st->dcd_sum0; - st->dcd_sum0 = 2; /* slight bias */ - st->dcd_time = 120; - } - if (st->bit_pll >= 0x10000) { - st->bit_pll &= 0xffff; - st->shreg >>= 1; - st->shreg |= (!(st->last_rxbit ^ - st->last_sample)) << 16; - st->last_rxbit = st->last_sample; - diag_trigger(sm); - if (st->shreg & 1) { - hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1); - st->shreg = 0x10000; - } - } - diag_add(sm, *buf, sum); - } -} - -/* --------------------------------------------------------------------- */ - -static void demod_init_2400(struct sm_state *sm) -{ - struct demod_state_afsk24 *st = (struct demod_state_afsk24 *)(&sm->d); - - st->dcd_time = 120; - st->dcd_sum0 = 2; -} - -/* --------------------------------------------------------------------- */ - -const struct modem_tx_info sm_afsk2400_8_tx = { - "afsk2400_8", sizeof(struct mod_state_afsk24), AFSK24_SAMPLERATE, 2400, - modulator_2400_u8, modulator_2400_s16, NULL -}; - -const struct modem_rx_info sm_afsk2400_8_rx = { - "afsk2400_8", sizeof(struct demod_state_afsk24), - AFSK24_SAMPLERATE, 2400, 14, AFSK24_SAMPLERATE/2400, - demodulator_2400_u8, demodulator_2400_s16, demod_init_2400 -}; - -/* --------------------------------------------------------------------- */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/net/hamradio/soundmodem/sm_afsk2666.c linux.2.5.47-ac4/drivers/net/hamradio/soundmodem/sm_afsk2666.c --- linux.2.5.47/drivers/net/hamradio/soundmodem/sm_afsk2666.c 2002-10-31 14:57:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/net/hamradio/soundmodem/sm_afsk2666.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,356 +0,0 @@ -/*****************************************************************************/ - -/* - * sm_afsk2666.c -- soundcard radio modem driver, 2666 baud AFSK modem - * - * Copyright (C) 1997 Thomas Sailer (sailer@ife.ee.ethz.ch) - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Please note that the GPL allows you to use the driver, NOT the radio. - * In order to use the radio, you need a license from the communications - * authority of your country. - * - */ - -#include "sm.h" -#include "sm_tbl_afsk2666.h" - -/* --------------------------------------------------------------------- */ - -struct demod_state_afsk26 { - unsigned int shreg; - unsigned long descram; - int dem_sum[8]; - int dem_sum_mean; - int dem_cnt; - unsigned int bit_pll; - unsigned char last_sample; - unsigned int dcd_shreg; - int dcd_sum0, dcd_sum1, dcd_sum2; - unsigned int dcd_time; -}; - -struct mod_state_afsk26 { - unsigned int shreg; - unsigned long scram; - unsigned int bit_pll; - unsigned int phinc; - unsigned int tx_seq; -}; - -/* --------------------------------------------------------------------- */ - -#define DESCRAM_TAP1 0x20000 -#define DESCRAM_TAP2 0x01000 -#define DESCRAM_TAP3 0x00001 - -#define DESCRAM_TAPSH1 17 -#define DESCRAM_TAPSH2 12 -#define DESCRAM_TAPSH3 0 - -#define SCRAM_TAP1 0x20000 /* X^17 */ -#define SCRAM_TAPN 0x00021 /* X^0+X^5 */ - -/* --------------------------------------------------------------------- */ - -static void modulator_2666_u8(struct sm_state *sm, unsigned char *buf, unsigned int buflen) -{ - struct mod_state_afsk26 *st = (struct mod_state_afsk26 *)(&sm->m); - - for (; buflen > 0; buflen--, buf++) { - if (!st->tx_seq++) { - if (st->shreg <= 1) - st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; - st->scram = ((st->scram << 1) | (st->scram & 1)); - st->scram ^= (!(st->shreg & 1)); - st->shreg >>= 1; - if (st->scram & (SCRAM_TAP1 << 1)) - st->scram ^= SCRAM_TAPN << 1; - st->phinc = afsk26_carfreq[!(st->scram & (SCRAM_TAP1 << 2))]; - } - if (st->tx_seq >= 6) - st->tx_seq = 0; - *buf = OFFSCOS(st->bit_pll); - st->bit_pll += st->phinc; - } -} - -/* --------------------------------------------------------------------- */ - -static void modulator_2666_s16(struct sm_state *sm, short *buf, unsigned int buflen) -{ - struct mod_state_afsk26 *st = (struct mod_state_afsk26 *)(&sm->m); - - for (; buflen > 0; buflen--, buf++) { - if (!st->tx_seq++) { - if (st->shreg <= 1) - st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; - st->scram = ((st->scram << 1) | (st->scram & 1)); - st->scram ^= (!(st->shreg & 1)); - st->shreg >>= 1; - if (st->scram & (SCRAM_TAP1 << 1)) - st->scram ^= SCRAM_TAPN << 1; - st->phinc = afsk26_carfreq[!(st->scram & (SCRAM_TAP1 << 2))]; - } - if (st->tx_seq >= 6) - st->tx_seq = 0; - *buf = COS(st->bit_pll); - st->bit_pll += st->phinc; - } -} - -/* --------------------------------------------------------------------- */ - -static __inline__ int convolution12_u8(const unsigned char *st, const int *coeff, int csum) -{ - int sum = -0x80 * csum; - - sum += (st[0] * coeff[0]); - sum += (st[-1] * coeff[1]); - sum += (st[-2] * coeff[2]); - sum += (st[-3] * coeff[3]); - sum += (st[-4] * coeff[4]); - sum += (st[-5] * coeff[5]); - sum += (st[-6] * coeff[6]); - sum += (st[-7] * coeff[7]); - sum += (st[-8] * coeff[8]); - sum += (st[-9] * coeff[9]); - sum += (st[-10] * coeff[10]); - sum += (st[-11] * coeff[11]); - - return sum; -} - -static __inline__ int convolution12_s16(const short *st, const int *coeff, int csum) -{ - int sum = 0; - - sum += (st[0] * coeff[0]); - sum += (st[-1] * coeff[1]); - sum += (st[-2] * coeff[2]); - sum += (st[-3] * coeff[3]); - sum += (st[-4] * coeff[4]); - sum += (st[-5] * coeff[5]); - sum += (st[-6] * coeff[6]); - sum += (st[-7] * coeff[7]); - sum += (st[-8] * coeff[8]); - sum += (st[-9] * coeff[9]); - sum += (st[-10] * coeff[10]); - sum += (st[-11] * coeff[11]); - - sum >>= 8; - return sum; -} - -/* ---------------------------------------------------------------------- */ - -#if 0 -static int binexp(unsigned int i) -{ - int ret = 31; - - if (!i) - return 0; - if (i < 0x10000LU) { - i <<= 16; - ret -= 16; - } - if (i < 0x1000000LU) { - i <<= 8; - ret -= 8; - } - if (i < 0x10000000LU) { - i <<= 4; - ret -= 4; - } - if (i < 0x40000000LU) { - i <<= 2; - ret -= 2; - } - if (i < 0x80000000LU) - ret -= 1; - return ret; -} - -static const sqrt_tab[16] = { - 00000, 16384, 23170, 28378, 32768, 36636, 40132, 43348, - 46341, 49152, 51811, 54340, 56756, 59073, 61303, 63455 -}; - - -static unsigned int int_sqrt_approx(unsigned int i) -{ - unsigned int j; - - if (i < 16) - return sqrt_tab[i] >> 14; - j = binexp(i) >> 1; - i >>= (j * 2 - 2); - return (sqrt_tab[i & 0xf] << j) >> 15; -} -#endif - -/* --------------------------------------------------------------------- */ - -extern unsigned int est_pwr(int i, int q) -{ - unsigned int ui = abs(i); - unsigned int uq = abs(q); - - if (uq > ui) { - unsigned int tmp; - tmp = ui; - ui = uq; - uq = tmp; - } - if (uq > (ui >> 1)) - return 7*(ui>>3) + 9*(uq>>4); - else - return ui + (uq>>2); -} - -/* --------------------------------------------------------------------- */ - -static void demod_one_sample(struct sm_state *sm, struct demod_state_afsk26 *st, int curval, - int loi, int loq, int hii, int hiq) -{ - static const int pll_corr[2] = { -0xa00, 0xa00 }; - unsigned char curbit; - unsigned int descx; - int val; - - /* - * estimate power - */ - val = est_pwr(hii, hiq) - est_pwr(loi, loq); - /* - * estimate center value - */ - st->dem_sum[0] += val >> 8; - if ((++st->dem_cnt) >= 256) { - st->dem_cnt = 0; - st->dem_sum_mean = (st->dem_sum[0]+st->dem_sum[1]+ - st->dem_sum[2]+st->dem_sum[3]+ - st->dem_sum[4]+st->dem_sum[5]+ - st->dem_sum[6]+st->dem_sum[7]) >> 3; - memmove(st->dem_sum+1, st->dem_sum, - sizeof(st->dem_sum)-sizeof(st->dem_sum[0])); - st->dem_sum[0] = 0; - } - /* - * decision and bit clock regen - */ - val -= st->dem_sum_mean; - diag_add(sm, curval, val); - - st->dcd_shreg <<= 1; - st->bit_pll += 0x1555; - curbit = (val > 0); - if (st->last_sample ^ curbit) { - st->dcd_shreg |= 1; - st->bit_pll += pll_corr[st->bit_pll < (0x8000+0x1555)]; - st->dcd_sum0 += 4*hweight8(st->dcd_shreg & 0x1e) - - hweight16(st->dcd_shreg & 0xfe00); - } - st->last_sample = curbit; - hdlcdrv_channelbit(&sm->hdrv, curbit); - if ((--st->dcd_time) <= 0) { - hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + st->dcd_sum1 + - st->dcd_sum2) < 0); - st->dcd_sum2 = st->dcd_sum1; - st->dcd_sum1 = st->dcd_sum0; - st->dcd_sum0 = 2; /* slight bias */ - st->dcd_time = 400; - } - if (st->bit_pll >= 0x10000) { - st->bit_pll &= 0xffffu; - st->descram = (st->descram << 1) | curbit; - descx = st->descram ^ (st->descram >> 1); - descx ^= ((descx >> DESCRAM_TAPSH1) ^ - (descx >> DESCRAM_TAPSH2)); - st->shreg >>= 1; - st->shreg |= (!(descx & 1)) << 16; - if (st->shreg & 1) { - hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1); - st->shreg = 0x10000; - } - diag_trigger(sm); - } -} - -/* --------------------------------------------------------------------- */ - -static void demodulator_2666_u8(struct sm_state *sm, const unsigned char *buf, unsigned int buflen) -{ - struct demod_state_afsk26 *st = (struct demod_state_afsk26 *)(&sm->d); - - for (; buflen > 0; buflen--, buf++) { - demod_one_sample(sm, st, (*buf-0x80)<<8, - convolution12_u8(buf, afsk26_dem_tables[0][0].i, AFSK26_DEM_SUM_I_0_0), - convolution12_u8(buf, afsk26_dem_tables[0][0].q, AFSK26_DEM_SUM_Q_0_0), - convolution12_u8(buf, afsk26_dem_tables[0][1].i, AFSK26_DEM_SUM_I_0_1), - convolution12_u8(buf, afsk26_dem_tables[0][1].q, AFSK26_DEM_SUM_Q_0_1)); - demod_one_sample(sm, st, (*buf-0x80)<<8, - convolution12_u8(buf, afsk26_dem_tables[1][0].i, AFSK26_DEM_SUM_I_1_0), - convolution12_u8(buf, afsk26_dem_tables[1][0].q, AFSK26_DEM_SUM_Q_1_0), - convolution12_u8(buf, afsk26_dem_tables[1][1].i, AFSK26_DEM_SUM_I_1_1), - convolution12_u8(buf, afsk26_dem_tables[1][1].q, AFSK26_DEM_SUM_Q_1_1)); - } -} - -/* --------------------------------------------------------------------- */ - -static void demodulator_2666_s16(struct sm_state *sm, const short *buf, unsigned int buflen) -{ - struct demod_state_afsk26 *st = (struct demod_state_afsk26 *)(&sm->d); - - for (; buflen > 0; buflen--, buf++) { - demod_one_sample(sm, st, *buf, - convolution12_s16(buf, afsk26_dem_tables[0][0].i, AFSK26_DEM_SUM_I_0_0), - convolution12_s16(buf, afsk26_dem_tables[0][0].q, AFSK26_DEM_SUM_Q_0_0), - convolution12_s16(buf, afsk26_dem_tables[0][1].i, AFSK26_DEM_SUM_I_0_1), - convolution12_s16(buf, afsk26_dem_tables[0][1].q, AFSK26_DEM_SUM_Q_0_1)); - demod_one_sample(sm, st, *buf, - convolution12_s16(buf, afsk26_dem_tables[1][0].i, AFSK26_DEM_SUM_I_1_0), - convolution12_s16(buf, afsk26_dem_tables[1][0].q, AFSK26_DEM_SUM_Q_1_0), - convolution12_s16(buf, afsk26_dem_tables[1][1].i, AFSK26_DEM_SUM_I_1_1), - convolution12_s16(buf, afsk26_dem_tables[1][1].q, AFSK26_DEM_SUM_Q_1_1)); - } -} - -/* --------------------------------------------------------------------- */ - -static void demod_init_2666(struct sm_state *sm) -{ - struct demod_state_afsk26 *st = (struct demod_state_afsk26 *)(&sm->d); - - st->dcd_time = 400; - st->dcd_sum0 = 2; -} - -/* --------------------------------------------------------------------- */ - -const struct modem_tx_info sm_afsk2666_tx = { - "afsk2666", sizeof(struct mod_state_afsk26), AFSK26_SAMPLERATE, 2666, - modulator_2666_u8, modulator_2666_s16, NULL -}; - -const struct modem_rx_info sm_afsk2666_rx = { - "afsk2666", sizeof(struct demod_state_afsk26), AFSK26_SAMPLERATE, 2666, 12, 6, - demodulator_2666_u8, demodulator_2666_s16, demod_init_2666 -}; - -/* --------------------------------------------------------------------- */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/net/hamradio/soundmodem/sm.c linux.2.5.47-ac4/drivers/net/hamradio/soundmodem/sm.c --- linux.2.5.47/drivers/net/hamradio/soundmodem/sm.c 2002-10-31 14:57:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/net/hamradio/soundmodem/sm.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,759 +0,0 @@ -/*****************************************************************************/ - -/* - * sm.c -- soundcard radio modem driver. - * - * Copyright (C) 1996-2000 Thomas Sailer (sailer@ife.ee.ethz.ch) - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Please note that the GPL allows you to use the driver, NOT the radio. - * In order to use the radio, you need a license from the communications - * authority of your country. - * - * - * Command line options (insmod command line) - * - * mode mode string; eg. "wss:afsk1200" - * iobase base address of the soundcard; common values are 0x220 for sbc, - * 0x530 for wss - * irq interrupt number; common values are 7 or 5 for sbc, 11 for wss - * dma dma number; common values are 0 or 1 - * - * - * History: - * 0.1 21.09.1996 Started - * 18.10.1996 Changed to new user space access routines (copy_{to,from}_user) - * 0.4 21.01.1997 Separately compileable soundcard/modem modules - * 0.5 03.03.1997 fixed LPT probing (check_lpt result was interpreted the wrong way round) - * 0.6 16.04.1997 init code/data tagged - * 0.7 30.07.1997 fixed halfduplex interrupt handlers/hotfix for CS423X - * 0.8 14.04.1998 cleanups - * 0.9 03.08.1999 adapt to Linus' new __setup/__initcall - * use parport lowlevel drivers instead of directly writing to a parallel port - * removed some pre-2.2 kernel compatibility cruft - * 0.10 10.08.1999 Check if parport can do SPP and is safe to access during interrupt contexts - * 0.11 12.02.2000 adapted to softnet driver interface - * 0.12 03.07.2000 fix interface name handling - */ - -/*****************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "sm.h" - -/* --------------------------------------------------------------------- */ - -/*static*/ const char sm_drvname[] = "soundmodem"; -static const char sm_drvinfo[] = KERN_INFO "soundmodem: (C) 1996-2000 Thomas Sailer, HB9JNX/AE4WA\n" -KERN_INFO "soundmodem: version 0.12 compiled " __TIME__ " " __DATE__ "\n"; - -/* --------------------------------------------------------------------- */ - -/*static*/ const struct modem_tx_info *sm_modem_tx_table[] = { -#ifdef CONFIG_SOUNDMODEM_AFSK1200 - &sm_afsk1200_tx, -#endif /* CONFIG_SOUNDMODEM_AFSK1200 */ -#ifdef CONFIG_SOUNDMODEM_AFSK2400_7 - &sm_afsk2400_7_tx, -#endif /* CONFIG_SOUNDMODEM_AFSK2400_7 */ -#ifdef CONFIG_SOUNDMODEM_AFSK2400_8 - &sm_afsk2400_8_tx, -#endif /* CONFIG_SOUNDMODEM_AFSK2400_8 */ -#ifdef CONFIG_SOUNDMODEM_AFSK2666 - &sm_afsk2666_tx, -#endif /* CONFIG_SOUNDMODEM_AFSK2666 */ -#ifdef CONFIG_SOUNDMODEM_PSK4800 - &sm_psk4800_tx, -#endif /* CONFIG_SOUNDMODEM_PSK4800 */ -#ifdef CONFIG_SOUNDMODEM_HAPN4800 - &sm_hapn4800_8_tx, - &sm_hapn4800_10_tx, - &sm_hapn4800_pm8_tx, - &sm_hapn4800_pm10_tx, -#endif /* CONFIG_SOUNDMODEM_HAPN4800 */ -#ifdef CONFIG_SOUNDMODEM_FSK9600 - &sm_fsk9600_4_tx, - &sm_fsk9600_5_tx, -#endif /* CONFIG_SOUNDMODEM_FSK9600 */ - NULL -}; - -/*static*/ const struct modem_rx_info *sm_modem_rx_table[] = { -#ifdef CONFIG_SOUNDMODEM_AFSK1200 - &sm_afsk1200_rx, -#endif /* CONFIG_SOUNDMODEM_AFSK1200 */ -#ifdef CONFIG_SOUNDMODEM_AFSK2400_7 - &sm_afsk2400_7_rx, -#endif /* CONFIG_SOUNDMODEM_AFSK2400_7 */ -#ifdef CONFIG_SOUNDMODEM_AFSK2400_8 - &sm_afsk2400_8_rx, -#endif /* CONFIG_SOUNDMODEM_AFSK2400_8 */ -#ifdef CONFIG_SOUNDMODEM_AFSK2666 - &sm_afsk2666_rx, -#endif /* CONFIG_SOUNDMODEM_AFSK2666 */ -#ifdef CONFIG_SOUNDMODEM_PSK4800 - &sm_psk4800_rx, -#endif /* CONFIG_SOUNDMODEM_PSK4800 */ -#ifdef CONFIG_SOUNDMODEM_HAPN4800 - &sm_hapn4800_8_rx, - &sm_hapn4800_10_rx, - &sm_hapn4800_pm8_rx, - &sm_hapn4800_pm10_rx, -#endif /* CONFIG_SOUNDMODEM_HAPN4800 */ -#ifdef CONFIG_SOUNDMODEM_FSK9600 - &sm_fsk9600_4_rx, - &sm_fsk9600_5_rx, -#endif /* CONFIG_SOUNDMODEM_FSK9600 */ - NULL -}; - -static const struct hardware_info *sm_hardware_table[] = { -#ifdef CONFIG_SOUNDMODEM_SBC - &sm_hw_sbc, - &sm_hw_sbcfdx, -#endif /* CONFIG_SOUNDMODEM_SBC */ -#ifdef CONFIG_SOUNDMODEM_WSS - &sm_hw_wss, - &sm_hw_wssfdx, -#endif /* CONFIG_SOUNDMODEM_WSS */ - NULL -}; - -/* --------------------------------------------------------------------- */ - -#define NR_PORTS 4 - -static struct net_device sm_device[NR_PORTS]; - -/* --------------------------------------------------------------------- */ - -#define UART_RBR(iobase) (iobase+0) -#define UART_THR(iobase) (iobase+0) -#define UART_IER(iobase) (iobase+1) -#define UART_IIR(iobase) (iobase+2) -#define UART_FCR(iobase) (iobase+2) -#define UART_LCR(iobase) (iobase+3) -#define UART_MCR(iobase) (iobase+4) -#define UART_LSR(iobase) (iobase+5) -#define UART_MSR(iobase) (iobase+6) -#define UART_SCR(iobase) (iobase+7) -#define UART_DLL(iobase) (iobase+0) -#define UART_DLM(iobase) (iobase+1) - -#define SER_EXTENT 8 - -#define MIDI_DATA(iobase) (iobase) -#define MIDI_STATUS(iobase) (iobase+1) -#define MIDI_READ_FULL 0x80 /* attention: negative logic!! */ -#define MIDI_WRITE_EMPTY 0x40 /* attention: negative logic!! */ - -#define MIDI_EXTENT 2 - -/* ---------------------------------------------------------------------- */ - -#define PARAM_TXDELAY 1 -#define PARAM_PERSIST 2 -#define PARAM_SLOTTIME 3 -#define PARAM_TXTAIL 4 -#define PARAM_FULLDUP 5 -#define PARAM_HARDWARE 6 -#define PARAM_RETURN 255 - -#define SP_SER 1 -#define SP_PAR 2 -#define SP_MIDI 4 - -/* - * ===================== port checking routines ======================== - */ - -enum uart { c_uart_unknown, c_uart_8250, - c_uart_16450, c_uart_16550, c_uart_16550A}; -static const char *uart_str[] = - { "unknown", "8250", "16450", "16550", "16550A" }; - -static enum uart check_uart(unsigned int iobase) -{ - unsigned char b1,b2,b3; - enum uart u; - enum uart uart_tab[] = - { c_uart_16450, c_uart_unknown, c_uart_16550, c_uart_16550A }; - - if (iobase <= 0 || iobase > 0x1000-SER_EXTENT) - return c_uart_unknown; - if (check_region(iobase, SER_EXTENT)) - return c_uart_unknown; - b1 = inb(UART_MCR(iobase)); - outb(b1 | 0x10, UART_MCR(iobase)); /* loopback mode */ - b2 = inb(UART_MSR(iobase)); - outb(0x1a, UART_MCR(iobase)); - b3 = inb(UART_MSR(iobase)) & 0xf0; - outb(b1, UART_MCR(iobase)); /* restore old values */ - outb(b2, UART_MSR(iobase)); - if (b3 != 0x90) - return c_uart_unknown; - inb(UART_RBR(iobase)); - inb(UART_RBR(iobase)); - outb(0x01, UART_FCR(iobase)); /* enable FIFOs */ - u = uart_tab[(inb(UART_IIR(iobase)) >> 6) & 3]; - if (u == c_uart_16450) { - outb(0x5a, UART_SCR(iobase)); - b1 = inb(UART_SCR(iobase)); - outb(0xa5, UART_SCR(iobase)); - b2 = inb(UART_SCR(iobase)); - if ((b1 != 0x5a) || (b2 != 0xa5)) - u = c_uart_8250; - } - return u; -} - -/* --------------------------------------------------------------------- */ - -static int check_midi(unsigned int iobase) -{ - unsigned long timeout; - unsigned long flags; - unsigned char b; - - if (iobase <= 0 || iobase > 0x1000-MIDI_EXTENT) - return 0; - if (check_region(iobase, MIDI_EXTENT)) - return 0; - timeout = jiffies + (HZ / 100); - while (inb(MIDI_STATUS(iobase)) & MIDI_WRITE_EMPTY) - if ((signed)(jiffies - timeout) > 0) - return 0; - save_flags(flags); - cli(); - outb(0xff, MIDI_DATA(iobase)); - b = inb(MIDI_STATUS(iobase)); - restore_flags(flags); - if (!(b & MIDI_WRITE_EMPTY)) - return 0; - while (inb(MIDI_STATUS(iobase)) & MIDI_WRITE_EMPTY) - if ((signed)(jiffies - timeout) > 0) - return 0; - return 1; -} - -/* --------------------------------------------------------------------- */ - -void sm_output_status(struct sm_state *sm) -{ - int invert_dcd = 0; - int invert_ptt = 0; - - int ptt = /*hdlcdrv_ptt(&sm->hdrv)*/(sm->dma.ptt_cnt > 0) ^ invert_ptt; - int dcd = (!!sm->hdrv.hdlcrx.dcd) ^ invert_dcd; - - if (sm->hdrv.ptt_out.flags & SP_SER) { - outb(dcd | (ptt << 1), UART_MCR(sm->hdrv.ptt_out.seriobase)); - outb(0x40 & (-ptt), UART_LCR(sm->hdrv.ptt_out.seriobase)); - } - if (sm->hdrv.ptt_out.flags & SP_PAR && sm->pardev && sm->pardev->port) - parport_write_data(sm->pardev->port, ptt | (dcd << 1)); - if (sm->hdrv.ptt_out.flags & SP_MIDI && hdlcdrv_ptt(&sm->hdrv)) - outb(0, MIDI_DATA(sm->hdrv.ptt_out.midiiobase)); -} - -/* --------------------------------------------------------------------- */ - -static void sm_output_open(struct sm_state *sm, const char *ifname) -{ - enum uart u = c_uart_unknown; - struct parport *pp = NULL; - - sm->hdrv.ptt_out.flags = 0; - if (sm->hdrv.ptt_out.seriobase > 0 && - sm->hdrv.ptt_out.seriobase <= 0x1000-SER_EXTENT && - ((u = check_uart(sm->hdrv.ptt_out.seriobase))) != c_uart_unknown) { - sm->hdrv.ptt_out.flags |= SP_SER; - request_region(sm->hdrv.ptt_out.seriobase, SER_EXTENT, "sm ser ptt"); - outb(0, UART_IER(sm->hdrv.ptt_out.seriobase)); - /* 5 bits, 1 stop, no parity, no break, Div latch access */ - outb(0x80, UART_LCR(sm->hdrv.ptt_out.seriobase)); - outb(0, UART_DLM(sm->hdrv.ptt_out.seriobase)); - outb(1, UART_DLL(sm->hdrv.ptt_out.seriobase)); /* as fast as possible */ - /* LCR and MCR set by output_status */ - } - sm->pardev = NULL; - if (sm->hdrv.ptt_out.pariobase > 0) { - pp = parport_enumerate(); - while (pp && pp->base != sm->hdrv.ptt_out.pariobase) - pp = pp->next; - if (!pp) - printk(KERN_WARNING "%s: parport at address 0x%x not found\n", sm_drvname, sm->hdrv.ptt_out.pariobase); - else if ((~pp->modes) & (PARPORT_MODE_PCSPP | PARPORT_MODE_SAFEININT)) - printk(KERN_WARNING "%s: parport at address 0x%x cannot be used\n", sm_drvname, sm->hdrv.ptt_out.pariobase); - else { - sm->pardev = parport_register_device(pp, ifname, NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL); - if (!sm->pardev) { - pp = NULL; - printk(KERN_WARNING "%s: cannot register parport device (address 0x%x)\n", sm_drvname, sm->hdrv.ptt_out.pariobase); - } else { - if (parport_claim(sm->pardev)) { - parport_unregister_device(sm->pardev); - sm->pardev = NULL; - printk(KERN_WARNING "%s: cannot claim parport at address 0x%x\n", sm_drvname, sm->hdrv.ptt_out.pariobase); - } else - sm->hdrv.ptt_out.flags |= SP_PAR; - } - } - } - if (sm->hdrv.ptt_out.midiiobase > 0 && - sm->hdrv.ptt_out.midiiobase <= 0x1000-MIDI_EXTENT && - check_midi(sm->hdrv.ptt_out.midiiobase)) { - sm->hdrv.ptt_out.flags |= SP_MIDI; - request_region(sm->hdrv.ptt_out.midiiobase, MIDI_EXTENT, - "sm midi ptt"); - } - sm_output_status(sm); - - printk(KERN_INFO "%s: ptt output:", sm_drvname); - if (sm->hdrv.ptt_out.flags & SP_SER) - printk(" serial interface at 0x%x, uart %s", sm->hdrv.ptt_out.seriobase, - uart_str[u]); - if (sm->hdrv.ptt_out.flags & SP_PAR) - printk(" parallel interface at 0x%x", sm->hdrv.ptt_out.pariobase); - if (sm->hdrv.ptt_out.flags & SP_MIDI) - printk(" mpu401 (midi) interface at 0x%x", sm->hdrv.ptt_out.midiiobase); - if (!sm->hdrv.ptt_out.flags) - printk(" none"); - printk("\n"); -} - -/* --------------------------------------------------------------------- */ - -static void sm_output_close(struct sm_state *sm) -{ - /* release regions used for PTT output */ - sm->hdrv.hdlctx.ptt = sm->hdrv.hdlctx.calibrate = 0; - sm_output_status(sm); - if (sm->hdrv.ptt_out.flags & SP_SER) - release_region(sm->hdrv.ptt_out.seriobase, SER_EXTENT); - if (sm->hdrv.ptt_out.flags & SP_PAR && sm->pardev) { - parport_release(sm->pardev); - parport_unregister_device(sm->pardev); - } - if (sm->hdrv.ptt_out.flags & SP_MIDI) - release_region(sm->hdrv.ptt_out.midiiobase, MIDI_EXTENT); - sm->hdrv.ptt_out.flags = 0; -} - -/* --------------------------------------------------------------------- */ - -static int sm_open(struct net_device *dev); -static int sm_close(struct net_device *dev); -static int sm_ioctl(struct net_device *dev, struct ifreq *ifr, - struct hdlcdrv_ioctl *hi, int cmd); - -/* --------------------------------------------------------------------- */ - -static const struct hdlcdrv_ops sm_ops = { - sm_drvname, sm_drvinfo, sm_open, sm_close, sm_ioctl -}; - -/* --------------------------------------------------------------------- */ - -static int sm_open(struct net_device *dev) -{ - struct sm_state *sm; - int err; - - if (!dev || !dev->priv || - ((struct sm_state *)dev->priv)->hdrv.magic != HDLCDRV_MAGIC) { - printk(KERN_ERR "sm_open: invalid device struct\n"); - return -EINVAL; - } - sm = (struct sm_state *)dev->priv; - - if (!sm->mode_tx || !sm->mode_rx || !sm->hwdrv || !sm->hwdrv->open) - return -ENODEV; - sm->hdrv.par.bitrate = sm->mode_rx->bitrate; - err = sm->hwdrv->open(dev, sm); - if (err) - return err; - sm_output_open(sm, dev->name); - MOD_INC_USE_COUNT; - printk(KERN_INFO "%s: %s mode %s.%s at iobase 0x%lx irq %u dma %u dma2 %u\n", - sm_drvname, sm->hwdrv->hw_name, sm->mode_tx->name, - sm->mode_rx->name, dev->base_addr, dev->irq, dev->dma, sm->hdrv.ptt_out.dma2); - return 0; -} - -/* --------------------------------------------------------------------- */ - -static int sm_close(struct net_device *dev) -{ - struct sm_state *sm; - int err = -ENODEV; - - if (!dev || !dev->priv || - ((struct sm_state *)dev->priv)->hdrv.magic != HDLCDRV_MAGIC) { - printk(KERN_ERR "sm_close: invalid device struct\n"); - return -EINVAL; - } - sm = (struct sm_state *)dev->priv; - - - if (sm->hwdrv && sm->hwdrv->close) - err = sm->hwdrv && sm->hwdrv->close(dev, sm); - sm_output_close(sm); - MOD_DEC_USE_COUNT; - printk(KERN_INFO "%s: close %s at iobase 0x%lx irq %u dma %u\n", - sm_drvname, sm->hwdrv->hw_name, dev->base_addr, dev->irq, dev->dma); - return err; -} - -/* --------------------------------------------------------------------- */ - -static int sethw(struct net_device *dev, struct sm_state *sm, char *mode) -{ - char *cp = strchr(mode, ':'); - const struct hardware_info **hwp = sm_hardware_table; - - if (!cp) - cp = mode; - else { - *cp++ = '\0'; - while (hwp && (*hwp) && (*hwp)->hw_name && strcmp((*hwp)->hw_name, mode)) - hwp++; - if (!hwp || !*hwp || !(*hwp)->hw_name) - return -EINVAL; - if ((*hwp)->loc_storage > sizeof(sm->hw)) { - printk(KERN_ERR "%s: insufficient storage for hw driver %s (%d)\n", - sm_drvname, (*hwp)->hw_name, (*hwp)->loc_storage); - return -EINVAL; - } - sm->hwdrv = *hwp; - } - if (!*cp) - return 0; - if (sm->hwdrv && sm->hwdrv->sethw) - return sm->hwdrv->sethw(dev, sm, cp); - return -EINVAL; -} - -/* --------------------------------------------------------------------- */ - -static int sm_ioctl(struct net_device *dev, struct ifreq *ifr, - struct hdlcdrv_ioctl *hi, int cmd) -{ - struct sm_state *sm; - struct sm_ioctl bi; - unsigned long flags; - unsigned int newdiagmode; - unsigned int newdiagflags; - char *cp; - const struct modem_tx_info **mtp = sm_modem_tx_table; - const struct modem_rx_info **mrp = sm_modem_rx_table; - const struct hardware_info **hwp = sm_hardware_table; - - if (!dev || !dev->priv || - ((struct sm_state *)dev->priv)->hdrv.magic != HDLCDRV_MAGIC) { - printk(KERN_ERR "sm_ioctl: invalid device struct\n"); - return -EINVAL; - } - sm = (struct sm_state *)dev->priv; - - if (cmd != SIOCDEVPRIVATE) { - if (!sm->hwdrv || !sm->hwdrv->ioctl) - return sm->hwdrv->ioctl(dev, sm, ifr, hi, cmd); - return -ENOIOCTLCMD; - } - switch (hi->cmd) { - default: - if (sm->hwdrv && sm->hwdrv->ioctl) - return sm->hwdrv->ioctl(dev, sm, ifr, hi, cmd); - return -ENOIOCTLCMD; - - case HDLCDRVCTL_GETMODE: - cp = hi->data.modename; - if (sm->hwdrv && sm->hwdrv->hw_name) - cp += sprintf(cp, "%s:", sm->hwdrv->hw_name); - else - cp += sprintf(cp, ":"); - if (sm->mode_tx && sm->mode_tx->name) - cp += sprintf(cp, "%s", sm->mode_tx->name); - else - cp += sprintf(cp, ""); - if (!sm->mode_rx || !sm->mode_rx || - strcmp(sm->mode_rx->name, sm->mode_tx->name)) { - if (sm->mode_rx && sm->mode_rx->name) - cp += sprintf(cp, ",%s", sm->mode_rx->name); - else - cp += sprintf(cp, ","); - } - if (copy_to_user(ifr->ifr_data, hi, sizeof(*hi))) - return -EFAULT; - return 0; - - case HDLCDRVCTL_SETMODE: - if (netif_running(dev) || !capable(CAP_NET_ADMIN)) - return -EACCES; - hi->data.modename[sizeof(hi->data.modename)-1] = '\0'; - return sethw(dev, sm, hi->data.modename); - - case HDLCDRVCTL_MODELIST: - cp = hi->data.modename; - while (*hwp) { - if ((*hwp)->hw_name) - cp += sprintf(cp, "%s:,", (*hwp)->hw_name); - hwp++; - } - while (*mtp) { - if ((*mtp)->name) - cp += sprintf(cp, ">%s,", (*mtp)->name); - mtp++; - } - while (*mrp) { - if ((*mrp)->name) - cp += sprintf(cp, "<%s,", (*mrp)->name); - mrp++; - } - cp[-1] = '\0'; - if (copy_to_user(ifr->ifr_data, hi, sizeof(*hi))) - return -EFAULT; - return 0; - -#ifdef SM_DEBUG - case SMCTL_GETDEBUG: - if (copy_from_user(&bi, ifr->ifr_data, sizeof(bi))) - return -EFAULT; - bi.data.dbg.int_rate = sm->debug_vals.last_intcnt; - bi.data.dbg.mod_cycles = sm->debug_vals.mod_cyc; - bi.data.dbg.demod_cycles = sm->debug_vals.demod_cyc; - bi.data.dbg.dma_residue = sm->debug_vals.dma_residue; - sm->debug_vals.mod_cyc = sm->debug_vals.demod_cyc = - sm->debug_vals.dma_residue = 0; - if (copy_to_user(ifr->ifr_data, &bi, sizeof(bi))) - return -EFAULT; - return 0; -#endif /* SM_DEBUG */ - - case SMCTL_DIAGNOSE: - if (copy_from_user(&bi, ifr->ifr_data, sizeof(bi))) - return -EFAULT; - newdiagmode = bi.data.diag.mode; - newdiagflags = bi.data.diag.flags; - if (newdiagmode > SM_DIAGMODE_CONSTELLATION) - return -EINVAL; - bi.data.diag.mode = sm->diag.mode; - bi.data.diag.flags = sm->diag.flags; - bi.data.diag.samplesperbit = sm->mode_rx->sperbit; - if (sm->diag.mode != newdiagmode) { - save_flags(flags); - cli(); - sm->diag.ptr = -1; - sm->diag.flags = newdiagflags & ~SM_DIAGFLAG_VALID; - sm->diag.mode = newdiagmode; - restore_flags(flags); - if (copy_to_user(ifr->ifr_data, &bi, sizeof(bi))) - return -EFAULT; - return 0; - } - if (sm->diag.ptr < 0 || sm->diag.mode == SM_DIAGMODE_OFF) { - if (copy_to_user(ifr->ifr_data, &bi, sizeof(bi))) - return -EFAULT; - return 0; - } - if (bi.data.diag.datalen > DIAGDATALEN) - bi.data.diag.datalen = DIAGDATALEN; - if (sm->diag.ptr < bi.data.diag.datalen) { - if (copy_to_user(ifr->ifr_data, &bi, sizeof(bi))) - return -EFAULT; - return 0; - } - if (copy_to_user(bi.data.diag.data, sm->diag.data, - bi.data.diag.datalen * sizeof(short))) - return -EFAULT; - bi.data.diag.flags |= SM_DIAGFLAG_VALID; - save_flags(flags); - cli(); - sm->diag.ptr = -1; - sm->diag.flags = newdiagflags & ~SM_DIAGFLAG_VALID; - sm->diag.mode = newdiagmode; - restore_flags(flags); - if (copy_to_user(ifr->ifr_data, &bi, sizeof(bi))) - return -EFAULT; - return 0; - } -} - -/* --------------------------------------------------------------------- */ - -/* - * command line settable parameters - */ -static char *mode[NR_PORTS] = { [0 ... NR_PORTS-1] = NULL }; -static int iobase[NR_PORTS] = { [0 ... NR_PORTS-1] = -1 }; -static int irq[NR_PORTS] = { [0 ... NR_PORTS-1] = -1 }; -static int dma[NR_PORTS] = { [0 ... NR_PORTS-1] = -1 }; -static int dma2[NR_PORTS] = { [0 ... NR_PORTS-1] = -1 }; -static int serio[NR_PORTS] = { [0 ... NR_PORTS-1] = 0 }; -static int pario[NR_PORTS] = { [0 ... NR_PORTS-1] = 0 }; -static int midiio[NR_PORTS] = { [0 ... NR_PORTS-1] = 0 }; - -MODULE_PARM(mode, "1-" __MODULE_STRING(NR_PORTS) "s"); -MODULE_PARM_DESC(mode, "soundmodem operating mode; eg. sbc:afsk1200 or wss:fsk9600"); -MODULE_PARM(iobase, "1-" __MODULE_STRING(NR_PORTS) "i"); -MODULE_PARM_DESC(iobase, "soundmodem base address"); -MODULE_PARM(irq, "1-" __MODULE_STRING(NR_PORTS) "i"); -MODULE_PARM_DESC(irq, "soundmodem interrupt"); -MODULE_PARM(dma, "1-" __MODULE_STRING(NR_PORTS) "i"); -MODULE_PARM_DESC(dma, "soundmodem dma channel"); -MODULE_PARM(dma2, "1-" __MODULE_STRING(NR_PORTS) "i"); -MODULE_PARM_DESC(dma2, "soundmodem 2nd dma channel; full duplex only"); -MODULE_PARM(serio, "1-" __MODULE_STRING(NR_PORTS) "i"); -MODULE_PARM_DESC(serio, "soundmodem PTT output on serial port"); -MODULE_PARM(pario, "1-" __MODULE_STRING(NR_PORTS) "i"); -MODULE_PARM_DESC(pario, "soundmodem PTT output on parallel port"); -MODULE_PARM(midiio, "1-" __MODULE_STRING(NR_PORTS) "i"); -MODULE_PARM_DESC(midiio, "soundmodem PTT output on midi port"); - -MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu"); -MODULE_DESCRIPTION("Soundcard amateur radio modem driver"); - -/* --------------------------------------------------------------------- */ - -static int __init init_soundmodem(void) -{ - int i, j, found = 0; - char set_hw = 1; - struct sm_state *sm; - - printk(sm_drvinfo); - /* - * register net devices - */ - for (i = 0; i < NR_PORTS; i++) { - struct net_device *dev = sm_device+i; - char ifname[IFNAMSIZ]; - - sprintf(ifname, "sm%d", i); - if (!mode[i]) - set_hw = 0; - else { - if (!strncmp(mode[i], "sbc", 3)) { - if (iobase[i] == -1) - iobase[i] = 0x220; - if (irq[i] == -1) - irq[i] = 5; - if (dma[i] == -1) - dma[i] = 1; - } else { - if (iobase[i] == -1) - iobase[i] = 0x530; - if (irq[i] == -1) - irq[i] = 11; - if (dma[i] == -1) - dma[i] = 1; - } - } - if (!set_hw) - iobase[i] = irq[i] = 0; - j = hdlcdrv_register_hdlcdrv(dev, &sm_ops, sizeof(struct sm_state), ifname, iobase[i], irq[i], dma[i]); - if (!j) { - sm = (struct sm_state *)dev->priv; - sm->hdrv.ptt_out.dma2 = dma2[i]; - sm->hdrv.ptt_out.seriobase = serio[i]; - sm->hdrv.ptt_out.pariobase = pario[i]; - sm->hdrv.ptt_out.midiiobase = midiio[i]; - if (set_hw && sethw(dev, sm, mode[i])) - set_hw = 0; - found++; - } else { - printk(KERN_WARNING "%s: cannot register net device\n", sm_drvname); - } - } - if (!found) - return -ENXIO; - return 0; -} - -static void __exit cleanup_soundmodem(void) -{ - int i; - - printk(KERN_INFO "sm: cleanup_module called\n"); - - for(i = 0; i < NR_PORTS; i++) { - struct net_device *dev = sm_device+i; - struct sm_state *sm = (struct sm_state *)dev->priv; - - if (sm) { - if (sm->hdrv.magic != HDLCDRV_MAGIC) - printk(KERN_ERR "sm: invalid magic in " - "cleanup_module\n"); - else - hdlcdrv_unregister_hdlcdrv(dev); - } - } -} - -module_init(init_soundmodem); -module_exit(cleanup_soundmodem); - -/* --------------------------------------------------------------------- */ - -#ifndef MODULE - -/* - * format: soundmodem=io,irq,dma[,dma2[,serio[,pario]]],mode - * mode: hw:modem - * hw: sbc, wss, wssfdx - * modem: afsk1200, fsk9600 - */ - -static int __init sm_setup(char *str) -{ - static unsigned nr_dev; - int ints[8]; - - if (nr_dev >= NR_PORTS) - return 0; - str = get_options(str, 8, ints); - mode[nr_dev] = str; - if (ints[0] >= 1) - iobase[nr_dev] = ints[1]; - if (ints[0] >= 2) - irq[nr_dev] = ints[2]; - if (ints[0] >= 3) - dma[nr_dev] = ints[3]; - if (ints[0] >= 4) - dma2[nr_dev] = ints[4]; - if (ints[0] >= 5) - serio[nr_dev] = ints[5]; - if (ints[0] >= 6) - pario[nr_dev] = ints[6]; - if (ints[0] >= 7) - midiio[nr_dev] = ints[7]; - nr_dev++; - return 1; -} - -__setup("soundmodem=", sm_setup); - -#endif /* MODULE */ -/* --------------------------------------------------------------------- */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/net/hamradio/soundmodem/smdma.h linux.2.5.47-ac4/drivers/net/hamradio/soundmodem/smdma.h --- linux.2.5.47/drivers/net/hamradio/soundmodem/smdma.h 2002-10-31 14:57:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/net/hamradio/soundmodem/smdma.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,217 +0,0 @@ -/*****************************************************************************/ - -/* - * smdma.h -- soundcard radio modem driver dma buffer routines. - * - * Copyright (C) 1996 Thomas Sailer (sailer@ife.ee.ethz.ch) - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Please note that the GPL allows you to use the driver, NOT the radio. - * In order to use the radio, you need a license from the communications - * authority of your country. - * - */ - -#ifndef _SMDMA_H -#define _SMDMA_H - -/* ---------------------------------------------------------------------- */ - -#include "sm.h" - -/* ---------------------------------------------------------------------- */ - -#define DMA_MODE_AUTOINIT 0x10 -#define NUM_FRAGMENTS 4 - -/* - * NOTE: make sure that hdlcdrv_hdlcbuffer contains enough space - * for the modulator to fill the whole DMA buffer without underrun - * at the highest possible baud rate, otherwise the TX state machine will - * not work correctly. That is (9k6 FSK): HDLCDRV_HDLCBUFFER > 6*NUM_FRAGMENTS - */ - -/* --------------------------------------------------------------------- */ -/* - * ===================== DMA buffer management =========================== - */ - -/* - * returns the number of samples per fragment - */ -static __inline__ unsigned int dma_setup(struct sm_state *sm, int send, unsigned int dmanr) -{ - if (send) { - disable_dma(dmanr); - clear_dma_ff(dmanr); - set_dma_mode(dmanr, DMA_MODE_WRITE | DMA_MODE_AUTOINIT); - set_dma_addr(dmanr, virt_to_bus(sm->dma.obuf)); - set_dma_count(dmanr, sm->dma.ofragsz * NUM_FRAGMENTS); - enable_dma(dmanr); - if (sm->dma.o16bit) - return sm->dma.ofragsz/2; - return sm->dma.ofragsz; - } else { - disable_dma(dmanr); - clear_dma_ff(dmanr); - set_dma_mode(dmanr, DMA_MODE_READ | DMA_MODE_AUTOINIT); - set_dma_addr(dmanr, virt_to_bus(sm->dma.ibuf)); - set_dma_count(dmanr, sm->dma.ifragsz * NUM_FRAGMENTS); - enable_dma(dmanr); - if (sm->dma.i16bit) - return sm->dma.ifragsz/2; - return sm->dma.ifragsz; - } -} - -/* --------------------------------------------------------------------- */ - -static __inline__ unsigned int dma_ptr(struct sm_state *sm, int send, unsigned int dmanr, - unsigned int *curfrag) -{ - unsigned int dmaptr, sz, frg, offs; - - dmaptr = get_dma_residue(dmanr); - if (send) { - sz = sm->dma.ofragsz * NUM_FRAGMENTS; - if (dmaptr == 0 || dmaptr > sz) - dmaptr = sz; - dmaptr--; - frg = dmaptr / sm->dma.ofragsz; - offs = (dmaptr % sm->dma.ofragsz) + 1; - *curfrag = NUM_FRAGMENTS - 1 - frg; -#ifdef SM_DEBUG - if (!sm->debug_vals.dma_residue || offs < sm->debug_vals.dma_residue) - sm->debug_vals.dma_residue = offs; -#endif /* SM_DEBUG */ - if (sm->dma.o16bit) - return offs/2; - return offs; - } else { - sz = sm->dma.ifragsz * NUM_FRAGMENTS; - if (dmaptr == 0 || dmaptr > sz) - dmaptr = sz; - dmaptr--; - frg = dmaptr / sm->dma.ifragsz; - offs = (dmaptr % sm->dma.ifragsz) + 1; - *curfrag = NUM_FRAGMENTS - 1 - frg; -#ifdef SM_DEBUG - if (!sm->debug_vals.dma_residue || offs < sm->debug_vals.dma_residue) - sm->debug_vals.dma_residue = offs; -#endif /* SM_DEBUG */ - if (sm->dma.i16bit) - return offs/2; - return offs; - } -} - -/* --------------------------------------------------------------------- */ - -static __inline__ int dma_end_transmit(struct sm_state *sm, unsigned int curfrag) -{ - unsigned int diff = (NUM_FRAGMENTS + curfrag - sm->dma.ofragptr) % NUM_FRAGMENTS; - - sm->dma.ofragptr = curfrag; - if (sm->dma.ptt_cnt <= 0) { - sm->dma.ptt_cnt = 0; - return 0; - } - sm->dma.ptt_cnt -= diff; - if (sm->dma.ptt_cnt <= 0) { - sm->dma.ptt_cnt = 0; - return -1; - } - return 0; -} - -static __inline__ void dma_transmit(struct sm_state *sm) -{ - void *p; - - while (sm->dma.ptt_cnt < NUM_FRAGMENTS && hdlcdrv_ptt(&sm->hdrv)) { - p = (unsigned char *)sm->dma.obuf + sm->dma.ofragsz * - ((sm->dma.ofragptr + sm->dma.ptt_cnt) % NUM_FRAGMENTS); - if (sm->dma.o16bit) { - time_exec(sm->debug_vals.mod_cyc, - sm->mode_tx->modulator_s16(sm, p, sm->dma.ofragsz/2)); - } else { - time_exec(sm->debug_vals.mod_cyc, - sm->mode_tx->modulator_u8(sm, p, sm->dma.ofragsz)); - } - sm->dma.ptt_cnt++; - } -} - -static __inline__ void dma_init_transmit(struct sm_state *sm) -{ - sm->dma.ofragptr = 0; - sm->dma.ptt_cnt = 0; -} - -static __inline__ void dma_start_transmit(struct sm_state *sm) -{ - sm->dma.ofragptr = 0; - if (sm->dma.o16bit) { - time_exec(sm->debug_vals.mod_cyc, - sm->mode_tx->modulator_s16(sm, sm->dma.obuf, sm->dma.ofragsz/2)); - } else { - time_exec(sm->debug_vals.mod_cyc, - sm->mode_tx->modulator_u8(sm, sm->dma.obuf, sm->dma.ofragsz)); - } - sm->dma.ptt_cnt = 1; -} - -static __inline__ void dma_clear_transmit(struct sm_state *sm) -{ - sm->dma.ptt_cnt = 0; - memset(sm->dma.obuf, (sm->dma.o16bit) ? 0 : 0x80, sm->dma.ofragsz * NUM_FRAGMENTS); -} - -/* --------------------------------------------------------------------- */ - -static __inline__ void dma_receive(struct sm_state *sm, unsigned int curfrag) -{ - void *p; - - while (sm->dma.ifragptr != curfrag) { - if (sm->dma.ifragptr) - p = (unsigned char *)sm->dma.ibuf + - sm->dma.ifragsz * sm->dma.ifragptr; - else { - p = (unsigned char *)sm->dma.ibuf + NUM_FRAGMENTS * sm->dma.ifragsz; - memcpy(p, sm->dma.ibuf, sm->dma.ifragsz); - } - if (sm->dma.o16bit) { - time_exec(sm->debug_vals.demod_cyc, - sm->mode_rx->demodulator_s16(sm, p, sm->dma.ifragsz/2)); - } else { - time_exec(sm->debug_vals.demod_cyc, - sm->mode_rx->demodulator_u8(sm, p, sm->dma.ifragsz)); - } - sm->dma.ifragptr = (sm->dma.ifragptr + 1) % NUM_FRAGMENTS; - } -} - -static __inline__ void dma_init_receive(struct sm_state *sm) -{ - sm->dma.ifragptr = 0; -} - -/* --------------------------------------------------------------------- */ -#endif /* _SMDMA_H */ - - - diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/net/hamradio/soundmodem/sm_fsk9600.c linux.2.5.47-ac4/drivers/net/hamradio/soundmodem/sm_fsk9600.c --- linux.2.5.47/drivers/net/hamradio/soundmodem/sm_fsk9600.c 2002-10-31 14:57:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/net/hamradio/soundmodem/sm_fsk9600.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,391 +0,0 @@ -/*****************************************************************************/ - -/* - * sm_fsk9600.c -- soundcard radio modem driver, - * 9600 baud G3RUH compatible FSK modem - * - * Copyright (C) 1996 Thomas Sailer (sailer@ife.ee.ethz.ch) - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Please note that the GPL allows you to use the driver, NOT the radio. - * In order to use the radio, you need a license from the communications - * authority of your country. - * - */ - -#include "sm.h" -#include "sm_tbl_fsk9600.h" - -/* --------------------------------------------------------------------- */ - -struct demod_state_fsk96 { - unsigned int shreg; - unsigned long descram; - unsigned int bit_pll; - unsigned char last_sample; - unsigned int dcd_shreg; - int dcd_sum0, dcd_sum1, dcd_sum2; - unsigned int dcd_time; -}; - -struct mod_state_fsk96 { - unsigned int shreg; - unsigned long scram; - unsigned char tx_bit; - unsigned char *txtbl; - unsigned int txphase; -}; - -/* --------------------------------------------------------------------- */ - -#define DESCRAM_TAP1 0x20000 -#define DESCRAM_TAP2 0x01000 -#define DESCRAM_TAP3 0x00001 - -#define DESCRAM_TAPSH1 17 -#define DESCRAM_TAPSH2 12 -#define DESCRAM_TAPSH3 0 - -#define SCRAM_TAP1 0x20000 /* X^17 */ -#define SCRAM_TAPN 0x00021 /* X^0+X^5 */ - -/* --------------------------------------------------------------------- */ - -static void modulator_9600_4_u8(struct sm_state *sm, unsigned char *buf, unsigned int buflen) -{ - struct mod_state_fsk96 *st = (struct mod_state_fsk96 *)(&sm->m); - - for (; buflen > 0; buflen--) { - if (!st->txphase++) { - if (st->shreg <= 1) - st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; - st->scram = (st->scram << 1) | (st->scram & 1); - st->scram ^= !(st->shreg & 1); - st->shreg >>= 1; - if (st->scram & (SCRAM_TAP1 << 1)) - st->scram ^= SCRAM_TAPN << 1; - st->tx_bit = (st->tx_bit << 1) | (!!(st->scram & (SCRAM_TAP1 << 2))); - st->txtbl = fsk96_txfilt_4 + (st->tx_bit & 0xff); - } - if (st->txphase >= 4) - st->txphase = 0; - *buf++ = *st->txtbl; - st->txtbl += 0x100; - } -} - -/* --------------------------------------------------------------------- */ - -static void modulator_9600_4_s16(struct sm_state *sm, short *buf, unsigned int buflen) -{ - struct mod_state_fsk96 *st = (struct mod_state_fsk96 *)(&sm->m); - - for (; buflen > 0; buflen--) { - if (!st->txphase++) { - if (st->shreg <= 1) - st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; - st->scram = (st->scram << 1) | (st->scram & 1); - st->scram ^= !(st->shreg & 1); - st->shreg >>= 1; - if (st->scram & (SCRAM_TAP1 << 1)) - st->scram ^= SCRAM_TAPN << 1; - st->tx_bit = (st->tx_bit << 1) | (!!(st->scram & (SCRAM_TAP1 << 2))); - st->txtbl = fsk96_txfilt_4 + (st->tx_bit & 0xff); - } - if (st->txphase >= 4) - st->txphase = 0; - *buf++ = ((*st->txtbl)-0x80) << 8; - st->txtbl += 0x100; - } -} - -/* --------------------------------------------------------------------- */ - -static void demodulator_9600_4_u8(struct sm_state *sm, const unsigned char *buf, unsigned int buflen) -{ - struct demod_state_fsk96 *st = (struct demod_state_fsk96 *)(&sm->d); - static const int pll_corr[2] = { -0x1000, 0x1000 }; - unsigned char curbit; - unsigned int descx; - - for (; buflen > 0; buflen--, buf++) { - st->dcd_shreg <<= 1; - st->bit_pll += 0x4000; - curbit = (*buf >= 0x80); - if (st->last_sample ^ curbit) { - st->dcd_shreg |= 1; - st->bit_pll += pll_corr[st->bit_pll < 0xa000]; - st->dcd_sum0 += 8 * hweight8(st->dcd_shreg & 0x0c) - - !!(st->dcd_shreg & 0x10); - } - st->last_sample = curbit; - hdlcdrv_channelbit(&sm->hdrv, st->last_sample); - if ((--st->dcd_time) <= 0) { - hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + - st->dcd_sum1 + - st->dcd_sum2) < 0); - st->dcd_sum2 = st->dcd_sum1; - st->dcd_sum1 = st->dcd_sum0; - st->dcd_sum0 = 2; /* slight bias */ - st->dcd_time = 240; - } - if (st->bit_pll >= 0x10000) { - st->bit_pll &= 0xffff; - st->descram = (st->descram << 1) | curbit; - descx = st->descram ^ (st->descram >> 1); - descx ^= ((descx >> DESCRAM_TAPSH1) ^ - (descx >> DESCRAM_TAPSH2)); - st->shreg >>= 1; - st->shreg |= (!(descx & 1)) << 16; - if (st->shreg & 1) { - hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1); - st->shreg = 0x10000; - } - diag_trigger(sm); - } - diag_add_one(sm, ((short)(*buf - 0x80)) << 8); - } -} - -/* --------------------------------------------------------------------- */ - -static void demodulator_9600_4_s16(struct sm_state *sm, const short *buf, unsigned int buflen) -{ - struct demod_state_fsk96 *st = (struct demod_state_fsk96 *)(&sm->d); - static const int pll_corr[2] = { -0x1000, 0x1000 }; - unsigned char curbit; - unsigned int descx; - - for (; buflen > 0; buflen--, buf++) { - st->dcd_shreg <<= 1; - st->bit_pll += 0x4000; - curbit = (*buf >= 0); - if (st->last_sample ^ curbit) { - st->dcd_shreg |= 1; - st->bit_pll += pll_corr[st->bit_pll < 0xa000]; - st->dcd_sum0 += 8 * hweight8(st->dcd_shreg & 0x0c) - - !!(st->dcd_shreg & 0x10); - } - st->last_sample = curbit; - hdlcdrv_channelbit(&sm->hdrv, st->last_sample); - if ((--st->dcd_time) <= 0) { - hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + - st->dcd_sum1 + - st->dcd_sum2) < 0); - st->dcd_sum2 = st->dcd_sum1; - st->dcd_sum1 = st->dcd_sum0; - st->dcd_sum0 = 2; /* slight bias */ - st->dcd_time = 240; - } - if (st->bit_pll >= 0x10000) { - st->bit_pll &= 0xffff; - st->descram = (st->descram << 1) | curbit; - descx = st->descram ^ (st->descram >> 1); - descx ^= ((descx >> DESCRAM_TAPSH1) ^ - (descx >> DESCRAM_TAPSH2)); - st->shreg >>= 1; - st->shreg |= (!(descx & 1)) << 16; - if (st->shreg & 1) { - hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1); - st->shreg = 0x10000; - } - diag_trigger(sm); - } - diag_add_one(sm, *buf); - } -} - -/* --------------------------------------------------------------------- */ - -static void modulator_9600_5_u8(struct sm_state *sm, unsigned char *buf, unsigned int buflen) -{ - struct mod_state_fsk96 *st = (struct mod_state_fsk96 *)(&sm->m); - - for (; buflen > 0; buflen--) { - if (!st->txphase++) { - if (st->shreg <= 1) - st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; - st->scram = (st->scram << 1) | (st->scram & 1); - st->scram ^= !(st->shreg & 1); - st->shreg >>= 1; - if (st->scram & (SCRAM_TAP1 << 1)) - st->scram ^= SCRAM_TAPN << 1; - st->tx_bit = (st->tx_bit << 1) | (!!(st->scram & (SCRAM_TAP1 << 2))); - st->txtbl = fsk96_txfilt_5 + (st->tx_bit & 0xff); - } - if (st->txphase >= 5) - st->txphase = 0; - *buf++ = *st->txtbl; - st->txtbl += 0x100; - } -} - -/* --------------------------------------------------------------------- */ - -static void modulator_9600_5_s16(struct sm_state *sm, short *buf, unsigned int buflen) -{ - struct mod_state_fsk96 *st = (struct mod_state_fsk96 *)(&sm->m); - - for (; buflen > 0; buflen--) { - if (!st->txphase++) { - if (st->shreg <= 1) - st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; - st->scram = (st->scram << 1) | (st->scram & 1); - st->scram ^= !(st->shreg & 1); - st->shreg >>= 1; - if (st->scram & (SCRAM_TAP1 << 1)) - st->scram ^= SCRAM_TAPN << 1; - st->tx_bit = (st->tx_bit << 1) | (!!(st->scram & (SCRAM_TAP1 << 2))); - st->txtbl = fsk96_txfilt_5 + (st->tx_bit & 0xff); - } - if (st->txphase >= 5) - st->txphase = 0; - *buf++ = ((*st->txtbl)-0x80)<<8; - st->txtbl += 0x100; - } -} - -/* --------------------------------------------------------------------- */ - -static void demodulator_9600_5_u8(struct sm_state *sm, const unsigned char *buf, unsigned int buflen) -{ - struct demod_state_fsk96 *st = (struct demod_state_fsk96 *)(&sm->d); - static const int pll_corr[2] = { -0x1000, 0x1000 }; - unsigned char curbit; - unsigned int descx; - - for (; buflen > 0; buflen--, buf++) { - st->dcd_shreg <<= 1; - st->bit_pll += 0x3333; - curbit = (*buf >= 0x80); - if (st->last_sample ^ curbit) { - st->dcd_shreg |= 1; - st->bit_pll += pll_corr[st->bit_pll < 0x9999]; - st->dcd_sum0 += 16 * hweight8(st->dcd_shreg & 0x0c) - - hweight8(st->dcd_shreg & 0x70); - } - st->last_sample = curbit; - hdlcdrv_channelbit(&sm->hdrv, st->last_sample); - if ((--st->dcd_time) <= 0) { - hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + - st->dcd_sum1 + - st->dcd_sum2) < 0); - st->dcd_sum2 = st->dcd_sum1; - st->dcd_sum1 = st->dcd_sum0; - st->dcd_sum0 = 2; /* slight bias */ - st->dcd_time = 240; - } - if (st->bit_pll >= 0x10000) { - st->bit_pll &= 0xffff; - st->descram = (st->descram << 1) | curbit; - descx = st->descram ^ (st->descram >> 1); - descx ^= ((descx >> DESCRAM_TAPSH1) ^ - (descx >> DESCRAM_TAPSH2)); - st->shreg >>= 1; - st->shreg |= (!(descx & 1)) << 16; - if (st->shreg & 1) { - hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1); - st->shreg = 0x10000; - } - diag_trigger(sm); - } - diag_add_one(sm, ((short)(*buf - 0x80)) << 8); - } -} - -/* --------------------------------------------------------------------- */ - -static void demodulator_9600_5_s16(struct sm_state *sm, const short *buf, unsigned int buflen) -{ - struct demod_state_fsk96 *st = (struct demod_state_fsk96 *)(&sm->d); - static const int pll_corr[2] = { -0x1000, 0x1000 }; - unsigned char curbit; - unsigned int descx; - - for (; buflen > 0; buflen--, buf++) { - st->dcd_shreg <<= 1; - st->bit_pll += 0x3333; - curbit = (*buf >= 0); - if (st->last_sample ^ curbit) { - st->dcd_shreg |= 1; - st->bit_pll += pll_corr[st->bit_pll < 0x9999]; - st->dcd_sum0 += 16 * hweight8(st->dcd_shreg & 0x0c) - - hweight8(st->dcd_shreg & 0x70); - } - st->last_sample = curbit; - hdlcdrv_channelbit(&sm->hdrv, st->last_sample); - if ((--st->dcd_time) <= 0) { - hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + - st->dcd_sum1 + - st->dcd_sum2) < 0); - st->dcd_sum2 = st->dcd_sum1; - st->dcd_sum1 = st->dcd_sum0; - st->dcd_sum0 = 2; /* slight bias */ - st->dcd_time = 240; - } - if (st->bit_pll >= 0x10000) { - st->bit_pll &= 0xffff; - st->descram = (st->descram << 1) | curbit; - descx = st->descram ^ (st->descram >> 1); - descx ^= ((descx >> DESCRAM_TAPSH1) ^ - (descx >> DESCRAM_TAPSH2)); - st->shreg >>= 1; - st->shreg |= (!(descx & 1)) << 16; - if (st->shreg & 1) { - hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1); - st->shreg = 0x10000; - } - diag_trigger(sm); - } - diag_add_one(sm, *buf); - } -} - -/* --------------------------------------------------------------------- */ - -static void demod_init_9600(struct sm_state *sm) -{ - struct demod_state_fsk96 *st = (struct demod_state_fsk96 *)(&sm->d); - - st->dcd_time = 240; - st->dcd_sum0 = 2; -} - -/* --------------------------------------------------------------------- */ - -const struct modem_tx_info sm_fsk9600_4_tx = { - "fsk9600", sizeof(struct mod_state_fsk96), 38400, 9600, - modulator_9600_4_u8, modulator_9600_4_s16, NULL -}; - -const struct modem_rx_info sm_fsk9600_4_rx = { - "fsk9600", sizeof(struct demod_state_fsk96), 38400, 9600, 1, 4, - demodulator_9600_4_u8, demodulator_9600_4_s16, demod_init_9600 -}; - -/* --------------------------------------------------------------------- */ - -const struct modem_tx_info sm_fsk9600_5_tx = { - "fsk9600", sizeof(struct mod_state_fsk96), 48000, 9600, - modulator_9600_5_u8, modulator_9600_5_s16, NULL -}; - -const struct modem_rx_info sm_fsk9600_5_rx = { - "fsk9600", sizeof(struct demod_state_fsk96), 48000, 9600, 1, 5, - demodulator_9600_5_u8, demodulator_9600_5_s16, demod_init_9600 -}; - -/* --------------------------------------------------------------------- */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/net/hamradio/soundmodem/sm.h linux.2.5.47-ac4/drivers/net/hamradio/soundmodem/sm.h --- linux.2.5.47/drivers/net/hamradio/soundmodem/sm.h 2002-10-31 14:57:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/net/hamradio/soundmodem/sm.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,383 +0,0 @@ -/*****************************************************************************/ - -/* - * sm.h -- soundcard radio modem driver internal header. - * - * Copyright (C) 1996-1999 Thomas Sailer (sailer@ife.ee.ethz.ch) - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Please note that the GPL allows you to use the driver, NOT the radio. - * In order to use the radio, you need a license from the communications - * authority of your country. - * - */ - -#ifndef _SM_H -#define _SM_H - -/* ---------------------------------------------------------------------- */ - -#include -#include -#include -#include -#include - -#define SM_DEBUG - -/* ---------------------------------------------------------------------- */ -/* - * Information that need to be kept for each board. - */ - -struct sm_state { - struct hdlcdrv_state hdrv; - - const struct modem_tx_info *mode_tx; - const struct modem_rx_info *mode_rx; - - const struct hardware_info *hwdrv; - - struct pardevice *pardev; - - /* - * Hardware (soundcard) access routines state - */ - struct { - void *ibuf; - unsigned int ifragsz; - unsigned int ifragptr; - unsigned int i16bit; - void *obuf; - unsigned int ofragsz; - unsigned int ofragptr; - unsigned int o16bit; - int ptt_cnt; - } dma; - - union { - long hw[32/sizeof(long)]; - } hw; - - /* - * state of the modem code - */ - union { - long m[48/sizeof(long)]; - } m; - union { - long d[256/sizeof(long)]; - } d; - -#define DIAGDATALEN 64 - struct diag_data { - unsigned int mode; - unsigned int flags; - volatile int ptr; - short data[DIAGDATALEN]; - } diag; - - -#ifdef SM_DEBUG - struct debug_vals { - unsigned long last_jiffies; - unsigned cur_intcnt; - unsigned last_intcnt; - unsigned mod_cyc; - unsigned demod_cyc; - unsigned dma_residue; - } debug_vals; -#endif /* SM_DEBUG */ -}; - -/* ---------------------------------------------------------------------- */ -/* - * Mode definition structure - */ - -struct modem_tx_info { - const char *name; - unsigned int loc_storage; - int srate; - int bitrate; - void (*modulator_u8)(struct sm_state *, unsigned char *, unsigned int); - void (*modulator_s16)(struct sm_state *, short *, unsigned int); - void (*init)(struct sm_state *); -}; - -struct modem_rx_info { - const char *name; - unsigned int loc_storage; - int srate; - int bitrate; - unsigned int overlap; - unsigned int sperbit; - void (*demodulator_u8)(struct sm_state *, const unsigned char *, unsigned int); - void (*demodulator_s16)(struct sm_state *, const short *, unsigned int); - void (*init)(struct sm_state *); -}; - -/* ---------------------------------------------------------------------- */ -/* - * Soundcard driver definition structure - */ - -struct hardware_info { - char *hw_name; /* used for request_{region,irq,dma} */ - unsigned int loc_storage; - /* - * mode specific open/close - */ - int (*open)(struct net_device *, struct sm_state *); - int (*close)(struct net_device *, struct sm_state *); - int (*ioctl)(struct net_device *, struct sm_state *, struct ifreq *, - struct hdlcdrv_ioctl *, int); - int (*sethw)(struct net_device *, struct sm_state *, char *); -}; - -/* --------------------------------------------------------------------- */ - -extern const char sm_drvname[]; -extern const char sm_drvinfo[]; - -/* --------------------------------------------------------------------- */ -/* - * ===================== diagnostics stuff =============================== - */ - -static inline void diag_trigger(struct sm_state *sm) -{ - if (sm->diag.ptr < 0) - if (!(sm->diag.flags & SM_DIAGFLAG_DCDGATE) || sm->hdrv.hdlcrx.dcd) - sm->diag.ptr = 0; -} - -/* --------------------------------------------------------------------- */ - -#define SHRT_MAX ((short)(((unsigned short)(~0U))>>1)) -#define SHRT_MIN (-SHRT_MAX-1) - -static inline void diag_add(struct sm_state *sm, int valinp, int valdemod) -{ - int val; - - if ((sm->diag.mode != SM_DIAGMODE_INPUT && - sm->diag.mode != SM_DIAGMODE_DEMOD) || - sm->diag.ptr >= DIAGDATALEN || sm->diag.ptr < 0) - return; - val = (sm->diag.mode == SM_DIAGMODE_DEMOD) ? valdemod : valinp; - /* clip */ - if (val > SHRT_MAX) - val = SHRT_MAX; - if (val < SHRT_MIN) - val = SHRT_MIN; - sm->diag.data[sm->diag.ptr++] = val; -} - -/* --------------------------------------------------------------------- */ - -static inline void diag_add_one(struct sm_state *sm, int val) -{ - if ((sm->diag.mode != SM_DIAGMODE_INPUT && - sm->diag.mode != SM_DIAGMODE_DEMOD) || - sm->diag.ptr >= DIAGDATALEN || sm->diag.ptr < 0) - return; - /* clip */ - if (val > SHRT_MAX) - val = SHRT_MAX; - if (val < SHRT_MIN) - val = SHRT_MIN; - sm->diag.data[sm->diag.ptr++] = val; -} - -/* --------------------------------------------------------------------- */ - -static inline void diag_add_constellation(struct sm_state *sm, int vali, int valq) -{ - if ((sm->diag.mode != SM_DIAGMODE_CONSTELLATION) || - sm->diag.ptr >= DIAGDATALEN-1 || sm->diag.ptr < 0) - return; - /* clip */ - if (vali > SHRT_MAX) - vali = SHRT_MAX; - if (vali < SHRT_MIN) - vali = SHRT_MIN; - if (valq > SHRT_MAX) - valq = SHRT_MAX; - if (valq < SHRT_MIN) - valq = SHRT_MIN; - sm->diag.data[sm->diag.ptr++] = vali; - sm->diag.data[sm->diag.ptr++] = valq; -} - -/* --------------------------------------------------------------------- */ -/* - * ===================== utility functions =============================== - */ - -#if 0 -static inline unsigned int hweight32(unsigned int w) - __attribute__ ((unused)); -static inline unsigned int hweight16(unsigned short w) - __attribute__ ((unused)); -static inline unsigned int hweight8(unsigned char w) - __attribute__ ((unused)); - -static inline unsigned int hweight32(unsigned int w) -{ - unsigned int res = (w & 0x55555555) + ((w >> 1) & 0x55555555); - res = (res & 0x33333333) + ((res >> 2) & 0x33333333); - res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F); - res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF); - return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF); -} - -static inline unsigned int hweight16(unsigned short w) -{ - unsigned short res = (w & 0x5555) + ((w >> 1) & 0x5555); - res = (res & 0x3333) + ((res >> 2) & 0x3333); - res = (res & 0x0F0F) + ((res >> 4) & 0x0F0F); - return (res & 0x00FF) + ((res >> 8) & 0x00FF); -} - -static inline unsigned int hweight8(unsigned char w) -{ - unsigned short res = (w & 0x55) + ((w >> 1) & 0x55); - res = (res & 0x33) + ((res >> 2) & 0x33); - return (res & 0x0F) + ((res >> 4) & 0x0F); -} - -#endif - -static inline unsigned int gcd(unsigned int x, unsigned int y) - __attribute__ ((unused)); -static inline unsigned int lcm(unsigned int x, unsigned int y) - __attribute__ ((unused)); - -static inline unsigned int gcd(unsigned int x, unsigned int y) -{ - for (;;) { - if (!x) - return y; - if (!y) - return x; - if (x > y) - x %= y; - else - y %= x; - } -} - -static inline unsigned int lcm(unsigned int x, unsigned int y) -{ - return x * y / gcd(x, y); -} - -/* --------------------------------------------------------------------- */ -/* - * ===================== profiling ======================================= - */ - - -#ifdef __i386__ - -#include - -/* - * only do 32bit cycle counter arithmetic; we hope we won't overflow. - * in fact, overflowing modems would require over 2THz CPU clock speeds :-) - */ - -#define time_exec(var,cmd) \ -({ \ - if (cpu_has_tsc) { \ - unsigned int cnt1, cnt2; \ - rdtscl(cnt1); \ - cmd; \ - rdtscl(cnt2); \ - var = cnt2-cnt1; \ - } else { \ - cmd; \ - } \ -}) - -#else /* __i386__ */ - -#define time_exec(var,cmd) cmd - -#endif /* __i386__ */ - -/* --------------------------------------------------------------------- */ - -extern const struct modem_tx_info sm_afsk1200_tx; -extern const struct modem_tx_info sm_afsk2400_7_tx; -extern const struct modem_tx_info sm_afsk2400_8_tx; -extern const struct modem_tx_info sm_afsk2666_tx; -extern const struct modem_tx_info sm_psk4800_tx; -extern const struct modem_tx_info sm_hapn4800_8_tx; -extern const struct modem_tx_info sm_hapn4800_10_tx; -extern const struct modem_tx_info sm_hapn4800_pm8_tx; -extern const struct modem_tx_info sm_hapn4800_pm10_tx; -extern const struct modem_tx_info sm_fsk9600_4_tx; -extern const struct modem_tx_info sm_fsk9600_5_tx; - -extern const struct modem_rx_info sm_afsk1200_rx; -extern const struct modem_rx_info sm_afsk2400_7_rx; -extern const struct modem_rx_info sm_afsk2400_8_rx; -extern const struct modem_rx_info sm_afsk2666_rx; -extern const struct modem_rx_info sm_psk4800_rx; -extern const struct modem_rx_info sm_hapn4800_8_rx; -extern const struct modem_rx_info sm_hapn4800_10_rx; -extern const struct modem_rx_info sm_hapn4800_pm8_rx; -extern const struct modem_rx_info sm_hapn4800_pm10_rx; -extern const struct modem_rx_info sm_fsk9600_4_rx; -extern const struct modem_rx_info sm_fsk9600_5_rx; - -extern const struct hardware_info sm_hw_sbc; -extern const struct hardware_info sm_hw_sbcfdx; -extern const struct hardware_info sm_hw_wss; -extern const struct hardware_info sm_hw_wssfdx; - -extern const struct modem_tx_info *sm_modem_tx_table[]; -extern const struct modem_rx_info *sm_modem_rx_table[]; -extern const struct hardware_info *sm_hardware_table[]; - -/* --------------------------------------------------------------------- */ - -void sm_output_status(struct sm_state *sm); -/*void sm_output_open(struct sm_state *sm);*/ -/*void sm_output_close(struct sm_state *sm);*/ - -/* --------------------------------------------------------------------- */ - -extern void inline sm_int_freq(struct sm_state *sm) -{ -#ifdef SM_DEBUG - unsigned long cur_jiffies = jiffies; - /* - * measure the interrupt frequency - */ - sm->debug_vals.cur_intcnt++; - if ((cur_jiffies - sm->debug_vals.last_jiffies) >= HZ) { - sm->debug_vals.last_jiffies = cur_jiffies; - sm->debug_vals.last_intcnt = sm->debug_vals.cur_intcnt; - sm->debug_vals.cur_intcnt = 0; - } -#endif /* SM_DEBUG */ -} - -/* --------------------------------------------------------------------- */ -#endif /* _SM_H */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/net/hamradio/soundmodem/sm_hapn4800.c linux.2.5.47-ac4/drivers/net/hamradio/soundmodem/sm_hapn4800.c --- linux.2.5.47/drivers/net/hamradio/soundmodem/sm_hapn4800.c 2002-10-31 14:57:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/net/hamradio/soundmodem/sm_hapn4800.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,560 +0,0 @@ -/*****************************************************************************/ - -/* - * sm_hapn4800.c -- soundcard radio modem driver, 4800 baud HAPN modem - * - * Copyright (C) 1996 Thomas Sailer (sailer@ife.ee.ethz.ch) - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Please note that the GPL allows you to use the driver, NOT the radio. - * In order to use the radio, you need a license from the communications - * authority of your country. - * - * - * This module implements a (hopefully) HAPN (Hamilton Area Packet - * Network) compatible 4800 baud modem. - * The HAPN modem uses kind of "duobinary signalling" (not really, - * duobinary signalling gives ... 0 0 -1 0 1 0 0 ... at the sampling - * instants, whereas HAPN signalling gives ... 0 0 -1 1 0 0 ..., see - * Proakis, Digital Communications). - * The code is untested. It is compatible with itself (i.e. it can decode - * the packets it sent), but I could not test if it is compatible with - * any "real" HAPN modem, since noone uses it in my region of the world. - * Feedback therefore welcome. - */ - -#include "sm.h" -#include "sm_tbl_hapn4800.h" - -/* --------------------------------------------------------------------- */ - -struct demod_state_hapn48 { - unsigned int shreg; - unsigned int bit_pll; - unsigned char last_bit; - unsigned char last_bit2; - unsigned int dcd_shreg; - int dcd_sum0, dcd_sum1, dcd_sum2; - unsigned int dcd_time; - int lvlhi, lvllo; -}; - -struct mod_state_hapn48 { - unsigned int shreg; - unsigned char tx_bit; - unsigned int tx_seq; - const unsigned char *tbl; -}; - -/* --------------------------------------------------------------------- */ - -static void modulator_hapn4800_10_u8(struct sm_state *sm, unsigned char *buf, unsigned int buflen) -{ - struct mod_state_hapn48 *st = (struct mod_state_hapn48 *)(&sm->m); - - for (; buflen > 0; buflen--, buf++) { - if (!st->tx_seq++) { - if (st->shreg <= 1) - st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; - st->tx_bit = ((st->tx_bit << 1) | - (st->tx_bit & 1)); - st->tx_bit ^= (!(st->shreg & 1)); - st->shreg >>= 1; - st->tbl = hapn48_txfilt_10 + (st->tx_bit & 0xf); - } - if (st->tx_seq >= 10) - st->tx_seq = 0; - *buf = *st->tbl; - st->tbl += 0x10; - } -} - -/* --------------------------------------------------------------------- */ - -static void modulator_hapn4800_10_s16(struct sm_state *sm, short *buf, unsigned int buflen) -{ - struct mod_state_hapn48 *st = (struct mod_state_hapn48 *)(&sm->m); - - for (; buflen > 0; buflen--, buf++) { - if (!st->tx_seq++) { - if (st->shreg <= 1) - st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; - st->tx_bit = ((st->tx_bit << 1) | - (st->tx_bit & 1)); - st->tx_bit ^= (!(st->shreg & 1)); - st->shreg >>= 1; - st->tbl = hapn48_txfilt_10 + (st->tx_bit & 0xf); - } - if (st->tx_seq >= 10) - st->tx_seq = 0; - *buf = ((*st->tbl)-0x80)<<8; - st->tbl += 0x10; - } -} - -/* --------------------------------------------------------------------- */ - -static void modulator_hapn4800_8_u8(struct sm_state *sm, unsigned char *buf, unsigned int buflen) -{ - struct mod_state_hapn48 *st = (struct mod_state_hapn48 *)(&sm->m); - - for (; buflen > 0; buflen--, buf++) { - if (!st->tx_seq++) { - if (st->shreg <= 1) - st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; - st->tx_bit = (st->tx_bit << 1) | (st->tx_bit & 1); - st->tx_bit ^= !(st->shreg & 1); - st->shreg >>= 1; - st->tbl = hapn48_txfilt_8 + (st->tx_bit & 0xf); - } - if (st->tx_seq >= 8) - st->tx_seq = 0; - *buf = *st->tbl; - st->tbl += 0x10; - } -} - -/* --------------------------------------------------------------------- */ - -static void modulator_hapn4800_8_s16(struct sm_state *sm, short *buf, unsigned int buflen) -{ - struct mod_state_hapn48 *st = (struct mod_state_hapn48 *)(&sm->m); - - for (; buflen > 0; buflen--, buf++) { - if (!st->tx_seq++) { - if (st->shreg <= 1) - st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; - st->tx_bit = (st->tx_bit << 1) | (st->tx_bit & 1); - st->tx_bit ^= !(st->shreg & 1); - st->shreg >>= 1; - st->tbl = hapn48_txfilt_8 + (st->tx_bit & 0xf); - } - if (st->tx_seq >= 8) - st->tx_seq = 0; - *buf = ((*st->tbl)-0x80)<<8; - st->tbl += 0x10; - } -} - -/* --------------------------------------------------------------------- */ - -static void modulator_hapn4800_pm10_u8(struct sm_state *sm, unsigned char *buf, unsigned int buflen) -{ - struct mod_state_hapn48 *st = (struct mod_state_hapn48 *)(&sm->m); - - for (; buflen > 0; buflen--, buf++) { - if (!st->tx_seq++) { - if (st->shreg <= 1) - st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; - st->tx_bit = ((st->tx_bit << 1) | - (st->tx_bit & 1)); - st->tx_bit ^= (!(st->shreg & 1)); - st->shreg >>= 1; - st->tbl = hapn48_txfilt_pm10 + (st->tx_bit & 0xf); - } - if (st->tx_seq >= 10) - st->tx_seq = 0; - *buf = *st->tbl; - st->tbl += 0x10; - } -} - -/* --------------------------------------------------------------------- */ - -static void modulator_hapn4800_pm10_s16(struct sm_state *sm, short *buf, unsigned int buflen) -{ - struct mod_state_hapn48 *st = (struct mod_state_hapn48 *)(&sm->m); - - for (; buflen > 0; buflen--, buf++) { - if (!st->tx_seq++) { - if (st->shreg <= 1) - st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; - st->tx_bit = ((st->tx_bit << 1) | - (st->tx_bit & 1)); - st->tx_bit ^= (!(st->shreg & 1)); - st->shreg >>= 1; - st->tbl = hapn48_txfilt_pm10 + (st->tx_bit & 0xf); - } - if (st->tx_seq >= 10) - st->tx_seq = 0; - *buf = ((*st->tbl)-0x80)<<8; - st->tbl += 0x10; - } -} - -/* --------------------------------------------------------------------- */ - -static void modulator_hapn4800_pm8_u8(struct sm_state *sm, unsigned char *buf, unsigned int buflen) -{ - struct mod_state_hapn48 *st = (struct mod_state_hapn48 *)(&sm->m); - - for (; buflen > 0; buflen--, buf++) { - if (!st->tx_seq++) { - if (st->shreg <= 1) - st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; - st->tx_bit = (st->tx_bit << 1) | (st->tx_bit & 1); - st->tx_bit ^= !(st->shreg & 1); - st->shreg >>= 1; - st->tbl = hapn48_txfilt_pm8 + (st->tx_bit & 0xf); - } - if (st->tx_seq >= 8) - st->tx_seq = 0; - *buf = *st->tbl; - st->tbl += 0x10; - } -} - -/* --------------------------------------------------------------------- */ - -static void modulator_hapn4800_pm8_s16(struct sm_state *sm, short *buf, unsigned int buflen) -{ - struct mod_state_hapn48 *st = (struct mod_state_hapn48 *)(&sm->m); - - for (; buflen > 0; buflen--, buf++) { - if (!st->tx_seq++) { - if (st->shreg <= 1) - st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; - st->tx_bit = (st->tx_bit << 1) | (st->tx_bit & 1); - st->tx_bit ^= !(st->shreg & 1); - st->shreg >>= 1; - st->tbl = hapn48_txfilt_pm8 + (st->tx_bit & 0xf); - } - if (st->tx_seq >= 8) - st->tx_seq = 0; - *buf = ((*st->tbl)-0x80)<<8; - st->tbl += 0x10; - } -} - -/* --------------------------------------------------------------------- */ - -static void demodulator_hapn4800_10_u8(struct sm_state *sm, const unsigned char *buf, unsigned int buflen) -{ - struct demod_state_hapn48 *st = (struct demod_state_hapn48 *)(&sm->d); - static const int pll_corr[2] = { -0x800, 0x800 }; - int curst, cursync; - int inv; - - for (; buflen > 0; buflen--, buf++) { - inv = ((int)(buf[-2])-0x80) << 8; - st->lvlhi = (st->lvlhi * 65309) >> 16; /* decay */ - st->lvllo = (st->lvllo * 65309) >> 16; /* decay */ - if (inv > st->lvlhi) - st->lvlhi = inv; - if (inv < st->lvllo) - st->lvllo = inv; - if (buflen & 1) - st->dcd_shreg <<= 1; - st->bit_pll += 0x199a; - curst = cursync = 0; - if (inv > st->lvlhi >> 1) { - curst = 1; - cursync = (buf[-2] > buf[-1] && buf[-2] > buf[-3] && - buf[-2] > buf[-0] && buf[-2] > buf[-4]); - } else if (inv < st->lvllo >> 1) { - curst = -1; - cursync = (buf[-2] < buf[-1] && buf[-2] < buf[-3] && - buf[-2] < buf[-0] && buf[-2] < buf[-4]); - } - if (cursync) { - st->dcd_shreg |= cursync; - st->bit_pll += pll_corr[((st->bit_pll - 0x8000u) & 0xffffu) < 0x8ccdu]; - st->dcd_sum0 += 16 * hweight32(st->dcd_shreg & 0x18c6318c) - - hweight32(st->dcd_shreg & 0xe739ce70); - } - hdlcdrv_channelbit(&sm->hdrv, cursync); - if ((--st->dcd_time) <= 0) { - hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + - st->dcd_sum1 + - st->dcd_sum2) < 0); - st->dcd_sum2 = st->dcd_sum1; - st->dcd_sum1 = st->dcd_sum0; - st->dcd_sum0 = 2; /* slight bias */ - st->dcd_time = 240; - } - if (st->bit_pll >= 0x10000) { - st->bit_pll &= 0xffff; - st->last_bit2 = st->last_bit; - if (curst < 0) - st->last_bit = 0; - else if (curst > 0) - st->last_bit = 1; - st->shreg >>= 1; - st->shreg |= ((st->last_bit ^ st->last_bit2 ^ 1) & 1) << 16; - if (st->shreg & 1) { - hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1); - st->shreg = 0x10000; - } - diag_trigger(sm); - } - diag_add_one(sm, inv); - } -} - -/* --------------------------------------------------------------------- */ - -static void demodulator_hapn4800_10_s16(struct sm_state *sm, const short *buf, unsigned int buflen) -{ - struct demod_state_hapn48 *st = (struct demod_state_hapn48 *)(&sm->d); - static const int pll_corr[2] = { -0x800, 0x800 }; - int curst, cursync; - int inv; - - for (; buflen > 0; buflen--, buf++) { - inv = buf[-2]; - st->lvlhi = (st->lvlhi * 65309) >> 16; /* decay */ - st->lvllo = (st->lvllo * 65309) >> 16; /* decay */ - if (inv > st->lvlhi) - st->lvlhi = inv; - if (inv < st->lvllo) - st->lvllo = inv; - if (buflen & 1) - st->dcd_shreg <<= 1; - st->bit_pll += 0x199a; - curst = cursync = 0; - if (inv > st->lvlhi >> 1) { - curst = 1; - cursync = (buf[-2] > buf[-1] && buf[-2] > buf[-3] && - buf[-2] > buf[-0] && buf[-2] > buf[-4]); - } else if (inv < st->lvllo >> 1) { - curst = -1; - cursync = (buf[-2] < buf[-1] && buf[-2] < buf[-3] && - buf[-2] < buf[-0] && buf[-2] < buf[-4]); - } - if (cursync) { - st->dcd_shreg |= cursync; - st->bit_pll += pll_corr[((st->bit_pll - 0x8000u) & 0xffffu) < 0x8ccdu]; - st->dcd_sum0 += 16 * hweight32(st->dcd_shreg & 0x18c6318c) - - hweight32(st->dcd_shreg & 0xe739ce70); - } - hdlcdrv_channelbit(&sm->hdrv, cursync); - if ((--st->dcd_time) <= 0) { - hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + - st->dcd_sum1 + - st->dcd_sum2) < 0); - st->dcd_sum2 = st->dcd_sum1; - st->dcd_sum1 = st->dcd_sum0; - st->dcd_sum0 = 2; /* slight bias */ - st->dcd_time = 240; - } - if (st->bit_pll >= 0x10000) { - st->bit_pll &= 0xffff; - st->last_bit2 = st->last_bit; - if (curst < 0) - st->last_bit = 0; - else if (curst > 0) - st->last_bit = 1; - st->shreg >>= 1; - st->shreg |= ((st->last_bit ^ st->last_bit2 ^ 1) & 1) << 16; - if (st->shreg & 1) { - hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1); - st->shreg = 0x10000; - } - diag_trigger(sm); - } - diag_add_one(sm, inv); - } -} - -/* --------------------------------------------------------------------- */ - -static void demodulator_hapn4800_8_u8(struct sm_state *sm, const unsigned char *buf, unsigned int buflen) -{ - struct demod_state_hapn48 *st = (struct demod_state_hapn48 *)(&sm->d); - static const int pll_corr[2] = { -0x800, 0x800 }; - int curst, cursync; - int inv; - - for (; buflen > 0; buflen--, buf++) { - inv = ((int)(buf[-2])-0x80) << 8; - st->lvlhi = (st->lvlhi * 65309) >> 16; /* decay */ - st->lvllo = (st->lvllo * 65309) >> 16; /* decay */ - if (inv > st->lvlhi) - st->lvlhi = inv; - if (inv < st->lvllo) - st->lvllo = inv; - if (buflen & 1) - st->dcd_shreg <<= 1; - st->bit_pll += 0x2000; - curst = cursync = 0; - if (inv > st->lvlhi >> 1) { - curst = 1; - cursync = (buf[-2] > buf[-1] && buf[-2] > buf[-3] && - buf[-2] > buf[-0] && buf[-2] > buf[-4]); - } else if (inv < st->lvllo >> 1) { - curst = -1; - cursync = (buf[-2] < buf[-1] && buf[-2] < buf[-3] && - buf[-2] < buf[-0] && buf[-2] < buf[-4]); - } - if (cursync) { - st->dcd_shreg |= cursync; - st->bit_pll += pll_corr[((st->bit_pll - 0x8000u) & 0xffffu) < 0x9000u]; - st->dcd_sum0 += 16 * hweight32(st->dcd_shreg & 0x44444444) - - hweight32(st->dcd_shreg & 0xbbbbbbbb); - } - hdlcdrv_channelbit(&sm->hdrv, cursync); - if ((--st->dcd_time) <= 0) { - hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + - st->dcd_sum1 + - st->dcd_sum2) < 0); - st->dcd_sum2 = st->dcd_sum1; - st->dcd_sum1 = st->dcd_sum0; - st->dcd_sum0 = 2; /* slight bias */ - st->dcd_time = 240; - } - if (st->bit_pll >= 0x10000) { - st->bit_pll &= 0xffff; - st->last_bit2 = st->last_bit; - if (curst < 0) - st->last_bit = 0; - else if (curst > 0) - st->last_bit = 1; - st->shreg >>= 1; - st->shreg |= ((st->last_bit ^ st->last_bit2 ^ 1) & 1) << 16; - if (st->shreg & 1) { - hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1); - st->shreg = 0x10000; - } - diag_trigger(sm); - } - diag_add_one(sm, inv); - } -} - -/* --------------------------------------------------------------------- */ - -static void demodulator_hapn4800_8_s16(struct sm_state *sm, const short *buf, unsigned int buflen) -{ - struct demod_state_hapn48 *st = (struct demod_state_hapn48 *)(&sm->d); - static const int pll_corr[2] = { -0x800, 0x800 }; - int curst, cursync; - int inv; - - for (; buflen > 0; buflen--, buf++) { - inv = buf[-2]; - st->lvlhi = (st->lvlhi * 65309) >> 16; /* decay */ - st->lvllo = (st->lvllo * 65309) >> 16; /* decay */ - if (inv > st->lvlhi) - st->lvlhi = inv; - if (inv < st->lvllo) - st->lvllo = inv; - if (buflen & 1) - st->dcd_shreg <<= 1; - st->bit_pll += 0x2000; - curst = cursync = 0; - if (inv > st->lvlhi >> 1) { - curst = 1; - cursync = (buf[-2] > buf[-1] && buf[-2] > buf[-3] && - buf[-2] > buf[-0] && buf[-2] > buf[-4]); - } else if (inv < st->lvllo >> 1) { - curst = -1; - cursync = (buf[-2] < buf[-1] && buf[-2] < buf[-3] && - buf[-2] < buf[-0] && buf[-2] < buf[-4]); - } - if (cursync) { - st->dcd_shreg |= cursync; - st->bit_pll += pll_corr[((st->bit_pll - 0x8000u) & 0xffffu) < 0x9000u]; - st->dcd_sum0 += 16 * hweight32(st->dcd_shreg & 0x44444444) - - hweight32(st->dcd_shreg & 0xbbbbbbbb); - } - hdlcdrv_channelbit(&sm->hdrv, cursync); - if ((--st->dcd_time) <= 0) { - hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + - st->dcd_sum1 + - st->dcd_sum2) < 0); - st->dcd_sum2 = st->dcd_sum1; - st->dcd_sum1 = st->dcd_sum0; - st->dcd_sum0 = 2; /* slight bias */ - st->dcd_time = 240; - } - if (st->bit_pll >= 0x10000) { - st->bit_pll &= 0xffff; - st->last_bit2 = st->last_bit; - if (curst < 0) - st->last_bit = 0; - else if (curst > 0) - st->last_bit = 1; - st->shreg >>= 1; - st->shreg |= ((st->last_bit ^ st->last_bit2 ^ 1) & 1) << 16; - if (st->shreg & 1) { - hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1); - st->shreg = 0x10000; - } - diag_trigger(sm); - } - diag_add_one(sm, inv); - } -} - -/* --------------------------------------------------------------------- */ - -static void demod_init_hapn4800(struct sm_state *sm) -{ - struct demod_state_hapn48 *st = (struct demod_state_hapn48 *)(&sm->d); - - st->dcd_time = 120; - st->dcd_sum0 = 2; -} - -/* --------------------------------------------------------------------- */ - -const struct modem_tx_info sm_hapn4800_8_tx = { - "hapn4800", sizeof(struct mod_state_hapn48), 38400, 4800, - modulator_hapn4800_8_u8, modulator_hapn4800_8_s16, NULL -}; - -const struct modem_rx_info sm_hapn4800_8_rx = { - "hapn4800", sizeof(struct demod_state_hapn48), 38400, 4800, 5, 8, - demodulator_hapn4800_8_u8, demodulator_hapn4800_8_s16, demod_init_hapn4800 -}; - -/* --------------------------------------------------------------------- */ - -const struct modem_tx_info sm_hapn4800_10_tx = { - "hapn4800", sizeof(struct mod_state_hapn48), 48000, 4800, - modulator_hapn4800_10_u8, modulator_hapn4800_10_s16, NULL -}; - -const struct modem_rx_info sm_hapn4800_10_rx = { - "hapn4800", sizeof(struct demod_state_hapn48), 48000, 4800, 5, 10, - demodulator_hapn4800_10_u8, demodulator_hapn4800_10_s16, demod_init_hapn4800 -}; - -/* --------------------------------------------------------------------- */ - -const struct modem_tx_info sm_hapn4800_pm8_tx = { - "hapn4800pm", sizeof(struct mod_state_hapn48), 38400, 4800, - modulator_hapn4800_pm8_u8, modulator_hapn4800_pm8_s16, NULL -}; - -const struct modem_rx_info sm_hapn4800_pm8_rx = { - "hapn4800pm", sizeof(struct demod_state_hapn48), 38400, 4800, 5, 8, - demodulator_hapn4800_8_u8, demodulator_hapn4800_8_s16, demod_init_hapn4800 -}; - -/* --------------------------------------------------------------------- */ - -const struct modem_tx_info sm_hapn4800_pm10_tx = { - "hapn4800pm", sizeof(struct mod_state_hapn48), 48000, 4800, - modulator_hapn4800_pm10_u8, modulator_hapn4800_pm10_s16, NULL -}; - -const struct modem_rx_info sm_hapn4800_pm10_rx = { - "hapn4800pm", sizeof(struct demod_state_hapn48), 48000, 4800, 5, 10, - demodulator_hapn4800_10_u8, demodulator_hapn4800_10_s16, demod_init_hapn4800 -}; - -/* --------------------------------------------------------------------- */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/net/hamradio/soundmodem/sm_psk4800.c linux.2.5.47-ac4/drivers/net/hamradio/soundmodem/sm_psk4800.c --- linux.2.5.47/drivers/net/hamradio/soundmodem/sm_psk4800.c 2002-10-31 14:57:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/net/hamradio/soundmodem/sm_psk4800.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,418 +0,0 @@ -/*****************************************************************************/ - -/* - * sm_psk4800.c -- soundcard radio modem driver, 4800 baud 8PSK modem - * - * Copyright (C) 1997 Thomas Sailer (sailer@ife.ee.ethz.ch) - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Please note that the GPL allows you to use the driver, NOT the radio. - * In order to use the radio, you need a license from the communications - * authority of your country. - * - */ - -#include "sm.h" -#include "sm_tbl_psk4800.h" - -/* --------------------------------------------------------------------- */ - -#define DESCRAM_TAP1 0x20000 -#define DESCRAM_TAP2 0x01000 -#define DESCRAM_TAP3 0x00001 - -#define DESCRAM_TAPSH1 17 -#define DESCRAM_TAPSH2 12 -#define DESCRAM_TAPSH3 0 - -#define SCRAM_TAP1 0x20000 /* X^17 */ -#define SCRAM_TAPN 0x00021 /* X^0+X^5 */ - -#define SCRAM_SHIFT 17 - -/* --------------------------------------------------------------------- */ - -struct demod_state_psk48 { - /* - * input mixer and lowpass - */ - short infi[PSK48_RXF_LEN/2], infq[PSK48_RXF_LEN/2]; - unsigned int downmixer; - int ovrphase; - short magi, magq; - /* - * sampling instant recovery - */ - int pwrhist[5]; - unsigned int s_phase; - int cur_sync; - /* - * phase recovery - */ - short cur_phase_dev; - short last_ph_err; - unsigned short pskph; - unsigned int phase; - unsigned short last_pskph; - unsigned char cur_raw, last_raw, rawbits; - /* - * decoding - */ - unsigned int shreg; - unsigned long descram; - unsigned int bit_pll; - unsigned char last_sample; - unsigned int dcd_shreg; - int dcd_sum0, dcd_sum1, dcd_sum2; - unsigned int dcd_time; -}; - -struct mod_state_psk48 { - unsigned char txbits[PSK48_TXF_NUMSAMPLES]; - unsigned short txphase; - unsigned int shreg; - unsigned long scram; - const short *tbl; - unsigned int txseq; -}; - -/* --------------------------------------------------------------------- */ - -static void modulator_4800_u8(struct sm_state *sm, unsigned char *buf, unsigned int buflen) -{ - struct mod_state_psk48 *st = (struct mod_state_psk48 *)(&sm->m); - int i, j; - int si, sq; - - for (; buflen > 0; buflen--, buf++) { - if (!st->txseq++) { - memmove(st->txbits+1, st->txbits, - sizeof(st->txbits)-sizeof(st->txbits[0])); - for (i = 0; i < 3; i++) { - if (st->shreg <= 1) - st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; - st->scram = (st->scram << 1) | - (st->shreg & 1); - st->shreg >>= 1; - if (st->scram & SCRAM_TAP1) - st->scram ^= SCRAM_TAPN; - } - j = (st->scram >> (SCRAM_SHIFT+3)) & 7; - st->txbits[0] -= (j ^ (j >> 1)); - st->txbits[0] &= 7; - st->tbl = psk48_tx_table; - } - if (st->txseq >= PSK48_TXF_OVERSAMPLING) - st->txseq = 0; - for (j = si = sq = 0; j < PSK48_TXF_NUMSAMPLES; j++, st->tbl += 16) { - si += st->tbl[st->txbits[j]]; - sq += st->tbl[st->txbits[j]+8]; - } - *buf = ((si*COS(st->txphase)+ sq*SIN(st->txphase)) >> 23) + 0x80; - st->txphase = (st->txphase + PSK48_PHASEINC) & 0xffffu; - } -} - -/* --------------------------------------------------------------------- */ - -static void modulator_4800_s16(struct sm_state *sm, short *buf, unsigned int buflen) -{ - struct mod_state_psk48 *st = (struct mod_state_psk48 *)(&sm->m); - int i, j; - int si, sq; - - for (; buflen > 0; buflen--, buf++) { - if (!st->txseq++) { - memmove(st->txbits+1, st->txbits, - sizeof(st->txbits)-sizeof(st->txbits[0])); - for (i = 0; i < 3; i++) { - if (st->shreg <= 1) - st->shreg = hdlcdrv_getbits(&sm->hdrv) | 0x10000; - st->scram = (st->scram << 1) | - (st->shreg & 1); - st->shreg >>= 1; - if (st->scram & SCRAM_TAP1) - st->scram ^= SCRAM_TAPN; - } - j = (st->scram >> (SCRAM_SHIFT+3)) & 7; - st->txbits[0] -= (j ^ (j >> 1)); - st->txbits[0] &= 7; - st->tbl = psk48_tx_table; - } - if (st->txseq >= PSK48_TXF_OVERSAMPLING) - st->txseq = 0; - for (j = si = sq = 0; j < PSK48_TXF_NUMSAMPLES; j++, st->tbl += 16) { - si += st->tbl[st->txbits[j]]; - sq += st->tbl[st->txbits[j]+8]; - } - *buf = (si*COS(st->txphase)+ sq*SIN(st->txphase)) >> 15; - st->txphase = (st->txphase + PSK48_PHASEINC) & 0xffffu; - } -} - -/* --------------------------------------------------------------------- */ - -static __inline__ unsigned short tbl_atan(short q, short i) -{ - short tmp; - unsigned short argoffs = 0; - - if (i == 0 && q == 0) - return 0; - switch (((q < 0) << 1) | (i < 0)) { - case 0: - break; - case 1: - tmp = q; - q = -i; - i = tmp; - argoffs = 0x4000; - break; - case 3: - q = -q; - i = -i; - argoffs = 0x8000; - break; - case 2: - tmp = -q; - q = i; - i = tmp; - argoffs = 0xc000; - break; - } - if (q > i) { - tmp = i / q * ATAN_TABLEN; - return (argoffs+0x4000-atan_tab[((i<<15)/q*ATAN_TABLEN>>15)]) - &0xffffu; - } - return (argoffs+atan_tab[((q<<15)/i*ATAN_TABLEN)>>15])&0xffffu; -} - -#define ATAN(q,i) tbl_atan(q, i) - -/* --------------------------------------------------------------------- */ - -static void demod_psk48_baseband(struct sm_state *sm, struct demod_state_psk48 *st, - short vali, short valq) -{ - int i, j; - - st->magi = vali; - st->magq = valq; - memmove(st->pwrhist+1, st->pwrhist, - sizeof(st->pwrhist)-sizeof(st->pwrhist[0])); - st->pwrhist[0] = st->magi * st->magi + - st->magq * st->magq; - st->cur_sync = ((st->pwrhist[4] >> 2) > st->pwrhist[2] && - (st->pwrhist[0] >> 2) > st->pwrhist[2] && - st-> pwrhist[3] > st->pwrhist[2] && - st->pwrhist[1] > st->pwrhist[2]); - st->s_phase &= 0xffff; - st->s_phase += PSK48_SPHASEINC; - st->dcd_shreg <<= 1; - if (st->cur_sync) { - if (st->s_phase >= (0x8000 + 5*PSK48_SPHASEINC/2)) - st->s_phase -= PSK48_SPHASEINC/6; - else - st->s_phase += PSK48_SPHASEINC/6; - st->dcd_sum0 = 4*hweight8(st->dcd_shreg & 0xf8)- - hweight16(st->dcd_shreg & 0x1f00); - } - if ((--st->dcd_time) <= 0) { - hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + st->dcd_sum1 + - st->dcd_sum2) < 0); - st->dcd_sum2 = st->dcd_sum1; - st->dcd_sum1 = st->dcd_sum0; - st->dcd_sum0 = 2; /* slight bias */ - st->dcd_time = 240; - } - if (st->s_phase < 0x10000) - return; - /* - * sample one constellation - */ - st->last_pskph = st->pskph; - st->pskph = (ATAN(st->magq, st->magi)- - st->phase) & 0xffffu; - st->last_ph_err = (st->pskph & 0x1fffu) - 0x1000; - st->phase += st->last_ph_err/16; - st->last_raw = st->cur_raw; - st->cur_raw = ((st->pskph >> 13) & 7); - i = (st->cur_raw - st->last_raw) & 7; - st->rawbits = i ^ (i >> 1) ^ (i >> 2); - st->descram = (st->descram << 3) | (st->rawbits); - hdlcdrv_channelbit(&sm->hdrv, st->descram & 4); - hdlcdrv_channelbit(&sm->hdrv, st->descram & 2); - hdlcdrv_channelbit(&sm->hdrv, st->descram & 1); - i = (((st->descram >> DESCRAM_TAPSH1) & 7) ^ - ((st->descram >> DESCRAM_TAPSH2) & 7) ^ - ((st->descram >> DESCRAM_TAPSH3) & 7)); - for (j = 4; j; j >>= 1) { - st->shreg >>= 1; - st->shreg |= (!!(i & j)) << 16; - if (st->shreg & 1) { - hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1); - st->shreg = 0x10000; - } - } - -#if 0 - st->dcd_shreg <<= 1; - st->bit_pll += 0x4000; - curbit = (*buf >= 0x80); - if (st->last_sample ^ curbit) { - st->dcd_shreg |= 1; - st->bit_pll += pll_corr - [st->bit_pll < 0xa000]; - st->dcd_sum0 += 8 * - hweight8(st->dcd_shreg & 0x0c) - - !!(st->dcd_shreg & 0x10); - } - st->last_sample = curbit; - hdlcdrv_channelbit(&sm->hdrv, st->last_sample); - if ((--st->dcd_time) <= 0) { - hdlcdrv_setdcd(&sm->hdrv, (st->dcd_sum0 + - st->dcd_sum1 + - st->dcd_sum2) < 0); - st->dcd_sum2 = st->dcd_sum1; - st->dcd_sum1 = st->dcd_sum0; - st->dcd_sum0 = 2; /* slight bias */ - st->dcd_time = 240; - } - if (st->bit_pll >= 0x10000) { - st->bit_pll &= 0xffffu; - st->descram = (st->descram << 1) | curbit; - descx = st->descram ^ (st->descram >> 1); - descx ^= ((descx >> DESCRAM_TAPSH1) ^ - (descx >> DESCRAM_TAPSH2)); - st->shreg >>= 1; - st->shreg |= (!(descx & 1)) << 16; - if (st->shreg & 1) { - hdlcdrv_putbits(&sm->hdrv, st->shreg >> 1); - st->shreg = 0x10000; - } - diag_trigger(sm); - } - diag_add_one(sm, ((short)(*buf - 0x80)) << 8); -#endif - - diag_trigger(sm); - diag_add_constellation(sm, (vali*COS(st->phase)+ valq*SIN(st->phase)) >> 13, - (valq*COS(st->phase) - vali*SIN(st->phase)) >> 13); -} - -/* --------------------------------------------------------------------- */ - -static void demodulator_4800_u8(struct sm_state *sm, const unsigned char *buf, unsigned int buflen) -{ - struct demod_state_psk48 *st = (struct demod_state_psk48 *)(&sm->d); - int i, si, sq; - const short *coeff; - - for (; buflen > 0; buflen--, buf++) { - memmove(st->infi+1, st->infi, - sizeof(st->infi)-sizeof(st->infi[0])); - memmove(st->infq+1, st->infq, - sizeof(st->infq)-sizeof(st->infq[0])); - si = *buf; - si &= 0xff; - si -= 128; - diag_add_one(sm, si << 8); - st->infi[0] = (si * COS(st->downmixer))>>7; - st->infq[0] = (si * SIN(st->downmixer))>>7; - st->downmixer = (st->downmixer-PSK48_PHASEINC)&0xffffu; - for (i = si = sq = 0, coeff = psk48_rx_coeff; i < (PSK48_RXF_LEN/2); - i++, coeff += 2) { - si += st->infi[i] * (*coeff); - sq += st->infq[i] * (*coeff); - } - demod_psk48_baseband(sm, st, si >> 15, sq >> 15); - for (i = si = sq = 0, coeff = psk48_rx_coeff + 1; i < (PSK48_RXF_LEN/2); - i++, coeff += 2) { - si += st->infi[i] * (*coeff); - sq += st->infq[i] * (*coeff); - } - demod_psk48_baseband(sm, st, si >> 15, sq >> 15); - } -} - -/* --------------------------------------------------------------------- */ - -static void demodulator_4800_s16(struct sm_state *sm, const short *buf, unsigned int buflen) -{ - struct demod_state_psk48 *st = (struct demod_state_psk48 *)(&sm->d); - int i, si, sq; - const short *coeff; - - for (; buflen > 0; buflen--, buf++) { - memmove(st->infi+1, st->infi, - sizeof(st->infi)-sizeof(st->infi[0])); - memmove(st->infq+1, st->infq, - sizeof(st->infq)-sizeof(st->infq[0])); - si = *buf; - diag_add_one(sm, si); - st->infi[0] = (si * COS(st->downmixer))>>15; - st->infq[0] = (si * SIN(st->downmixer))>>15; - st->downmixer = (st->downmixer-PSK48_PHASEINC)&0xffffu; - for (i = si = sq = 0, coeff = psk48_rx_coeff; i < (PSK48_RXF_LEN/2); - i++, coeff += 2) { - si += st->infi[i] * (*coeff); - sq += st->infq[i] * (*coeff); - } - demod_psk48_baseband(sm, st, si >> 15, sq >> 15); - for (i = si = sq = 0, coeff = psk48_rx_coeff + 1; i < (PSK48_RXF_LEN/2); - i++, coeff += 2) { - si += st->infi[i] * (*coeff); - sq += st->infq[i] * (*coeff); - } - demod_psk48_baseband(sm, st, si >> 15, sq >> 15); - } -} - -/* --------------------------------------------------------------------- */ - -static void mod_init_4800(struct sm_state *sm) -{ - struct mod_state_psk48 *st = (struct mod_state_psk48 *)(&sm->m); - - st->scram = 1; -} - -/* --------------------------------------------------------------------- */ - -static void demod_init_4800(struct sm_state *sm) -{ - struct demod_state_psk48 *st = (struct demod_state_psk48 *)(&sm->d); - - st->dcd_time = 120; - st->dcd_sum0 = 2; -} - -/* --------------------------------------------------------------------- */ - -const struct modem_tx_info sm_psk4800_tx = { - "psk4800", sizeof(struct mod_state_psk48), - PSK48_SAMPLERATE, 4800, - modulator_4800_u8, modulator_4800_s16, mod_init_4800 -}; - -const struct modem_rx_info sm_psk4800_rx = { - "psk4800", sizeof(struct demod_state_psk48), - PSK48_SAMPLERATE, 4800, 1, PSK48_TXF_OVERSAMPLING, - demodulator_4800_u8, demodulator_4800_s16, demod_init_4800 -}; - -/* --------------------------------------------------------------------- */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/net/hamradio/soundmodem/sm_sbc.c linux.2.5.47-ac4/drivers/net/hamradio/soundmodem/sm_sbc.c --- linux.2.5.47/drivers/net/hamradio/soundmodem/sm_sbc.c 2002-10-31 14:57:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/net/hamradio/soundmodem/sm_sbc.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,941 +0,0 @@ - - -/* - * sm_sbc.c -- soundcard radio modem driver soundblaster hardware driver - * - * Copyright (C) 1996 Thomas Sailer (sailer@ife.ee.ethz.ch) - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Please note that the GPL allows you to use the driver, NOT the radio. - * In order to use the radio, you need a license from the communications - * authority of your country. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "sm.h" -#include "smdma.h" - -/* --------------------------------------------------------------------- */ - -/* - * currently this module is supposed to support both module styles, i.e. - * the old one present up to about 2.1.9, and the new one functioning - * starting with 2.1.21. The reason is I have a kit allowing to compile - * this module also under 2.0.x which was requested by several people. - * This will go in 2.2 - */ -#include - -#if LINUX_VERSION_CODE >= 0x20100 -#include -#else -#include -#include - -#undef put_user -#undef get_user - -#define put_user(x,ptr) ({ __put_user((unsigned long)(x),(ptr),sizeof(*(ptr))); 0; }) -#define get_user(x,ptr) ({ x = ((__typeof__(*(ptr)))__get_user((ptr),sizeof(*(ptr)))); 0; }) - -static inline int copy_from_user(void *to, const void *from, unsigned long n) -{ - int i = verify_area(VERIFY_READ, from, n); - if (i) - return i; - memcpy_fromfs(to, from, n); - return 0; -} - -static inline int copy_to_user(void *to, const void *from, unsigned long n) -{ - int i = verify_area(VERIFY_WRITE, to, n); - if (i) - return i; - memcpy_tofs(to, from, n); - return 0; -} -#endif - -/* --------------------------------------------------------------------- */ - -struct sc_state_sbc { - unsigned char revhi, revlo; - unsigned char fmt[2]; - unsigned int sr[2]; -}; - -#define SCSTATE ((struct sc_state_sbc *)(&sm->hw)) - -/* --------------------------------------------------------------------- */ -/* - * the sbc converter's registers - */ -#define DSP_RESET(iobase) (iobase+0x6) -#define DSP_READ_DATA(iobase) (iobase+0xa) -#define DSP_WRITE_DATA(iobase) (iobase+0xc) -#define DSP_WRITE_STATUS(iobase) (iobase+0xc) -#define DSP_DATA_AVAIL(iobase) (iobase+0xe) -#define DSP_MIXER_ADDR(iobase) (iobase+0x4) -#define DSP_MIXER_DATA(iobase) (iobase+0x5) -#define DSP_INTACK_16BIT(iobase) (iobase+0xf) -#define SBC_EXTENT 16 - -/* --------------------------------------------------------------------- */ -/* - * SBC commands - */ -#define SBC_OUTPUT 0x14 -#define SBC_INPUT 0x24 -#define SBC_BLOCKSIZE 0x48 -#define SBC_HI_OUTPUT 0x91 -#define SBC_HI_INPUT 0x99 -#define SBC_LO_OUTPUT_AUTOINIT 0x1c -#define SBC_LO_INPUT_AUTOINIT 0x2c -#define SBC_HI_OUTPUT_AUTOINIT 0x90 -#define SBC_HI_INPUT_AUTOINIT 0x98 -#define SBC_IMMED_INT 0xf2 -#define SBC_GET_REVISION 0xe1 -#define ESS_GET_REVISION 0xe7 -#define SBC_SPEAKER_ON 0xd1 -#define SBC_SPEAKER_OFF 0xd3 -#define SBC_DMA_ON 0xd0 -#define SBC_DMA_OFF 0xd4 -#define SBC_SAMPLE_RATE 0x40 -#define SBC_SAMPLE_RATE_OUT 0x41 -#define SBC_SAMPLE_RATE_IN 0x42 -#define SBC_MONO_8BIT 0xa0 -#define SBC_MONO_16BIT 0xa4 -#define SBC_STEREO_8BIT 0xa8 -#define SBC_STEREO_16BIT 0xac - -#define SBC4_OUT8_AI 0xc6 -#define SBC4_IN8_AI 0xce -#define SBC4_MODE_UNS_MONO 0x00 -#define SBC4_MODE_SIGN_MONO 0x10 - -#define SBC4_OUT16_AI 0xb6 -#define SBC4_IN16_AI 0xbe - -/* --------------------------------------------------------------------- */ - -static int inline reset_dsp(struct net_device *dev) -{ - int i; - - outb(1, DSP_RESET(dev->base_addr)); - udelay(300); - outb(0, DSP_RESET(dev->base_addr)); - for (i = 0; i < 0xffff; i++) - if (inb(DSP_DATA_AVAIL(dev->base_addr)) & 0x80) - if (inb(DSP_READ_DATA(dev->base_addr)) == 0xaa) - return 1; - return 0; -} - -/* --------------------------------------------------------------------- */ - -static void inline write_dsp(struct net_device *dev, unsigned char data) -{ - int i; - - for (i = 0; i < 0xffff; i++) - if (!(inb(DSP_WRITE_STATUS(dev->base_addr)) & 0x80)) { - outb(data, DSP_WRITE_DATA(dev->base_addr)); - return; - } -} - -/* --------------------------------------------------------------------- */ - -static int inline read_dsp(struct net_device *dev, unsigned char *data) -{ - int i; - - if (!data) - return 0; - for (i = 0; i < 0xffff; i++) - if (inb(DSP_DATA_AVAIL(dev->base_addr)) & 0x80) { - *data = inb(DSP_READ_DATA(dev->base_addr)); - return 1; - } - return 0; -} - -/* --------------------------------------------------------------------- */ - -static int config_resources(struct net_device *dev, struct sm_state *sm, int fdx) -{ - unsigned char irqreg = 0, dmareg = 0, realirq, realdma; - unsigned long flags; - - switch (dev->irq) { - case 2: - case 9: - irqreg |= 0x01; - break; - - case 5: - irqreg |= 0x02; - break; - - case 7: - irqreg |= 0x04; - break; - - case 10: - irqreg |= 0x08; - break; - - default: - return -ENODEV; - } - - switch (dev->dma) { - case 0: - dmareg |= 0x01; - break; - - case 1: - dmareg |= 0x02; - break; - - case 3: - dmareg |= 0x08; - break; - - default: - return -ENODEV; - } - - if (fdx) { - switch (sm->hdrv.ptt_out.dma2) { - case 5: - dmareg |= 0x20; - break; - - case 6: - dmareg |= 0x40; - break; - - case 7: - dmareg |= 0x80; - break; - - default: - return -ENODEV; - } - } - save_flags(flags); - cli(); - outb(0x80, DSP_MIXER_ADDR(dev->base_addr)); - outb(irqreg, DSP_MIXER_DATA(dev->base_addr)); - realirq = inb(DSP_MIXER_DATA(dev->base_addr)); - outb(0x81, DSP_MIXER_ADDR(dev->base_addr)); - outb(dmareg, DSP_MIXER_DATA(dev->base_addr)); - realdma = inb(DSP_MIXER_DATA(dev->base_addr)); - restore_flags(flags); - if ((~realirq) & irqreg || (~realdma) & dmareg) { - printk(KERN_ERR "%s: sbc resource registers cannot be set; PnP device " - "and IRQ/DMA specified wrongly?\n", sm_drvname); - return -EINVAL; - } - return 0; -} - -/* --------------------------------------------------------------------- */ - -static void inline sbc_int_ack_8bit(struct net_device *dev) -{ - inb(DSP_DATA_AVAIL(dev->base_addr)); -} - -/* --------------------------------------------------------------------- */ - -static void inline sbc_int_ack_16bit(struct net_device *dev) -{ - inb(DSP_INTACK_16BIT(dev->base_addr)); -} - -/* --------------------------------------------------------------------- */ - -static void setup_dma_dsp(struct net_device *dev, struct sm_state *sm, int send) -{ - unsigned long flags; - static const unsigned char sbcmode[2][2] = { - { SBC_LO_INPUT_AUTOINIT, SBC_LO_OUTPUT_AUTOINIT }, - { SBC_HI_INPUT_AUTOINIT, SBC_HI_OUTPUT_AUTOINIT } - }; - static const unsigned char sbc4mode[2] = { SBC4_IN8_AI, SBC4_OUT8_AI }; - static const unsigned char sbcskr[2] = { SBC_SPEAKER_OFF, SBC_SPEAKER_ON }; - unsigned int nsamps; - - send = !!send; - if (!reset_dsp(dev)) { - printk(KERN_ERR "%s: sbc: cannot reset sb dsp\n", sm_drvname); - return; - } - save_flags(flags); - cli(); - sbc_int_ack_8bit(dev); - write_dsp(dev, SBC_SAMPLE_RATE); /* set sampling rate */ - write_dsp(dev, SCSTATE->fmt[send]); - write_dsp(dev, sbcskr[send]); - nsamps = dma_setup(sm, send, dev->dma) - 1; - sbc_int_ack_8bit(dev); - if (SCSTATE->revhi >= 4) { - write_dsp(dev, sbc4mode[send]); - write_dsp(dev, SBC4_MODE_UNS_MONO); - write_dsp(dev, nsamps & 0xff); - write_dsp(dev, nsamps >> 8); - } else { - write_dsp(dev, SBC_BLOCKSIZE); - write_dsp(dev, nsamps & 0xff); - write_dsp(dev, nsamps >> 8); - write_dsp(dev, sbcmode[SCSTATE->fmt[send] >= 180][send]); - /* hispeed mode if sample rate > 13kHz */ - } - restore_flags(flags); -} - -/* --------------------------------------------------------------------- */ - -static void sbc_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - struct net_device *dev = (struct net_device *)dev_id; - struct sm_state *sm = (struct sm_state *)dev->priv; - unsigned int curfrag; - - if (!dev || !sm || sm->hdrv.magic != HDLCDRV_MAGIC) - return; - cli(); - sbc_int_ack_8bit(dev); - disable_dma(dev->dma); - clear_dma_ff(dev->dma); - dma_ptr(sm, sm->dma.ptt_cnt > 0, dev->dma, &curfrag); - enable_dma(dev->dma); - sm_int_freq(sm); - sti(); - if (sm->dma.ptt_cnt <= 0) { - dma_receive(sm, curfrag); - hdlcdrv_arbitrate(dev, &sm->hdrv); - if (hdlcdrv_ptt(&sm->hdrv)) { - /* starting to transmit */ - disable_dma(dev->dma); - hdlcdrv_transmitter(dev, &sm->hdrv); /* prefill HDLC buffer */ - dma_start_transmit(sm); - setup_dma_dsp(dev, sm, 1); - dma_transmit(sm); - } - } else if (dma_end_transmit(sm, curfrag)) { - /* stopping transmission */ - disable_dma(dev->dma); - sti(); - dma_init_receive(sm); - setup_dma_dsp(dev, sm, 0); - } else - dma_transmit(sm); - sm_output_status(sm); - hdlcdrv_transmitter(dev, &sm->hdrv); - hdlcdrv_receiver(dev, &sm->hdrv); - -} - -/* --------------------------------------------------------------------- */ - -static int sbc_open(struct net_device *dev, struct sm_state *sm) -{ - int err; - unsigned int dmasz, u; - - if (sizeof(sm->m) < sizeof(struct sc_state_sbc)) { - printk(KERN_ERR "sm sbc: sbc state too big: %d > %d\n", - sizeof(struct sc_state_sbc), sizeof(sm->m)); - return -ENODEV; - } - if (!dev || !sm) - return -ENXIO; - if (dev->base_addr <= 0 || dev->base_addr > 0x1000-SBC_EXTENT || - dev->irq < 2 || dev->irq > 15 || dev->dma > 3) - return -ENXIO; - if (check_region(dev->base_addr, SBC_EXTENT)) - return -EACCES; - /* - * check if a card is available - */ - if (!reset_dsp(dev)) { - printk(KERN_ERR "%s: sbc: no card at io address 0x%lx\n", - sm_drvname, dev->base_addr); - return -ENODEV; - } - write_dsp(dev, SBC_GET_REVISION); - if (!read_dsp(dev, &SCSTATE->revhi) || - !read_dsp(dev, &SCSTATE->revlo)) - return -ENODEV; - printk(KERN_INFO "%s: SoundBlaster DSP revision %d.%d\n", sm_drvname, - SCSTATE->revhi, SCSTATE->revlo); - if (SCSTATE->revhi < 2) { - printk(KERN_ERR "%s: your card is an antiquity, at least DSP " - "rev 2.00 required\n", sm_drvname); - return -ENODEV; - } - if (SCSTATE->revhi < 3 && - (SCSTATE->fmt[0] >= 180 || SCSTATE->fmt[1] >= 180)) { - printk(KERN_ERR "%s: sbc io 0x%lx: DSP rev %d.%02d too " - "old, at least 3.00 required\n", sm_drvname, - dev->base_addr, SCSTATE->revhi, SCSTATE->revlo); - return -ENODEV; - } - if (SCSTATE->revhi >= 4 && - (err = config_resources(dev, sm, 0))) { - printk(KERN_ERR "%s: invalid IRQ and/or DMA specified\n", sm_drvname); - return err; - } - /* - * initialize some variables - */ - dma_init_receive(sm); - dmasz = (NUM_FRAGMENTS + 1) * sm->dma.ifragsz; - u = NUM_FRAGMENTS * sm->dma.ofragsz; - if (u > dmasz) - dmasz = u; - if (!(sm->dma.ibuf = sm->dma.obuf = kmalloc(dmasz, GFP_KERNEL | GFP_DMA))) - return -ENOMEM; - dma_init_transmit(sm); - dma_init_receive(sm); - - memset(&sm->m, 0, sizeof(sm->m)); - memset(&sm->d, 0, sizeof(sm->d)); - if (sm->mode_tx->init) - sm->mode_tx->init(sm); - if (sm->mode_rx->init) - sm->mode_rx->init(sm); - - if (request_dma(dev->dma, sm->hwdrv->hw_name)) { - kfree(sm->dma.obuf); - return -EBUSY; - } - if (request_irq(dev->irq, sbc_interrupt, SA_INTERRUPT, - sm->hwdrv->hw_name, dev)) { - free_dma(dev->dma); - kfree(sm->dma.obuf); - return -EBUSY; - } - request_region(dev->base_addr, SBC_EXTENT, sm->hwdrv->hw_name); - setup_dma_dsp(dev, sm, 0); - return 0; -} - -/* --------------------------------------------------------------------- */ - -static int sbc_close(struct net_device *dev, struct sm_state *sm) -{ - if (!dev || !sm) - return -EINVAL; - /* - * disable interrupts - */ - disable_dma(dev->dma); - reset_dsp(dev); - free_irq(dev->irq, dev); - free_dma(dev->dma); - release_region(dev->base_addr, SBC_EXTENT); - kfree(sm->dma.obuf); - return 0; -} - -/* --------------------------------------------------------------------- */ - -static int sbc_sethw(struct net_device *dev, struct sm_state *sm, char *mode) -{ - char *cp = strchr(mode, '.'); - const struct modem_tx_info **mtp = sm_modem_tx_table; - const struct modem_rx_info **mrp; - - if (!strcmp(mode, "off")) { - sm->mode_tx = NULL; - sm->mode_rx = NULL; - return 0; - } - if (cp) - *cp++ = '\0'; - else - cp = mode; - for (; *mtp; mtp++) { - if ((*mtp)->loc_storage > sizeof(sm->m)) { - printk(KERN_ERR "%s: insufficient storage for modulator %s (%d)\n", - sm_drvname, (*mtp)->name, (*mtp)->loc_storage); - continue; - } - if (!(*mtp)->name || strcmp((*mtp)->name, mode)) - continue; - if ((*mtp)->srate < 5000 || (*mtp)->srate > 44100) - continue; - if (!(*mtp)->modulator_u8) - continue; - for (mrp = sm_modem_rx_table; *mrp; mrp++) { - if ((*mrp)->loc_storage > sizeof(sm->d)) { - printk(KERN_ERR "%s: insufficient storage for demodulator %s (%d)\n", - sm_drvname, (*mrp)->name, (*mrp)->loc_storage); - continue; - } - if (!(*mrp)->demodulator_u8) - continue; - if ((*mrp)->name && !strcmp((*mrp)->name, cp) && - (*mrp)->srate >= 5000 && (*mrp)->srate <= 44100) { - sm->mode_tx = *mtp; - sm->mode_rx = *mrp; - SCSTATE->fmt[0] = 256-((1000000L+sm->mode_rx->srate/2)/ - sm->mode_rx->srate); - SCSTATE->fmt[1] = 256-((1000000L+sm->mode_tx->srate/2)/ - sm->mode_tx->srate); - sm->dma.ifragsz = (sm->mode_rx->srate + 50)/100; - sm->dma.ofragsz = (sm->mode_tx->srate + 50)/100; - if (sm->dma.ifragsz < sm->mode_rx->overlap) - sm->dma.ifragsz = sm->mode_rx->overlap; - sm->dma.i16bit = sm->dma.o16bit = 0; - return 0; - } - } - } - return -EINVAL; -} - -/* --------------------------------------------------------------------- */ - -static int sbc_ioctl(struct net_device *dev, struct sm_state *sm, struct ifreq *ifr, - struct hdlcdrv_ioctl *hi, int cmd) -{ - struct sm_ioctl bi; - unsigned long flags; - int i; - - if (cmd != SIOCDEVPRIVATE) - return -ENOIOCTLCMD; - - if (hi->cmd == HDLCDRVCTL_MODEMPARMASK) - return HDLCDRV_PARMASK_IOBASE | HDLCDRV_PARMASK_IRQ | - HDLCDRV_PARMASK_DMA | HDLCDRV_PARMASK_SERIOBASE | - HDLCDRV_PARMASK_PARIOBASE | HDLCDRV_PARMASK_MIDIIOBASE; - - if (copy_from_user(&bi, ifr->ifr_data, sizeof(bi))) - return -EFAULT; - - switch (bi.cmd) { - default: - return -ENOIOCTLCMD; - - case SMCTL_GETMIXER: - i = 0; - bi.data.mix.sample_rate = sm->mode_rx->srate; - bi.data.mix.bit_rate = sm->hdrv.par.bitrate; - bi.data.mix.mixer_type = SM_MIXER_INVALID; - switch (SCSTATE->revhi) { - case 2: - bi.data.mix.mixer_type = SM_MIXER_CT1335; - break; - case 3: - bi.data.mix.mixer_type = SM_MIXER_CT1345; - break; - case 4: - bi.data.mix.mixer_type = SM_MIXER_CT1745; - break; - } - if (bi.data.mix.mixer_type != SM_MIXER_INVALID && - bi.data.mix.reg < 0x80) { - save_flags(flags); - cli(); - outb(bi.data.mix.reg, DSP_MIXER_ADDR(dev->base_addr)); - bi.data.mix.data = inb(DSP_MIXER_DATA(dev->base_addr)); - restore_flags(flags); - i = 1; - } - if (copy_to_user(ifr->ifr_data, &bi, sizeof(bi))) - return -EFAULT; - return i; - - case SMCTL_SETMIXER: - if (!capable(CAP_SYS_RAWIO)) - return -EACCES; - switch (SCSTATE->revhi) { - case 2: - if (bi.data.mix.mixer_type != SM_MIXER_CT1335) - return -EINVAL; - break; - case 3: - if (bi.data.mix.mixer_type != SM_MIXER_CT1345) - return -EINVAL; - break; - case 4: - if (bi.data.mix.mixer_type != SM_MIXER_CT1745) - return -EINVAL; - break; - default: - return -ENODEV; - } - if (bi.data.mix.reg >= 0x80) - return -EACCES; - save_flags(flags); - cli(); - outb(bi.data.mix.reg, DSP_MIXER_ADDR(dev->base_addr)); - outb(bi.data.mix.data, DSP_MIXER_DATA(dev->base_addr)); - restore_flags(flags); - return 0; - - } - if (copy_to_user(ifr->ifr_data, &bi, sizeof(bi))) - return -EFAULT; - return 0; - -} - -/* --------------------------------------------------------------------- */ - -const struct hardware_info sm_hw_sbc = { - "sbc", sizeof(struct sc_state_sbc), - sbc_open, sbc_close, sbc_ioctl, sbc_sethw -}; - -/* --------------------------------------------------------------------- */ - -static void setup_dma_fdx_dsp(struct net_device *dev, struct sm_state *sm) -{ - unsigned long flags; - unsigned int isamps, osamps; - - if (!reset_dsp(dev)) { - printk(KERN_ERR "%s: sbc: cannot reset sb dsp\n", sm_drvname); - return; - } - save_flags(flags); - cli(); - sbc_int_ack_8bit(dev); - sbc_int_ack_16bit(dev); - /* should eventually change to set rates individually by SBC_SAMPLE_RATE_{IN/OUT} */ - write_dsp(dev, SBC_SAMPLE_RATE_IN); - write_dsp(dev, SCSTATE->sr[0] >> 8); - write_dsp(dev, SCSTATE->sr[0] & 0xff); - write_dsp(dev, SBC_SAMPLE_RATE_OUT); - write_dsp(dev, SCSTATE->sr[1] >> 8); - write_dsp(dev, SCSTATE->sr[1] & 0xff); - write_dsp(dev, SBC_SPEAKER_ON); - if (sm->dma.o16bit) { - /* - * DMA channel 1 (8bit) does input (capture), - * DMA channel 2 (16bit) does output (playback) - */ - isamps = dma_setup(sm, 0, dev->dma) - 1; - osamps = dma_setup(sm, 1, sm->hdrv.ptt_out.dma2) - 1; - sbc_int_ack_8bit(dev); - sbc_int_ack_16bit(dev); - write_dsp(dev, SBC4_IN8_AI); - write_dsp(dev, SBC4_MODE_UNS_MONO); - write_dsp(dev, isamps & 0xff); - write_dsp(dev, isamps >> 8); - write_dsp(dev, SBC4_OUT16_AI); - write_dsp(dev, SBC4_MODE_SIGN_MONO); - write_dsp(dev, osamps & 0xff); - write_dsp(dev, osamps >> 8); - } else { - /* - * DMA channel 1 (8bit) does output (playback), - * DMA channel 2 (16bit) does input (capture) - */ - isamps = dma_setup(sm, 0, sm->hdrv.ptt_out.dma2) - 1; - osamps = dma_setup(sm, 1, dev->dma) - 1; - sbc_int_ack_8bit(dev); - sbc_int_ack_16bit(dev); - write_dsp(dev, SBC4_OUT8_AI); - write_dsp(dev, SBC4_MODE_UNS_MONO); - write_dsp(dev, osamps & 0xff); - write_dsp(dev, osamps >> 8); - write_dsp(dev, SBC4_IN16_AI); - write_dsp(dev, SBC4_MODE_SIGN_MONO); - write_dsp(dev, isamps & 0xff); - write_dsp(dev, isamps >> 8); - } - dma_init_receive(sm); - dma_init_transmit(sm); - restore_flags(flags); -} - -/* --------------------------------------------------------------------- */ - -static void sbcfdx_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - struct net_device *dev = (struct net_device *)dev_id; - struct sm_state *sm = (struct sm_state *)dev->priv; - unsigned char intsrc, pbint = 0, captint = 0; - unsigned int ocfrag, icfrag; - unsigned long flags; - - if (!dev || !sm || sm->hdrv.magic != HDLCDRV_MAGIC) - return; - save_flags(flags); - cli(); - outb(0x82, DSP_MIXER_ADDR(dev->base_addr)); - intsrc = inb(DSP_MIXER_DATA(dev->base_addr)); - if (intsrc & 0x01) { - sbc_int_ack_8bit(dev); - if (sm->dma.o16bit) { - captint = 1; - disable_dma(dev->dma); - clear_dma_ff(dev->dma); - dma_ptr(sm, 0, dev->dma, &icfrag); - enable_dma(dev->dma); - } else { - pbint = 1; - disable_dma(dev->dma); - clear_dma_ff(dev->dma); - dma_ptr(sm, 1, dev->dma, &ocfrag); - enable_dma(dev->dma); - } - } - if (intsrc & 0x02) { - sbc_int_ack_16bit(dev); - if (sm->dma.o16bit) { - pbint = 1; - disable_dma(sm->hdrv.ptt_out.dma2); - clear_dma_ff(sm->hdrv.ptt_out.dma2); - dma_ptr(sm, 1, sm->hdrv.ptt_out.dma2, &ocfrag); - enable_dma(sm->hdrv.ptt_out.dma2); - } else { - captint = 1; - disable_dma(sm->hdrv.ptt_out.dma2); - clear_dma_ff(sm->hdrv.ptt_out.dma2); - dma_ptr(sm, 0, sm->hdrv.ptt_out.dma2, &icfrag); - enable_dma(sm->hdrv.ptt_out.dma2); - } - } - restore_flags(flags); - sm_int_freq(sm); - sti(); - if (pbint) { - if (dma_end_transmit(sm, ocfrag)) - dma_clear_transmit(sm); - dma_transmit(sm); - } - if (captint) { - dma_receive(sm, icfrag); - hdlcdrv_arbitrate(dev, &sm->hdrv); - } - sm_output_status(sm); - hdlcdrv_transmitter(dev, &sm->hdrv); - hdlcdrv_receiver(dev, &sm->hdrv); -} - -/* --------------------------------------------------------------------- */ - -static int sbcfdx_open(struct net_device *dev, struct sm_state *sm) -{ - int err; - - if (sizeof(sm->m) < sizeof(struct sc_state_sbc)) { - printk(KERN_ERR "sm sbc: sbc state too big: %d > %d\n", - sizeof(struct sc_state_sbc), sizeof(sm->m)); - return -ENODEV; - } - if (!dev || !sm) - return -ENXIO; - if (dev->base_addr <= 0 || dev->base_addr > 0x1000-SBC_EXTENT || - dev->irq < 2 || dev->irq > 15 || dev->dma > 3) - return -ENXIO; - if (check_region(dev->base_addr, SBC_EXTENT)) - return -EACCES; - /* - * check if a card is available - */ - if (!reset_dsp(dev)) { - printk(KERN_ERR "%s: sbc: no card at io address 0x%lx\n", - sm_drvname, dev->base_addr); - return -ENODEV; - } - write_dsp(dev, SBC_GET_REVISION); - if (!read_dsp(dev, &SCSTATE->revhi) || - !read_dsp(dev, &SCSTATE->revlo)) - return -ENODEV; - printk(KERN_INFO "%s: SoundBlaster DSP revision %d.%d\n", sm_drvname, - SCSTATE->revhi, SCSTATE->revlo); - if (SCSTATE->revhi < 4) { - printk(KERN_ERR "%s: at least DSP rev 4.00 required\n", sm_drvname); - return -ENODEV; - } - if ((err = config_resources(dev, sm, 1))) { - printk(KERN_ERR "%s: invalid IRQ and/or DMA specified\n", sm_drvname); - return err; - } - /* - * initialize some variables - */ - if (!(sm->dma.ibuf = kmalloc(sm->dma.ifragsz * (NUM_FRAGMENTS+1), GFP_KERNEL | GFP_DMA))) - return -ENOMEM; - if (!(sm->dma.obuf = kmalloc(sm->dma.ofragsz * NUM_FRAGMENTS, GFP_KERNEL | GFP_DMA))) { - kfree(sm->dma.ibuf); - return -ENOMEM; - } - dma_init_transmit(sm); - dma_init_receive(sm); - - memset(&sm->m, 0, sizeof(sm->m)); - memset(&sm->d, 0, sizeof(sm->d)); - if (sm->mode_tx->init) - sm->mode_tx->init(sm); - if (sm->mode_rx->init) - sm->mode_rx->init(sm); - - if (request_dma(dev->dma, sm->hwdrv->hw_name)) { - kfree(sm->dma.ibuf); - kfree(sm->dma.obuf); - return -EBUSY; - } - if (request_dma(sm->hdrv.ptt_out.dma2, sm->hwdrv->hw_name)) { - kfree(sm->dma.ibuf); - kfree(sm->dma.obuf); - free_dma(dev->dma); - return -EBUSY; - } - if (request_irq(dev->irq, sbcfdx_interrupt, SA_INTERRUPT, - sm->hwdrv->hw_name, dev)) { - kfree(sm->dma.ibuf); - kfree(sm->dma.obuf); - free_dma(dev->dma); - free_dma(sm->hdrv.ptt_out.dma2); - return -EBUSY; - } - request_region(dev->base_addr, SBC_EXTENT, sm->hwdrv->hw_name); - setup_dma_fdx_dsp(dev, sm); - return 0; -} - -/* --------------------------------------------------------------------- */ - -static int sbcfdx_close(struct net_device *dev, struct sm_state *sm) -{ - if (!dev || !sm) - return -EINVAL; - /* - * disable interrupts - */ - disable_dma(dev->dma); - disable_dma(sm->hdrv.ptt_out.dma2); - reset_dsp(dev); - free_irq(dev->irq, dev); - free_dma(dev->dma); - free_dma(sm->hdrv.ptt_out.dma2); - release_region(dev->base_addr, SBC_EXTENT); - kfree(sm->dma.ibuf); - kfree(sm->dma.obuf); - return 0; -} - -/* --------------------------------------------------------------------- */ - -static int sbcfdx_sethw(struct net_device *dev, struct sm_state *sm, char *mode) -{ - char *cp = strchr(mode, '.'); - const struct modem_tx_info **mtp = sm_modem_tx_table; - const struct modem_rx_info **mrp; - - if (!strcmp(mode, "off")) { - sm->mode_tx = NULL; - sm->mode_rx = NULL; - return 0; - } - if (cp) - *cp++ = '\0'; - else - cp = mode; - for (; *mtp; mtp++) { - if ((*mtp)->loc_storage > sizeof(sm->m)) { - printk(KERN_ERR "%s: insufficient storage for modulator %s (%d)\n", - sm_drvname, (*mtp)->name, (*mtp)->loc_storage); - continue; - } - if (!(*mtp)->name || strcmp((*mtp)->name, mode)) - continue; - if ((*mtp)->srate < 5000 || (*mtp)->srate > 44100) - continue; - for (mrp = sm_modem_rx_table; *mrp; mrp++) { - if ((*mrp)->loc_storage > sizeof(sm->d)) { - printk(KERN_ERR "%s: insufficient storage for demodulator %s (%d)\n", - sm_drvname, (*mrp)->name, (*mrp)->loc_storage); - continue; - } - if ((*mrp)->name && !strcmp((*mrp)->name, cp) && - (*mtp)->srate >= 5000 && (*mtp)->srate <= 44100 && - (*mrp)->srate == (*mtp)->srate) { - sm->mode_tx = *mtp; - sm->mode_rx = *mrp; - SCSTATE->sr[0] = sm->mode_rx->srate; - SCSTATE->sr[1] = sm->mode_tx->srate; - sm->dma.ifragsz = (sm->mode_rx->srate + 50)/100; - sm->dma.ofragsz = (sm->mode_tx->srate + 50)/100; - if (sm->dma.ifragsz < sm->mode_rx->overlap) - sm->dma.ifragsz = sm->mode_rx->overlap; - if (sm->mode_rx->demodulator_s16 && sm->mode_tx->modulator_u8) { - sm->dma.i16bit = 1; - sm->dma.o16bit = 0; - sm->dma.ifragsz <<= 1; - } else if (sm->mode_rx->demodulator_u8 && sm->mode_tx->modulator_s16) { - sm->dma.i16bit = 0; - sm->dma.o16bit = 1; - sm->dma.ofragsz <<= 1; - } else { - printk(KERN_INFO "%s: mode %s or %s unusable\n", sm_drvname, - sm->mode_rx->name, sm->mode_tx->name); - sm->mode_tx = NULL; - sm->mode_rx = NULL; - return -EINVAL; - } - return 0; - } - } - } - return -EINVAL; -} - -/* --------------------------------------------------------------------- */ - -static int sbcfdx_ioctl(struct net_device *dev, struct sm_state *sm, struct ifreq *ifr, - struct hdlcdrv_ioctl *hi, int cmd) -{ - if (cmd != SIOCDEVPRIVATE) - return -ENOIOCTLCMD; - - if (hi->cmd == HDLCDRVCTL_MODEMPARMASK) - return HDLCDRV_PARMASK_IOBASE | HDLCDRV_PARMASK_IRQ | - HDLCDRV_PARMASK_DMA | HDLCDRV_PARMASK_DMA2 | HDLCDRV_PARMASK_SERIOBASE | - HDLCDRV_PARMASK_PARIOBASE | HDLCDRV_PARMASK_MIDIIOBASE; - - return sbc_ioctl(dev, sm, ifr, hi, cmd); -} - -/* --------------------------------------------------------------------- */ - -const struct hardware_info sm_hw_sbcfdx = { - "sbcfdx", sizeof(struct sc_state_sbc), - sbcfdx_open, sbcfdx_close, sbcfdx_ioctl, sbcfdx_sethw -}; - -/* --------------------------------------------------------------------- */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/net/hamradio/soundmodem/sm_wss.c linux.2.5.47-ac4/drivers/net/hamradio/soundmodem/sm_wss.c --- linux.2.5.47/drivers/net/hamradio/soundmodem/sm_wss.c 2002-10-31 14:57:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/net/hamradio/soundmodem/sm_wss.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,967 +0,0 @@ -/*****************************************************************************/ - -/* - * sm_wss.c -- soundcard radio modem driver, WSS (half duplex) driver - * - * Copyright (C) 1996 Thomas Sailer (sailer@ife.ee.ethz.ch) - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Please note that the GPL allows you to use the driver, NOT the radio. - * In order to use the radio, you need a license from the communications - * authority of your country. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include "sm.h" -#include "smdma.h" - -/* --------------------------------------------------------------------- */ - -/* - * currently this module is supposed to support both module styles, i.e. - * the old one present up to about 2.1.9, and the new one functioning - * starting with 2.1.21. The reason is I have a kit allowing to compile - * this module also under 2.0.x which was requested by several people. - * This will go in 2.2 - */ -#include - -#if LINUX_VERSION_CODE >= 0x20100 -#include -#else -#include -#include - -#undef put_user -#undef get_user - -#define put_user(x,ptr) ({ __put_user((unsigned long)(x),(ptr),sizeof(*(ptr))); 0; }) -#define get_user(x,ptr) ({ x = ((__typeof__(*(ptr)))__get_user((ptr),sizeof(*(ptr)))); 0; }) - -static inline int copy_from_user(void *to, const void *from, unsigned long n) -{ - int i = verify_area(VERIFY_READ, from, n); - if (i) - return i; - memcpy_fromfs(to, from, n); - return 0; -} - -static inline int copy_to_user(void *to, const void *from, unsigned long n) -{ - int i = verify_area(VERIFY_WRITE, to, n); - if (i) - return i; - memcpy_tofs(to, from, n); - return 0; -} -#endif - -/* --------------------------------------------------------------------- */ - -struct sc_state_wss { - unsigned char revwss, revid, revv, revcid; - unsigned char fmt[2]; - unsigned char crystal; -}; - -#define SCSTATE ((struct sc_state_wss *)(&sm->hw)) - -/* --------------------------------------------------------------------- */ - -#define WSS_CONFIG(iobase) (iobase+0) -#define WSS_STATUS(iobase) (iobase+3) -#define WSS_CODEC_IA(iobase) (iobase+4) -#define WSS_CODEC_ID(iobase) (iobase+5) -#define WSS_CODEC_STATUS(iobase) (iobase+6) -#define WSS_CODEC_DATA(iobase) (iobase+7) - -#define WSS_EXTENT 8 - -#define CS423X_HOTFIX - -/* --------------------------------------------------------------------- */ - -static void write_codec(struct net_device *dev, unsigned char idx, - unsigned char data) -{ - int timeout = 900000; - - /* wait until codec ready */ - while (timeout > 0 && inb(WSS_CODEC_IA(dev->base_addr)) & 0x80) - timeout--; - outb(idx, WSS_CODEC_IA(dev->base_addr)); - outb(data, WSS_CODEC_ID(dev->base_addr)); -} - - -/* --------------------------------------------------------------------- */ - -static unsigned char read_codec(struct net_device *dev, unsigned char idx) -{ - int timeout = 900000; - - /* wait until codec ready */ - while (timeout > 0 && inb(WSS_CODEC_IA(dev->base_addr)) & 0x80) - timeout--; - outb(idx & 0x1f, WSS_CODEC_IA(dev->base_addr)); - return inb(WSS_CODEC_ID(dev->base_addr)); -} - -/* --------------------------------------------------------------------- */ - -extern void inline wss_ack_int(struct net_device *dev) -{ - outb(0, WSS_CODEC_STATUS(dev->base_addr)); -} - -/* --------------------------------------------------------------------- */ - -static int wss_srate_tab[16] = { - 8000, 5510, 16000, 11025, 27420, 18900, 32000, 22050, - -1, 37800, -1, 44100, 48000, 33075, 9600, 6620 -}; - -static int wss_srate_index(int srate) -{ - int i; - - for (i = 0; i < (sizeof(wss_srate_tab)/sizeof(wss_srate_tab[0])); i++) - if (srate == wss_srate_tab[i] && wss_srate_tab[i] > 0) - return i; - return -1; -} - -/* --------------------------------------------------------------------- */ - -static int wss_set_codec_fmt(struct net_device *dev, struct sm_state *sm, unsigned char fmt, - unsigned char fmt2, char fdx, char fullcalib) -{ - unsigned long time; - unsigned long flags; - - save_flags(flags); - cli(); - /* Clock and data format register */ - write_codec(dev, 0x48, fmt); - if (SCSTATE->crystal) { - write_codec(dev, 0x5c, fmt2 & 0xf0); - /* MCE and interface config reg */ - write_codec(dev, 0x49, (fdx ? 0 : 0x4) | (fullcalib ? 0x18 : 0)); - } else - /* MCE and interface config reg */ - write_codec(dev, 0x49, fdx ? 0x8 : 0xc); - outb(0xb, WSS_CODEC_IA(dev->base_addr)); /* leave MCE */ - if (SCSTATE->crystal && !fullcalib) { - restore_flags(flags); - return 0; - } - /* - * wait for ACI start - */ - time = 1000; - while (!(read_codec(dev, 0x0b) & 0x20)) - if (!(--time)) { - printk(KERN_WARNING "%s: ad1848 auto calibration timed out (1)\n", - sm_drvname); - restore_flags(flags); - return -1; - } - /* - * wait for ACI end - */ - sti(); - time = jiffies + HZ/4; - while ((read_codec(dev, 0x0b) & 0x20) && ((signed)(jiffies - time) < 0)); - restore_flags(flags); - if ((signed)(jiffies - time) >= 0) { - printk(KERN_WARNING "%s: ad1848 auto calibration timed out (2)\n", - sm_drvname); - return -1; - } - return 0; -} - -/* --------------------------------------------------------------------- */ - -static int wss_init_codec(struct net_device *dev, struct sm_state *sm, char fdx, - unsigned char src_l, unsigned char src_r, - int igain_l, int igain_r, - int ogain_l, int ogain_r) -{ - unsigned char tmp, reg0, reg1, reg6, reg7; - static const signed char irqtab[16] = - { -1, -1, 0x10, -1, -1, -1, -1, 0x08, -1, 0x10, 0x18, 0x20, -1, -1, - -1, -1 }; - static const signed char dmatab[4] = { 1, 2, -1, 3 }; - - tmp = inb(WSS_STATUS(dev->base_addr)); - if ((tmp & 0x3f) != 0x04 && (tmp & 0x3f) != 0x00 && - (tmp & 0x3f) != 0x0f) { - printk(KERN_WARNING "sm: WSS card id register not found, " - "address 0x%lx, ID register 0x%02x\n", - dev->base_addr, (int)tmp); - /* return -1; */ - SCSTATE->revwss = 0; - } else { - if ((tmp & 0x80) && ((dev->dma == 0) || - ((dev->irq >= 8) && (dev->irq != 9)))) { - printk(KERN_ERR "%s: WSS: DMA0 and/or IRQ8..IRQ15 " - "(except IRQ9) cannot be used on an 8bit " - "card\n", sm_drvname); - return -1; - } - if (dev->irq > 15 || irqtab[dev->irq] == -1) { - printk(KERN_ERR "%s: WSS: invalid interrupt %d\n", - sm_drvname, (int)dev->irq); - return -1; - } - if (dev->dma > 3 || dmatab[dev->dma] == -1) { - printk(KERN_ERR "%s: WSS: invalid dma channel %d\n", - sm_drvname, (int)dev->dma); - return -1; - } - tmp = irqtab[dev->irq] | dmatab[dev->dma]; - /* irq probe */ - outb((tmp & 0x38) | 0x40, WSS_CONFIG(dev->base_addr)); - if (!(inb(WSS_STATUS(dev->base_addr)) & 0x40)) { - outb(0, WSS_CONFIG(dev->base_addr)); - printk(KERN_ERR "%s: WSS: IRQ%d is not free!\n", - sm_drvname, dev->irq); - } - outb(tmp, WSS_CONFIG(dev->base_addr)); - SCSTATE->revwss = inb(WSS_STATUS(dev->base_addr)) & 0x3f; - } - /* - * initialize the codec - */ - if (igain_l < 0) - igain_l = 0; - if (igain_r < 0) - igain_r = 0; - if (ogain_l > 0) - ogain_l = 0; - if (ogain_r > 0) - ogain_r = 0; - reg0 = (src_l << 6) & 0xc0; - reg1 = (src_r << 6) & 0xc0; - if (reg0 == 0x80 && igain_l >= 20) { - reg0 |= 0x20; - igain_l -= 20; - } - if (reg1 == 0x80 && igain_r >= 20) { - reg1 |= 0x20; - igain_r -= 20; - } - if (igain_l > 23) - igain_l = 23; - if (igain_r > 23) - igain_r = 23; - reg0 |= igain_l * 2 / 3; - reg1 |= igain_r * 2 / 3; - reg6 = (ogain_l < -95) ? 0x80 : (ogain_l * (-2) / 3); - reg7 = (ogain_r < -95) ? 0x80 : (ogain_r * (-2) / 3); - write_codec(dev, 9, 0); - write_codec(dev, 0, 0x45); - if (read_codec(dev, 0) != 0x45) - goto codec_err; - write_codec(dev, 0, 0xaa); - if (read_codec(dev, 0) != 0xaa) - goto codec_err; - write_codec(dev, 12, 0x40); /* enable MODE2 */ - write_codec(dev, 16, 0); - write_codec(dev, 0, 0x45); - SCSTATE->crystal = (read_codec(dev, 16) != 0x45); - write_codec(dev, 0, 0xaa); - SCSTATE->crystal &= (read_codec(dev, 16) != 0xaa); - if (SCSTATE->crystal) { - SCSTATE->revcid = read_codec(dev, 0x19); - SCSTATE->revv = (SCSTATE->revcid >> 5) & 7; - SCSTATE->revcid &= 7; - write_codec(dev, 0x10, 0x80); /* maximum output level */ - write_codec(dev, 0x11, 0x02); /* xtal enable and no HPF */ - write_codec(dev, 0x12, 0x80); /* left line input control */ - write_codec(dev, 0x13, 0x80); /* right line input control */ - write_codec(dev, 0x16, 0); /* disable alternative freq sel */ - write_codec(dev, 0x1a, 0xe0); /* mono IO disable */ - write_codec(dev, 0x1b, 0x00); /* left out no att */ - write_codec(dev, 0x1d, 0x00); /* right out no att */ - } - - if (wss_set_codec_fmt(dev, sm, SCSTATE->fmt[0], SCSTATE->fmt[0], fdx, 1)) - goto codec_err; - - write_codec(dev, 0, reg0); /* left input control */ - write_codec(dev, 1, reg1); /* right input control */ - write_codec(dev, 2, 0x80); /* left aux#1 input control */ - write_codec(dev, 3, 0x80); /* right aux#1 input control */ - write_codec(dev, 4, 0x80); /* left aux#2 input control */ - write_codec(dev, 5, 0x80); /* right aux#2 input control */ - write_codec(dev, 6, reg6); /* left dac control */ - write_codec(dev, 7, reg7); /* right dac control */ - write_codec(dev, 0xa, 0x2); /* pin control register */ - write_codec(dev, 0xd, 0x0); /* digital mix control */ - SCSTATE->revid = read_codec(dev, 0xc) & 0xf; - /* - * print revisions - */ - if (SCSTATE->crystal) - printk(KERN_INFO "%s: Crystal CODEC ID %d, Chip revision %d, " - " Chip ID %d\n", sm_drvname, (int)SCSTATE->revid, - (int)SCSTATE->revv, (int)SCSTATE->revcid); - else - printk(KERN_INFO "%s: WSS revision %d, CODEC revision %d\n", - sm_drvname, (int)SCSTATE->revwss, - (int)SCSTATE->revid); - return 0; - codec_err: - outb(0, WSS_CONFIG(dev->base_addr)); - printk(KERN_ERR "%s: no WSS soundcard found at address 0x%lx\n", - sm_drvname, dev->base_addr); - return -1; -} - -/* --------------------------------------------------------------------- */ - -static void setup_dma_wss(struct net_device *dev, struct sm_state *sm, int send) -{ - unsigned long flags; - static const unsigned char codecmode[2] = { 0x0e, 0x0d }; - unsigned char oldcodecmode; - long abrt; - unsigned char fmt; - unsigned int numsamps; - - send = !!send; - fmt = SCSTATE->fmt[send]; - save_flags(flags); - cli(); - /* - * perform the final DMA sequence to disable the codec request - */ - oldcodecmode = read_codec(dev, 9); - write_codec(dev, 9, 0xc); /* disable codec */ - wss_ack_int(dev); - if (read_codec(dev, 11) & 0x10) { - dma_setup(sm, oldcodecmode & 1, dev->dma); - abrt = 0; - while ((read_codec(dev, 11) & 0x10) || ((++abrt) >= 0x10000)); - } -#ifdef CS423X_HOTFIX - if (read_codec(dev, 0x8) != fmt || SCSTATE->crystal) - wss_set_codec_fmt(dev, sm, fmt, fmt, 0, 0); -#else /* CS423X_HOTFIX */ - if (read_codec(dev, 0x8) != fmt) - wss_set_codec_fmt(dev, sm, fmt, fmt, 0, 0); -#endif /* CS423X_HOTFIX */ - numsamps = dma_setup(sm, send, dev->dma) - 1; - write_codec(dev, 15, numsamps & 0xff); - write_codec(dev, 14, numsamps >> 8); - write_codec(dev, 9, codecmode[send]); - restore_flags(flags); -} - -/* --------------------------------------------------------------------- */ - -static void wss_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - struct net_device *dev = (struct net_device *)dev_id; - struct sm_state *sm = (struct sm_state *)dev->priv; - unsigned int curfrag; - unsigned int nums; - - if (!dev || !sm || !sm->mode_rx || !sm->mode_tx || - sm->hdrv.magic != HDLCDRV_MAGIC) - return; - cli(); - wss_ack_int(dev); - disable_dma(dev->dma); - clear_dma_ff(dev->dma); - nums = dma_ptr(sm, sm->dma.ptt_cnt > 0, dev->dma, &curfrag) - 1; - write_codec(dev, 15, nums & 0xff); - write_codec(dev, 14, nums >> 8); - enable_dma(dev->dma); - sm_int_freq(sm); - sti(); - if (sm->dma.ptt_cnt <= 0) { - dma_receive(sm, curfrag); - hdlcdrv_arbitrate(dev, &sm->hdrv); - if (hdlcdrv_ptt(&sm->hdrv)) { - /* starting to transmit */ - disable_dma(dev->dma); - hdlcdrv_transmitter(dev, &sm->hdrv); /* prefill HDLC buffer */ - dma_start_transmit(sm); - setup_dma_wss(dev, sm, 1); - dma_transmit(sm); - } - } else if (dma_end_transmit(sm, curfrag)) { - /* stopping transmission */ - disable_dma(dev->dma); - dma_init_receive(sm); - setup_dma_wss(dev, sm, 0); - } else - dma_transmit(sm); - sm_output_status(sm); - hdlcdrv_transmitter(dev, &sm->hdrv); - hdlcdrv_receiver(dev, &sm->hdrv); -} - -/* --------------------------------------------------------------------- */ - -static int wss_open(struct net_device *dev, struct sm_state *sm) -{ - unsigned int dmasz, u; - - if (sizeof(sm->m) < sizeof(struct sc_state_wss)) { - printk(KERN_ERR "sm wss: wss state too big: %d > %d\n", - sizeof(struct sc_state_wss), sizeof(sm->m)); - return -ENODEV; - } - if (!dev || !sm || !sm->mode_rx || !sm->mode_tx) - return -ENXIO; - if (dev->base_addr <= 0 || dev->base_addr > 0x1000-WSS_EXTENT || - dev->irq < 2 || dev->irq > 15 || dev->dma > 3) - return -ENXIO; - if (check_region(dev->base_addr, WSS_EXTENT)) - return -EACCES; - /* - * check if a card is available - */ - if (wss_init_codec(dev, sm, 0, 1, 1, 0, 0, -45, -45)) - return -ENODEV; - /* - * initialize some variables - */ - dma_init_receive(sm); - dmasz = (NUM_FRAGMENTS + 1) * sm->dma.ifragsz; - u = NUM_FRAGMENTS * sm->dma.ofragsz; - if (u > dmasz) - dmasz = u; - if (!(sm->dma.ibuf = sm->dma.obuf = kmalloc(dmasz, GFP_KERNEL | GFP_DMA))) - return -ENOMEM; - dma_init_transmit(sm); - dma_init_receive(sm); - - memset(&sm->m, 0, sizeof(sm->m)); - memset(&sm->d, 0, sizeof(sm->d)); - if (sm->mode_tx->init) - sm->mode_tx->init(sm); - if (sm->mode_rx->init) - sm->mode_rx->init(sm); - - if (request_dma(dev->dma, sm->hwdrv->hw_name)) { - kfree(sm->dma.obuf); - return -EBUSY; - } - if (request_irq(dev->irq, wss_interrupt, SA_INTERRUPT, - sm->hwdrv->hw_name, dev)) { - free_dma(dev->dma); - kfree(sm->dma.obuf); - return -EBUSY; - } - request_region(dev->base_addr, WSS_EXTENT, sm->hwdrv->hw_name); - setup_dma_wss(dev, sm, 0); - return 0; -} - -/* --------------------------------------------------------------------- */ - -static int wss_close(struct net_device *dev, struct sm_state *sm) -{ - if (!dev || !sm) - return -EINVAL; - /* - * disable interrupts - */ - disable_dma(dev->dma); - write_codec(dev, 9, 0xc); /* disable codec */ - free_irq(dev->irq, dev); - free_dma(dev->dma); - release_region(dev->base_addr, WSS_EXTENT); - kfree(sm->dma.obuf); - return 0; -} - -/* --------------------------------------------------------------------- */ - -static int wss_sethw(struct net_device *dev, struct sm_state *sm, char *mode) -{ - char *cp = strchr(mode, '.'); - const struct modem_tx_info **mtp = sm_modem_tx_table; - const struct modem_rx_info **mrp; - int i, j; - - if (!strcmp(mode, "off")) { - sm->mode_tx = NULL; - sm->mode_rx = NULL; - return 0; - } - if (cp) - *cp++ = '\0'; - else - cp = mode; - for (; *mtp; mtp++) { - if ((*mtp)->loc_storage > sizeof(sm->m)) { - printk(KERN_ERR "%s: insufficient storage for modulator %s (%d)\n", - sm_drvname, (*mtp)->name, (*mtp)->loc_storage); - continue; - } - if (!(*mtp)->name || strcmp((*mtp)->name, mode)) - continue; - if ((i = wss_srate_index((*mtp)->srate)) < 0) - continue; - for (mrp = sm_modem_rx_table; *mrp; mrp++) { - if ((*mrp)->loc_storage > sizeof(sm->d)) { - printk(KERN_ERR "%s: insufficient storage for demodulator %s (%d)\n", - sm_drvname, (*mrp)->name, (*mrp)->loc_storage); - continue; - } - if ((*mrp)->name && !strcmp((*mrp)->name, cp) && - ((j = wss_srate_index((*mrp)->srate)) >= 0)) { - sm->mode_tx = *mtp; - sm->mode_rx = *mrp; - SCSTATE->fmt[0] = j; - SCSTATE->fmt[1] = i; - sm->dma.ifragsz = (sm->mode_rx->srate + 50)/100; - sm->dma.ofragsz = (sm->mode_tx->srate + 50)/100; - if (sm->dma.ifragsz < sm->mode_rx->overlap) - sm->dma.ifragsz = sm->mode_rx->overlap; - /* prefer same data format if possible to minimize switching times */ - sm->dma.i16bit = sm->dma.o16bit = 2; - if (sm->mode_rx->srate == sm->mode_tx->srate) { - if (sm->mode_rx->demodulator_s16 && sm->mode_tx->modulator_s16) - sm->dma.i16bit = sm->dma.o16bit = 1; - else if (sm->mode_rx->demodulator_u8 && sm->mode_tx->modulator_u8) - sm->dma.i16bit = sm->dma.o16bit = 0; - } - if (sm->dma.i16bit == 2) { - if (sm->mode_rx->demodulator_s16) - sm->dma.i16bit = 1; - else if (sm->mode_rx->demodulator_u8) - sm->dma.i16bit = 0; - } - if (sm->dma.o16bit == 2) { - if (sm->mode_tx->modulator_s16) - sm->dma.o16bit = 1; - else if (sm->mode_tx->modulator_u8) - sm->dma.o16bit = 0; - } - if (sm->dma.i16bit == 2 || sm->dma.o16bit == 2) { - printk(KERN_INFO "%s: mode %s or %s unusable\n", sm_drvname, - sm->mode_rx->name, sm->mode_tx->name); - sm->mode_tx = NULL; - sm->mode_rx = NULL; - return -EINVAL; - } -#ifdef __BIG_ENDIAN - /* big endian 16bit only works on crystal cards... */ - if (sm->dma.i16bit) { - SCSTATE->fmt[0] |= 0xc0; - sm->dma.ifragsz <<= 1; - } - if (sm->dma.o16bit) { - SCSTATE->fmt[1] |= 0xc0; - sm->dma.ofragsz <<= 1; - } -#else /* __BIG_ENDIAN */ - if (sm->dma.i16bit) { - SCSTATE->fmt[0] |= 0x40; - sm->dma.ifragsz <<= 1; - } - if (sm->dma.o16bit) { - SCSTATE->fmt[1] |= 0x40; - sm->dma.ofragsz <<= 1; - } -#endif /* __BIG_ENDIAN */ - return 0; - } - } - } - return -EINVAL; -} - -/* --------------------------------------------------------------------- */ - -static int wss_ioctl(struct net_device *dev, struct sm_state *sm, struct ifreq *ifr, - struct hdlcdrv_ioctl *hi, int cmd) -{ - struct sm_ioctl bi; - int i; - - if (cmd != SIOCDEVPRIVATE) - return -ENOIOCTLCMD; - - if (hi->cmd == HDLCDRVCTL_MODEMPARMASK) - return HDLCDRV_PARMASK_IOBASE | HDLCDRV_PARMASK_IRQ | - HDLCDRV_PARMASK_DMA | HDLCDRV_PARMASK_SERIOBASE | - HDLCDRV_PARMASK_PARIOBASE | HDLCDRV_PARMASK_MIDIIOBASE; - - if (copy_from_user(&bi, ifr->ifr_data, sizeof(bi))) - return -EFAULT; - - switch (bi.cmd) { - default: - return -ENOIOCTLCMD; - - case SMCTL_GETMIXER: - i = 0; - bi.data.mix.sample_rate = sm->mode_rx->srate; - bi.data.mix.bit_rate = sm->hdrv.par.bitrate; - bi.data.mix.mixer_type = SCSTATE->crystal ? - SM_MIXER_CRYSTAL : SM_MIXER_AD1848; - if (((SCSTATE->crystal ? 0x2c0c20fflu: 0x20fflu) - >> bi.data.mix.reg) & 1) { - bi.data.mix.data = read_codec(dev, bi.data.mix.reg); - i = 1; - } - if (copy_to_user(ifr->ifr_data, &bi, sizeof(bi))) - return -EFAULT; - return i; - - case SMCTL_SETMIXER: - if (!capable(CAP_SYS_RAWIO)) - return -EACCES; - if ((bi.data.mix.mixer_type != SM_MIXER_CRYSTAL || - !SCSTATE->crystal) && - (bi.data.mix.mixer_type != SM_MIXER_AD1848 || - bi.data.mix.reg >= 0x10)) - return -EINVAL; - if (!((0x2c0c20fflu >> bi.data.mix.reg) & 1)) - return -EACCES; - write_codec(dev, bi.data.mix.reg, bi.data.mix.data); - return 0; - - } - if (copy_to_user(ifr->ifr_data, &bi, sizeof(bi))) - return -EFAULT; - return 0; - -} - -/* --------------------------------------------------------------------- */ - -const struct hardware_info sm_hw_wss = { - "wss", sizeof(struct sc_state_wss), - wss_open, wss_close, wss_ioctl, wss_sethw -}; - -/* --------------------------------------------------------------------- */ - -static void setup_fdx_dma_wss(struct net_device *dev, struct sm_state *sm) -{ - unsigned long flags; - unsigned char oldcodecmode, codecdma; - long abrt; - unsigned int osamps, isamps; - - save_flags(flags); - cli(); - /* - * perform the final DMA sequence to disable the codec request - */ - oldcodecmode = read_codec(dev, 9); - write_codec(dev, 9, 0); /* disable codec DMA */ - wss_ack_int(dev); - if ((codecdma = read_codec(dev, 11)) & 0x10) { - dma_setup(sm, 1, dev->dma); - dma_setup(sm, 0, sm->hdrv.ptt_out.dma2); - abrt = 0; - while (((codecdma = read_codec(dev, 11)) & 0x10) || ((++abrt) >= 0x10000)); - } - wss_set_codec_fmt(dev, sm, SCSTATE->fmt[1], SCSTATE->fmt[0], 1, 1); - osamps = dma_setup(sm, 1, dev->dma) - 1; - isamps = dma_setup(sm, 0, sm->hdrv.ptt_out.dma2) - 1; - write_codec(dev, 15, osamps & 0xff); - write_codec(dev, 14, osamps >> 8); - if (SCSTATE->crystal) { - write_codec(dev, 31, isamps & 0xff); - write_codec(dev, 30, isamps >> 8); - } - write_codec(dev, 9, 3); - restore_flags(flags); -} - -/* --------------------------------------------------------------------- */ - -static void wssfdx_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - struct net_device *dev = (struct net_device *)dev_id; - struct sm_state *sm = (struct sm_state *)dev->priv; - unsigned long flags; - unsigned char cry_int_src; - unsigned icfrag, ocfrag, isamps, osamps; - - if (!dev || !sm || !sm->mode_rx || !sm->mode_tx || - sm->hdrv.magic != HDLCDRV_MAGIC) - return; - save_flags(flags); - cli(); - if (SCSTATE->crystal) { - /* Crystal has an essentially different interrupt handler! */ - cry_int_src = read_codec(dev, 0x18); - wss_ack_int(dev); - if (cry_int_src & 0x10) { /* playback interrupt */ - disable_dma(dev->dma); - clear_dma_ff(dev->dma); - osamps = dma_ptr(sm, 1, dev->dma, &ocfrag)-1; - write_codec(dev, 15, osamps & 0xff); - write_codec(dev, 14, osamps >> 8); - enable_dma(dev->dma); - } - if (cry_int_src & 0x20) { /* capture interrupt */ - disable_dma(sm->hdrv.ptt_out.dma2); - clear_dma_ff(sm->hdrv.ptt_out.dma2); - isamps = dma_ptr(sm, 0, sm->hdrv.ptt_out.dma2, &icfrag)-1; - write_codec(dev, 31, isamps & 0xff); - write_codec(dev, 30, isamps >> 8); - enable_dma(sm->hdrv.ptt_out.dma2); - } - restore_flags(flags); - sm_int_freq(sm); - sti(); - if (cry_int_src & 0x10) { - if (dma_end_transmit(sm, ocfrag)) - dma_clear_transmit(sm); - dma_transmit(sm); - } - if (cry_int_src & 0x20) { - dma_receive(sm, icfrag); - hdlcdrv_arbitrate(dev, &sm->hdrv); - } - sm_output_status(sm); - hdlcdrv_transmitter(dev, &sm->hdrv); - hdlcdrv_receiver(dev, &sm->hdrv); - return; - } - wss_ack_int(dev); - disable_dma(dev->dma); - disable_dma(sm->hdrv.ptt_out.dma2); - clear_dma_ff(dev->dma); - clear_dma_ff(sm->hdrv.ptt_out.dma2); - osamps = dma_ptr(sm, 1, dev->dma, &ocfrag)-1; - isamps = dma_ptr(sm, 0, sm->hdrv.ptt_out.dma2, &icfrag)-1; - write_codec(dev, 15, osamps & 0xff); - write_codec(dev, 14, osamps >> 8); - if (SCSTATE->crystal) { - write_codec(dev, 31, isamps & 0xff); - write_codec(dev, 30, isamps >> 8); - } - enable_dma(dev->dma); - enable_dma(sm->hdrv.ptt_out.dma2); - restore_flags(flags); - sm_int_freq(sm); - sti(); - if (dma_end_transmit(sm, ocfrag)) - dma_clear_transmit(sm); - dma_transmit(sm); - dma_receive(sm, icfrag); - hdlcdrv_arbitrate(dev, &sm->hdrv); - sm_output_status(sm); - hdlcdrv_transmitter(dev, &sm->hdrv); - hdlcdrv_receiver(dev, &sm->hdrv); -} - -/* --------------------------------------------------------------------- */ - -static int wssfdx_open(struct net_device *dev, struct sm_state *sm) -{ - if (!dev || !sm || !sm->mode_rx || !sm->mode_tx) - return -ENXIO; - if (dev->base_addr <= 0 || dev->base_addr > 0x1000-WSS_EXTENT || - dev->irq < 2 || dev->irq > 15 || dev->dma > 3) - return -ENXIO; - if (check_region(dev->base_addr, WSS_EXTENT)) - return -EACCES; - /* - * check if a card is available - */ - if (wss_init_codec(dev, sm, 1, 1, 1, 0, 0, -45, -45)) - return -ENODEV; - /* - * initialize some variables - */ - if (!(sm->dma.ibuf = kmalloc(sm->dma.ifragsz * (NUM_FRAGMENTS+1), GFP_KERNEL | GFP_DMA))) - return -ENOMEM; - if (!(sm->dma.obuf = kmalloc(sm->dma.ofragsz * NUM_FRAGMENTS, GFP_KERNEL | GFP_DMA))) { - kfree(sm->dma.ibuf); - return -ENOMEM; - } - dma_init_transmit(sm); - dma_init_receive(sm); - - memset(&sm->m, 0, sizeof(sm->m)); - memset(&sm->d, 0, sizeof(sm->d)); - if (sm->mode_tx->init) - sm->mode_tx->init(sm); - if (sm->mode_rx->init) - sm->mode_rx->init(sm); - - if (request_dma(dev->dma, sm->hwdrv->hw_name)) { - kfree(sm->dma.ibuf); - kfree(sm->dma.obuf); - return -EBUSY; - } - if (request_dma(sm->hdrv.ptt_out.dma2, sm->hwdrv->hw_name)) { - kfree(sm->dma.ibuf); - kfree(sm->dma.obuf); - free_dma(dev->dma); - return -EBUSY; - } - if (request_irq(dev->irq, wssfdx_interrupt, SA_INTERRUPT, - sm->hwdrv->hw_name, dev)) { - kfree(sm->dma.ibuf); - kfree(sm->dma.obuf); - free_dma(dev->dma); - free_dma(sm->hdrv.ptt_out.dma2); - return -EBUSY; - } - request_region(dev->base_addr, WSS_EXTENT, sm->hwdrv->hw_name); - setup_fdx_dma_wss(dev, sm); - return 0; -} - -/* --------------------------------------------------------------------- */ - -static int wssfdx_close(struct net_device *dev, struct sm_state *sm) -{ - if (!dev || !sm) - return -EINVAL; - /* - * disable interrupts - */ - disable_dma(dev->dma); - disable_dma(sm->hdrv.ptt_out.dma2); - write_codec(dev, 9, 0xc); /* disable codec */ - free_irq(dev->irq, dev); - free_dma(dev->dma); - free_dma(sm->hdrv.ptt_out.dma2); - release_region(dev->base_addr, WSS_EXTENT); - kfree(sm->dma.ibuf); - kfree(sm->dma.obuf); - return 0; -} - -/* --------------------------------------------------------------------- */ - -static int wssfdx_sethw(struct net_device *dev, struct sm_state *sm, char *mode) -{ - char *cp = strchr(mode, '.'); - const struct modem_tx_info **mtp = sm_modem_tx_table; - const struct modem_rx_info **mrp; - int i; - - if (!strcmp(mode, "off")) { - sm->mode_tx = NULL; - sm->mode_rx = NULL; - return 0; - } - if (cp) - *cp++ = '\0'; - else - cp = mode; - for (; *mtp; mtp++) { - if ((*mtp)->loc_storage > sizeof(sm->m)) { - printk(KERN_ERR "%s: insufficient storage for modulator %s (%d)\n", - sm_drvname, (*mtp)->name, (*mtp)->loc_storage); - continue; - } - if (!(*mtp)->name || strcmp((*mtp)->name, mode)) - continue; - if ((i = wss_srate_index((*mtp)->srate)) < 0) - continue; - for (mrp = sm_modem_rx_table; *mrp; mrp++) { - if ((*mrp)->loc_storage > sizeof(sm->d)) { - printk(KERN_ERR "%s: insufficient storage for demodulator %s (%d)\n", - sm_drvname, (*mrp)->name, (*mrp)->loc_storage); - continue; - } - if ((*mrp)->name && !strcmp((*mrp)->name, cp) && - (*mtp)->srate == (*mrp)->srate) { - sm->mode_tx = *mtp; - sm->mode_rx = *mrp; - SCSTATE->fmt[0] = SCSTATE->fmt[1] = i; - sm->dma.ifragsz = sm->dma.ofragsz = (sm->mode_rx->srate + 50)/100; - if (sm->dma.ifragsz < sm->mode_rx->overlap) - sm->dma.ifragsz = sm->mode_rx->overlap; - sm->dma.i16bit = sm->dma.o16bit = 2; - if (sm->mode_rx->demodulator_s16) { - sm->dma.i16bit = 1; - sm->dma.ifragsz <<= 1; -#ifdef __BIG_ENDIAN /* big endian 16bit only works on crystal cards... */ - SCSTATE->fmt[0] |= 0xc0; -#else /* __BIG_ENDIAN */ - SCSTATE->fmt[0] |= 0x40; -#endif /* __BIG_ENDIAN */ - } else if (sm->mode_rx->demodulator_u8) - sm->dma.i16bit = 0; - if (sm->mode_tx->modulator_s16) { - sm->dma.o16bit = 1; - sm->dma.ofragsz <<= 1; -#ifdef __BIG_ENDIAN /* big endian 16bit only works on crystal cards... */ - SCSTATE->fmt[1] |= 0xc0; -#else /* __BIG_ENDIAN */ - SCSTATE->fmt[1] |= 0x40; -#endif /* __BIG_ENDIAN */ - } else if (sm->mode_tx->modulator_u8) - sm->dma.o16bit = 0; - if (sm->dma.i16bit == 2 || sm->dma.o16bit == 2) { - printk(KERN_INFO "%s: mode %s or %s unusable\n", sm_drvname, - sm->mode_rx->name, sm->mode_tx->name); - sm->mode_tx = NULL; - sm->mode_rx = NULL; - return -EINVAL; - } - return 0; - } - } - } - return -EINVAL; -} - -/* --------------------------------------------------------------------- */ - -static int wssfdx_ioctl(struct net_device *dev, struct sm_state *sm, struct ifreq *ifr, - struct hdlcdrv_ioctl *hi, int cmd) -{ - if (cmd != SIOCDEVPRIVATE) - return -ENOIOCTLCMD; - - if (hi->cmd == HDLCDRVCTL_MODEMPARMASK) - return HDLCDRV_PARMASK_IOBASE | HDLCDRV_PARMASK_IRQ | - HDLCDRV_PARMASK_DMA | HDLCDRV_PARMASK_DMA2 | - HDLCDRV_PARMASK_SERIOBASE | HDLCDRV_PARMASK_PARIOBASE | - HDLCDRV_PARMASK_MIDIIOBASE; - - return wss_ioctl(dev, sm, ifr, hi, cmd); -} - -/* --------------------------------------------------------------------- */ - -const struct hardware_info sm_hw_wssfdx = { - "wssfdx", sizeof(struct sc_state_wss), - wssfdx_open, wssfdx_close, wssfdx_ioctl, wssfdx_sethw -}; - -/* --------------------------------------------------------------------- */ - -#undef SCSTATE diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/net/pcmcia/smc91c92_cs.c linux.2.5.47-ac4/drivers/net/pcmcia/smc91c92_cs.c --- linux.2.5.47/drivers/net/pcmcia/smc91c92_cs.c 2002-11-11 16:39:10.000000000 +0000 +++ linux.2.5.47-ac4/drivers/net/pcmcia/smc91c92_cs.c 2002-11-13 15:22:31.000000000 +0000 @@ -358,6 +358,7 @@ memset(smc, 0, sizeof(struct smc_private)); link = &smc->link; dev = &smc->dev; spin_lock_init(&smc->lock); + init_timer(&link->release); link->release.function = &smc91c92_release; link->release.data = (u_long)link; link->io.NumPorts1 = 16; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/net/rrunner.c linux.2.5.47-ac4/drivers/net/rrunner.c --- linux.2.5.47/drivers/net/rrunner.c 2002-10-31 14:57:04.000000000 +0000 +++ linux.2.5.47-ac4/drivers/net/rrunner.c 2002-11-13 15:13:33.000000000 +0000 @@ -1,7 +1,7 @@ /* * rrunner.c: Linux driver for the Essential RoadRunner HIPPI board. * - * Copyright (C) 1998-2000 by Jes Sorensen, . + * Copyright (C) 1998-2002 by Jes Sorensen, . * * Thanks to Essential Communication for providing us with hardware * and very comprehensive documentation without which I would not have @@ -19,9 +19,10 @@ * * Softnet support and various other patches from Val Henson of * ODS/Essential. + * + * PCI DMA mapping code partly based on work by Francois Romieu. */ -#error Please convert me to Documentation/DMA-mapping.txt #define DEBUG 1 #define RX_DMA_SKBUFF 1 @@ -50,45 +51,20 @@ #include #include -#if (LINUX_VERSION_CODE < 0x02030e) -#define net_device device -#endif - -#if (LINUX_VERSION_CODE >= 0x02031b) -#define NEW_NETINIT -#endif - -#if (LINUX_VERSION_CODE < 0x02032b) -/* - * SoftNet changes - */ -#define dev_kfree_skb_irq(a) dev_kfree_skb(a) -#define netif_wake_queue(dev) clear_bit(0, &dev->tbusy) -#define netif_stop_queue(dev) set_bit(0, &dev->tbusy) - -static inline void netif_start_queue(struct net_device *dev) -{ - dev->tbusy = 0; - dev->start = 1; -} - -#define rr_mark_net_bh(foo) mark_bh(foo) -#define rr_if_busy(dev) dev->tbusy -#define rr_if_running(dev) dev->start /* Currently unused. */ -#define rr_if_down(dev) do { dev->start = 0; } while (0) -#else -#define NET_BH 0 -#define rr_mark_net_bh(foo) do { } while(0) #define rr_if_busy(dev) netif_queue_stopped(dev) #define rr_if_running(dev) netif_running(dev) -#define rr_if_down(dev) do { } while(0) -#endif #include "rrunner.h" #define RUN_AT(x) (jiffies + (x)) +MODULE_AUTHOR("Jes Sorensen "); +MODULE_DESCRIPTION("Essential RoadRunner HIPPI driver"); +MODULE_LICENSE("GPL"); + +static char version[] __initdata = "rrunner.c: v0.50 11/11/2002 Jes Sorensen (jes@wildopensource.com)\n"; + /* * Implementation notes: * @@ -104,11 +80,6 @@ * stack will need to know about I/O vectors or something similar. */ -static char version[] __initdata = "rrunner.c: v0.22 03/01/2000 Jes Sorensen (Jes.Sorensen@cern.ch)\n"; - -static struct net_device *root_dev; - - /* * These are checked at init time to see if they are at least 256KB * and increased to 256KB if they are not. This is done to avoid ending @@ -117,200 +88,185 @@ extern __u32 sysctl_wmem_max; extern __u32 sysctl_rmem_max; -static int probed __initdata = 0; - -#if LINUX_VERSION_CODE >= 0x20400 -static struct pci_device_id rrunner_pci_tbl[] __initdata = { - { PCI_VENDOR_ID_ESSENTIAL, PCI_DEVICE_ID_ESSENTIAL_ROADRUNNER, PCI_ANY_ID, PCI_ANY_ID, }, - { } /* Terminating entry */ -}; -MODULE_DEVICE_TABLE(pci, rrunner_pci_tbl); -#endif /* LINUX_VERSION_CODE >= 0x20400 */ - -#ifdef NEW_NETINIT -int __init rr_hippi_probe (void) -#else -int __init rr_hippi_probe (struct net_device *dev) -#endif +static int __devinit rr_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) { -#ifdef NEW_NETINIT struct net_device *dev; -#endif - int boards_found = 0; - int version_disp; /* was version info already displayed? */ - struct pci_dev *pdev = NULL; - struct pci_dev *opdev = NULL; + static int version_disp; u8 pci_latency; struct rr_private *rrpriv; + void *tmpptr; + dma_addr_t ring_dma; + int ret; - if (probed) - return -ENODEV; - probed++; - - version_disp = 0; - - while((pdev = pci_find_device(PCI_VENDOR_ID_ESSENTIAL, - PCI_DEVICE_ID_ESSENTIAL_ROADRUNNER, - pdev))) - { - if (pci_enable_device(pdev)) - continue; + dev = init_hippi_dev(NULL, sizeof(struct rr_private)); + if (!dev) { + ret = -ENOMEM; + goto out2; + } - if (pdev == opdev) - return 0; + ret = pci_enable_device(pdev); + if (ret) { + ret = -ENODEV; + goto out2; + } - /* - * So we found our HIPPI ... time to tell the system. - */ + if (!dev->priv) + dev->priv = kmalloc(sizeof(*rrpriv), GFP_KERNEL); - dev = init_hippi_dev(NULL, sizeof(struct rr_private)); + if (!dev->priv) { + ret = -ENOMEM; + goto out2; + } - if (!dev) - break; + rrpriv = (struct rr_private *)dev->priv; + memset(rrpriv, 0, sizeof(*rrpriv)); - if (!dev->priv) - dev->priv = kmalloc(sizeof(*rrpriv), GFP_KERNEL); + SET_MODULE_OWNER(dev); - if (!dev->priv) - return -ENOMEM; + if (pci_request_regions(pdev, "rrunner")) { + ret = -EIO; + goto out; + } - rrpriv = (struct rr_private *)dev->priv; - memset(rrpriv, 0, sizeof(*rrpriv)); + pci_set_drvdata(pdev, dev); -#ifdef CONFIG_SMP - spin_lock_init(&rrpriv->lock); -#endif - sprintf(rrpriv->name, "RoadRunner serial HIPPI"); + rrpriv->pci_dev = pdev; - dev->irq = pdev->irq; - SET_MODULE_OWNER(dev); - dev->open = &rr_open; - dev->hard_start_xmit = &rr_start_xmit; - dev->stop = &rr_close; - dev->get_stats = &rr_get_stats; - dev->do_ioctl = &rr_ioctl; + spin_lock_init(&rrpriv->lock); + sprintf(rrpriv->name, "RoadRunner serial HIPPI"); -#if (LINUX_VERSION_CODE < 0x02030d) - dev->base_addr = pdev->base_address[0]; -#else - dev->base_addr = pdev->resource[0].start; -#endif + dev->irq = pdev->irq; + dev->open = &rr_open; + dev->hard_start_xmit = &rr_start_xmit; + dev->stop = &rr_close; + dev->get_stats = &rr_get_stats; + dev->do_ioctl = &rr_ioctl; - /* display version info if adapter is found */ - if (!version_disp) - { - /* set display flag to TRUE so that */ - /* we only display this string ONCE */ - version_disp = 1; - printk(version); - } - - pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency); - if (pci_latency <= 0x58){ - pci_latency = 0x58; - pci_write_config_byte(pdev, PCI_LATENCY_TIMER, - pci_latency); - } - - pci_set_master(pdev); - - printk(KERN_INFO "%s: Essential RoadRunner serial HIPPI " - "at 0x%08lx, irq %i, PCI latency %i\n", dev->name, - dev->base_addr, dev->irq, pci_latency); + dev->base_addr = pci_resource_start(pdev, 0); - /* - * Remap the regs into kernel space. - */ + /* display version info if adapter is found */ + if (!version_disp) { + /* set display flag to TRUE so that */ + /* we only display this string ONCE */ + version_disp = 1; + printk(version); + } - rrpriv->regs = (struct rr_regs *) - ioremap(dev->base_addr, 0x1000); + pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency); + if (pci_latency <= 0x58){ + pci_latency = 0x58; + pci_write_config_byte(pdev, PCI_LATENCY_TIMER, pci_latency); + } - if (!rrpriv->regs){ - printk(KERN_ERR "%s: Unable to map I/O register, " - "RoadRunner %i will be disabled.\n", - dev->name, boards_found); - break; - } + pci_set_master(pdev); - /* - * Don't access any registes before this point! - */ -#ifdef __BIG_ENDIAN - writel(readl(®s->HostCtrl) | NO_SWAP, ®s->HostCtrl); -#endif - /* - * Need to add a case for little-endian 64-bit hosts here. - */ + printk(KERN_INFO "%s: Essential RoadRunner serial HIPPI " + "at 0x%08lx, irq %i, PCI latency %i\n", dev->name, + dev->base_addr, dev->irq, pci_latency); + + /* + * Remap the regs into kernel space. + */ - rr_init(dev); + rrpriv->regs = (struct rr_regs *)ioremap(dev->base_addr, 0x1000); - boards_found++; - dev->base_addr = 0; - dev = NULL; - opdev = pdev; + if (!rrpriv->regs){ + printk(KERN_ERR "%s: Unable to map I/O register, " + "RoadRunner will be disabled.\n", dev->name); + ret = -EIO; + goto out; } - /* - * If we're at this point we're going through rr_hippi_probe() - * for the first time. Return success (0) if we've initialized - * 1 or more boards. Otherwise, return failure (-ENODEV). - */ + tmpptr = pci_alloc_consistent(pdev, TX_TOTAL_SIZE, &ring_dma); + rrpriv->tx_ring = tmpptr; + rrpriv->tx_ring_dma = ring_dma; -#ifdef MODULE - return boards_found; -#else - if (boards_found > 0) - return 0; - else - return -ENODEV; -#endif -} + if (!tmpptr) { + ret = -ENOMEM; + goto out; + } + tmpptr = pci_alloc_consistent(pdev, RX_TOTAL_SIZE, &ring_dma); + rrpriv->rx_ring = tmpptr; + rrpriv->rx_ring_dma = ring_dma; -#ifdef MODULE -#if LINUX_VERSION_CODE > 0x20118 -MODULE_AUTHOR("Jes Sorensen "); -MODULE_DESCRIPTION("Essential RoadRunner HIPPI driver"); -MODULE_LICENSE("GPL"); -#endif + if (!tmpptr) { + ret = -ENOMEM; + goto out; + } -int init_module(void) -{ - int cards; + tmpptr = pci_alloc_consistent(pdev, EVT_RING_SIZE, &ring_dma); + rrpriv->evt_ring = tmpptr; + rrpriv->evt_ring_dma = ring_dma; - root_dev = NULL; + if (!tmpptr) { + ret = -ENOMEM; + goto out; + } -#ifdef NEW_NETINIT - cards = rr_hippi_probe(); -#else - cards = rr_hippi_probe(NULL); + /* + * Don't access any register before this point! + */ +#ifdef __BIG_ENDIAN + writel(readl(®s->HostCtrl) | NO_SWAP, ®s->HostCtrl); #endif - return cards ? 0 : -ENODEV; + /* + * Need to add a case for little-endian 64-bit hosts here. + */ + + rr_init(dev); + + dev->base_addr = 0; + return 0; + + out: + if (rrpriv->rx_ring) + pci_free_consistent(pdev, RX_TOTAL_SIZE, rrpriv->rx_ring, + rrpriv->rx_ring_dma); + if (rrpriv->tx_ring) + pci_free_consistent(pdev, TX_TOTAL_SIZE, rrpriv->tx_ring, + rrpriv->tx_ring_dma); + if (rrpriv->regs) + iounmap(rrpriv->regs); + if (pdev) { + pci_release_regions(pdev); + pci_set_drvdata(pdev, NULL); + } + + out2: + if (dev) { + unregister_hipdev(dev); + kfree(dev); + } + return ret; } -void cleanup_module(void) +static void __devexit rr_remove_one (struct pci_dev *pdev) { - struct rr_private *rr; - struct net_device *next; - - while (root_dev) { - next = ((struct rr_private *)root_dev->priv)->next; - rr = (struct rr_private *)root_dev->priv; + struct net_device *dev = pci_get_drvdata(pdev); + struct rr_private *rr = (struct rr_private *)dev->priv; + if (dev) { if (!(readl(&rr->regs->HostCtrl) & NIC_HALTED)){ printk(KERN_ERR "%s: trying to unload running NIC\n", - root_dev->name); + dev->name); writel(HALT_NIC, &rr->regs->HostCtrl); } + pci_free_consistent(pdev, EVT_RING_SIZE, rr->evt_ring, + rr->evt_ring_dma); + pci_free_consistent(pdev, RX_TOTAL_SIZE, rr->rx_ring, + rr->rx_ring_dma); + pci_free_consistent(pdev, TX_TOTAL_SIZE, rr->tx_ring, + rr->tx_ring_dma); + unregister_hipdev(dev); iounmap(rr->regs); - unregister_hipdev(root_dev); - kfree(root_dev); - - root_dev = next; + kfree(dev); + pci_release_regions(pdev); + pci_set_drvdata(pdev, NULL); } } -#endif /* @@ -634,9 +590,6 @@ sysctl_wmem_max = 262144; } - rrpriv->next = root_dev; - root_dev = dev; - return 0; } @@ -668,14 +621,14 @@ goto error; } - set_rxaddr(regs, rrpriv->rx_ctrl); - set_infoaddr(regs, rrpriv->info); + set_rxaddr(regs, rrpriv->rx_ctrl_dma); + set_infoaddr(regs, rrpriv->info_dma); rrpriv->info->evt_ctrl.entry_size = sizeof(struct event); rrpriv->info->evt_ctrl.entries = EVT_RING_ENTRIES; rrpriv->info->evt_ctrl.mode = 0; rrpriv->info->evt_ctrl.pi = 0; - set_rraddr(&rrpriv->info->evt_ctrl.rngptr, rrpriv->evt_ring); + set_rraddr(&rrpriv->info->evt_ctrl.rngptr, rrpriv->evt_ring_dma); rrpriv->info->cmd_ctrl.entry_size = sizeof(struct cmd); rrpriv->info->cmd_ctrl.entries = CMD_RING_ENTRIES; @@ -695,7 +648,7 @@ rrpriv->info->tx_ctrl.entries = TX_RING_ENTRIES; rrpriv->info->tx_ctrl.mode = 0; rrpriv->info->tx_ctrl.pi = 0; - set_rraddr(&rrpriv->info->tx_ctrl.rngptr, rrpriv->tx_ring); + set_rraddr(&rrpriv->info->tx_ctrl.rngptr, rrpriv->tx_ring_dma); /* * Set dirty_tx before we start receiving interrupts, otherwise @@ -730,6 +683,7 @@ for (i = 0; i < RX_RING_ENTRIES; i++) { struct sk_buff *skb; + dma_addr_t addr; rrpriv->rx_ring[i].mode = 0; skb = alloc_skb(dev->mtu + HIPPI_HLEN, GFP_ATOMIC); @@ -740,6 +694,8 @@ goto error; } rrpriv->rx_skbuff[i] = skb; + addr = pci_map_single(rrpriv->pci_dev, skb->data, + dev->mtu + HIPPI_HLEN, PCI_DMA_FROMDEVICE); /* * Sanity test to see if we conflict with the DMA * limitations of the Roadrunner. @@ -747,7 +703,7 @@ if ((((unsigned long)skb->data) & 0xfff) > ~65320) printk("skb alloc error\n"); - set_rraddr(&rrpriv->rx_ring[i].addr, skb->data); + set_rraddr(&rrpriv->rx_ring[i].addr, addr); rrpriv->rx_ring[i].size = dev->mtu + HIPPI_HLEN; } @@ -756,7 +712,7 @@ rrpriv->rx_ctrl[4].mode = 8; rrpriv->rx_ctrl[4].pi = 0; wmb(); - set_rraddr(&rrpriv->rx_ctrl[4].rngptr, rrpriv->rx_ring); + set_rraddr(&rrpriv->rx_ctrl[4].rngptr, rrpriv->rx_ring_dma); udelay(1000); @@ -785,10 +741,17 @@ * make sure we release everything we allocated before failing */ for (i = 0; i < RX_RING_ENTRIES; i++) { - if (rrpriv->rx_skbuff[i]) { + struct sk_buff *skb = rrpriv->rx_skbuff[i]; + + if (skb) { + pci_unmap_single(rrpriv->pci_dev, + rrpriv->rx_ring[i].addr.addrlo, + dev->mtu + HIPPI_HLEN, + PCI_DMA_FROMDEVICE); rrpriv->rx_ring[i].size = 0; set_rraddr(&rrpriv->rx_ring[i].addr, 0); - dev_kfree_skb(rrpriv->rx_skbuff[i]); + dev_kfree_skb(skb); + rrpriv->rx_skbuff[i] = 0; } } return ecode; @@ -1009,12 +972,14 @@ struct rr_regs *regs = rrpriv->regs; do { + struct rx_desc *desc; u32 pkt_len; - pkt_len = rrpriv->rx_ring[index].size; + + desc = &(rrpriv->rx_ring[index]); + pkt_len = desc->size; #if (DEBUG > 2) printk("index %i, rxlimit %i\n", index, rxlimit); - printk("len %x, mode %x\n", pkt_len, - rrpriv->rx_ring[index].mode); + printk("len %x, mode %x\n", pkt_len, desc->mode); #endif if ( (rrpriv->rx_ring[index].mode & PACKET_BAD) == PACKET_BAD){ rrpriv->stats.rx_dropped++; @@ -1022,7 +987,12 @@ } if (pkt_len > 0){ - struct sk_buff *skb; + struct sk_buff *skb, *rx_skb; + + rx_skb = rrpriv->rx_skbuff[index]; + + pci_dma_sync_single(rrpriv->pci_dev, desc->addr.addrlo, + pkt_len, PCI_DMA_FROMDEVICE); if (pkt_len < PKT_COPY_THRESHOLD) { skb = alloc_skb(pkt_len, GFP_ATOMIC); @@ -1032,19 +1002,27 @@ goto defer; }else memcpy(skb_put(skb, pkt_len), - rrpriv->rx_skbuff[index]->data, - pkt_len); + rx_skb->data, pkt_len); }else{ struct sk_buff *newskb; newskb = alloc_skb(dev->mtu + HIPPI_HLEN, - GFP_ATOMIC); + GFP_ATOMIC); if (newskb){ - skb = rrpriv->rx_skbuff[index]; + dma_addr_t addr; + + pci_unmap_single(rrpriv->pci_dev, + desc->addr.addrlo, dev->mtu + + HIPPI_HLEN, PCI_DMA_FROMDEVICE); + skb = rx_skb; skb_put(skb, pkt_len); rrpriv->rx_skbuff[index] = newskb; - set_rraddr(&rrpriv->rx_ring[index].addr, newskb->data); - }else{ + addr = pci_map_single(rrpriv->pci_dev, + newskb->data, + dev->mtu + HIPPI_HLEN, + PCI_DMA_FROMDEVICE); + set_rraddr(&desc->addr, addr); + } else { printk("%s: Out of memory, deferring " "packet\n", dev->name); rrpriv->stats.rx_dropped++; @@ -1061,8 +1039,8 @@ rrpriv->stats.rx_bytes += pkt_len; } defer: - rrpriv->rx_ring[index].mode = 0; - rrpriv->rx_ring[index].size = dev->mtu + HIPPI_HLEN; + desc->mode = 0; + desc->size = dev->mtu + HIPPI_HLEN; if ((index & 7) == 7) writel(index, ®s->IpRxPi); @@ -1120,14 +1098,24 @@ * of sync. error need to check entry in ring -kbf */ if(rrpriv->tx_skbuff[txcon]){ + struct tx_desc *desc; + struct sk_buff *skb; + + desc = &(rrpriv->tx_ring[txcon]); + skb = rrpriv->tx_skbuff[txcon]; + rrpriv->stats.tx_packets++; - rrpriv->stats.tx_bytes +=rrpriv->tx_skbuff[txcon]->len; - dev_kfree_skb_irq(rrpriv->tx_skbuff[txcon]); + rrpriv->stats.tx_bytes += skb->len; + + pci_unmap_single(rrpriv->pci_dev, + desc->addr.addrlo, skb->len, + PCI_DMA_TODEVICE); + dev_kfree_skb_irq(skb); rrpriv->tx_skbuff[txcon] = NULL; - rrpriv->tx_ring[txcon].size = 0; + desc->size = 0; set_rraddr(&rrpriv->tx_ring[txcon].addr, 0); - rrpriv->tx_ring[txcon].mode = 0; + desc->mode = 0; } txcon = (txcon + 1) % TX_RING_ENTRIES; } while (txcsmr != txcon); @@ -1139,7 +1127,6 @@ != rrpriv->dirty_tx)){ rrpriv->tx_full = 0; netif_wake_queue(dev); - rr_mark_net_bh(NET_BH); } } @@ -1164,6 +1151,7 @@ memset(rrpriv->rx_ctrl, 0, 256 * sizeof(struct ring_ctrl)); memset(rrpriv->info, 0, sizeof(struct rr_info)); wmb(); + for (i = 0; i < TX_RING_ENTRIES; i++) { if (rrpriv->tx_skbuff[i]) { rrpriv->tx_ring[i].size = 0; @@ -1181,6 +1169,7 @@ rrpriv->rx_skbuff[i] = NULL; } } + if (rr_init1(dev)) { spin_lock_irqsave(&rrpriv->lock, flags); writel(readl(®s->HostCtrl)|HALT_NIC|RR_CLEAR_INT, @@ -1195,12 +1184,13 @@ static int rr_open(struct net_device *dev) { - struct rr_private *rrpriv; + struct rr_private *rrpriv = (struct rr_private *)dev->priv; + struct pci_dev *pdev = rrpriv->pci_dev; struct rr_regs *regs; int ecode = 0; unsigned long flags; + dma_addr_t dma_addr; - rrpriv = (struct rr_private *)dev->priv; regs = rrpriv->regs; if (rrpriv->fw_rev < 0x00020000) { @@ -1210,24 +1200,29 @@ goto error; } - rrpriv->rx_ctrl = kmalloc(256*sizeof(struct ring_ctrl), GFP_KERNEL); + rrpriv->rx_ctrl = pci_alloc_consistent(pdev, + 256 * sizeof(struct ring_ctrl), + &dma_addr); if (!rrpriv->rx_ctrl) { ecode = -ENOMEM; goto error; } + rrpriv->rx_ctrl_dma = dma_addr; + memset(rrpriv->rx_ctrl, 0, 256*sizeof(struct ring_ctrl)); - rrpriv->info = kmalloc(sizeof(struct rr_info), GFP_KERNEL); - if (!rrpriv->info){ - rrpriv->rx_ctrl = NULL; + rrpriv->info = pci_alloc_consistent(pdev, sizeof(struct rr_info), + &dma_addr); + if (!rrpriv->info) { ecode = -ENOMEM; goto error; } - memset(rrpriv->rx_ctrl, 0, 256 * sizeof(struct ring_ctrl)); + rrpriv->info_dma = dma_addr; memset(rrpriv->info, 0, sizeof(struct rr_info)); wmb(); spin_lock_irqsave(&rrpriv->lock, flags); writel(readl(®s->HostCtrl)|HALT_NIC|RR_CLEAR_INT, ®s->HostCtrl); + readl(®s->HostCtrl); spin_unlock_irqrestore(&rrpriv->lock, flags); if (request_irq(dev->irq, rr_interrupt, SA_SHIRQ, rrpriv->name, dev)) @@ -1251,6 +1246,7 @@ netif_start_queue(dev); + MOD_INC_USE_COUNT; return ecode; error: @@ -1268,12 +1264,54 @@ } netif_stop_queue(dev); - rr_if_down(dev); return ecode; } +static inline void rr_raz_tx(struct rr_private *rrpriv, + struct net_device *dev) +{ + int i; + + for (i = 0; i < TX_RING_ENTRIES; i++) { + struct sk_buff *skb = rrpriv->tx_skbuff[i]; + + if (skb) { + struct tx_desc *desc = &(rrpriv->tx_ring[i]); + + pci_unmap_single(rrpriv->pci_dev, desc->addr.addrlo, + skb->len, PCI_DMA_TODEVICE); + desc->size = 0; + set_rraddr(&desc->addr, 0); + dev_kfree_skb(skb); + rrpriv->tx_skbuff[i] = NULL; + } + } +} + + +static inline void rr_raz_rx(struct rr_private *rrpriv, + struct net_device *dev) +{ + int i; + + for (i = 0; i < RX_RING_ENTRIES; i++) { + struct sk_buff *skb = rrpriv->rx_skbuff[i]; + + if (skb) { + struct rx_desc *desc = &(rrpriv->rx_ring[i]); + + pci_unmap_single(rrpriv->pci_dev, desc->addr.addrlo, + dev->mtu + HIPPI_HLEN, PCI_DMA_FROMDEVICE); + desc->size = 0; + set_rraddr(&desc->addr, 0); + dev_kfree_skb(skb); + rrpriv->rx_skbuff[i] = NULL; + } + } +} + static void rr_dump(struct net_device *dev) { struct rr_private *rrpriv; @@ -1313,11 +1351,10 @@ if (rrpriv->tx_skbuff[cons]){ len = min_t(int, 0x80, rrpriv->tx_skbuff[cons]->len); printk("skbuff for cons %i is valid - dumping data (0x%x bytes - skbuff len 0x%x)\n", cons, len, rrpriv->tx_skbuff[cons]->len); - printk("mode 0x%x, size 0x%x,\n phys %08x (virt %08lx), skbuff-addr %08lx, truesize 0x%x\n", + printk("mode 0x%x, size 0x%x,\n phys %08x, skbuff-addr %08lx, truesize 0x%x\n", rrpriv->tx_ring[cons].mode, rrpriv->tx_ring[cons].size, rrpriv->tx_ring[cons].addr.addrlo, - (unsigned long)bus_to_virt(rrpriv->tx_ring[cons].addr.addrlo), (unsigned long)rrpriv->tx_skbuff[cons]->data, (unsigned int)rrpriv->tx_skbuff[cons]->truesize); for (i = 0; i < len; i++){ @@ -1342,20 +1379,20 @@ { struct rr_private *rrpriv; struct rr_regs *regs; + unsigned long flags; u32 tmp; short i; netif_stop_queue(dev); - rr_if_down(dev); - + rrpriv = (struct rr_private *)dev->priv; regs = rrpriv->regs; /* * Lock to make sure we are not cleaning up while another CPU - * handling interrupts. + * is handling interrupts. */ - spin_lock(&rrpriv->lock); + spin_lock_irqsave(&rrpriv->lock, flags); tmp = readl(®s->HostCtrl); if (tmp & NIC_HALTED){ @@ -1364,12 +1401,12 @@ }else{ tmp |= HALT_NIC | RR_CLEAR_INT; writel(tmp, ®s->HostCtrl); - wmb(); + readl(®s->HostCtrl); } rrpriv->fw_running = 0; - del_timer(&rrpriv->timer); + del_timer_sync(&rrpriv->timer); writel(0, ®s->TxPi); writel(0, ®s->IpRxPi); @@ -1403,18 +1440,18 @@ } } - if (rrpriv->rx_ctrl) { - kfree(rrpriv->rx_ctrl); - rrpriv->rx_ctrl = NULL; - } - if (rrpriv->info) { - kfree(rrpriv->info); - rrpriv->info = NULL; - } + pci_free_consistent(rrpriv->pci_dev, 256 * sizeof(struct ring_ctrl), + rrpriv->rx_ctrl, rrpriv->rx_ctrl_dma); + rrpriv->rx_ctrl = NULL; + + pci_free_consistent(rrpriv->pci_dev, sizeof(struct rr_info), + rrpriv->info, rrpriv->info_dma); + rrpriv->info = NULL; free_irq(dev->irq, dev); - spin_unlock(&rrpriv->lock); + spin_unlock_irqrestore(&rrpriv->lock, flags); + MOD_DEC_USE_COUNT; return 0; } @@ -1467,7 +1504,8 @@ index = txctrl->pi; rrpriv->tx_skbuff[index] = skb; - set_rraddr(&rrpriv->tx_ring[index].addr, skb->data); + set_rraddr(&rrpriv->tx_ring[index].addr, pci_map_single( + rrpriv->pci_dev, skb->data, len + 8, PCI_DMA_TODEVICE)); rrpriv->tx_ring[index].size = len + 8; /* include IFIELD */ rrpriv->tx_ring[index].mode = PACKET_START | PACKET_END; txctrl->pi = (index + 1) % TX_RING_ENTRIES; @@ -1612,6 +1650,7 @@ { struct rr_private *rrpriv; unsigned char *image, *oldimage; + unsigned long flags; unsigned int i; int error = -EOPNOTSUPP; @@ -1629,25 +1668,27 @@ "for EEPROM image\n", dev->name); return -ENOMEM; } - - spin_lock(&rrpriv->lock); - + + if (rrpriv->fw_running){ printk("%s: Firmware already running\n", dev->name); error = -EPERM; - goto out_spin; + goto gf_out; } + spin_lock_irqsave(&rrpriv->lock, flags); i = rr_read_eeprom(rrpriv, 0, image, EEPROM_BYTES); if (i != EEPROM_BYTES){ - printk(KERN_ERR "%s: Error reading EEPROM\n", dev->name); + printk(KERN_ERR "%s: Error reading EEPROM\n", + dev->name); error = -EFAULT; - goto out_spin; + goto gf_out; } - spin_unlock(&rrpriv->lock); + spin_unlock_irqrestore(&rrpriv->lock, flags); error = copy_to_user(rq->ifr_data, image, EEPROM_BYTES); if (error) error = -EFAULT; + gf_out: kfree(image); return error; @@ -1657,56 +1698,52 @@ } image = kmalloc(EEPROM_WORDS * sizeof(u32), GFP_KERNEL); - if (!image){ - printk(KERN_ERR "%s: Unable to allocate memory " - "for EEPROM image\n", dev->name); - return -ENOMEM; - } - oldimage = kmalloc(EEPROM_WORDS * sizeof(u32), GFP_KERNEL); - if (!oldimage){ - kfree(image); + if (!image || !oldimage) { printk(KERN_ERR "%s: Unable to allocate memory " - "for old EEPROM image\n", dev->name); - return -ENOMEM; + "for EEPROM image\n", dev->name); + error = -ENOMEM; + goto wf_out; } error = copy_from_user(image, rq->ifr_data, EEPROM_BYTES); if (error) { - kfree(image); - kfree(oldimage); - return -EFAULT; + error = -EFAULT; + goto wf_out; } - spin_lock(&rrpriv->lock); if (rrpriv->fw_running){ - kfree(oldimage); printk("%s: Firmware already running\n", dev->name); error = -EPERM; - goto out_spin; + goto wf_out; } printk("%s: Updating EEPROM firmware\n", dev->name); + spin_lock_irqsave(&rrpriv->lock, flags); error = write_eeprom(rrpriv, 0, image, EEPROM_BYTES); if (error) printk(KERN_ERR "%s: Error writing EEPROM\n", dev->name); i = rr_read_eeprom(rrpriv, 0, oldimage, EEPROM_BYTES); + spin_unlock_irqrestore(&rrpriv->lock, flags); + if (i != EEPROM_BYTES) printk(KERN_ERR "%s: Error reading back EEPROM " "image\n", dev->name); - spin_unlock(&rrpriv->lock); error = memcmp(image, oldimage, EEPROM_BYTES); if (error){ printk(KERN_ERR "%s: Error verifying EEPROM image\n", dev->name); error = -EFAULT; } - kfree(image); - kfree(oldimage); + wf_out: + if (oldimage) + kfree(oldimage); + if (image) + kfree(image); return error; case SIOCRRID: @@ -1714,13 +1751,34 @@ default: return error; } +} - out_spin: - kfree(image); - spin_unlock(&rrpriv->lock); - return error; +static struct pci_device_id rr_pci_tbl[] __devinitdata = { + { PCI_VENDOR_ID_ESSENTIAL, PCI_DEVICE_ID_ESSENTIAL_ROADRUNNER, + PCI_ANY_ID, PCI_ANY_ID, }, + { 0,} +}; +MODULE_DEVICE_TABLE(pci, rr_pci_tbl); + +static struct pci_driver rr_driver = { + name: "rrunner", + id_table: rr_pci_tbl, + probe: rr_init_one, + remove: rr_remove_one, +}; + +static int __init rr_init_module(void) +{ + return pci_module_init(&rr_driver); +} + +static void __exit rr_cleanup_module(void) +{ + pci_unregister_driver(&rr_driver); } +module_init(rr_init_module); +module_exit(rr_cleanup_module); /* * Local variables: diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/net/rrunner.h linux.2.5.47-ac4/drivers/net/rrunner.h --- linux.2.5.47/drivers/net/rrunner.h 2002-10-31 14:57:04.000000000 +0000 +++ linux.2.5.47-ac4/drivers/net/rrunner.h 2002-11-13 15:13:33.000000000 +0000 @@ -351,7 +351,7 @@ */ #define EVT_RING_ENTRIES 64 -#define EVT_RING_SIZE (EVT_RING_ENTRIES * sizeof(struct event)) +#define EVT_RING_SIZE (EVT_RING_ENTRIES * sizeof(struct event)) struct event { #ifdef __LITTLE_ENDIAN @@ -496,9 +496,9 @@ } rraddr; -static inline void set_rraddr(rraddr *ra, volatile void *addr) +static inline void set_rraddr(rraddr *ra, dma_addr_t addr) { - unsigned long baddr = virt_to_bus((void *)addr); + unsigned long baddr = addr; #if (BITS_PER_LONG == 64) ra->addrlo = baddr; #else @@ -509,9 +509,9 @@ } -static inline void set_rxaddr(struct rr_regs *regs, volatile void *addr) +static inline void set_rxaddr(struct rr_regs *regs, volatile dma_addr_t addr) { - unsigned long baddr = virt_to_bus((void *)addr); + unsigned long baddr = addr; #if (BITS_PER_LONG == 64) && defined(__LITTLE_ENDIAN) writel(baddr & 0xffffffff, ®s->RxRingHi); writel(baddr >> 32, ®s->RxRingLo); @@ -526,9 +526,9 @@ } -static inline void set_infoaddr(struct rr_regs *regs, volatile void *addr) +static inline void set_infoaddr(struct rr_regs *regs, volatile dma_addr_t addr) { - unsigned long baddr = virt_to_bus((void *)addr); + unsigned long baddr = addr; #if (BITS_PER_LONG == 64) && defined(__LITTLE_ENDIAN) writel(baddr & 0xffffffff, ®s->InfoPtrHi); writel(baddr >> 32, ®s->InfoPtrLo); @@ -552,7 +552,7 @@ #else #define TX_RING_ENTRIES 16 #endif -#define TX_RING_SIZE (TX_RING_ENTRIES * sizeof(struct tx_desc)) +#define TX_TOTAL_SIZE (TX_RING_ENTRIES * sizeof(struct tx_desc)) struct tx_desc{ rraddr addr; @@ -574,7 +574,7 @@ #else #define RX_RING_ENTRIES 16 #endif -#define RX_RING_SIZE (RX_RING_ENTRIES * sizeof(struct rx_desc)) +#define RX_TOTAL_SIZE (RX_RING_ENTRIES * sizeof(struct rx_desc)) struct rx_desc{ rraddr addr; @@ -798,24 +798,30 @@ struct rr_private { - struct rx_desc rx_ring[RX_RING_ENTRIES]; - struct tx_desc tx_ring[TX_RING_ENTRIES]; - struct event evt_ring[EVT_RING_ENTRIES]; + struct rx_desc *rx_ring; + struct tx_desc *tx_ring; + struct event *evt_ring; + dma_addr_t tx_ring_dma; + dma_addr_t rx_ring_dma; + dma_addr_t evt_ring_dma; + /* Alignment ok ? */ struct sk_buff *rx_skbuff[RX_RING_ENTRIES]; struct sk_buff *tx_skbuff[TX_RING_ENTRIES]; struct rr_regs *regs; /* Register base */ struct ring_ctrl *rx_ctrl; /* Receive ring control */ struct rr_info *info; /* Shared info page */ - struct net_device *next; + dma_addr_t rx_ctrl_dma; + dma_addr_t info_dma; spinlock_t lock; struct timer_list timer; u32 cur_rx, cur_cmd, cur_evt; u32 dirty_rx, dirty_tx; u32 tx_full; u32 fw_rev; - short fw_running; + volatile short fw_running; char name[24]; /* The assigned name */ struct net_device_stats stats; + struct pci_dev *pci_dev; }; @@ -837,5 +843,6 @@ unsigned long length); static u32 rr_read_eeprom_word(struct rr_private *rrpriv, void * offset); static int rr_load_firmware(struct net_device *dev); - +static inline void rr_raz_tx(struct rr_private *, struct net_device *); +static inline void rr_raz_rx(struct rr_private *, struct net_device *); #endif /* _RRUNNER_H_ */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/net/slip.c linux.2.5.47-ac4/drivers/net/slip.c --- linux.2.5.47/drivers/net/slip.c 2002-10-31 14:57:04.000000000 +0000 +++ linux.2.5.47-ac4/drivers/net/slip.c 2002-11-05 13:52:33.000000000 +0000 @@ -261,7 +261,7 @@ if (xbuff == NULL || rbuff == NULL) { #endif if (mtu >= sl->mtu) { - printk("%s: unable to grow slip buffers, MTU change cancelled.\n", + printk(KERN_WARNING "%s: unable to grow slip buffers, MTU change cancelled.\n", dev->name); err = -ENOBUFS; } @@ -348,7 +348,7 @@ if ((c = sl->rbuff[0]) & SL_TYPE_COMPRESSED_TCP) { /* ignore compressed packets when CSLIP is off */ if (!(sl->mode & SL_MODE_CSLIP)) { - printk("%s: compressed packet ignored\n", sl->dev->name); + printk(KERN_WARNING "%s: compressed packet ignored\n", sl->dev->name); return; } /* make sure we've reserved enough space for uncompress to use */ @@ -365,7 +365,7 @@ /* turn on header compression */ sl->mode |= SL_MODE_CSLIP; sl->mode &= ~SL_MODE_ADAPTIVE; - printk("%s: header compression turned on\n", sl->dev->name); + printk(KERN_INFO "%s: header compression turned on\n", sl->dev->name); } sl->rbuff[0] &= 0x4f; if (slhc_remember(sl->slcomp, sl->rbuff, count) <= 0) { @@ -379,7 +379,7 @@ skb = dev_alloc_skb(count); if (skb == NULL) { - printk("%s: memory squeeze, dropping packet.\n", sl->dev->name); + printk(KERN_WARNING "%s: memory squeeze, dropping packet.\n", sl->dev->name); sl->rx_dropped++; return; } @@ -400,7 +400,7 @@ int actual, count; if (len > sl->mtu) { /* Sigh, shouldn't occur BUT ... */ - printk ("%s: truncating oversized transmit packet!\n", sl->dev->name); + printk(KERN_WARNING "%s: truncating oversized transmit packet!\n", sl->dev->name); sl->tx_dropped++; sl_unlock(sl); return; @@ -487,7 +487,7 @@ /* 20 sec timeout not reached */ goto out; } - printk("%s: transmit timed out, %s?\n", dev->name, + printk(KERN_WARNING "%s: transmit timed out, %s?\n", dev->name, (sl->tty->driver.chars_in_buffer(sl->tty) || sl->xleft) ? "bad line quality" : "driver error"); sl->xleft = 0; @@ -510,7 +510,7 @@ spin_lock(&sl->lock); if (!netif_running(dev)) { spin_unlock(&sl->lock); - printk("%s: xmit call when iface is down\n", dev->name); + printk(KERN_WARNING "%s: xmit call when iface is down\n", dev->name); dev_kfree_skb(skb); return 0; } @@ -1332,7 +1332,7 @@ ".\n", SLIP_VERSION, slip_maxdev ); #if defined(SL_INCLUDE_CSLIP) && !defined(MODULE) - printk("CSLIP: code copyright 1989 Regents of the University of California.\n"); + printk(KERN_INFO "CSLIP: code copyright 1989 Regents of the University of California.\n"); #endif #ifdef CONFIG_SLIP_SMART printk(KERN_INFO "SLIP linefill/keepalive option.\n"); @@ -1341,7 +1341,7 @@ slip_ctrls = (slip_ctrl_t **) kmalloc(sizeof(void*)*slip_maxdev, GFP_KERNEL); if (slip_ctrls == NULL) { - printk("SLIP: Can't allocate slip_ctrls[] array! Uaargh! (-> No SLIP available)\n"); + printk(KERN_ERR "SLIP: Can't allocate slip_ctrls[] array! Uaargh! (-> No SLIP available)\n"); return -ENOMEM; } @@ -1364,7 +1364,7 @@ sl_ldisc.receive_room = slip_receive_room; sl_ldisc.write_wakeup = slip_write_wakeup; if ((status = tty_register_ldisc(N_SLIP, &sl_ldisc)) != 0) { - printk("SLIP: can't register line discipline (err = %d)\n", status); + printk(KERN_ERR "SLIP: can't register line discipline (err = %d)\n", status); } @@ -1418,7 +1418,7 @@ if (slc) { unregister_netdev(&slc->dev); if (slc->ctrl.tty) { - printk("%s: tty discipline is still running\n", slc->dev.name); + printk(KERN_ERR "%s: tty discipline is still running\n", slc->dev.name); /* Pin module forever */ MOD_INC_USE_COUNT; busy++; @@ -1436,7 +1436,7 @@ } if ((i = tty_register_ldisc(N_SLIP, NULL))) { - printk("SLIP: can't unregister line discipline (err = %d)\n", i); + printk(KERN_ERR "SLIP: can't unregister line discipline (err = %d)\n", i); } } #endif /* MODULE */ @@ -1498,7 +1498,7 @@ /* keepalive still high :(, we must hangup */ if( sl->outfill ) /* outfill timer must be deleted too */ (void)del_timer(&sl->outfill_timer); - printk("%s: no packets received during keepalive timeout, hangup.\n", sl->dev->name); + printk(KERN_DEBUG "%s: no packets received during keepalive timeout, hangup.\n", sl->dev->name); tty_hangup(sl->tty); /* this must hangup tty & close slip */ /* I think we need not something else */ goto out; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/net/tokenring/olympic.c linux.2.5.47-ac4/drivers/net/tokenring/olympic.c --- linux.2.5.47/drivers/net/tokenring/olympic.c 2002-10-31 14:57:03.000000000 +0000 +++ linux.2.5.47-ac4/drivers/net/tokenring/olympic.c 2002-10-31 15:05:20.000000000 +0000 @@ -655,8 +655,8 @@ printk(" stat_ring[7]: %p\n", &(olympic_priv->olympic_rx_status_ring[7]) ); printk("RXCDA: %x, rx_ring[0]: %p\n",readl(olympic_mmio+RXCDA),&olympic_priv->olympic_rx_ring[0]); - printk("Rx_ring_dma_addr = %08x, rx_status_dma_addr = -%08x\n",olympic_priv->rx_ring_dma_addr,olympic_priv->rx_status_ring_dma_addr) ; + printk("Rx_ring_dma_addr = %08x, rx_status_dma_addr = %08x\n", + olympic_priv->rx_ring_dma_addr,olympic_priv->rx_status_ring_dma_addr) ; #endif writew((((readw(olympic_mmio+RXENQ)) & 0x8000) ^ 0x8000) | i,olympic_mmio+RXENQ); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/net/wan/pc300_drv.c linux.2.5.47-ac4/drivers/net/wan/pc300_drv.c --- linux.2.5.47/drivers/net/wan/pc300_drv.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/net/wan/pc300_drv.c 2002-11-12 15:36:56.000000000 +0000 @@ -3687,3 +3687,9 @@ module_init(cpc_init); module_exit(cpc_cleanup_module); + +MODULE_DESCRIPTION("Cyclades-PC300 cards driver"); +MODULE_AUTHOR( "Author: Ivan Passos \r\n" + "Maintainer: Henrique Gobbi - */ - -#include -#include -#include -#include - -/* Obsolete functions, these will be going away... */ - -#define PCI_OP(rw,size,type) \ -int pcibios_##rw##_config_##size (unsigned char bus, unsigned char dev_fn, \ - unsigned char where, unsigned type val) \ -{ \ - struct pci_dev *dev = pci_find_slot(bus, dev_fn); \ - if (!dev) return PCIBIOS_DEVICE_NOT_FOUND; \ - return pci_##rw##_config_##size(dev, where, val); \ -} - -PCI_OP(read, byte, char *) -PCI_OP(read, word, short *) -PCI_OP(read, dword, int *) -PCI_OP(write, byte, char) -PCI_OP(write, word, short) -PCI_OP(write, dword, int) - -EXPORT_SYMBOL(pcibios_read_config_byte); -EXPORT_SYMBOL(pcibios_read_config_word); -EXPORT_SYMBOL(pcibios_read_config_dword); -EXPORT_SYMBOL(pcibios_write_config_byte); -EXPORT_SYMBOL(pcibios_write_config_word); -EXPORT_SYMBOL(pcibios_write_config_dword); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/pci/Makefile linux.2.5.47-ac4/drivers/pci/Makefile --- linux.2.5.47/drivers/pci/Makefile 2002-11-11 16:39:10.000000000 +0000 +++ linux.2.5.47-ac4/drivers/pci/Makefile 2002-11-11 16:56:01.000000000 +0000 @@ -6,7 +6,7 @@ probe.o proc.o search.o compat.o setup-bus.o obj-y += access.o probe.o pci.o pool.o quirks.o \ - compat.o names.o pci-driver.o search.o hotplug.o + names.o pci-driver.o search.o hotplug.o obj-$(CONFIG_PM) += power.o obj-$(CONFIG_PROC_FS) += proc.o diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/pci/pci.c linux.2.5.47-ac4/drivers/pci/pci.c --- linux.2.5.47/drivers/pci/pci.c 2002-11-11 16:39:10.000000000 +0000 +++ linux.2.5.47-ac4/drivers/pci/pci.c 2002-11-11 16:55:33.000000000 +0000 @@ -729,6 +729,7 @@ __setup("pci=", pci_setup); #if defined(CONFIG_ISA) || defined(CONFIG_EISA) +/* FIXME: Some boxes have multiple ISA bridges! */ struct pci_dev *isa_bridge; EXPORT_SYMBOL(isa_bridge); #endif diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/pci/pci.ids linux.2.5.47-ac4/drivers/pci/pci.ids --- linux.2.5.47/drivers/pci/pci.ids 2002-11-11 16:39:10.000000000 +0000 +++ linux.2.5.47-ac4/drivers/pci/pci.ids 2002-11-11 16:55:33.000000000 +0000 @@ -497,8 +497,8 @@ 1011 500b DE500B Fast Ethernet 1014 0001 10/100 EtherJet Cardbus 1025 0315 ALN315 Fast Ethernet - 1033 800c PC-9821-CS01 - 1033 800d PC-9821NR-B06 + 1033 800c PC-9821-CS01 100BASE-TX Interface Card + 1033 800d PC-9821NR-B06 100BASE-TX Interface Card 108d 0016 Rapidfire 2327 10/100 Ethernet 108d 0017 GoCard 2250 Ethernet 10/100 Cardbus 10b8 2005 SMC8032DT Extreme Ethernet 10/100 @@ -1049,17 +1049,21 @@ 0003 ATM Controller 0004 R4000 PCI Bridge 0005 PCI to 486-like bus Bridge - 0006 GUI Accelerator + 0006 PC-9800 Graphic Accelerator 0007 PCI to UX-Bus Bridge - 0008 GUI Accelerator - 0009 GUI Accelerator for W98 + 0008 PC-9800 Graphic Accelerator + 0009 PCI to PC9800 Core-Graph Bridge + 0016 PCI to VL Bridge 001a [Nile II] 0021 Vrc4373 [Nile I] 0029 PowerVR PCX1 002a PowerVR 3D + 002c Star Alpha 2 + 002d PCI to C-bus Bridge 0035 USB 1179 0001 USB 12ee 7000 Root Hub + 003b PCI to C-bus Bridge 003e NAPCCARD Cardbus Controller 0046 PowerVR PCX2 [midas] 005a Vrc5074 [Nile 4] @@ -3489,7 +3493,7 @@ 5811 FW323 dead 0800 FireWire Host Bus Adapter 11c2 Sand Microelectronics -11c3 NEC Corp +11c3 NEC Corporation 11c4 Document Technologies, Inc 11c5 Shiva Corporation 11c6 Dainippon Screen Mfg. Co. Ltd diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/pci/probe.c linux.2.5.47-ac4/drivers/pci/probe.c --- linux.2.5.47/drivers/pci/probe.c 2002-11-11 16:39:10.000000000 +0000 +++ linux.2.5.47-ac4/drivers/pci/probe.c 2002-11-11 16:56:21.000000000 +0000 @@ -34,13 +34,20 @@ } /* - * Find the extent of a PCI decode.. + * Find the extent of a PCI decode, do sanity checks. */ -static u32 pci_size(u32 base, unsigned long mask) +static u32 pci_size(u32 base, u32 maxbase, unsigned long mask) { - u32 size = mask & base; /* Find the significant bits */ + u32 size = mask & maxbase; /* Find the significant bits */ + if (!size) + return 0; size = size & ~(size-1); /* Get the lowest of them to find the decode size */ - return size-1; /* extent = size - 1 */ + size -= 1; /* extent = size - 1 */ + if (base == maxbase && ((base | size) & mask) != mask) + return 0; /* base == maxbase can be valid only + if the BAR has been already + programmed with all 1s */ + return size; } static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom) @@ -63,13 +70,17 @@ if (l == 0xffffffff) l = 0; if ((l & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_MEMORY) { + sz = pci_size(l, sz, PCI_BASE_ADDRESS_MEM_MASK); + if (!sz) + continue; res->start = l & PCI_BASE_ADDRESS_MEM_MASK; res->flags |= l & ~PCI_BASE_ADDRESS_MEM_MASK; - sz = pci_size(sz, PCI_BASE_ADDRESS_MEM_MASK); } else { + sz = pci_size(l, sz, PCI_BASE_ADDRESS_IO_MASK & 0xffff); + if (!sz) + continue; res->start = l & PCI_BASE_ADDRESS_IO_MASK; res->flags |= l & ~PCI_BASE_ADDRESS_IO_MASK; - sz = pci_size(sz, PCI_BASE_ADDRESS_IO_MASK & 0xffff); } res->end = res->start + (unsigned long) sz; res->flags |= pci_calc_resource_flags(l); @@ -99,6 +110,7 @@ if (rom) { dev->rom_base_reg = rom; res = &dev->resource[PCI_ROM_RESOURCE]; + res->name = dev->name; pci_read_config_dword(dev, rom, &l); pci_write_config_dword(dev, rom, ~PCI_ROM_ADDRESS_ENABLE); pci_read_config_dword(dev, rom, &sz); @@ -106,13 +118,14 @@ if (l == 0xffffffff) l = 0; if (sz && sz != 0xffffffff) { + sz = pci_size(l, sz, PCI_ROM_ADDRESS_MASK); + if (!sz) + return; res->flags = (l & PCI_ROM_ADDRESS_ENABLE) | IORESOURCE_MEM | IORESOURCE_PREFETCH | IORESOURCE_READONLY | IORESOURCE_CACHEABLE; res->start = l & PCI_ROM_ADDRESS_MASK; - sz = pci_size(sz, PCI_ROM_ADDRESS_MASK); res->end = res->start + (unsigned long) sz; } - res->name = dev->name; } } @@ -384,7 +397,7 @@ /* The PCI-to-PCI bridge spec requires that subtractive decoding (i.e. transparent) bridge must have programming interface code of 0x01. */ - dev->transparent = ((class & 0xff) == 1); + dev->transparent = ((dev->class & 0xff) == 1); pci_read_bases(dev, 2, PCI_ROM_ADDRESS1); break; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/pci/quirks.c linux.2.5.47-ac4/drivers/pci/quirks.c --- linux.2.5.47/drivers/pci/quirks.c 2002-11-11 16:39:10.000000000 +0000 +++ linux.2.5.47-ac4/drivers/pci/quirks.c 2002-11-15 02:13:49.000000000 +0000 @@ -212,6 +212,17 @@ } /* + * ATI Northbridge setups MCE the processor if you even + * read somewhere between 0x3b0->0x3bb + */ + +static void __devinit quirk_ati_exploding_mce(struct pci_dev *dev) +{ + printk(KERN_INFO "ATI Northbridge, reserving I/O ports 0x3b0 to 0x3bb.\n"); + request_region(0x3b0, 0x0C, "RadeonIGP"); +} + +/* * Let's make the southbridge information explicit instead * of having to worry about people probing the ACPI areas, * for example.. (Yes, it happens, and if you read the wrong @@ -477,6 +488,24 @@ } /* + * Common misconfiguration of the MediaGX/Geode PCI master that will + * reduce PCI bandwidth from 70MB/s to 25MB/s. See the GXM/GXLV/GX1 + * datasheets found at http://www.national.com/ds/GX for info on what + * these bits do. + */ + +static void __init quirk_mediagx_master(struct pci_dev *dev) +{ + u8 reg; + pci_read_config_byte(dev, 0x41, ®); + if (reg & 2) { + reg &= ~2; + printk(KERN_INFO "PCI: Fixup for MediaGX/Geode Slave Disconnect Boundary (0x41=0x%02x)\n", reg); + pci_write_config_byte(dev, 0x41, reg); + } +} + +/* * The main table of quirks. */ @@ -530,6 +559,7 @@ { PCI_FIXUP_FINAL, PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7410, quirk_amd_ioapic }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_FE_GATE_700C, quirk_amd_ordering }, + { PCI_FIXUP_FINAL, PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_IGP, quirk_ati_exploding_mce }, /* * i82380FB mobile docking controller: its PCI-to-PCI bridge * is subtractive decoding (transparent), and does indicate this @@ -538,6 +568,8 @@ */ { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82380FB, quirk_transparent_bridge }, + { PCI_FIXUP_FINAL, PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_PCI_MASTER, quirk_mediagx_master }, + { 0 } }; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/pci/setup-res.c linux.2.5.47-ac4/drivers/pci/setup-res.c --- linux.2.5.47/drivers/pci/setup-res.c 2002-10-31 14:57:18.000000000 +0000 +++ linux.2.5.47-ac4/drivers/pci/setup-res.c 2002-10-31 15:05:41.000000000 +0000 @@ -137,7 +137,7 @@ } /* Sort resources by alignment */ -void __init +void __devinit pdev_sort_resources(struct pci_dev *dev, struct resource_list *head) { int i; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/pnp/pnpbios/core.c linux.2.5.47-ac4/drivers/pnp/pnpbios/core.c --- linux.2.5.47/drivers/pnp/pnpbios/core.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/pnp/pnpbios/core.c 2002-11-04 14:16:46.000000000 +0000 @@ -1494,7 +1494,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 -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/s390/block/dasd_3990_erp.c linux.2.5.47-ac4/drivers/s390/block/dasd_3990_erp.c --- linux.2.5.47/drivers/s390/block/dasd_3990_erp.c 2002-10-31 14:57:13.000000000 +0000 +++ linux.2.5.47-ac4/drivers/s390/block/dasd_3990_erp.c 2002-10-31 15:05:34.000000000 +0000 @@ -1122,6 +1122,9 @@ break; default: /* unknown message format - should not happen */ + DEV_MESSAGE (KERN_WARNING, device, + "unknown message format %02x", + msg_format); break; } /* end switch message format */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/s390/block/dasd.c linux.2.5.47-ac4/drivers/s390/block/dasd.c --- linux.2.5.47/drivers/s390/block/dasd.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/s390/block/dasd.c 2002-10-31 17:37:12.000000000 +0000 @@ -80,6 +80,7 @@ MODULE_SUPPORTED_DEVICE("dasd"); MODULE_PARM(dasd, "1-" __MODULE_STRING(256) "s"); MODULE_PARM(dasd_disciplines, "1-" __MODULE_STRING(8) "s"); +MODULE_LICENSE("GPL"); /* * SECTION: prototypes for static functions of dasd.c @@ -1172,6 +1173,7 @@ BUG(); break; } + retries++; } dasd_schedule_bh(device); return rc; @@ -1536,7 +1538,7 @@ goto restart; } - /* Rechain request on device device request queue */ + /* Rechain finished requests to final queue */ cqr->endclk = get_clock(); list_move_tail(&cqr->list, final_queue); } @@ -1623,7 +1625,7 @@ /* * Take a look at the first request on the ccw queue and check - * if it reached its expire time. + * if it reached its expire time. If so, terminate the IO. */ static inline void __dasd_check_expire(dasd_device_t * device) @@ -1748,7 +1750,7 @@ } /* - * Schedules a call to dasd_process_queues over the device tasklet. + * Schedules a call to dasd_tasklet over the device tasklet. */ void dasd_schedule_bh(dasd_device_t * device) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/s390/block/dasd_devmap.c linux.2.5.47-ac4/drivers/s390/block/dasd_devmap.c --- linux.2.5.47/drivers/s390/block/dasd_devmap.c 2002-10-31 14:57:13.000000000 +0000 +++ linux.2.5.47-ac4/drivers/s390/block/dasd_devmap.c 2002-10-31 15:05:34.000000000 +0000 @@ -87,6 +87,8 @@ int dasd_devno(char *str, char **endp) { + int val; + /* remove leading '0x' */ if (*str == '0') { str++; @@ -96,7 +98,10 @@ /* We require at least one hex digit */ if (!isxdigit(*str)) return -EINVAL; - return simple_strtoul(str, endp, 16); + val = simple_strtoul(str, endp, 16); + if ((val > 0xFFFF) || (val < 0)) + return -EINVAL; + return val; } /* diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/s390/block/dasd_diag.c linux.2.5.47-ac4/drivers/s390/block/dasd_diag.c --- linux.2.5.47/drivers/s390/block/dasd_diag.c 2002-10-31 14:57:13.000000000 +0000 +++ linux.2.5.47-ac4/drivers/s390/block/dasd_diag.c 2002-10-31 15:05:34.000000000 +0000 @@ -40,6 +40,8 @@ #endif /* PRINTK_HEADER */ #define PRINTK_HEADER "dasd(diag):" +MODULE_LICENSE("GPL"); + static dasd_discipline_t dasd_diag_discipline; typedef struct dasd_diag_private_t { diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/s390/block/dasd_eckd.c linux.2.5.47-ac4/drivers/s390/block/dasd_eckd.c --- linux.2.5.47/drivers/s390/block/dasd_eckd.c 2002-10-31 14:57:13.000000000 +0000 +++ linux.2.5.47-ac4/drivers/s390/block/dasd_eckd.c 2002-10-31 15:05:34.000000000 +0000 @@ -59,6 +59,8 @@ #define ECKD_F7(i) (i->factor7) #define ECKD_F8(i) (i->factor8) +MODULE_LICENSE("GPL"); + static dasd_discipline_t dasd_eckd_discipline; typedef struct dasd_eckd_private_t { @@ -183,6 +185,31 @@ } static inline void +check_XRC (ccw1_t *de_ccw, + DE_eckd_data_t *data, + dasd_device_t *device) +{ + dasd_eckd_private_t *private; + + private = (dasd_eckd_private_t *) device->private; + + /* switch on System Time Stamp - needed for XRC Support */ + if (private->rdc_data.facilities.XRC_supported) { + + data->ga_extended |= 0x08; /* switch on 'Time Stamp Valid' */ + data->ga_extended |= 0x02; /* switch on 'Extended Parameter' */ + + data->ep_sys_time = get_clock (); + + de_ccw->count = sizeof (DE_eckd_data_t); + de_ccw->flags = CCW_FLAG_SLI; + } + + return; + +} /* end check_XRC */ + +static inline void define_extent(ccw1_t * ccw, DE_eckd_data_t * data, int trk, int totrk, int cmd, dasd_device_t * device) { @@ -216,10 +243,12 @@ case DASD_ECKD_CCW_WRITE_KD_MT: data->mask.perm = 0x02; data->attributes.operation = private->attrib.operation; + check_XRC (ccw, data, device); break; case DASD_ECKD_CCW_WRITE_CKD: case DASD_ECKD_CCW_WRITE_CKD_MT: data->attributes.operation = DASD_BYPASS_CACHE; + check_XRC (ccw, data, device); break; case DASD_ECKD_CCW_ERASE: case DASD_ECKD_CCW_WRITE_HOME_ADDRESS: @@ -227,6 +256,7 @@ data->mask.perm = 0x3; data->mask.auth = 0x1; data->attributes.operation = DASD_BYPASS_CACHE; + check_XRC (ccw, data, device); break; default: MESSAGE(KERN_ERR, "unknown opcode 0x%x", cmd); @@ -497,6 +527,11 @@ private->rdc_data.cu_type, private->rdc_data.cu_model.model); return 0; + + /* get characteristis via diag to determine the kind of minidisk under VM */ + /* needed beacause XRC is not support by VM (jet) */ + /* Can be removed as soon as VM supports XRC */ + // TBD ??? HUM } static int @@ -563,6 +598,7 @@ cqr->device = device; cqr->retries = 0; + cqr->buildclk = get_clock(); cqr->status = DASD_CQR_FILLED; return cqr; } @@ -881,6 +917,7 @@ } fcp->device = device; fcp->retries = 2; /* set retry counter to enable ERP */ + fcp->buildclk = get_clock(); fcp->status = DASD_CQR_FILLED; return fcp; } @@ -1119,6 +1156,7 @@ cqr->device = device; cqr->retries = 0; cqr->expires = 10 * HZ; + cqr->buildclk = get_clock(); cqr->status = DASD_CQR_FILLED; rc = dasd_sleep_on_immediatly(cqr); @@ -1163,6 +1201,7 @@ cqr->device = device; cqr->retries = 0; cqr->expires = 10 * HZ; + cqr->buildclk = get_clock(); cqr->status = DASD_CQR_FILLED; rc = dasd_sleep_on_immediatly(cqr); @@ -1209,6 +1248,7 @@ cqr->device = device; cqr->retries = 0; cqr->expires = 10 * HZ; + cqr->buildclk = get_clock(); cqr->status = DASD_CQR_FILLED; rc = dasd_sleep_on_immediatly(cqr); @@ -1277,6 +1317,7 @@ ccw->count = sizeof (dasd_rssd_perf_stats_t); ccw->cda = (__u32)(addr_t) stats; + cqr->buildclk = get_clock(); cqr->status = DASD_CQR_FILLED; rc = dasd_sleep_on(cqr); if (rc == 0) { diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/s390/block/dasd_eckd.h linux.2.5.47-ac4/drivers/s390/block/dasd_eckd.h --- linux.2.5.47/drivers/s390/block/dasd_eckd.h 2002-10-31 14:57:13.000000000 +0000 +++ linux.2.5.47-ac4/drivers/s390/block/dasd_eckd.h 2002-10-31 15:05:34.000000000 +0000 @@ -1,3 +1,16 @@ +/* + * File...........: linux/drivers/s390/block/dasd_eckd.h + * Author(s)......: Holger Smolinski + * Horst Hummel + * Bugreports.to..: + * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 + * + * $Revision: 1.4 $ + * + * History of changes + * + */ + #ifndef DASD_ECKD_H #define DASD_ECKD_H @@ -102,6 +115,10 @@ __u8 ga_extended; /* Global Attributes Extended */ ch_t beg_ext; ch_t end_ext; + unsigned long long ep_sys_time; /* Extended Parameter - System Time Stamp */ + __u8 ep_format; /* Extended Parameter format byte */ + __u8 ep_prio; /* Extended Parameter priority I/O byte */ + __u8 ep_reserved[6]; /* Extended Parameter Reserved */ } __attribute__ ((packed)) DE_eckd_data_t; typedef struct LO_eckd_data_t { @@ -141,7 +158,8 @@ unsigned char reserved2:4; unsigned char reserved3:8; unsigned char defect_wr:1; - unsigned char reserved4:2; + unsigned char XRC_supported:1; + unsigned char reserved4:1; unsigned char striping:1; unsigned char reserved5:4; unsigned char cfw:1; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/s390/block/dasd_fba.c linux.2.5.47-ac4/drivers/s390/block/dasd_fba.c --- linux.2.5.47/drivers/s390/block/dasd_fba.c 2002-10-31 14:57:13.000000000 +0000 +++ linux.2.5.47-ac4/drivers/s390/block/dasd_fba.c 2002-10-31 15:05:34.000000000 +0000 @@ -38,6 +38,8 @@ #define DASD_FBA_CCW_LOCATE 0x43 #define DASD_FBA_CCW_DEFINE_EXTENT 0x63 +MODULE_LICENSE("GPL"); + static dasd_discipline_t dasd_fba_discipline; typedef struct dasd_fba_private_t { diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/s390/block/dasd_proc.c linux.2.5.47-ac4/drivers/s390/block/dasd_proc.c --- linux.2.5.47/drivers/s390/block/dasd_proc.c 2002-10-31 14:57:13.000000000 +0000 +++ linux.2.5.47-ac4/drivers/s390/block/dasd_proc.c 2002-10-31 15:05:34.000000000 +0000 @@ -195,10 +195,7 @@ break; case DASD_STATE_READY: case DASD_STATE_ONLINE: - if (device->state < DASD_STATE_ONLINE) - len += sprintf(str + len, "fenced "); - else - len += sprintf(str + len, "active "); + len += sprintf(str + len, "active "); if (dasd_check_blocksize(device->bp_block)) len += sprintf(str + len, "n/f "); else diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/scsi/aacraid/aachba.c linux.2.5.47-ac4/drivers/scsi/aacraid/aachba.c --- linux.2.5.47/drivers/scsi/aacraid/aachba.c 2002-11-05 13:54:44.000000000 +0000 +++ linux.2.5.47-ac4/drivers/scsi/aacraid/aachba.c 2002-11-11 20:32:15.000000000 +0000 @@ -1113,12 +1113,12 @@ qd.locked = fsa_dev_ptr->locked[qd.cnum]; qd.deleted = fsa_dev_ptr->deleted[qd.cnum]; - if (fsa_dev_ptr->devno[qd.cnum][0] == '\0') + if (fsa_dev_ptr->devname[qd.cnum][0] == '\0') qd.unmapped = 1; else qd.unmapped = 0; - strncpy(dq.name, fsa_dev_ptr->devname[qd.cnum], 8); + strncpy(qd.name, fsa_dev_ptr->devname[qd.cnum], 8); if (copy_to_user(arg, &qd, sizeof (struct aac_query_disk))) return -EFAULT; @@ -1170,7 +1170,7 @@ * Mark the container as no longer being valid. */ fsa_dev_ptr->valid[dd.cnum] = 0; - fsa_dev_ptr->devno[dd.cnum][0] = '\0'; + fsa_dev_ptr->devname[dd.cnum][0] = '\0'; return 0; } } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/scsi/aacraid/commctrl.c linux.2.5.47-ac4/drivers/scsi/aacraid/commctrl.c --- linux.2.5.47/drivers/scsi/aacraid/commctrl.c 2002-10-31 14:57:13.000000000 +0000 +++ linux.2.5.47-ac4/drivers/scsi/aacraid/commctrl.c 2002-10-31 15:05:34.000000000 +0000 @@ -424,7 +424,12 @@ status = aac_get_pci_info(dev,arg); break; default: - status = -ENOTTY; + /* + * Return EINVAL instead of ENOTTY because blkdev_ioctl + * understands the EINVAL return code to mean that the + * ioctl wasn't handled and blk_ioctl should be called. + */ + status = -EINVAL; break; } return status; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/scsi/aic7xxx/aic7xxx_reg.h linux.2.5.47-ac4/drivers/scsi/aic7xxx/aic7xxx_reg.h --- linux.2.5.47/drivers/scsi/aic7xxx/aic7xxx_reg.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.47-ac4/drivers/scsi/aic7xxx/aic7xxx_reg.h 2002-11-12 17:24:34.000000000 +0000 @@ -0,0 +1,716 @@ +/* + * DO NOT EDIT - This file is automatically generated + * from the following source files: + * + * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#37 $ + * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#24 $ + */ + +#define SCSISEQ 0x00 +#define TEMODE 0x80 +#define SCSIRSTO 0x01 + +#define SXFRCTL0 0x01 +#define DFON 0x80 +#define DFPEXP 0x40 +#define FAST20 0x20 +#define CLRSTCNT 0x10 +#define SPIOEN 0x08 +#define SCAMEN 0x04 +#define CLRCHN 0x02 + +#define SXFRCTL1 0x02 +#define BITBUCKET 0x80 +#define SWRAPEN 0x40 +#define STIMESEL 0x18 +#define ENSTIMER 0x04 +#define ACTNEGEN 0x02 +#define STPWEN 0x01 + +#define SCSISIGO 0x03 +#define CDO 0x80 +#define IOO 0x40 +#define MSGO 0x20 +#define ATNO 0x10 +#define SELO 0x08 +#define BSYO 0x04 +#define REQO 0x02 +#define ACKO 0x01 + +#define SCSISIGI 0x03 +#define P_DATAIN_DT 0x60 +#define P_DATAOUT_DT 0x20 +#define ATNI 0x10 +#define SELI 0x08 +#define BSYI 0x04 +#define REQI 0x02 +#define ACKI 0x01 + +#define SCSIRATE 0x04 +#define WIDEXFER 0x80 +#define SXFR 0x70 +#define ENABLE_CRC 0x40 +#define SINGLE_EDGE 0x10 +#define SOFS 0x0f +#define SXFR_ULTRA2 0x0f + +#define SCSIID 0x05 +#define SCSIOFFSET 0x05 +#define SOFS_ULTRA2 0x7f + +#define SCSIDATL 0x06 + +#define SCSIDATH 0x07 + +#define STCNT 0x08 + +#define OPTIONMODE 0x08 +#define AUTORATEEN 0x80 +#define AUTOACKEN 0x40 +#define ATNMGMNTEN 0x20 +#define BUSFREEREV 0x10 +#define EXPPHASEDIS 0x08 +#define SCSIDATL_IMGEN 0x04 +#define OPTIONMODE_DEFAULTS 0x03 +#define AUTO_MSGOUT_DE 0x02 +#define DIS_MSGIN_DUALEDGE 0x01 + +#define TARGCRCCNT 0x0a + +#define CLRSINT0 0x0b +#define CLRSELDO 0x40 +#define CLRSELDI 0x20 +#define CLRSELINGO 0x10 +#define CLRIOERR 0x08 +#define CLRSWRAP 0x08 +#define CLRSPIORDY 0x02 + +#define SSTAT0 0x0b +#define TARGET 0x80 +#define SELDO 0x40 +#define SELDI 0x20 +#define SELINGO 0x10 +#define SWRAP 0x08 +#define IOERR 0x08 +#define SDONE 0x04 +#define SPIORDY 0x02 +#define DMADONE 0x01 + +#define CLRSINT1 0x0c +#define CLRSELTIMEO 0x80 +#define CLRATNO 0x40 +#define CLRSCSIRSTI 0x20 +#define CLRBUSFREE 0x08 +#define CLRSCSIPERR 0x04 +#define CLRPHASECHG 0x02 +#define CLRREQINIT 0x01 + +#define SSTAT1 0x0c +#define SELTO 0x80 +#define ATNTARG 0x40 +#define SCSIRSTI 0x20 +#define PHASEMIS 0x10 +#define BUSFREE 0x08 +#define SCSIPERR 0x04 +#define PHASECHG 0x02 +#define REQINIT 0x01 + +#define SSTAT2 0x0d +#define OVERRUN 0x80 +#define SHVALID 0x40 +#define SFCNT 0x1f +#define EXP_ACTIVE 0x10 +#define CRCVALERR 0x08 +#define CRCENDERR 0x04 +#define CRCREQERR 0x02 +#define DUAL_EDGE_ERR 0x01 + +#define SSTAT3 0x0e +#define SCSICNT 0xf0 +#define U2OFFCNT 0x7f +#define OFFCNT 0x0f + +#define SCSIID_ULTRA2 0x0f + +#define SIMODE0 0x10 +#define ENSELDO 0x40 +#define ENSELDI 0x20 +#define ENSELINGO 0x10 +#define ENIOERR 0x08 +#define ENSWRAP 0x08 +#define ENSDONE 0x04 +#define ENSPIORDY 0x02 +#define ENDMADONE 0x01 + +#define SIMODE1 0x11 +#define ENSELTIMO 0x80 +#define ENATNTARG 0x40 +#define ENSCSIRST 0x20 +#define ENPHASEMIS 0x10 +#define ENBUSFREE 0x08 +#define ENSCSIPERR 0x04 +#define ENPHASECHG 0x02 +#define ENREQINIT 0x01 + +#define SCSIBUSL 0x12 + +#define SCSIBUSH 0x13 + +#define SHADDR 0x14 + +#define SELTIMER 0x18 +#define TARGIDIN 0x18 +#define STAGE6 0x20 +#define STAGE5 0x10 +#define STAGE4 0x08 +#define STAGE3 0x04 +#define STAGE2 0x02 +#define STAGE1 0x01 + +#define SELID 0x19 +#define SELID_MASK 0xf0 +#define ONEBIT 0x08 + +#define SCAMCTL 0x1a +#define ENSCAMSELO 0x80 +#define CLRSCAMSELID 0x40 +#define ALTSTIM 0x20 +#define DFLTTID 0x10 +#define SCAMLVL 0x03 + +#define TARGID 0x1b + +#define SPIOCAP 0x1b +#define SOFT1 0x80 +#define SOFT0 0x40 +#define SOFTCMDEN 0x20 +#define HAS_BRDCTL 0x10 +#define SEEPROM 0x08 +#define EEPROM 0x04 +#define ROM 0x02 +#define SSPIOCPS 0x01 + +#define BRDCTL 0x1d +#define BRDDAT7 0x80 +#define BRDDAT6 0x40 +#define BRDDAT5 0x20 +#define BRDDAT4 0x10 +#define BRDSTB 0x10 +#define BRDDAT3 0x08 +#define BRDCS 0x08 +#define BRDDAT2 0x04 +#define BRDRW 0x04 +#define BRDRW_ULTRA2 0x02 +#define BRDCTL1 0x02 +#define BRDCTL0 0x01 +#define BRDSTB_ULTRA2 0x01 + +#define SEECTL 0x1e +#define EXTARBACK 0x80 +#define EXTARBREQ 0x40 +#define SEEMS 0x20 +#define SEERDY 0x10 +#define SEECS 0x08 +#define SEECK 0x04 +#define SEEDO 0x02 +#define SEEDI 0x01 + +#define SBLKCTL 0x1f +#define DIAGLEDEN 0x80 +#define DIAGLEDON 0x40 +#define AUTOFLUSHDIS 0x20 +#define ENAB40 0x08 +#define SELBUSB 0x08 +#define ENAB20 0x04 +#define SELWIDE 0x02 +#define XCVR 0x01 + +#define BUSY_TARGETS 0x20 +#define TARG_SCSIRATE 0x20 + +#define SRAM_BASE 0x20 + +#define ULTRA_ENB 0x30 +#define CMDSIZE_TABLE 0x30 + +#define DISC_DSB 0x32 + +#define CMDSIZE_TABLE_TAIL 0x34 + +#define MWI_RESIDUAL 0x38 + +#define NEXT_QUEUED_SCB 0x39 + +#define MSG_OUT 0x3a + +#define DMAPARAMS 0x3b +#define PRELOADEN 0x80 +#define WIDEODD 0x40 +#define SCSIEN 0x20 +#define SDMAEN 0x10 +#define SDMAENACK 0x10 +#define HDMAEN 0x08 +#define HDMAENACK 0x08 +#define DIRECTION 0x04 +#define FIFOFLUSH 0x02 +#define FIFORESET 0x01 + +#define SEQ_FLAGS 0x3c +#define IDENTIFY_SEEN 0x80 +#define TARGET_CMD_IS_TAGGED 0x40 +#define DPHASE 0x20 +#define TARG_CMD_PENDING 0x10 +#define CMDPHASE_PENDING 0x08 +#define DPHASE_PENDING 0x04 +#define SPHASE_PENDING 0x02 +#define NO_DISCONNECT 0x01 + +#define SAVED_SCSIID 0x3d + +#define SAVED_LUN 0x3e + +#define LASTPHASE 0x3f +#define P_MESGIN 0xe0 +#define PHASE_MASK 0xe0 +#define P_STATUS 0xc0 +#define P_MESGOUT 0xa0 +#define P_COMMAND 0x80 +#define CDI 0x80 +#define P_DATAIN 0x40 +#define IOI 0x40 +#define MSGI 0x20 +#define P_BUSFREE 0x01 +#define P_DATAOUT 0x00 + +#define WAITING_SCBH 0x40 + +#define DISCONNECTED_SCBH 0x41 + +#define FREE_SCBH 0x42 + +#define COMPLETE_SCBH 0x43 + +#define HSCB_ADDR 0x44 + +#define SHARED_DATA_ADDR 0x48 + +#define KERNEL_QINPOS 0x4c + +#define QINPOS 0x4d + +#define QOUTPOS 0x4e + +#define KERNEL_TQINPOS 0x4f + +#define TQINPOS 0x50 + +#define ARG_1 0x51 +#define RETURN_1 0x51 +#define SEND_MSG 0x80 +#define SEND_SENSE 0x40 +#define SEND_REJ 0x20 +#define MSGOUT_PHASEMIS 0x10 +#define EXIT_MSG_LOOP 0x08 +#define CONT_MSG_LOOP 0x04 +#define CONT_TARG_SESSION 0x02 + +#define ARG_2 0x52 +#define RETURN_2 0x52 + +#define LAST_MSG 0x53 + +#define SCSISEQ_TEMPLATE 0x54 +#define ENSELO 0x40 +#define ENSELI 0x20 +#define ENRSELI 0x10 +#define ENAUTOATNO 0x08 +#define ENAUTOATNI 0x04 +#define ENAUTOATNP 0x02 + +#define DATA_COUNT_ODD 0x55 + +#define INITIATOR_TAG 0x56 + +#define SEQ_FLAGS2 0x57 +#define TARGET_MSG_PENDING 0x02 +#define SCB_DMA 0x01 + +#define SCSICONF 0x5a +#define TERM_ENB 0x80 +#define RESET_SCSI 0x40 +#define ENSPCHK 0x20 +#define HWSCSIID 0x0f +#define HSCSIID 0x07 + +#define INTDEF 0x5c +#define EDGE_TRIG 0x80 +#define VECTOR 0x0f + +#define HOSTCONF 0x5d + +#define HA_274_BIOSCTRL 0x5f +#define BIOSDISABLED 0x30 +#define BIOSMODE 0x30 +#define CHANNEL_B_PRIMARY 0x08 + +#define SEQCTL 0x60 +#define PERRORDIS 0x80 +#define PAUSEDIS 0x40 +#define FAILDIS 0x20 +#define FASTMODE 0x10 +#define BRKADRINTEN 0x08 +#define STEP 0x04 +#define SEQRESET 0x02 +#define LOADRAM 0x01 + +#define SEQRAM 0x61 + +#define SEQADDR0 0x62 + +#define SEQADDR1 0x63 +#define SEQADDR1_MASK 0x01 + +#define ACCUM 0x64 + +#define SINDEX 0x65 + +#define DINDEX 0x66 + +#define ALLONES 0x69 + +#define ALLZEROS 0x6a + +#define NONE 0x6a + +#define FLAGS 0x6b +#define ZERO 0x02 +#define CARRY 0x01 + +#define SINDIR 0x6c + +#define DINDIR 0x6d + +#define FUNCTION1 0x6e + +#define STACK 0x6f + +#define TARG_OFFSET 0x70 + +#define BCTL 0x84 +#define ACE 0x08 +#define ENABLE 0x01 + +#define DSCOMMAND0 0x84 +#define CACHETHEN 0x80 +#define DPARCKEN 0x40 +#define MPARCKEN 0x20 +#define EXTREQLCK 0x10 +#define INTSCBRAMSEL 0x08 +#define RAMPS 0x04 +#define USCBSIZE32 0x02 +#define CIOPARCKEN 0x01 + +#define BUSTIME 0x85 +#define BOFF 0xf0 +#define BON 0x0f + +#define DSCOMMAND1 0x85 +#define DSLATT 0xfc +#define HADDLDSEL1 0x02 +#define HADDLDSEL0 0x01 + +#define BUSSPD 0x86 +#define DFTHRSH 0xc0 +#define DFTHRSH_75 0x80 +#define STBOFF 0x38 +#define STBON 0x07 + +#define HS_MAILBOX 0x86 +#define HOST_MAILBOX 0xf0 +#define HOST_TQINPOS 0x80 +#define SEQ_MAILBOX 0x0f + +#define DSPCISTATUS 0x86 +#define DFTHRSH_100 0xc0 + +#define HCNTRL 0x87 +#define POWRDN 0x40 +#define SWINT 0x10 +#define IRQMS 0x08 +#define PAUSE 0x04 +#define INTEN 0x02 +#define CHIPRST 0x01 +#define CHIPRSTACK 0x01 + +#define HADDR 0x88 + +#define HCNT 0x8c + +#define SCBPTR 0x90 + +#define INTSTAT 0x91 +#define SEQINT_MASK 0xf1 +#define OUT_OF_RANGE 0xe1 +#define NO_FREE_SCB 0xd1 +#define SCB_MISMATCH 0xc1 +#define MISSED_BUSFREE 0xb1 +#define MKMSG_FAILED 0xa1 +#define DATA_OVERRUN 0x91 +#define PERR_DETECTED 0x81 +#define BAD_STATUS 0x71 +#define HOST_MSG_LOOP 0x61 +#define PDATA_REINIT 0x51 +#define IGN_WIDE_RES 0x41 +#define NO_MATCH 0x31 +#define NO_IDENT 0x21 +#define SEND_REJECT 0x11 +#define INT_PEND 0x0f +#define BRKADRINT 0x08 +#define SCSIINT 0x04 +#define CMDCMPLT 0x02 +#define BAD_PHASE 0x01 +#define SEQINT 0x01 + +#define CLRINT 0x92 +#define CLRPARERR 0x10 +#define CLRBRKADRINT 0x08 +#define CLRSCSIINT 0x04 +#define CLRCMDINT 0x02 +#define CLRSEQINT 0x01 + +#define ERROR 0x92 +#define CIOPARERR 0x80 +#define PCIERRSTAT 0x40 +#define MPARERR 0x20 +#define DPARERR 0x10 +#define SQPARERR 0x08 +#define ILLOPCODE 0x04 +#define ILLSADDR 0x02 +#define ILLHADDR 0x01 + +#define DFCNTRL 0x93 + +#define DFSTATUS 0x94 +#define PRELOAD_AVAIL 0x80 +#define DFCACHETH 0x40 +#define FIFOQWDEMP 0x20 +#define MREQPEND 0x10 +#define HDONE 0x08 +#define DFTHRESH 0x04 +#define FIFOFULL 0x02 +#define FIFOEMP 0x01 + +#define DFWADDR 0x95 + +#define DFRADDR 0x97 + +#define DFDAT 0x99 + +#define SCBCNT 0x9a +#define SCBAUTO 0x80 +#define SCBCNT_MASK 0x1f + +#define QINFIFO 0x9b + +#define QINCNT 0x9c + +#define QOUTFIFO 0x9d + +#define CRCCONTROL1 0x9d +#define CRCONSEEN 0x80 +#define CRCVALCHKEN 0x40 +#define CRCENDCHKEN 0x20 +#define CRCREQCHKEN 0x10 +#define TARGCRCENDEN 0x08 +#define TARGCRCCNTEN 0x04 + +#define QOUTCNT 0x9e + +#define SCSIPHASE 0x9e +#define STATUS_PHASE 0x20 +#define COMMAND_PHASE 0x10 +#define MSG_IN_PHASE 0x08 +#define MSG_OUT_PHASE 0x04 +#define DATA_PHASE_MASK 0x03 +#define DATA_IN_PHASE 0x02 +#define DATA_OUT_PHASE 0x01 + +#define SFUNCT 0x9f +#define ALT_MODE 0x80 + +#define SCB_BASE 0xa0 + +#define SCB_CDB_PTR 0xa0 +#define SCB_RESIDUAL_DATACNT 0xa0 +#define SCB_CDB_STORE 0xa0 + +#define SCB_RESIDUAL_SGPTR 0xa4 + +#define SCB_SCSI_STATUS 0xa8 + +#define SCB_TARGET_PHASES 0xa9 + +#define SCB_TARGET_DATA_DIR 0xaa + +#define SCB_TARGET_ITAG 0xab + +#define SCB_DATAPTR 0xac + +#define SCB_DATACNT 0xb0 +#define SG_LAST_SEG 0x80 +#define SG_HIGH_ADDR_BITS 0x7f + +#define SCB_SGPTR 0xb4 +#define SG_RESID_VALID 0x04 +#define SG_FULL_RESID 0x02 +#define SG_LIST_NULL 0x01 + +#define SCB_CONTROL 0xb8 +#define TARGET_SCB 0x80 +#define DISCENB 0x40 +#define TAG_ENB 0x20 +#define MK_MESSAGE 0x10 +#define ULTRAENB 0x08 +#define DISCONNECTED 0x04 +#define SCB_TAG_TYPE 0x03 + +#define SCB_SCSIID 0xb9 +#define TID 0xf0 +#define TWIN_CHNLB 0x80 +#define TWIN_TID 0x70 +#define OID 0x0f + +#define SCB_LUN 0xba +#define LID 0xff + +#define SCB_TAG 0xbb + +#define SCB_CDB_LEN 0xbc + +#define SCB_SCSIRATE 0xbd + +#define SCB_SCSIOFFSET 0xbe + +#define SCB_NEXT 0xbf + +#define SCB_64_SPARE 0xc0 + +#define SEECTL_2840 0xc0 +#define CS_2840 0x04 +#define CK_2840 0x02 +#define DO_2840 0x01 + +#define STATUS_2840 0xc1 +#define EEPROM_TF 0x80 +#define BIOS_SEL 0x60 +#define ADSEL 0x1e +#define DI_2840 0x01 + +#define SCB_64_BTT 0xd0 + +#define CCHADDR 0xe0 + +#define CCHCNT 0xe8 + +#define CCSGRAM 0xe9 + +#define CCSGADDR 0xea + +#define CCSGCTL 0xeb +#define CCSGDONE 0x80 +#define CCSGEN 0x08 +#define SG_FETCH_NEEDED 0x02 +#define CCSGRESET 0x01 + +#define CCSCBRAM 0xec + +#define CCSCBADDR 0xed + +#define CCSCBCTL 0xee +#define CCSCBDONE 0x80 +#define ARRDONE 0x40 +#define CCARREN 0x10 +#define CCSCBEN 0x08 +#define CCSCBDIR 0x04 +#define CCSCBRESET 0x01 + +#define CCSCBCNT 0xef + +#define SCBBADDR 0xf0 + +#define CCSCBPTR 0xf1 + +#define HNSCB_QOFF 0xf4 + +#define SNSCB_QOFF 0xf6 + +#define SDSCB_QOFF 0xf8 + +#define QOFF_CTLSTA 0xfa +#define SCB_AVAIL 0x40 +#define SNSCB_ROLLOVER 0x20 +#define SDSCB_ROLLOVER 0x10 +#define SCB_QSIZE 0x07 +#define SCB_QSIZE_256 0x06 + +#define DFF_THRSH 0xfb +#define WR_DFTHRSH 0x70 +#define WR_DFTHRSH_MAX 0x70 +#define WR_DFTHRSH_90 0x60 +#define WR_DFTHRSH_85 0x50 +#define WR_DFTHRSH_75 0x40 +#define WR_DFTHRSH_63 0x30 +#define WR_DFTHRSH_50 0x20 +#define WR_DFTHRSH_25 0x10 +#define RD_DFTHRSH 0x07 +#define RD_DFTHRSH_MAX 0x07 +#define RD_DFTHRSH_90 0x06 +#define RD_DFTHRSH_85 0x05 +#define RD_DFTHRSH_75 0x04 +#define RD_DFTHRSH_63 0x03 +#define RD_DFTHRSH_50 0x02 +#define RD_DFTHRSH_25 0x01 +#define RD_DFTHRSH_MIN 0x00 +#define WR_DFTHRSH_MIN 0x00 + +#define SG_CACHE_SHADOW 0xfc +#define SG_ADDR_MASK 0xf8 +#define ODD_SEG 0x04 +#define LAST_SEG 0x02 +#define LAST_SEG_DONE 0x01 + +#define SG_CACHE_PRE 0xfc + + +#define MAX_OFFSET_ULTRA2 0x7f +#define MAX_OFFSET_16BIT 0x08 +#define BUS_8_BIT 0x00 +#define TARGET_CMD_CMPLT 0xfe +#define STATUS_QUEUE_FULL 0x28 +#define STATUS_BUSY 0x08 +#define MAX_OFFSET_8BIT 0x0f +#define BUS_32_BIT 0x02 +#define CCSGADDR_MAX 0x80 +#define TID_SHIFT 0x04 +#define SCB_DOWNLOAD_SIZE_64 0x30 +#define HOST_MAILBOX_SHIFT 0x04 +#define CMD_GROUP_CODE_SHIFT 0x05 +#define CCSGRAM_MAXSEGS 0x10 +#define SCB_LIST_NULL 0xff +#define SG_SIZEOF 0x08 +#define SCB_DOWNLOAD_SIZE 0x20 +#define SEQ_MAILBOX_SHIFT 0x00 +#define TARGET_DATA_IN 0x01 +#define HOST_MSG 0xff +#define BUS_16_BIT 0x01 +#define SCB_UPLOAD_SIZE 0x20 + + +/* Downloaded Constant Definitions */ +#define INVERTED_CACHESIZE_MASK 0x03 +#define SG_PREFETCH_ADDR_MASK 0x06 +#define SG_PREFETCH_ALIGN_MASK 0x05 +#define QOUTFIFO_OFFSET 0x00 +#define SG_PREFETCH_CNT 0x04 +#define CACHESIZE_MASK 0x02 +#define QINFIFO_OFFSET 0x01 diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/scsi/aic7xxx/aic7xxx_seq.h linux.2.5.47-ac4/drivers/scsi/aic7xxx/aic7xxx_seq.h --- linux.2.5.47/drivers/scsi/aic7xxx/aic7xxx_seq.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.47-ac4/drivers/scsi/aic7xxx/aic7xxx_seq.h 2002-11-12 17:24:34.000000000 +0000 @@ -0,0 +1,1299 @@ +/* + * DO NOT EDIT - This file is automatically generated + * from the following source files: + * + * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#37 $ + * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#24 $ + */ +static uint8_t seqprog[] = { + 0xb2, 0x00, 0x00, 0x08, + 0xf7, 0x11, 0x22, 0x08, + 0x00, 0x65, 0xe0, 0x59, + 0xf7, 0x01, 0x02, 0x08, + 0xff, 0x6a, 0x24, 0x08, + 0x40, 0x00, 0x40, 0x68, + 0x08, 0x1f, 0x3e, 0x10, + 0x40, 0x00, 0x40, 0x68, + 0xff, 0x40, 0x3c, 0x60, + 0x08, 0x1f, 0x3e, 0x10, + 0x60, 0x0b, 0x42, 0x68, + 0x40, 0xfa, 0x12, 0x78, + 0x01, 0x4d, 0xc8, 0x30, + 0x00, 0x4c, 0x12, 0x70, + 0x01, 0x39, 0xa2, 0x30, + 0x00, 0x6a, 0xb2, 0x5e, + 0x01, 0x51, 0x20, 0x31, + 0x01, 0x57, 0xae, 0x00, + 0x0d, 0x6a, 0x76, 0x00, + 0x00, 0x51, 0x04, 0x5e, + 0x01, 0x51, 0xc8, 0x30, + 0x00, 0x39, 0xc8, 0x60, + 0x00, 0xbb, 0x30, 0x70, + 0xc1, 0x6a, 0xca, 0x5e, + 0x01, 0xbf, 0x72, 0x30, + 0x01, 0x40, 0x7e, 0x31, + 0x01, 0x90, 0x80, 0x30, + 0x01, 0xf6, 0xd4, 0x30, + 0x01, 0x4d, 0x9a, 0x18, + 0xfe, 0x57, 0xae, 0x08, + 0x01, 0x40, 0x20, 0x31, + 0x00, 0x65, 0xcc, 0x58, + 0x60, 0x0b, 0x40, 0x78, + 0x08, 0x6a, 0x18, 0x00, + 0x08, 0x11, 0x22, 0x00, + 0x60, 0x0b, 0x00, 0x78, + 0x40, 0x0b, 0xfc, 0x68, + 0x80, 0x0b, 0xb6, 0x78, + 0x20, 0x6a, 0x16, 0x00, + 0xa4, 0x6a, 0x06, 0x00, + 0x08, 0x3c, 0x78, 0x00, + 0x01, 0x50, 0xc8, 0x30, + 0xe0, 0x6a, 0xcc, 0x00, + 0x48, 0x6a, 0xee, 0x5d, + 0x01, 0x6a, 0xdc, 0x01, + 0x88, 0x6a, 0xcc, 0x00, + 0x48, 0x6a, 0xee, 0x5d, + 0x01, 0x6a, 0x26, 0x01, + 0xf0, 0x19, 0x7a, 0x08, + 0x0f, 0x18, 0xc8, 0x08, + 0x0f, 0x0f, 0xc8, 0x08, + 0x0f, 0x05, 0xc8, 0x08, + 0x00, 0x3d, 0x7a, 0x00, + 0x08, 0x1f, 0x6e, 0x78, + 0x80, 0x3d, 0x7a, 0x00, + 0x01, 0x3d, 0xd8, 0x31, + 0x01, 0x3d, 0x32, 0x31, + 0x10, 0x03, 0x46, 0x79, + 0x00, 0x65, 0xf4, 0x58, + 0x80, 0x66, 0xae, 0x78, + 0x01, 0x66, 0xd8, 0x31, + 0x01, 0x66, 0x32, 0x31, + 0x3f, 0x66, 0x7c, 0x08, + 0x40, 0x66, 0x82, 0x68, + 0x01, 0x3c, 0x78, 0x00, + 0x10, 0x03, 0x9e, 0x78, + 0x00, 0x65, 0xf4, 0x58, + 0xe0, 0x66, 0xc8, 0x18, + 0x00, 0x65, 0xaa, 0x50, + 0xdd, 0x66, 0xc8, 0x18, + 0x00, 0x65, 0xaa, 0x48, + 0x01, 0x66, 0xd8, 0x31, + 0x01, 0x66, 0x32, 0x31, + 0x10, 0x03, 0x46, 0x79, + 0x00, 0x65, 0xf4, 0x58, + 0x01, 0x66, 0xd8, 0x31, + 0x01, 0x66, 0x32, 0x31, + 0x01, 0x66, 0xac, 0x30, + 0x40, 0x3c, 0x78, 0x00, + 0xff, 0x6a, 0xd8, 0x01, + 0xff, 0x6a, 0x32, 0x01, + 0x90, 0x3c, 0x78, 0x00, + 0x02, 0x57, 0x3a, 0x69, + 0x10, 0x03, 0x38, 0x69, + 0x00, 0x65, 0x1e, 0x41, + 0x02, 0x57, 0xae, 0x00, + 0x00, 0x65, 0x9e, 0x40, + 0x61, 0x6a, 0xca, 0x5e, + 0x08, 0x51, 0x1e, 0x71, + 0x02, 0x0b, 0xb2, 0x78, + 0x00, 0x65, 0xae, 0x40, + 0x1a, 0x01, 0x02, 0x00, + 0xf0, 0x19, 0x7a, 0x08, + 0x0f, 0x0f, 0xc8, 0x08, + 0x0f, 0x05, 0xc8, 0x08, + 0x00, 0x3d, 0x7a, 0x00, + 0x08, 0x1f, 0xc4, 0x78, + 0x80, 0x3d, 0x7a, 0x00, + 0x20, 0x6a, 0x16, 0x00, + 0x00, 0x65, 0xc0, 0x41, + 0x00, 0x65, 0xa4, 0x5e, + 0x00, 0x65, 0x12, 0x40, + 0x20, 0x11, 0xd2, 0x68, + 0x20, 0x6a, 0x18, 0x00, + 0x20, 0x11, 0x22, 0x00, + 0xf7, 0x1f, 0xca, 0x08, + 0x80, 0xb9, 0xd8, 0x78, + 0x08, 0x65, 0xca, 0x00, + 0x01, 0x65, 0x3e, 0x30, + 0x01, 0xb9, 0x1e, 0x30, + 0x7f, 0xb9, 0x0a, 0x08, + 0x01, 0xb9, 0x0a, 0x30, + 0x01, 0x54, 0xca, 0x30, + 0x80, 0xb8, 0xe6, 0x78, + 0x80, 0x65, 0xca, 0x00, + 0x01, 0x65, 0x00, 0x34, + 0x01, 0x54, 0x00, 0x34, + 0x1a, 0x01, 0x02, 0x00, + 0x08, 0xb8, 0xf0, 0x78, + 0x20, 0x01, 0x02, 0x00, + 0x02, 0xbd, 0x08, 0x34, + 0x01, 0xbd, 0x08, 0x34, + 0x08, 0x01, 0x02, 0x00, + 0x02, 0x0b, 0xf6, 0x78, + 0xf7, 0x01, 0x02, 0x08, + 0x01, 0x06, 0xcc, 0x34, + 0xb2, 0x00, 0x00, 0x08, + 0x40, 0x6a, 0x16, 0x00, + 0x01, 0x40, 0x20, 0x31, + 0x01, 0xbf, 0x80, 0x30, + 0x01, 0xb9, 0x7a, 0x30, + 0x01, 0xba, 0x7c, 0x30, + 0x00, 0x65, 0xea, 0x58, + 0x80, 0x0b, 0xbc, 0x79, + 0xe4, 0x6a, 0x60, 0x5d, + 0x80, 0xba, 0x76, 0x5d, + 0x20, 0xb8, 0x16, 0x79, + 0x20, 0x6a, 0x76, 0x5d, + 0x00, 0xab, 0x76, 0x5d, + 0x01, 0xa9, 0x78, 0x30, + 0x10, 0xb8, 0x1e, 0x79, + 0xe4, 0x6a, 0x60, 0x5d, + 0x00, 0x65, 0xae, 0x40, + 0x10, 0x03, 0x36, 0x69, + 0x08, 0x3c, 0x52, 0x69, + 0x04, 0x3c, 0x8a, 0x69, + 0x02, 0x3c, 0x90, 0x69, + 0x01, 0x3c, 0x3c, 0x79, + 0x01, 0x6a, 0xa2, 0x30, + 0x00, 0x65, 0x9c, 0x59, + 0x04, 0x51, 0x2c, 0x61, + 0x00, 0x6a, 0xb2, 0x5e, + 0x0d, 0x6a, 0x76, 0x00, + 0x00, 0xbb, 0x04, 0x5e, + 0x00, 0x65, 0x16, 0x41, + 0xa4, 0x6a, 0x06, 0x00, + 0x00, 0x65, 0xf4, 0x58, + 0x00, 0x65, 0xae, 0x40, + 0xe4, 0x6a, 0x60, 0x5d, + 0x20, 0x3c, 0x42, 0x79, + 0x02, 0x6a, 0x76, 0x5d, + 0x04, 0x6a, 0x76, 0x5d, + 0x01, 0x03, 0x44, 0x69, + 0xf7, 0x11, 0x22, 0x08, + 0xff, 0x6a, 0x24, 0x08, + 0xff, 0x6a, 0x06, 0x08, + 0x01, 0x6a, 0x7e, 0x00, + 0x00, 0x65, 0x9c, 0x59, + 0x00, 0x65, 0x04, 0x40, + 0x80, 0x86, 0xc8, 0x08, + 0x01, 0x4f, 0xc8, 0x30, + 0x00, 0x50, 0x64, 0x61, + 0xc4, 0x6a, 0x60, 0x5d, + 0x40, 0x3c, 0x60, 0x79, + 0x28, 0x6a, 0x76, 0x5d, + 0x00, 0x65, 0x44, 0x41, + 0x08, 0x6a, 0x76, 0x5d, + 0x00, 0x65, 0x44, 0x41, + 0x84, 0x6a, 0x60, 0x5d, + 0x00, 0x65, 0xf4, 0x58, + 0x01, 0x66, 0xc8, 0x30, + 0x01, 0x64, 0xd8, 0x31, + 0x01, 0x64, 0x32, 0x31, + 0x5b, 0x64, 0xc8, 0x28, + 0x30, 0x64, 0xca, 0x18, + 0x01, 0x6c, 0xc8, 0x30, + 0xff, 0x64, 0x86, 0x79, + 0x08, 0x01, 0x02, 0x00, + 0x02, 0x0b, 0x78, 0x79, + 0x01, 0x64, 0x7e, 0x61, + 0xf7, 0x01, 0x02, 0x08, + 0x01, 0x06, 0xd8, 0x31, + 0x01, 0x06, 0x32, 0x31, + 0xff, 0x64, 0xc8, 0x18, + 0xff, 0x64, 0x78, 0x69, + 0xf7, 0x3c, 0x78, 0x08, + 0x00, 0x65, 0x1e, 0x41, + 0x40, 0xaa, 0x7e, 0x10, + 0x04, 0xaa, 0x60, 0x5d, + 0x00, 0x65, 0x52, 0x42, + 0xc4, 0x6a, 0x60, 0x5d, + 0xc0, 0x6a, 0x7e, 0x00, + 0x00, 0xa8, 0x76, 0x5d, + 0xe4, 0x6a, 0x06, 0x00, + 0x00, 0x6a, 0x76, 0x5d, + 0x00, 0x65, 0x44, 0x41, + 0x10, 0x3c, 0xa0, 0x69, + 0x00, 0xbb, 0x80, 0x44, + 0x18, 0x6a, 0xda, 0x01, + 0x01, 0x69, 0xd8, 0x31, + 0x1c, 0x6a, 0xd0, 0x01, + 0x09, 0xee, 0xdc, 0x01, + 0x80, 0xee, 0xa8, 0x79, + 0xff, 0x6a, 0xdc, 0x09, + 0x01, 0x93, 0x26, 0x01, + 0x03, 0x6a, 0x2a, 0x01, + 0x01, 0x69, 0x32, 0x31, + 0x1c, 0x6a, 0xd2, 0x5d, + 0x0a, 0x93, 0x26, 0x01, + 0x00, 0x65, 0x9a, 0x5e, + 0x01, 0x50, 0xa0, 0x18, + 0x02, 0x6a, 0x22, 0x05, + 0x80, 0x6a, 0x74, 0x00, + 0x80, 0x3c, 0x78, 0x00, + 0x00, 0x65, 0xca, 0x5d, + 0x01, 0x3f, 0xc8, 0x30, + 0xbf, 0x64, 0x52, 0x7a, + 0x80, 0x64, 0xa6, 0x73, + 0xa0, 0x64, 0x04, 0x74, + 0xc0, 0x64, 0xf8, 0x73, + 0xe0, 0x64, 0x34, 0x74, + 0x01, 0x6a, 0xca, 0x5e, + 0x00, 0x65, 0xc0, 0x41, + 0xf7, 0x11, 0x22, 0x08, + 0x01, 0x06, 0xd4, 0x30, + 0xff, 0x6a, 0x24, 0x08, + 0xf7, 0x01, 0x02, 0x08, + 0x09, 0x0c, 0xda, 0x79, + 0x08, 0x0c, 0x04, 0x68, + 0xb1, 0x6a, 0xca, 0x5e, + 0xff, 0x6a, 0x26, 0x09, + 0x12, 0x01, 0x02, 0x00, + 0x02, 0x6a, 0x08, 0x30, + 0xff, 0x6a, 0x08, 0x08, + 0xdf, 0x01, 0x02, 0x08, + 0x01, 0x6a, 0x7e, 0x00, + 0xff, 0x6a, 0x78, 0x0c, + 0xff, 0x6a, 0xc8, 0x08, + 0x08, 0xa4, 0x48, 0x19, + 0x00, 0xa5, 0x4a, 0x21, + 0x00, 0xa6, 0x4c, 0x21, + 0x00, 0xa7, 0x4e, 0x25, + 0x08, 0xeb, 0xce, 0x7e, + 0x80, 0xeb, 0xfa, 0x79, + 0xff, 0x6a, 0xd6, 0x09, + 0x08, 0xeb, 0xfe, 0x69, + 0xff, 0x6a, 0xd4, 0x0c, + 0x80, 0xa3, 0xce, 0x6e, + 0x88, 0xeb, 0x14, 0x72, + 0x08, 0xeb, 0xce, 0x6e, + 0x04, 0xea, 0x18, 0xe2, + 0x08, 0xee, 0xce, 0x6e, + 0x04, 0x6a, 0xd0, 0x81, + 0x05, 0xa4, 0xc0, 0x89, + 0x03, 0xa5, 0xc2, 0x31, + 0x09, 0x6a, 0xd6, 0x05, + 0x00, 0x65, 0xfc, 0x59, + 0x06, 0xa4, 0xd4, 0x89, + 0x80, 0x94, 0xce, 0x7e, + 0x07, 0xe9, 0x10, 0x31, + 0x01, 0x8c, 0x20, 0x7a, + 0x01, 0x55, 0xaa, 0x10, + 0x01, 0xe9, 0x46, 0x31, + 0x00, 0xa3, 0xac, 0x5e, + 0x00, 0x65, 0xee, 0x59, + 0x01, 0xa4, 0xca, 0x30, + 0x01, 0x55, 0x2c, 0x7a, + 0x04, 0x65, 0xca, 0x00, + 0x80, 0xa3, 0x30, 0x7a, + 0x02, 0x65, 0xca, 0x00, + 0x01, 0x65, 0xf8, 0x31, + 0x80, 0x93, 0x26, 0x01, + 0xff, 0x6a, 0xd4, 0x0c, + 0x01, 0x8c, 0xc8, 0x30, + 0x00, 0x88, 0xc8, 0x18, + 0x02, 0x64, 0xc8, 0x88, + 0xff, 0x64, 0xce, 0x7e, + 0xff, 0x8d, 0x46, 0x6a, + 0xff, 0x8e, 0x46, 0x6a, + 0x03, 0x8c, 0xd4, 0x98, + 0x00, 0x65, 0xce, 0x56, + 0x01, 0x64, 0x70, 0x30, + 0xff, 0x64, 0xc8, 0x10, + 0x01, 0x64, 0xc8, 0x18, + 0x00, 0x8c, 0x18, 0x19, + 0xff, 0x8d, 0x1a, 0x21, + 0xff, 0x8e, 0x1c, 0x25, + 0x80, 0x3c, 0x56, 0x6a, + 0x21, 0x6a, 0xca, 0x46, + 0xa8, 0x6a, 0x76, 0x00, + 0x79, 0x6a, 0x76, 0x00, + 0x40, 0x3f, 0x5e, 0x6a, + 0x04, 0x3b, 0x76, 0x00, + 0x04, 0x6a, 0xd4, 0x81, + 0x20, 0x3c, 0x66, 0x7a, + 0x51, 0x6a, 0xca, 0x5e, + 0x00, 0x65, 0x80, 0x42, + 0x20, 0x3c, 0x78, 0x00, + 0x00, 0xb3, 0xac, 0x5e, + 0x07, 0xac, 0x10, 0x31, + 0x05, 0xb3, 0x46, 0x31, + 0x88, 0x6a, 0xcc, 0x00, + 0xac, 0x6a, 0xe0, 0x5d, + 0xa3, 0x6a, 0xcc, 0x00, + 0xb3, 0x6a, 0xe4, 0x5d, + 0x00, 0x65, 0x36, 0x5a, + 0xfd, 0xa4, 0x48, 0x09, + 0x01, 0x8c, 0xaa, 0x08, + 0x03, 0x8c, 0x10, 0x30, + 0x00, 0x65, 0xd8, 0x5d, + 0x01, 0xa4, 0x92, 0x7a, + 0x04, 0x3b, 0x76, 0x08, + 0x01, 0x3b, 0x26, 0x31, + 0x80, 0x02, 0x04, 0x00, + 0x10, 0x0c, 0x88, 0x7a, + 0x03, 0x9e, 0x8a, 0x6a, + 0x7f, 0x02, 0x04, 0x08, + 0x91, 0x6a, 0xca, 0x5e, + 0x00, 0x65, 0xc0, 0x41, + 0x01, 0xa4, 0xca, 0x30, + 0x80, 0xa3, 0x98, 0x7a, + 0x02, 0x65, 0xca, 0x00, + 0x01, 0x55, 0x9c, 0x7a, + 0x04, 0x65, 0xca, 0x00, + 0x01, 0x65, 0xf8, 0x31, + 0x01, 0x3b, 0x26, 0x31, + 0x00, 0x65, 0x02, 0x5a, + 0x01, 0xfc, 0xaa, 0x6a, + 0x80, 0x0b, 0xa0, 0x6a, + 0x10, 0x0c, 0xa0, 0x7a, + 0x20, 0x93, 0xa0, 0x6a, + 0x02, 0x93, 0x26, 0x01, + 0x02, 0xfc, 0xb4, 0x7a, + 0x40, 0x0d, 0xce, 0x6a, + 0x01, 0xa4, 0x48, 0x01, + 0x00, 0x65, 0xce, 0x42, + 0x40, 0x0d, 0xba, 0x6a, + 0x00, 0x65, 0x02, 0x5a, + 0x00, 0x65, 0xac, 0x42, + 0x80, 0xfc, 0xc4, 0x7a, + 0x80, 0xa4, 0xc4, 0x6a, + 0xff, 0xa5, 0x4a, 0x19, + 0xff, 0xa6, 0x4c, 0x21, + 0xff, 0xa7, 0x4e, 0x21, + 0xf8, 0xfc, 0x48, 0x09, + 0xff, 0x6a, 0xaa, 0x08, + 0x04, 0xfc, 0xcc, 0x7a, + 0x01, 0x55, 0xaa, 0x00, + 0xff, 0x6a, 0x46, 0x09, + 0x04, 0x3b, 0xe6, 0x6a, + 0x02, 0x93, 0x26, 0x01, + 0x01, 0x94, 0xd0, 0x7a, + 0x01, 0x94, 0xd0, 0x7a, + 0x01, 0x94, 0xd0, 0x7a, + 0x01, 0x94, 0xd0, 0x7a, + 0x01, 0x94, 0xd0, 0x7a, + 0x01, 0xa4, 0xe4, 0x7a, + 0x01, 0xfc, 0xde, 0x7a, + 0x01, 0x94, 0xe6, 0x6a, + 0x00, 0x65, 0x80, 0x42, + 0x01, 0x94, 0xe4, 0x7a, + 0x10, 0x94, 0xe6, 0x6a, + 0xd7, 0x93, 0x26, 0x09, + 0x28, 0x93, 0xea, 0x6a, + 0x01, 0x85, 0x0a, 0x01, + 0x02, 0xfc, 0xf2, 0x6a, + 0x01, 0x14, 0x46, 0x31, + 0xff, 0x6a, 0x10, 0x09, + 0xfe, 0x85, 0x0a, 0x09, + 0xff, 0x38, 0x00, 0x6b, + 0x80, 0xa3, 0x00, 0x7b, + 0x80, 0x0b, 0xfe, 0x7a, + 0x04, 0x3b, 0x00, 0x7b, + 0xbf, 0x3b, 0x76, 0x08, + 0x01, 0x3b, 0x26, 0x31, + 0x00, 0x65, 0x02, 0x5a, + 0x01, 0x0b, 0x0e, 0x6b, + 0x10, 0x0c, 0x02, 0x7b, + 0x04, 0x93, 0x0c, 0x6b, + 0x01, 0x94, 0x0a, 0x7b, + 0x10, 0x94, 0x0c, 0x6b, + 0xc7, 0x93, 0x26, 0x09, + 0x01, 0x99, 0xd4, 0x30, + 0x38, 0x93, 0x10, 0x6b, + 0xff, 0x08, 0x62, 0x6b, + 0xff, 0x09, 0x62, 0x6b, + 0xff, 0x0a, 0x62, 0x6b, + 0xff, 0x38, 0x2c, 0x7b, + 0x04, 0x14, 0x10, 0x31, + 0x01, 0x38, 0x18, 0x31, + 0x02, 0x6a, 0x1a, 0x31, + 0x88, 0x6a, 0xcc, 0x00, + 0x14, 0x6a, 0xe6, 0x5d, + 0x00, 0x38, 0xd2, 0x5d, + 0xff, 0x6a, 0x70, 0x08, + 0x00, 0x65, 0x58, 0x43, + 0x80, 0xa3, 0x32, 0x7b, + 0x01, 0xa4, 0x48, 0x01, + 0x00, 0x65, 0x62, 0x43, + 0x08, 0xeb, 0x38, 0x7b, + 0x00, 0x65, 0x02, 0x5a, + 0x08, 0xeb, 0x34, 0x6b, + 0x07, 0xe9, 0x10, 0x31, + 0x01, 0xe9, 0xca, 0x30, + 0x01, 0x65, 0x46, 0x31, + 0x00, 0x6a, 0xac, 0x5e, + 0x88, 0x6a, 0xcc, 0x00, + 0xa4, 0x6a, 0xe6, 0x5d, + 0x08, 0x6a, 0xd2, 0x5d, + 0x0d, 0x93, 0x26, 0x01, + 0x00, 0x65, 0x9a, 0x5e, + 0x88, 0x6a, 0xcc, 0x00, + 0x00, 0x65, 0x7c, 0x5e, + 0x01, 0x99, 0x46, 0x31, + 0x00, 0xa3, 0xac, 0x5e, + 0x01, 0x88, 0x10, 0x31, + 0x00, 0x65, 0x36, 0x5a, + 0x00, 0x65, 0xee, 0x59, + 0x03, 0x8c, 0x10, 0x30, + 0x00, 0x65, 0xd8, 0x5d, + 0x01, 0x8c, 0x60, 0x7b, + 0x01, 0x55, 0xaa, 0x10, + 0x80, 0x0b, 0x80, 0x6a, + 0x80, 0x0b, 0x6a, 0x6b, + 0x01, 0x0c, 0x64, 0x7b, + 0x10, 0x0c, 0x80, 0x7a, + 0x03, 0x9e, 0x80, 0x6a, + 0x00, 0x65, 0xf8, 0x59, + 0x00, 0x6a, 0xac, 0x5e, + 0x01, 0xa4, 0x8a, 0x6b, + 0xff, 0x38, 0x80, 0x7b, + 0x01, 0x38, 0xc8, 0x30, + 0x00, 0x08, 0x40, 0x19, + 0xff, 0x6a, 0xc8, 0x08, + 0x00, 0x09, 0x42, 0x21, + 0x00, 0x0a, 0x44, 0x21, + 0xff, 0x6a, 0x70, 0x08, + 0x00, 0x65, 0x82, 0x43, + 0x03, 0x08, 0x40, 0x31, + 0x03, 0x08, 0x40, 0x31, + 0x01, 0x08, 0x40, 0x31, + 0x01, 0x09, 0x42, 0x31, + 0x01, 0x0a, 0x44, 0x31, + 0xfd, 0xb4, 0x68, 0x09, + 0x12, 0x01, 0x02, 0x00, + 0x12, 0x01, 0x02, 0x00, + 0x04, 0x3c, 0xc0, 0x79, + 0xfb, 0x3c, 0x78, 0x08, + 0x04, 0x93, 0x1e, 0x79, + 0x01, 0x0c, 0x96, 0x6b, + 0x01, 0x55, 0x1e, 0x79, + 0x80, 0x04, 0x1e, 0x79, + 0xe4, 0x6a, 0x60, 0x5d, + 0x23, 0x6a, 0x76, 0x5d, + 0x01, 0x6a, 0x76, 0x5d, + 0x00, 0x65, 0x1e, 0x41, + 0x00, 0x65, 0xc0, 0x41, + 0x80, 0x3c, 0xaa, 0x6b, + 0x21, 0x6a, 0xca, 0x46, + 0x01, 0xbc, 0x18, 0x31, + 0x02, 0x6a, 0x1a, 0x31, + 0x02, 0x6a, 0xf8, 0x01, + 0x01, 0xbc, 0x10, 0x30, + 0x02, 0x6a, 0x12, 0x30, + 0x01, 0xbc, 0x10, 0x30, + 0xff, 0x6a, 0x12, 0x08, + 0xff, 0x6a, 0x14, 0x08, + 0xf3, 0xbc, 0xd4, 0x18, + 0xa0, 0x6a, 0xd0, 0x53, + 0x04, 0xa0, 0x10, 0x31, + 0xac, 0x6a, 0x26, 0x01, + 0x04, 0xa0, 0x10, 0x31, + 0x03, 0x08, 0x18, 0x31, + 0x88, 0x6a, 0xcc, 0x00, + 0xa0, 0x6a, 0xe6, 0x5d, + 0x00, 0xbc, 0xd2, 0x5d, + 0x3d, 0x6a, 0x26, 0x01, + 0x00, 0x65, 0xe8, 0x43, + 0xff, 0x6a, 0x10, 0x09, + 0xa4, 0x6a, 0x26, 0x01, + 0x0c, 0xa0, 0x32, 0x31, + 0x05, 0x6a, 0x26, 0x01, + 0x35, 0x6a, 0x26, 0x01, + 0x0c, 0xa0, 0x32, 0x31, + 0x36, 0x6a, 0x26, 0x01, + 0x02, 0x93, 0x26, 0x01, + 0x35, 0x6a, 0x26, 0x01, + 0x00, 0x65, 0x8e, 0x5e, + 0x00, 0x65, 0x8e, 0x5e, + 0x02, 0x93, 0x26, 0x01, + 0x04, 0x0b, 0xec, 0x6b, + 0x10, 0x0c, 0xe8, 0x7b, + 0x01, 0x03, 0xec, 0x6b, + 0x20, 0x93, 0xe8, 0x6b, + 0xc7, 0x93, 0x26, 0x09, + 0x38, 0x93, 0xf2, 0x6b, + 0x10, 0x01, 0x02, 0x00, + 0x00, 0x65, 0xc0, 0x41, + 0x80, 0x3c, 0xfc, 0x6b, + 0x21, 0x6a, 0xca, 0x46, + 0x01, 0x06, 0x50, 0x31, + 0x00, 0x65, 0xc0, 0x41, + 0x10, 0x3f, 0x06, 0x00, + 0x10, 0x6a, 0x06, 0x00, + 0x01, 0x3a, 0xca, 0x30, + 0x80, 0x65, 0x20, 0x64, + 0x10, 0xb8, 0x44, 0x6c, + 0xc0, 0xba, 0xca, 0x00, + 0x40, 0xb8, 0x10, 0x6c, + 0xbf, 0x65, 0xca, 0x08, + 0x20, 0xb8, 0x24, 0x7c, + 0x01, 0x65, 0x0c, 0x30, + 0x00, 0x65, 0xca, 0x5d, + 0xa0, 0x3f, 0x2c, 0x64, + 0x23, 0xb8, 0x0c, 0x08, + 0x00, 0x65, 0xca, 0x5d, + 0xa0, 0x3f, 0x2c, 0x64, + 0x00, 0xbb, 0x24, 0x44, + 0xff, 0x65, 0x24, 0x64, + 0x00, 0x65, 0x44, 0x44, + 0x40, 0x6a, 0x18, 0x00, + 0x01, 0x65, 0x0c, 0x30, + 0x00, 0x65, 0xca, 0x5d, + 0xa0, 0x3f, 0x00, 0x74, + 0x40, 0x6a, 0x18, 0x00, + 0x01, 0x3a, 0xa6, 0x30, + 0x08, 0x6a, 0x74, 0x00, + 0x00, 0x65, 0xc0, 0x41, + 0x64, 0x6a, 0x5a, 0x5d, + 0x80, 0x64, 0xca, 0x6c, + 0x04, 0x64, 0x90, 0x74, + 0x02, 0x64, 0x9e, 0x74, + 0x00, 0x6a, 0x60, 0x74, + 0x03, 0x64, 0xbc, 0x74, + 0x23, 0x64, 0x4c, 0x74, + 0x08, 0x64, 0x5c, 0x74, + 0x61, 0x6a, 0xca, 0x5e, + 0x00, 0x65, 0xca, 0x5d, + 0x08, 0x51, 0xc2, 0x71, + 0x00, 0x65, 0x44, 0x44, + 0x80, 0x04, 0x5a, 0x7c, + 0x51, 0x6a, 0x50, 0x5d, + 0x01, 0x51, 0x5a, 0x64, + 0x01, 0xa4, 0x56, 0x7c, + 0x01, 0x55, 0x5c, 0x7c, + 0x41, 0x6a, 0xca, 0x5e, + 0x00, 0x65, 0x5c, 0x44, + 0x07, 0x6a, 0x46, 0x5d, + 0x01, 0x06, 0xd4, 0x30, + 0x00, 0x65, 0xc0, 0x41, + 0x10, 0xb8, 0x64, 0x7c, + 0xa1, 0x6a, 0xca, 0x5e, + 0x01, 0xb4, 0x6a, 0x6c, + 0x02, 0xb4, 0x6c, 0x6c, + 0x01, 0xa4, 0x6c, 0x7c, + 0xff, 0xa8, 0x7c, 0x7c, + 0x04, 0xb4, 0x68, 0x01, + 0x01, 0x6a, 0x76, 0x00, + 0x00, 0xbb, 0x04, 0x5e, + 0xff, 0xa8, 0x7c, 0x7c, + 0x71, 0x6a, 0xca, 0x5e, + 0x40, 0x51, 0x7c, 0x64, + 0x00, 0x65, 0xa4, 0x5e, + 0x00, 0x65, 0xd2, 0x41, + 0x00, 0xbb, 0x80, 0x5c, + 0x00, 0x65, 0xd2, 0x41, + 0x00, 0x65, 0xa4, 0x5e, + 0x01, 0x65, 0xa2, 0x30, + 0x01, 0xf8, 0xc8, 0x30, + 0x01, 0x4e, 0xc8, 0x30, + 0x00, 0x6a, 0xa8, 0xdd, + 0x00, 0x51, 0xba, 0x5d, + 0x01, 0x4e, 0x9c, 0x18, + 0x02, 0x6a, 0x22, 0x05, + 0x04, 0xb8, 0x70, 0x01, + 0x00, 0x65, 0xc6, 0x5e, + 0x20, 0xb8, 0xd2, 0x69, + 0x01, 0xbb, 0xa2, 0x30, + 0x01, 0xba, 0x7c, 0x30, + 0x00, 0xb9, 0xc0, 0x5c, + 0x00, 0x65, 0xd2, 0x41, + 0x01, 0x06, 0xd4, 0x30, + 0x20, 0x3c, 0xc0, 0x79, + 0x20, 0x3c, 0x5c, 0x7c, + 0x01, 0xa4, 0xac, 0x7c, + 0x01, 0xb4, 0x68, 0x01, + 0x00, 0x65, 0xc0, 0x41, + 0x00, 0x65, 0x5c, 0x44, + 0x04, 0x14, 0x58, 0x31, + 0x01, 0x06, 0xd4, 0x30, + 0x08, 0xa0, 0x60, 0x31, + 0xac, 0x6a, 0xcc, 0x00, + 0x14, 0x6a, 0xe6, 0x5d, + 0x01, 0x06, 0xd4, 0x30, + 0xa0, 0x6a, 0xde, 0x5d, + 0x00, 0x65, 0xc0, 0x41, + 0xdf, 0x3c, 0x78, 0x08, + 0x00, 0x65, 0x5c, 0x44, + 0x4c, 0x65, 0xcc, 0x28, + 0x01, 0x3e, 0x20, 0x31, + 0xd0, 0x66, 0xcc, 0x18, + 0x20, 0x66, 0xcc, 0x18, + 0x01, 0x51, 0xda, 0x34, + 0x4c, 0x3d, 0xca, 0x28, + 0x3f, 0x64, 0x7c, 0x08, + 0xd0, 0x65, 0xca, 0x18, + 0x01, 0x3e, 0x20, 0x31, + 0x30, 0x65, 0xd4, 0x18, + 0x00, 0x65, 0xd8, 0x4c, + 0xe1, 0x6a, 0x22, 0x01, + 0xff, 0x6a, 0xd4, 0x08, + 0x20, 0x65, 0xd4, 0x18, + 0x00, 0x65, 0xe0, 0x54, + 0xe1, 0x6a, 0x22, 0x01, + 0xff, 0x6a, 0xd4, 0x08, + 0x20, 0x65, 0xca, 0x18, + 0xe0, 0x65, 0xd4, 0x18, + 0x00, 0x65, 0xea, 0x4c, + 0xe1, 0x6a, 0x22, 0x01, + 0xff, 0x6a, 0xd4, 0x08, + 0xd0, 0x65, 0xd4, 0x18, + 0x00, 0x65, 0xf2, 0x54, + 0xe1, 0x6a, 0x22, 0x01, + 0xff, 0x6a, 0xd4, 0x08, + 0x01, 0x6c, 0xa2, 0x30, + 0xff, 0x51, 0x04, 0x75, + 0x00, 0x51, 0x80, 0x5d, + 0x01, 0x51, 0x20, 0x31, + 0x00, 0x65, 0x26, 0x45, + 0x01, 0xba, 0xc8, 0x30, + 0x00, 0x3e, 0x26, 0x75, + 0x00, 0x65, 0xa2, 0x5e, + 0x80, 0x3c, 0x78, 0x00, + 0x01, 0x06, 0xd4, 0x30, + 0x00, 0x65, 0xca, 0x5d, + 0x01, 0x3c, 0x78, 0x00, + 0xe0, 0x3f, 0x42, 0x65, + 0x02, 0x3c, 0x78, 0x00, + 0x20, 0x12, 0x42, 0x65, + 0x51, 0x6a, 0x50, 0x5d, + 0x00, 0x51, 0x80, 0x5d, + 0x51, 0x6a, 0x50, 0x5d, + 0x01, 0x51, 0x20, 0x31, + 0x04, 0x3c, 0x78, 0x00, + 0x01, 0xb9, 0xc8, 0x30, + 0x00, 0x3d, 0x40, 0x65, + 0x08, 0x3c, 0x78, 0x00, + 0x01, 0xba, 0xc8, 0x30, + 0x00, 0x3e, 0x40, 0x65, + 0x10, 0x3c, 0x78, 0x00, + 0x04, 0xb8, 0x40, 0x7d, + 0xfb, 0xb8, 0x70, 0x09, + 0x20, 0xb8, 0x36, 0x6d, + 0x01, 0x90, 0xc8, 0x30, + 0xff, 0x6a, 0xa2, 0x00, + 0x00, 0x3d, 0xc0, 0x5c, + 0x01, 0x64, 0x20, 0x31, + 0x80, 0x6a, 0x78, 0x00, + 0x00, 0x65, 0xec, 0x58, + 0x10, 0xb8, 0x5c, 0x7c, + 0xff, 0x6a, 0x46, 0x5d, + 0x00, 0x65, 0x5c, 0x44, + 0x00, 0x65, 0xa2, 0x5e, + 0x31, 0x6a, 0xca, 0x5e, + 0x00, 0x65, 0x5c, 0x44, + 0x10, 0x3f, 0x06, 0x00, + 0x10, 0x6a, 0x06, 0x00, + 0x01, 0x65, 0x74, 0x34, + 0x81, 0x6a, 0xca, 0x5e, + 0x00, 0x65, 0x52, 0x45, + 0x01, 0x06, 0xd4, 0x30, + 0x01, 0x0c, 0x52, 0x7d, + 0x04, 0x0c, 0x4c, 0x6d, + 0xe0, 0x03, 0x7e, 0x08, + 0xe0, 0x3f, 0xc0, 0x61, + 0x01, 0x65, 0xcc, 0x30, + 0x01, 0x12, 0xda, 0x34, + 0x01, 0x06, 0xd4, 0x34, + 0x01, 0x03, 0x60, 0x6d, + 0x40, 0x03, 0xcc, 0x08, + 0x01, 0x65, 0x06, 0x30, + 0x40, 0x65, 0xc8, 0x08, + 0x00, 0x66, 0x6e, 0x75, + 0x40, 0x65, 0x6e, 0x7d, + 0x00, 0x65, 0x6e, 0x5d, + 0xff, 0x6a, 0xd4, 0x08, + 0xff, 0x6a, 0xd4, 0x08, + 0xff, 0x6a, 0xd4, 0x08, + 0xff, 0x6a, 0xd4, 0x0c, + 0x08, 0x01, 0x02, 0x00, + 0x02, 0x0b, 0x78, 0x7d, + 0x01, 0x65, 0x0c, 0x30, + 0x02, 0x0b, 0x7c, 0x7d, + 0xf7, 0x01, 0x02, 0x0c, + 0x01, 0x65, 0xc8, 0x30, + 0xff, 0x41, 0xa0, 0x75, + 0x01, 0x41, 0x20, 0x31, + 0xff, 0x6a, 0xa4, 0x00, + 0x00, 0x65, 0x90, 0x45, + 0xff, 0xbf, 0xa0, 0x75, + 0x01, 0x90, 0xa4, 0x30, + 0x01, 0xbf, 0x20, 0x31, + 0x00, 0xbb, 0x8a, 0x65, + 0xff, 0x52, 0x9e, 0x75, + 0x01, 0xbf, 0xcc, 0x30, + 0x01, 0x90, 0xca, 0x30, + 0x01, 0x52, 0x20, 0x31, + 0x01, 0x66, 0x7e, 0x31, + 0x01, 0x65, 0x20, 0x35, + 0x01, 0xbf, 0x82, 0x34, + 0x01, 0x64, 0xa2, 0x30, + 0x00, 0x6a, 0xb2, 0x5e, + 0x0d, 0x6a, 0x76, 0x00, + 0x00, 0x51, 0x04, 0x46, + 0x01, 0x65, 0xa4, 0x30, + 0xe0, 0x6a, 0xcc, 0x00, + 0x48, 0x6a, 0xf8, 0x5d, + 0x01, 0x6a, 0xd0, 0x01, + 0x01, 0x6a, 0xdc, 0x05, + 0x88, 0x6a, 0xcc, 0x00, + 0x48, 0x6a, 0xf8, 0x5d, + 0x01, 0x6a, 0xd2, 0x5d, + 0x01, 0x6a, 0x26, 0x05, + 0x01, 0x65, 0xd8, 0x31, + 0x09, 0xee, 0xdc, 0x01, + 0x80, 0xee, 0xbe, 0x7d, + 0xff, 0x6a, 0xdc, 0x0d, + 0x01, 0x65, 0x32, 0x31, + 0x0a, 0x93, 0x26, 0x01, + 0x00, 0x65, 0x9a, 0x46, + 0x81, 0x6a, 0xca, 0x5e, + 0x01, 0x0c, 0xca, 0x7d, + 0x04, 0x0c, 0xc8, 0x6d, + 0xe0, 0x03, 0x06, 0x08, + 0xe0, 0x03, 0x7e, 0x0c, + 0x01, 0x65, 0x18, 0x31, + 0xff, 0x6a, 0x1a, 0x09, + 0xff, 0x6a, 0x1c, 0x0d, + 0x01, 0x8c, 0x10, 0x30, + 0x01, 0x8d, 0x12, 0x30, + 0x01, 0x8e, 0x14, 0x34, + 0x01, 0x6c, 0xda, 0x30, + 0x01, 0x6c, 0xda, 0x30, + 0x01, 0x6c, 0xda, 0x30, + 0x01, 0x6c, 0xda, 0x30, + 0x01, 0x6c, 0xda, 0x30, + 0x01, 0x6c, 0xda, 0x30, + 0x01, 0x6c, 0xda, 0x30, + 0x01, 0x6c, 0xda, 0x34, + 0x3d, 0x64, 0xa4, 0x28, + 0x55, 0x64, 0xc8, 0x28, + 0x00, 0x65, 0xf8, 0x45, + 0x2e, 0x64, 0xa4, 0x28, + 0x66, 0x64, 0xc8, 0x28, + 0x00, 0x6c, 0xda, 0x18, + 0x01, 0x52, 0xc8, 0x30, + 0x00, 0x6c, 0xda, 0x20, + 0xff, 0x6a, 0xc8, 0x08, + 0x00, 0x6c, 0xda, 0x20, + 0x00, 0x6c, 0xda, 0x24, + 0x01, 0x65, 0xc8, 0x30, + 0xe0, 0x6a, 0xcc, 0x00, + 0x44, 0x6a, 0xf4, 0x5d, + 0x01, 0x90, 0xe2, 0x31, + 0x04, 0x3b, 0x18, 0x7e, + 0x30, 0x6a, 0xd0, 0x01, + 0x20, 0x6a, 0xd0, 0x01, + 0x1d, 0x6a, 0xdc, 0x01, + 0xdc, 0xee, 0x14, 0x66, + 0x00, 0x65, 0x30, 0x46, + 0x20, 0x6a, 0xd0, 0x01, + 0x01, 0x6a, 0xdc, 0x01, + 0x20, 0xa0, 0xd8, 0x31, + 0x09, 0xee, 0xdc, 0x01, + 0x80, 0xee, 0x20, 0x7e, + 0x11, 0x6a, 0xdc, 0x01, + 0x50, 0xee, 0x24, 0x66, + 0x20, 0x6a, 0xd0, 0x01, + 0x09, 0x6a, 0xdc, 0x01, + 0x88, 0xee, 0x2a, 0x66, + 0x19, 0x6a, 0xdc, 0x01, + 0xd8, 0xee, 0x2e, 0x66, + 0xff, 0x6a, 0xdc, 0x09, + 0x18, 0xee, 0x32, 0x6e, + 0xff, 0x6a, 0xd4, 0x0c, + 0x88, 0x6a, 0xcc, 0x00, + 0x44, 0x6a, 0xf4, 0x5d, + 0x20, 0x6a, 0xd2, 0x5d, + 0x01, 0x3b, 0x26, 0x31, + 0x04, 0x3b, 0x4c, 0x6e, + 0xa0, 0x6a, 0xca, 0x00, + 0x20, 0x65, 0xc8, 0x18, + 0x00, 0x65, 0x8a, 0x5e, + 0x00, 0x65, 0x44, 0x66, + 0x0a, 0x93, 0x26, 0x01, + 0x00, 0x65, 0x9a, 0x46, + 0xa0, 0x6a, 0xcc, 0x00, + 0xff, 0x6a, 0xc8, 0x08, + 0x20, 0x94, 0x50, 0x6e, + 0x10, 0x94, 0x52, 0x6e, + 0x08, 0x94, 0x6c, 0x6e, + 0x08, 0x94, 0x6c, 0x6e, + 0x08, 0x94, 0x6c, 0x6e, + 0xff, 0x8c, 0xc8, 0x10, + 0xc1, 0x64, 0xc8, 0x18, + 0xf8, 0x64, 0xc8, 0x08, + 0x01, 0x99, 0xda, 0x30, + 0x00, 0x66, 0x60, 0x66, + 0xc0, 0x66, 0x9c, 0x76, + 0x60, 0x66, 0xc8, 0x18, + 0x3d, 0x64, 0xc8, 0x28, + 0x00, 0x65, 0x50, 0x46, + 0xf7, 0x93, 0x26, 0x09, + 0x08, 0x93, 0x6e, 0x6e, + 0x00, 0x62, 0xc4, 0x18, + 0x00, 0x65, 0x9a, 0x5e, + 0x00, 0x65, 0x7a, 0x5e, + 0x00, 0x65, 0x7a, 0x5e, + 0x00, 0x65, 0x7a, 0x5e, + 0x01, 0x99, 0xda, 0x30, + 0x01, 0x99, 0xda, 0x30, + 0x01, 0x99, 0xda, 0x30, + 0x01, 0x99, 0xda, 0x30, + 0x01, 0x99, 0xda, 0x30, + 0x01, 0x99, 0xda, 0x30, + 0x01, 0x99, 0xda, 0x30, + 0x01, 0x99, 0xda, 0x34, + 0x01, 0x6c, 0x32, 0x31, + 0x01, 0x6c, 0x32, 0x31, + 0x01, 0x6c, 0x32, 0x31, + 0x01, 0x6c, 0x32, 0x31, + 0x01, 0x6c, 0x32, 0x31, + 0x01, 0x6c, 0x32, 0x31, + 0x01, 0x6c, 0x32, 0x31, + 0x01, 0x6c, 0x32, 0x35, + 0x08, 0x94, 0x9a, 0x7e, + 0xf7, 0x93, 0x26, 0x09, + 0x08, 0x93, 0x9e, 0x6e, + 0xff, 0x6a, 0xd4, 0x0c, + 0x04, 0xb8, 0xc6, 0x6e, + 0x01, 0x42, 0x7e, 0x31, + 0xff, 0x6a, 0x76, 0x01, + 0x01, 0x90, 0x84, 0x34, + 0xff, 0x6a, 0x76, 0x05, + 0x01, 0x85, 0x0a, 0x01, + 0x7f, 0x65, 0x10, 0x09, + 0xfe, 0x85, 0x0a, 0x0d, + 0xff, 0x42, 0xc2, 0x66, + 0xff, 0x41, 0xba, 0x66, + 0xd1, 0x6a, 0xca, 0x5e, + 0xff, 0x6a, 0xca, 0x04, + 0x01, 0x41, 0x20, 0x31, + 0x01, 0xbf, 0x82, 0x30, + 0x01, 0x6a, 0x76, 0x00, + 0x00, 0xbb, 0x04, 0x46, + 0x01, 0x42, 0x20, 0x31, + 0x01, 0xbf, 0x84, 0x34, + 0x01, 0x41, 0x7e, 0x31, + 0x01, 0x90, 0x82, 0x34, + 0x01, 0x65, 0x22, 0x31, + 0xff, 0x6a, 0xd4, 0x08, + 0xff, 0x6a, 0xd4, 0x0c +}; + +static int ahc_patch23_func(struct ahc_softc *ahc); + +static int +ahc_patch23_func(struct ahc_softc *ahc) +{ + return ((ahc->bugs & AHC_SCBCHAN_UPLOAD_BUG) != 0); +} + +static int ahc_patch22_func(struct ahc_softc *ahc); + +static int +ahc_patch22_func(struct ahc_softc *ahc) +{ + return ((ahc->features & AHC_CMD_CHAN) == 0); +} + +static int ahc_patch21_func(struct ahc_softc *ahc); + +static int +ahc_patch21_func(struct ahc_softc *ahc) +{ + return ((ahc->features & AHC_QUEUE_REGS) == 0); +} + +static int ahc_patch20_func(struct ahc_softc *ahc); + +static int +ahc_patch20_func(struct ahc_softc *ahc) +{ + return ((ahc->features & AHC_WIDE) != 0); +} + +static int ahc_patch19_func(struct ahc_softc *ahc); + +static int +ahc_patch19_func(struct ahc_softc *ahc) +{ + return ((ahc->flags & AHC_SCB_BTT) != 0); +} + +static int ahc_patch18_func(struct ahc_softc *ahc); + +static int +ahc_patch18_func(struct ahc_softc *ahc) +{ + return ((ahc->bugs & AHC_PCI_2_1_RETRY_BUG) != 0); +} + +static int ahc_patch17_func(struct ahc_softc *ahc); + +static int +ahc_patch17_func(struct ahc_softc *ahc) +{ + return ((ahc->flags & AHC_TMODE_WIDEODD_BUG) != 0); +} + +static int ahc_patch16_func(struct ahc_softc *ahc); + +static int +ahc_patch16_func(struct ahc_softc *ahc) +{ + return ((ahc->bugs & AHC_AUTOFLUSH_BUG) != 0); +} + +static int ahc_patch15_func(struct ahc_softc *ahc); + +static int +ahc_patch15_func(struct ahc_softc *ahc) +{ + return ((ahc->features & AHC_ULTRA2) == 0); +} + +static int ahc_patch14_func(struct ahc_softc *ahc); + +static int +ahc_patch14_func(struct ahc_softc *ahc) +{ + return ((ahc->bugs & AHC_PCI_MWI_BUG) != 0 && ahc->pci_cachesize != 0); +} + +static int ahc_patch13_func(struct ahc_softc *ahc); + +static int +ahc_patch13_func(struct ahc_softc *ahc) +{ + return ((ahc->flags & AHC_39BIT_ADDRESSING) != 0); +} + +static int ahc_patch12_func(struct ahc_softc *ahc); + +static int +ahc_patch12_func(struct ahc_softc *ahc) +{ + return ((ahc->features & AHC_HS_MAILBOX) != 0); +} + +static int ahc_patch11_func(struct ahc_softc *ahc); + +static int +ahc_patch11_func(struct ahc_softc *ahc) +{ + return ((ahc->features & AHC_ULTRA) != 0); +} + +static int ahc_patch10_func(struct ahc_softc *ahc); + +static int +ahc_patch10_func(struct ahc_softc *ahc) +{ + return ((ahc->features & AHC_MULTI_TID) != 0); +} + +static int ahc_patch9_func(struct ahc_softc *ahc); + +static int +ahc_patch9_func(struct ahc_softc *ahc) +{ + return ((ahc->features & AHC_CMD_CHAN) != 0); +} + +static int ahc_patch8_func(struct ahc_softc *ahc); + +static int +ahc_patch8_func(struct ahc_softc *ahc) +{ + return ((ahc->flags & AHC_INITIATORROLE) != 0); +} + +static int ahc_patch7_func(struct ahc_softc *ahc); + +static int +ahc_patch7_func(struct ahc_softc *ahc) +{ + return ((ahc->flags & AHC_TARGETROLE) != 0); +} + +static int ahc_patch6_func(struct ahc_softc *ahc); + +static int +ahc_patch6_func(struct ahc_softc *ahc) +{ + return ((ahc->features & AHC_DT) == 0); +} + +static int ahc_patch5_func(struct ahc_softc *ahc); + +static int +ahc_patch5_func(struct ahc_softc *ahc) +{ + return ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0); +} + +static int ahc_patch4_func(struct ahc_softc *ahc); + +static int +ahc_patch4_func(struct ahc_softc *ahc) +{ + return ((ahc->flags & AHC_PAGESCBS) != 0); +} + +static int ahc_patch3_func(struct ahc_softc *ahc); + +static int +ahc_patch3_func(struct ahc_softc *ahc) +{ + return ((ahc->features & AHC_QUEUE_REGS) != 0); +} + +static int ahc_patch2_func(struct ahc_softc *ahc); + +static int +ahc_patch2_func(struct ahc_softc *ahc) +{ + return ((ahc->features & AHC_TWIN) != 0); +} + +static int ahc_patch1_func(struct ahc_softc *ahc); + +static int +ahc_patch1_func(struct ahc_softc *ahc) +{ + return ((ahc->features & AHC_ULTRA2) != 0); +} + +static int ahc_patch0_func(struct ahc_softc *ahc); + +static int +ahc_patch0_func(struct ahc_softc *ahc) +{ + return (0); +} + +typedef int patch_func_t (struct ahc_softc *); +struct patch { + patch_func_t *patch_func; + uint32_t begin :10, + skip_instr :10, + skip_patch :12; +} patches[] = { + { ahc_patch1_func, 4, 1, 1 }, + { ahc_patch2_func, 6, 2, 1 }, + { ahc_patch2_func, 9, 1, 1 }, + { ahc_patch3_func, 11, 1, 2 }, + { ahc_patch0_func, 12, 2, 1 }, + { ahc_patch4_func, 15, 1, 2 }, + { ahc_patch0_func, 16, 1, 1 }, + { ahc_patch5_func, 22, 2, 1 }, + { ahc_patch3_func, 27, 1, 2 }, + { ahc_patch0_func, 28, 1, 1 }, + { ahc_patch6_func, 34, 1, 1 }, + { ahc_patch7_func, 37, 54, 19 }, + { ahc_patch8_func, 37, 1, 1 }, + { ahc_patch9_func, 42, 3, 2 }, + { ahc_patch0_func, 45, 3, 1 }, + { ahc_patch10_func, 49, 1, 2 }, + { ahc_patch0_func, 50, 2, 3 }, + { ahc_patch1_func, 50, 1, 2 }, + { ahc_patch0_func, 51, 1, 1 }, + { ahc_patch2_func, 53, 2, 1 }, + { ahc_patch9_func, 55, 1, 2 }, + { ahc_patch0_func, 56, 1, 1 }, + { ahc_patch9_func, 60, 1, 2 }, + { ahc_patch0_func, 61, 1, 1 }, + { ahc_patch9_func, 71, 1, 2 }, + { ahc_patch0_func, 72, 1, 1 }, + { ahc_patch9_func, 75, 1, 2 }, + { ahc_patch0_func, 76, 1, 1 }, + { ahc_patch9_func, 79, 1, 2 }, + { ahc_patch0_func, 80, 1, 1 }, + { ahc_patch8_func, 91, 9, 4 }, + { ahc_patch1_func, 93, 1, 2 }, + { ahc_patch0_func, 94, 1, 1 }, + { ahc_patch2_func, 96, 2, 1 }, + { ahc_patch2_func, 105, 4, 1 }, + { ahc_patch1_func, 109, 1, 2 }, + { ahc_patch0_func, 110, 2, 3 }, + { ahc_patch2_func, 110, 1, 2 }, + { ahc_patch0_func, 111, 1, 1 }, + { ahc_patch7_func, 112, 4, 2 }, + { ahc_patch0_func, 116, 1, 1 }, + { ahc_patch11_func, 118, 2, 1 }, + { ahc_patch1_func, 120, 1, 2 }, + { ahc_patch0_func, 121, 1, 1 }, + { ahc_patch7_func, 122, 4, 1 }, + { ahc_patch7_func, 133, 89, 11 }, + { ahc_patch4_func, 151, 1, 1 }, + { ahc_patch1_func, 164, 1, 1 }, + { ahc_patch12_func, 169, 1, 2 }, + { ahc_patch0_func, 170, 1, 1 }, + { ahc_patch9_func, 181, 1, 2 }, + { ahc_patch0_func, 182, 1, 1 }, + { ahc_patch9_func, 191, 1, 2 }, + { ahc_patch0_func, 192, 1, 1 }, + { ahc_patch9_func, 208, 6, 2 }, + { ahc_patch0_func, 214, 6, 1 }, + { ahc_patch8_func, 222, 18, 2 }, + { ahc_patch1_func, 235, 1, 1 }, + { ahc_patch1_func, 242, 1, 2 }, + { ahc_patch0_func, 243, 2, 2 }, + { ahc_patch11_func, 244, 1, 1 }, + { ahc_patch9_func, 252, 31, 3 }, + { ahc_patch1_func, 268, 14, 2 }, + { ahc_patch13_func, 273, 1, 1 }, + { ahc_patch14_func, 283, 14, 1 }, + { ahc_patch1_func, 299, 1, 2 }, + { ahc_patch0_func, 300, 1, 1 }, + { ahc_patch9_func, 303, 1, 1 }, + { ahc_patch13_func, 308, 1, 1 }, + { ahc_patch9_func, 309, 2, 2 }, + { ahc_patch0_func, 311, 4, 1 }, + { ahc_patch14_func, 315, 1, 1 }, + { ahc_patch15_func, 318, 2, 3 }, + { ahc_patch9_func, 318, 1, 2 }, + { ahc_patch0_func, 319, 1, 1 }, + { ahc_patch6_func, 324, 1, 2 }, + { ahc_patch0_func, 325, 1, 1 }, + { ahc_patch1_func, 329, 50, 11 }, + { ahc_patch6_func, 338, 2, 4 }, + { ahc_patch7_func, 338, 1, 1 }, + { ahc_patch8_func, 339, 1, 1 }, + { ahc_patch0_func, 340, 1, 1 }, + { ahc_patch16_func, 341, 1, 1 }, + { ahc_patch6_func, 360, 6, 3 }, + { ahc_patch16_func, 360, 5, 1 }, + { ahc_patch0_func, 366, 5, 1 }, + { ahc_patch13_func, 374, 5, 1 }, + { ahc_patch0_func, 379, 54, 17 }, + { ahc_patch14_func, 379, 1, 1 }, + { ahc_patch7_func, 381, 2, 2 }, + { ahc_patch17_func, 382, 1, 1 }, + { ahc_patch9_func, 385, 1, 1 }, + { ahc_patch18_func, 392, 1, 1 }, + { ahc_patch14_func, 397, 9, 3 }, + { ahc_patch9_func, 398, 3, 2 }, + { ahc_patch0_func, 401, 3, 1 }, + { ahc_patch9_func, 409, 6, 2 }, + { ahc_patch0_func, 415, 9, 2 }, + { ahc_patch13_func, 415, 1, 1 }, + { ahc_patch13_func, 424, 2, 1 }, + { ahc_patch14_func, 426, 1, 1 }, + { ahc_patch9_func, 428, 1, 2 }, + { ahc_patch0_func, 429, 1, 1 }, + { ahc_patch7_func, 432, 1, 1 }, + { ahc_patch7_func, 433, 1, 1 }, + { ahc_patch8_func, 434, 3, 3 }, + { ahc_patch6_func, 435, 1, 2 }, + { ahc_patch0_func, 436, 1, 1 }, + { ahc_patch9_func, 437, 1, 1 }, + { ahc_patch15_func, 438, 1, 2 }, + { ahc_patch13_func, 438, 1, 1 }, + { ahc_patch14_func, 440, 9, 4 }, + { ahc_patch9_func, 440, 1, 1 }, + { ahc_patch9_func, 447, 2, 1 }, + { ahc_patch0_func, 449, 4, 3 }, + { ahc_patch9_func, 449, 1, 2 }, + { ahc_patch0_func, 450, 3, 1 }, + { ahc_patch1_func, 454, 2, 1 }, + { ahc_patch7_func, 456, 10, 2 }, + { ahc_patch0_func, 466, 1, 1 }, + { ahc_patch8_func, 467, 109, 23 }, + { ahc_patch1_func, 469, 3, 2 }, + { ahc_patch0_func, 472, 5, 3 }, + { ahc_patch9_func, 472, 2, 2 }, + { ahc_patch0_func, 474, 3, 1 }, + { ahc_patch1_func, 479, 2, 2 }, + { ahc_patch0_func, 481, 6, 3 }, + { ahc_patch9_func, 481, 2, 2 }, + { ahc_patch0_func, 483, 3, 1 }, + { ahc_patch1_func, 489, 2, 2 }, + { ahc_patch0_func, 491, 9, 7 }, + { ahc_patch9_func, 491, 5, 6 }, + { ahc_patch19_func, 491, 1, 2 }, + { ahc_patch0_func, 492, 1, 1 }, + { ahc_patch19_func, 494, 1, 2 }, + { ahc_patch0_func, 495, 1, 1 }, + { ahc_patch0_func, 496, 4, 1 }, + { ahc_patch6_func, 500, 3, 2 }, + { ahc_patch0_func, 503, 1, 1 }, + { ahc_patch1_func, 506, 1, 1 }, + { ahc_patch6_func, 512, 1, 2 }, + { ahc_patch0_func, 513, 1, 1 }, + { ahc_patch20_func, 550, 7, 1 }, + { ahc_patch3_func, 578, 1, 2 }, + { ahc_patch0_func, 579, 1, 1 }, + { ahc_patch21_func, 582, 1, 1 }, + { ahc_patch8_func, 584, 104, 33 }, + { ahc_patch4_func, 585, 1, 1 }, + { ahc_patch1_func, 591, 2, 2 }, + { ahc_patch0_func, 593, 1, 1 }, + { ahc_patch1_func, 596, 1, 2 }, + { ahc_patch0_func, 597, 1, 1 }, + { ahc_patch9_func, 598, 3, 3 }, + { ahc_patch15_func, 599, 1, 1 }, + { ahc_patch0_func, 601, 4, 1 }, + { ahc_patch19_func, 609, 2, 2 }, + { ahc_patch0_func, 611, 1, 1 }, + { ahc_patch19_func, 615, 10, 3 }, + { ahc_patch5_func, 617, 8, 1 }, + { ahc_patch0_func, 625, 9, 2 }, + { ahc_patch5_func, 626, 8, 1 }, + { ahc_patch4_func, 636, 1, 2 }, + { ahc_patch0_func, 637, 1, 1 }, + { ahc_patch19_func, 638, 1, 2 }, + { ahc_patch0_func, 639, 3, 2 }, + { ahc_patch4_func, 641, 1, 1 }, + { ahc_patch5_func, 642, 1, 1 }, + { ahc_patch5_func, 645, 1, 1 }, + { ahc_patch5_func, 647, 1, 1 }, + { ahc_patch4_func, 649, 2, 2 }, + { ahc_patch0_func, 651, 2, 1 }, + { ahc_patch5_func, 653, 1, 1 }, + { ahc_patch5_func, 656, 1, 1 }, + { ahc_patch5_func, 659, 1, 1 }, + { ahc_patch19_func, 663, 1, 1 }, + { ahc_patch19_func, 666, 1, 1 }, + { ahc_patch4_func, 672, 1, 1 }, + { ahc_patch6_func, 675, 1, 2 }, + { ahc_patch0_func, 676, 1, 1 }, + { ahc_patch7_func, 688, 16, 1 }, + { ahc_patch4_func, 704, 20, 1 }, + { ahc_patch9_func, 725, 4, 2 }, + { ahc_patch0_func, 729, 4, 1 }, + { ahc_patch9_func, 733, 4, 2 }, + { ahc_patch0_func, 737, 3, 1 }, + { ahc_patch6_func, 743, 1, 1 }, + { ahc_patch22_func, 745, 14, 1 }, + { ahc_patch7_func, 759, 3, 1 }, + { ahc_patch9_func, 771, 24, 8 }, + { ahc_patch19_func, 775, 1, 2 }, + { ahc_patch0_func, 776, 1, 1 }, + { ahc_patch15_func, 781, 4, 2 }, + { ahc_patch0_func, 785, 7, 3 }, + { ahc_patch23_func, 785, 5, 2 }, + { ahc_patch0_func, 790, 2, 1 }, + { ahc_patch0_func, 795, 42, 3 }, + { ahc_patch18_func, 807, 18, 2 }, + { ahc_patch0_func, 825, 1, 1 }, + { ahc_patch4_func, 849, 1, 1 }, + { ahc_patch4_func, 850, 3, 2 }, + { ahc_patch0_func, 853, 1, 1 }, + { ahc_patch13_func, 854, 3, 1 }, + { ahc_patch4_func, 857, 12, 1 } +}; +struct cs { + u_int16_t begin; + u_int16_t end; +} critical_sections[] = { + { 11, 18 }, + { 21, 30 }, + { 704, 720 }, + { 850, 853 }, + { 857, 863 }, + { 865, 867 }, + { 867, 869 } +}; +const int num_critical_sections = sizeof(critical_sections) + / sizeof(*critical_sections); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/scsi/dpt_i2o.c linux.2.5.47-ac4/drivers/scsi/dpt_i2o.c --- linux.2.5.47/drivers/scsi/dpt_i2o.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/scsi/dpt_i2o.c 2002-10-31 17:49:27.000000000 +0000 @@ -1033,10 +1033,10 @@ kfree(pHba->lct); } if(pHba->status_block) { - kfree(pHba->status_block); + pci_free_consistent(pHba->pDev, sizeof(struct i2o_status_block), pHba->status_block, pHba->status_block_dma); } if(pHba->reply_pool){ - kfree(pHba->reply_pool); + pci_free_consistent(pHba->pDev, pHba->reply_pool_size, pHba->reply_pool, pHba->reply_pool_dma); } for(d = pHba->devices; d ; d = next){ @@ -2106,18 +2106,19 @@ } // msg[0] is set later // I2O_CMD_SCSI_EXEC - msg[1] = ((0xff<<24)|(HOST_TID<<12)|d->tid); + msg[1] = cpu_to_le32((0xff<<24)|(HOST_TID<<12)|d->tid); msg[2] = 0; - msg[3] = (u32)cmd; /* We want the SCSI control block back */ + // FIXME: Broken for 64bit !! + msg[3] = cpu_to_le32((u32)cmd); /* We want the SCSI control block back */ // Our cards use the transaction context as the tag for queueing // Adaptec/DPT Private stuff - msg[4] = I2O_CMD_SCSI_EXEC|(DPT_ORGANIZATION_ID<<16); - msg[5] = d->tid; + msg[4] = cpu_to_le32(I2O_CMD_SCSI_EXEC|(DPT_ORGANIZATION_ID<<16)); + msg[5] = cpu_to_le32(d->tid); /* Direction, disconnect ok | sense data | simple queue , CDBLen */ // I2O_SCB_FLAG_ENABLE_DISCONNECT | // I2O_SCB_FLAG_SIMPLE_QUEUE_TAG | // I2O_SCB_FLAG_SENSE_DATA_IN_MESSAGE; - msg[6] = scsidir|0x20a00000|cmd->cmd_len; + msg[6] = cpu_to_le32(scsidir|0x20a00000|cmd->cmd_len); mptr=msg+7; @@ -2130,15 +2131,21 @@ /* Now fill in the SGList and command */ if(cmd->use_sg) { struct scatterlist *sg = (struct scatterlist *)cmd->request_buffer; + int sg_count = pci_map_sg(pHba->pDev, sg, Cmnd->use_sg, + scsi_to_pci_dma_dir(Cmnd->sc_data_direction)); + + if(sg_count == 0) + return -ENOMEM; + len = 0; - for(i = 0 ; i < cmd->use_sg; i++) { - *mptr++ = direction|0x10000000|sg->length; - len+=sg->length; - *mptr++ = virt_to_bus(sg->address); + for(i = 0 ; i < sg_count; i++) { + *mptr++ = cpu_to_le32(direction|0x10000000|sg_dma_length(sg)); + len+= cpu_to_le32(sg_dma_length(sg)); + *mptr++ = sg_dmap_address(sg); sg++; } /* Make this an end of list */ - mptr[-2] = direction|0xD0000000|(sg-1)->length; + mptr[-2] = cpu_to_le32(direction|0xD0000000|sg_dma_length(sg-1)); reqlen = mptr - msg; *lenptr = len; @@ -2147,24 +2154,29 @@ len, cmd->underflow); } } else { + dma_addr_t dma_addr = pci_map_single(pHba->pDev, + Cmnd->request_buffer, + Cmnd->request_bufflen, + scsi_to_pci_dma_dir(Cmnd->sc_data_direction)); + + if(dma_addr == 0) + return -ENOMEM; + + Cmnd->SCp.ptr = (char *)(unsigned long) dma_addr; *lenptr = len = cmd->request_bufflen; if(len == 0) { reqlen = 12; } else { - *mptr++ = 0xD0000000|direction|cmd->request_bufflen; - *mptr++ = virt_to_bus(cmd->request_buffer); + *mptr++ = cpu_to_le32(0xD0000000|direction|cmd->request_bufflen); + *mptr++ = cpu_to_le32(dma_addr); } } /* Stick the headers on */ - msg[0] = reqlen<<16 | ((reqlen > 12) ? SGL_OFFSET_12 : SGL_OFFSET_0); + msg[0] = cpu_to_le32(reqlen<<16 | ((reqlen > 12) ? SGL_OFFSET_12 : SGL_OFFSET_0)); // Send it on it's way - rcode = adpt_i2o_post_this(pHba, msg, reqlen<<2); - if (rcode == 0) { - return 0; - } - return rcode; + return adpt_i2o_post_this(pHba, msg, reqlen<<2); } @@ -2204,19 +2216,31 @@ adpt_hba* pHba; u32 hba_status; u32 dev_status; - u32 reply_flags = readl(reply) & 0xff00; // Leave it shifted up 8 bits + u32 reply_flags = le32_to_cpu(readl(reply)) & 0xff00; // Leave it shifted up 8 bits // I know this would look cleaner if I just read bytes // but the model I have been using for all the rest of the // io is in 4 byte words - so I keep that model - u16 detailed_status = readl(reply+16) &0xffff; + u16 detailed_status = le32_to_cpu(readl(reply+16)) &0xffff; dev_status = (detailed_status & 0xff); hba_status = detailed_status >> 8; // calculate resid for sg - cmd->resid = cmd->request_bufflen - readl(reply+5); + cmd->resid = cmd->request_bufflen - le32_to_cpu(readl(reply+5)); pHba = (adpt_hba*) cmd->host->hostdata[0]; + if (cmd->use_sg) + pci_unmap_sg(pHba->pDev, + (struct scatterlist *)cmd->buffer, + cmd->use_sg, + scsi_to_pci_dma_dir(cmd->sc_data_direction)); + else if (Cmnd->request_bufflen) + pci_unmap_single(pHba->pDev, + (dma_addr_t)((long)cmd->SCp.ptr), + cmd->request_bufflen, + scsi_to_pci_dma_dir(cmd->sc_data_direction)); + + cmd->sense_buffer[0] = '\0'; // initialize sense valid flag to false if(!(reply_flags & MSG_FAIL)) { @@ -2224,7 +2248,7 @@ case I2O_SCSI_DSC_SUCCESS: cmd->result = (DID_OK << 16); // handle underflow - if(readl(reply+5) < cmd->underflow ) { + if(le32_to_cpu(readl(reply+5)) < cmd->underflow ) { cmd->result = (DID_ERROR <<16); printk(KERN_WARNING"%s: SCSI CMD underflow\n",pHba->name); } @@ -2646,6 +2670,7 @@ u32* ptr; u32 outbound_frame; // This had to be a 32 bit address u32 m; + dma_addr_t statdma; do { rmb(); @@ -2662,25 +2687,24 @@ msg=(u32 *)(pHba->msg_addr_virt+m); - status = kmalloc(4,GFP_KERNEL|ADDR32); + status = pci_alloc_consistent(pHba->pDev, 4, &statdma); if (status==NULL) { adpt_send_nop(pHba, m); - printk(KERN_WARNING"%s: IOP reset failed - no free memory.\n", - pHba->name); + printk(KERN_WARNING"%s: IOP reset failed - no free memory.\n", pHba->name); return -ENOMEM; } memset(status, 0, 4); - writel(EIGHT_WORD_MSG_SIZE| SGL_OFFSET_6, &msg[0]); - writel(I2O_CMD_OUTBOUND_INIT<<24 | HOST_TID<<12 | ADAPTER_TID, &msg[1]); + writel(cpu_to_le32(EIGHT_WORD_MSG_SIZE| SGL_OFFSET_6), &msg[0]); + writel(cpu_to_le32(I2O_CMD_OUTBOUND_INIT<<24 | HOST_TID<<12 | ADAPTER_TID), &msg[1]); writel(0, &msg[2]); - writel(0x0106, &msg[3]); /* Transaction context */ - writel(4096, &msg[4]); /* Host page frame size */ - writel((REPLY_FRAME_SIZE)<<16|0x80, &msg[5]); /* Outbound msg frame size and Initcode */ - writel(0xD0000004, &msg[6]); /* Simple SG LE, EOB */ - writel(virt_to_bus(status), &msg[7]); + writel(cpu_to_le32(0x0106), &msg[3]); /* Transaction context */ + writel(cpu_to_le32(4096), &msg[4]); /* Host page frame size */ + writel(cpu_to_le32((REPLY_FRAME_SIZE)<<16|0x80), &msg[5]); /* Outbound msg frame size and Initcode */ + writel(cpu_to_le32(0xD0000004), &msg[6]); /* Simple SG LE, EOB */ + writel(cpu_to_le32(statdma), &msg[7]); - writel(m, pHba->post_port); + writel(cpu_to_le32(m), pHba->post_port); wmb(); // Wait for the reply status to come back @@ -2701,16 +2725,17 @@ // If the command was successful, fill the fifo with our reply // message packets if(*status != 0x04 /*I2O_EXEC_OUTBOUND_INIT_COMPLETE*/) { - kfree((void*)status); + pci_free_consistent(pHba->pDev, 4, status, statdma); return -2; } - kfree((void*)status); + pci_free_consistent(pHba->pDev, 4, status, statdma); if(pHba->reply_pool != NULL){ - kfree(pHba->reply_pool); + pci_free_consistent(pHba->pDev, pHba->reply_pool_size, pHba->reply_pool, pHba->reply_pool_dma); } - pHba->reply_pool = (u32*)kmalloc(pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4, GFP_KERNEL|ADDR32); + pHba->reply_pool_size = pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4 + pHba->reply_pool = (u32*)pci_alloc_consistent(pHba->pDev, pHba->reply_pool_size , &pHba->reply_pool_dma); if(!pHba->reply_pool){ printk(KERN_ERR"%s: Could not allocate reply pool\n",pHba->name); return -1; @@ -2718,11 +2743,12 @@ memset(pHba->reply_pool, 0 , pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4); ptr = pHba->reply_pool; + dma = pHba->reply_pool_dma; for(i = 0; i < pHba->reply_fifo_size; i++) { - outbound_frame = (u32)virt_to_bus(ptr); - writel(outbound_frame, pHba->reply_port); + writel(cpu_to_le32(dma), pHba->reply_port); wmb(); ptr += REPLY_FRAME_SIZE; + dma += REPLY_FRAME_SIZE; } adpt_i2o_status_get(pHba); return 0; @@ -2738,39 +2764,32 @@ * used by IOPs to track changes. */ - - static s32 adpt_i2o_status_get(adpt_hba* pHba) { ulong timeout; u32 m; u32 *msg; u8 *status_block=NULL; - ulong status_block_bus; if(pHba->status_block == NULL) { - pHba->status_block = (i2o_status_block*) - kmalloc(sizeof(i2o_status_block),GFP_KERNEL|ADDR32); + pHba->status_block = (i2o_status_block*) pci_alloc_consistent(pHba->pDev, (sizeof(i2o_status_block), &pHba->status_block_dma); if(pHba->status_block == NULL) { - printk(KERN_ERR - "dpti%d: Get Status Block failed; Out of memory. \n", - pHba->unit); + printk(KERN_ERR "dpti%d: Get Status Block failed; Out of memory. \n", pHba->unit); return -ENOMEM; } } memset(pHba->status_block, 0, sizeof(i2o_status_block)); status_block = (u8*)(pHba->status_block); - status_block_bus = virt_to_bus(pHba->status_block); + timeout = jiffies+TMOUT_GETSTATUS*HZ; do { rmb(); - m = readl(pHba->post_port); + m = cpu_to_le32(readl(pHba->post_port)); if (m != EMPTY_QUEUE) { break; } if(time_after(jiffies,timeout)){ - printk(KERN_ERR "%s: Timeout waiting for message !\n", - pHba->name); + printk(KERN_ERR "%s: Timeout waiting for message !\n", pHba->name); return -ETIMEDOUT; } } while(m==EMPTY_QUEUE); @@ -2778,24 +2797,23 @@ msg=(u32*)(pHba->msg_addr_virt+m); - writel(NINE_WORD_MSG_SIZE|SGL_OFFSET_0, &msg[0]); - writel(I2O_CMD_STATUS_GET<<24|HOST_TID<<12|ADAPTER_TID, &msg[1]); + writel(cpu_to_le32(NINE_WORD_MSG_SIZE|SGL_OFFSET_0), &msg[0]); + writel(cpu_to_le32(I2O_CMD_STATUS_GET<<24|HOST_TID<<12|ADAPTER_TID), &msg[1]); writel(1, &msg[2]); writel(0, &msg[3]); writel(0, &msg[4]); writel(0, &msg[5]); - writel(((u32)status_block_bus)&0xffffffff, &msg[6]); + writel(cpu_to_le32(pHba->status_block_dma), &msg[6]); writel(0, &msg[7]); - writel(sizeof(i2o_status_block), &msg[8]); // 88 bytes + writel(cpu_to_le32(sizeof(i2o_status_block)), &msg[8]); // 88 bytes //post message - writel(m, pHba->post_port); + writel(cpu_to_le32(m), pHba->post_port); wmb(); while(status_block[87]!=0xff){ if(time_after(jiffies,timeout)){ - printk(KERN_ERR"dpti%d: Get status timeout.\n", - pHba->unit); + printk(KERN_ERR"dpti%d: Get status timeout.\n", pHba->unit); return -ETIMEDOUT; } rmb(); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/scsi/dpti.h linux.2.5.47-ac4/drivers/scsi/dpti.h --- linux.2.5.47/drivers/scsi/dpti.h 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/scsi/dpti.h 2002-10-31 17:49:39.000000000 +0000 @@ -282,12 +282,15 @@ u32 post_fifo_size; u32 reply_fifo_size; u32* reply_pool; + dma_addr_t reply_pool_dma; + u32 reply_pool_size; u32 sg_tablesize; // Scatter/Gather List Size. u8 top_scsi_channel; u8 top_scsi_id; u8 top_scsi_lun; i2o_status_block* status_block; + dma_addr_t status_block_dma; i2o_hrt* hrt; i2o_lct* lct; uint lct_size; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/scsi/i60uscsi.c linux.2.5.47-ac4/drivers/scsi/i60uscsi.c --- linux.2.5.47/drivers/scsi/i60uscsi.c 2002-10-31 14:57:11.000000000 +0000 +++ linux.2.5.47-ac4/drivers/scsi/i60uscsi.c 2002-11-03 01:14:17.000000000 +0000 @@ -566,10 +566,10 @@ ORC_WR(pHCB->HCS_Base + ORC_HCTRL, SCSIRST); if (waitSCSIRSTdone(pHCB) == FALSE) { spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags); - return (SCSI_RESET_ERROR); + return FAILED; } else { spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags); - return (SCSI_RESET_SUCCESS); + return SUCCESS; } } @@ -581,7 +581,7 @@ Output : None. Return : pSRB - Pointer to SCSI request block. *****************************************************************************/ -int orc_device_reset(ORC_HCS * pHCB, Scsi_Cmnd *SCpnt, unsigned int target, unsigned int ResetFlags) +int orc_device_reset(ORC_HCS * pHCB, Scsi_Cmnd *SCpnt, unsigned int target) { /* I need Host Control Block Information */ ORC_SCB *pScb; ESCB *pVirEscb; @@ -608,11 +608,11 @@ if (i == ORC_MAXQUEUE) { printk("Unable to Reset - No SCB Found\n"); spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags); - return (SCSI_RESET_NOT_RUNNING); + return FAILED; } if ((pScb = orc_alloc_scb(pHCB)) == NULL) { spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags); - return (SCSI_RESET_NOT_RUNNING); + return FAILED; } pScb->SCB_Opcode = ORC_BUSDEVRST; pScb->SCB_Target = target; @@ -626,12 +626,10 @@ pScb->SCB_SGLen = 0; pVirEscb->SCB_Srb = 0; - if (ResetFlags & SCSI_RESET_SYNCHRONOUS) { - pVirEscb->SCB_Srb = SCpnt; - } + pVirEscb->SCB_Srb = SCpnt; orc_exec_scb(pHCB, pScb); /* Start execute SCB */ spin_unlock_irqrestore(&(pHCB->BitAllocFlagLock), flags); - return SCSI_RESET_PENDING; + return SUCCESS; } @@ -838,21 +836,21 @@ if ((pVirScb->SCB_Status) && (pVirEscb->SCB_Srb == SCpnt)) { if (pVirScb->SCB_TagMsg == 0) { spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags); - return (SCSI_ABORT_BUSY); + return FAILED; } else { if (abort_SCB(hcsp, pVirScb)) { pVirEscb->SCB_Srb = NULL; spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags); - return (SCSI_ABORT_SUCCESS); + return SUCCESS; } else { spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags); - return (SCSI_ABORT_NOT_RUNNING); + return FAILED; } } } } spin_unlock_irqrestore(&(hcsp->BitAllocFlagLock), flags); - return (SCSI_ABORT_NOT_RUNNING); + return FAILED; } /*********************************************************************** diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/scsi/inia100.c linux.2.5.47-ac4/drivers/scsi/inia100.c --- linux.2.5.47/drivers/scsi/inia100.c 2002-11-03 01:15:47.000000000 +0000 +++ linux.2.5.47-ac4/drivers/scsi/inia100.c 2002-11-03 01:17:58.000000000 +0000 @@ -123,7 +123,7 @@ extern void orc_release_scb(ORC_HCS * hcsp, ORC_SCB * scbp); extern void orc_release_dma(ORC_HCS * hcsp, Scsi_Cmnd * cmnd); extern void orc_interrupt(ORC_HCS * hcsp); -extern int orc_device_reset(ORC_HCS * pHCB, Scsi_Cmnd *SCpnt, unsigned int target, unsigned int ResetFlags); +extern int orc_device_reset(ORC_HCS * pHCB, Scsi_Cmnd *SCpnt, unsigned int target); extern int orc_reset_scsi_bus(ORC_HCS * pHCB); extern int abort_SCB(ORC_HCS * hcsp, ORC_SCB * pScb); extern int orc_abort_srb(ORC_HCS * hcsp, Scsi_Cmnd *SCpnt); @@ -511,7 +511,7 @@ Output : None. Return : pSRB - Pointer to SCSI request block. *****************************************************************************/ -int inia100_queue(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *)) +static int inia100_queue(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *)) { register ORC_SCB *pSCB; ORC_HCS *pHCB; /* Point to Host adapter control block */ @@ -538,7 +538,7 @@ Output : None. Return : pSRB - Pointer to SCSI request block. *****************************************************************************/ -int inia100_abort(Scsi_Cmnd * SCpnt) +static int inia100_abort(Scsi_Cmnd * SCpnt) { ORC_HCS *hcsp; @@ -554,15 +554,25 @@ Output : None. Return : pSRB - Pointer to SCSI request block. *****************************************************************************/ -int inia100_reset(Scsi_Cmnd * SCpnt, unsigned int reset_flags) +static int inia100_bus_reset(Scsi_Cmnd * SCpnt) { /* I need Host Control Block Information */ ORC_HCS *pHCB; pHCB = (ORC_HCS *) SCpnt->host->hostdata; + return orc_reset_scsi_bus(pHCB); +} - if (reset_flags & (SCSI_RESET_SUGGEST_BUS_RESET | SCSI_RESET_SUGGEST_HOST_RESET)) - return orc_reset_scsi_bus(pHCB); - else - return orc_device_reset(pHCB, SCpnt, SCpnt->target, reset_flags); +/***************************************************************************** + Function name : inia100_device_reset + Description : Reset the device + Input : pHCB - Pointer to host adapter structure + Output : None. + Return : pSRB - Pointer to SCSI request block. +*****************************************************************************/ +static int inia100_device_reset(Scsi_Cmnd * SCpnt) +{ /* I need Host Control Block Information */ + ORC_HCS *pHCB; + pHCB = (ORC_HCS *) SCpnt->host->hostdata; + return orc_device_reset(pHCB, SCpnt, SCpnt->target); } @@ -645,41 +655,6 @@ return; } -/***************************************************************************** - Function name : inia100_biosparam - Description : Return the "logical geometry" - Input : pHCB - Pointer to host adapter structure - Output : None. - Return : pSRB - Pointer to SCSI request block. -*****************************************************************************/ -int inia100_biosparam(struct scsi_device *sdev, struct block_device *bdev, - sector_t capacity, int *info_array) -{ - ORC_HCS *pHcb; /* Point to Host adapter control block */ - ORC_TCS *pTcb; - - pHcb = (ORC_HCS *) sdev->host->hostdata; - pTcb = &pHcb->HCS_Tcs[sdev->id]; - - if (pTcb->TCS_DrvHead) { - info_array[0] = pTcb->TCS_DrvHead; - info_array[1] = pTcb->TCS_DrvSector; - info_array[2] = (unsigned long)capacity / pTcb->TCS_DrvHead / pTcb->TCS_DrvSector; - } else { - if (pTcb->TCS_DrvFlags & TCF_DRV_255_63) { - info_array[0] = 255; - info_array[1] = 63; - info_array[2] = (unsigned long)capacity / 255 / 63; - } else { - info_array[0] = 64; - info_array[1] = 32; - info_array[2] = capacity >> 11; - } - } - return 0; -} - - /* * Interrupt handler (main routine of the driver) */ @@ -707,7 +682,7 @@ /* * Release ressources */ -int inia100_release(struct Scsi_Host *hreg) +static int inia100_release(struct Scsi_Host *hreg) { ORC_HCS *pHCB = (ORC_HCS *)hreg->hostdata; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/scsi/inia100.h linux.2.5.47-ac4/drivers/scsi/inia100.h --- linux.2.5.47/drivers/scsi/inia100.h 2002-11-05 13:54:44.000000000 +0000 +++ linux.2.5.47-ac4/drivers/scsi/inia100.h 2002-11-05 14:24:54.000000000 +0000 @@ -75,14 +75,12 @@ #include #include -extern int inia100_detect(Scsi_Host_Template *); -extern int inia100_release(struct Scsi_Host *); -extern int inia100_queue(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *)); -extern int inia100_abort(Scsi_Cmnd *); -extern int inia100_reset(Scsi_Cmnd *, unsigned int); - -extern int inia100_biosparam(struct scsi_device *, struct block_device *, - sector_t, int *); +static int inia100_detect(Scsi_Host_Template *); +static int inia100_release(struct Scsi_Host *); +static int inia100_queue(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *)); +static int inia100_abort(Scsi_Cmnd *); +static int inia100_device_reset(Scsi_Cmnd *); +static int inia100_bus_reset(Scsi_Cmnd *); #define inia100_REVID "Initio INI-A100U2W SCSI device driver; Revision: 1.02d" @@ -92,8 +90,9 @@ detect: inia100_detect, \ release: inia100_release, \ queuecommand: inia100_queue, \ - abort: inia100_abort, \ - reset: inia100_reset, \ + eh_abort_handler:inia100_abort, \ + eh_bus_reset_handler: inia100_bus_reset, \ + eh_device_reset_handler:inia100_device_reset, \ can_queue: 1, \ this_id: 1, \ sg_tablesize: SG_ALL, \ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/scsi/ips.c linux.2.5.47-ac4/drivers/scsi/ips.c --- linux.2.5.47/drivers/scsi/ips.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.47-ac4/drivers/scsi/ips.c 2002-11-11 20:20:52.000000000 +0000 @@ -856,7 +856,7 @@ ips_name, ips_next_controller, mem_addr, mem_len); #if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0) - if (check_mem_region(mem_addr, mem_len)) { + if (!request_mem_region(mem_addr, mem_len, "ips")) { /* Couldn't allocate io space */ printk(KERN_WARNING "(%s%d) couldn't allocate IO space %x len %d.\n", ips_name, ips_next_controller, io_addr, io_len); @@ -866,7 +866,6 @@ continue; } - request_mem_region(mem_addr, mem_len, "ips"); #endif base = mem_addr & PAGE_MASK; @@ -884,7 +883,7 @@ DEBUG_VAR(1, "(%s%d) detect, IO region %x, size: %d", ips_name, ips_next_controller, io_addr, io_len); - if (check_region(io_addr, io_len)) { + if (!request_region(io_addr, io_len, "ips")) { /* Couldn't allocate io space */ printk(KERN_WARNING "(%s%d) couldn't allocate IO space %x len %d.\n", ips_name, ips_next_controller, io_addr, io_len); @@ -894,7 +893,6 @@ continue; } - request_region(io_addr, io_len, "ips"); } /* get planer status */ @@ -7329,12 +7327,11 @@ uint32_t base; uint32_t offs; - if (check_mem_region(mem_addr, mem_len)) { + if (!request_mem_region(mem_addr, mem_len, "ips")) { printk(KERN_WARNING "Couldn't allocate IO Memory space %x len %d.\n", mem_addr, mem_len); return -1; } - request_mem_region(mem_addr, mem_len, "ips"); base = mem_addr & PAGE_MASK; offs = mem_addr - base; ioremap_ptr = ioremap(base, PAGE_SIZE); @@ -7346,11 +7343,10 @@ /* setup I/O mapped area (if applicable) */ if (io_addr) { - if (check_region(io_addr, io_len)) { + if (!request_region(io_addr, io_len, "ips")) { printk(KERN_WARNING "Couldn't allocate IO space %x len %d.\n", io_addr, io_len); return -1; } - request_region(io_addr, io_len, "ips"); } /* get the revision ID */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/scsi/megaraid.c linux.2.5.47-ac4/drivers/scsi/megaraid.c --- linux.2.5.47/drivers/scsi/megaraid.c 2002-11-11 16:39:10.000000000 +0000 +++ linux.2.5.47-ac4/drivers/scsi/megaraid.c 2002-11-12 15:34:26.000000000 +0000 @@ -494,27 +494,18 @@ #include #include #include +#include #include #include #include #include /* for kmalloc() */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0) /* 0x20100 */ -#include -#else -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) /* 0x20300 */ -#include -#else #include -#endif -#endif #include #include -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,0,24) /* 0x020024 */ #include -#endif /* * These header files are required for Shutdown Notification routines @@ -557,17 +548,6 @@ writel (value, megaCfg->base + 0x2C); } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) /* 0x020200 */ -#include -#define cpuid smp_processor_id() -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,4) -#define scsi_set_pci_device(x,y) -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) /* 0x020400 */ - /* * Linux 2.4 and higher * @@ -580,122 +560,6 @@ MODULE_DESCRIPTION ("LSI Logic MegaRAID driver"); MODULE_LICENSE ("GPL"); -#define DRIVER_LOCK_T -#define DRIVER_LOCK_INIT(p) -#define DRIVER_LOCK(p) -#define DRIVER_UNLOCK(p) -#define IO_LOCK_T unsigned long io_flags = 0 -#define IO_LOCK(host) spin_lock_irqsave(host->host_lock,io_flags) -#define IO_UNLOCK(host) spin_unlock_irqrestore(host->host_lock,io_flags) -#define IO_LOCK_IRQ(host) spin_lock_irq(host->host_lock) -#define IO_UNLOCK_IRQ(host) spin_unlock_irq(host->host_lock) - -#define queue_task_irq(a,b) queue_task(a,b) -#define queue_task_irq_off(a,b) queue_task(a,b) - -#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) /* 0x020200 */ - -/* - * Linux 2.2 and higher - * - * No driver private lock - * Use the io_request_lock not cli/sti - * No pci region api - * queue_task is now a single simple API - */ - -static char kernel_version[] = UTS_RELEASE; -MODULE_AUTHOR ("LSI Logic Corporation"); -MODULE_DESCRIPTION ("LSI Logic MegaRAID driver"); - -#define DRIVER_LOCK_T -#define DRIVER_LOCK_INIT(p) -#define DRIVER_LOCK(p) -#define DRIVER_UNLOCK(p) -#define IO_LOCK_T unsigned long io_flags = 0 -#define IO_LOCK(host) spin_lock_irqsave(host->host_lock,io_flags); -#define IO_UNLOCK(host) spin_unlock_irqrestore(host->host_lock,io_flags); - -#define pci_free_consistent(a,b,c,d) -#define pci_unmap_single(a,b,c,d) -#define pci_enable_device(x) (0) -#define queue_task_irq(a,b) queue_task(a,b) -#define queue_task_irq_off(a,b) queue_task(a,b) - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,19) /* 0x020219 */ -#define init_MUTEX_LOCKED(x) (*(x)=MUTEX_LOCKED) -#define init_MUTEX(x) (*(x)=MUTEX) -#define DECLARE_WAIT_QUEUE_HEAD(x) struct wait_queue *x = NULL -#endif - - -#else - -/* - * Linux 2.0 macros. Here we have to provide some of our own - * functionality. We also only work little endian 32bit. - * Again no pci_alloc/free api - * IO_LOCK/IO_LOCK_T were never used in 2.0 so now are empty - */ - -#define cpuid 0 -#define DRIVER_LOCK_T long cpu_flags; -#define DRIVER_LOCK_INIT(p) -#define DRIVER_LOCK(p) \ - save_flags(cpu_flags); \ - cli(); -#define DRIVER_UNLOCK(p) \ - restore_flags(cpu_flags); -#define IO_LOCK_T -#define IO_LOCK(p) -#define IO_UNLOCK(p) -#define le32_to_cpu(x) (x) -#define cpu_to_le32(x) (x) - -#define pci_free_consistent(a,b,c,d) -#define pci_unmap_single(a,b,c,d) - -#define init_MUTEX_LOCKED(x) (*(x)=MUTEX_LOCKED) -#define init_MUTEX(x) (*(x)=MUTEX) - -#define pci_enable_device(x) (0) - -/* - * 2.0 lacks spinlocks, iounmap/ioremap - */ - -#define ioremap vremap -#define iounmap vfree - - /* simulate spin locks */ -typedef struct { - volatile char lock; -} spinlock_t; - -#define spin_lock_init(x) { (x)->lock = 0;} -#define spin_lock_irqsave(x,flags) { while ((x)->lock) barrier();\ - (x)->lock=1; save_flags(flags);\ - cli();} -#define spin_unlock_irqrestore(x,flags) { (x)->lock=0; restore_flags(flags);} - -#define DECLARE_WAIT_QUEUE_HEAD(x) struct wait_queue *x = NULL - -#endif - - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) /* 0x020400 */ -#define dma_alloc_consistent pci_alloc_consistent -#define dma_free_consistent pci_free_consistent -#else -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,19) /* 0x020219 */ -typedef unsigned long dma_addr_t; -#endif -void *dma_alloc_consistent(void *, size_t, dma_addr_t *); -void dma_free_consistent(void *, size_t, void *, dma_addr_t); -int mega_get_order(int); -int pow_2(int); -#endif - /* set SERDEBUG to 1 to enable serial debugging */ #define SERDEBUG 0 #if SERDEBUG @@ -705,7 +569,6 @@ static int ser_printk (const char *fmt, ...); #endif -#ifdef CONFIG_PROC_FS #define COPY_BACK if (offset > megaCfg->procidx) { \ *eof = TRUE; \ megaCfg->procidx = 0; \ @@ -717,7 +580,6 @@ memcpy(page, &megaCfg->procbuf[offset], count); \ megaCfg->procidx = 0; \ megaCfg->procbuf[0] = 0; -#endif /* * ================================================================ @@ -730,11 +592,7 @@ processor id cannot be scanned */ static char *megaraid; -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,0) /* 0x20100 */ -#ifdef MODULE MODULE_PARM (megaraid, "s"); -#endif -#endif static int skip_id = -1; static int numCtlrs = 0; static mega_host_config *megaCtlrs[FC_MAX_CHANNELS] = { 0 }; @@ -760,6 +618,7 @@ /* For controller re-ordering */ static struct file_operations megadev_fops = { + owner: THIS_MODULE, ioctl:megadev_ioctl_entry, open:megadev_open, release:megadev_close, @@ -785,13 +644,6 @@ volatile static spinlock_t serial_lock; #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) /* 0x20300 */ -static struct proc_dir_entry proc_scsi_megaraid = { - PROC_SCSI_MEGARAID, 8, "megaraid", - S_IFDIR | S_IRUGO | S_IXUGO, 2 -}; -#endif - #ifdef CONFIG_PROC_FS extern struct proc_dir_entry proc_root; #endif @@ -887,7 +739,6 @@ if ((pScb == NULL) || (pScb->idx >= 0xFE)) { return; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) switch (pScb->dma_type) { case M_RD_DMA_TYPE_NONE: break; @@ -927,7 +778,6 @@ default: break; } -#endif /* Unlink from pending queue */ if (pScb == megaCfg->qPendingH) { @@ -991,9 +841,7 @@ pScb->state = SCB_ACTIVE; pScb->SCpnt = SCpnt; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) pScb->dma_type = M_RD_DMA_TYPE_NONE; -#endif return pScb; } @@ -1059,13 +907,8 @@ SCpnt = pScb->SCpnt; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) pthru = pScb->pthru; epthru = pScb->epthru; -#else - pthru = &pScb->pthru; - epthru = &pScb->epthru; -#endif mbox = (mega_mailbox *) & pScb->mboxData; @@ -1079,11 +922,7 @@ islogical = ( (SCpnt->channel >= megaCfg->productInfo.SCSIChanPresent) && (SCpnt->channel <= megaCfg->host->max_channel) ); -#if 0 - islogical = (SCpnt->channel == megaCfg->host->max_channel); -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) /* Special Case to handle PassThrough->XferAddrress > 4GB */ switch (SCpnt->cmnd[0]) { case INQUIRY: @@ -1092,7 +931,6 @@ pScb->bounce_buffer, SCpnt->request_bufflen); break; } -#endif mega_freeSCB (megaCfg, pScb); @@ -1101,24 +939,14 @@ * sent, and returned data==hard disk or removable hard disk and not * logical, request should return failure! - PJ */ -#if 0 - if (SCpnt->cmnd[0] == INQUIRY && ((((u_char *) SCpnt->request_buffer)[0] & 0x1F) == TYPE_DISK) && !islogical) { - status = 0xF0; - } -#endif if (SCpnt->cmnd[0] == INQUIRY && !islogical) { if ( SCpnt->use_sg ) { sgList = (struct scatterlist *)SCpnt->request_buffer; - memcpy(&c, cpu_to_le32(sg_dma_address(&sgList[0])), 0x1); + c = *(u8 *) cpu_to_le32(sg_dma_address(&sgList[0])); } else { - memcpy(&c, SCpnt->request_buffer, 0x1); - } -#if 0 - if( (c & 0x1F ) == TYPE_DISK ) { - status = 0xF0; + c = *(u8 *)SCpnt->request_buffer; } -#endif if( IS_RAID_CH(SCpnt->channel) && ((c & 0x1F ) == TYPE_DISK) ) { status = 0xF0; } @@ -1214,22 +1042,12 @@ if ((SCpnt->cmnd[0] == M_RD_IOCTL_CMD) || (SCpnt->cmnd[0] == M_RD_IOCTL_CMD_NEW)) -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) - return mega_ioctl (megaCfg, SCpnt); /* Handle IOCTL command */ -#else { - printk(KERN_WARNING "megaraid ioctl: older interface - " - "not supported.\n"); return NULL; } -#endif islogical = ( (SCpnt->channel >= megaCfg->productInfo.SCSIChanPresent) && (SCpnt->channel <= megaCfg->host->max_channel) ); -#if 0 - islogical = (IS_RAID_CH(SCpnt->channel) && /* virtual ch is raid - AM */ - (SCpnt->channel == megaCfg->host->max_channel)); -#endif if ( ! megaCfg->support_ext_cdb ) { if (!islogical && lun != 0) { @@ -1320,11 +1138,7 @@ callDone (SCpnt); return NULL; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) pthru = pScb->pthru; -#else - pthru = &pScb->pthru; -#endif mbox = (mega_mailbox *) & pScb->mboxData; memset (mbox, 0, sizeof (pScb->mboxData)); @@ -1336,30 +1150,12 @@ pthru->logdrv = lun; pthru->cdblen = SCpnt->cmd_len; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) /*Not sure about the direction */ pScb->dma_direction = PCI_DMA_BIDIRECTIONAL; pScb->dma_type = M_RD_PTHRU_WITH_BULK_DATA; -#if 0 -/* Normal Code w/o the need for bounce buffer */ - pScb->dma_h_bulkdata - = pci_map_single (megaCfg->dev, - SCpnt->request_buffer, - SCpnt->request_bufflen, - pScb->dma_direction); - - pthru->dataxferaddr = pScb->dma_h_bulkdata; -#else -/* Special Code to use bounce buffer for READ_CAPA/INQ */ pthru->dataxferaddr = pScb->dma_bounce_buffer; pScb->dma_type = M_RD_DMA_TYPE_NONE; -#endif - -#else - pthru->dataxferaddr = - virt_to_bus (SCpnt->request_buffer); -#endif pthru->dataxferlen = SCpnt->request_bufflen; memcpy (pthru->cdb, SCpnt->cmnd, SCpnt->cmd_len); @@ -1367,12 +1163,8 @@ /* Initialize mailbox area */ mbox->cmd = MEGA_MBOXCMD_PASSTHRU; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) mbox->xferaddr = pScb->dma_passthruhandle64; TRACE1 (("M_RD_PTHRU_WITH_BULK_DATA Enabled \n")); -#else - mbox->xferaddr = virt_to_bus (pthru); -#endif return pScb; case READ_6: @@ -1396,9 +1188,7 @@ READ_10) ? MEGA_MBOXCMD_LREAD64 : MEGA_MBOXCMD_LWRITE64; } else { - mbox->cmd = (*SCpnt->cmnd == READ_6 - || *SCpnt->cmnd == - READ_10) ? MEGA_MBOXCMD_LREAD : + mbox->cmd = (*SCpnt->cmnd == READ_6 || *SCpnt->cmnd == READ_10) ? MEGA_MBOXCMD_LREAD : MEGA_MBOXCMD_LWRITE; } @@ -1469,20 +1259,16 @@ } } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - if (*SCpnt->cmnd == READ_6 || *SCpnt->cmnd == READ_10 - || *SCpnt->cmnd == READ_12) { + if (*SCpnt->cmnd == READ_6 || *SCpnt->cmnd == READ_10 || *SCpnt->cmnd == READ_12) { pScb->dma_direction = PCI_DMA_FROMDEVICE; } else { /*WRITE_6 or WRITE_10 */ pScb->dma_direction = PCI_DMA_TODEVICE; } -#endif /* Calculate Scatter-Gather info */ mbox->numsgelements = mega_build_sglist (megaCfg, pScb, (u32 *)&mbox->xferaddr, (u32 *)&seg); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) pScb->iDataSize = seg; if (mbox->numsgelements) { @@ -1492,8 +1278,6 @@ pScb->dma_type = M_RD_BULK_DATA_ONLY; TRACE1 (("M_RD_BULK_DATA_ONLY Enabled \n")); } -#endif - return pScb; default: SCpnt->result = (DID_BAD_TARGET << 16); @@ -1520,7 +1304,6 @@ if ( megaCfg->support_ext_cdb && SCpnt->cmd_len > 10 ) { epthru = mega_prepare_extpassthru(megaCfg, pScb, SCpnt); mbox->cmd = MEGA_MBOXCMD_EXTPASSTHRU; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) mbox->xferaddr = pScb->dma_ext_passthruhandle64; if(epthru->numsgelements) { @@ -1528,16 +1311,12 @@ } else { pScb->dma_type = M_RD_EPTHRU_WITH_BULK_DATA; } -#else - mbox->xferaddr = virt_to_bus(epthru); -#endif } else { pthru = mega_prepare_passthru(megaCfg, pScb, SCpnt); /* Initialize mailbox */ mbox->cmd = MEGA_MBOXCMD_PASSTHRU; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) mbox->xferaddr = pScb->dma_passthruhandle64; if (pthru->numsgelements) { @@ -1545,9 +1324,6 @@ } else { pScb->dma_type = M_RD_PTHRU_WITH_BULK_DATA; } -#else - mbox->xferaddr = virt_to_bus(pthru); -#endif } return pScb; } @@ -1597,11 +1373,7 @@ { mega_passthru *pthru; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) pthru = scb->pthru; -#else - pthru = &scb->pthru; -#endif memset (pthru, 0, sizeof (mega_passthru)); /* set adapter timeout value to 10 min. for tape drive */ @@ -1618,7 +1390,6 @@ memcpy (pthru->cdb, sc->cmnd, sc->cmd_len); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) /* Not sure about the direction */ scb->dma_direction = PCI_DMA_BIDIRECTIONAL; @@ -1631,20 +1402,12 @@ pthru->dataxferlen = sc->request_bufflen; break; default: - pthru->numsgelements = - mega_build_sglist( + pthru->numsgelements = mega_build_sglist( megacfg, scb, (u32 *)&pthru->dataxferaddr, (u32 *)&pthru->dataxferlen ); break; } -#else - pthru->numsgelements = - mega_build_sglist( - megacfg, scb, (u32 *)&pthru->dataxferaddr, - (u32 *)&pthru->dataxferlen - ); -#endif return pthru; } @@ -1653,11 +1416,7 @@ { mega_ext_passthru *epthru; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) epthru = scb->epthru; -#else - epthru = &scb->epthru; -#endif memset(epthru, 0, sizeof(mega_ext_passthru)); /* set adapter timeout value to 10 min. for tape drive */ @@ -1674,7 +1433,6 @@ memcpy(epthru->cdb, sc->cmnd, sc->cmd_len); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) /* Not sure about the direction */ scb->dma_direction = PCI_DMA_BIDIRECTIONAL; @@ -1694,13 +1452,6 @@ ); break; } -#else - epthru->numsgelements = - mega_build_sglist( - megacfg, scb, (u32 *)&epthru->dataxferaddr, - (u32 *)&epthru->dataxferlen - ); -#endif return epthru; } @@ -1741,8 +1492,6 @@ static void inline set_mbox_xfer_addr (mega_host_config * megaCfg, mega_scb * pScb, mega_ioctl_mbox * mbox, u32 direction) { - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) switch (direction) { case TO_DEVICE: pScb->dma_direction = PCI_DMA_TODEVICE; @@ -1755,290 +1504,15 @@ break; } - pScb->dma_h_bulkdata - = pci_map_single (megaCfg->dev, - pScb->buff_ptr, - pScb->iDataSize, pScb->dma_direction); + pScb->dma_h_bulkdata = pci_map_single (megaCfg->dev, pScb->buff_ptr, pScb->iDataSize, pScb->dma_direction); mbox->xferaddr = pScb->dma_h_bulkdata; pScb->dma_type = M_RD_BULK_DATA_ONLY; TRACE1 (("M_RD_BULK_DATA_ONLY Enabled \n")); -#else - mbox->xferaddr = virt_to_bus (pScb->buff_ptr); -#endif -} - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) - -/*-------------------------------------------------------------------- - * build RAID commands for controller, passed down through ioctl() - *--------------------------------------------------------------------*/ -static mega_scb *mega_ioctl (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt) -{ - mega_scb *pScb; - mega_ioctl_mbox *mbox; - mega_mailbox *mailbox; - mega_passthru *pthru; - u8 *mboxdata; - long seg, i = 0; - unsigned char *data = (unsigned char *) SCpnt->request_buffer; - - if ((pScb = mega_allocateSCB (megaCfg, SCpnt)) == NULL) { - SCpnt->result = (DID_ERROR << 16); - callDone (SCpnt); - return NULL; - } - pthru = &pScb->pthru; - - mboxdata = (u8 *) & pScb->mboxData; - mbox = (mega_ioctl_mbox *) & pScb->mboxData; - mailbox = (mega_mailbox *) & pScb->mboxData; - memset (mailbox, 0, sizeof (pScb->mboxData)); - - if (data[0] == 0x03) { /* passthrough command */ - unsigned char cdblen = data[2]; - memset (pthru, 0, sizeof (mega_passthru)); - pthru->islogical = (data[cdblen + 3] & 0x80) ? 1 : 0; - pthru->timeout = data[cdblen + 3] & 0x07; - pthru->reqsenselen = 14; - pthru->ars = (data[cdblen + 3] & 0x08) ? 1 : 0; - pthru->logdrv = data[cdblen + 4]; - pthru->channel = data[cdblen + 5]; - pthru->target = data[cdblen + 6]; - pthru->cdblen = cdblen; - memcpy (pthru->cdb, &data[3], cdblen); - - mailbox->cmd = MEGA_MBOXCMD_PASSTHRU; - - - pthru->numsgelements = mega_build_sglist (megaCfg, pScb, - (u32 *) & pthru-> - dataxferaddr, - (u32 *) & pthru-> - dataxferlen); - - mailbox->xferaddr = virt_to_bus (pthru); - - for (i = 0; i < (SCpnt->request_bufflen - cdblen - 7); i++) { - data[i] = data[i + cdblen + 7]; - } - return pScb; - } - /* else normal (nonpassthru) command */ - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,0,24) /*0x020024 */ - /* - *usage of the function copy from user is used in case of data more than - *4KB.This is used only with adapters which supports more than 8 logical - * drives.This feature is disabled on kernels earlier or same as 2.0.36 - * as the uaccess.h file is not available with those kernels. - */ - - if (SCpnt->cmnd[0] == M_RD_IOCTL_CMD_NEW) { - /* use external data area for large xfers */ - /* If cmnd[0] is set to M_RD_IOCTL_CMD_NEW then * - * cmnd[4..7] = external user buffer * - * cmnd[8..11] = length of buffer * - * */ - char *user_area = (char *)*((u32*)&SCpnt->cmnd[4]); - u32 xfer_size = *((u32 *) & SCpnt->cmnd[8]); - switch (data[0]) { - case FW_FIRE_WRITE: - case FW_FIRE_FLASH: - if ((ulong) user_area & (PAGE_SIZE - 1)) { - printk - ("megaraid:user address not aligned on 4K boundary.Error.\n"); - SCpnt->result = (DID_ERROR << 16); - callDone (SCpnt); - return NULL; - } - break; - default: - break; - } - - if (!(pScb->buff_ptr = kmalloc (xfer_size, GFP_KERNEL))) { - printk - ("megaraid: Insufficient mem for M_RD_IOCTL_CMD_NEW.\n"); - SCpnt->result = (DID_ERROR << 16); - callDone (SCpnt); - return NULL; - } - - copy_from_user (pScb->buff_ptr, user_area, xfer_size); - pScb->iDataSize = xfer_size; - - switch (data[0]) { - case DCMD_FC_CMD: - switch (data[1]) { - case DCMD_FC_READ_NVRAM_CONFIG: - case DCMD_GET_DISK_CONFIG: - { - if ((ulong) pScb-> - buff_ptr & (PAGE_SIZE - 1)) { - printk - ("megaraid:user address not sufficient Error.\n"); - SCpnt->result = - (DID_ERROR << 16); - callDone (SCpnt); - return NULL; - } - - /*building SG list */ - mega_build_kernel_sg (pScb->buff_ptr, - xfer_size, - pScb, mbox); - break; - } - default: - break; - } /*switch (data[1]) */ - break; - } - - } -#endif - - mbox->cmd = data[0]; - mbox->channel = data[1]; - mbox->param = data[2]; - mbox->pad[0] = data[3]; - mbox->logdrv = data[4]; - - if (SCpnt->cmnd[0] == M_RD_IOCTL_CMD_NEW) { - switch (data[0]) { - case FW_FIRE_WRITE: - mbox->cmd = FW_FIRE_WRITE; - mbox->channel = data[1]; /* Current Block Number */ - set_mbox_xfer_addr (megaCfg, pScb, mbox, TO_DEVICE); - mbox->numsgelements = 0; - break; - case FW_FIRE_FLASH: - mbox->cmd = FW_FIRE_FLASH; - mbox->channel = data[1] | 0x80; /* Origin */ - set_mbox_xfer_addr (megaCfg, pScb, mbox, TO_DEVICE); - mbox->numsgelements = 0; - break; - case DCMD_FC_CMD: - *(mboxdata + 0) = data[0]; /*mailbox byte 0: DCMD_FC_CMD */ - *(mboxdata + 2) = data[1]; /*sub command */ - switch (data[1]) { - case DCMD_FC_READ_NVRAM_CONFIG: - case DCMD_FC_READ_NVRAM_CONFIG_64: - /* number of elements in SG list */ - *(mboxdata + 3) = mbox->numsgelements; - if (megaCfg->flag & BOARD_64BIT) - *(mboxdata + 2) = - DCMD_FC_READ_NVRAM_CONFIG_64; - break; - case DCMD_WRITE_CONFIG: - case DCMD_WRITE_CONFIG_64: - if (megaCfg->flag & BOARD_64BIT) - *(mboxdata + 2) = DCMD_WRITE_CONFIG_64; - set_mbox_xfer_addr (megaCfg, pScb, mbox, - TO_DEVICE); - mbox->numsgelements = 0; - break; - case DCMD_GET_DISK_CONFIG: - case DCMD_GET_DISK_CONFIG_64: - if (megaCfg->flag & BOARD_64BIT) - *(mboxdata + 2) = - DCMD_GET_DISK_CONFIG_64; - *(mboxdata + 3) = data[2]; /*number of elements in SG list */ - /*nr of elements in SG list */ - *(mboxdata + 4) = mbox->numsgelements; - break; - case DCMD_DELETE_LOGDRV: - case DCMD_DELETE_DRIVEGROUP: - case NC_SUBOP_ENQUIRY3: - *(mboxdata + 3) = data[2]; - set_mbox_xfer_addr (megaCfg, pScb, mbox, - FROMTO_DEVICE); - mbox->numsgelements = 0; - break; - case DCMD_CHANGE_LDNO: - case DCMD_CHANGE_LOOPID: - *(mboxdata + 3) = data[2]; - *(mboxdata + 4) = data[3]; - set_mbox_xfer_addr (megaCfg, pScb, mbox, - TO_DEVICE); - mbox->numsgelements = 0; - break; - default: - set_mbox_xfer_addr (megaCfg, pScb, mbox, - FROMTO_DEVICE); - mbox->numsgelements = 0; - break; - } /*switch */ - break; - default: - set_mbox_xfer_addr (megaCfg, pScb, mbox, FROMTO_DEVICE); - mbox->numsgelements = 0; - break; - } - } else { - - mbox->numsgelements = mega_build_sglist (megaCfg, pScb, - (u32 *) & mbox-> - xferaddr, - (u32 *) & seg); - - /* Handling some of the fw special commands */ - switch (data[0]) { - case 6: /* START_DEV */ - mbox->xferaddr = *((u32 *) & data[i + 6]); - break; - default: - break; - } - - for (i = 0; i < (SCpnt->request_bufflen - 6); i++) { - data[i] = data[i + 6]; - } - } - - return (pScb); } - -static void mega_build_kernel_sg (char *barea, ulong xfersize, mega_scb * pScb, mega_ioctl_mbox * mbox) -{ - ulong i, buffer_area, len, end, end_page, x, idx = 0; - - buffer_area = (ulong) barea; - i = buffer_area; - end = buffer_area + xfersize; - end_page = (end) & ~(PAGE_SIZE - 1); - - do { - len = PAGE_SIZE - (i % PAGE_SIZE); - x = pScb->sgList[idx].address = - virt_to_bus ((volatile void *) i); - pScb->sgList[idx].length = len; - i += len; - idx++; - } while (i < end_page); - - if ((end - i) < 0) { - printk ("megaraid:Error in user address\n"); - } - - if (end - i) { - pScb->sgList[idx].address = virt_to_bus ((volatile void *) i); - pScb->sgList[idx].length = end - i; - idx++; - } - mbox->xferaddr = virt_to_bus (pScb->sgList); - mbox->numsgelements = idx; -} -#endif - - -#if DEBUG -static unsigned int cum_time = 0; -static unsigned int cum_time_cnt = 0; - static void showMbox (mega_scb * pScb) { +#ifdef DEBUG mega_mailbox *mbox; if (pScb == NULL) @@ -2049,16 +1523,15 @@ pScb->SCpnt->pid, mbox->cmd, mbox->cmdid, mbox->numsectors, mbox->lba, mbox->xferaddr, mbox->logdrv, mbox->numsgelements); +#endif } -#endif - /*-------------------------------------------------------------------- * Interrupt service routine *--------------------------------------------------------------------*/ static void megaraid_isr (int irq, void *devp, struct pt_regs *regs) { - IO_LOCK_T; + unsigned long io_flags; mega_host_config * megaCfg; u_char byte, idx, sIdx, tmpBox[MAILBOX_SIZE]; u32 dword = 0; @@ -2103,7 +1576,7 @@ for (idx = 0; idx < MAX_FIRMWARE_STATUS; idx++) completed[idx] = 0; - IO_LOCK(megaCfg->host); + spin_lock_irqsave(megaCfg->host->host_lock, io_flags); megaCfg->nInterrupts++; qCnt = 0xff; @@ -2124,27 +1597,8 @@ if (megaCfg->flag & BOARD_QUARTZ) { WROUTDOOR (megaCfg, dword); /* Acknowledge interrupt */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) /* In this case mbox contains physical address */ -#if 0 - WRINDOOR (megaCfg, megaCfg->adjdmahandle64 | 0x2); -#else WRINDOOR (megaCfg, 0x2); -#endif - -#else - -#if 0 - WRINDOOR (megaCfg, virt_to_bus (megaCfg->mbox) | 0x2); -#else - WRINDOOR (megaCfg, 0x2); -#endif - -#endif - -#if 0 - while (RDINDOOR (megaCfg) & 0x02) ; -#endif } else { CLEAR_INTR (megaCfg->host->io_port); } @@ -2222,7 +1676,7 @@ megaCfg->flag &= ~IN_ISR; /* Loop through any pending requests */ mega_runpendq (megaCfg); - IO_UNLOCK(megaCfg->host); + spin_unlock_irqrestore(megaCfg->host->host_lock, io_flags); } @@ -2267,9 +1721,7 @@ { volatile mega_mailbox *mbox = (mega_mailbox *) megaCfg->mbox; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) volatile mega_mailbox64 *mbox64 = (mega_mailbox64 *) megaCfg->mbox64; -#endif u_char byte; @@ -2283,12 +1735,8 @@ mboxData[0x1] = (pScb ? pScb->idx + 1 : 0xFE); /* Set cmdid */ mboxData[0xF] = 1; /* Set busy */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) /* In this case mbox contains physical address */ phys_mbox = megaCfg->adjdmahandle64; -#else - phys_mbox = virt_to_bus (megaCfg->mbox); -#endif #if DEBUG ShowMbox (pScb); @@ -2296,12 +1744,10 @@ /* Wait until mailbox is free */ if (mega_busyWaitMbox (megaCfg)) { - printk ("Blocked mailbox......!!\n"); + printk (KERN_WARNING "megaraid: Blocked mailbox......!!\n"); udelay (1000); -#if DEBUG showMbox (pLastScb); -#endif /* Abort command */ if (pScb == NULL) { @@ -2320,7 +1766,6 @@ memcpy ((char *) mbox, mboxData, 16); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) switch (mboxData[0]) { case MEGA_MBOXCMD_LREAD64: case MEGA_MBOXCMD_LWRITE64: @@ -2329,7 +1774,6 @@ mbox->xferaddr = 0xFFFFFFFF; break; } -#endif /* Kick IO */ if (intr) { @@ -2416,10 +1860,7 @@ { struct scatterlist *sgList; int idx; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) int sgcnt; -#endif mega_mailbox *mbox = NULL; @@ -2427,7 +1868,6 @@ /* Scatter-gather not used */ if (scb->SCpnt->use_sg == 0) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) scb->dma_h_bulkdata = pci_map_single (megaCfg->dev, scb->SCpnt->request_buffer, scb->SCpnt->request_bufflen, @@ -2448,45 +1888,11 @@ *buffer = scb->dma_h_bulkdata; *length = (u32) scb->SCpnt->request_bufflen; } -#else - *buffer = virt_to_bus (scb->SCpnt->request_buffer); - *length = (u32) scb->SCpnt->request_bufflen; -#endif return 0; } sgList = (struct scatterlist *) scb->SCpnt->request_buffer; -#if 0 - if (scb->SCpnt->use_sg == 1) { - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - scb->dma_h_bulkdata = pci_map_single (megaCfg->dev, - sgList[0].address, - sgList[0].length, scb->dma_direction); - - if ((megaCfg->flag & BOARD_64BIT) && - ((mbox->cmd == MEGA_MBOXCMD_LREAD64) || - (mbox->cmd == MEGA_MBOXCMD_LWRITE64))) { - scb->sg64List[0].address = scb->dma_h_bulkdata; - scb->sg64List[0].length = scb->SCpnt->request_bufflen; - *buffer = scb->dma_sghandle64; - *length = 0; - scb->sglist_count = 1; - return 1; - } else { - *buffer = scb->dma_h_bulkdata; - *length = (u32) sgList[0].length; - } -#else - *buffer = virt_to_bus (sgList[0].address); - *length = (u32) sgList[0].length; -#endif - - return 0; - } -#endif /* Copy Scatter-Gather list info into controller structure */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) sgcnt = pci_map_sg (megaCfg->dev, sgList, scb->SCpnt->use_sg, scb->dma_direction); @@ -2508,29 +1914,14 @@ } -#else - for (idx = 0; idx < scb->SCpnt->use_sg; idx++) { - scb->sgList[idx].address = virt_to_bus (sgList[idx].address); - scb->sgList[idx].length = (u32) sgList[idx].length; - } -#endif /* Reset pointer and length fields */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) *buffer = scb->dma_sghandle64; scb->sglist_count = scb->SCpnt->use_sg; -#else - *buffer = virt_to_bus (scb->sgList); -#endif *length = 0; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) /* Return count of SG requests */ return sgcnt; -#else - /* Return count of SG requests */ - return scb->SCpnt->use_sg; -#endif } /*-------------------------------------------------------------------- @@ -2553,11 +1944,7 @@ mega_register_mailbox (mega_host_config * megaCfg, u32 paddr) { /* align on 16-byte boundary */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) megaCfg->mbox = &megaCfg->mailbox64ptr->mailbox; -#else - megaCfg->mbox = &megaCfg->mailbox64.mailbox; -#endif #ifdef __LP64__ megaCfg->mbox = (mega_mailbox *) ((((u64) megaCfg->mbox) + 16) & ((u64) (-1) ^ 0x0F)); @@ -2568,9 +1955,7 @@ megaCfg->mbox = (mega_mailbox *) ((((u32) megaCfg->mbox) + 16) & 0xFFFFFFF0); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) megaCfg->adjdmahandle64 = ((megaCfg->dma_handle64 + 16) & 0xFFFFFFF0); -#endif megaCfg->mbox64 = (mega_mailbox64 *) ((u_char *) megaCfg->mbox - 8); paddr = (paddr + 4 + 16) & 0xFFFFFFF0; @@ -2639,9 +2024,7 @@ mega_mailbox *mbox; u_char mboxData[16]; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) dma_addr_t raid_inq_dma_handle = 0, prod_info_dma_handle = 0, enquiry3_dma_handle = 0; -#endif u8 retval; /* Initialize adapter inquiry mailbox */ @@ -2657,16 +2040,11 @@ * if not succeeded, then issue MEGA_MBOXCMD_ADAPTERINQ command and * update enquiry3 structure */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) enquiry3_dma_handle = pci_map_single (megaCfg->dev, (void *) megaCfg->mega_buffer, (2 * 1024L), PCI_DMA_FROMDEVICE); mbox->xferaddr = enquiry3_dma_handle; -#else - /*Taken care */ - mbox->xferaddr = virt_to_bus ((void *) megaCfg->mega_buffer); -#endif /* Initialize mailbox databuffer addr */ enquiry3Pnt = (mega_Enquiry3 *) megaCfg->mega_buffer; @@ -2681,16 +2059,11 @@ mega_RAIDINQ adapterInquiryData; mega_RAIDINQ *adapterInquiryPnt = &adapterInquiryData; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) raid_inq_dma_handle = pci_map_single (megaCfg->dev, (void *) adapterInquiryPnt, sizeof (mega_RAIDINQ), PCI_DMA_FROMDEVICE); mbox->xferaddr = raid_inq_dma_handle; -#else - /*taken care */ - mbox->xferaddr = virt_to_bus ((void *) adapterInquiryPnt); -#endif mbox->cmd = MEGA_MBOXCMD_ADAPTERINQ; /*issue old 0x05 command to adapter */ /* Issue a blocking command to the card */ ; @@ -2712,7 +2085,6 @@ pci_unmap_single (megaCfg->dev, enquiry3_dma_handle, (2 * 1024L), PCI_DMA_FROMDEVICE); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) /*get productInfo, which is static information and will be unchanged*/ prod_info_dma_handle = pci_map_single (megaCfg->dev, @@ -2720,10 +2092,6 @@ sizeof (megaRaidProductInfo), PCI_DMA_FROMDEVICE); mbox->xferaddr = prod_info_dma_handle; -#else - /*taken care */ - mbox->xferaddr = virt_to_bus ((void *) &megaCfg->productInfo); -#endif mboxData[0] = FC_NEW_CONFIG; /* i.e. mbox->cmd=0xA1 */ mboxData[2] = NC_SUBOP_PRODUCT_INFO; /* i.e. 0x0E */ @@ -2741,16 +2109,10 @@ /* * kernel scans the channels from 0 to <= max_channel */ - megaCfg->host->max_channel = - megaCfg->productInfo.SCSIChanPresent + NVIRT_CHAN -1; + megaCfg->host->max_channel = megaCfg->productInfo.SCSIChanPresent + NVIRT_CHAN -1; megaCfg->host->max_id = 16; /* max targets per channel */ /*(megaCfg->flag & BOARD_40LD)?FC_MAX_TARGETS_PER_CHANNEL:MAX_TARGET+1; */ -#if 0 - megaCfg->host->max_lun = /* max lun */ - (megaCfg->flag & BOARD_40LD) ? - FC_MAX_LOGICAL_DRIVES : MAX_LOGICAL_DRIVES; -#endif megaCfg->host->max_lun = 7; /* Upto 7 luns for non disk devices */ megaCfg->host->cmd_per_lun = MAX_CMD_PER_LUN; @@ -2762,12 +2124,6 @@ megaCfg->host->can_queue = megaCfg->max_cmds - 1; -#if 0 - if (megaCfg->host->can_queue >= MAX_COMMANDS) { - megaCfg->host->can_queue = MAX_COMMANDS - 16; - } -#endif - /* use HP firmware and bios version encoding */ if (megaCfg->productInfo.subSystemVendorID == HP_SUBSYS_ID) { sprintf (megaCfg->fwVer, "%c%d%d.%d%d", @@ -2816,7 +2172,7 @@ * Returns data to be displayed in /proc/scsi/megaraid/X *----------------------------------------------------------*/ -int megaraid_proc_info (char *buffer, char **start, off_t offset, +static int megaraid_proc_info (char *buffer, char **start, off_t offset, int length, int host_no, int inout) { *start = buffer; @@ -2829,114 +2185,45 @@ mega_host_config *megaCfg = NULL; struct Scsi_Host *host = NULL; u_char pciBus, pciDevFun, megaIrq; - u16 magic; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) u32 magic64; -#endif - - int i; - -#ifdef __LP64__ - u64 megaBase; -#else - u32 megaBase; -#endif - + int i; + unsigned long megaBase; u16 pciIdx = 0; u16 numFound = 0; - u16 subsysid, subsysvid; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0) /* 0x20100 */ - while (!pcibios_find_device - (pciVendor, pciDev, pciIdx, &pciBus, &pciDevFun)) { -#else - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0) /*0x20300 */ struct pci_dev *pdev = NULL; -#else - struct pci_dev *pdev = pci_devices; -#endif - while ((pdev = pci_find_device (pciVendor, pciDev, pdev))) { + while ((pdev = pci_find_device (pciVendor, pciDev, pdev))) + { if(pci_enable_device (pdev)) continue; pciBus = pdev->bus->number; pciDevFun = pdev->devfn; -#endif - if ((flag & BOARD_QUARTZ) && (skip_id == -1)) { - pci_read_config_word (pdev, PCI_CONF_AMISIG, &magic); - if ((magic != AMI_SIGNATURE) - && (magic != AMI_SIGNATURE_471)) { + + if ((flag & BOARD_QUARTZ) && (skip_id == -1)) + { + pci_read_config_word (pdev, PCI_CONF_AMISIG, &magic); + if ((magic != AMI_SIGNATURE) && (magic != AMI_SIGNATURE_471)) + { pciIdx++; continue; /* not an AMI board */ } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) pci_read_config_dword (pdev, PCI_CONF_AMISIG64, &magic64); if (magic64 == AMI_64BIT_SIGNATURE) flag |= BOARD_64BIT; -#endif } /* Hmmm...Should we not make this more modularized so that in future we dont add for each firmware */ - if (flag & BOARD_QUARTZ) { - /* Check to see if this is a Dell PERC RAID controller model 466 */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0) /* 0x20100 */ - pcibios_read_config_word (pciBus, pciDevFun, - PCI_SUBSYSTEM_VENDOR_ID, - &subsysvid); - pcibios_read_config_word (pciBus, pciDevFun, - PCI_SUBSYSTEM_ID, &subsysid); -#else - pci_read_config_word (pdev, - PCI_SUBSYSTEM_VENDOR_ID, - &subsysvid); - pci_read_config_word (pdev, - PCI_SUBSYSTEM_ID, &subsysid); -#endif - -#if 0 - /* - * This routine is called with well know values and we - * should not be getting what we have not asked. - * Also, the check is not right. It should have been for - * pci_vendor_id not subsysvid - AM - */ - - /* If we dont detect this valid subsystem vendor id's - we refuse to load the driver - PART of PC200X compliance - */ - - if ((subsysvid != AMI_SUBSYS_ID) - && (subsysvid != DELL_SUBSYS_ID) - && (subsysvid != HP_SUBSYS_ID)) - continue; -#endif - } - printk (KERN_NOTICE "megaraid: found 0x%4.04x:0x%4.04x:idx %d:bus %d:slot %d:func %d\n", pciVendor, pciDev, pciIdx, pciBus, PCI_SLOT (pciDevFun), PCI_FUNC (pciDevFun)); /* Read the base port and IRQ from PCI */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0) /* 0x20100 */ - pcibios_read_config_dword (pciBus, pciDevFun, - PCI_BASE_ADDRESS_0, - (u_int *) & megaBase); - pcibios_read_config_byte (pciBus, pciDevFun, - PCI_INTERRUPT_LINE, &megaIrq); -#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) /*0x20300 */ - megaBase = pdev->base_address[0]; - megaIrq = pdev->irq; -#else - megaBase = pci_resource_start (pdev, 0); megaIrq = pdev->irq; -#endif pciIdx++; @@ -2971,8 +2258,7 @@ M_RD_CRLFSTR, host->host_no, (u_int) megaBase, megaIrq); if (flag & BOARD_64BIT) - printk (KERN_NOTICE "scsi%d : Enabling 64 bit support\n", - host->host_no); + printk (KERN_NOTICE "scsi%d : Enabling 64 bit support\n", host->host_no); /* Copy resource info into structure */ megaCfg->qCompletedH = NULL; @@ -2991,10 +2277,7 @@ megaCfg->int_qh = NULL; megaCfg->int_qt = NULL; megaCfg->int_qlen = 0; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) megaCfg->dev = pdev; -#endif megaCfg->host = host; megaCfg->base = megaBase; megaCfg->host->irq = megaIrq; @@ -3012,41 +2295,30 @@ } /* Request our IRQ */ - if (request_irq (megaIrq, megaraid_isr, SA_SHIRQ, - "megaraid", megaCfg)) { - printk (KERN_WARNING - "megaraid: Couldn't register IRQ %d!\n", - megaIrq); + if (request_irq (megaIrq, megaraid_isr, SA_SHIRQ, "megaraid", megaCfg)) { + printk (KERN_WARNING "megaraid: Couldn't register IRQ %d!\n", megaIrq); goto err_release; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) /* * unmap while releasing the driver, Is it required to be * PCI_DMA_BIDIRECTIONAL */ - megaCfg->mailbox64ptr - = pci_alloc_consistent (megaCfg->dev, - sizeof (mega_mailbox64), - &(megaCfg->dma_handle64)); + megaCfg->mailbox64ptr = pci_alloc_consistent (megaCfg->dev, sizeof (mega_mailbox64), &(megaCfg->dma_handle64)); mega_register_mailbox (megaCfg, megaCfg->dma_handle64); -#else - mega_register_mailbox (megaCfg, - virt_to_bus ((void *) &megaCfg-> - mailbox64)); -#endif mega_i_query_adapter (megaCfg); - if ((subsysid == 0x1111) && (subsysvid == 0x1111)) { - + if (pdev->subsystem_vendor == 0x1111 && pdev->subsystem_device == 0x1111) + { /* * Which firmware */ if( strcmp(megaCfg->fwVer, "3.00") == 0 || - strcmp(megaCfg->fwVer, "3.01") == 0 ) { + strcmp(megaCfg->fwVer, "3.01") == 0 ) + { printk( KERN_WARNING "megaraid: Your card is a Dell PERC 2/SC RAID controller " @@ -3064,20 +2336,22 @@ /* * If we have a HP 1M(0x60E7)/2M(0x60E8) controller with - * firmware H.01.07 or H.01.08, disable 64 bit support, + * firmware H.01.07 H.01.08 or H.01.09, disable 64 bit support, * since this firmware cannot handle 64 bit addressing */ - if( (subsysvid == HP_SUBSYS_ID) && - ((subsysid == 0x60E7)||(subsysid == 0x60E8)) ) { - + if(pdev->subsystem_vendor == HP_SUBSYS_ID && + (pdev->subsystem_device == 0x60E7 || pdev->subsystem_device == 0x60E8 || pdev->subsystem_device == 0x60E9)) + { /* * which firmware */ if( strcmp(megaCfg->fwVer, "H01.07") == 0 || - strcmp(megaCfg->fwVer, "H01.08") == 0 ) { + strcmp(megaCfg->fwVer, "H01.08") == 0 || + strcmp(megaCfg->fwVer, "H01.09") == 0 ) + { printk(KERN_WARNING - "megaraid: Firmware H.01.07 or H.01.08 on 1M/2M " + "megaraid: Firmware H.01.07 to H.01.09 on 1M/2M " "controllers\nmegaraid: do not support 64 bit " "addressing.\n" "megaraid: DISABLING 64 bit support.\n"); @@ -3147,21 +2421,19 @@ numFound++; /* Set the Mode of addressing to 64 bit */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) if ((megaCfg->flag & BOARD_64BIT) && BITS_PER_LONG == 64) #ifdef __LP64__ pdev->dma_mask = 0xffffffffffffffff; #else pdev->dma_mask = 0xffffffff; #endif -#endif continue; - err_release: +err_release: if (flag & BOARD_QUARTZ) release_region (megaBase, 16); - err_unregister: +err_unregister: scsi_unregister (host); - err_unmap: +err_unmap: if (flag & BOARD_QUARTZ) iounmap ((void *) megaBase); } @@ -3172,23 +2444,12 @@ * Detects if a megaraid controller exists in this system *---------------------------------------------------------*/ -int megaraid_detect (Scsi_Host_Template * pHostTmpl) +static int megaraid_detect (Scsi_Host_Template * pHostTmpl) { int ctlridx = 0, count = 0; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) /*0x20300 */ - pHostTmpl->proc_dir = &proc_scsi_megaraid; -#else pHostTmpl->proc_name = "megaraid"; -#endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0) /* 0x20100 */ - if (!pcibios_present ()) { - printk (KERN_WARNING "megaraid: PCI bios not present." - M_RD_CRLFSTR); - return 0; - } -#endif skip_id = -1; if (megaraid && !strncmp (megaraid, "skip", strlen ("skip"))) { if (megaraid[4] != '\0') { @@ -3216,13 +2477,7 @@ #ifdef CONFIG_PROC_FS if (count) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0) /*0x20300 */ mega_proc_dir_entry = proc_mkdir ("megaraid", &proc_root); -#else - mega_proc_dir_entry = create_proc_entry ("megaraid", - S_IFDIR | S_IRUGO | - S_IXUGO, &proc_root); -#endif if (!mega_proc_dir_entry) printk ("megaraid: failed to create megaraid root\n"); else @@ -3260,7 +2515,7 @@ /*--------------------------------------------------------------------- * Release the controller's resources *---------------------------------------------------------------------*/ -int megaraid_release (struct Scsi_Host *pSHost) +static int megaraid_release (struct Scsi_Host *pSHost) { mega_host_config *megaCfg; mega_mailbox *mbox; @@ -3367,10 +2622,7 @@ mega_mailbox *mboxp; unsigned char mbox[16]; int i; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) dma_addr_t dma_handle; -#endif mboxp = (mega_mailbox *)mbox; @@ -3383,14 +2635,10 @@ memset((void *)megacfg->mega_buffer, 0, sizeof(megacfg->mega_buffer)); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) dma_handle = pci_map_single(megacfg->dev, (void *)megacfg->mega_buffer, (2 * 1024L), PCI_DMA_FROMDEVICE); mboxp->xferaddr = dma_handle; -#else - mboxp->xferaddr = virt_to_bus((void *)megacfg->mega_buffer); -#endif /* * Non-ROMB firware fail this command, so all channels @@ -3407,13 +2655,8 @@ else { mega_ch_class = 0xFF; } - - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) pci_unmap_single(megacfg->dev, dma_handle, (2 * 1024L), PCI_DMA_FROMDEVICE); -#endif - } @@ -3429,10 +2672,7 @@ u16 cksum = 0; char *cksum_p; int i; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) dma_addr_t dma_handle; -#endif mboxp = (mega_mailbox *)mbox; @@ -3443,14 +2683,10 @@ memset((void *)megacfg->mega_buffer, 0, sizeof(megacfg->mega_buffer)); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) dma_handle = pci_map_single(megacfg->dev, (void *)megacfg->mega_buffer, (2 * 1024L), PCI_DMA_FROMDEVICE); mboxp->xferaddr = dma_handle; -#else - mboxp->xferaddr = virt_to_bus((void *)megacfg->mega_buffer); -#endif megacfg->boot_ldrv_enabled = 0; megacfg->boot_ldrv = 0; @@ -3470,11 +2706,8 @@ } } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) pci_unmap_single(megacfg->dev, dma_handle, (2 * 1024L), PCI_DMA_FROMDEVICE); -#endif - } @@ -3490,16 +2723,13 @@ megaCfg->scbList[i].sgList, megaCfg->scbList[i]. dma_sghandle64); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) /* 0x020400 */ - kfree (megaCfg->scbList[i].sgList); /* free sgList */ -#endif } } /*---------------------------------------------- * Get information about the card/driver *----------------------------------------------*/ -const char *megaraid_info (struct Scsi_Host *pSHost) +static const char *megaraid_info (struct Scsi_Host *pSHost) { static char buffer[512]; mega_host_config *megaCfg; @@ -3531,12 +2761,11 @@ *-----------------------------------------------------------------*/ int megaraid_queue (Scsi_Cmnd * SCpnt, void (*pktComp) (Scsi_Cmnd *)) { - DRIVER_LOCK_T mega_host_config * megaCfg; + mega_host_config * megaCfg; mega_scb *pScb; char *user_area = NULL; megaCfg = (mega_host_config *) SCpnt->host->hostdata; - DRIVER_LOCK (megaCfg); if (!(megaCfg->flag & (1L << SCpnt->channel))) { if (SCpnt->channel < megaCfg->productInfo.SCSIChanPresent) @@ -3571,7 +2800,6 @@ megaCfg->qCompletedT->host_scribble = (unsigned char *) NULL; megaCfg->qCcnt++; - DRIVER_UNLOCK (megaCfg); return 0; } else if (megaCfg->flag & IN_RESET) { SCpnt->result = (DID_RESET << 16); @@ -3586,7 +2814,6 @@ megaCfg->qCompletedT->host_scribble = (unsigned char *) NULL; megaCfg->qCcnt++; - DRIVER_UNLOCK (megaCfg); return 0; } @@ -3611,7 +2838,6 @@ megaCfg->qPcnt++; if (mega_runpendq (megaCfg) == -1) { - DRIVER_UNLOCK (megaCfg); return 0; } } @@ -3629,38 +2855,31 @@ if (pScb->SCpnt->cmnd[0] == M_RD_IOCTL_CMD_NEW) { init_MUTEX_LOCKED (&pScb->ioctl_sem); - IO_UNLOCK_IRQ(megaCfg->host); + spin_unlock_irq(megaCfg->host->host_lock); down (&pScb->ioctl_sem); - user_area = (char *)*((u32*)&pScb->SCpnt->cmnd[4]); - if (copy_to_user - (user_area, pScb->buff_ptr, pScb->iDataSize)) { - printk - ("megaraid: Error copying ioctl return value to user buffer.\n"); + user_area = (char *)*((u32*)&pScb->SCpnt->cmnd[4]); + if (copy_to_user(user_area, pScb->buff_ptr, pScb->iDataSize)) { pScb->SCpnt->result = (DID_ERROR << 16); } - IO_LOCK_IRQ(megaCfg->host); - DRIVER_LOCK (megaCfg); + spin_lock_irq(megaCfg->host->host_lock); kfree (pScb->buff_ptr); pScb->buff_ptr = NULL; mega_cmd_done (megaCfg, pScb, pScb->SCpnt->result); mega_rundoneq (megaCfg); mega_runpendq (megaCfg); - DRIVER_UNLOCK (megaCfg); } megaCfg->flag &= ~IN_QUEUE; } - - DRIVER_UNLOCK (megaCfg); return 0; } /*---------------------------------------------------------------------- * Issue a blocking command to the controller *----------------------------------------------------------------------*/ -volatile static int internal_done_flag = 0; -volatile static int internal_done_errcode = 0; +static int internal_done_flag = 0; +static int internal_done_errcode = 0; static DECLARE_WAIT_QUEUE_HEAD (internal_wait); @@ -3673,30 +2892,31 @@ /* shouldn't be used, but included for completeness */ -int megaraid_command (Scsi_Cmnd * SCpnt) +static int megaraid_command (Scsi_Cmnd * SCpnt) { internal_done_flag = 0; - /* Queue command, and wait until it has completed */ megaraid_queue (SCpnt, internal_done); - - while (!internal_done_flag) { - interruptible_sleep_on (&internal_wait); - } - + wait_event(internal_wait, internal_done_flag); return internal_done_errcode; } /*--------------------------------------------------------------------- * Abort a previous SCSI request *---------------------------------------------------------------------*/ -int megaraid_abort (Scsi_Cmnd * SCpnt) +static int megaraid_abort(Scsi_Cmnd * SCpnt) { mega_host_config *megaCfg; + struct Scsi_Host *host; int rc; /*, idx; */ mega_scb *pScb; + unsigned long flags; - rc = SCSI_ABORT_NOT_RUNNING; + host = SCpnt->host; + + spin_lock_irqsave(host->host_lock, flags); + + rc = SUCCESS; megaCfg = (mega_host_config *) SCpnt->host->hostdata; @@ -3705,9 +2925,7 @@ for (pScb = megaCfg->qPendingH; pScb; pScb = pScb->next) { if (pScb->SCpnt == SCpnt) { /* Found an aborting command */ -#if DEBUG showMbox (pScb); -#endif /* * If the command is queued to be issued to the firmware, abort the scsi cmd, @@ -3724,10 +2942,10 @@ switch (pScb->state) { case SCB_ABORTED: /* Already aborted */ - rc = SCSI_ABORT_SNOOZE; + rc = SUCCESS; break; case SCB_ISSUED: /* Waiting on ISR result */ - rc = SCSI_ABORT_NOT_RUNNING; + rc = SUCCESS; pScb->state = SCB_ABORTED; break; case SCB_ACTIVE: /* still on the pending queue */ @@ -3744,12 +2962,11 @@ megaCfg->qCompletedT->host_scribble = (unsigned char *) NULL; megaCfg->qCcnt++; - rc = SCSI_ABORT_SUCCESS; + rc = SUCCESS; break; default: - printk - ("megaraid_abort: unknown command state!!\n"); - rc = SCSI_ABORT_NOT_RUNNING; + printk(KERN_ERR "megaraid_abort: unknown command state!!\n"); + rc = FAILED; break; } break; @@ -3781,6 +2998,7 @@ } mega_rundoneq (megaCfg); + spin_unlock_irqrestore(host->host_lock, flags); return rc; } @@ -3788,22 +3006,22 @@ * Reset a previous SCSI request *---------------------------------------------------------------------*/ -int megaraid_reset (Scsi_Cmnd * SCpnt, unsigned int rstflags) +static int megaraid_host_reset(Scsi_Cmnd * SCpnt) { mega_host_config *megaCfg; int idx; - int rc; mega_scb *pScb; + unsigned long flags; + struct Scsi_Host *host = SCpnt->host; - rc = SCSI_RESET_NOT_RUNNING; - megaCfg = (mega_host_config *) SCpnt->host->hostdata; + megaCfg = (mega_host_config *) host->hostdata; + spin_lock_irqsave(host->host_lock, flags); megaCfg->flag |= IN_RESET; - printk - ("megaraid_RESET: %.08lx cmd=%.02x , flag = %x\n", + printk("megaraid_RESET: %.08lx cmd=%.02x \n", SCpnt->serial_number, SCpnt->cmnd[0], SCpnt->channel, - SCpnt->target, SCpnt->lun, rstflags); + SCpnt->target, SCpnt->lun); TRACE (("RESET: %.08lx %.02x <%d.%d.%d>\n", SCpnt->serial_number, SCpnt->cmnd[0], SCpnt->channel, @@ -3826,7 +3044,8 @@ megaCfg->flag &= ~IN_RESET; mega_rundoneq (megaCfg); - return rc; + spin_unlock_irqrestore(host->host_lock, flags); + return SUCCESS; } #ifdef CONFIG_PROC_FS @@ -3974,42 +3193,10 @@ return count; } -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0) /*0x20300 */ #define CREATE_READ_PROC(string, fxn) create_proc_read_entry(string, \ S_IRUSR | S_IFREG,\ controller_proc_dir_entry,\ fxn, megaCfg) -#else -#define CREATE_READ_PROC(string, fxn) create_proc_read_entry(string,S_IRUSR | S_IFREG, controller_proc_dir_entry, fxn, megaCfg) - -static struct proc_dir_entry * -create_proc_read_entry (const char *string, - int mode, - struct proc_dir_entry *parent, - read_proc_t * fxn, mega_host_config * megaCfg) -{ - struct proc_dir_entry *temp = NULL; - - temp = kmalloc (sizeof (struct proc_dir_entry), GFP_KERNEL); - if (!temp) - return NULL; - memset (temp, 0, sizeof (struct proc_dir_entry)); - - if ((temp->name = kmalloc (strlen (string) + 1, GFP_KERNEL)) == NULL) { - kfree (temp); - return NULL; - } - - strcpy ((char *) temp->name, string); - temp->namelen = strlen (string); - temp->mode = mode; /*S_IFREG | S_IRUSR */ ; - temp->data = (void *) megaCfg; - temp->read_proc = fxn; - proc_register (parent, temp); - return temp; -} -#endif - static void mega_create_proc_entry (int index, struct proc_dir_entry *parent) { u_char string[64] = { 0 }; @@ -4018,30 +3205,36 @@ sprintf (string, "%d", index); -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0) /*0x20300 */ - controller_proc_dir_entry = - megaCfg->controller_proc_dir_entry = proc_mkdir (string, parent); -#else - controller_proc_dir_entry = - megaCfg->controller_proc_dir_entry = - create_proc_entry (string, S_IFDIR | S_IRUGO | S_IXUGO, parent); -#endif + controller_proc_dir_entry = megaCfg->controller_proc_dir_entry = proc_mkdir (string, parent); if (!controller_proc_dir_entry) printk ("\nmegaraid: proc_mkdir failed\n"); else { - megaCfg->proc_read = - CREATE_READ_PROC ("config", proc_read_config); - megaCfg->proc_status = - CREATE_READ_PROC ("status", proc_read_status); + megaCfg->proc_read = CREATE_READ_PROC ("config", proc_read_config); + megaCfg->proc_status = CREATE_READ_PROC ("status", proc_read_status); megaCfg->proc_stat = CREATE_READ_PROC ("stat", proc_read_stat); - megaCfg->proc_mbox = - CREATE_READ_PROC ("mailbox", proc_read_mbox); + megaCfg->proc_mbox = CREATE_READ_PROC ("mailbox", proc_read_mbox); } } #endif /* CONFIG_PROC_FS */ + +/*--------------------------------------------------------- + * Convert capacity to cylinders + * accounting for the fact capacity could be a 64 bit value + *---------------------------------------------------------- + */ +static inline u32 cap_to_cyls(sector_t capacity, u32 divisor) +{ +#ifdef CONFIG_LBD + do_div(capacity, divisor); +#else + capacity /= divisor; +#endif + return (u32) capacity; +} + /*------------------------------------------------------------- * Return the disk geometry for a particular disk * Input: @@ -4052,59 +3245,34 @@ * geom[1] = sectors * geom[2] = cylinders *-------------------------------------------------------------*/ -int megaraid_biosparam (struct scsi_device *sdev, struct block_device *bdev, +static int megaraid_biosparam (struct scsi_device *sdev, struct block_device *bdev, sector_t capacity, int *geom) { - int heads, sectors, cylinders; - mega_host_config *megaCfg; - - /* Get pointer to host config structure */ - megaCfg = (mega_host_config *) sdev->host->hostdata; + int rv = 0; + int heads = 64; + int sectors = 32; if( IS_RAID_CH(sdev->channel)) { - /* Default heads (64) & sectors (32) */ - heads = 64; - sectors = 32; - cylinders = (unsigned long)capacity >> 11; - - /* Handle extended translation size for logical drives > 1Gb */ - if (capacity >= 0x200000) { - heads = 255; - sectors = 63; - cylinders = (unsigned long)capacity / (heads * sectors); - } - - /* return result */ - geom[0] = heads; - geom[1] = sectors; - geom[2] = cylinders; - } - else { - if( mega_partsize(bdev, capacity, geom) == 0 ) return 0; - - printk(KERN_WARNING - "megaraid: invalid partition on this disk on channel %d\n", - sdev->channel); - - /* Default heads (64) & sectors (32) */ - heads = 64; - sectors = 32; - cylinders = capacity >> 11; - /* Handle extended translation size for logical drives > 1Gb */ if (capacity >= 0x200000) { heads = 255; sectors = 63; - cylinders = (unsigned long)capacity / (heads * sectors); } - /* return result */ + /* partition size based on defaults */ geom[0] = heads; geom[1] = sectors; - geom[2] = cylinders; + geom[2] = cap_to_cyls(capacity, heads * sectors); /* cylinders */ + } else { + rv = mega_partsize(bdev, capacity, geom); } - return 0; + if (rv != 0) { + printk(KERN_WARNING + "megaraid: invalid partition on this disk on channel %d\n", + sdev->channel); + } + return rv; } /* @@ -4121,50 +3289,42 @@ mega_partsize(struct block_device *bdev, sector_t capacity, int *geom) { struct partition *p, *largest = NULL; - int i, largest_cyl; - int heads, cyls, sectors; - unsigned char *buf; - - if (!(buf = scsi_bios_ptable(bdev))) - return -1; - - if( *(unsigned short *)(buf + 64) == 0xAA55 ) { - - for( largest_cyl = -1, p = (struct partition *)buf, - i = 0; i < 4; ++i, ++p) { - - if (!p->sys_ind) continue; - - cyls = p->end_cyl + ((p->end_sector & 0xc0) << 2); - - if(cyls >= largest_cyl) { - largest_cyl = cyls; - largest = p; + int i, cyls, largest_cyl; + int rv = -1; + unsigned char *buf = scsi_bios_ptable(bdev); + + if (buf) { + if( *(unsigned short *)(buf + 64) == 0xAA55 ) { + for( largest_cyl = -1, p = (struct partition *)buf, + i = 0; i < 4; ++i, ++p) { + + if (!p->sys_ind) continue; + + cyls = p->end_cyl + ((p->end_sector & 0xc0) << 2); + + if(cyls >= largest_cyl) { + largest_cyl = cyls; + largest = p; + } } } - } - - if (largest) { - heads = largest->end_head + 1; - sectors = largest->end_sector & 0x3f; - - if (heads == 0 || sectors == 0) { - kfree(buf); - return -1; + if (largest) { + int heads = largest->end_head + 1; + int sectors = largest->end_sector & 0x3f; + + if (heads != 0 && sectors != 0) { + geom[0] = heads; + geom[1] = sectors; + geom[2] = cap_to_cyls(capacity, heads * sectors); + rv = 0; + } + } - - cyls = (unsigned long)capacity/(heads * sectors); - - geom[0] = heads; - geom[1] = sectors; - geom[2] = cyls; - + kfree(buf); - return 0; } - - kfree(buf); - return -1; + + return rv; } @@ -4228,7 +3388,6 @@ * and the mid-layer operations are not connected with this flag. */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) megacfg->scbList[idx].sgList = pci_alloc_consistent (megacfg->dev, sizeof (mega_64sglist) * MAX_SGLIST, @@ -4237,9 +3396,6 @@ megacfg->scbList[idx].sg64List = (mega_64sglist *) megacfg->scbList[idx].sgList; -#else - megacfg->scbList[idx].sgList = kmalloc (sizeof (mega_sglist) * MAX_SGLIST, GFP_ATOMIC | GFP_DMA); -#endif if (megacfg->scbList[idx].sgList == NULL) { printk (KERN_WARNING @@ -4247,20 +3403,13 @@ mega_freeSgList (megacfg); return -1; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - megacfg->scbList[idx].pthru = pci_alloc_consistent (megacfg->dev, - sizeof (mega_passthru), - &(megacfg->scbList[idx]. - dma_passthruhandle64)); + megacfg->scbList[idx].pthru = pci_alloc_consistent (megacfg->dev, sizeof (mega_passthru), &(megacfg->scbList[idx].dma_passthruhandle64)); if (megacfg->scbList[idx].pthru == NULL) { - printk (KERN_WARNING - "Can't allocate passthru for id %d\n", idx); + printk (KERN_WARNING "Can't allocate passthru for id %d\n", idx); } - megacfg->scbList[idx].epthru = - pci_alloc_consistent( - megacfg->dev, sizeof(mega_ext_passthru), + megacfg->scbList[idx].epthru = pci_alloc_consistent(megacfg->dev, sizeof(mega_ext_passthru), &(megacfg->scbList[idx].dma_ext_passthruhandle64) ); @@ -4272,16 +3421,12 @@ * Allocate a 256 Byte Bounce Buffer for handling INQ/RD_CAPA */ megacfg->scbList[idx].bounce_buffer = pci_alloc_consistent (megacfg->dev, - 256, - &(megacfg->scbList[idx]. - dma_bounce_buffer)); + 256, &(megacfg->scbList[idx].dma_bounce_buffer)); if (!megacfg->scbList[idx].bounce_buffer) - printk - ("megaraid: allocation for bounce buffer failed\n"); + printk(KERN_ERR "megaraid: allocation for bounce buffer failed\n"); megacfg->scbList[idx].dma_type = M_RD_DMA_TYPE_NONE; -#endif if (idx < MAX_COMMANDS) { /* @@ -4289,8 +3434,7 @@ * lock not required since we are loading the driver, so no * commands possible right now. */ - enq_scb_freelist (megacfg, &megacfg->scbList[idx], - NO_LOCK, INTR_ENB); + enq_scb_freelist (megacfg, &megacfg->scbList[idx], NO_LOCK, INTR_ENB); } } @@ -4338,7 +3482,6 @@ */ static int megadev_open (struct inode *inode, struct file *filep) { - MOD_INC_USE_COUNT; return 0; /* success */ } @@ -4350,9 +3493,9 @@ /* * We do not allow parallel ioctls to the driver as of now. */ - down (&mimd_entry_mtx); + down(&mimd_entry_mtx); ret = megadev_ioctl (inode, filep, cmd, arg); - up (&mimd_entry_mtx); + up(&mimd_entry_mtx); return ret; @@ -4368,22 +3511,18 @@ int nadap = numCtlrs; u8 opcode; u32 outlen; - int ret; + int ret = 0; u8 subopcode; Scsi_Cmnd *scsicmd; struct Scsi_Host *shpnt; char *uaddr; struct uioctl_t *uioc; - dma_addr_t dma_addr; - u32 length; + dma_addr_t dma_addr; + u32 length; mega_host_config *megacfg = NULL; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) /* 0x020400 */ struct pci_dev pdev; struct pci_dev *pdevp = &pdev; -#else - char *pdevp = NULL; -#endif - IO_LOCK_T; + unsigned long io_flags; if (!inode) return -EINVAL; @@ -4394,10 +3533,6 @@ /* * Get the user ioctl structure */ - ret = verify_area (VERIFY_WRITE, (char *) arg, sizeof (struct uioctl_t)); - - if (ret) - return ret; if(copy_from_user (&ioc, (char *) arg, sizeof (struct uioctl_t))) return -EFAULT; @@ -4442,24 +3577,17 @@ adapno = GETADAP (adapno); if (adapno >= numCtlrs) - return (-ENODEV); - - ret = verify_area (VERIFY_WRITE, - ioc.data, - sizeof (struct mcontroller)); - if (ret) - return ret; + return -ENODEV; /* * Copy struct mcontroller to user area */ - copy_to_user (ioc.data, - mcontroller + adapno, - sizeof (struct mcontroller)); + if(copy_to_user(ioc.data, mcontroller + adapno, sizeof (struct mcontroller))) + return -EFAULT; return 0; default: - return (-EINVAL); + return -EINVAL; } /* inner switch */ break; @@ -4500,49 +3628,28 @@ outlen = ioc.outlen; inlen = ioc.inlen; - if(outlen) { - ret = verify_area(VERIFY_WRITE, (char *)ioc.ui.fcs.buffer, length); - if (ret) return ret; - } - if(inlen) { - ret = verify_area(VERIFY_READ, (char *) ioc.ui.fcs.buffer, length); - if (ret) return ret; - } - /* * Find this host */ shpnt = megaCtlrs[adapno]->host; if(shpnt == NULL) return -ENODEV; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) scsicmd = (Scsi_Cmnd *)kmalloc(sizeof(Scsi_Cmnd), GFP_KERNEL|GFP_DMA); -#else - scsicmd = (Scsi_Cmnd *)scsi_init_malloc(sizeof(Scsi_Cmnd), - GFP_ATOMIC | GFP_DMA); -#endif - if(scsicmd == NULL) return -ENOMEM; + if(scsicmd == NULL) + return -ENOMEM; memset(scsicmd, 0, sizeof(Scsi_Cmnd)); scsicmd->host = shpnt; if( outlen || inlen ) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) pdevp = &pdev; memcpy(pdevp, megacfg->dev, sizeof(struct pci_dev)); pdevp->dma_mask = 0xffffffff; -#else - pdevp = NULL; -#endif - kvaddr = dma_alloc_consistent(pdevp, length, &dma_addr); + kvaddr = pci_alloc_consistent(pdevp, length, &dma_addr); if( kvaddr == NULL ) { printk(KERN_WARNING "megaraid:allocation failed\n"); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) /*0x20400 */ kfree(scsicmd); -#else - scsi_init_free((char *)scsicmd, sizeof(Scsi_Cmnd)); -#endif return -ENOMEM; } @@ -4559,10 +3666,10 @@ init_MUTEX_LOCKED(&mimd_ioctl_sem); - IO_LOCK(shpnt); + spin_lock_irqsave(shpnt->host_lock, io_flags); megaraid_queue(scsicmd, megadev_ioctl_done); - IO_UNLOCK(shpnt); + spin_unlock_irqrestore(shpnt->host_lock, io_flags); down(&mimd_ioctl_sem); @@ -4580,17 +3687,14 @@ } else { put_user(1, &uioc->mbox[16]); /* numstatus */ /* status */ + put_user (scsicmd->result, &uioc->mbox[17]); } if (kvaddr) { - dma_free_consistent(pdevp, length, kvaddr, dma_addr); + pci_free_consistent(pdevp, length, kvaddr, dma_addr); } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) /*0x20400 */ kfree (scsicmd); -#else - scsi_init_free((char *)scsicmd, sizeof(Scsi_Cmnd)); -#endif /* restore the user address */ ioc.ui.fcs.buffer = uaddr; @@ -4605,7 +3709,7 @@ adapno = GETADAP (adapno); if (adapno >= numCtlrs) - return (-ENODEV); + return -ENODEV; /* save the user address */ uaddr = ioc.data; @@ -4613,16 +3717,7 @@ inlen = ioc.inlen; if ((outlen >= IOCTL_MAX_DATALEN) || (inlen >= IOCTL_MAX_DATALEN)) - return (-EINVAL); - - if (outlen) { - ret = verify_area (VERIFY_WRITE, ioc.data, outlen); - if (ret) return ret; - } - if (inlen) { - ret = verify_area (VERIFY_READ, ioc.data, inlen); - if (ret) return ret; - } + return -EINVAL; /* * Find this host @@ -4637,7 +3732,6 @@ if( ioc.mbox[0] == FC_DEL_LOGDRV && ioc.mbox[2] == OP_DEL_LOGDRV ) { if( !megacfg->support_random_del ) { - printk("megaraid: logdrv delete on non supporting f/w.\n"); return -EINVAL; } @@ -4652,37 +3746,25 @@ return ret; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) scsicmd = (Scsi_Cmnd *)kmalloc(sizeof(Scsi_Cmnd), GFP_KERNEL|GFP_DMA); -#else - scsicmd = (Scsi_Cmnd *)scsi_init_malloc(sizeof(Scsi_Cmnd), - GFP_ATOMIC | GFP_DMA); -#endif - if(scsicmd == NULL) return -ENOMEM; + if(scsicmd == NULL) + return -ENOMEM; memset(scsicmd, 0, sizeof(Scsi_Cmnd)); scsicmd->host = shpnt; if (outlen || inlen) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) pdevp = &pdev; memcpy(pdevp, megacfg->dev, sizeof(struct pci_dev)); pdevp->dma_mask = 0xffffffff; -#else - pdevp = NULL; -#endif /* * Allocate a page of kernel space. */ - kvaddr = dma_alloc_consistent(pdevp, PAGE_SIZE, &dma_addr); + kvaddr = pci_alloc_consistent(pdevp, PAGE_SIZE, &dma_addr); if( kvaddr == NULL ) { printk (KERN_WARNING "megaraid:allocation failed\n"); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) /*0x20400 */ kfree(scsicmd); -#else - scsi_init_free((char *)scsicmd, sizeof(Scsi_Cmnd)); -#endif return -ENOMEM; } @@ -4703,10 +3785,10 @@ init_MUTEX_LOCKED (&mimd_ioctl_sem); - IO_LOCK(shpnt); + spin_lock_irqsave(shpnt->host_lock, io_flags); megaraid_queue (scsicmd, megadev_ioctl_done); - - IO_UNLOCK(shpnt); + spin_unlock_irqrestore(shpnt->host_lock, io_flags); + down (&mimd_ioctl_sem); if (!scsicmd->result && outlen) { @@ -4730,14 +3812,10 @@ } if (kvaddr) { - dma_free_consistent(pdevp, PAGE_SIZE, kvaddr, dma_addr ); + pci_free_consistent(pdevp, PAGE_SIZE, kvaddr, dma_addr ); } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) kfree (scsicmd); -#else - scsi_init_free((char *)scsicmd, sizeof(Scsi_Cmnd)); -#endif /* restore user pointer */ ioc.data = uaddr; @@ -4752,14 +3830,12 @@ return 0; } -static void -megadev_ioctl_done(Scsi_Cmnd *sc) +static void megadev_ioctl_done(Scsi_Cmnd *sc) { up (&mimd_ioctl_sem); } -static mega_scb * -megadev_doioctl (mega_host_config * megacfg, Scsi_Cmnd * sc) +static mega_scb *megadev_doioctl (mega_host_config * megacfg, Scsi_Cmnd * sc) { u8 cmd; struct uioctl_t *ioc = NULL; @@ -4792,14 +3868,9 @@ /* * prepare the SCB with information from the user ioctl structure */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) pthru = scb->pthru; -#else - pthru = &scb->pthru; -#endif memcpy (pthru, &ioc->pthru, sizeof (mega_passthru)); mboxpthru = (struct mbox_passthru *) scb->mboxData; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) if (megacfg->flag & BOARD_64BIT) { /* This is just a sample with one element * This if executes onlu on 2.4 kernels @@ -4822,14 +3893,6 @@ pthru->numsgelements = 0; } -#else - { - mboxpthru->dataxferaddr = virt_to_bus (&scb->pthru); - pthru->dataxferaddr = virt_to_bus (ioc->data); - pthru->numsgelements = 0; - } -#endif - pthru->reqsenselen = 14; break; @@ -4852,18 +3915,12 @@ return scb; } -static int -megadev_close (struct inode *inode, struct file *filep) +static int megadev_close (struct inode *inode, struct file *filep) { -#ifdef MODULE - MOD_DEC_USE_COUNT; -#endif return 0; } - -static int -mega_support_ext_cdb(mega_host_config *this_hba) +static int mega_support_ext_cdb(mega_host_config *this_hba) { mega_mailbox *mboxpnt; unsigned char mbox[16]; @@ -4888,8 +3945,8 @@ * Find out if this controller supports random deletion and addition of * logical drives */ -static int -mega_support_random_del(mega_host_config *this_hba) + +static int mega_support_random_del(mega_host_config *this_hba) { mega_mailbox *mboxpnt; unsigned char mbox[16]; @@ -4910,11 +3967,10 @@ return !ret; } -static int -mega_del_logdrv(mega_host_config *this_hba, int logdrv) +static int mega_del_logdrv(mega_host_config *this_hba, int logdrv) { int rval; - IO_LOCK_T; + unsigned long flags; DECLARE_WAIT_QUEUE_HEAD(wq); mega_scb *scbp; @@ -4922,16 +3978,15 @@ * Stop sending commands to the controller, queue them internally. * When deletion is complete, ISR will flush the queue. */ - IO_LOCK(this_hba->host); + spin_lock_irqsave(this_hba->host->host_lock, flags); this_hba->quiescent = 1; - IO_UNLOCK(this_hba->host); + spin_unlock_irqrestore(this_hba->host->host_lock, flags); - while( this_hba->qPcnt ) { - sleep_on_timeout( &wq, 1*HZ ); /* sleep for 1s */ - } + wait_event_interruptible_timeout(wq, !this_hba->qPcnt, HZ); + rval = mega_do_del_logdrv(this_hba, logdrv); - IO_LOCK(this_hba->host); + spin_lock_irqsave(this_hba->host->host_lock, flags); /* * Attach the internal queue to the pending queue */ @@ -4965,25 +4020,19 @@ */ if( this_hba->read_ldidmap) { for( scbp = this_hba->qPendingH; scbp; scbp = scbp->next ) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) if( scbp->pthru->logdrv < 0x80 ) scbp->pthru->logdrv += 0x80; -#else - if( scbp->pthru.logdrv < 0x80 ) - scbp->pthru.logdrv += 0x80; -#endif } } this_hba->quiescent = 0; - IO_UNLOCK(this_hba->host); + spin_unlock_irqrestore(this_hba->host->host_lock, flags); return rval; } -static int -mega_do_del_logdrv(mega_host_config *this_hba, int logdrv) +static int mega_do_del_logdrv(mega_host_config *this_hba, int logdrv) { mega_mailbox *mboxpnt; unsigned char mbox[16]; @@ -5001,12 +4050,11 @@ /* log this event */ if( rval != 0 ) { - printk("megaraid: Attempt to delete logical drive %d failed.", - logdrv); + printk(KERN_WARNING "megaraid: Attempt to delete logical drive %d failed.", logdrv); return rval; } - printk("megaraid: logical drive %d deleted.\n", logdrv); + printk(KERN_INFO "megaraid: logical drive %d deleted.\n", logdrv); /* * After deleting first logical drive, the logical drives must be @@ -5017,100 +4065,26 @@ return rval; } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) -void * -dma_alloc_consistent(void *dev, size_t size, dma_addr_t *dma_addr) -{ - void *_tv; - int npages; - int order = 0; - - /* - * How many pages application needs - */ - npages = size / PAGE_SIZE; - - /* Do we need one more page */ - if(size % PAGE_SIZE) - npages++; - - order = mega_get_order(npages); - - _tv = (void *)__get_free_pages(GFP_DMA, order); - - if( _tv != NULL ) { - memset(_tv, 0, size); - *(dma_addr) = virt_to_bus(_tv); - } - return _tv; -} - -/* - * int mega_get_order(int) - * - * returns the order to be used as 2nd argument to __get_free_pages() - which - * return pages equal to pow(2, order) - AM - */ -int -mega_get_order(int n) -{ - int i = 0; - - while( pow_2(i++) < n ) - ; /* null statement */ - - return i-1; -} - -/* - * int pow_2(int) - * - * calculates pow(2, i) - */ -int -pow_2(int i) -{ - unsigned int v = 1; - - while(i--) - v <<= 1; - - return v; -} - -void -dma_free_consistent(void *dev, size_t size, void *vaddr, dma_addr_t dma_addr) -{ - int npages; - int order = 0; - - npages = size / PAGE_SIZE; - - if(size % PAGE_SIZE) - npages++; - - if (npages == 1) - order = 0; - else if (npages == 2) - order = 1; - else if (npages <= 4) - order = 2; - else - order = 3; - - free_pages((unsigned long)vaddr, order); - -} -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) -static -#endif /* LINUX VERSION 2.4.XX */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) || defined(MODULE) -Scsi_Host_Template driver_template = MEGARAID; +static Scsi_Host_Template driver_template = { + name: "MegaRAID", /* Driver Name */ + proc_info: megaraid_proc_info, /* /proc driver info */ + detect: megaraid_detect, /* Detect Host Adapter */ + release: megaraid_release, /* Release Host Adapter */ + info: megaraid_info, /* Driver Info Function */ + command: megaraid_command, /* Command Function */ + queuecommand: megaraid_queue, /* Queue Command Function */ + eh_abort_handler: megaraid_abort, /* Abort Command Function */ + eh_host_reset_handler: megaraid_host_reset, /* Reset Command Function */ + bios_param: megaraid_biosparam, /* Disk BIOS Parameters */ + can_queue: MAX_COMMANDS, /* Can Queue */ + this_id: 7, /* HBA Target ID */ + sg_tablesize: MAX_SGLIST, /* Scatter/Gather Table Size */ + cmd_per_lun: MAX_CMD_PER_LUN, /* SCSI Commands per LUN */ + present: 0, /* Present */ + unchecked_isa_dma: 0, /* Default Unchecked ISA DMA */ + use_clustering: ENABLE_CLUSTERING, /* Enable Clustering */ + highmem_io: 1 +}; #include "scsi_module.c" -#endif /* LINUX VERSION 2.4.XX || MODULE */ - -/* vi: set ts=4: */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/scsi/megaraid.h linux.2.5.47-ac4/drivers/scsi/megaraid.h --- linux.2.5.47/drivers/scsi/megaraid.h 2002-11-11 16:39:10.000000000 +0000 +++ linux.2.5.47-ac4/drivers/scsi/megaraid.h 2002-11-12 15:34:26.000000000 +0000 @@ -1,10 +1,6 @@ #ifndef __MEGARAID_H__ #define __MEGARAID_H__ -#ifndef LINUX_VERSION_CODE -#include -#endif - /* * For state flag. Do not use LSB(8 bits) which are * reserved for storing info about channels. @@ -13,17 +9,17 @@ #define IN_ABORT 0x40000000L #define IN_RESET 0x20000000L #define IN_QUEUE 0x10000000L -#define BOARD_QUARTZ 0x08000000L +#define BOARD_QUARTZ 0x08000000L #define BOARD_40LD 0x04000000L #define BOARD_64BIT 0x02000000L -#define SCB_FREE 0x0 -#define SCB_ACTIVE 0x1 -#define SCB_WAITQ 0x2 -#define SCB_ISSUED 0x3 -#define SCB_COMPLETE 0x4 -#define SCB_ABORTED 0x5 -#define SCB_RESET 0x6 +#define SCB_FREE 0x0 +#define SCB_ACTIVE 0x1 +#define SCB_WAITQ 0x2 +#define SCB_ISSUED 0x3 +#define SCB_COMPLETE 0x4 +#define SCB_ABORTED 0x5 +#define SCB_RESET 0x6 #define M_RD_CRLFSTR "\n" #define M_RD_IOCTL_CMD 0x80 @@ -180,52 +176,6 @@ #define AMI_SIGNATURE_471 0xCCCC #define AMI_64BIT_SIGNATURE 0x0299 -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0) /*0x20100 */ -#define MEGARAID \ - { NULL, /* Next */\ - NULL, /* Usage Count Pointer */\ - NULL, /* proc Directory Entry */\ - megaraid_proc_info, /* proc Info Function */\ - "MegaRAID", /* Driver Name */\ - megaraid_detect, /* Detect Host Adapter */\ - megaraid_release, /* Release Host Adapter */\ - megaraid_info, /* Driver Info Function */\ - megaraid_command, /* Command Function */\ - megaraid_queue, /* Queue Command Function */\ - megaraid_abort, /* Abort Command Function */\ - megaraid_reset, /* Reset Command Function */\ - NULL, /* Slave Attach Function */\ - megaraid_biosparam, /* Disk BIOS Parameters */\ - MAX_COMMANDS, /* # of cmds that can be\ - outstanding at any time */\ - 7, /* HBA Target ID */\ - MAX_SGLIST, /* Scatter/Gather Table Size */\ - MAX_CMD_PER_LUN, /* SCSI Commands per LUN */\ - 0, /* Present */\ - 0, /* Default Unchecked ISA DMA */\ - ENABLE_CLUSTERING } /* Enable Clustering */ -#else -#define MEGARAID \ - {\ - name: "MegaRAID", /* Driver Name */\ - proc_info: megaraid_proc_info, /* /proc driver info */\ - detect: megaraid_detect, /* Detect Host Adapter */\ - release: megaraid_release, /* Release Host Adapter */\ - info: megaraid_info, /* Driver Info Function */\ - command: megaraid_command, /* Command Function */\ - queuecommand: megaraid_queue, /* Queue Command Function */\ - bios_param: megaraid_biosparam, /* Disk BIOS Parameters */\ - can_queue: MAX_COMMANDS, /* Can Queue */\ - this_id: 7, /* HBA Target ID */\ - sg_tablesize: MAX_SGLIST, /* Scatter/Gather Table Size */\ - cmd_per_lun: MAX_CMD_PER_LUN, /* SCSI Commands per LUN */\ - present: 0, /* Present */\ - unchecked_isa_dma: 0, /* Default Unchecked ISA DMA */\ - use_clustering: ENABLE_CLUSTERING, /* Enable Clustering */\ - highmem_io: 1, \ - } -#endif - /*********************************************************************** * Structure Declarations for the Firmware supporting 40 Logical Drives * and 256 Physical Drives. @@ -941,16 +891,16 @@ * *================================================================ */ -const char *megaraid_info (struct Scsi_Host *); -int megaraid_detect (Scsi_Host_Template *); -int megaraid_release (struct Scsi_Host *); -int megaraid_command (Scsi_Cmnd *); -int megaraid_abort (Scsi_Cmnd *); -int megaraid_reset (Scsi_Cmnd *, unsigned int); -int megaraid_queue (Scsi_Cmnd *, void (*done) (Scsi_Cmnd *)); -int megaraid_biosparam (struct scsi_device *, struct block_device *, +static const char *megaraid_info (struct Scsi_Host *); +static int megaraid_detect (Scsi_Host_Template *); +static int megaraid_release (struct Scsi_Host *); +static int megaraid_command (Scsi_Cmnd *); +static int megaraid_abort (Scsi_Cmnd *); +static int megaraid_host_reset (Scsi_Cmnd *); +static int megaraid_queue (Scsi_Cmnd *, void (*done) (Scsi_Cmnd *)); +static int megaraid_biosparam (struct scsi_device *, struct block_device *, sector_t, int *); -int megaraid_proc_info (char *buffer, char **start, off_t offset, +static int megaraid_proc_info (char *buffer, char **start, off_t offset, int length, int hostno, int inout); static int megaIssueCmd (mega_host_config * megaCfg, u_char * mboxData, diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/scsi/NCR53c406a.c linux.2.5.47-ac4/drivers/scsi/NCR53c406a.c --- linux.2.5.47/drivers/scsi/NCR53c406a.c 2002-11-11 16:39:10.000000000 +0000 +++ linux.2.5.47-ac4/drivers/scsi/NCR53c406a.c 2002-11-12 15:35:48.000000000 +0000 @@ -55,7 +55,6 @@ #include #include "scsi.h" #include "hosts.h" -#include "NCR53c406a.h" /* ============================================================= */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/scsi/pcmcia/aha152x.c linux.2.5.47-ac4/drivers/scsi/pcmcia/aha152x.c --- linux.2.5.47/drivers/scsi/pcmcia/aha152x.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.47-ac4/drivers/scsi/pcmcia/aha152x.c 2002-11-03 01:31:31.000000000 +0000 @@ -0,0 +1,3928 @@ +/* aha152x.c -- Adaptec AHA-152x driver + * Author: Jürgen E. Fischer, fischer@norbit.de + * Copyright 1993-2000 Jürgen E. Fischer + * + * 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, 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. + * + * + * $Id: aha152x.c,v 2.5 2002/04/14 11:24:53 fischer Exp $ + * + * $Log: aha152x.c,v $ + * Revision 2.5 2002/04/14 11:24:53 fischer + * - isapnp support + * - abort fixed + * - 2.5 support + * + * Revision 2.4 2000/12/16 12:53:56 fischer + * - allow REQUEST SENSE to be queued + * - handle shared PCI interrupts + * + * Revision 2.3 2000/11/04 16:40:26 fischer + * - handle data overruns + * - extend timeout for data phases + * + * Revision 2.2 2000/08/08 19:54:53 fischer + * - minor changes + * + * Revision 2.1 2000/05/17 16:23:17 fischer + * - signature update + * - fix for data out w/o scatter gather + * + * Revision 2.0 1999/12/25 15:07:32 fischer + * - interrupt routine completly reworked + * - basic support for new eh code + * + * Revision 1.21 1999/11/10 23:46:36 fischer + * - default to synchronous operation + * - synchronous negotiation fixed + * - added timeout to loops + * - debugging output can be controlled through procfs + * + * Revision 1.20 1999/11/07 18:37:31 fischer + * - synchronous operation works + * - resid support for sg driver + * + * Revision 1.19 1999/11/02 22:39:59 fischer + * - moved leading comments to README.aha152x + * - new additional module parameters + * - updates for 2.3 + * - support for the Tripace TC1550 controller + * - interrupt handling changed + * + * Revision 1.18 1996/09/07 20:10:40 fischer + * - fixed can_queue handling (multiple outstanding commands working again) + * + * Revision 1.17 1996/08/17 16:05:14 fischer + * - biosparam improved + * - interrupt verification + * - updated documentation + * - cleanups + * + * Revision 1.16 1996/06/09 00:04:56 root + * - added configuration symbols for insmod (aha152x/aha152x1) + * + * Revision 1.15 1996/04/30 14:52:06 fischer + * - proc info fixed + * - support for extended translation for >1GB disks + * + * Revision 1.14 1996/01/17 15:11:20 fischer + * - fixed lockup in MESSAGE IN phase after reconnection + * + * Revision 1.13 1996/01/09 02:15:53 fischer + * - some cleanups + * - moved request_irq behind controller initialization + * (to avoid spurious interrupts) + * + * Revision 1.12 1995/12/16 12:26:07 fischer + * - barrier()s added + * - configurable RESET delay added + * + * Revision 1.11 1995/12/06 21:18:35 fischer + * - some minor updates + * + * Revision 1.10 1995/07/22 19:18:45 fischer + * - support for 2 controllers + * - started synchronous data transfers (not working yet) + * + * Revision 1.9 1995/03/18 09:20:24 root + * - patches for PCMCIA and modules + * + * Revision 1.8 1995/01/21 22:07:19 root + * - snarf_region => request_region + * - aha152x_intr interface change + * + * Revision 1.7 1995/01/02 23:19:36 root + * - updated COMMAND_SIZE to cmd_len + * - changed sti() to restore_flags() + * - fixed some #ifdef which generated warnings + * + * Revision 1.6 1994/11/24 20:35:27 root + * - problem with odd number of bytes in fifo fixed + * + * Revision 1.5 1994/10/30 14:39:56 root + * - abort code fixed + * - debugging improved + * + * Revision 1.4 1994/09/12 11:33:01 root + * - irqaction to request_irq + * - abortion updated + * + * Revision 1.3 1994/08/04 13:53:05 root + * - updates for mid-level-driver changes + * - accept unexpected BUSFREE phase as error condition + * - parity check now configurable + * + * Revision 1.2 1994/07/03 12:56:36 root + * - cleaned up debugging code + * - more tweaking on reset delays + * - updated abort/reset code (pretty untested...) + * + * Revision 1.1 1994/05/28 21:18:49 root + * - update for mid-level interface change (abort-reset) + * - delays after resets adjusted for some slow devices + * + * Revision 1.0 1994/03/25 12:52:00 root + * - Fixed "more data than expected" problem + * - added new BIOS signatures + * + * Revision 0.102 1994/01/31 20:44:12 root + * - minor changes in insw/outsw handling + * + * Revision 0.101 1993/12/13 01:16:27 root + * - fixed STATUS phase (non-GOOD stati were dropped sometimes; + * fixes problems with CD-ROM sector size detection & media change) + * + * Revision 0.100 1993/12/10 16:58:47 root + * - fix for unsuccessful selections in case of non-continuous id assignments + * on the scsi bus. + * + * Revision 0.99 1993/10/24 16:19:59 root + * - fixed DATA IN (rare read errors gone) + * + * Revision 0.98 1993/10/17 12:54:44 root + * - fixed some recent fixes (shame on me) + * - moved initialization of scratch area to aha152x_queue + * + * Revision 0.97 1993/10/09 18:53:53 root + * - DATA IN fixed. Rarely left data in the fifo. + * + * Revision 0.96 1993/10/03 00:53:59 root + * - minor changes on DATA IN + * + * Revision 0.95 1993/09/24 10:36:01 root + * - change handling of MSGI after reselection + * - fixed sti/cli + * - minor changes + * + * Revision 0.94 1993/09/18 14:08:22 root + * - fixed bug in multiple outstanding command code + * - changed detection + * - support for kernel command line configuration + * - reset corrected + * - changed message handling + * + * Revision 0.93 1993/09/15 20:41:19 root + * - fixed bugs with multiple outstanding commands + * + * Revision 0.92 1993/09/13 02:46:33 root + * - multiple outstanding commands work (no problems with IBM drive) + * + * Revision 0.91 1993/09/12 20:51:46 root + * added multiple outstanding commands + * (some problem with this $%&? IBM device remain) + * + * Revision 0.9 1993/09/12 11:11:22 root + * - corrected auto-configuration + * - changed the auto-configuration (added some '#define's) + * - added support for dis-/reconnection + * + * Revision 0.8 1993/09/06 23:09:39 root + * - added support for the drive activity light + * - minor changes + * + * Revision 0.7 1993/09/05 14:30:15 root + * - improved phase detection + * - now using the new snarf_region code of 0.99pl13 + * + * Revision 0.6 1993/09/02 11:01:38 root + * first public release; added some signatures and biosparam() + * + * Revision 0.5 1993/08/30 10:23:30 root + * fixed timing problems with my IBM drive + * + * Revision 0.4 1993/08/29 14:06:52 root + * fixed some problems with timeouts due incomplete commands + * + * Revision 0.3 1993/08/28 15:55:03 root + * writing data works too. mounted and worked on a dos partition + * + * Revision 0.2 1993/08/27 22:42:07 root + * reading data works. Mounted a msdos partition. + * + * Revision 0.1 1993/08/25 13:38:30 root + * first "damn thing doesn't work" version + * + * Revision 0.0 1993/08/14 19:54:25 root + * empty function bodies; detect() works. + * + * + ************************************************************************** + + see README.aha152x for configuration details + + **************************************************************************/ + +#include + +#if defined(PCMCIA) +#undef MODULE +#endif + +#include +#include +#include +#include +#include +#include "scsi.h" +#include "hosts.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "aha152x.h" +#include +#include + +#include + +/* DEFINES */ + +/* For PCMCIA cards, always use AUTOCONF */ +#if defined(PCMCIA) || defined(MODULE) +#if !defined(AUTOCONF) +#define AUTOCONF +#endif +#endif + +#if !defined(AUTOCONF) && !defined(SETUP0) +#error define AUTOCONF or SETUP0 +#endif + +#if defined(AHA152X_DEBUG) +#define DEBUG_DEFAULT debug_eh + +#define DPRINTK(when,msgs...) \ + do { if(HOSTDATA(shpnt)->debug & (when)) printk(msgs); } while(0) + +#define DO_LOCK(flags) \ + do { \ + if(spin_is_locked(&QLOCK)) { \ + DPRINTK(debug_intr, DEBUG_LEAD "(%s:%d) already locked at %s:%d\n", CMDINFO(CURRENT_SC), __FUNCTION__, __LINE__, QLOCKER, QLOCKERL); \ + } \ + DPRINTK(debug_locks, DEBUG_LEAD "(%s:%d) locking\n", CMDINFO(CURRENT_SC), __FUNCTION__, __LINE__); \ + spin_lock_irqsave(&QLOCK,flags); \ + DPRINTK(debug_locks, DEBUG_LEAD "(%s:%d) locked\n", CMDINFO(CURRENT_SC), __FUNCTION__, __LINE__); \ + QLOCKER=__FUNCTION__; \ + QLOCKERL=__LINE__; \ + } while(0) + +#define DO_UNLOCK(flags) \ + do { \ + DPRINTK(debug_locks, DEBUG_LEAD "(%s:%d) unlocking (locked at %s:%d)\n", CMDINFO(CURRENT_SC), __FUNCTION__, __LINE__, QLOCKER, QLOCKERL); \ + spin_unlock_irqrestore(&QLOCK,flags); \ + DPRINTK(debug_locks, DEBUG_LEAD "(%s:%d) unlocked\n", CMDINFO(CURRENT_SC), __FUNCTION__, __LINE__); \ + QLOCKER="(not locked)"; \ + QLOCKERL=0; \ + } while(0) + +#else +#define DPRINTK(when,msgs...) +#define DO_LOCK(flags) spin_lock_irqsave(&QLOCK,flags) +#define DO_UNLOCK(flags) spin_unlock_irqrestore(&QLOCK,flags) +#endif + +#define LEAD "(scsi%d:%d:%d) " +#define WARN_LEAD KERN_WARNING LEAD +#define INFO_LEAD KERN_INFO LEAD +#define NOTE_LEAD KERN_NOTICE LEAD +#define ERR_LEAD KERN_ERR LEAD +#define DEBUG_LEAD KERN_DEBUG LEAD +#define CMDINFO(cmd) \ + (cmd) ? ((cmd)->host->host_no) : -1, \ + (cmd) ? ((cmd)->target & 0x0f) : -1, \ + (cmd) ? ((cmd)->lun & 0x07) : -1 + +#define DELAY_DEFAULT 1000 + +#if defined(PCMCIA) +#define IRQ_MIN 0 +#define IRQ_MAX 16 +#else +#define IRQ_MIN 9 +#if defined(__PPC) +#define IRQ_MAX (NR_IRQS-1) +#else +#define IRQ_MAX 12 +#endif +#endif + +enum { + not_issued = 0x0001, /* command not yet issued */ + selecting = 0x0002, /* target is beeing selected */ + identified = 0x0004, /* IDENTIFY was sent */ + disconnected = 0x0008, /* target disconnected */ + completed = 0x0010, /* target sent COMMAND COMPLETE */ + aborted = 0x0020, /* ABORT was sent */ + resetted = 0x0040, /* BUS DEVICE RESET was sent */ + spiordy = 0x0080, /* waiting for SPIORDY to raise */ + syncneg = 0x0100, /* synchronous negotiation in progress */ + aborting = 0x0200, /* ABORT is pending */ + resetting = 0x0400, /* BUS DEVICE RESET is pending */ +}; + +#if defined(MODULE) +MODULE_AUTHOR("Jürgen Fischer"); +MODULE_DESCRIPTION(AHA152X_REVID); +MODULE_LICENSE("GPL"); + +MODULE_PARM(io, "1-2i"); +MODULE_PARM_DESC(io,"base io address of controller"); +static int io[] = {0, 0}; + +MODULE_PARM(irq, "1-2i"); +MODULE_PARM_DESC(irq,"interrupt for controller"); +static int irq[] = {0, 0}; + +MODULE_PARM(scsiid, "1-2i"); +MODULE_PARM_DESC(scsiid,"scsi id of controller"); +static int scsiid[] = {7, 7}; + +MODULE_PARM(reconnect, "1-2i"); +MODULE_PARM_DESC(reconnect,"allow targets to disconnect"); +static int reconnect[] = {1, 1}; + +MODULE_PARM(parity, "1-2i"); +MODULE_PARM_DESC(parity,"use scsi parity"); +static int parity[] = {1, 1}; + +MODULE_PARM(sync, "1-2i"); +MODULE_PARM_DESC(sync,"use synchronous transfers"); +static int sync[] = {1, 1}; + +MODULE_PARM(delay, "1-2i"); +MODULE_PARM_DESC(delay,"scsi reset delay"); +static int delay[] = {DELAY_DEFAULT, DELAY_DEFAULT}; + +MODULE_PARM(exttrans, "1-2i"); +MODULE_PARM_DESC(exttrans,"use extended translation"); +static int exttrans[] = {0, 0}; + +#if !defined(AHA152X_DEBUG) +MODULE_PARM(aha152x, "1-8i"); +MODULE_PARM_DESC(aha152x, "parameters for first controller"); +static int aha152x[] = {0, 11, 7, 1, 1, 0, DELAY_DEFAULT, 0}; + +MODULE_PARM(aha152x1, "1-8i"); +MODULE_PARM_DESC(aha152x1, "parameters for second controller"); +static int aha152x1[] = {0, 11, 7, 1, 1, 0, DELAY_DEFAULT, 0}; +#else +MODULE_PARM(debug, "1-2i"); +MODULE_PARM_DESC(debug, "flags for driver debugging"); +static int debug[] = {DEBUG_DEFAULT, DEBUG_DEFAULT}; + +MODULE_PARM(aha152x, "1-9i"); +MODULE_PARM_DESC(aha152x, "parameters for first controller"); +static int aha152x[] = {0, 11, 7, 1, 1, 1, DELAY_DEFAULT, 0, DEBUG_DEFAULT}; + +MODULE_PARM(aha152x1, "1-9i"); +MODULE_PARM_DESC(aha152x1, "parameters for second controller"); +static int aha152x1[] = {0, 11, 7, 1, 1, 1, DELAY_DEFAULT, 0, DEBUG_DEFAULT}; +#endif /* !defined(AHA152X_DEBUG) */ + +#ifdef __ISAPNP__ +static struct isapnp_device_id id_table[] __devinitdata = { + { ISAPNP_DEVICE_SINGLE('A','D','P',0x1505, 'A','D','P',0x1505), }, + { ISAPNP_DEVICE_SINGLE_END, } +}; +MODULE_DEVICE_TABLE(isapnp, id_table); +#endif /* ISAPNP */ +#endif /* MODULE */ + +/* set by aha152x_setup according to the command line */ +static int setup_count = 0; +static int registered_count = 0; +static struct aha152x_setup { + int io_port; + int irq; + int scsiid; + int reconnect; + int parity; + int synchronous; + int delay; + int ext_trans; + int tc1550; +#if defined(AHA152X_DEBUG) + int debug; +#endif + char *conf; +} setup[2]; + +static struct Scsi_Host *aha152x_host[2]; + +/* + * internal states of the host + * + */ +enum aha152x_state { + idle=0, + unknown, + seldo, + seldi, + selto, + busfree, + msgo, + cmd, + msgi, + status, + datai, + datao, + parerr, + rsti, + maxstate +}; + +/* + * current state information of the host + * + */ +struct aha152x_hostdata { + Scsi_Cmnd *issue_SC; + /* pending commands to issue */ + + Scsi_Cmnd *current_SC; + /* current command on the bus */ + + Scsi_Cmnd *disconnected_SC; + /* commands that disconnected */ + + Scsi_Cmnd *done_SC; + /* command that was completed */ + + spinlock_t lock; + /* host lock */ + +#if defined(AHA152X_DEBUG) + char *locker; /* which function has the lock */ + int lockerl; /* where did it get it */ + + int debug; /* current debugging setting */ +#endif + +#if defined(AHA152X_STAT) + int total_commands; + int disconnections; + int busfree_without_any_action; + int busfree_without_old_command; + int busfree_without_new_command; + int busfree_without_done_command; + int busfree_with_check_condition; + int count[maxstate]; + int count_trans[maxstate]; + unsigned long time[maxstate]; +#endif + + int commands; /* current number of commands */ + + int reconnect; /* disconnection allowed */ + int parity; /* parity checking enabled */ + int synchronous; /* synchronous transferes enabled */ + int delay; /* reset out delay */ + int ext_trans; /* extended translation enabled */ + + int swint; /* software-interrupt was fired during detect() */ + int service; /* bh needs to be run */ + int in_intr; /* bh is running */ + + /* current state, + previous state, + last state different from current state */ + enum aha152x_state state, prevstate, laststate; + + int target; + /* reconnecting target */ + + unsigned char syncrate[8]; + /* current synchronous transfer agreements */ + + unsigned char syncneg[8]; + /* 0: no negotiation; + * 1: negotiation in progress; + * 2: negotiation completed + */ + + int cmd_i; + /* number of sent bytes of current command */ + + int msgi_len; + /* number of received message bytes */ + unsigned char msgi[256]; + /* received message bytes */ + + int msgo_i, msgo_len; + /* number of sent bytes and length of current messages */ + unsigned char msgo[256]; + /* pending messages */ + + int data_len; + /* number of sent/received bytes in dataphase */ + + unsigned long io_port0; + unsigned long io_port1; +}; + + +/* + * host specific command extension + * + */ +struct aha152x_scdata { + Scsi_Cmnd *next; /* next sc in queue */ + Scsi_Cmnd *done; /* done command */ + struct semaphore *sem; /* semaphore to block on */ +}; + + +/* access macros for hostdata */ + +#define HOSTDATA(shpnt) ((struct aha152x_hostdata *) &shpnt->hostdata) + +#define HOSTNO ((shpnt)->host_no) + +#define CURRENT_SC (HOSTDATA(shpnt)->current_SC) +#define DONE_SC (HOSTDATA(shpnt)->done_SC) +#define ISSUE_SC (HOSTDATA(shpnt)->issue_SC) +#define DISCONNECTED_SC (HOSTDATA(shpnt)->disconnected_SC) +#define QLOCK (HOSTDATA(shpnt)->lock) +#define QLOCKER (HOSTDATA(shpnt)->locker) +#define QLOCKERL (HOSTDATA(shpnt)->lockerl) + +#define STATE (HOSTDATA(shpnt)->state) +#define PREVSTATE (HOSTDATA(shpnt)->prevstate) +#define LASTSTATE (HOSTDATA(shpnt)->laststate) + +#define RECONN_TARGET (HOSTDATA(shpnt)->target) + +#define CMD_I (HOSTDATA(shpnt)->cmd_i) + +#define MSGO(i) (HOSTDATA(shpnt)->msgo[i]) +#define MSGO_I (HOSTDATA(shpnt)->msgo_i) +#define MSGOLEN (HOSTDATA(shpnt)->msgo_len) +#define ADDMSGO(x) (MSGOLEN<256 ? MSGO(MSGOLEN++)=x : aha152x_error(shpnt,"MSGO overflow")) + +#define MSGI(i) (HOSTDATA(shpnt)->msgi[i]) +#define MSGILEN (HOSTDATA(shpnt)->msgi_len) +#define ADDMSGI(x) (MSGILEN<256 ? MSGI(MSGILEN++)=x : aha152x_error(shpnt,"MSGI overflow")) + +#define DATA_LEN (HOSTDATA(shpnt)->data_len) + +#define SYNCRATE (HOSTDATA(shpnt)->syncrate[CURRENT_SC->target]) +#define SYNCNEG (HOSTDATA(shpnt)->syncneg[CURRENT_SC->target]) + +#define DELAY (HOSTDATA(shpnt)->delay) +#define EXT_TRANS (HOSTDATA(shpnt)->ext_trans) +#define TC1550 (HOSTDATA(shpnt)->tc1550) +#define RECONNECT (HOSTDATA(shpnt)->reconnect) +#define PARITY (HOSTDATA(shpnt)->parity) +#define SYNCHRONOUS (HOSTDATA(shpnt)->synchronous) + +#define HOSTIOPORT0 (HOSTDATA(shpnt)->io_port0) +#define HOSTIOPORT1 (HOSTDATA(shpnt)->io_port1) + +#define SCDATA(SCpnt) ((struct aha152x_scdata *) (SCpnt)->host_scribble) +#define SCNEXT(SCpnt) SCDATA(SCpnt)->next +#define SCDONE(SCpnt) SCDATA(SCpnt)->done +#define SCSEM(SCpnt) SCDATA(SCpnt)->sem + +#define SG_ADDRESS(buffer) ((char *) (page_address((buffer)->page)+(buffer)->offset)) + +/* state handling */ +static void seldi_run(struct Scsi_Host *shpnt); +static void seldo_run(struct Scsi_Host *shpnt); +static void selto_run(struct Scsi_Host *shpnt); +static void busfree_run(struct Scsi_Host *shpnt); + +static void msgo_init(struct Scsi_Host *shpnt); +static void msgo_run(struct Scsi_Host *shpnt); +static void msgo_end(struct Scsi_Host *shpnt); + +static void cmd_init(struct Scsi_Host *shpnt); +static void cmd_run(struct Scsi_Host *shpnt); +static void cmd_end(struct Scsi_Host *shpnt); + +static void datai_init(struct Scsi_Host *shpnt); +static void datai_run(struct Scsi_Host *shpnt); +static void datai_end(struct Scsi_Host *shpnt); + +static void datao_init(struct Scsi_Host *shpnt); +static void datao_run(struct Scsi_Host *shpnt); +static void datao_end(struct Scsi_Host *shpnt); + +static void status_run(struct Scsi_Host *shpnt); + +static void msgi_run(struct Scsi_Host *shpnt); +static void msgi_end(struct Scsi_Host *shpnt); + +static void parerr_run(struct Scsi_Host *shpnt); +static void rsti_run(struct Scsi_Host *shpnt); + +static void is_complete(struct Scsi_Host *shpnt); + +/* + * driver states + * + */ +static struct { + char *name; + void (*init)(struct Scsi_Host *); + void (*run)(struct Scsi_Host *); + void (*end)(struct Scsi_Host *); + int spio; +} states[] = { + { "idle", 0, 0, 0, 0}, + { "unknown", 0, 0, 0, 0}, + { "seldo", 0, seldo_run, 0, 0}, + { "seldi", 0, seldi_run, 0, 0}, + { "selto", 0, selto_run, 0, 0}, + { "busfree", 0, busfree_run, 0, 0}, + { "msgo", msgo_init, msgo_run, msgo_end, 1}, + { "cmd", cmd_init, cmd_run, cmd_end, 1}, + { "msgi", 0, msgi_run, msgi_end, 1}, + { "status", 0, status_run, 0, 1}, + { "datai", datai_init, datai_run, datai_end, 0}, + { "datao", datao_init, datao_run, datao_end, 0}, + { "parerr", 0, parerr_run, 0, 0}, + { "rsti", 0, rsti_run, 0, 0}, +}; + +/* setup & interrupt */ +static void intr(int irq, void *dev_id, struct pt_regs *); +static void reset_ports(struct Scsi_Host *shpnt); +static void aha152x_error(struct Scsi_Host *shpnt, char *msg); +static void done(struct Scsi_Host *shpnt, int error); +static int checksetup(struct aha152x_setup *setup); + +/* diagnostics */ +static void disp_ports(struct Scsi_Host *shpnt); +static void show_command(Scsi_Cmnd * ptr); +static void show_queues(struct Scsi_Host *shpnt); +static void disp_enintr(struct Scsi_Host *shpnt); + +/* possible i/o addresses for the AIC-6260; default first */ +static unsigned short ports[] = { 0x340, 0x140 }; + +#if !defined(SKIP_BIOSTEST) +/* possible locations for the Adaptec BIOS; defaults first */ +static unsigned int addresses[] = +{ + 0xdc000, /* default first */ + 0xc8000, + 0xcc000, + 0xd0000, + 0xd4000, + 0xd8000, + 0xe0000, + 0xeb800, /* VTech Platinum SMP */ + 0xf0000, +}; + +/* signatures for various AIC-6[23]60 based controllers. + The point in detecting signatures is to avoid useless and maybe + harmful probes on ports. I'm not sure that all listed boards pass + auto-configuration. For those which fail the BIOS signature is + obsolete, because user intervention to supply the configuration is + needed anyway. May be an information whether or not the BIOS supports + extended translation could be also useful here. */ +static struct signature { + unsigned char *signature; + int sig_offset; + int sig_length; +} signatures[] = +{ + { "Adaptec AHA-1520 BIOS", 0x102e, 21 }, + /* Adaptec 152x */ + { "Adaptec AHA-1520B", 0x000b, 17 }, + /* Adaptec 152x rev B */ + { "Adaptec AHA-1520B", 0x0026, 17 }, + /* Iomega Jaz Jet ISA (AIC6370Q) */ + { "Adaptec ASW-B626 BIOS", 0x1029, 21 }, + /* on-board controller */ + { "Adaptec BIOS: ASW-B626", 0x000f, 22 }, + /* on-board controller */ + { "Adaptec ASW-B626 S2", 0x2e6c, 19 }, + /* on-board controller */ + { "Adaptec BIOS:AIC-6360", 0x000c, 21 }, + /* on-board controller */ + { "ScsiPro SP-360 BIOS", 0x2873, 19 }, + /* ScsiPro-Controller */ + { "GA-400 LOCAL BUS SCSI BIOS", 0x102e, 26 }, + /* Gigabyte Local-Bus-SCSI */ + { "Adaptec BIOS:AVA-282X", 0x000c, 21 }, + /* Adaptec 282x */ + { "Adaptec IBM Dock II SCSI", 0x2edd, 24 }, + /* IBM Thinkpad Dock II */ + { "Adaptec BIOS:AHA-1532P", 0x001c, 22 }, + /* IBM Thinkpad Dock II SCSI */ + { "DTC3520A Host Adapter BIOS", 0x318a, 26 }, + /* DTC 3520A ISA SCSI */ +}; +#endif + + +/* + * queue services: + * + */ +static inline void append_SC(Scsi_Cmnd **SC, Scsi_Cmnd *new_SC) +{ + Scsi_Cmnd *end; + + SCNEXT(new_SC) = NULL; + if (!*SC) + *SC = new_SC; + else { + for (end = *SC; SCNEXT(end); end = SCNEXT(end)) + ; + SCNEXT(end) = new_SC; + } +} + +static inline Scsi_Cmnd *remove_first_SC(Scsi_Cmnd ** SC) +{ + Scsi_Cmnd *ptr; + + ptr = *SC; + if (ptr) { + *SC = SCNEXT(*SC); + SCNEXT(ptr)=NULL; + } + return ptr; +} + +static inline Scsi_Cmnd *remove_lun_SC(Scsi_Cmnd ** SC, int target, int lun) +{ + Scsi_Cmnd *ptr, *prev; + + for (ptr = *SC, prev = NULL; + ptr && ((ptr->target != target) || (ptr->lun != lun)); + prev = ptr, ptr = SCNEXT(ptr)) + ; + + if (ptr) { + if (prev) + SCNEXT(prev) = SCNEXT(ptr); + else + *SC = SCNEXT(ptr); + + SCNEXT(ptr)=NULL; + } + + return ptr; +} + +static inline Scsi_Cmnd *remove_SC(Scsi_Cmnd **SC, Scsi_Cmnd *SCp) +{ + Scsi_Cmnd *ptr, *prev; + + for (ptr = *SC, prev = NULL; + ptr && SCp!=ptr; + prev = ptr, ptr = SCNEXT(ptr)) + ; + + if (ptr) { + if (prev) + SCNEXT(prev) = SCNEXT(ptr); + else + *SC = SCNEXT(ptr); + + SCNEXT(ptr)=NULL; + } + + return ptr; +} + +#if defined(PCMCIA) || !defined(MODULE) +void aha152x_setup(char *str, int *ints) +{ + if(setup_count>=ARRAY_SIZE(setup)) { + printk(KERN_ERR "aha152x: you can only configure up to two controllers\n"); + return; + } + + setup[setup_count].conf = str; + setup[setup_count].io_port = ints[0] >= 1 ? ints[1] : 0x340; + setup[setup_count].irq = ints[0] >= 2 ? ints[2] : 11; + setup[setup_count].scsiid = ints[0] >= 3 ? ints[3] : 7; + setup[setup_count].reconnect = ints[0] >= 4 ? ints[4] : 1; + setup[setup_count].parity = ints[0] >= 5 ? ints[5] : 1; + setup[setup_count].synchronous = ints[0] >= 6 ? ints[6] : 1; + setup[setup_count].delay = ints[0] >= 7 ? ints[7] : DELAY_DEFAULT; + setup[setup_count].ext_trans = ints[0] >= 8 ? ints[8] : 0; +#if defined(AHA152X_DEBUG) + setup[setup_count].debug = ints[0] >= 9 ? ints[9] : DEBUG_DEFAULT; + if (ints[0] > 9) { + printk(KERN_NOTICE "aha152x: usage: aha152x=[,[," + "[,[,[,[,[,[,]]]]]]]]\n"); +#else + if (ints[0] > 8) { /*}*/ + printk(KERN_NOTICE "aha152x: usage: aha152x=[,[," + "[,[,[,[,[,]]]]]]]\n"); +#endif + return; + } else { + setup_count++; + return; + } +} +#endif + +#if !defined(MODULE) +static int __init do_setup(char *str) +{ + +#if defined(AHA152X_DEBUG) + int ints[11]; +#else + int ints[10]; +#endif + int count=setup_count; + + get_options(str, ARRAY_SIZE(ints), ints); + aha152x_setup(str,ints); + + return countswint++; + + SETPORT(DMACNTRL0, INTEN); +} + +#ifdef __ISAPNP__ +static struct pci_dev *pnpdev[2]; +static int num_pnpdevs; +#endif +int aha152x_detect(Scsi_Host_Template * tpnt) +{ + int i, j, ok; +#if defined(AUTOCONF) + aha152x_config conf; +#ifdef __ISAPNP__ + struct pci_dev *dev = NULL; +#endif +#endif + tpnt->proc_name = "aha152x"; + + for (i = 0; i < ARRAY_SIZE(aha152x_host); i++) + aha152x_host[i] = (struct Scsi_Host *) NULL; + + if (setup_count) { + printk(KERN_INFO "aha152x: processing commandline: "); + + for (i = 0; i < setup_count; i++) + if (!checksetup(&setup[i])) { + printk(KERN_ERR "\naha152x: %s\n", setup[i].conf); + printk(KERN_ERR "aha152x: invalid line\n"); + } + printk("ok\n"); + } + +#if defined(SETUP0) + if (setup_count < ARRAY_SIZE(setup)) { + struct aha152x_setup override = SETUP0; + + if (setup_count == 0 || (override.io_port != setup[0].io_port)) { + if (!checksetup(&override)) { + printk(KERN_ERR "\naha152x: invalid override SETUP0={0x%x,%d,%d,%d,%d,%d,%d,%d}\n", + override.io_port, + override.irq, + override.scsiid, + override.reconnect, + override.parity, + override.synchronous, + override.delay, + override.ext_trans); + } else + setup[setup_count++] = override; + } + } +#endif + +#if defined(SETUP1) + if (setup_count < ARRAY_SIZE(setup)) { + struct aha152x_setup override = SETUP1; + + if (setup_count == 0 || (override.io_port != setup[0].io_port)) { + if (!checksetup(&override)) { + printk(KERN_ERR "\naha152x: invalid override SETUP1={0x%x,%d,%d,%d,%d,%d,%d,%d}\n", + override.io_port, + override.irq, + override.scsiid, + override.reconnect, + override.parity, + override.synchronous, + override.delay, + override.ext_trans); + } else + setup[setup_count++] = override; + } + } +#endif + +#if defined(MODULE) + if (setup_countprepare(dev) < 0) + continue; + if (dev->active) + continue; + if (!(dev->resource[0].flags & IORESOURCE_IO)) + continue; + dev->resource[0].flags |= IORESOURCE_AUTO; + if (dev->activate(dev) < 0) + continue; + if ( setup_count==1 && dev->resource[0].start==setup[0].io_port) { + dev->deactivate(dev); + continue; + } + setup[setup_count].io_port = dev->resource[0].start; + setup[setup_count].irq = dev->irq_resource[0].start; + setup[setup_count].scsiid = 7; + setup[setup_count].reconnect = 1; + setup[setup_count].parity = 1; + setup[setup_count].synchronous = 1; + setup[setup_count].delay = DELAY_DEFAULT; + setup[setup_count].ext_trans = 0; +#if defined(AHA152X_DEBUG) + setup[setup_count].debug = DEBUG_DEFAULT; +#endif + pnpdev[num_pnpdevs++] = dev; + printk (KERN_INFO + "aha152x: found ISAPnP AVA-1505A at io=0x%03x, irq=%d\n", + setup[setup_count].io_port, setup[setup_count].irq); + setup_count++; + } +#endif + + +#if defined(AUTOCONF) + if (setup_countio_port = setup[i].io_port; + shpnt->n_io_port = IO_RANGE; + shpnt->irq = setup[i].irq; + + if(!setup[i].tc1550) { + HOSTIOPORT0 = setup[i].io_port; + HOSTIOPORT1 = setup[i].io_port; + } else { + HOSTIOPORT0 = setup[i].io_port+0x10; + HOSTIOPORT1 = setup[i].io_port-0x10; + } + + ISSUE_SC = 0; + CURRENT_SC = 0; + DONE_SC = 0; + DISCONNECTED_SC = 0; + + QLOCK = SPIN_LOCK_UNLOCKED; + + STATE = 0; + PREVSTATE = 0; + LASTSTATE = 0; + + MSGILEN = 0; + MSGOLEN = 0; + + RECONNECT = setup[i].reconnect; + SYNCHRONOUS = setup[i].synchronous; + PARITY = setup[i].parity; + DELAY = setup[i].delay; + EXT_TRANS = setup[i].ext_trans; +#if defined(AHA152X_DEBUG) + HOSTDATA(shpnt)->debug = setup[i].debug; +#endif + HOSTDATA(shpnt)->in_intr = 0; + HOSTDATA(shpnt)->commands = 0; + +#if defined(AHA152X_STAT) + HOSTDATA(shpnt)->total_commands=0; + HOSTDATA(shpnt)->disconnections=0; + HOSTDATA(shpnt)->busfree_without_any_action=0; + HOSTDATA(shpnt)->busfree_without_old_command=0; + HOSTDATA(shpnt)->busfree_without_new_command=0; + HOSTDATA(shpnt)->busfree_without_done_command=0; + HOSTDATA(shpnt)->busfree_with_check_condition=0; + for (j = idle; jcount[j]=0; + HOSTDATA(shpnt)->count_trans[j]=0; + HOSTDATA(shpnt)->time[j]=0; + } +#endif + + for (j = 0; j < 8; j++) { + HOSTDATA(shpnt)->syncrate[j] = 0; + HOSTDATA(shpnt)->syncneg[j] = 0; + } + + SETPORT(SCSIID, setup[i].scsiid << 4); + shpnt->this_id = setup[i].scsiid; + + if (setup[i].reconnect) + shpnt->can_queue = AHA152X_MAXQUEUE; + + /* RESET OUT */ + printk("aha152x: resetting bus...\n"); + SETPORT(SCSISEQ, SCSIRSTO); + mdelay(256); + SETPORT(SCSISEQ, 0); + mdelay(DELAY); + + reset_ports(shpnt); + + printk(KERN_INFO + "aha152x%d%s: " + "vital data: rev=%x, " + "io=0x%03lx (0x%03lx/0x%03lx), " + "irq=%d, " + "scsiid=%d, " + "reconnect=%s, " + "parity=%s, " + "synchronous=%s, " + "delay=%d, " + "extended translation=%s\n", + HOSTNO, setup[i].tc1550 ? " (tc1550 mode)" : "", + GETPORT(REV) & 0x7, + shpnt->io_port, HOSTIOPORT0, HOSTIOPORT1, + shpnt->irq, + shpnt->this_id, + RECONNECT ? "enabled" : "disabled", + PARITY ? "enabled" : "disabled", + SYNCHRONOUS ? "enabled" : "disabled", + DELAY, + EXT_TRANS ? "enabled" : "disabled"); + + request_region(shpnt->io_port, IO_RANGE, "aha152x"); + + /* not expecting any interrupts */ + SETPORT(SIMODE0, 0); + SETPORT(SIMODE1, 0); + + ok = request_irq(shpnt->irq, swintr, SA_INTERRUPT|SA_SHIRQ, "aha152x", shpnt); + if (ok < 0) { + if (ok==-EINVAL) + printk(KERN_ERR "aha152x%d: bad IRQ %d.\n", HOSTNO, shpnt->irq); + else if(ok==-EBUSY) + printk(KERN_ERR "aha152x%d: IRQ %d already in use.\n", HOSTNO, shpnt->irq); + else + printk(KERN_ERR "aha152x%d: Unexpected error code %d on requesting IRQ %d.\n", HOSTNO, ok, shpnt->irq); + + printk(KERN_ERR "aha152x%d: driver needs an IRQ.\n", HOSTNO); + + scsi_unregister(shpnt); + registered_count--; + release_region(shpnt->io_port, IO_RANGE); + aha152x_host[registered_count] = 0; + shpnt = 0; + continue; + } + HOSTDATA(shpnt)->swint = 0; + + printk(KERN_INFO "aha152x%d: trying software interrupt, ", HOSTNO); + SETPORT(DMACNTRL0, SWINT|INTEN); + mdelay(1000); + free_irq(shpnt->irq, shpnt); + + if (!HOSTDATA(shpnt)->swint) { + if (TESTHI(DMASTAT, INTSTAT)) { + printk("lost.\n"); + } else { + printk("failed.\n"); + } + + SETPORT(DMACNTRL0, INTEN); + + printk(KERN_ERR "aha152x%d: IRQ %d possibly wrong. Please verify.\n", HOSTNO, shpnt->irq); + + registered_count--; + release_region(shpnt->io_port, IO_RANGE); + aha152x_host[registered_count] = 0; + scsi_unregister(shpnt); + shpnt=NULL; + continue; + } + printk("ok.\n"); + + + /* clear interrupts */ + SETPORT(SSTAT0, 0x7f); + SETPORT(SSTAT1, 0xef); + + if (request_irq(shpnt->irq, intr, SA_INTERRUPT|SA_SHIRQ, "aha152x", shpnt) < 0) { + printk(KERN_ERR "aha152x%d: failed to reassign interrupt.\n", HOSTNO); + + registered_count--; + release_region(shpnt->io_port, IO_RANGE); + aha152x_host[registered_count] = 0; + scsi_unregister(shpnt); + shpnt=NULL; + continue; + } + } + + return registered_count>0; +} + + +int aha152x_release(struct Scsi_Host *shpnt) +{ + if (shpnt->irq) + free_irq(shpnt->irq, shpnt); + + if (shpnt->io_port) + release_region(shpnt->io_port, IO_RANGE); + +#ifdef __ISAPNP__ + while (num_pnpdevs--) + pnpdev[num_pnpdevs]->deactivate(pnpdev[num_pnpdevs]); +#endif + scsi_unregister(shpnt); + + return 0; +} + +/* + * setup controller to generate interrupts depending + * on current state (lock has to be acquired) + * + */ +static int setup_expected_interrupts(struct Scsi_Host *shpnt) +{ + ASSERT_LOCK(&QLOCK,1); + + if(CURRENT_SC) { + CURRENT_SC->SCp.phase |= 1 << 16; + + if(CURRENT_SC->SCp.phase & selecting) { + DPRINTK(debug_intr, DEBUG_LEAD "expecting: (seldo) (seltimo) (seldi)\n", CMDINFO(CURRENT_SC)); + SETPORT(SSTAT1, SELTO); + SETPORT(SIMODE0, ENSELDO | (DISCONNECTED_SC ? ENSELDI : 0)); + SETPORT(SIMODE1, ENSELTIMO); + } else { + DPRINTK(debug_intr, DEBUG_LEAD "expecting: (phase change) (busfree) %s\n", CMDINFO(CURRENT_SC), CURRENT_SC->SCp.phase & spiordy ? "(spiordy)" : ""); + SETPORT(SIMODE0, (CURRENT_SC->SCp.phase & spiordy) ? ENSPIORDY : 0); + SETPORT(SIMODE1, ENPHASEMIS | ENSCSIRST | ENSCSIPERR | ENBUSFREE); + } + } else if(STATE==seldi) { + DPRINTK(debug_intr, DEBUG_LEAD "expecting: (phase change) (identify)\n", CMDINFO(CURRENT_SC)); + SETPORT(SIMODE0, 0); + SETPORT(SIMODE1, ENPHASEMIS | ENSCSIRST | ENSCSIPERR | ENBUSFREE); + } else { + DPRINTK(debug_intr, DEBUG_LEAD "expecting: %s %s\n", + CMDINFO(CURRENT_SC), + DISCONNECTED_SC ? "(reselection)" : "", + ISSUE_SC ? "(busfree)" : ""); + SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0); + SETPORT(SIMODE1, ENSCSIRST | ( (ISSUE_SC||DONE_SC) ? ENBUSFREE : 0)); + } + + if(!HOSTDATA(shpnt)->in_intr) + SETBITS(DMACNTRL0, INTEN); + + return TESTHI(DMASTAT, INTSTAT); +} + + +/* + * Queue a command and setup interrupts for a free bus. + */ +int aha152x_internal_queue(Scsi_Cmnd *SCpnt, struct semaphore *sem, int phase, Scsi_Cmnd *done_SC, void (*done)(Scsi_Cmnd *)) +{ + struct Scsi_Host *shpnt = SCpnt->host; + unsigned long flags; + +#if defined(AHA152X_DEBUG) + if (HOSTDATA(shpnt)->debug & debug_queue) { + printk(INFO_LEAD "queue: cmd_len=%d pieces=%d size=%u cmnd=", + CMDINFO(SCpnt), SCpnt->cmd_len, SCpnt->use_sg, SCpnt->request_bufflen); + print_command(SCpnt->cmnd); + } +#endif + + SCpnt->scsi_done = done; + SCpnt->resid = SCpnt->request_bufflen; + SCpnt->SCp.phase = not_issued | phase; + SCpnt->SCp.Status = CHECK_CONDITION; + SCpnt->SCp.Message = 0; + SCpnt->SCp.have_data_in = 0; + SCpnt->SCp.sent_command = 0; + SCpnt->host_scribble = kmalloc(sizeof(struct aha152x_scdata), GFP_ATOMIC); + if(!SCpnt->host_scribble) { + printk(ERR_LEAD "allocation failed\n", CMDINFO(SCpnt)); + return FAILED; + } + + SCNEXT(SCpnt) = 0; + SCDONE(SCpnt) = done_SC; + SCSEM(SCpnt) = sem; + + /* setup scratch area + SCp.ptr : buffer pointer + SCp.this_residual : buffer length + SCp.buffer : next buffer + SCp.buffers_residual : left buffers in list + SCp.phase : current state of the command */ + if (SCpnt->use_sg) { + SCpnt->SCp.buffer = (struct scatterlist *) SCpnt->request_buffer; + SCpnt->SCp.ptr = SG_ADDRESS(SCpnt->SCp.buffer); + SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length; + SCpnt->SCp.buffers_residual = SCpnt->use_sg - 1; + } else { + SCpnt->SCp.ptr = (char *) SCpnt->request_buffer; + SCpnt->SCp.this_residual = SCpnt->request_bufflen; + SCpnt->SCp.buffer = NULL; + SCpnt->SCp.buffers_residual = 0; + } + + DO_LOCK(flags); + +#if defined(AHA152X_STAT) + HOSTDATA(shpnt)->total_commands++; +#endif + + /* Turn led on, when this is the first command. */ + HOSTDATA(shpnt)->commands++; + if (HOSTDATA(shpnt)->commands==1) + SETPORT(PORTA, 1); + + append_SC(&ISSUE_SC, SCpnt); + + if(!HOSTDATA(shpnt)->in_intr) + setup_expected_interrupts(shpnt); + + DO_UNLOCK(flags); + + return 0; +} + +int aha152x_queue(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) +{ +#if 0 + if(*SCpnt->cmnd == REQUEST_SENSE) { + SCpnt->result = 0; + done(SCpnt); + + return 0; + } +#endif + + return aha152x_internal_queue(SCpnt, 0, 0, 0, done); +} + + +/* + * run a command + * + */ +void internal_done(Scsi_Cmnd *SCpnt) +{ +#if 0 + struct Scsi_Host *shpnt = SCpnt->host; + + DPRINTK(debug_eh, INFO_LEAD "internal_done called\n", CMDINFO(SCpnt)); +#endif + if(SCSEM(SCpnt)) + up(SCSEM(SCpnt)); +} + +int aha152x_command(Scsi_Cmnd * SCpnt) +{ + DECLARE_MUTEX_LOCKED(sem); + + aha152x_internal_queue(SCpnt, &sem, 0, 0, internal_done); + down(&sem); + + return SUCCESS; +} + +/* + * Abort a command + * + */ +int aha152x_abort(Scsi_Cmnd *SCpnt) +{ + struct Scsi_Host *shpnt = SCpnt->host; + Scsi_Cmnd *ptr; + unsigned long flags; + + if(!shpnt) { + printk(ERR_LEAD "abort(%p): no host structure\n", CMDINFO(SCpnt), SCpnt); + return FAILED; + } + +#if defined(AHA152X_DEBUG) + if(HOSTDATA(shpnt)->debug & debug_eh) { + printk(DEBUG_LEAD "abort(%p)", CMDINFO(SCpnt), SCpnt); + show_queues(shpnt); + } +#endif + + DO_LOCK(flags); + + ptr=remove_SC(&ISSUE_SC, SCpnt); + + if(ptr) { + DPRINTK(debug_eh, DEBUG_LEAD "not yet issued - SUCCESS\n", CMDINFO(SCpnt)); + + HOSTDATA(shpnt)->commands--; + if (!HOSTDATA(shpnt)->commands) + SETPORT(PORTA, 0); + DO_UNLOCK(flags); + + kfree(SCpnt->host_scribble); + SCpnt->host_scribble=0; + + return SUCCESS; + } + + DO_UNLOCK(flags); + + /* + * FIXME: + * for current command: queue ABORT for message out and raise ATN + * for disconnected command: pseudo SC with ABORT message or ABORT on reselection? + * + */ + + printk(ERR_LEAD "cannot abort running or disconnected command\n", CMDINFO(SCpnt)); + + return FAILED; +} + +static void timer_expired(unsigned long p) +{ + Scsi_Cmnd *SCp = (Scsi_Cmnd *)p; + struct semaphore *sem = SCSEM(SCp); + struct Scsi_Host *shpnt = SCp->host; + + /* remove command from issue queue */ + if(remove_SC(&ISSUE_SC, SCp)) { + printk(KERN_INFO "aha152x: ABORT timed out - removed from issue queue\n"); + kfree(SCp->host_scribble); + SCp->host_scribble=0; + } else { + printk(KERN_INFO "aha152x: ABORT timed out - not on issue queue\n"); + } + + up(sem); +} + +/* + * Reset a device + * + * FIXME: never seen this live. might lockup... + * + */ +int aha152x_device_reset(Scsi_Cmnd * SCpnt) +{ + struct Scsi_Host *shpnt = SCpnt->host; + DECLARE_MUTEX_LOCKED(sem); + struct timer_list timer; + Scsi_Cmnd cmnd; + +#if defined(AHA152X_DEBUG) + if(HOSTDATA(shpnt)->debug & debug_eh) { + printk(INFO_LEAD "aha152x_device_reset(%p)", CMDINFO(SCpnt), SCpnt); + show_queues(shpnt); + } +#endif + + if(CURRENT_SC==SCpnt) { + printk(ERR_LEAD "cannot reset current device\n", CMDINFO(SCpnt)); + return FAILED; + } + + cmnd.cmd_len = 0; + cmnd.host = SCpnt->host; + cmnd.target = SCpnt->target; + cmnd.lun = SCpnt->lun; + cmnd.use_sg = 0; + cmnd.request_buffer = 0; + cmnd.request_bufflen = 0; + + init_timer(&timer); + timer.data = (unsigned long) &cmnd; + timer.expires = jiffies + 100*HZ; /* 10s */ + timer.function = (void (*)(unsigned long)) timer_expired; + + aha152x_internal_queue(&cmnd, &sem, resetting, 0, internal_done); + + add_timer(&timer); + down(&sem); + + del_timer(&timer); + + if(cmnd.SCp.phase & resetted) { + return SUCCESS; + } else { + return FAILED; + } +} + +void free_hard_reset_SCs(struct Scsi_Host *shpnt, Scsi_Cmnd **SCs) +{ + Scsi_Cmnd *ptr; + unsigned long flags; + + DO_LOCK(flags); + + ptr=*SCs; + while(ptr) { + Scsi_Cmnd *next = SCNEXT(ptr); + + if (!ptr->device->soft_reset) { + DPRINTK(debug_eh, DEBUG_LEAD "disconnected command %p removed\n", CMDINFO(ptr), ptr); + remove_SC(SCs, ptr); + HOSTDATA(shpnt)->commands--; + kfree(ptr->host_scribble); + ptr->host_scribble=0; + } + + ptr = next; + } + + DO_UNLOCK(flags); +} + +/* + * Reset the bus + * + */ +int aha152x_bus_reset(Scsi_Cmnd *SCpnt) +{ + struct Scsi_Host *shpnt = SCpnt->host; + unsigned long flags; + +#if defined(AHA152X_DEBUG) + if(HOSTDATA(shpnt)->debug & debug_eh) { + printk(DEBUG_LEAD "aha152x_bus_reset(%p)", CMDINFO(SCpnt), SCpnt); + show_queues(shpnt); + } +#endif + + free_hard_reset_SCs(shpnt, &ISSUE_SC); + free_hard_reset_SCs(shpnt, &DISCONNECTED_SC); + + DPRINTK(debug_eh, DEBUG_LEAD "resetting bus\n", CMDINFO(SCpnt)); + + SETPORT(SCSISEQ, SCSIRSTO); + mdelay(256); + SETPORT(SCSISEQ, 0); + mdelay(DELAY); + + DPRINTK(debug_eh, DEBUG_LEAD "bus reset returns\n", CMDINFO(SCpnt)); + + DO_LOCK(flags); + setup_expected_interrupts(shpnt); + if(HOSTDATA(shpnt)->commands==0) + SETPORT(PORTA, 0); + DO_UNLOCK(flags); + + return SUCCESS; +} + + +/* + * Restore default values to the AIC-6260 registers and reset the fifos + * + */ +static void reset_ports(struct Scsi_Host *shpnt) +{ + unsigned long flags; + + /* disable interrupts */ + SETPORT(DMACNTRL0, RSTFIFO); + + SETPORT(SCSISEQ, 0); + + SETPORT(SXFRCTL1, 0); + SETPORT(SCSISIG, 0); + SETRATE(0); + + /* clear all interrupt conditions */ + SETPORT(SSTAT0, 0x7f); + SETPORT(SSTAT1, 0xef); + + SETPORT(SSTAT4, SYNCERR | FWERR | FRERR); + + SETPORT(DMACNTRL0, 0); + SETPORT(DMACNTRL1, 0); + + SETPORT(BRSTCNTRL, 0xf1); + + /* clear SCSI fifos and transfer count */ + SETPORT(SXFRCTL0, CH1|CLRCH1|CLRSTCNT); + SETPORT(SXFRCTL0, CH1); + + DO_LOCK(flags); + setup_expected_interrupts(shpnt); + DO_UNLOCK(flags); +} + +/* + * Reset the host (bus and controller) + * + */ +int aha152x_host_reset(Scsi_Cmnd * SCpnt) +{ +#if defined(AHA152X_DEBUG) + struct Scsi_Host *shpnt = SCpnt->host; +#endif + + DPRINTK(debug_eh, DEBUG_LEAD "aha152x_host_reset(%p)\n", CMDINFO(SCpnt), SCpnt); + + aha152x_bus_reset(SCpnt); + + DPRINTK(debug_eh, DEBUG_LEAD "resetting ports\n", CMDINFO(SCpnt)); + reset_ports(SCpnt->host); + + return SUCCESS; +} + +/* + * Return the "logical geometry" + * + */ +int aha152x_biosparam(struct scsi_device *sdev, struct block_device *bdev, + sector_t capacity, int *info_array) +{ + struct Scsi_Host *shpnt = sdev->host; + + /* try default translation */ + info_array[0] = 64; + info_array[1] = 32; + info_array[2] = (unsigned long)capacity / (64 * 32); + + /* for disks >1GB do some guessing */ + if (info_array[2] >= 1024) { + int info[3]; + + /* try to figure out the geometry from the partition table */ + if (scsicam_bios_param(bdev, capacity, info) < 0 || + !((info[0] == 64 && info[1] == 32) || (info[0] == 255 && info[1] == 63))) { + if (EXT_TRANS) { + printk(KERN_NOTICE + "aha152x: unable to verify geometry for disk with >1GB.\n" + " using extended translation.\n"); + info_array[0] = 255; + info_array[1] = 63; + info_array[2] = (unsigned long)capacity / (255 * 63); + } else { + printk(KERN_NOTICE + "aha152x: unable to verify geometry for disk with >1GB.\n" + " Using default translation. Please verify yourself.\n" + " Perhaps you need to enable extended translation in the driver.\n" + " See /usr/src/linux/drivers/scsi/README.aha152x for details.\n"); + } + } else { + info_array[0] = info[0]; + info_array[1] = info[1]; + info_array[2] = info[2]; + + if (info[0] == 255 && !EXT_TRANS) { + printk(KERN_NOTICE + "aha152x: current partition table is using extended translation.\n" + " using it also, although it's not explicitly enabled.\n"); + } + } + } + + return 0; +} + +/* + * Internal done function + * + */ +static void done(struct Scsi_Host *shpnt, int error) +{ + if (CURRENT_SC) { + if(DONE_SC) + printk(ERR_LEAD "there's already a completed command %p - will cause abort\n", CMDINFO(CURRENT_SC), DONE_SC); + + DONE_SC = CURRENT_SC; + CURRENT_SC = 0; + DONE_SC->result = error; + } else + printk(KERN_ERR "aha152x: done() called outside of command\n"); +} + +static struct work_struct aha152x_tq; + +/* + * Run service completions on the card with interrupts enabled. + * + */ +static void run(void) +{ + int i; + for (i = 0; iservice) { + HOSTDATA(shpnt)->service=0; + is_complete(shpnt); + } + } +} + +/* + * Interrupts handler + * + */ + +static void intr(int irqno, void *dev_id, struct pt_regs *regs) +{ + struct Scsi_Host *shpnt = lookup_irq(irqno); + + if (!shpnt) { + printk(KERN_ERR "aha152x: catched interrupt %d for unknown controller.\n", irqno); + return; + } + + /* no more interrupts from the controller, while we're busy. + INTEN is restored by the BH handler */ + CLRBITS(DMACNTRL0, INTEN); + +#if 0 + /* check if there is already something to be + serviced; should not happen */ + if(HOSTDATA(shpnt)->service) { + printk(KERN_ERR "aha152x%d: lost interrupt (%d)\n", HOSTNO, HOSTDATA(shpnt)->service); + show_queues(shpnt); + } +#endif + + /* Poke the BH handler */ + HOSTDATA(shpnt)->service++; + INIT_WORK(&aha152x_tq, (void *) run, NULL); + schedule_work(&aha152x_tq); +} + +/* + * busfree phase + * - handle completition/disconnection/error of current command + * - start selection for next command (if any) + */ +static void busfree_run(struct Scsi_Host *shpnt) +{ + unsigned long flags; +#if defined(AHA152X_STAT) + int action=0; +#endif + + SETPORT(SXFRCTL0, CH1|CLRCH1|CLRSTCNT); + SETPORT(SXFRCTL0, CH1); + + SETPORT(SSTAT1, CLRBUSFREE); + + if(CURRENT_SC) { +#if defined(AHA152X_STAT) + action++; +#endif + CURRENT_SC->SCp.phase &= ~syncneg; + + if(CURRENT_SC->SCp.phase & completed) { + /* target sent COMMAND COMPLETE */ + done(shpnt, (CURRENT_SC->SCp.Status & 0xff) | ((CURRENT_SC->SCp.Message & 0xff) << 8) | (DID_OK << 16)); + + } else if(CURRENT_SC->SCp.phase & aborted) { + DPRINTK(debug_eh, DEBUG_LEAD "ABORT sent\n", CMDINFO(CURRENT_SC)); + done(shpnt, (CURRENT_SC->SCp.Status & 0xff) | ((CURRENT_SC->SCp.Message & 0xff) << 8) | (DID_ABORT << 16)); + + } else if(CURRENT_SC->SCp.phase & resetted) { + DPRINTK(debug_eh, DEBUG_LEAD "BUS DEVICE RESET sent\n", CMDINFO(CURRENT_SC)); + done(shpnt, (CURRENT_SC->SCp.Status & 0xff) | ((CURRENT_SC->SCp.Message & 0xff) << 8) | (DID_RESET << 16)); + + } else if(CURRENT_SC->SCp.phase & disconnected) { + /* target sent DISCONNECT */ + DPRINTK(debug_selection, DEBUG_LEAD "target disconnected at %d/%d\n", + CMDINFO(CURRENT_SC), + CURRENT_SC->resid, + CURRENT_SC->request_bufflen); +#if defined(AHA152X_STAT) + HOSTDATA(shpnt)->disconnections++; +#endif + append_SC(&DISCONNECTED_SC, CURRENT_SC); + CURRENT_SC->SCp.phase |= 1 << 16; + CURRENT_SC = 0; + + } else { + done(shpnt, DID_ERROR << 16); + } +#if defined(AHA152X_STAT) + } else { + HOSTDATA(shpnt)->busfree_without_old_command++; +#endif + } + + DO_LOCK(flags); + + if(DONE_SC) { +#if defined(AHA152X_STAT) + action++; +#endif + if(SCDONE(DONE_SC)) { + Scsi_Cmnd *ptr=DONE_SC; + DONE_SC=SCDONE(DONE_SC); + +#if 0 + if(HOSTDATA(shpnt)->debug & debug_eh) { + printk(ERR_LEAD "received sense: ", CMDINFO(ptr)); + print_sense("bh", DONE_SC); + } +#endif + + HOSTDATA(shpnt)->commands--; + if (!HOSTDATA(shpnt)->commands) + SETPORT(PORTA, 0); /* turn led off */ + + kfree(ptr->host_scribble); + kfree(ptr); + } else if(DONE_SC->SCp.Status==0x02) { +#if defined(AHA152X_STAT) + HOSTDATA(shpnt)->busfree_with_check_condition++; +#endif +#if 0 + DPRINTK(debug_eh, ERR_LEAD "CHECK CONDITION found\n", CMDINFO(DONE_SC)); +#endif + + if(!(DONE_SC->SCp.Status & not_issued)) { + Scsi_Cmnd *cmnd = kmalloc(sizeof(Scsi_Cmnd), GFP_ATOMIC); + + if(cmnd) { + Scsi_Cmnd *ptr=DONE_SC; + DONE_SC=0; + +#if 0 + DPRINTK(debug_eh, ERR_LEAD "requesting sense\n", CMDINFO(ptr)); +#endif + + cmnd->cmnd[0] = REQUEST_SENSE; + cmnd->cmnd[1] = 0; + cmnd->cmnd[2] = 0; + cmnd->cmnd[3] = 0; + cmnd->cmnd[4] = sizeof(ptr->sense_buffer); + cmnd->cmnd[5] = 0; + cmnd->cmd_len = 6; + cmnd->host = ptr->host; + cmnd->target = ptr->target; + cmnd->lun = ptr->lun; + cmnd->use_sg = 0; + cmnd->request_buffer = ptr->sense_buffer; + cmnd->request_bufflen = sizeof(ptr->sense_buffer); + + DO_UNLOCK(flags); + aha152x_internal_queue(cmnd, 0, 0, ptr, internal_done); + DO_LOCK(flags); + } else { + printk(ERR_LEAD "allocation failed\n", CMDINFO(CURRENT_SC)); + if(cmnd) + kfree(cmnd); + } + } else { +#if 0 + DPRINTK(debug_eh, ERR_LEAD "command not issued - CHECK CONDITION ignored\n", CMDINFO(DONE_SC)); +#endif + } + } + + if(DONE_SC && DONE_SC->scsi_done) { + /* turn led off, when no commands are in the driver */ + HOSTDATA(shpnt)->commands--; + if (!HOSTDATA(shpnt)->commands) + SETPORT(PORTA, 0); /* turn led off */ + + DO_UNLOCK(flags); + DPRINTK(debug_done, DEBUG_LEAD "calling scsi_done(%p)\n", CMDINFO(DONE_SC), DONE_SC); + DONE_SC->scsi_done(DONE_SC); + DPRINTK(debug_done, DEBUG_LEAD "scsi_done(%p) returned\n", CMDINFO(DONE_SC), DONE_SC); + DO_LOCK(flags); + + kfree(DONE_SC->host_scribble); + DONE_SC->host_scribble=0; + } + + DONE_SC=0; +#if defined(AHA152X_STAT) + } else { + HOSTDATA(shpnt)->busfree_without_done_command++; +#endif + } + + if(ISSUE_SC) + CURRENT_SC = remove_first_SC(&ISSUE_SC); + + DO_UNLOCK(flags); + + if(CURRENT_SC) { +#if defined(AHA152X_STAT) + action++; +#endif + CURRENT_SC->SCp.phase |= selecting; + + DPRINTK(debug_selection, DEBUG_LEAD "selecting target\n", CMDINFO(CURRENT_SC)); + + /* clear selection timeout */ + SETPORT(SSTAT1, SELTO); + + SETPORT(SCSIID, (shpnt->this_id << OID_) | CURRENT_SC->target); + SETPORT(SXFRCTL1, (PARITY ? ENSPCHK : 0 ) | ENSTIMER); + SETPORT(SCSISEQ, ENSELO | ENAUTOATNO | (DISCONNECTED_SC ? ENRESELI : 0)); + } else { +#if defined(AHA152X_STAT) + HOSTDATA(shpnt)->busfree_without_new_command++; +#endif + SETPORT(SCSISEQ, DISCONNECTED_SC ? ENRESELI : 0); + } + +#if defined(AHA152X_STAT) + if(!action) + HOSTDATA(shpnt)->busfree_without_any_action++; +#endif +} + +/* + * Selection done (OUT) + * - queue IDENTIFY message and SDTR to selected target for message out + * (ATN asserted automagically via ENAUTOATNO in busfree()) + */ +static void seldo_run(struct Scsi_Host *shpnt) +{ + SETPORT(SCSISIG, 0); + SETPORT(SSTAT1, CLRBUSFREE); + SETPORT(SSTAT1, CLRPHASECHG); + + CURRENT_SC->SCp.phase &= ~(selecting|not_issued); + + SETPORT(SCSISEQ, 0); + + if (TESTLO(SSTAT0, SELDO)) { + printk(ERR_LEAD "aha152x: passing bus free condition\n", CMDINFO(CURRENT_SC)); + done(shpnt, DID_NO_CONNECT << 16); + return; + } + + SETPORT(SSTAT0, CLRSELDO); + + ADDMSGO(IDENTIFY(RECONNECT, CURRENT_SC->lun)); + + if (CURRENT_SC->SCp.phase & aborting) { + ADDMSGO(ABORT); + } else if (CURRENT_SC->SCp.phase & resetting) { + ADDMSGO(BUS_DEVICE_RESET); + } else if (SYNCNEG==0 && SYNCHRONOUS) { + CURRENT_SC->SCp.phase |= syncneg; + ADDMSGO(EXTENDED_MESSAGE); + ADDMSGO(3); + ADDMSGO(EXTENDED_SDTR); + ADDMSGO(50); /* 200ns */ + ADDMSGO(8); /* 8 byte req/ack offset */ + + SYNCNEG=1; /* negotiation in progress */ + } + + SETRATE(SYNCRATE); +} + +/* + * Selection timeout + * - return command to mid-level with failure cause + * + */ +static void selto_run(struct Scsi_Host *shpnt) +{ + SETPORT(SCSISEQ, 0); + SETPORT(SSTAT1, CLRSELTIMO); + + DPRINTK(debug_selection, DEBUG_LEAD "selection timeout\n", CMDINFO(CURRENT_SC)); + + if(!CURRENT_SC) { + DPRINTK(debug_selection, DEBUG_LEAD "!CURRENT_SC\n", CMDINFO(CURRENT_SC)); + return; + } + + CURRENT_SC->SCp.phase &= ~selecting; + + if (CURRENT_SC->SCp.phase & aborted) { + DPRINTK(debug_selection, DEBUG_LEAD "aborted\n", CMDINFO(CURRENT_SC)); + done(shpnt, DID_ABORT << 16); + } else if (TESTLO(SSTAT0, SELINGO)) { + DPRINTK(debug_selection, DEBUG_LEAD "arbitration not won\n", CMDINFO(CURRENT_SC)); + done(shpnt, DID_BUS_BUSY << 16); + } else { + /* ARBITRATION won, but SELECTION failed */ + DPRINTK(debug_selection, DEBUG_LEAD "selection failed\n", CMDINFO(CURRENT_SC)); + done(shpnt, DID_NO_CONNECT << 16); + } +} + +/* + * Selection in done + * - put current command back to issue queue + * (reconnection of a disconnected nexus instead + * of successful selection out) + * + */ +static void seldi_run(struct Scsi_Host *shpnt) +{ + int selid; + int target; + unsigned long flags; + + SETPORT(SCSISIG, 0); + SETPORT(SSTAT0, CLRSELDI); + SETPORT(SSTAT1, CLRBUSFREE); + SETPORT(SSTAT1, CLRPHASECHG); + + if(CURRENT_SC) { + if(!(CURRENT_SC->SCp.phase & not_issued)) + printk(ERR_LEAD "command should not have been issued yet\n", CMDINFO(CURRENT_SC)); + + DPRINTK(debug_selection, ERR_LEAD "command requeued - reselection\n", CMDINFO(CURRENT_SC)); + + DO_LOCK(flags); + append_SC(&ISSUE_SC, CURRENT_SC); + DO_UNLOCK(flags); + + CURRENT_SC = 0; + } + + if(!DISCONNECTED_SC) { + DPRINTK(debug_selection, DEBUG_LEAD "unexpected SELDI ", CMDINFO(CURRENT_SC)); + return; + } + + RECONN_TARGET=-1; + + selid = GETPORT(SELID) & ~(1 << shpnt->this_id); + + if (selid==0) { + printk("aha152x%d: target id unknown (%02x)\n", HOSTNO, selid); + return; + } + + for(target=7; !(selid & (1 << target)); target--) + ; + + if(selid & ~(1 << target)) { + printk("aha152x%d: multiple targets reconnected (%02x)\n", + HOSTNO, selid); + } + + + SETPORT(SCSIID, (shpnt->this_id << OID_) | target); + SETPORT(SCSISEQ, 0); + + SETRATE(HOSTDATA(shpnt)->syncrate[target]); + + RECONN_TARGET=target; + DPRINTK(debug_selection, DEBUG_LEAD "target %d reselected (%02x).\n", CMDINFO(CURRENT_SC), target, selid); +} + +/* + * message in phase + * - handle initial message after reconnection to identify + * reconnecting nexus + * - queue command on DISCONNECTED_SC on DISCONNECT message + * - set completed flag on COMMAND COMPLETE + * (other completition code moved to busfree_run) + * - handle response to SDTR + * - clear synchronous transfer agreements on BUS RESET + * + * FIXME: what about SAVE POINTERS, RESTORE POINTERS? + * + */ +static void msgi_run(struct Scsi_Host *shpnt) +{ + for(;;) { + int sstat1 = GETPORT(SSTAT1); + + if(sstat1 & (PHASECHG|PHASEMIS|BUSFREE) || !(sstat1 & REQINIT)) + return; + + if(TESTLO(SSTAT0,SPIORDY)) { + DPRINTK(debug_msgi, DEBUG_LEAD "!SPIORDY\n", CMDINFO(CURRENT_SC)); + return; + } + + ADDMSGI(GETPORT(SCSIDAT)); + +#if defined(AHA152X_DEBUG) + if (HOSTDATA(shpnt)->debug & debug_msgi) { + printk(INFO_LEAD "inbound message %02x ", CMDINFO(CURRENT_SC), MSGI(0)); + print_msg(&MSGI(0)); + printk("\n"); + } +#endif + + if(!CURRENT_SC) { + if(LASTSTATE!=seldi) { + printk(KERN_ERR "aha152x%d: message in w/o current command not after reselection\n", HOSTNO); + } + + /* + * Handle reselection + */ + if(!(MSGI(0) & IDENTIFY_BASE)) { + printk(KERN_ERR "aha152x%d: target didn't identify after reselection\n", HOSTNO); + continue; + } + + CURRENT_SC = remove_lun_SC(&DISCONNECTED_SC, RECONN_TARGET, MSGI(0) & 0x3f); + + if (!CURRENT_SC) { + show_queues(shpnt); + printk(KERN_ERR "aha152x%d: no disconnected command for target %d/%d\n", HOSTNO, RECONN_TARGET, MSGI(0) & 0x3f); + continue; + } + + DPRINTK(debug_msgi, DEBUG_LEAD "target reconnected\n", CMDINFO(CURRENT_SC)); + + CURRENT_SC->SCp.Message = MSGI(0); + CURRENT_SC->SCp.phase &= ~disconnected; + + MSGILEN=0; + + /* next message if any */ + continue; + } + + CURRENT_SC->SCp.Message = MSGI(0); + + switch (MSGI(0)) { + case DISCONNECT: + if (!RECONNECT) + printk(WARN_LEAD "target was not allowed to disconnect\n", CMDINFO(CURRENT_SC)); + + CURRENT_SC->SCp.phase |= disconnected; + break; + + case COMMAND_COMPLETE: + if(CURRENT_SC->SCp.phase & completed) + DPRINTK(debug_msgi, DEBUG_LEAD "again COMMAND COMPLETE\n", CMDINFO(CURRENT_SC)); + + CURRENT_SC->SCp.phase |= completed; + break; + + case MESSAGE_REJECT: + if (SYNCNEG==1) { + printk(INFO_LEAD "Synchronous Data Transfer Request was rejected\n", CMDINFO(CURRENT_SC)); + SYNCNEG=2; /* negotiation completed */ + } else + printk(INFO_LEAD "inbound message (MESSAGE REJECT)\n", CMDINFO(CURRENT_SC)); + break; + + case SAVE_POINTERS: + break; + + case RESTORE_POINTERS: + break; + + case EXTENDED_MESSAGE: + if(MSGILEN<2 || MSGILENsynchronous) + break; + + printk(INFO_LEAD, CMDINFO(CURRENT_SC)); + print_msg(&MSGI(0)); + printk("\n"); + + ticks = (MSGI(3) * 4 + 49) / 50; + + if (syncneg) { + /* negotiation in progress */ + if (ticks > 9 || MSGI(4) < 1 || MSGI(4) > 8) { + ADDMSGO(MESSAGE_REJECT); + printk(INFO_LEAD "received Synchronous Data Transfer Request invalid - rejected\n", CMDINFO(CURRENT_SC)); + break; + } + + SYNCRATE |= ((ticks - 2) << 4) + MSGI(4); + } else if (ticks <= 9 && MSGI(4) >= 1) { + ADDMSGO(EXTENDED_MESSAGE); + ADDMSGO(3); + ADDMSGO(EXTENDED_SDTR); + if (ticks < 4) { + ticks = 4; + ADDMSGO(50); + } else + ADDMSGO(MSGI(3)); + + if (MSGI(4) > 8) + MSGI(4) = 8; + + ADDMSGO(MSGI(4)); + + SYNCRATE |= ((ticks - 2) << 4) + MSGI(4); + } else { + /* requested SDTR is too slow, do it asynchronously */ + printk(INFO_LEAD "Synchronous Data Transfer Request too slow - Rejecting\n", CMDINFO(CURRENT_SC)); + ADDMSGO(MESSAGE_REJECT); + } + + SYNCNEG=2; /* negotiation completed */ + SETRATE(SYNCRATE); + } + break; + + case BUS_DEVICE_RESET: + { + int i; + + for(i=0; i<8; i++) { + HOSTDATA(shpnt)->syncrate[i]=0; + HOSTDATA(shpnt)->syncneg[i]=0; + } + + } + break; + + case EXTENDED_MODIFY_DATA_POINTER: + case EXTENDED_EXTENDED_IDENTIFY: + case EXTENDED_WDTR: + default: + ADDMSGO(MESSAGE_REJECT); + break; + } + break; + } + + MSGILEN=0; + } +} + +static void msgi_end(struct Scsi_Host *shpnt) +{ + if(MSGILEN>0) + printk(WARN_LEAD "target left before message completed (%d)\n", CMDINFO(CURRENT_SC), MSGILEN); + + if (MSGOLEN > 0 && !(GETPORT(SSTAT1) & BUSFREE)) { + DPRINTK(debug_msgi, DEBUG_LEAD "msgo pending\n", CMDINFO(CURRENT_SC)); + SETPORT(SCSISIG, P_MSGI | SIG_ATNO); + } +} + +/* + * message out phase + * + */ +static void msgo_init(struct Scsi_Host *shpnt) +{ + if(MSGOLEN==0) { + if((CURRENT_SC->SCp.phase & syncneg) && SYNCNEG==2 && SYNCRATE==0) { + ADDMSGO(IDENTIFY(RECONNECT, CURRENT_SC->lun)); + } else { + printk(INFO_LEAD "unexpected MESSAGE OUT phase; rejecting\n", CMDINFO(CURRENT_SC)); + ADDMSGO(MESSAGE_REJECT); + } + } + +#if defined(AHA152X_DEBUG) + if(HOSTDATA(shpnt)->debug & debug_msgo) { + int i; + + printk(DEBUG_LEAD "messages( ", CMDINFO(CURRENT_SC)); + for (i=0; iSCp.phase |= identified; + + if (MSGO(MSGO_I)==ABORT) + CURRENT_SC->SCp.phase |= aborted; + + if (MSGO(MSGO_I)==BUS_DEVICE_RESET) + CURRENT_SC->SCp.phase |= resetted; + + SETPORT(SCSIDAT, MSGO(MSGO_I++)); + } +} + +static void msgo_end(struct Scsi_Host *shpnt) +{ + if(MSGO_ISCp.sent_command) { + printk(ERR_LEAD "command already sent\n", CMDINFO(CURRENT_SC)); + done(shpnt, DID_ERROR << 16); + return; + } + +#if defined(AHA152X_DEBUG) + if (HOSTDATA(shpnt)->debug & debug_cmd) { + printk(DEBUG_LEAD "cmd_init: ", CMDINFO(CURRENT_SC)); + print_command(CURRENT_SC->cmnd); + } +#endif + + CMD_I=0; +} + +/* + * command phase + * + */ +static void cmd_run(struct Scsi_Host *shpnt) +{ + if(CMD_I==CURRENT_SC->cmd_len) { + DPRINTK(debug_cmd, DEBUG_LEAD "command already completely sent (%d/%d)", CMDINFO(CURRENT_SC), CMD_I, CURRENT_SC->cmd_len); + disp_ports(shpnt); + } + + while(CMD_Icmd_len) { + DPRINTK(debug_cmd, DEBUG_LEAD "command byte %02x (%d/%d)\n", CMDINFO(CURRENT_SC), CURRENT_SC->cmnd[CMD_I], CMD_I, CURRENT_SC->cmd_len); + + if(TESTLO(SSTAT0, SPIORDY)) { + DPRINTK(debug_cmd, DEBUG_LEAD "!SPIORDY\n", CMDINFO(CURRENT_SC)); + return; + } + + SETPORT(SCSIDAT, CURRENT_SC->cmnd[CMD_I++]); + } +} + +static void cmd_end(struct Scsi_Host *shpnt) +{ + if(CMD_Icmd_len) + printk(ERR_LEAD "command sent incompletely (%d/%d)\n", CMDINFO(CURRENT_SC), CMD_I, CURRENT_SC->cmd_len); + else + CURRENT_SC->SCp.sent_command++; +} + +/* + * status phase + * + */ +static void status_run(struct Scsi_Host *shpnt) +{ + if(TESTLO(SSTAT0,SPIORDY)) { + DPRINTK(debug_status, DEBUG_LEAD "!SPIORDY\n", CMDINFO(CURRENT_SC)); + return; + } + + CURRENT_SC->SCp.Status = GETPORT(SCSIDAT); + +#if defined(AHA152X_DEBUG) + if (HOSTDATA(shpnt)->debug & debug_status) { + printk(DEBUG_LEAD "inbound status %02x ", CMDINFO(CURRENT_SC), CURRENT_SC->SCp.Status); + print_status(CURRENT_SC->SCp.Status); + printk("\n"); + } +#endif +} + +/* + * data in phase + * + */ +static void datai_init(struct Scsi_Host *shpnt) +{ + SETPORT(DMACNTRL0, RSTFIFO); + SETPORT(DMACNTRL0, RSTFIFO|ENDMA); + + SETPORT(SXFRCTL0, CH1|CLRSTCNT); + SETPORT(SXFRCTL0, CH1|SCSIEN|DMAEN); + + SETPORT(SIMODE0, 0); + SETPORT(SIMODE1, ENSCSIPERR | ENSCSIRST | ENPHASEMIS | ENBUSFREE); + + DATA_LEN=0; + DPRINTK(debug_datai, + DEBUG_LEAD "datai_init: request_bufflen=%d resid=%d\n", + CMDINFO(CURRENT_SC), CURRENT_SC->request_bufflen, CURRENT_SC->resid); +} + +static void datai_run(struct Scsi_Host *shpnt) +{ + unsigned int the_time; + int fifodata, data_count; + + /* + * loop while the phase persists or the fifos are not empty + * + */ + while(TESTLO(DMASTAT, INTSTAT) || TESTLO(DMASTAT, DFIFOEMP) || TESTLO(SSTAT2, SEMPTY)) { + /* FIXME: maybe this should be done by setting up + * STCNT to trigger ENSWRAP interrupt, instead of + * polling for DFIFOFULL + */ + the_time=jiffies + 10*HZ; + while(TESTLO(DMASTAT, DFIFOFULL|INTSTAT) && time_before(jiffies,the_time)) + barrier(); + + if(TESTLO(DMASTAT, DFIFOFULL|INTSTAT)) { + printk(ERR_LEAD "datai timeout", CMDINFO(CURRENT_SC)); + disp_ports(shpnt); + break; + } + + if(TESTHI(DMASTAT, DFIFOFULL)) { + fifodata = 128; + } else { + the_time=jiffies + 10*HZ; + while(TESTLO(SSTAT2, SEMPTY) && time_before(jiffies,the_time)) + barrier(); + + if(TESTLO(SSTAT2, SEMPTY)) { + printk(ERR_LEAD "datai sempty timeout", CMDINFO(CURRENT_SC)); + disp_ports(shpnt); + break; + } + + fifodata = GETPORT(FIFOSTAT); + } + + if(CURRENT_SC->SCp.this_residual>0) { + while(fifodata>0 && CURRENT_SC->SCp.this_residual>0) { + data_count = fifodata>CURRENT_SC->SCp.this_residual ? + CURRENT_SC->SCp.this_residual : + fifodata; + fifodata -= data_count; + + if(data_count & 1) { + DPRINTK(debug_datai, DEBUG_LEAD "8bit\n", CMDINFO(CURRENT_SC)); + SETPORT(DMACNTRL0, ENDMA|_8BIT); + *CURRENT_SC->SCp.ptr++ = GETPORT(DATAPORT); + CURRENT_SC->SCp.this_residual--; + DATA_LEN++; + SETPORT(DMACNTRL0, ENDMA); + } + + if(data_count > 1) { + DPRINTK(debug_datai, DEBUG_LEAD "16bit(%d)\n", CMDINFO(CURRENT_SC), data_count); + data_count >>= 1; + insw(DATAPORT, CURRENT_SC->SCp.ptr, data_count); + CURRENT_SC->SCp.ptr += 2 * data_count; + CURRENT_SC->SCp.this_residual -= 2 * data_count; + DATA_LEN += 2 * data_count; + } + + if(CURRENT_SC->SCp.this_residual==0 && CURRENT_SC->SCp.buffers_residual>0) { + /* advance to next buffer */ + CURRENT_SC->SCp.buffers_residual--; + CURRENT_SC->SCp.buffer++; + CURRENT_SC->SCp.ptr = SG_ADDRESS(CURRENT_SC->SCp.buffer); + CURRENT_SC->SCp.this_residual = CURRENT_SC->SCp.buffer->length; + } + } + } else if(fifodata>0) { + printk(ERR_LEAD "no buffers left for %d(%d) bytes (data overrun!?)\n", CMDINFO(CURRENT_SC), fifodata, GETPORT(FIFOSTAT)); + SETPORT(DMACNTRL0, ENDMA|_8BIT); + while(fifodata>0) { + int data; + data=GETPORT(DATAPORT); + DPRINTK(debug_datai, DEBUG_LEAD "data=%02x\n", CMDINFO(CURRENT_SC), data); + fifodata--; + DATA_LEN++; + } + SETPORT(DMACNTRL0, ENDMA|_8BIT); + } + } + + if(TESTLO(DMASTAT, INTSTAT) || + TESTLO(DMASTAT, DFIFOEMP) || + TESTLO(SSTAT2, SEMPTY) || + GETPORT(FIFOSTAT)>0) { + /* + * something went wrong, if there's something left in the fifos + * or the phase didn't change + */ + printk(ERR_LEAD "fifos should be empty and phase should have changed\n", CMDINFO(CURRENT_SC)); + disp_ports(shpnt); + } + + if(DATA_LEN!=GETSTCNT()) { + printk(ERR_LEAD + "manual transfer count differs from automatic (count=%d;stcnt=%d;diff=%d;fifostat=%d)", + CMDINFO(CURRENT_SC), DATA_LEN, GETSTCNT(), GETSTCNT()-DATA_LEN, GETPORT(FIFOSTAT)); + disp_ports(shpnt); + mdelay(10000); + } +} + +static void datai_end(struct Scsi_Host *shpnt) +{ + CURRENT_SC->resid -= GETSTCNT(); + + DPRINTK(debug_datai, + DEBUG_LEAD "datai_end: request_bufflen=%d resid=%d stcnt=%d\n", + CMDINFO(CURRENT_SC), CURRENT_SC->request_bufflen, CURRENT_SC->resid, GETSTCNT()); + + SETPORT(SXFRCTL0, CH1|CLRSTCNT); + SETPORT(DMACNTRL0, 0); +} + +/* + * data out phase + * + */ +static void datao_init(struct Scsi_Host *shpnt) +{ + SETPORT(DMACNTRL0, WRITE_READ | RSTFIFO); + SETPORT(DMACNTRL0, WRITE_READ | ENDMA); + + SETPORT(SXFRCTL0, CH1|CLRSTCNT); + SETPORT(SXFRCTL0, CH1|SCSIEN|DMAEN); + + SETPORT(SIMODE0, 0); + SETPORT(SIMODE1, ENSCSIPERR | ENSCSIRST | ENPHASEMIS | ENBUSFREE ); + + DATA_LEN = CURRENT_SC->resid; + + DPRINTK(debug_datao, + DEBUG_LEAD "datao_init: request_bufflen=%d; resid=%d\n", + CMDINFO(CURRENT_SC), CURRENT_SC->request_bufflen, CURRENT_SC->resid); +} + +static void datao_run(struct Scsi_Host *shpnt) +{ + unsigned int the_time; + int data_count; + + /* until phase changes or all data sent */ + while(TESTLO(DMASTAT, INTSTAT) && CURRENT_SC->SCp.this_residual>0) { + data_count = 128; + if(data_count > CURRENT_SC->SCp.this_residual) + data_count=CURRENT_SC->SCp.this_residual; + + if(TESTLO(DMASTAT, DFIFOEMP)) { + printk(ERR_LEAD "datao fifo not empty (%d)", CMDINFO(CURRENT_SC), GETPORT(FIFOSTAT)); + disp_ports(shpnt); + break; + } + + if(data_count & 1) { + SETPORT(DMACNTRL0,WRITE_READ|ENDMA|_8BIT); + SETPORT(DATAPORT, *CURRENT_SC->SCp.ptr++); + CURRENT_SC->SCp.this_residual--; + CURRENT_SC->resid--; + SETPORT(DMACNTRL0,WRITE_READ|ENDMA); + } + + if(data_count > 1) { + data_count >>= 1; + outsw(DATAPORT, CURRENT_SC->SCp.ptr, data_count); + CURRENT_SC->SCp.ptr += 2 * data_count; + CURRENT_SC->SCp.this_residual -= 2 * data_count; + CURRENT_SC->resid -= 2 * data_count; + } + + if(CURRENT_SC->SCp.this_residual==0 && CURRENT_SC->SCp.buffers_residual>0) { + /* advance to next buffer */ + CURRENT_SC->SCp.buffers_residual--; + CURRENT_SC->SCp.buffer++; + CURRENT_SC->SCp.ptr = SG_ADDRESS(CURRENT_SC->SCp.buffer); + CURRENT_SC->SCp.this_residual = CURRENT_SC->SCp.buffer->length; + } + + the_time=jiffies + 10*HZ; + while(TESTLO(DMASTAT, DFIFOEMP|INTSTAT) && time_before(jiffies,the_time)) + barrier(); + + if(TESTLO(DMASTAT, DFIFOEMP|INTSTAT)) { + printk(ERR_LEAD "dataout timeout", CMDINFO(CURRENT_SC)); + disp_ports(shpnt); + break; + } + } +} + +static void datao_end(struct Scsi_Host *shpnt) +{ + if(TESTLO(DMASTAT, DFIFOEMP)) { + int data_count = (DATA_LEN - CURRENT_SC->resid) - GETSTCNT(); + + DPRINTK(debug_datao, DEBUG_LEAD "datao: %d bytes to resend (%d written, %d transferred)\n", + CMDINFO(CURRENT_SC), + data_count, + DATA_LEN-CURRENT_SC->resid, + GETSTCNT()); + + CURRENT_SC->resid += data_count; + + if(CURRENT_SC->use_sg) { + data_count -= CURRENT_SC->SCp.ptr - SG_ADDRESS(CURRENT_SC->SCp.buffer); + while(data_count>0) { + CURRENT_SC->SCp.buffer--; + CURRENT_SC->SCp.buffers_residual++; + data_count -= CURRENT_SC->SCp.buffer->length; + } + CURRENT_SC->SCp.ptr = SG_ADDRESS(CURRENT_SC->SCp.buffer) - data_count; + CURRENT_SC->SCp.this_residual = CURRENT_SC->SCp.buffer->length + data_count; + } else { + CURRENT_SC->SCp.ptr -= data_count; + CURRENT_SC->SCp.this_residual += data_count; + } + } + + DPRINTK(debug_datao, DEBUG_LEAD "datao_end: request_bufflen=%d; resid=%d; stcnt=%d\n", + CMDINFO(CURRENT_SC), + CURRENT_SC->request_bufflen, + CURRENT_SC->resid, + GETSTCNT()); + + SETPORT(SXFRCTL0, CH1|CLRCH1|CLRSTCNT); + SETPORT(SXFRCTL0, CH1); + + SETPORT(DMACNTRL0, 0); +} + +/* + * figure out what state we're in + * + */ +static int update_state(struct Scsi_Host *shpnt) +{ + int dataphase=0; + unsigned int stat0 = GETPORT(SSTAT0); + unsigned int stat1 = GETPORT(SSTAT1); + + PREVSTATE = STATE; + STATE=unknown; + + if(stat1 & SCSIRSTI) { + STATE=rsti; + SETPORT(SCSISEQ,0); + SETPORT(SSTAT1,SCSIRSTI); + } else if(stat0 & SELDI && PREVSTATE==busfree) { + STATE=seldi; + } else if(stat0 & SELDO && CURRENT_SC && (CURRENT_SC->SCp.phase & selecting)) { + STATE=seldo; + } else if(stat1 & SELTO) { + STATE=selto; + } else if(stat1 & BUSFREE) { + STATE=busfree; + SETPORT(SSTAT1,BUSFREE); + } else if(stat1 & SCSIPERR) { + STATE=parerr; + SETPORT(SSTAT1,SCSIPERR); + } else if(stat1 & REQINIT) { + switch(GETPORT(SCSISIG) & P_MASK) { + case P_MSGI: STATE=msgi; break; + case P_MSGO: STATE=msgo; break; + case P_DATAO: STATE=datao; break; + case P_DATAI: STATE=datai; break; + case P_STATUS: STATE=status; break; + case P_CMD: STATE=cmd; break; + } + dataphase=1; + } + + if((stat0 & SELDI) && STATE!=seldi && !dataphase) { + printk(INFO_LEAD "reselection missed?", CMDINFO(CURRENT_SC)); + disp_ports(shpnt); + } + + if(STATE!=PREVSTATE) { + LASTSTATE=PREVSTATE; + } + + return dataphase; +} + +/* + * handle parity error + * + * FIXME: in which phase? + * + */ +static void parerr_run(struct Scsi_Host *shpnt) +{ + printk(ERR_LEAD "parity error\n", CMDINFO(CURRENT_SC)); + done(shpnt, DID_PARITY << 16); +} + +/* + * handle reset in + * + */ +static void rsti_run(struct Scsi_Host *shpnt) +{ + Scsi_Cmnd *ptr; + + printk(KERN_NOTICE "aha152x%d: scsi reset in\n", HOSTNO); + + ptr=DISCONNECTED_SC; + while(ptr) { + Scsi_Cmnd *next = SCNEXT(ptr); + + if (!ptr->device->soft_reset) { + remove_SC(&DISCONNECTED_SC, ptr); + + ptr->result = DID_RESET << 16; + ptr->scsi_done(ptr); + + kfree(ptr->host_scribble); + ptr->host_scribble=0; + } + + ptr = next; + } + + if(CURRENT_SC && !CURRENT_SC->device->soft_reset) + done(shpnt, DID_RESET << 16 ); +} + + +/* + * bottom-half handler + * + */ +static void is_complete(struct Scsi_Host *shpnt) +{ + int dataphase; + unsigned long flags; + int pending; + + DO_LOCK(flags); + if(HOSTDATA(shpnt)->in_intr!=0) { + DO_UNLOCK(flags); + /* aha152x_error never returns.. */ + aha152x_error(shpnt, "bottom-half already running!?"); + } + HOSTDATA(shpnt)->in_intr++; + DO_UNLOCK(flags); + + /* + * loop while there are interrupt conditions pending + * + */ + do { + unsigned long start = jiffies; + dataphase=update_state(shpnt); + + DPRINTK(debug_phases, LEAD "start %s %s(%s)\n", CMDINFO(CURRENT_SC), states[STATE].name, states[PREVSTATE].name, states[LASTSTATE].name); + + /* + * end previous state + * + */ + if(PREVSTATE!=STATE && states[PREVSTATE].end) + states[PREVSTATE].end(shpnt); + + /* + * disable SPIO mode if previous phase used it + * and this one doesn't + * + */ + if(states[PREVSTATE].spio && !states[STATE].spio) { + SETPORT(SXFRCTL0, CH1); + SETPORT(DMACNTRL0, 0); + if(CURRENT_SC) + CURRENT_SC->SCp.phase &= ~spiordy; + } + + /* + * accept current dataphase phase + * + */ + if(dataphase) { + SETPORT(SSTAT0, REQINIT); + SETPORT(SCSISIG, GETPORT(SCSISIG) & P_MASK); + SETPORT(SSTAT1, PHASECHG); + } + + /* + * enable SPIO mode if previous didn't use it + * and this one does + * + */ + if(!states[PREVSTATE].spio && states[STATE].spio) { + SETPORT(DMACNTRL0, 0); + SETPORT(SXFRCTL0, CH1|SPIOEN); + if(CURRENT_SC) + CURRENT_SC->SCp.phase |= spiordy; + } + + /* + * initialize for new state + * + */ + if(PREVSTATE!=STATE && states[STATE].init) + states[STATE].init(shpnt); + + /* + * handle current state + * + */ + if(states[STATE].run) + states[STATE].run(shpnt); + else + printk(ERR_LEAD "unexpected state (%x)\n", CMDINFO(CURRENT_SC), STATE); + + /* + * setup controller to interrupt on + * the next expected condition and + * loop if it's already there + * + */ + DO_LOCK(flags); + pending=setup_expected_interrupts(shpnt); +#if defined(AHA152X_STAT) + HOSTDATA(shpnt)->count[STATE]++; + if(PREVSTATE!=STATE) + HOSTDATA(shpnt)->count_trans[STATE]++; + HOSTDATA(shpnt)->time[STATE] += jiffies-start; +#endif + DO_UNLOCK(flags); + + DPRINTK(debug_phases, LEAD "end %s %s(%s)\n", CMDINFO(CURRENT_SC), states[STATE].name, states[PREVSTATE].name, states[LASTSTATE].name); + } while(pending); + + /* + * enable interrupts and leave bottom-half + * + */ + DO_LOCK(flags); + HOSTDATA(shpnt)->in_intr--; + SETBITS(DMACNTRL0, INTEN); + DO_UNLOCK(flags); +} + + +/* + * Dump the current driver status and panic + */ +static void aha152x_error(struct Scsi_Host *shpnt, char *msg) +{ + printk(KERN_EMERG "\naha152x%d: %s\n", HOSTNO, msg); + show_queues(shpnt); + panic("aha152x panic\n"); +} + +/* + * Display registers of AIC-6260 + */ +static void disp_ports(struct Scsi_Host *shpnt) +{ +#if defined(AHA152X_DEBUG) + int s; + + printk("\n%s: %s(%s) ", + CURRENT_SC ? "busy" : "waiting", + states[STATE].name, + states[PREVSTATE].name); + + s = GETPORT(SCSISEQ); + printk("SCSISEQ( "); + if (s & TEMODEO) + printk("TARGET MODE "); + if (s & ENSELO) + printk("SELO "); + if (s & ENSELI) + printk("SELI "); + if (s & ENRESELI) + printk("RESELI "); + if (s & ENAUTOATNO) + printk("AUTOATNO "); + if (s & ENAUTOATNI) + printk("AUTOATNI "); + if (s & ENAUTOATNP) + printk("AUTOATNP "); + if (s & SCSIRSTO) + printk("SCSIRSTO "); + printk(");"); + + printk(" SCSISIG("); + s = GETPORT(SCSISIG); + switch (s & P_MASK) { + case P_DATAO: + printk("DATA OUT"); + break; + case P_DATAI: + printk("DATA IN"); + break; + case P_CMD: + printk("COMMAND"); + break; + case P_STATUS: + printk("STATUS"); + break; + case P_MSGO: + printk("MESSAGE OUT"); + break; + case P_MSGI: + printk("MESSAGE IN"); + break; + default: + printk("*illegal*"); + break; + } + + printk("); "); + + printk("INTSTAT (%s); ", TESTHI(DMASTAT, INTSTAT) ? "hi" : "lo"); + + printk("SSTAT( "); + s = GETPORT(SSTAT0); + if (s & TARGET) + printk("TARGET "); + if (s & SELDO) + printk("SELDO "); + if (s & SELDI) + printk("SELDI "); + if (s & SELINGO) + printk("SELINGO "); + if (s & SWRAP) + printk("SWRAP "); + if (s & SDONE) + printk("SDONE "); + if (s & SPIORDY) + printk("SPIORDY "); + if (s & DMADONE) + printk("DMADONE "); + + s = GETPORT(SSTAT1); + if (s & SELTO) + printk("SELTO "); + if (s & ATNTARG) + printk("ATNTARG "); + if (s & SCSIRSTI) + printk("SCSIRSTI "); + if (s & PHASEMIS) + printk("PHASEMIS "); + if (s & BUSFREE) + printk("BUSFREE "); + if (s & SCSIPERR) + printk("SCSIPERR "); + if (s & PHASECHG) + printk("PHASECHG "); + if (s & REQINIT) + printk("REQINIT "); + printk("); "); + + + printk("SSTAT( "); + + s = GETPORT(SSTAT0) & GETPORT(SIMODE0); + + if (s & TARGET) + printk("TARGET "); + if (s & SELDO) + printk("SELDO "); + if (s & SELDI) + printk("SELDI "); + if (s & SELINGO) + printk("SELINGO "); + if (s & SWRAP) + printk("SWRAP "); + if (s & SDONE) + printk("SDONE "); + if (s & SPIORDY) + printk("SPIORDY "); + if (s & DMADONE) + printk("DMADONE "); + + s = GETPORT(SSTAT1) & GETPORT(SIMODE1); + + if (s & SELTO) + printk("SELTO "); + if (s & ATNTARG) + printk("ATNTARG "); + if (s & SCSIRSTI) + printk("SCSIRSTI "); + if (s & PHASEMIS) + printk("PHASEMIS "); + if (s & BUSFREE) + printk("BUSFREE "); + if (s & SCSIPERR) + printk("SCSIPERR "); + if (s & PHASECHG) + printk("PHASECHG "); + if (s & REQINIT) + printk("REQINIT "); + printk("); "); + + printk("SXFRCTL0( "); + + s = GETPORT(SXFRCTL0); + if (s & SCSIEN) + printk("SCSIEN "); + if (s & DMAEN) + printk("DMAEN "); + if (s & CH1) + printk("CH1 "); + if (s & CLRSTCNT) + printk("CLRSTCNT "); + if (s & SPIOEN) + printk("SPIOEN "); + if (s & CLRCH1) + printk("CLRCH1 "); + printk("); "); + + printk("SIGNAL( "); + + s = GETPORT(SCSISIG); + if (s & SIG_ATNI) + printk("ATNI "); + if (s & SIG_SELI) + printk("SELI "); + if (s & SIG_BSYI) + printk("BSYI "); + if (s & SIG_REQI) + printk("REQI "); + if (s & SIG_ACKI) + printk("ACKI "); + printk("); "); + + printk("SELID (%02x), ", GETPORT(SELID)); + + printk("STCNT (%d), ", GETSTCNT()); + + printk("SSTAT2( "); + + s = GETPORT(SSTAT2); + if (s & SOFFSET) + printk("SOFFSET "); + if (s & SEMPTY) + printk("SEMPTY "); + if (s & SFULL) + printk("SFULL "); + printk("); SFCNT (%d); ", s & (SFULL | SFCNT)); + + s = GETPORT(SSTAT3); + printk("SCSICNT (%d), OFFCNT(%d), ", (s & 0xf0) >> 4, s & 0x0f); + + printk("SSTAT4( "); + s = GETPORT(SSTAT4); + if (s & SYNCERR) + printk("SYNCERR "); + if (s & FWERR) + printk("FWERR "); + if (s & FRERR) + printk("FRERR "); + printk("); "); + + printk("DMACNTRL0( "); + s = GETPORT(DMACNTRL0); + printk("%s ", s & _8BIT ? "8BIT" : "16BIT"); + printk("%s ", s & DMA ? "DMA" : "PIO"); + printk("%s ", s & WRITE_READ ? "WRITE" : "READ"); + if (s & ENDMA) + printk("ENDMA "); + if (s & INTEN) + printk("INTEN "); + if (s & RSTFIFO) + printk("RSTFIFO "); + if (s & SWINT) + printk("SWINT "); + printk("); "); + + printk("DMASTAT( "); + s = GETPORT(DMASTAT); + if (s & ATDONE) + printk("ATDONE "); + if (s & WORDRDY) + printk("WORDRDY "); + if (s & DFIFOFULL) + printk("DFIFOFULL "); + if (s & DFIFOEMP) + printk("DFIFOEMP "); + printk(")\n"); +#endif +} + +/* + * display enabled interrupts + */ +static void disp_enintr(struct Scsi_Host *shpnt) +{ + int s; + + printk(KERN_DEBUG "enabled interrupts ( "); + + s = GETPORT(SIMODE0); + if (s & ENSELDO) + printk("ENSELDO "); + if (s & ENSELDI) + printk("ENSELDI "); + if (s & ENSELINGO) + printk("ENSELINGO "); + if (s & ENSWRAP) + printk("ENSWRAP "); + if (s & ENSDONE) + printk("ENSDONE "); + if (s & ENSPIORDY) + printk("ENSPIORDY "); + if (s & ENDMADONE) + printk("ENDMADONE "); + + s = GETPORT(SIMODE1); + if (s & ENSELTIMO) + printk("ENSELTIMO "); + if (s & ENATNTARG) + printk("ENATNTARG "); + if (s & ENPHASEMIS) + printk("ENPHASEMIS "); + if (s & ENBUSFREE) + printk("ENBUSFREE "); + if (s & ENSCSIPERR) + printk("ENSCSIPERR "); + if (s & ENPHASECHG) + printk("ENPHASECHG "); + if (s & ENREQINIT) + printk("ENREQINIT "); + printk(")\n"); +} + +/* + * Show the command data of a command + */ +static void show_command(Scsi_Cmnd *ptr) +{ + printk(KERN_DEBUG "0x%08x: target=%d; lun=%d; cmnd=(", + (unsigned int) ptr, ptr->target, ptr->lun); + + print_command(ptr->cmnd); + + printk(KERN_DEBUG "); request_bufflen=%d; resid=%d; phase |", + ptr->request_bufflen, ptr->resid); + + if (ptr->SCp.phase & not_issued) + printk("not issued|"); + if (ptr->SCp.phase & selecting) + printk("selecting|"); + if (ptr->SCp.phase & identified) + printk("identified|"); + if (ptr->SCp.phase & disconnected) + printk("disconnected|"); + if (ptr->SCp.phase & completed) + printk("completed|"); + if (ptr->SCp.phase & spiordy) + printk("spiordy|"); + if (ptr->SCp.phase & syncneg) + printk("syncneg|"); + if (ptr->SCp.phase & aborted) + printk("aborted|"); + if (ptr->SCp.phase & resetted) + printk("resetted|"); + printk("; next=0x%p\n", SCNEXT(ptr)); +} + +/* + * Dump the queued data + */ +static void show_queues(struct Scsi_Host *shpnt) +{ + Scsi_Cmnd *ptr; + unsigned long flags; + + DO_LOCK(flags); + printk(KERN_DEBUG "\nqueue status:\nissue_SC:\n"); + for (ptr = ISSUE_SC; ptr; ptr = SCNEXT(ptr)) + show_command(ptr); + DO_UNLOCK(flags); + + printk(KERN_DEBUG "current_SC:\n"); + if (CURRENT_SC) + show_command(CURRENT_SC); + else + printk(KERN_DEBUG "none\n"); + + printk(KERN_DEBUG "disconnected_SC:\n"); + for (ptr = DISCONNECTED_SC; ptr; ptr = SCNEXT(ptr)) + show_command(ptr); + + disp_ports(shpnt); + disp_enintr(shpnt); +} + +#undef SPRINTF +#define SPRINTF(args...) pos += sprintf(pos, ## args) + +static int get_command(char *pos, Scsi_Cmnd * ptr) +{ + char *start = pos; + int i; + + SPRINTF("0x%08x: target=%d; lun=%d; cmnd=( ", + (unsigned int) ptr, ptr->target, ptr->lun); + + for (i = 0; i < COMMAND_SIZE(ptr->cmnd[0]); i++) + SPRINTF("0x%02x ", ptr->cmnd[i]); + + SPRINTF("); resid=%d; residual=%d; buffers=%d; phase |", + ptr->resid, ptr->SCp.this_residual, ptr->SCp.buffers_residual); + + if (ptr->SCp.phase & not_issued) + SPRINTF("not issued|"); + if (ptr->SCp.phase & selecting) + SPRINTF("selecting|"); + if (ptr->SCp.phase & disconnected) + SPRINTF("disconnected|"); + if (ptr->SCp.phase & aborted) + SPRINTF("aborted|"); + if (ptr->SCp.phase & identified) + SPRINTF("identified|"); + if (ptr->SCp.phase & completed) + SPRINTF("completed|"); + if (ptr->SCp.phase & spiordy) + SPRINTF("spiordy|"); + if (ptr->SCp.phase & syncneg) + SPRINTF("syncneg|"); + SPRINTF("; next=0x%p\n", SCNEXT(ptr)); + + return (pos - start); +} + +static int get_ports(struct Scsi_Host *shpnt, char *pos) +{ + char *start = pos; + int s; + + SPRINTF("\n%s: %s(%s) ", CURRENT_SC ? "on bus" : "waiting", states[STATE].name, states[PREVSTATE].name); + + s = GETPORT(SCSISEQ); + SPRINTF("SCSISEQ( "); + if (s & TEMODEO) + SPRINTF("TARGET MODE "); + if (s & ENSELO) + SPRINTF("SELO "); + if (s & ENSELI) + SPRINTF("SELI "); + if (s & ENRESELI) + SPRINTF("RESELI "); + if (s & ENAUTOATNO) + SPRINTF("AUTOATNO "); + if (s & ENAUTOATNI) + SPRINTF("AUTOATNI "); + if (s & ENAUTOATNP) + SPRINTF("AUTOATNP "); + if (s & SCSIRSTO) + SPRINTF("SCSIRSTO "); + SPRINTF(");"); + + SPRINTF(" SCSISIG("); + s = GETPORT(SCSISIG); + switch (s & P_MASK) { + case P_DATAO: + SPRINTF("DATA OUT"); + break; + case P_DATAI: + SPRINTF("DATA IN"); + break; + case P_CMD: + SPRINTF("COMMAND"); + break; + case P_STATUS: + SPRINTF("STATUS"); + break; + case P_MSGO: + SPRINTF("MESSAGE OUT"); + break; + case P_MSGI: + SPRINTF("MESSAGE IN"); + break; + default: + SPRINTF("*illegal*"); + break; + } + + SPRINTF("); "); + + SPRINTF("INTSTAT (%s); ", TESTHI(DMASTAT, INTSTAT) ? "hi" : "lo"); + + SPRINTF("SSTAT( "); + s = GETPORT(SSTAT0); + if (s & TARGET) + SPRINTF("TARGET "); + if (s & SELDO) + SPRINTF("SELDO "); + if (s & SELDI) + SPRINTF("SELDI "); + if (s & SELINGO) + SPRINTF("SELINGO "); + if (s & SWRAP) + SPRINTF("SWRAP "); + if (s & SDONE) + SPRINTF("SDONE "); + if (s & SPIORDY) + SPRINTF("SPIORDY "); + if (s & DMADONE) + SPRINTF("DMADONE "); + + s = GETPORT(SSTAT1); + if (s & SELTO) + SPRINTF("SELTO "); + if (s & ATNTARG) + SPRINTF("ATNTARG "); + if (s & SCSIRSTI) + SPRINTF("SCSIRSTI "); + if (s & PHASEMIS) + SPRINTF("PHASEMIS "); + if (s & BUSFREE) + SPRINTF("BUSFREE "); + if (s & SCSIPERR) + SPRINTF("SCSIPERR "); + if (s & PHASECHG) + SPRINTF("PHASECHG "); + if (s & REQINIT) + SPRINTF("REQINIT "); + SPRINTF("); "); + + + SPRINTF("SSTAT( "); + + s = GETPORT(SSTAT0) & GETPORT(SIMODE0); + + if (s & TARGET) + SPRINTF("TARGET "); + if (s & SELDO) + SPRINTF("SELDO "); + if (s & SELDI) + SPRINTF("SELDI "); + if (s & SELINGO) + SPRINTF("SELINGO "); + if (s & SWRAP) + SPRINTF("SWRAP "); + if (s & SDONE) + SPRINTF("SDONE "); + if (s & SPIORDY) + SPRINTF("SPIORDY "); + if (s & DMADONE) + SPRINTF("DMADONE "); + + s = GETPORT(SSTAT1) & GETPORT(SIMODE1); + + if (s & SELTO) + SPRINTF("SELTO "); + if (s & ATNTARG) + SPRINTF("ATNTARG "); + if (s & SCSIRSTI) + SPRINTF("SCSIRSTI "); + if (s & PHASEMIS) + SPRINTF("PHASEMIS "); + if (s & BUSFREE) + SPRINTF("BUSFREE "); + if (s & SCSIPERR) + SPRINTF("SCSIPERR "); + if (s & PHASECHG) + SPRINTF("PHASECHG "); + if (s & REQINIT) + SPRINTF("REQINIT "); + SPRINTF("); "); + + SPRINTF("SXFRCTL0( "); + + s = GETPORT(SXFRCTL0); + if (s & SCSIEN) + SPRINTF("SCSIEN "); + if (s & DMAEN) + SPRINTF("DMAEN "); + if (s & CH1) + SPRINTF("CH1 "); + if (s & CLRSTCNT) + SPRINTF("CLRSTCNT "); + if (s & SPIOEN) + SPRINTF("SPIOEN "); + if (s & CLRCH1) + SPRINTF("CLRCH1 "); + SPRINTF("); "); + + SPRINTF("SIGNAL( "); + + s = GETPORT(SCSISIG); + if (s & SIG_ATNI) + SPRINTF("ATNI "); + if (s & SIG_SELI) + SPRINTF("SELI "); + if (s & SIG_BSYI) + SPRINTF("BSYI "); + if (s & SIG_REQI) + SPRINTF("REQI "); + if (s & SIG_ACKI) + SPRINTF("ACKI "); + SPRINTF("); "); + + SPRINTF("SELID(%02x), ", GETPORT(SELID)); + + SPRINTF("STCNT(%d), ", GETSTCNT()); + + SPRINTF("SSTAT2( "); + + s = GETPORT(SSTAT2); + if (s & SOFFSET) + SPRINTF("SOFFSET "); + if (s & SEMPTY) + SPRINTF("SEMPTY "); + if (s & SFULL) + SPRINTF("SFULL "); + SPRINTF("); SFCNT (%d); ", s & (SFULL | SFCNT)); + + s = GETPORT(SSTAT3); + SPRINTF("SCSICNT (%d), OFFCNT(%d), ", (s & 0xf0) >> 4, s & 0x0f); + + SPRINTF("SSTAT4( "); + s = GETPORT(SSTAT4); + if (s & SYNCERR) + SPRINTF("SYNCERR "); + if (s & FWERR) + SPRINTF("FWERR "); + if (s & FRERR) + SPRINTF("FRERR "); + SPRINTF("); "); + + SPRINTF("DMACNTRL0( "); + s = GETPORT(DMACNTRL0); + SPRINTF("%s ", s & _8BIT ? "8BIT" : "16BIT"); + SPRINTF("%s ", s & DMA ? "DMA" : "PIO"); + SPRINTF("%s ", s & WRITE_READ ? "WRITE" : "READ"); + if (s & ENDMA) + SPRINTF("ENDMA "); + if (s & INTEN) + SPRINTF("INTEN "); + if (s & RSTFIFO) + SPRINTF("RSTFIFO "); + if (s & SWINT) + SPRINTF("SWINT "); + SPRINTF("); "); + + SPRINTF("DMASTAT( "); + s = GETPORT(DMASTAT); + if (s & ATDONE) + SPRINTF("ATDONE "); + if (s & WORDRDY) + SPRINTF("WORDRDY "); + if (s & DFIFOFULL) + SPRINTF("DFIFOFULL "); + if (s & DFIFOEMP) + SPRINTF("DFIFOEMP "); + SPRINTF(")\n"); + + SPRINTF("enabled interrupts( "); + + s = GETPORT(SIMODE0); + if (s & ENSELDO) + SPRINTF("ENSELDO "); + if (s & ENSELDI) + SPRINTF("ENSELDI "); + if (s & ENSELINGO) + SPRINTF("ENSELINGO "); + if (s & ENSWRAP) + SPRINTF("ENSWRAP "); + if (s & ENSDONE) + SPRINTF("ENSDONE "); + if (s & ENSPIORDY) + SPRINTF("ENSPIORDY "); + if (s & ENDMADONE) + SPRINTF("ENDMADONE "); + + s = GETPORT(SIMODE1); + if (s & ENSELTIMO) + SPRINTF("ENSELTIMO "); + if (s & ENATNTARG) + SPRINTF("ENATNTARG "); + if (s & ENPHASEMIS) + SPRINTF("ENPHASEMIS "); + if (s & ENBUSFREE) + SPRINTF("ENBUSFREE "); + if (s & ENSCSIPERR) + SPRINTF("ENSCSIPERR "); + if (s & ENPHASECHG) + SPRINTF("ENPHASECHG "); + if (s & ENREQINIT) + SPRINTF("ENREQINIT "); + SPRINTF(")\n"); + + return (pos - start); +} + +int aha152x_set_info(char *buffer, int length, struct Scsi_Host *shpnt) +{ + if(!shpnt || !buffer || length<8 || strncmp("aha152x ", buffer, 8)!=0) + return -EINVAL; + +#if defined(AHA152X_DEBUG) + if(length>14 && strncmp("debug ", buffer+8, 6)==0) { + int debug = HOSTDATA(shpnt)->debug; + + HOSTDATA(shpnt)->debug = simple_strtoul(buffer+14, NULL, 0); + + printk(KERN_INFO "aha152x%d: debugging options set to 0x%04x (were 0x%04x)\n", HOSTNO, HOSTDATA(shpnt)->debug, debug); + } else +#endif +#if defined(AHA152X_STAT) + if(length>13 && strncmp("reset", buffer+8, 5)==0) { + int i; + + HOSTDATA(shpnt)->total_commands=0; + HOSTDATA(shpnt)->disconnections=0; + HOSTDATA(shpnt)->busfree_without_any_action=0; + HOSTDATA(shpnt)->busfree_without_old_command=0; + HOSTDATA(shpnt)->busfree_without_new_command=0; + HOSTDATA(shpnt)->busfree_without_done_command=0; + HOSTDATA(shpnt)->busfree_with_check_condition=0; + for (i = idle; icount[i]=0; + HOSTDATA(shpnt)->count_trans[i]=0; + HOSTDATA(shpnt)->time[i]=0; + } + + printk(KERN_INFO "aha152x%d: stats reseted.\n", HOSTNO); + + } else +#endif + { + return -EINVAL; + } + + + return length; +} + +#undef SPRINTF +#define SPRINTF(args...) \ + do { if(pos < buffer + length) pos += sprintf(pos, ## args); } while(0) + +int aha152x_proc_info(char *buffer, char **start, + off_t offset, int length, int hostno, int inout) +{ + int i; + char *pos = buffer; + struct Scsi_Host *shpnt; + Scsi_Cmnd *ptr; + unsigned long flags; + int thislength; + + for (i = 0, shpnt = (struct Scsi_Host *) NULL; ihost_no == hostno) + shpnt = aha152x_host[i]; + + if (!shpnt) + return -ESRCH; + + DPRINTK(debug_procinfo, + KERN_DEBUG "aha152x_proc_info: buffer=%p offset=%ld length=%d hostno=%d inout=%d\n", + buffer, offset, length, hostno, inout); + + + if (inout) + return aha152x_set_info(buffer, length, shpnt); + + SPRINTF(AHA152X_REVID "\n"); + + SPRINTF("ioports 0x%04lx to 0x%04lx\n", + shpnt->io_port, shpnt->io_port + shpnt->n_io_port - 1); + SPRINTF("interrupt 0x%02x\n", shpnt->irq); + SPRINTF("disconnection/reconnection %s\n", + RECONNECT ? "enabled" : "disabled"); + SPRINTF("parity checking %s\n", + PARITY ? "enabled" : "disabled"); + SPRINTF("synchronous transfers %s\n", + SYNCHRONOUS ? "enabled" : "disabled"); + SPRINTF("%d commands currently queued\n", HOSTDATA(shpnt)->commands); + + if(SYNCHRONOUS) { + SPRINTF("synchronously operating targets (tick=50 ns):\n"); + for (i = 0; i < 8; i++) + if (HOSTDATA(shpnt)->syncrate[i] & 0x7f) + SPRINTF("target %d: period %dT/%dns; req/ack offset %d\n", + i, + (((HOSTDATA(shpnt)->syncrate[i] & 0x70) >> 4) + 2), + (((HOSTDATA(shpnt)->syncrate[i] & 0x70) >> 4) + 2) * 50, + HOSTDATA(shpnt)->syncrate[i] & 0x0f); + } +#if defined(AHA152X_DEBUG) +#define PDEBUG(flags,txt) \ + if(HOSTDATA(shpnt)->debug & flags) SPRINTF("(%s) ", txt); + + SPRINTF("enabled debugging options: "); + + PDEBUG(debug_procinfo, "procinfo"); + PDEBUG(debug_queue, "queue"); + PDEBUG(debug_intr, "interrupt"); + PDEBUG(debug_selection, "selection"); + PDEBUG(debug_msgo, "message out"); + PDEBUG(debug_msgi, "message in"); + PDEBUG(debug_status, "status"); + PDEBUG(debug_cmd, "command"); + PDEBUG(debug_datai, "data in"); + PDEBUG(debug_datao, "data out"); + PDEBUG(debug_eh, "eh"); + PDEBUG(debug_locks, "locks"); + PDEBUG(debug_phases, "phases"); + + SPRINTF("\n"); +#endif + + SPRINTF("\nqueue status:\n"); + DO_LOCK(flags); + if (ISSUE_SC) { + SPRINTF("not yet issued commands:\n"); + for (ptr = ISSUE_SC; ptr; ptr = SCNEXT(ptr)) + pos += get_command(pos, ptr); + } else + SPRINTF("no not yet issued commands\n"); + DO_UNLOCK(flags); + + if (CURRENT_SC) { + SPRINTF("current command:\n"); + pos += get_command(pos, CURRENT_SC); + } else + SPRINTF("no current command\n"); + + if (DISCONNECTED_SC) { + SPRINTF("disconnected commands:\n"); + for (ptr = DISCONNECTED_SC; ptr; ptr = SCNEXT(ptr)) + pos += get_command(pos, ptr); + } else + SPRINTF("no disconnected commands\n"); + + pos += get_ports(shpnt, pos); + +#if defined(AHA152X_STAT) + SPRINTF("statistics:\n" + "total commands: %d\n" + "disconnections: %d\n" + "busfree with check condition: %d\n" + "busfree without old command: %d\n" + "busfree without new command: %d\n" + "busfree without done command: %d\n" + "busfree without any action: %d\n" + "state " + "transitions " + "count " + "time\n", + HOSTDATA(shpnt)->total_commands, + HOSTDATA(shpnt)->disconnections, + HOSTDATA(shpnt)->busfree_with_check_condition, + HOSTDATA(shpnt)->busfree_without_old_command, + HOSTDATA(shpnt)->busfree_without_new_command, + HOSTDATA(shpnt)->busfree_without_done_command, + HOSTDATA(shpnt)->busfree_without_any_action); + for(i=0; icount_trans[i], + HOSTDATA(shpnt)->count[i], + HOSTDATA(shpnt)->time[i]); + } +#endif + + DPRINTK(debug_procinfo, KERN_DEBUG "aha152x_proc_info: pos=%p\n", pos); + + thislength = pos - (buffer + offset); + DPRINTK(debug_procinfo, KERN_DEBUG "aha152x_proc_info: length=%d thislength=%d\n", length, thislength); + + if(thislength<0) { + DPRINTK(debug_procinfo, KERN_DEBUG "aha152x_proc_info: output too short\n"); + *start = 0; + return 0; + } + + thislength = thislength + + * 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, 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + + ************************************************************************** + + SUMMARY: + + Future Domain BIOS versions supported for autodetect: + 2.0, 3.0, 3.2, 3.4 (1.0), 3.5 (2.0), 3.6, 3.61 + Chips are supported: + TMC-1800, TMC-18C50, TMC-18C30, TMC-36C70 + Boards supported: + Future Domain TMC-1650, TMC-1660, TMC-1670, TMC-1680, TMC-1610M/MER/MEX + Future Domain TMC-3260 (PCI) + Quantum ISA-200S, ISA-250MG + Adaptec AHA-2920A (PCI) [BUT *NOT* AHA-2920C -- use aic7xxx instead] + IBM ? + LILO/INSMOD command-line options: + fdomain=,[,] + + + + NOTE: + + The Adaptec AHA-2920C has an Adaptec AIC-7850 chip on it. + Use the aic7xxx driver for this board. + + The Adaptec AHA-2920A has a Future Domain chip on it, so this is the right + driver for that card. Unfortunately, the boxes will probably just say + "2920", so you'll have to look on the card for a Future Domain logo, or a + letter after the 2920. + + + + THANKS: + + Thanks to Adaptec for providing PCI boards for testing. This finally + enabled me to test the PCI detection and correct it for PCI boards that do + not have a BIOS at a standard ISA location. For PCI boards, LILO/INSMOD + command-line options should no longer be needed. --RF 18Nov98 + + + + DESCRIPTION: + + This is the Linux low-level SCSI driver for Future Domain TMC-1660/1680 + TMC-1650/1670, and TMC-3260 SCSI host adapters. The 1650 and 1670 have a + 25-pin external connector, whereas the 1660 and 1680 have a SCSI-2 50-pin + high-density external connector. The 1670 and 1680 have floppy disk + controllers built in. The TMC-3260 is a PCI bus card. + + Future Domain's older boards are based on the TMC-1800 chip, and this + driver was originally written for a TMC-1680 board with the TMC-1800 chip. + More recently, boards are being produced with the TMC-18C50 and TMC-18C30 + chips. The latest and greatest board may not work with this driver. If + you have to patch this driver so that it will recognize your board's BIOS + signature, then the driver may fail to function after the board is + detected. + + Please note that the drive ordering that Future Domain implemented in BIOS + versions 3.4 and 3.5 is the opposite of the order (currently) used by the + rest of the SCSI industry. If you have BIOS version 3.4 or 3.5, and have + more than one drive, then the drive ordering will be the reverse of that + which you see under DOS. For example, under DOS SCSI ID 0 will be D: and + SCSI ID 1 will be C: (the boot device). Under Linux, SCSI ID 0 will be + /dev/sda and SCSI ID 1 will be /dev/sdb. The Linux ordering is consistent + with that provided by all the other SCSI drivers for Linux. If you want + this changed, you will probably have to patch the higher level SCSI code. + If you do so, please send me patches that are protected by #ifdefs. + + If you have a TMC-8xx or TMC-9xx board, then this is not the driver for + your board. Please refer to the Seagate driver for more information and + possible support. + + + + HISTORY: + + Linux Driver Driver + Version Version Date Support/Notes + + 0.0 3 May 1992 V2.0 BIOS; 1800 chip + 0.97 1.9 28 Jul 1992 + 0.98.6 3.1 27 Nov 1992 + 0.99 3.2 9 Dec 1992 + + 0.99.3 3.3 10 Jan 1993 V3.0 BIOS + 0.99.5 3.5 18 Feb 1993 + 0.99.10 3.6 15 May 1993 V3.2 BIOS; 18C50 chip + 0.99.11 3.17 3 Jul 1993 (now under RCS) + 0.99.12 3.18 13 Aug 1993 + 0.99.14 5.6 31 Oct 1993 (reselection code removed) + + 0.99.15 5.9 23 Jan 1994 V3.4 BIOS (preliminary) + 1.0.8/1.1.1 5.15 1 Apr 1994 V3.4 BIOS; 18C30 chip (preliminary) + 1.0.9/1.1.3 5.16 7 Apr 1994 V3.4 BIOS; 18C30 chip + 1.1.38 5.18 30 Jul 1994 36C70 chip (PCI version of 18C30) + 1.1.62 5.20 2 Nov 1994 V3.5 BIOS + 1.1.73 5.22 7 Dec 1994 Quantum ISA-200S board; V2.0 BIOS + + 1.1.82 5.26 14 Jan 1995 V3.5 BIOS; TMC-1610M/MER/MEX board + 1.2.10 5.28 5 Jun 1995 Quantum ISA-250MG board; V2.0, V2.01 BIOS + 1.3.4 5.31 23 Jun 1995 PCI BIOS-32 detection (preliminary) + 1.3.7 5.33 4 Jul 1995 PCI BIOS-32 detection + 1.3.28 5.36 17 Sep 1995 V3.61 BIOS; LILO command-line support + 1.3.34 5.39 12 Oct 1995 V3.60 BIOS; /proc + 1.3.72 5.39 8 Feb 1996 Adaptec AHA-2920 board + 1.3.85 5.41 4 Apr 1996 + 2.0.12 5.44 8 Aug 1996 Use ID 7 for all PCI cards + 2.1.1 5.45 2 Oct 1996 Update ROM accesses for 2.1.x + 2.1.97 5.46 23 Apr 1998 Rewritten PCI detection routines [mj] + 2.1.11x 5.47 9 Aug 1998 Touched for 8 SCSI disk majors support + 5.48 18 Nov 1998 BIOS no longer needed for PCI detection + 2.2.0 5.50 28 Dec 1998 Support insmod parameters + + + REFERENCES USED: + + "TMC-1800 SCSI Chip Specification (FDC-1800T)", Future Domain Corporation, + 1990. + + "Technical Reference Manual: 18C50 SCSI Host Adapter Chip", Future Domain + Corporation, January 1992. + + "LXT SCSI Products: Specifications and OEM Technical Manual (Revision + B/September 1991)", Maxtor Corporation, 1991. + + "7213S product Manual (Revision P3)", Maxtor Corporation, 1992. + + "Draft Proposed American National Standard: Small Computer System + Interface - 2 (SCSI-2)", Global Engineering Documents. (X3T9.2/86-109, + revision 10h, October 17, 1991) + + Private communications, Drew Eckhardt (drew@cs.colorado.edu) and Eric + Youngdale (ericy@cais.com), 1992. + + Private communication, Tuong Le (Future Domain Engineering department), + 1994. (Disk geometry computations for Future Domain BIOS version 3.4, and + TMC-18C30 detection.) + + Hogan, Thom. The Programmer's PC Sourcebook. Microsoft Press, 1988. Page + 60 (2.39: Disk Partition Table Layout). + + "18C30 Technical Reference Manual", Future Domain Corporation, 1993, page + 6-1. + + + + NOTES ON REFERENCES: + + The Maxtor manuals were free. Maxtor telephone technical support is + great! + + The Future Domain manuals were $25 and $35. They document the chip, not + the TMC-16x0 boards, so some information I had to guess at. In 1992, + Future Domain sold DOS BIOS source for $250 and the UN*X driver source was + $750, but these required a non-disclosure agreement, so even if I could + have afforded them, they would *not* have been useful for writing this + publically distributable driver. Future Domain technical support has + provided some information on the phone and have sent a few useful FAXs. + They have been much more helpful since they started to recognize that the + word "Linux" refers to an operating system :-). + + + + ALPHA TESTERS: + + There are many other alpha testers that come and go as the driver + develops. The people listed here were most helpful in times of greatest + need (mostly early on -- I've probably left out a few worthy people in + more recent times): + + Todd Carrico (todd@wutc.wustl.edu), Dan Poirier (poirier@cs.unc.edu ), Ken + Corey (kenc@sol.acs.unt.edu), C. de Bruin (bruin@bruin@sterbbs.nl), Sakari + Aaltonen (sakaria@vipunen.hit.fi), John Rice (rice@xanth.cs.odu.edu), Brad + Yearwood (brad@optilink.com), and Ray Toy (toy@soho.crd.ge.com). + + Special thanks to Tien-Wan Yang (twyang@cs.uh.edu), who graciously lent me + his 18C50-based card for debugging. He is the sole reason that this + driver works with the 18C50 chip. + + Thanks to Dave Newman (dnewman@crl.com) for providing initial patches for + the version 3.4 BIOS. + + Thanks to James T. McKinley (mckinley@msupa.pa.msu.edu) for providing + patches that support the TMC-3260, a PCI bus card with the 36C70 chip. + The 36C70 chip appears to be "completely compatible" with the 18C30 chip. + + Thanks to Eric Kasten (tigger@petroglyph.cl.msu.edu) for providing the + patch for the version 3.5 BIOS. + + Thanks for Stephen Henson (shenson@nyx10.cs.du.edu) for providing the + patch for the Quantum ISA-200S SCSI adapter. + + Thanks to Adam Bowen for the signature to the 1610M/MER/MEX scsi cards, to + Martin Andrews (andrewm@ccfadm.eeg.ccf.org) for the signature to some + random TMC-1680 repackaged by IBM; and to Mintak Ng (mintak@panix.com) for + the version 3.61 BIOS signature. + + Thanks for Mark Singer (elf@netcom.com) and Richard Simpson + (rsimpson@ewrcsdra.demon.co.uk) for more Quantum signatures and detective + work on the Quantum RAM layout. + + Special thanks to James T. McKinley (mckinley@msupa.pa.msu.edu) for + providing patches for proper PCI BIOS32-mediated detection of the TMC-3260 + card (a PCI bus card with the 36C70 chip). Please send James PCI-related + bug reports. + + Thanks to Tom Cavin (tec@usa1.com) for preliminary command-line option + patches. + + New PCI detection code written by Martin Mares + + Insmod parameter code based on patches from Daniel Graham + . + + All of the alpha testers deserve much thanks. + + + + NOTES ON USER DEFINABLE OPTIONS: + + DEBUG: This turns on the printing of various debug information. + + ENABLE_PARITY: This turns on SCSI parity checking. With the current + driver, all attached devices must support SCSI parity. If none of your + devices support parity, then you can probably get the driver to work by + turning this option off. I have no way of testing this, however, and it + would appear that no one ever uses this option. + + FIFO_COUNT: The host adapter has an 8K cache (host adapters based on the + 18C30 chip have a 2k cache). When this many 512 byte blocks are filled by + the SCSI device, an interrupt will be raised. Therefore, this could be as + low as 0, or as high as 16. Note, however, that values which are too high + or too low seem to prevent any interrupts from occurring, and thereby lock + up the machine. I have found that 2 is a good number, but throughput may + be increased by changing this value to values which are close to 2. + Please let me know if you try any different values. + + DO_DETECT: This activates some old scan code which was needed before the + high level drivers got fixed. If you are having trouble with the driver, + turning this on should not hurt, and might help. Please let me know if + this is the case, since this code will be removed from future drivers. + + RESELECTION: This is no longer an option, since I gave up trying to + implement it in version 4.x of this driver. It did not improve + performance at all and made the driver unstable (because I never found one + of the two race conditions which were introduced by the multiple + outstanding command code). The instability seems a very high price to pay + just so that you don't have to wait for the tape to rewind. If you want + this feature implemented, send me patches. I'll be happy to send a copy + of my (broken) driver to anyone who would like to see a copy. + + **************************************************************************/ + +#include + +#ifdef PCMCIA +#undef MODULE +#endif + +#include +#include +#include +#include +#include "scsi.h" +#include "hosts.h" +#include "fdomain.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include /* for CONFIG_PCI */ + +#define VERSION "$Revision: 5.50 $" + +/* START OF USER DEFINABLE OPTIONS */ + +#define DEBUG 1 /* Enable debugging output */ +#define ENABLE_PARITY 1 /* Enable SCSI Parity */ +#define FIFO_COUNT 2 /* Number of 512 byte blocks before INTR */ +#define DO_DETECT 0 /* Do device detection here (see scsi.c) */ + +/* END OF USER DEFINABLE OPTIONS */ + +#if DEBUG +#define EVERY_ACCESS 0 /* Write a line on every scsi access */ +#define ERRORS_ONLY 1 /* Only write a line if there is an error */ +#define DEBUG_DETECT 0 /* Debug fdomain_16x0_detect() */ +#define DEBUG_MESSAGES 1 /* Debug MESSAGE IN phase */ +#define DEBUG_ABORT 1 /* Debug abort() routine */ +#define DEBUG_RESET 1 /* Debug reset() routine */ +#define DEBUG_RACE 1 /* Debug interrupt-driven race condition */ +#else +#define EVERY_ACCESS 0 /* LEAVE THESE ALONE--CHANGE THE ONES ABOVE */ +#define ERRORS_ONLY 0 +#define DEBUG_DETECT 0 +#define DEBUG_MESSAGES 0 +#define DEBUG_ABORT 0 +#define DEBUG_RESET 0 +#define DEBUG_RACE 0 +#endif + +/* Errors are reported on the line, so we don't need to report them again */ +#if EVERY_ACCESS +#undef ERRORS_ONLY +#define ERRORS_ONLY 0 +#endif + +#if ENABLE_PARITY +#define PARITY_MASK 0x08 +#else +#define PARITY_MASK 0x00 +#endif + +enum chip_type { + unknown = 0x00, + tmc1800 = 0x01, + tmc18c50 = 0x02, + tmc18c30 = 0x03, +}; + +enum { + in_arbitration = 0x02, + in_selection = 0x04, + in_other = 0x08, + disconnect = 0x10, + aborted = 0x20, + sent_ident = 0x40, +}; + +enum in_port_type { + Read_SCSI_Data = 0, + SCSI_Status = 1, + TMC_Status = 2, + FIFO_Status = 3, /* tmc18c50/tmc18c30 only */ + Interrupt_Cond = 4, /* tmc18c50/tmc18c30 only */ + LSB_ID_Code = 5, + MSB_ID_Code = 6, + Read_Loopback = 7, + SCSI_Data_NoACK = 8, + Interrupt_Status = 9, + Configuration1 = 10, + Configuration2 = 11, /* tmc18c50/tmc18c30 only */ + Read_FIFO = 12, + FIFO_Data_Count = 14 +}; + +enum out_port_type { + Write_SCSI_Data = 0, + SCSI_Cntl = 1, + Interrupt_Cntl = 2, + SCSI_Mode_Cntl = 3, + TMC_Cntl = 4, + Memory_Cntl = 5, /* tmc18c50/tmc18c30 only */ + Write_Loopback = 7, + IO_Control = 11, /* tmc18c30 only */ + Write_FIFO = 12 +}; + +/* .bss will zero all the static variables below */ +static int port_base; +static unsigned long bios_base; +static int bios_major; +static int bios_minor; +static int PCI_bus; +static int Quantum; /* Quantum board variant */ +static int interrupt_level; +static volatile int in_command; +static Scsi_Cmnd *current_SC; +static enum chip_type chip = unknown; +static int adapter_mask; +static int this_id; +static int setup_called; + +#if DEBUG_RACE +static volatile int in_interrupt_flag; +#endif + +static int SCSI_Mode_Cntl_port; +static int FIFO_Data_Count_port; +static int Interrupt_Cntl_port; +static int Interrupt_Status_port; +static int Read_FIFO_port; +static int Read_SCSI_Data_port; +static int SCSI_Cntl_port; +static int SCSI_Data_NoACK_port; +static int SCSI_Status_port; +static int TMC_Cntl_port; +static int TMC_Status_port; +static int Write_FIFO_port; +static int Write_SCSI_Data_port; + +static int FIFO_Size = 0x2000; /* 8k FIFO for + pre-tmc18c30 chips */ + +static void do_fdomain_16x0_intr( int irq, void *dev_id, + struct pt_regs * regs ); + +#ifdef MODULE + /* Allow insmod parameters to be like LILO + parameters. For example: + insmod fdomain fdomain=0x140,11 + */ +static char * fdomain = NULL; +MODULE_PARM(fdomain, "s"); +#endif + +static unsigned long addresses[] = { + 0xc8000, + 0xca000, + 0xce000, + 0xde000, + 0xcc000, /* Extra addresses for PCI boards */ + 0xd0000, + 0xe0000, +}; +#define ADDRESS_COUNT (sizeof( addresses ) / sizeof( unsigned )) + +static unsigned short ports[] = { 0x140, 0x150, 0x160, 0x170 }; +#define PORT_COUNT (sizeof( ports ) / sizeof( unsigned short )) + +static unsigned short ints[] = { 3, 5, 10, 11, 12, 14, 15, 0 }; + +/* + + READ THIS BEFORE YOU ADD A SIGNATURE! + + READING THIS SHORT NOTE CAN SAVE YOU LOTS OF TIME! + + READ EVERY WORD, ESPECIALLY THE WORD *NOT* + + This driver works *ONLY* for Future Domain cards using the TMC-1800, + TMC-18C50, or TMC-18C30 chip. This includes models TMC-1650, 1660, 1670, + and 1680. These are all 16-bit cards. + + The following BIOS signature signatures are for boards which do *NOT* + work with this driver (these TMC-8xx and TMC-9xx boards may work with the + Seagate driver): + + FUTURE DOMAIN CORP. (C) 1986-1988 V4.0I 03/16/88 + FUTURE DOMAIN CORP. (C) 1986-1989 V5.0C2/14/89 + FUTURE DOMAIN CORP. (C) 1986-1989 V6.0A7/28/89 + FUTURE DOMAIN CORP. (C) 1986-1990 V6.0105/31/90 + FUTURE DOMAIN CORP. (C) 1986-1990 V6.0209/18/90 + FUTURE DOMAIN CORP. (C) 1986-1990 V7.009/18/90 + FUTURE DOMAIN CORP. (C) 1992 V8.00.004/02/92 + + (The cards which do *NOT* work are all 8-bit cards -- although some of + them have a 16-bit form-factor, the upper 8-bits are used only for IRQs + and are *NOT* used for data. You can tell the difference by following + the tracings on the circuit board -- if only the IRQ lines are involved, + you have a "8-bit" card, and should *NOT* use this driver.) + +*/ + +struct signature { + const char *signature; + int sig_offset; + int sig_length; + int major_bios_version; + int minor_bios_version; + int flag; /* 1 == PCI_bus, 2 == ISA_200S, 3 == ISA_250MG, 4 == ISA_200S */ +} signatures[] = { + /* 1 2 3 4 5 6 */ + /* 123456789012345678901234567890123456789012345678901234567890 */ + { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V2.07/28/89", 5, 50, 2, 0, 0 }, + { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V1.07/28/89", 5, 50, 2, 0, 0 }, + { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V2.07/28/89", 72, 50, 2, 0, 2 }, + { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V2.0", 73, 43, 2, 0, 3 }, + { "FUTURE DOMAIN CORP. (C) 1991 1800-V2.0.", 72, 39, 2, 0, 4 }, + { "FUTURE DOMAIN CORP. (C) 1992 V3.00.004/02/92", 5, 44, 3, 0, 0 }, + { "FUTURE DOMAIN TMC-18XX (C) 1993 V3.203/12/93", 5, 44, 3, 2, 0 }, + { "IBM F1 P2 BIOS v1.0104/29/93", 5, 28, 3, -1, 0 }, + { "Future Domain Corp. V1.0008/18/93", 5, 33, 3, 4, 0 }, + { "Future Domain Corp. V1.0008/18/93", 26, 33, 3, 4, 1 }, + { "Adaptec AHA-2920 PCI-SCSI Card", 42, 31, 3, -1, 1 }, + { "IBM F1 P264/32", 5, 14, 3, -1, 1 }, + /* This next signature may not be a 3.5 bios */ + { "Future Domain Corp. V2.0108/18/93", 5, 33, 3, 5, 0 }, + { "FUTURE DOMAIN CORP. V3.5008/18/93", 5, 34, 3, 5, 0 }, + { "FUTURE DOMAIN 18c30/18c50/1800 (C) 1994 V3.5", 5, 44, 3, 5, 0 }, + { "FUTURE DOMAIN CORP. V3.6008/18/93", 5, 34, 3, 6, 0 }, + { "FUTURE DOMAIN CORP. V3.6108/18/93", 5, 34, 3, 6, 0 }, + { "FUTURE DOMAIN TMC-18XX", 5, 22, -1, -1, 0 }, + + /* READ NOTICE ABOVE *BEFORE* YOU WASTE YOUR TIME ADDING A SIGNATURE + Also, fix the disk geometry code for your signature and send your + changes for faith@cs.unc.edu. Above all, do *NOT* change any old + signatures! + + Note that the last line will match a "generic" 18XX bios. Because + Future Domain has changed the host SCSI ID and/or the location of the + geometry information in the on-board RAM area for each of the first + three BIOS's, it is still important to enter a fully qualified + signature in the table for any new BIOS's (after the host SCSI ID and + geometry location are verified). */ +}; + +#define SIGNATURE_COUNT (sizeof( signatures ) / sizeof( struct signature )) + +static void print_banner( struct Scsi_Host *shpnt ) +{ + if (!shpnt) return; /* This won't ever happen */ + + if (bios_major < 0 && bios_minor < 0) { + printk(KERN_INFO "scsi%d: No BIOS; using scsi id %d\n", + shpnt->host_no, shpnt->this_id); + } else { + printk(KERN_INFO "scsi%d: BIOS version ", shpnt->host_no); + + if (bios_major >= 0) printk("%d.", bios_major); + else printk("?."); + + if (bios_minor >= 0) printk("%d", bios_minor); + else printk("?."); + + printk( " at 0x%lx using scsi id %d\n", + bios_base, shpnt->this_id ); + } + + /* If this driver works for later FD PCI + boards, we will have to modify banner + for additional PCI cards, but for now if + it's PCI it's a TMC-3260 - JTM */ + printk(KERN_INFO "scsi%d: %s chip at 0x%x irq ", + shpnt->host_no, + chip == tmc1800 ? "TMC-1800" : (chip == tmc18c50 ? "TMC-18C50" : (chip == tmc18c30 ? (PCI_bus ? "TMC-36C70 (PCI bus)" : "TMC-18C30") : "Unknown")), + port_base); + + if (interrupt_level) + printk("%d", interrupt_level); + else + printk(""); + + printk( "\n" ); +} + +static int __init fdomain_setup(char *str) +{ + int ints[4]; + + (void)get_options(str, ARRAY_SIZE(ints), ints); + + if (setup_called++ || ints[0] < 2 || ints[0] > 3) { + printk(KERN_INFO "scsi: Usage: fdomain=,[,]\n"); + printk(KERN_ERR "scsi: Bad LILO/INSMOD parameters?\n"); + return 0; + } + + port_base = ints[0] >= 1 ? ints[1] : 0; + interrupt_level = ints[0] >= 2 ? ints[2] : 0; + this_id = ints[0] >= 3 ? ints[3] : 0; + + bios_major = bios_minor = -1; /* Use geometry for BIOS version >= 3.4 */ + ++setup_called; + return 1; +} + +__setup("fdomain=", fdomain_setup); + + +static void do_pause(unsigned amount) /* Pause for amount*10 milliseconds */ +{ + mdelay(10*amount); +} + +inline static void fdomain_make_bus_idle( void ) +{ + outb( 0, SCSI_Cntl_port ); + outb( 0, SCSI_Mode_Cntl_port ); + if (chip == tmc18c50 || chip == tmc18c30) + outb( 0x21 | PARITY_MASK, TMC_Cntl_port ); /* Clear forced intr. */ + else + outb( 0x01 | PARITY_MASK, TMC_Cntl_port ); +} + +static int fdomain_is_valid_port( int port ) +{ +#if DEBUG_DETECT + printk( " (%x%x),", + inb( port + MSB_ID_Code ), inb( port + LSB_ID_Code ) ); +#endif + + /* The MCA ID is a unique id for each MCA compatible board. We + are using ISA boards, but Future Domain provides the MCA ID + anyway. We can use this ID to ensure that this is a Future + Domain TMC-1660/TMC-1680. + */ + + if (inb( port + LSB_ID_Code ) != 0xe9) { /* test for 0x6127 id */ + if (inb( port + LSB_ID_Code ) != 0x27) return 0; + if (inb( port + MSB_ID_Code ) != 0x61) return 0; + chip = tmc1800; + } else { /* test for 0xe960 id */ + if (inb( port + MSB_ID_Code ) != 0x60) return 0; + chip = tmc18c50; + + /* Try to toggle 32-bit mode. This only + works on an 18c30 chip. (User reports + say this works, so we should switch to + it in the near future.) */ + + outb( 0x80, port + IO_Control ); + if ((inb( port + Configuration2 ) & 0x80) == 0x80) { + outb( 0x00, port + IO_Control ); + if ((inb( port + Configuration2 ) & 0x80) == 0x00) { + chip = tmc18c30; + FIFO_Size = 0x800; /* 2k FIFO */ + } + } + /* If that failed, we are an 18c50. */ + } + + return 1; +} + +static int fdomain_test_loopback( void ) +{ + int i; + int result; + + for (i = 0; i < 255; i++) { + outb( i, port_base + Write_Loopback ); + result = inb( port_base + Read_Loopback ); + if (i != result) + return 1; + } + return 0; +} + +/* fdomain_get_irq assumes that we have a valid MCA ID for a + TMC-1660/TMC-1680 Future Domain board. Now, check to be sure the + bios_base matches these ports. If someone was unlucky enough to have + purchased more than one Future Domain board, then they will have to + modify this code, as we only detect one board here. [The one with the + lowest bios_base.] + + Note that this routine is only used for systems without a PCI BIOS32 + (e.g., ISA bus). For PCI bus systems, this routine will likely fail + unless one of the IRQs listed in the ints array is used by the board. + Sometimes it is possible to use the computer's BIOS setup screen to + configure a PCI system so that one of these IRQs will be used by the + Future Domain card. */ + +static int fdomain_get_irq( int base ) +{ + int options = inb(base + Configuration1); + +#if DEBUG_DETECT + printk("scsi: Options = %x\n", options); +#endif + + /* Check for board with lowest bios_base -- + this isn't valid for the 18c30 or for + boards on the PCI bus, so just assume we + have the right board. */ + + if (chip != tmc18c30 && !PCI_bus && addresses[(options & 0xc0) >> 6 ] != bios_base) + return 0; + return ints[(options & 0x0e) >> 1]; +} + +static int fdomain_isa_detect( int *irq, int *iobase ) +{ + int i, j; + int base = 0xdeadbeef; + int flag = 0; + +#if DEBUG_DETECT + printk( "scsi: fdomain_isa_detect:" ); +#endif + + for (i = 0; !bios_base && i < ADDRESS_COUNT; i++) { +#if DEBUG_DETECT + printk( " %lx(%lx),", addresses[i], bios_base ); +#endif + for (j = 0; !bios_base && j < SIGNATURE_COUNT; j++) { + if (isa_check_signature(addresses[i] + signatures[j].sig_offset, + signatures[j].signature, + signatures[j].sig_length )) { + bios_major = signatures[j].major_bios_version; + bios_minor = signatures[j].minor_bios_version; + PCI_bus = (signatures[j].flag == 1); + Quantum = (signatures[j].flag > 1) ? signatures[j].flag : 0; + bios_base = addresses[i]; + } + } + } + + if (bios_major == 2) { + /* The TMC-1660/TMC-1680 has a RAM area just after the BIOS ROM. + Assuming the ROM is enabled (otherwise we wouldn't have been + able to read the ROM signature :-), then the ROM sets up the + RAM area with some magic numbers, such as a list of port + base addresses and a list of the disk "geometry" reported to + DOS (this geometry has nothing to do with physical geometry). + */ + + switch (Quantum) { + case 2: /* ISA_200S */ + case 3: /* ISA_250MG */ + base = readb(bios_base + 0x1fa2) + (readb(bios_base + 0x1fa3) << 8); + break; + case 4: /* ISA_200S (another one) */ + base = readb(bios_base + 0x1fa3) + (readb(bios_base + 0x1fa4) << 8); + break; + default: + base = readb(bios_base + 0x1fcc) + (readb(bios_base + 0x1fcd) << 8); + break; + } + +#if DEBUG_DETECT + printk( " %x,", base ); +#endif + + for (flag = 0, i = 0; !flag && i < PORT_COUNT; i++) { + if (base == ports[i]) + ++flag; + } + + if (flag && fdomain_is_valid_port( base )) { + *irq = fdomain_get_irq( base ); + *iobase = base; + return 1; + } + + /* This is a bad sign. It usually means that someone patched the + BIOS signature list (the signatures variable) to contain a BIOS + signature for a board *OTHER THAN* the TMC-1660/TMC-1680. */ + +#if DEBUG_DETECT + printk( " RAM FAILED, " ); +#endif + } + + /* Anyway, the alternative to finding the address in the RAM is to just + search through every possible port address for one that is attached + to the Future Domain card. Don't panic, though, about reading all + these random port addresses -- there are rumors that the Future + Domain BIOS does something very similar. + + Do not, however, check ports which the kernel knows are being used by + another driver. */ + + for (i = 0; i < PORT_COUNT; i++) { + base = ports[i]; + if (check_region( base, 0x10 )) { +#if DEBUG_DETECT + printk( " (%x inuse),", base ); +#endif + continue; + } +#if DEBUG_DETECT + printk( " %x,", base ); +#endif + if ((flag = fdomain_is_valid_port( base ))) break; + } + +#if DEBUG_DETECT + if (flag) printk( " SUCCESS\n" ); + else printk( " FAILURE\n" ); +#endif + + if (!flag) return 0; /* iobase not found */ + + *irq = fdomain_get_irq( base ); + *iobase = base; + + return 1; /* success */ +} + +/* PCI detection function: int fdomain_pci_bios_detect(int* irq, int* + iobase) This function gets the Interrupt Level and I/O base address from + the PCI configuration registers. */ + +#ifdef CONFIG_PCI +static int fdomain_pci_bios_detect( int *irq, int *iobase, struct pci_dev **ret_pdev ) +{ + unsigned int pci_irq; /* PCI interrupt line */ + unsigned long pci_base; /* PCI I/O base address */ + struct pci_dev *pdev = NULL; + +#if DEBUG_DETECT + /* Tell how to print a list of the known PCI devices from bios32 and + list vendor and device IDs being used if in debug mode. */ + + printk( "scsi: INFO: use lspci -v to see list of PCI devices\n" ); + printk( "scsi: TMC-3260 detect:" + " Using Vendor ID: 0x%x and Device ID: 0x%x\n", + PCI_VENDOR_ID_FD, + PCI_DEVICE_ID_FD_36C70 ); +#endif + + if ((pdev = pci_find_device(PCI_VENDOR_ID_FD, PCI_DEVICE_ID_FD_36C70, pdev)) == NULL) + return 0; + if (pci_enable_device(pdev)) return 0; + +#if DEBUG_DETECT + printk( "scsi: TMC-3260 detect:" + " PCI bus %u, device %u, function %u\n", + pdev->bus->number, + PCI_SLOT(pdev->devfn), + PCI_FUNC(pdev->devfn)); +#endif + + /* We now have the appropriate device function for the FD board so we + just read the PCI config info from the registers. */ + + pci_base = pci_resource_start(pdev, 0); + pci_irq = pdev->irq; + + /* Now we have the I/O base address and interrupt from the PCI + configuration registers. */ + + *irq = pci_irq; + *iobase = pci_base; + *ret_pdev = pdev; + +#if DEBUG_DETECT + printk( "scsi: TMC-3260 detect:" + " IRQ = %d, I/O base = 0x%x [0x%lx]\n", *irq, *iobase, pci_base ); +#endif + + if (!fdomain_is_valid_port( *iobase )) { + printk(KERN_ERR "scsi: PCI card detected, but driver not loaded (invalid port)\n" ); + return 0; + } + + /* Fill in a few global variables. Ugh. */ + bios_major = bios_minor = -1; + PCI_bus = 1; + Quantum = 0; + bios_base = 0; + + return 1; +} +#endif + +static int fdomain_16x0_detect( Scsi_Host_Template *tpnt ) +{ + int retcode; + struct Scsi_Host *shpnt; + struct pci_dev *pdev = NULL; +#if DO_DETECT + int i = 0; + int j = 0; + const int buflen = 255; + Scsi_Cmnd SCinit; + unsigned char do_inquiry[] = { INQUIRY, 0, 0, 0, buflen, 0 }; + unsigned char do_request_sense[] = { REQUEST_SENSE, 0, 0, 0, buflen, 0 }; + unsigned char do_read_capacity[] = { READ_CAPACITY, + 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + unsigned char buf[buflen]; +#endif + + tpnt->proc_name = "fdomain"; + +#ifdef MODULE + if (fdomain) + fdomain_setup(fdomain); +#endif + + if (setup_called) { +#if DEBUG_DETECT + printk( "scsi: No BIOS, using port_base = 0x%x, irq = %d\n", + port_base, interrupt_level ); +#endif + if (!fdomain_is_valid_port( port_base )) { + printk( "scsi: Cannot locate chip at port base 0x%x\n", + port_base ); + printk( "scsi: Bad LILO/INSMOD parameters?\n" ); + return 0; + } + } else { + int flag = 0; + +#ifdef CONFIG_PCI + /* Try PCI detection first */ + flag = fdomain_pci_bios_detect( &interrupt_level, &port_base, &pdev ); +#endif + if (!flag) { + /* Then try ISA bus detection */ + flag = fdomain_isa_detect( &interrupt_level, &port_base ); + + if (!flag) { + printk( "scsi: Detection failed (no card)\n" ); + return 0; + } + } + } + + SCSI_Mode_Cntl_port = port_base + SCSI_Mode_Cntl; + FIFO_Data_Count_port = port_base + FIFO_Data_Count; + Interrupt_Cntl_port = port_base + Interrupt_Cntl; + Interrupt_Status_port = port_base + Interrupt_Status; + Read_FIFO_port = port_base + Read_FIFO; + Read_SCSI_Data_port = port_base + Read_SCSI_Data; + SCSI_Cntl_port = port_base + SCSI_Cntl; + SCSI_Data_NoACK_port = port_base + SCSI_Data_NoACK; + SCSI_Status_port = port_base + SCSI_Status; + TMC_Cntl_port = port_base + TMC_Cntl; + TMC_Status_port = port_base + TMC_Status; + Write_FIFO_port = port_base + Write_FIFO; + Write_SCSI_Data_port = port_base + Write_SCSI_Data; + + fdomain_16x0_bus_reset( NULL); + + if (fdomain_test_loopback()) { + printk(KERN_ERR "scsi: Detection failed (loopback test failed at port base 0x%x)\n", port_base); + if (setup_called) { + printk(KERN_ERR "scsi: Bad LILO/INSMOD parameters?\n"); + } + return 0; + } + + if (this_id) { + tpnt->this_id = (this_id & 0x07); + adapter_mask = (1 << tpnt->this_id); + } else { + if (PCI_bus || (bios_major == 3 && bios_minor >= 2) || bios_major < 0) { + tpnt->this_id = 7; + adapter_mask = 0x80; + } else { + tpnt->this_id = 6; + adapter_mask = 0x40; + } + } + +/* Print out a banner here in case we can't + get resources. */ + + shpnt = scsi_register( tpnt, 0 ); + if(shpnt == NULL) + return 0; + shpnt->irq = interrupt_level; + shpnt->io_port = port_base; + scsi_set_pci_device(shpnt, pdev); + shpnt->n_io_port = 0x10; + print_banner( shpnt ); + + /* Log IRQ with kernel */ + if (!interrupt_level) { + printk(KERN_ERR "scsi: Card Detected, but driver not loaded (no IRQ)\n" ); + return 0; + } else { + /* Register the IRQ with the kernel */ + + retcode = request_irq( interrupt_level, + do_fdomain_16x0_intr, pdev?SA_SHIRQ:0, "fdomain", shpnt); + + if (retcode < 0) { + if (retcode == -EINVAL) { + printk(KERN_ERR "scsi: IRQ %d is bad!\n", interrupt_level ); + printk(KERN_ERR " This shouldn't happen!\n" ); + printk(KERN_ERR " Send mail to faith@acm.org\n" ); + } else if (retcode == -EBUSY) { + printk(KERN_ERR "scsi: IRQ %d is already in use!\n", interrupt_level ); + printk(KERN_ERR " Please use another IRQ!\n" ); + } else { + printk(KERN_ERR "scsi: Error getting IRQ %d\n", interrupt_level ); + printk(KERN_ERR " This shouldn't happen!\n" ); + printk(KERN_ERR " Send mail to faith@acm.org\n" ); + } + printk(KERN_ERR "scsi: Detected, but driver not loaded (IRQ)\n" ); + return 0; + } + } + + /* Log I/O ports with kernel */ + request_region( port_base, 0x10, "fdomain" ); + +#if DO_DETECT + + /* These routines are here because of the way the SCSI bus behaves after + a reset. This appropriate behavior was not handled correctly by the + higher level SCSI routines when I first wrote this driver. Now, + however, correct scan routines are part of scsi.c and these routines + are no longer needed. However, this code is still good for + debugging. */ + + SCinit.request_buffer = SCinit.buffer = buf; + SCinit.request_bufflen = SCinit.bufflen = sizeof(buf)-1; + SCinit.use_sg = 0; + SCinit.lun = 0; + + printk( "scsi: detection routine scanning for devices:\n" ); + for (i = 0; i < 8; i++) { + SCinit.target = i; + if (i == tpnt->this_id) /* Skip host adapter */ + continue; + memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense)); + retcode = fdomain_16x0_command(&SCinit); + if (!retcode) { + memcpy(SCinit.cmnd, do_inquiry, sizeof(do_inquiry)); + retcode = fdomain_16x0_command(&SCinit); + if (!retcode) { + printk( " SCSI ID %d: ", i ); + for (j = 8; j < (buf[4] < 32 ? buf[4] : 32); j++) + printk( "%c", buf[j] >= 20 ? buf[j] : ' ' ); + memcpy(SCinit.cmnd, do_read_capacity, sizeof(do_read_capacity)); + retcode = fdomain_16x0_command(&SCinit); + if (!retcode) { + unsigned long blocks, size, capacity; + + blocks = (buf[0] << 24) | (buf[1] << 16) + | (buf[2] << 8) | buf[3]; + size = (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7]; + capacity = +( +(blocks / 1024L) * +(size * 10L)) / 1024L; + + printk( "%lu MB (%lu byte blocks)", + ((capacity + 5L) / 10L), size ); + } else { + memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense)); + retcode = fdomain_16x0_command(&SCinit); + } + printk ("\n" ); + } else { + memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense)); + retcode = fdomain_16x0_command(&SCinit); + } + } + } +#endif + + return 1; /* Maximum of one adapter will be detected. */ +} + +static const char *fdomain_16x0_info( struct Scsi_Host *ignore ) +{ + static char buffer[128]; + char *pt; + + strcpy( buffer, "Future Domain 16-bit SCSI Driver Version" ); + if (strchr( VERSION, ':')) { /* Assume VERSION is an RCS Revision string */ + strcat( buffer, strchr( VERSION, ':' ) + 1 ); + pt = strrchr( buffer, '$') - 1; + if (!pt) /* Stripped RCS Revision string? */ + pt = buffer + strlen( buffer ) - 1; + if (*pt != ' ') + ++pt; + *pt = '\0'; + } else { /* Assume VERSION is a number */ + strcat( buffer, " " VERSION ); + } + + return buffer; +} + + /* First pass at /proc information routine. */ +/* + * inout : decides on the direction of the dataflow and the meaning of the + * variables + * buffer: If inout==FALSE data is being written to it else read from it + * *start: If inout==FALSE start of the valid data in the buffer + * offset: If inout==FALSE offset from the beginning of the imaginary file + * from which we start writing into the buffer + * length: If inout==FALSE max number of bytes to be written into the buffer + * else number of bytes in the buffer + */ +static int fdomain_16x0_proc_info( char *buffer, char **start, off_t offset, + int length, int hostno, int inout ) +{ + const char *info = fdomain_16x0_info( NULL ); + int len; + int pos; + int begin; + + if (inout) return(-EINVAL); + + begin = 0; + strcpy( buffer, info ); + strcat( buffer, "\n" ); + + pos = len = strlen( buffer ); + + if(pos < offset) { + len = 0; + begin = pos; + } + + *start = buffer + (offset - begin); /* Start of wanted data */ + len -= (offset - begin); + if(len > length) len = length; + + return(len); +} + +#if 0 +static int fdomain_arbitrate( void ) +{ + int status = 0; + unsigned long timeout; + +#if EVERY_ACCESS + printk( "fdomain_arbitrate()\n" ); +#endif + + outb( 0x00, SCSI_Cntl_port ); /* Disable data drivers */ + outb( adapter_mask, port_base + SCSI_Data_NoACK ); /* Set our id bit */ + outb( 0x04 | PARITY_MASK, TMC_Cntl_port ); /* Start arbitration */ + + timeout = 500; + do { + status = inb( TMC_Status_port ); /* Read adapter status */ + if (status & 0x02) /* Arbitration complete */ + return 0; + mdelay(1); /* Wait one millisecond */ + } while (--timeout); + + /* Make bus idle */ + fdomain_make_bus_idle(); + +#if EVERY_ACCESS + printk( "Arbitration failed, status = %x\n", status ); +#endif +#if ERRORS_ONLY + printk( "scsi: Arbitration failed, status = %x\n", status ); +#endif + return 1; +} +#endif + +static int fdomain_select( int target ) +{ + int status; + unsigned long timeout; + static int flag = 0; + + + outb( 0x82, SCSI_Cntl_port ); /* Bus Enable + Select */ + outb( adapter_mask | (1 << target), SCSI_Data_NoACK_port ); + + /* Stop arbitration and enable parity */ + outb( PARITY_MASK, TMC_Cntl_port ); + + timeout = 350; /* 350 msec */ + + do { + status = inb( SCSI_Status_port ); /* Read adapter status */ + if (status & 1) { /* Busy asserted */ + /* Enable SCSI Bus (on error, should make bus idle with 0) */ + outb( 0x80, SCSI_Cntl_port ); + return 0; + } + mdelay(1); /* wait one msec */ + } while (--timeout); + /* Make bus idle */ + fdomain_make_bus_idle(); +#if EVERY_ACCESS + if (!target) printk( "Selection failed\n" ); +#endif +#if ERRORS_ONLY + if (!target) { + if (!flag) /* Skip first failure for all chips. */ + ++flag; + else + printk( "scsi: Selection failed\n" ); + } +#endif + return 1; +} + +static void my_done(int error) +{ + if (in_command) { + in_command = 0; + outb( 0x00, Interrupt_Cntl_port ); + fdomain_make_bus_idle(); + current_SC->result = error; + if (current_SC->scsi_done) + current_SC->scsi_done( current_SC ); + else panic( "scsi: current_SC->scsi_done() == NULL" ); + } else { + panic( "scsi: my_done() called outside of command\n" ); + } +#if DEBUG_RACE + in_interrupt_flag = 0; +#endif +} + +static void do_fdomain_16x0_intr( int irq, void *dev_id, struct pt_regs * regs ) +{ + unsigned long flags; + int status; + int done = 0; + unsigned data_count; + + /* The fdomain_16x0_intr is only called via + the interrupt handler. The goal of the + sti() here is to allow other + interruptions while this routine is + running. */ + + /* Check for other IRQ sources */ + if((inb(TMC_Status_port)&0x01)==0) + return; + + /* It is our IRQ */ + outb( 0x00, Interrupt_Cntl_port ); + + /* We usually have one spurious interrupt after each command. Ignore it. */ + if (!in_command || !current_SC) { /* Spurious interrupt */ +#if EVERY_ACCESS + printk( "Spurious interrupt, in_command = %d, current_SC = %x\n", + in_command, current_SC ); +#endif + return; + } + + /* Abort calls my_done, so we do nothing here. */ + if (current_SC->SCp.phase & aborted) { +#if DEBUG_ABORT + printk( "scsi: Interrupt after abort, ignoring\n" ); +#endif + /* + return; */ + } + +#if DEBUG_RACE + ++in_interrupt_flag; +#endif + + if (current_SC->SCp.phase & in_arbitration) { + status = inb( TMC_Status_port ); /* Read adapter status */ + if (!(status & 0x02)) { +#if EVERY_ACCESS + printk( " AFAIL " ); +#endif + spin_lock_irqsave(current_SC->host->host_lock, flags); + my_done( DID_BUS_BUSY << 16 ); + spin_unlock_irqrestore(current_SC->host->host_lock, flags); + return; + } + current_SC->SCp.phase = in_selection; + + outb( 0x40 | FIFO_COUNT, Interrupt_Cntl_port ); + + outb( 0x82, SCSI_Cntl_port ); /* Bus Enable + Select */ + outb( adapter_mask | (1 << current_SC->target), SCSI_Data_NoACK_port ); + + /* Stop arbitration and enable parity */ + outb( 0x10 | PARITY_MASK, TMC_Cntl_port ); +#if DEBUG_RACE + in_interrupt_flag = 0; +#endif + return; + } else if (current_SC->SCp.phase & in_selection) { + status = inb( SCSI_Status_port ); + if (!(status & 0x01)) { + /* Try again, for slow devices */ + if (fdomain_select( current_SC->target )) { +#if EVERY_ACCESS + printk( " SFAIL " ); +#endif + spin_lock_irqsave(current_SC->host->host_lock, flags); + my_done( DID_NO_CONNECT << 16 ); + spin_unlock_irqrestore(current_SC->host->host_lock, flags); + return; + } else { +#if EVERY_ACCESS + printk( " AltSel " ); +#endif + /* Stop arbitration and enable parity */ + outb( 0x10 | PARITY_MASK, TMC_Cntl_port ); + } + } + current_SC->SCp.phase = in_other; + outb( 0x90 | FIFO_COUNT, Interrupt_Cntl_port ); + outb( 0x80, SCSI_Cntl_port ); +#if DEBUG_RACE + in_interrupt_flag = 0; +#endif + return; + } + + /* current_SC->SCp.phase == in_other: this is the body of the routine */ + + status = inb( SCSI_Status_port ); + + if (status & 0x10) { /* REQ */ + + switch (status & 0x0e) { + + case 0x08: /* COMMAND OUT */ + outb( current_SC->cmnd[current_SC->SCp.sent_command++], + Write_SCSI_Data_port ); +#if EVERY_ACCESS + printk( "CMD = %x,", + current_SC->cmnd[ current_SC->SCp.sent_command - 1] ); +#endif + break; + case 0x00: /* DATA OUT -- tmc18c50/tmc18c30 only */ + if (chip != tmc1800 && !current_SC->SCp.have_data_in) { + current_SC->SCp.have_data_in = -1; + outb( 0xd0 | PARITY_MASK, TMC_Cntl_port ); + } + break; + case 0x04: /* DATA IN -- tmc18c50/tmc18c30 only */ + if (chip != tmc1800 && !current_SC->SCp.have_data_in) { + current_SC->SCp.have_data_in = 1; + outb( 0x90 | PARITY_MASK, TMC_Cntl_port ); + } + break; + case 0x0c: /* STATUS IN */ + current_SC->SCp.Status = inb( Read_SCSI_Data_port ); +#if EVERY_ACCESS + printk( "Status = %x, ", current_SC->SCp.Status ); +#endif +#if ERRORS_ONLY + if (current_SC->SCp.Status + && current_SC->SCp.Status != 2 + && current_SC->SCp.Status != 8) { + printk( "scsi: target = %d, command = %x, status = %x\n", + current_SC->target, + current_SC->cmnd[0], + current_SC->SCp.Status ); + } +#endif + break; + case 0x0a: /* MESSAGE OUT */ + outb( MESSAGE_REJECT, Write_SCSI_Data_port ); /* Reject */ + break; + case 0x0e: /* MESSAGE IN */ + current_SC->SCp.Message = inb( Read_SCSI_Data_port ); +#if EVERY_ACCESS + printk( "Message = %x, ", current_SC->SCp.Message ); +#endif + if (!current_SC->SCp.Message) ++done; +#if DEBUG_MESSAGES || EVERY_ACCESS + if (current_SC->SCp.Message) { + printk( "scsi: message = %x\n", + current_SC->SCp.Message ); + } +#endif + break; + } + } + + if (chip == tmc1800 && !current_SC->SCp.have_data_in + && (current_SC->SCp.sent_command >= current_SC->cmd_len)) { + + if(scsi_to_pci_dma_dir(current_SC->sc_data_direction) == PCI_DMA_TODEVICE) + { + current_SC->SCp.have_data_in = -1; + outb( 0xd0 | PARITY_MASK, TMC_Cntl_port ); + } + else + { + current_SC->SCp.have_data_in = 1; + outb( 0x90 | PARITY_MASK, TMC_Cntl_port ); + } + } + + if (current_SC->SCp.have_data_in == -1) { /* DATA OUT */ + while ( (data_count = FIFO_Size - inw( FIFO_Data_Count_port )) > 512 ) { +#if EVERY_ACCESS + printk( "DC=%d, ", data_count ) ; +#endif + if (data_count > current_SC->SCp.this_residual) + data_count = current_SC->SCp.this_residual; + if (data_count > 0) { +#if EVERY_ACCESS + printk( "%d OUT, ", data_count ); +#endif + if (data_count == 1) { + outb( *current_SC->SCp.ptr++, Write_FIFO_port ); + --current_SC->SCp.this_residual; + } else { + data_count >>= 1; + outsw( Write_FIFO_port, current_SC->SCp.ptr, data_count ); + current_SC->SCp.ptr += 2 * data_count; + current_SC->SCp.this_residual -= 2 * data_count; + } + } + if (!current_SC->SCp.this_residual) { + if (current_SC->SCp.buffers_residual) { + --current_SC->SCp.buffers_residual; + ++current_SC->SCp.buffer; + current_SC->SCp.ptr = page_address(current_SC->SCp.buffer->page) + current_SC->SCp.buffer->offset; + current_SC->SCp.this_residual = current_SC->SCp.buffer->length; + } else + break; + } + } + } + + if (current_SC->SCp.have_data_in == 1) { /* DATA IN */ + while ((data_count = inw( FIFO_Data_Count_port )) > 0) { +#if EVERY_ACCESS + printk( "DC=%d, ", data_count ); +#endif + if (data_count > current_SC->SCp.this_residual) + data_count = current_SC->SCp.this_residual; + if (data_count) { +#if EVERY_ACCESS + printk( "%d IN, ", data_count ); +#endif + if (data_count == 1) { + *current_SC->SCp.ptr++ = inb( Read_FIFO_port ); + --current_SC->SCp.this_residual; + } else { + data_count >>= 1; /* Number of words */ + insw( Read_FIFO_port, current_SC->SCp.ptr, data_count ); + current_SC->SCp.ptr += 2 * data_count; + current_SC->SCp.this_residual -= 2 * data_count; + } + } + if (!current_SC->SCp.this_residual + && current_SC->SCp.buffers_residual) { + --current_SC->SCp.buffers_residual; + ++current_SC->SCp.buffer; + current_SC->SCp.ptr = page_address(current_SC->SCp.buffer->page) + current_SC->SCp.buffer->offset; + current_SC->SCp.this_residual = current_SC->SCp.buffer->length; + } + } + } + + if (done) { +#if EVERY_ACCESS + printk( " ** IN DONE %d ** ", current_SC->SCp.have_data_in ); +#endif + +#if ERRORS_ONLY + if (current_SC->cmnd[0] == REQUEST_SENSE && !current_SC->SCp.Status) { + if ((unsigned char)(*((char *)current_SC->request_buffer+2)) & 0x0f) { + unsigned char key; + unsigned char code; + unsigned char qualifier; + + key = (unsigned char)(*((char *)current_SC->request_buffer + 2)) + & 0x0f; + code = (unsigned char)(*((char *)current_SC->request_buffer + 12)); + qualifier = (unsigned char)(*((char *)current_SC->request_buffer + + 13)); + + if (key != UNIT_ATTENTION + && !(key == NOT_READY + && code == 0x04 + && (!qualifier || qualifier == 0x02 || qualifier == 0x01)) + && !(key == ILLEGAL_REQUEST && (code == 0x25 + || code == 0x24 + || !code))) + + printk( "scsi: REQUEST SENSE" + " Key = %x, Code = %x, Qualifier = %x\n", + key, code, qualifier ); + } + } +#endif +#if EVERY_ACCESS + printk( "BEFORE MY_DONE. . ." ); +#endif + spin_lock_irqsave(current_SC->host->host_lock, flags); + my_done( (current_SC->SCp.Status & 0xff) + | ((current_SC->SCp.Message & 0xff) << 8) | (DID_OK << 16) ); + spin_unlock_irqrestore(current_SC->host->host_lock, flags); +#if EVERY_ACCESS + printk( "RETURNING.\n" ); +#endif + + } else { + if (current_SC->SCp.phase & disconnect) { + outb( 0xd0 | FIFO_COUNT, Interrupt_Cntl_port ); + outb( 0x00, SCSI_Cntl_port ); + } else { + outb( 0x90 | FIFO_COUNT, Interrupt_Cntl_port ); + } + } +#if DEBUG_RACE + in_interrupt_flag = 0; +#endif + return; +} + +static int fdomain_16x0_queue( Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)) +{ + if (in_command) { + panic( "scsi: fdomain_16x0_queue() NOT REENTRANT!\n" ); + } +#if EVERY_ACCESS + printk( "queue: target = %d cmnd = 0x%02x pieces = %d size = %u\n", + SCpnt->target, + *(unsigned char *)SCpnt->cmnd, + SCpnt->use_sg, + SCpnt->request_bufflen ); +#endif + + fdomain_make_bus_idle(); + + current_SC = SCpnt; /* Save this for the done function */ + current_SC->scsi_done = done; + + /* Initialize static data */ + + if (current_SC->use_sg) { + current_SC->SCp.buffer = + (struct scatterlist *)current_SC->request_buffer; + current_SC->SCp.ptr = page_address(current_SC->SCp.buffer->page) + current_SC->SCp.buffer->offset; + current_SC->SCp.this_residual = current_SC->SCp.buffer->length; + current_SC->SCp.buffers_residual = current_SC->use_sg - 1; + } else { + current_SC->SCp.ptr = (char *)current_SC->request_buffer; + current_SC->SCp.this_residual = current_SC->request_bufflen; + current_SC->SCp.buffer = NULL; + current_SC->SCp.buffers_residual = 0; + } + + + current_SC->SCp.Status = 0; + current_SC->SCp.Message = 0; + current_SC->SCp.have_data_in = 0; + current_SC->SCp.sent_command = 0; + current_SC->SCp.phase = in_arbitration; + + /* Start arbitration */ + outb( 0x00, Interrupt_Cntl_port ); + outb( 0x00, SCSI_Cntl_port ); /* Disable data drivers */ + outb( adapter_mask, SCSI_Data_NoACK_port ); /* Set our id bit */ + ++in_command; + outb( 0x20, Interrupt_Cntl_port ); + outb( 0x14 | PARITY_MASK, TMC_Cntl_port ); /* Start arbitration */ + + return 0; +} + +/* The following code, which simulates the old-style command function, was + taken from Tommy Thorn's aha1542.c file. This code is Copyright (C) + 1992 Tommy Thorn. */ + +static volatile int internal_done_flag = 0; +static volatile int internal_done_errcode = 0; + +static void internal_done(Scsi_Cmnd *SCpnt) +{ + internal_done_errcode = SCpnt->result; + ++internal_done_flag; +} + +static int fdomain_16x0_command(Scsi_Cmnd *SCpnt) +{ + fdomain_16x0_queue(SCpnt, internal_done); + + while (!internal_done_flag) + cpu_relax(); + internal_done_flag = 0; + return internal_done_errcode; +} + +/* End of code derived from Tommy Thorn's work. */ + +static void print_info(Scsi_Cmnd *SCpnt) +{ + unsigned int imr; + unsigned int irr; + unsigned int isr; + + if (!SCpnt || !SCpnt->host) { + printk(KERN_WARNING "scsi: Cannot provide detailed information\n"); + return; + } + + printk(KERN_INFO "%s\n", fdomain_16x0_info( SCpnt->host ) ); + print_banner(SCpnt->host); + switch (SCpnt->SCp.phase) { + case in_arbitration: printk("arbitration"); break; + case in_selection: printk("selection"); break; + case in_other: printk("other"); break; + default: printk("unknown"); break; + } + + printk( " (%d), target = %d cmnd = 0x%02x pieces = %d size = %u\n", + SCpnt->SCp.phase, + SCpnt->target, + *(unsigned char *)SCpnt->cmnd, + SCpnt->use_sg, + SCpnt->request_bufflen ); + printk( "sent_command = %d, have_data_in = %d, timeout = %d\n", + SCpnt->SCp.sent_command, + SCpnt->SCp.have_data_in, + SCpnt->timeout ); +#if DEBUG_RACE + printk( "in_interrupt_flag = %d\n", in_interrupt_flag ); +#endif + + imr = (inb( 0x0a1 ) << 8) + inb( 0x21 ); + outb( 0x0a, 0xa0 ); + irr = inb( 0xa0 ) << 8; + outb( 0x0a, 0x20 ); + irr += inb( 0x20 ); + outb( 0x0b, 0xa0 ); + isr = inb( 0xa0 ) << 8; + outb( 0x0b, 0x20 ); + isr += inb( 0x20 ); + + /* Print out interesting information */ + printk( "IMR = 0x%04x", imr ); + if (imr & (1 << interrupt_level)) + printk( " (masked)" ); + printk( ", IRR = 0x%04x, ISR = 0x%04x\n", irr, isr ); + + printk( "SCSI Status = 0x%02x\n", inb( SCSI_Status_port ) ); + printk( "TMC Status = 0x%02x", inb( TMC_Status_port ) ); + if (inb( TMC_Status_port & 1)) + printk( " (interrupt)" ); + printk( "\n" ); + printk( "Interrupt Status = 0x%02x", inb( Interrupt_Status_port ) ); + if (inb( Interrupt_Status_port ) & 0x08) + printk( " (enabled)" ); + printk( "\n" ); + if (chip == tmc18c50 || chip == tmc18c30) { + printk( "FIFO Status = 0x%02x\n", inb( port_base + FIFO_Status ) ); + printk( "Int. Condition = 0x%02x\n", + inb( port_base + Interrupt_Cond ) ); + } + printk( "Configuration 1 = 0x%02x\n", inb( port_base + Configuration1 ) ); + if (chip == tmc18c50 || chip == tmc18c30) + printk( "Configuration 2 = 0x%02x\n", + inb( port_base + Configuration2 ) ); +} + +static int fdomain_16x0_abort( Scsi_Cmnd *SCpnt) +{ +#if EVERY_ACCESS || ERRORS_ONLY || DEBUG_ABORT + printk( "scsi: abort " ); +#endif + + if (!in_command) { +#if EVERY_ACCESS || ERRORS_ONLY + printk( " (not in command)\n" ); +#endif + return FAILED; + } else printk( "\n" ); + +#if DEBUG_ABORT + print_info( SCpnt ); +#endif + + fdomain_make_bus_idle(); + current_SC->SCp.phase |= aborted; + current_SC->result = DID_ABORT << 16; + + /* Aborts are not done well. . . */ + my_done(DID_ABORT << 16); + return SUCCESS; +} + +static int fdomain_16x0_bus_reset(Scsi_Cmnd *SCpnt) +{ + outb( 1, SCSI_Cntl_port ); + do_pause( 2 ); + outb( 0, SCSI_Cntl_port ); + do_pause( 115 ); + outb( 0, SCSI_Mode_Cntl_port ); + outb( PARITY_MASK, TMC_Cntl_port ); + return SUCCESS; +} + +static int fdomain_16x0_host_reset(Scsi_Cmnd *SCpnt) +{ + return FAILED; +} + +static int fdomain_16x0_device_reset(Scsi_Cmnd *SCpnt) +{ + return FAILED; +} + +#include + +static int fdomain_16x0_biosparam(struct scsi_device *sdev, + struct block_device *bdev, + sector_t capacity, int *info_array) +{ + int drive; + unsigned char buf[512 + sizeof (Scsi_Ioctl_Command)]; + Scsi_Ioctl_Command *sic = (Scsi_Ioctl_Command *) buf; + int size = capacity; + unsigned char *data = sic->data; + unsigned char do_read[] = { READ_6, 0, 0, 0, 1, 0 }; + int retcode; + unsigned long offset; + struct drive_info { + unsigned short cylinders; + unsigned char heads; + unsigned char sectors; + } i; + + /* NOTES: + The RAM area starts at 0x1f00 from the bios_base address. + + For BIOS Version 2.0: + + The drive parameter table seems to start at 0x1f30. + The first byte's purpose is not known. + Next is the cylinder, head, and sector information. + The last 4 bytes appear to be the drive's size in sectors. + The other bytes in the drive parameter table are unknown. + If anyone figures them out, please send me mail, and I will + update these notes. + + Tape drives do not get placed in this table. + + There is another table at 0x1fea: + If the byte is 0x01, then the SCSI ID is not in use. + If the byte is 0x18 or 0x48, then the SCSI ID is in use, + although tapes don't seem to be in this table. I haven't + seen any other numbers (in a limited sample). + + 0x1f2d is a drive count (i.e., not including tapes) + + The table at 0x1fcc are I/O ports addresses for the various + operations. I calculate these by hand in this driver code. + + + + For the ISA-200S version of BIOS Version 2.0: + + The drive parameter table starts at 0x1f33. + + WARNING: Assume that the table entry is 25 bytes long. Someone needs + to check this for the Quantum ISA-200S card. + + + + For BIOS Version 3.2: + + The drive parameter table starts at 0x1f70. Each entry is + 0x0a bytes long. Heads are one less than we need to report. + */ + + if (MAJOR(bdev->bd_dev) != SCSI_DISK0_MAJOR) { + printk("scsi: fdomain_16x0_biosparam: too many disks"); + return 0; + } + drive = MINOR(bdev->bd_dev) >> 4; + + if (bios_major == 2) { + switch (Quantum) { + case 2: /* ISA_200S */ + /* The value of 25 has never been verified. + It should probably be 15. */ + offset = bios_base + 0x1f33 + drive * 25; + break; + case 3: /* ISA_250MG */ + offset = bios_base + 0x1f36 + drive * 15; + break; + case 4: /* ISA_200S (another one) */ + offset = bios_base + 0x1f34 + drive * 15; + break; + default: + offset = bios_base + 0x1f31 + drive * 25; + break; + } + memcpy_fromio( &i, offset, sizeof( struct drive_info ) ); + info_array[0] = i.heads; + info_array[1] = i.sectors; + info_array[2] = i.cylinders; + } else if (bios_major == 3 + && bios_minor >= 0 + && bios_minor < 4) { /* 3.0 and 3.2 BIOS */ + memcpy_fromio( &i, bios_base + 0x1f71 + drive * 10, + sizeof( struct drive_info ) ); + info_array[0] = i.heads + 1; + info_array[1] = i.sectors; + info_array[2] = i.cylinders; + } else { /* 3.4 BIOS (and up?) */ + /* This algorithm was provided by Future Domain (much thanks!). */ + + sic->inlen = 0; /* zero bytes out */ + sic->outlen = 512; /* one sector in */ + memcpy( data, do_read, sizeof( do_read ) ); + retcode = kernel_scsi_ioctl( sdev, + SCSI_IOCTL_SEND_COMMAND, + sic ); + if (!retcode /* SCSI command ok */ + && data[511] == 0xaa && data[510] == 0x55 /* Partition table valid */ + && data[0x1c2]) { /* Partition type */ + + /* The partition table layout is as follows: + + Start: 0x1b3h + Offset: 0 = partition status + 1 = starting head + 2 = starting sector and cylinder (word, encoded) + 4 = partition type + 5 = ending head + 6 = ending sector and cylinder (word, encoded) + 8 = starting absolute sector (double word) + c = number of sectors (double word) + Signature: 0x1fe = 0x55aa + + So, this algorithm assumes: + 1) the first partition table is in use, + 2) the data in the first entry is correct, and + 3) partitions never divide cylinders + + Note that (1) may be FALSE for NetBSD (and other BSD flavors), + as well as for Linux. Note also, that Linux doesn't pay any + attention to the fields that are used by this algorithm -- it + only uses the absolute sector data. Recent versions of Linux's + fdisk(1) will fill this data in correctly, and forthcoming + versions will check for consistency. + + Checking for a non-zero partition type is not part of the + Future Domain algorithm, but it seemed to be a reasonable thing + to do, especially in the Linux and BSD worlds. */ + + info_array[0] = data[0x1c3] + 1; /* heads */ + info_array[1] = data[0x1c4] & 0x3f; /* sectors */ + } else { + + /* Note that this new method guarantees that there will always be + less than 1024 cylinders on a platter. This is good for drives + up to approximately 7.85GB (where 1GB = 1024 * 1024 kB). */ + + if ((unsigned int)size >= 0x7e0000U) { + info_array[0] = 0xff; /* heads = 255 */ + info_array[1] = 0x3f; /* sectors = 63 */ + } else if ((unsigned int)size >= 0x200000U) { + info_array[0] = 0x80; /* heads = 128 */ + info_array[1] = 0x3f; /* sectors = 63 */ + } else { + info_array[0] = 0x40; /* heads = 64 */ + info_array[1] = 0x20; /* sectors = 32 */ + } + } + /* For both methods, compute the cylinders */ + info_array[2] = (unsigned int)size / (info_array[0] * info_array[1] ); + } + + return 0; +} + +static int fdomain_16x0_release(struct Scsi_Host *shpnt) +{ + if (shpnt->irq) + free_irq(shpnt->irq, shpnt); + if (shpnt->io_port && shpnt->n_io_port) + release_region(shpnt->io_port, shpnt->n_io_port); + return 0; +} + +MODULE_LICENSE("GPL"); + +/* Eventually this will go into an include file, but this will be later */ +static Scsi_Host_Template driver_template = FDOMAIN_16X0; + +#include "scsi_module.c" diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/scsi/pcmcia/fdomain_stub.c linux.2.5.47-ac4/drivers/scsi/pcmcia/fdomain_stub.c --- linux.2.5.47/drivers/scsi/pcmcia/fdomain_stub.c 2002-10-31 14:57:12.000000000 +0000 +++ linux.2.5.47-ac4/drivers/scsi/pcmcia/fdomain_stub.c 2002-10-31 15:05:33.000000000 +0000 @@ -92,7 +92,8 @@ static dev_link_t *fdomain_attach(void); static void fdomain_detach(dev_link_t *); -static Scsi_Host_Template driver_template = FDOMAIN_16X0; +#define driver_template fdomain_driver_template +extern Scsi_Host_Template fdomain_driver_template; static dev_link_t *dev_list = NULL; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/scsi/pcmcia/Makefile linux.2.5.47-ac4/drivers/scsi/pcmcia/Makefile --- linux.2.5.47/drivers/scsi/pcmcia/Makefile 2002-10-31 14:57:12.000000000 +0000 +++ linux.2.5.47-ac4/drivers/scsi/pcmcia/Makefile 2002-10-31 15:05:33.000000000 +0000 @@ -7,12 +7,14 @@ obj-n := obj- := -vpath %c .. +vpath %c drivers/scsi CFLAGS_aha152x.o = -DPCMCIA -D__NO_VERSION__ -DAHA152X_STAT CFLAGS_fdomain.o = -DPCMCIA -D__NO_VERSION__ CFLAGS_qlogicfas.o = -DPCMCIA -D__NO_VERSION__ +EXTRA_CFLAGS := -Idrivers/scsi + # 16-bit client drivers obj-$(CONFIG_PCMCIA_QLOGIC) += qlogic_cs.o obj-$(CONFIG_PCMCIA_FDOMAIN) += fdomain_cs.o @@ -24,3 +26,12 @@ qlogic_cs-objs := qlogic_stub.o qlogicfas.o include $(TOPDIR)/Rules.make + +drivers/scsi/pcmcia/aha152x.c: drivers/scsi/aha152x.c + cp drivers/scsi/aha152x.c drivers/scsi/pcmcia + +drivers/scsi/pcmcia/fdomain.c: drivers/scsi/fdomain.c + cp drivers/scsi/fdomain.c drivers/scsi/pcmcia + +drivers/scsi/pcmcia/qlogicfas.c: drivers/scsi/qlogicfas.c + cp drivers/scsi/qlogicfas.c drivers/scsi/pcmcia diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/scsi/pcmcia/nsp_cs.h linux.2.5.47-ac4/drivers/scsi/pcmcia/nsp_cs.h --- linux.2.5.47/drivers/scsi/pcmcia/nsp_cs.h 2002-11-11 16:39:10.000000000 +0000 +++ linux.2.5.47-ac4/drivers/scsi/pcmcia/nsp_cs.h 2002-11-11 17:00:08.000000000 +0000 @@ -285,6 +285,7 @@ int length, int hostno, int inout); static int nsp_queuecommand(Scsi_Cmnd *, void (* done)(Scsi_Cmnd *)); + /*static int nsp_eh_abort(Scsi_Cmnd * SCpnt);*/ /*static int nsp_eh_device_reset(Scsi_Cmnd *SCpnt);*/ static int nsp_eh_bus_reset(Scsi_Cmnd *SCpnt); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/scsi/pcmcia/qlogicfas.c linux.2.5.47-ac4/drivers/scsi/pcmcia/qlogicfas.c --- linux.2.5.47/drivers/scsi/pcmcia/qlogicfas.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.47-ac4/drivers/scsi/pcmcia/qlogicfas.c 2002-11-11 20:00:29.000000000 +0000 @@ -0,0 +1,824 @@ +/*----------------------------------------------------------------*/ +/* + Qlogic linux driver - work in progress. No Warranty express or implied. + Use at your own risk. Support Tort Reform so you won't have to read all + these silly disclaimers. + + Copyright 1994, Tom Zerucha. + tz@execpc.com + + Additional Code, and much appreciated help by + Michael A. Griffith + grif@cs.ucr.edu + + Thanks to Eric Youngdale and Dave Hinds for loadable module and PCMCIA + help respectively, and for suffering through my foolishness during the + debugging process. + + Reference Qlogic FAS408 Technical Manual, 53408-510-00A, May 10, 1994 + (you can reference it, but it is incomplete and inaccurate in places) + + Version 0.46 1/30/97 - kernel 1.2.0+ + + Functions as standalone, loadable, and PCMCIA driver, the latter from + Dave Hinds' PCMCIA package. + + Cleaned up 26/10/2002 by Alan Cox as part of the 2.5 + SCSI driver cleanup and audit. This driver still needs work on the + following + - Non terminating hardware waits + - Support multiple cards at a time + - Some layering violations with its pcmcia stub + + Redistributable under terms of the GNU General Public License + + For the avoidance of doubt the "preferred form" of this code is one which + is in an open non patent encumbered format. Where cryptographic key signing + forms part of the process of creating an executable the information + including keys needed to generate an equivalently functional executable + are deemed to be part of the source code. + +*/ +/*----------------------------------------------------------------*/ +/* Configuration */ + +/* Set the following to 2 to use normal interrupt (active high/totempole- + tristate), otherwise use 0 (REQUIRED FOR PCMCIA) for active low, open + drain */ + +#define QL_INT_ACTIVE_HIGH 2 + +/* Set the following to 1 to enable the use of interrupts. Note that 0 tends + to be more stable, but slower (or ties up the system more) */ + +#define QL_USE_IRQ 1 + +/* Set the following to max out the speed of the PIO PseudoDMA transfers, + again, 0 tends to be slower, but more stable. */ + +#define QL_TURBO_PDMA 1 + +/* This should be 1 to enable parity detection */ + +#define QL_ENABLE_PARITY 1 + +/* This will reset all devices when the driver is initialized (during bootup). + The other linux drivers don't do this, but the DOS drivers do, and after + using DOS or some kind of crash or lockup this will bring things back + without requiring a cold boot. It does take some time to recover from a + reset, so it is slower, and I have seen timeouts so that devices weren't + recognized when this was set. */ + +#define QL_RESET_AT_START 0 + +/* crystal frequency in megahertz (for offset 5 and 9) + Please set this for your card. Most Qlogic cards are 40 Mhz. The + Control Concepts ISA (not VLB) is 24 Mhz */ + +#define XTALFREQ 40 + +/**********/ +/* DANGER! modify these at your own risk */ +/* SLOWCABLE can usually be reset to zero if you have a clean setup and + proper termination. The rest are for synchronous transfers and other + advanced features if your device can transfer faster than 5Mb/sec. + If you are really curious, email me for a quick howto until I have + something official */ +/**********/ + +/*****/ +/* config register 1 (offset 8) options */ +/* This needs to be set to 1 if your cabling is long or noisy */ +#define SLOWCABLE 1 + +/*****/ +/* offset 0xc */ +/* This will set fast (10Mhz) synchronous timing when set to 1 + For this to have an effect, FASTCLK must also be 1 */ +#define FASTSCSI 0 + +/* This when set to 1 will set a faster sync transfer rate */ +#define FASTCLK 0 /*(XTALFREQ>25?1:0)*/ + +/*****/ +/* offset 6 */ +/* This is the sync transfer divisor, XTALFREQ/X will be the maximum + achievable data rate (assuming the rest of the system is capable + and set properly) */ +#define SYNCXFRPD 5 /*(XTALFREQ/5)*/ + +/*****/ +/* offset 7 */ +/* This is the count of how many synchronous transfers can take place + i.e. how many reqs can occur before an ack is given. + The maximum value for this is 15, the upper bits can modify + REQ/ACK assertion and deassertion during synchronous transfers + If this is 0, the bus will only transfer asynchronously */ +#define SYNCOFFST 0 +/* for the curious, bits 7&6 control the deassertion delay in 1/2 cycles + of the 40Mhz clock. If FASTCLK is 1, specifying 01 (1/2) will + cause the deassertion to be early by 1/2 clock. Bits 5&4 control + the assertion delay, also in 1/2 clocks (FASTCLK is ignored here). */ + +/*----------------------------------------------------------------*/ +#ifdef PCMCIA +#undef QL_INT_ACTIVE_HIGH +#define QL_INT_ACTIVE_HIGH 0 +#endif + +#include + +#ifdef PCMCIA +#undef MODULE +#endif + +#include /* to get disk capacity */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "scsi.h" +#include "hosts.h" +#include "qlogicfas.h" +#include + +/*----------------------------------------------------------------*/ +/* driver state info, local to driver */ +static int qbase; /* Port */ +static int qinitid; /* initiator ID */ +static int qabort; /* Flag to cause an abort */ +static int qlirq = -1; /* IRQ being used */ +static char qinfo[80]; /* description */ +static Scsi_Cmnd *qlcmd; /* current command being processed */ + +static int qlcfg5 = (XTALFREQ << 5); /* 15625/512 */ +static int qlcfg6 = SYNCXFRPD; +static int qlcfg7 = SYNCOFFST; +static int qlcfg8 = (SLOWCABLE << 7) | (QL_ENABLE_PARITY << 4); +static int qlcfg9 = ((XTALFREQ + 4) / 5); +static int qlcfgc = (FASTCLK << 3) | (FASTSCSI << 4); + +/*----------------------------------------------------------------*/ +/* The qlogic card uses two register maps - These macros select which one */ +#define REG0 ( outb( inb( qbase + 0xd ) & 0x7f , qbase + 0xd ), outb( 4 , qbase + 0xd )) +#define REG1 ( outb( inb( qbase + 0xd ) | 0x80 , qbase + 0xd ), outb( 0xb4 | QL_INT_ACTIVE_HIGH , qbase + 0xd )) + +/* following is watchdog timeout in microseconds */ +#define WATCHDOG 5000000 + +/*----------------------------------------------------------------*/ +/* the following will set the monitor border color (useful to find + where something crashed or gets stuck at and as a simple profiler) */ + +#if 0 +#define rtrc(i) {inb(0x3da);outb(0x31,0x3c0);outb((i),0x3c0);} +#else +#define rtrc(i) {} +#endif + +/*----------------------------------------------------------------*/ +/* local functions */ +/*----------------------------------------------------------------*/ + +/* error recovery - reset everything */ + +static void ql_zap(void) +{ + int x; + + x = inb(qbase + 0xd); + REG0; + outb(3, qbase + 3); /* reset SCSI */ + outb(2, qbase + 3); /* reset chip */ + if (x & 0x80) + REG1; +} + +/* + * Do a pseudo-dma tranfer + */ + +static int ql_pdma(int phase, char *request, int reqlen) +{ + int j; + j = 0; + if (phase & 1) { /* in */ +#if QL_TURBO_PDMA + rtrc(4) + /* empty fifo in large chunks */ + if (reqlen >= 128 && (inb(qbase + 8) & 2)) { /* full */ + insl(qbase + 4, request, 32); + reqlen -= 128; + request += 128; + } + while (reqlen >= 84 && !(j & 0xc0)) /* 2/3 */ + if ((j = inb(qbase + 8)) & 4) + { + insl(qbase + 4, request, 21); + reqlen -= 84; + request += 84; + } + if (reqlen >= 44 && (inb(qbase + 8) & 8)) { /* 1/3 */ + insl(qbase + 4, request, 11); + reqlen -= 44; + request += 44; + } +#endif + /* until both empty and int (or until reclen is 0) */ + rtrc(7) + j = 0; + while (reqlen && !((j & 0x10) && (j & 0xc0))) + { + /* while bytes to receive and not empty */ + j &= 0xc0; + while (reqlen && !((j = inb(qbase + 8)) & 0x10)) + { + *request++ = inb(qbase + 4); + reqlen--; + } + if (j & 0x10) + j = inb(qbase + 8); + + } + } else { /* out */ +#if QL_TURBO_PDMA + rtrc(4) + if (reqlen >= 128 && inb(qbase + 8) & 0x10) { /* empty */ + outsl(qbase + 4, request, 32); + reqlen -= 128; + request += 128; + } + while (reqlen >= 84 && !(j & 0xc0)) /* 1/3 */ + if (!((j = inb(qbase + 8)) & 8)) { + outsl(qbase + 4, request, 21); + reqlen -= 84; + request += 84; + } + if (reqlen >= 40 && !(inb(qbase + 8) & 4)) { /* 2/3 */ + outsl(qbase + 4, request, 10); + reqlen -= 40; + request += 40; + } +#endif + /* until full and int (or until reclen is 0) */ + rtrc(7) + j = 0; + while (reqlen && !((j & 2) && (j & 0xc0))) { + /* while bytes to send and not full */ + while (reqlen && !((j = inb(qbase + 8)) & 2)) + { + outb(*request++, qbase + 4); + reqlen--; + } + if (j & 2) + j = inb(qbase + 8); + } + } + /* maybe return reqlen */ + return inb(qbase + 8) & 0xc0; +} + +/* + * Wait for interrupt flag (polled - not real hardware interrupt) + */ + +static int ql_wai(void) +{ + int i, k; + k = 0; + i = jiffies + WATCHDOG; + while (time_before(jiffies, i) && !qabort && !((k = inb(qbase + 4)) & 0xe0)) { + barrier(); + cpu_relax(); + } + if (time_after_eq(jiffies, i)) + return (DID_TIME_OUT); + if (qabort) + return (qabort == 1 ? DID_ABORT : DID_RESET); + if (k & 0x60) + ql_zap(); + if (k & 0x20) + return (DID_PARITY); + if (k & 0x40) + return (DID_ERROR); + return 0; +} + +/* + * Initiate scsi command - queueing handler + * caller must hold host lock + */ + +static void ql_icmd(Scsi_Cmnd * cmd) +{ + unsigned int i; + + qabort = 0; + + REG0; + /* clearing of interrupts and the fifo is needed */ + + inb(qbase + 5); /* clear interrupts */ + if (inb(qbase + 5)) /* if still interrupting */ + outb(2, qbase + 3); /* reset chip */ + else if (inb(qbase + 7) & 0x1f) + outb(1, qbase + 3); /* clear fifo */ + while (inb(qbase + 5)); /* clear ints */ + REG1; + outb(1, qbase + 8); /* set for PIO pseudo DMA */ + outb(0, qbase + 0xb); /* disable ints */ + inb(qbase + 8); /* clear int bits */ + REG0; + outb(0x40, qbase + 0xb); /* enable features */ + + /* configurables */ + outb(qlcfgc, qbase + 0xc); + /* config: no reset interrupt, (initiator) bus id */ + outb(0x40 | qlcfg8 | qinitid, qbase + 8); + outb(qlcfg7, qbase + 7); + outb(qlcfg6, qbase + 6); + /**/ outb(qlcfg5, qbase + 5); /* select timer */ + outb(qlcfg9 & 7, qbase + 9); /* prescaler */ +/* outb(0x99, qbase + 5); */ + outb(cmd->target, qbase + 4); + + for (i = 0; i < cmd->cmd_len; i++) + outb(cmd->cmnd[i], qbase + 2); + + qlcmd = cmd; + outb(0x41, qbase + 3); /* select and send command */ +} + +/* + * Process scsi command - usually after interrupt + */ + +static unsigned int ql_pcmd(Scsi_Cmnd * cmd) +{ + unsigned int i, j, k; + unsigned int result; /* ultimate return result */ + unsigned int status; /* scsi returned status */ + unsigned int message; /* scsi returned message */ + unsigned int phase; /* recorded scsi phase */ + unsigned int reqlen; /* total length of transfer */ + struct scatterlist *sglist; /* scatter-gather list pointer */ + unsigned int sgcount; /* sg counter */ + char *buf; + + rtrc(1) + j = inb(qbase + 6); + i = inb(qbase + 5); + if (i == 0x20) { + return (DID_NO_CONNECT << 16); + } + i |= inb(qbase + 5); /* the 0x10 bit can be set after the 0x08 */ + if (i != 0x18) { + printk(KERN_ERR "Ql:Bad Interrupt status:%02x\n", i); + ql_zap(); + return (DID_BAD_INTR << 16); + } + j &= 7; /* j = inb( qbase + 7 ) >> 5; */ + + /* correct status is supposed to be step 4 */ + /* it sometimes returns step 3 but with 0 bytes left to send */ + /* We can try stuffing the FIFO with the max each time, but we will get a + sequence of 3 if any bytes are left (but we do flush the FIFO anyway */ + + if (j != 3 && j != 4) { + printk(KERN_ERR "Ql:Bad sequence for command %d, int %02X, cmdleft = %d\n", + j, i, inb(qbase + 7) & 0x1f); + ql_zap(); + return (DID_ERROR << 16); + } + result = DID_OK; + if (inb(qbase + 7) & 0x1f) /* if some bytes in fifo */ + outb(1, qbase + 3); /* clear fifo */ + /* note that request_bufflen is the total xfer size when sg is used */ + reqlen = cmd->request_bufflen; + /* note that it won't work if transfers > 16M are requested */ + if (reqlen && !((phase = inb(qbase + 4)) & 6)) { /* data phase */ + rtrc(2) + outb(reqlen, qbase); /* low-mid xfer cnt */ + outb(reqlen >> 8, qbase + 1); /* low-mid xfer cnt */ + outb(reqlen >> 16, qbase + 0xe); /* high xfer cnt */ + outb(0x90, qbase + 3); /* command do xfer */ + /* PIO pseudo DMA to buffer or sglist */ + REG1; + if (!cmd->use_sg) + ql_pdma(phase, cmd->request_buffer, + cmd->request_bufflen); + else { + sgcount = cmd->use_sg; + sglist = cmd->request_buffer; + while (sgcount--) { + if (qabort) { + REG0; + return ((qabort == 1 ? DID_ABORT : DID_RESET) << 16); + } + buf = page_address(sglist->page) + sglist->offset; + if (ql_pdma(phase, buf, sglist->length)) + break; + sglist++; + } + } + REG0; + rtrc(2) + /* + * Wait for irq (split into second state of irq handler + * if this can take time) + */ + if ((k = ql_wai())) + return (k << 16); + k = inb(qbase + 5); /* should be 0x10, bus service */ + } + + /* + * Enter Status (and Message In) Phase + */ + + k = jiffies + WATCHDOG; + + while (time_before(jiffies, k) && !qabort && !(inb(qbase + 4) & 6)) + cpu_relax(); /* wait for status phase */ + + if (time_after_eq(jiffies, k)) { + ql_zap(); + return (DID_TIME_OUT << 16); + } + + /* FIXME: timeout ?? */ + while (inb(qbase + 5)) + cpu_relax(); /* clear pending ints */ + + if (qabort) + return ((qabort == 1 ? DID_ABORT : DID_RESET) << 16); + + outb(0x11, qbase + 3); /* get status and message */ + if ((k = ql_wai())) + return (k << 16); + i = inb(qbase + 5); /* get chip irq stat */ + j = inb(qbase + 7) & 0x1f; /* and bytes rec'd */ + status = inb(qbase + 2); + message = inb(qbase + 2); + + /* + * Should get function complete int if Status and message, else + * bus serv if only status + */ + if (!((i == 8 && j == 2) || (i == 0x10 && j == 1))) { + printk(KERN_ERR "Ql:Error during status phase, int=%02X, %d bytes recd\n", i, j); + result = DID_ERROR; + } + outb(0x12, qbase + 3); /* done, disconnect */ + rtrc(1) + if ((k = ql_wai())) + return (k << 16); + + /* + * Should get bus service interrupt and disconnect interrupt + */ + + i = inb(qbase + 5); /* should be bus service */ + while (!qabort && ((i & 0x20) != 0x20)) { + barrier(); + cpu_relax(); + i |= inb(qbase + 5); + } + rtrc(0) + + if (qabort) + return ((qabort == 1 ? DID_ABORT : DID_RESET) << 16); + + return (result << 16) | (message << 8) | (status & STATUS_MASK); +} + +#if QL_USE_IRQ + +/* + * Interrupt handler + */ + +static void ql_ihandl(int irq, void *dev_id, struct pt_regs *regs) +{ + Scsi_Cmnd *icmd; + REG0; + + if (!(inb(qbase + 4) & 0x80)) /* false alarm? */ + return; + + if (qlcmd == NULL) { /* no command to process? */ + int i; + i = 16; + while (i-- && inb(qbase + 5)); /* maybe also ql_zap() */ + return; + } + icmd = qlcmd; + icmd->result = ql_pcmd(icmd); + qlcmd = NULL; + /* + * If result is CHECK CONDITION done calls qcommand to request + * sense + */ + (icmd->scsi_done) (icmd); +} + +static void do_ql_ihandl(int irq, void *dev_id, struct pt_regs *regs) +{ + unsigned long flags; + struct Scsi_Host *host = dev_id; + + spin_lock_irqsave(host->host_lock, flags); + ql_ihandl(irq, dev_id, regs); + spin_unlock_irqrestore(host->host_lock, flags); +} + +#endif + +#if QL_USE_IRQ + +static void qlidone(Scsi_Cmnd * cmd) +{ +} /* null function */ + +#endif + +/* + * Synchronous command processing + */ + +static int qlogicfas_command(Scsi_Cmnd * cmd) +{ + int k; +#if QL_USE_IRQ + if (qlirq >= 0) { + qlogicfas_queuecommand(cmd, qlidone); + while (qlcmd != NULL) + { + cpu_relax(); + barrier(); + } + return cmd->result; + } +#endif + + /* + * Non-irq version + */ + + if (cmd->target == qinitid) + return (DID_BAD_TARGET << 16); + ql_icmd(cmd); + if ((k = ql_wai())) + return (k << 16); + return ql_pcmd(cmd); + +} + +#if QL_USE_IRQ + +/* + * Queued command + */ + +int qlogicfas_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) +{ + if (cmd->target == qinitid) { + cmd->result = DID_BAD_TARGET << 16; + done(cmd); + return 0; + } + + cmd->scsi_done = done; + /* wait for the last command's interrupt to finish */ + while (qlcmd != NULL) { + barrier(); + cpu_relax(); + } + ql_icmd(cmd); + return 0; +} +#else +int qlogicfas_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) +{ + return 1; +} +#endif + +#ifdef PCMCIA + +/* + * Allow PCMCIA code to preset the port + * port should be 0 and irq to -1 respectively for autoprobing + */ + +void qlogicfas_preset(int port, int irq) +{ + qbase = port; + qlirq = irq; +} + +#endif + +/* + * Look for qlogic card and init if found + */ + +int __devinit qlogicfas_detect(Scsi_Host_Template * host) +{ + int i, j; /* these are only used by IRQ detect */ + int qltyp; /* type of chip */ + struct Scsi_Host *hreg; /* registered host structure */ + + host->proc_name = "qlogicfas"; + + /* Qlogic Cards only exist at 0x230 or 0x330 (the chip itself + * decodes the address - I check 230 first since MIDI cards are + * typically at 0x330 + * + * Theoretically, two Qlogic cards can coexist in the same system. + * This should work by simply using this as a loadable module for + * the second card, but I haven't tested this. + */ + + if (!qbase) { + for (qbase = 0x230; qbase < 0x430; qbase += 0x100) { + if (!request_region(qbase, 0x10, "qlogicfas")) + continue; + REG1; + if (((inb(qbase + 0xe) ^ inb(qbase + 0xe)) == 7) + && ((inb(qbase + 0xe) ^ inb(qbase + 0xe)) == 7)) + break; + release_region(qbase, 0x10); + } + if (qbase == 0x430) + return 0; + } else + printk(KERN_INFO "Ql: Using preset base address of %03x\n", qbase); + + qltyp = inb(qbase + 0xe) & 0xf8; + qinitid = host->this_id; + if (qinitid < 0) + qinitid = 7; /* if no ID, use 7 */ + outb(1, qbase + 8); /* set for PIO pseudo DMA */ + REG0; + outb(0x40 | qlcfg8 | qinitid, qbase + 8); /* (ini) bus id, disable scsi rst */ + outb(qlcfg5, qbase + 5); /* select timer */ + outb(qlcfg9, qbase + 9); /* prescaler */ + +#if QL_RESET_AT_START + outb(3, qbase + 3); + REG1; + /* FIXME: timeout */ + while (inb(qbase + 0xf) & 4) + cpu_relax(); + REG0; +#endif + +#if QL_USE_IRQ + /* + * IRQ probe - toggle pin and check request pending + */ + + if (qlirq == -1) { + i = 0xffff; + j = 3; + outb(0x90, qbase + 3); /* illegal command - cause interrupt */ + REG1; + outb(10, 0x20); /* access pending interrupt map */ + outb(10, 0xa0); + while (j--) { + outb(0xb0 | QL_INT_ACTIVE_HIGH, qbase + 0xd); /* int pin off */ + i &= ~(inb(0x20) | (inb(0xa0) << 8)); /* find IRQ off */ + outb(0xb4 | QL_INT_ACTIVE_HIGH, qbase + 0xd); /* int pin on */ + i &= inb(0x20) | (inb(0xa0) << 8); /* find IRQ on */ + } + REG0; + while (inb(qbase + 5)); /* purge int */ + j = -1; + while (i) /* find on bit */ + i >>= 1, j++; /* should check for exactly 1 on */ + qlirq = j; + } else + printk(KERN_INFO "Ql: Using preset IRQ %d\n", qlirq); + + if (qlirq >= 0 && !request_irq(qlirq, do_ql_ihandl, 0, "qlogicfas", NULL)) + host->can_queue = 1; +#endif + hreg = scsi_register(host, 0); /* no host data */ + if (!hreg) + goto err_release_mem; + hreg->io_port = qbase; + hreg->n_io_port = 16; + hreg->dma_channel = -1; + if (qlirq != -1) + hreg->irq = qlirq; + + sprintf(qinfo, + "Qlogicfas Driver version 0.46, chip %02X at %03X, IRQ %d, TPdma:%d", + qltyp, qbase, qlirq, QL_TURBO_PDMA); + host->name = qinfo; + + return 1; + +err_release_mem: + release_region(qbase, 0x10); + if (host->can_queue) + free_irq(qlirq, do_ql_ihandl); + return 0; + +} + +/* + * Return bios parameters + */ + +int qlogicfas_biosparam(struct scsi_device * disk, + struct block_device *dev, + sector_t capacity, int ip[]) +{ +/* This should mimic the DOS Qlogic driver's behavior exactly */ + ip[0] = 0x40; + ip[1] = 0x20; + ip[2] = (unsigned long) capacity / (ip[0] * ip[1]); + if (ip[2] > 1024) { + ip[0] = 0xff; + ip[1] = 0x3f; + ip[2] = (unsigned long) capacity / (ip[0] * ip[1]); +#if 0 + if (ip[2] > 1023) + ip[2] = 1023; +#endif + } + return 0; +} + +/* + * Abort a command in progress + */ + +static int qlogicfas_abort(Scsi_Cmnd * cmd) +{ + qabort = 1; + ql_zap(); + return SUCCESS; +} + +/* + * Reset SCSI bus + * FIXME: This function is invoked with cmd = NULL directly by + * the PCMCIA qlogic_stub code. This wants fixing + */ + +static int qlogicfas_bus_reset(Scsi_Cmnd * cmd) +{ + qabort = 2; + ql_zap(); + return SUCCESS; +} + +/* + * Reset SCSI host controller + */ + +static int qlogicfas_host_reset(Scsi_Cmnd * cmd) +{ + return FAILED; +} + +/* + * Reset SCSI device + */ + +static int qlogicfas_device_reset(Scsi_Cmnd * cmd) +{ + return FAILED; +} + +/* + * Return info string + */ + +static const char *qlogicfas_info(struct Scsi_Host *host) +{ + return qinfo; +} + +MODULE_AUTHOR("Tom Zerucha, Michael Griffith"); +MODULE_DESCRIPTION("Driver for the Qlogic FAS SCSI controllers"); +MODULE_LICENSE("GPL"); + +/* + * The driver template is also needed for PCMCIA + */ + +Scsi_Host_Template qlogicfas_driver_template = QLOGICFAS; +#define driver_template qlogicfas_driver_template + +#include "scsi_module.c" + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/scsi/pcmcia/qlogic_stub.c linux.2.5.47-ac4/drivers/scsi/pcmcia/qlogic_stub.c --- linux.2.5.47/drivers/scsi/pcmcia/qlogic_stub.c 2002-10-31 14:57:12.000000000 +0000 +++ linux.2.5.47-ac4/drivers/scsi/pcmcia/qlogic_stub.c 2002-10-31 15:05:33.000000000 +0000 @@ -50,8 +50,6 @@ #include <../drivers/scsi/qlogicfas.h> -#define qlogic_reset(h) qlogicfas_reset(h, 0) - #include #include #include @@ -65,8 +63,7 @@ static int pc_debug = PCMCIA_DEBUG; MODULE_PARM(pc_debug, "i"); #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) -static char *version = -"qlogic_cs.c 1.79 2000/06/12 21:27:26 (David Hinds)"; +static char *version = "qlogic_cs.c 1.79-ac 2002/10/26 (David Hinds)"; #else #define DEBUG(n, args...) #endif @@ -76,7 +73,7 @@ /* Parameters that can be set with 'insmod' */ /* Bit map of interrupts to choose from */ -static u_int irq_mask = 0xdeb8; +static unsigned int irq_mask = 0xdeb8; static int irq_list[4] = { -1 }; MODULE_PARM(irq_mask, "i"); @@ -85,20 +82,21 @@ /*====================================================================*/ typedef struct scsi_info_t { - dev_link_t link; - u_short manf_id; - int ndev; - dev_node_t node[8]; + dev_link_t link; + unsigned short manf_id; + int ndev; + dev_node_t node[8]; } scsi_info_t; static void qlogic_release(u_long arg); -static int qlogic_event(event_t event, int priority, - event_callback_args_t *args); +static int qlogic_event(event_t event, int priority, event_callback_args_t * args); static dev_link_t *qlogic_attach(void); static void qlogic_detach(dev_link_t *); -static Scsi_Host_Template driver_template = QLOGICFAS; +/* Import our driver template */ +extern Scsi_Host_Template qlogicfas_driver_template; +#define driver_template qlogicfas_driver_template static dev_link_t *dev_list = NULL; @@ -108,97 +106,97 @@ static void cs_error(client_handle_t handle, int func, int ret) { - error_info_t err = { func, ret }; - CardServices(ReportError, handle, &err); + error_info_t err = { func, ret }; + CardServices(ReportError, handle, &err); } /*====================================================================*/ static dev_link_t *qlogic_attach(void) { - scsi_info_t *info; - client_reg_t client_reg; - dev_link_t *link; - int i, ret; - - DEBUG(0, "qlogic_attach()\n"); - - /* Create new SCSI device */ - info = kmalloc(sizeof(*info), GFP_KERNEL); - if (!info) return NULL; - memset(info, 0, sizeof(*info)); - link = &info->link; link->priv = info; - link->release.function = &qlogic_release; - link->release.data = (u_long)link; - - link->io.NumPorts1 = 16; - link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - link->io.IOAddrLines = 10; - link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; - link->irq.IRQInfo1 = IRQ_INFO2_VALID|IRQ_LEVEL_ID; - if (irq_list[0] == -1) - link->irq.IRQInfo2 = irq_mask; - else - for (i = 0; i < 4; i++) - link->irq.IRQInfo2 |= 1 << irq_list[i]; - link->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.Vcc = 50; - link->conf.IntType = INT_MEMORY_AND_IO; - link->conf.Present = PRESENT_OPTION; - - /* Register with Card Services */ - link->next = dev_list; - dev_list = link; - client_reg.dev_info = &dev_info; - client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; - client_reg.event_handler = &qlogic_event; - client_reg.EventMask = - CS_EVENT_RESET_REQUEST | CS_EVENT_CARD_RESET | - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.Version = 0x0210; - client_reg.event_callback_args.client_data = link; - ret = CardServices(RegisterClient, &link->handle, &client_reg); - if (ret != 0) { - cs_error(link->handle, RegisterClient, ret); - qlogic_detach(link); - return NULL; - } - - return link; -} /* qlogic_attach */ + scsi_info_t *info; + client_reg_t client_reg; + dev_link_t *link; + int i, ret; + + DEBUG(0, "qlogic_attach()\n"); + + /* Create new SCSI device */ + info = kmalloc(sizeof(*info), GFP_KERNEL); + if (!info) + return NULL; + memset(info, 0, sizeof(*info)); + link = &info->link; + link->priv = info; + link->release.function = &qlogic_release; + link->release.data = (u_long) link; + + link->io.NumPorts1 = 16; + link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; + link->io.IOAddrLines = 10; + link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; + link->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_LEVEL_ID; + if (irq_list[0] == -1) + link->irq.IRQInfo2 = irq_mask; + else + for (i = 0; i < 4; i++) + link->irq.IRQInfo2 |= 1 << irq_list[i]; + link->conf.Attributes = CONF_ENABLE_IRQ; + link->conf.Vcc = 50; + link->conf.IntType = INT_MEMORY_AND_IO; + link->conf.Present = PRESENT_OPTION; + + /* Register with Card Services */ + link->next = dev_list; + dev_list = link; + client_reg.dev_info = &dev_info; + client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; + client_reg.event_handler = &qlogic_event; + client_reg.EventMask = CS_EVENT_RESET_REQUEST | CS_EVENT_CARD_RESET | CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; + client_reg.Version = 0x0210; + client_reg.event_callback_args.client_data = link; + ret = CardServices(RegisterClient, &link->handle, &client_reg); + if (ret != 0) { + cs_error(link->handle, RegisterClient, ret); + qlogic_detach(link); + return NULL; + } + + return link; +} /* qlogic_attach */ /*====================================================================*/ -static void qlogic_detach(dev_link_t *link) +static void qlogic_detach(dev_link_t * link) { - dev_link_t **linkp; + dev_link_t **linkp; - DEBUG(0, "qlogic_detach(0x%p)\n", link); - - /* Locate device structure */ - for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) - if (*linkp == link) break; - if (*linkp == NULL) - return; + DEBUG(0, "qlogic_detach(0x%p)\n", link); - del_timer(&link->release); - if (link->state & DEV_CONFIG) { - qlogic_release((u_long)link); - if (link->state & DEV_STALE_CONFIG) { - link->state |= DEV_STALE_LINK; - return; + /* Locate device structure */ + for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) + if (*linkp == link) + break; + if (*linkp == NULL) + return; + + del_timer_sync(&link->release); + if (link->state & DEV_CONFIG) { + qlogic_release((u_long) link); + if (link->state & DEV_STALE_CONFIG) { + link->state |= DEV_STALE_LINK; + return; + } } - } - if (link->handle) - CardServices(DeregisterClient, link->handle); - - /* Unlink device structure, free bits */ - *linkp = link->next; - kfree(link->priv); - -} /* qlogic_detach */ + if (link->handle) + CardServices(DeregisterClient, link->handle); + + /* Unlink device structure, free bits */ + *linkp = link->next; + kfree(link->priv); + +} /* qlogic_detach */ /*====================================================================*/ @@ -208,220 +206,216 @@ #define CFG_CHECK(fn, args...) \ if (CardServices(fn, args) != 0) goto next_entry -static void qlogic_config(dev_link_t *link) +static void qlogic_config(dev_link_t * link) { - client_handle_t handle = link->handle; - scsi_info_t *info = link->priv; - tuple_t tuple; - cisparse_t parse; - int i, last_ret, last_fn; - u_short tuple_data[32]; - Scsi_Device *dev; - dev_node_t **tail, *node; - struct Scsi_Host *host; - - DEBUG(0, "qlogic_config(0x%p)\n", link); - - tuple.TupleData = (cisdata_t *)tuple_data; - tuple.TupleDataMax = 64; - tuple.TupleOffset = 0; - tuple.DesiredTuple = CISTPL_CONFIG; - CS_CHECK(GetFirstTuple, handle, &tuple); - CS_CHECK(GetTupleData, handle, &tuple); - CS_CHECK(ParseTuple, handle, &tuple, &parse); - link->conf.ConfigBase = parse.config.base; - - tuple.DesiredTuple = CISTPL_MANFID; - if ((CardServices(GetFirstTuple, handle, &tuple) == CS_SUCCESS) && - (CardServices(GetTupleData, handle, &tuple) == CS_SUCCESS)) - info->manf_id = le16_to_cpu(tuple.TupleData[0]); - - /* Configure card */ - driver_template.module = &__this_module; - link->state |= DEV_CONFIG; - - tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - CS_CHECK(GetFirstTuple, handle, &tuple); - while (1) { - CFG_CHECK(GetTupleData, handle, &tuple); - CFG_CHECK(ParseTuple, handle, &tuple, &parse); - link->conf.ConfigIndex = parse.cftable_entry.index; - link->io.BasePort1 = parse.cftable_entry.io.win[0].base; - link->io.NumPorts1 = parse.cftable_entry.io.win[0].len; - if (link->io.BasePort1 != 0) { - i = CardServices(RequestIO, handle, &link->io); - if (i == CS_SUCCESS) break; + client_handle_t handle = link->handle; + scsi_info_t *info = link->priv; + tuple_t tuple; + cisparse_t parse; + int i, last_ret, last_fn; + unsigned short tuple_data[32]; + Scsi_Device *dev; + dev_node_t **tail, *node; + struct Scsi_Host *host; + + DEBUG(0, "qlogic_config(0x%p)\n", link); + + tuple.TupleData = (cisdata_t *) tuple_data; + tuple.TupleDataMax = 64; + tuple.TupleOffset = 0; + tuple.DesiredTuple = CISTPL_CONFIG; + CS_CHECK(GetFirstTuple, handle, &tuple); + CS_CHECK(GetTupleData, handle, &tuple); + CS_CHECK(ParseTuple, handle, &tuple, &parse); + link->conf.ConfigBase = parse.config.base; + + tuple.DesiredTuple = CISTPL_MANFID; + if ((CardServices(GetFirstTuple, handle, &tuple) == CS_SUCCESS) && (CardServices(GetTupleData, handle, &tuple) == CS_SUCCESS)) + info->manf_id = le16_to_cpu(tuple.TupleData[0]); + + /* Configure card */ + driver_template.module = &__this_module; + link->state |= DEV_CONFIG; + + tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; + CS_CHECK(GetFirstTuple, handle, &tuple); + while (1) { + CFG_CHECK(GetTupleData, handle, &tuple); + CFG_CHECK(ParseTuple, handle, &tuple, &parse); + link->conf.ConfigIndex = parse.cftable_entry.index; + link->io.BasePort1 = parse.cftable_entry.io.win[0].base; + link->io.NumPorts1 = parse.cftable_entry.io.win[0].len; + if (link->io.BasePort1 != 0) { + i = CardServices(RequestIO, handle, &link->io); + if (i == CS_SUCCESS) + break; + } + next_entry: + CS_CHECK(GetNextTuple, handle, &tuple); } - next_entry: - CS_CHECK(GetNextTuple, handle, &tuple); - } - - CS_CHECK(RequestIRQ, handle, &link->irq); - CS_CHECK(RequestConfiguration, handle, &link->conf); - - if ((info->manf_id == MANFID_MACNICA) || - (info->manf_id == MANFID_PIONEER) || - (info->manf_id == 0x0098)) { - /* set ATAcmd */ - outb(0xb4, link->io.BasePort1+0xd); - outb(0x24, link->io.BasePort1+0x9); - outb(0x04, link->io.BasePort1+0xd); - } - - /* A bad hack... */ - release_region(link->io.BasePort1, link->io.NumPorts1); - - /* The KXL-810AN has a bigger IO port window */ - if (link->io.NumPorts1 == 32) - qlogicfas_preset(link->io.BasePort1+16, link->irq.AssignedIRQ); - else - qlogicfas_preset(link->io.BasePort1, link->irq.AssignedIRQ); - - scsi_register_host(&driver_template); - - tail = &link->dev; - info->ndev = 0; - for (host = scsi_host_get_next(NULL); host; - host = scsi_host_get_next(host)) - if (host->hostt == &driver_template) - for (dev = host->host_queue; dev; dev = dev->next) { - u_long arg[2], id; - kernel_scsi_ioctl(dev, SCSI_IOCTL_GET_IDLUN, arg); - id = (arg[0]&0x0f) + ((arg[0]>>4)&0xf0) + - ((arg[0]>>8)&0xf00) + ((arg[0]>>12)&0xf000); - node = &info->node[info->ndev]; - node->minor = 0; - switch (dev->type) { - case TYPE_TAPE: - node->major = SCSI_TAPE_MAJOR; - sprintf(node->dev_name, "st#%04lx", id); - break; - case TYPE_DISK: - case TYPE_MOD: - node->major = SCSI_DISK0_MAJOR; - sprintf(node->dev_name, "sd#%04lx", id); - break; - case TYPE_ROM: - case TYPE_WORM: - node->major = SCSI_CDROM_MAJOR; - sprintf(node->dev_name, "sr#%04lx", id); - break; - default: - node->major = SCSI_GENERIC_MAJOR; - sprintf(node->dev_name, "sg#%04lx", id); - break; - } - *tail = node; tail = &node->next; - info->ndev++; + + CS_CHECK(RequestIRQ, handle, &link->irq); + CS_CHECK(RequestConfiguration, handle, &link->conf); + + if ((info->manf_id == MANFID_MACNICA) || (info->manf_id == MANFID_PIONEER) || (info->manf_id == 0x0098)) { + /* set ATAcmd */ + outb(0xb4, link->io.BasePort1 + 0xd); + outb(0x24, link->io.BasePort1 + 0x9); + outb(0x04, link->io.BasePort1 + 0xd); } - *tail = NULL; - if (info->ndev == 0) - printk(KERN_INFO "qlogic_cs: no SCSI devices found\n"); - - link->state &= ~DEV_CONFIG_PENDING; - return; + + /* A bad hack... */ + release_region(link->io.BasePort1, link->io.NumPorts1); + + /* The KXL-810AN has a bigger IO port window */ + if (link->io.NumPorts1 == 32) + qlogicfas_preset(link->io.BasePort1 + 16, link->irq.AssignedIRQ); + else + qlogicfas_preset(link->io.BasePort1, link->irq.AssignedIRQ); + + scsi_register_host(&driver_template); + + tail = &link->dev; + info->ndev = 0; + for (host = scsi_host_get_next(NULL); host; host = scsi_host_get_next(host)) + if (host->hostt == &driver_template) + for (dev = host->host_queue; dev; dev = dev->next) { + u_long arg[2], id; + kernel_scsi_ioctl(dev, SCSI_IOCTL_GET_IDLUN, arg); + id = (arg[0] & 0x0f) + ((arg[0] >> 4) & 0xf0) + ((arg[0] >> 8) & 0xf00) + ((arg[0] >> 12) & 0xf000); + node = &info->node[info->ndev]; + node->minor = 0; + switch (dev->type) { + case TYPE_TAPE: + node->major = SCSI_TAPE_MAJOR; + sprintf(node->dev_name, "st#%04lx", id); + break; + case TYPE_DISK: + case TYPE_MOD: + node->major = SCSI_DISK0_MAJOR; + sprintf(node->dev_name, "sd#%04lx", id); + break; + case TYPE_ROM: + case TYPE_WORM: + node->major = SCSI_CDROM_MAJOR; + sprintf(node->dev_name, "sr#%04lx", id); + break; + default: + node->major = SCSI_GENERIC_MAJOR; + sprintf(node->dev_name, "sg#%04lx", id); + break; + } + *tail = node; + tail = &node->next; + info->ndev++; + } + *tail = NULL; + if (info->ndev == 0) + printk(KERN_INFO "qlogic_cs: no SCSI devices found\n"); + + link->state &= ~DEV_CONFIG_PENDING; + return; cs_failed: - cs_error(link->handle, last_fn, last_ret); - qlogic_release((u_long)link); - return; + cs_error(link->handle, last_fn, last_ret); + qlogic_release((u_long) link); + return; -} /* qlogic_config */ +} /* qlogic_config */ /*====================================================================*/ static void qlogic_release(u_long arg) { - dev_link_t *link = (dev_link_t *)arg; + dev_link_t *link = (dev_link_t *) arg; - DEBUG(0, "qlogic_release(0x%p)\n", link); + DEBUG(0, "qlogic_release(0x%p)\n", link); - if (GET_USE_COUNT(&__this_module) != 0) { - DEBUG(0, "qlogic_cs: release postponed, device still open\n"); - link->state |= DEV_STALE_CONFIG; - return; - } + if (GET_USE_COUNT(&__this_module) != 0) { + DEBUG(0, "qlogic_cs: release postponed, device still open\n"); + link->state |= DEV_STALE_CONFIG; + return; + } + + scsi_unregister_host(&driver_template); + link->dev = NULL; - scsi_unregister_host(&driver_template); - link->dev = NULL; - - CardServices(ReleaseConfiguration, link->handle); - CardServices(ReleaseIO, link->handle, &link->io); - CardServices(ReleaseIRQ, link->handle, &link->irq); - - link->state &= ~DEV_CONFIG; - if (link->state & DEV_STALE_LINK) - qlogic_detach(link); - -} /* qlogic_release */ + CardServices(ReleaseConfiguration, link->handle); + CardServices(ReleaseIO, link->handle, &link->io); + CardServices(ReleaseIRQ, link->handle, &link->irq); + + link->state &= ~DEV_CONFIG; + if (link->state & DEV_STALE_LINK) + qlogic_detach(link); + +} /* qlogic_release */ /*====================================================================*/ -static int qlogic_event(event_t event, int priority, - event_callback_args_t *args) +static int qlogic_event(event_t event, int priority, event_callback_args_t * args) { - dev_link_t *link = args->client_data; + dev_link_t *link = args->client_data; - DEBUG(1, "qlogic_event(0x%06x)\n", event); - - switch (event) { - case CS_EVENT_CARD_REMOVAL: - link->state &= ~DEV_PRESENT; - if (link->state & DEV_CONFIG) - mod_timer(&link->release, jiffies + HZ/20); - break; - case CS_EVENT_CARD_INSERTION: - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - qlogic_config(link); - break; - case CS_EVENT_PM_SUSPEND: - link->state |= DEV_SUSPEND; - /* Fall through... */ - case CS_EVENT_RESET_PHYSICAL: - if (link->state & DEV_CONFIG) - CardServices(ReleaseConfiguration, link->handle); - break; - case CS_EVENT_PM_RESUME: - link->state &= ~DEV_SUSPEND; - /* Fall through... */ - case CS_EVENT_CARD_RESET: - if (link->state & DEV_CONFIG) { - scsi_info_t *info = link->priv; - CardServices(RequestConfiguration, link->handle, &link->conf); - if ((info->manf_id == MANFID_MACNICA) || - (info->manf_id == MANFID_PIONEER) || - (info->manf_id == 0x0098)) { - outb( 0x80, link->io.BasePort1+0xd); - outb( 0x24, link->io.BasePort1+0x9); - outb( 0x04, link->io.BasePort1+0xd); - } - qlogic_reset(NULL); + DEBUG(1, "qlogic_event(0x%06x)\n", event); + + switch (event) { + case CS_EVENT_CARD_REMOVAL: + link->state &= ~DEV_PRESENT; + if (link->state & DEV_CONFIG) + mod_timer(&link->release, jiffies + HZ / 20); + break; + case CS_EVENT_CARD_INSERTION: + link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; + qlogic_config(link); + break; + case CS_EVENT_PM_SUSPEND: + link->state |= DEV_SUSPEND; + /* Fall through... */ + case CS_EVENT_RESET_PHYSICAL: + if (link->state & DEV_CONFIG) + CardServices(ReleaseConfiguration, link->handle); + break; + case CS_EVENT_PM_RESUME: + link->state &= ~DEV_SUSPEND; + /* Fall through... */ + case CS_EVENT_CARD_RESET: + if (link->state & DEV_CONFIG) { + scsi_info_t *info = link->priv; + CardServices(RequestConfiguration, link->handle, &link->conf); + if ((info->manf_id == MANFID_MACNICA) || (info->manf_id == MANFID_PIONEER) || (info->manf_id == 0x0098)) { + outb(0x80, link->io.BasePort1 + 0xd); + outb(0x24, link->io.BasePort1 + 0x9); + outb(0x04, link->io.BasePort1 + 0xd); + } + /* Ugggglllyyyy!!! */ + driver_template.eh_bus_reset_handler(NULL); + } + break; } - break; - } - return 0; -} /* qlogic_event */ + return 0; +} /* qlogic_event */ /*====================================================================*/ -static int __init init_qlogic_cs(void) { - servinfo_t serv; - DEBUG(0, "%s\n", version); - CardServices(GetCardServicesInfo, &serv); - if (serv.Revision != CS_RELEASE_CODE) { - printk(KERN_NOTICE "qlogic_cs: Card Services release " - "does not match!\n"); - return -1; - } - register_pccard_driver(&dev_info, &qlogic_attach, &qlogic_detach); - return 0; +static int __init init_qlogic_cs(void) +{ + servinfo_t serv; + DEBUG(0, "%s\n", version); + CardServices(GetCardServicesInfo, &serv); + if (serv.Revision != CS_RELEASE_CODE) { + printk(KERN_NOTICE "qlogic_cs: Card Services release " "does not match!\n"); + return -1; + } + register_pccard_driver(&dev_info, &qlogic_attach, &qlogic_detach); + return 0; } -static void __exit exit_qlogic_cs(void) { - DEBUG(0, "qlogic_cs: unloading\n"); - unregister_pccard_driver(&dev_info); - while (dev_list != NULL) - qlogic_detach(dev_list); +static void __exit exit_qlogic_cs(void) +{ + DEBUG(0, "qlogic_cs: unloading\n"); + unregister_pccard_driver(&dev_info); + while (dev_list != NULL) + qlogic_detach(dev_list); } module_init(init_qlogic_cs); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/scsi/README.nsp_cs linux.2.5.47-ac4/drivers/scsi/README.nsp_cs --- linux.2.5.47/drivers/scsi/README.nsp_cs 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.47-ac4/drivers/scsi/README.nsp_cs 2002-10-31 15:05:34.000000000 +0000 @@ -0,0 +1,129 @@ + + WorkBiT NinjaSCSI-3/32Bi driver for Linux + +1. Comment + This is Workbit corp.'s(http://www.workbit.co.jp/) NinjaSCSI-3 +(http://www.workbit.co.jp/ts/z_nj3r.html) and NinjaSCSI-32Bi +(http://www.workbit.co.jp/ts/z_njsc32bi.html) PCMCIA card driver module +for Linux. + +2. My Linux environment +Linux kernel: 2.4.17 / 2.2.20 +pcmcia-cs: 3.1.30 +gcc: gcc-2.95.4 +PC card: I-O data PCSC-F (NinjaSCSI-3) + I-O data CBSC-II in 16 bit mode (NinjaSCSI-32Bi) +SCSI device: I-O data CDPS-PX24 (CD-ROM drive) + Media Intelligent MMO-640GT (Optical disk drive) + +3. Install +[1] Check your PC card is true "NinjaSCSI-3" card. + If you installed pcmcia-cs already, pcmcia reports your card as UNKNOWN + card, and write ["WBT", "NinjaSCSI-3", "R1.0"] or some other string to + your console or log file. + You can also use "cardctl" program (this program is in pcmcia-cs source + code) to get more info. + +# cat /var/log/messgaes +... +Jan 2 03:45:06 lindberg cardmgr[78]: unsupported card in socket 1 +Jan 2 03:45:06 lindberg cardmgr[78]: product info: "WBT", "NinjaSCSI-3", "R1.0" +... +# cardctl ident +Socket 0: + no product info available +Socket 1: + product info: "IO DATA", "CBSC16 ", "1" + + +[2] Get Linux kernel source, and extract it to /usr/src. + Because NinjaSCSI driver requiers some SCSI header files in Linux kernel + source. + I recomend rebuilding your kernel. This eliminate some versioning problem. +$ cd /usr/src +$ tar -zxvf linux-x.x.x.tar.gz +$ cd linux +$ make config +... + +[3] If you use this driver with Kernel 2.2, Unpack pcmcia-cs in some directory + and make & install. This driver requies pcmcia-cs header file. +$ cd /usr/src +$ tar zxvf cs-pcmcia-cs-3.x.x.tar.gz +... + +[4] Extract this driver's archive somewhere, and edit Makefile, then do make. +$ tar -zxvf nsp_cs-x.x.tar.gz +$ cd nsp_cs-x.x +$ emacs Makefile +... +$ make + +[5] Copy nsp_cs.o to suitable plase, like /lib/modules//pcmcia/ . + +[6] Add these lines to /etc/pcmcia/config . + If you yse pcmcia-cs-3.1.8 or later, we can use "nsp_cs.conf" file. + So, you don't need to edit file. Just copy to /etc/pcmcia/ . + +------------------------------------- +device "nsp_cs" + class "scsi" module "nsp_cs" + +card "WorkBit NinjaSCSI-3" + version "WBT", "NinjaSCSI-3", "R1.0" + bind "nsp_cs" + +card "WorkBit NinjaSCSI-32Bi (16bit)" + version "WORKBIT", "UltraNinja-16", "1" + bind "nsp_cs" + +# OEM +card "WorkBit NinjaSCSI-32Bi (16bit) / IO-DATA" + version "IO DATA", "CBSC16 ", "1" + bind "nsp_cs" + +# OEM +card "WorkBit NinjaSCSI-32Bi (16bit) / KME-1" + version "KME ", "SCSI-CARD-001", "1" + bind "nsp_cs" +card "WorkBit NinjaSCSI-32Bi (16bit) / KME-2" + version "KME ", "SCSI-CARD-002", "1" + bind "nsp_cs" +card "WorkBit NinjaSCSI-32Bi (16bit) / KME-3" + version "KME ", "SCSI-CARD-003", "1" + bind "nsp_cs" +card "WorkBit NinjaSCSI-32Bi (16bit) / KME-4" + version "KME ", "SCSI-CARD-004", "1" + bind "nsp_cs" +------------------------------------- + +[7] Start (or restart) pcmcia-cs. +# /etc/rc.d/rc.pcmcia start (BSD style) +or +# /etc/init.d/pcmcia start (SYSV style) + + +4. History +See README.nin_cs . + +5. Caution + If you eject card when doing some operation for your SCSI device or suspend +your computer, you encount some *BAD* error like disk crash. + It works good when I using this driver right way. But I'm not guarantee +your data. Please backup your data when you use this driver. + +6. Known Bugs + Many bugs in this driver. Be careful! + +7. Testing + Please send me some reports(bug reports etc..) of this software. +When you send report, please tell me these or more. + card name + kernel version + your SCSI device name(hard drive, CD-ROM, etc...) + +8. Copyright + See GPL. + + +2002/01/17 yokota@netlab.is.tsukuba.ac.jp diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/scsi/sim710.c linux.2.5.47-ac4/drivers/scsi/sim710.c --- linux.2.5.47/drivers/scsi/sim710.c 2002-10-31 14:57:12.000000000 +0000 +++ linux.2.5.47-ac4/drivers/scsi/sim710.c 2002-10-31 15:05:32.000000000 +0000 @@ -296,15 +296,15 @@ " 04 socl: %02x sodl: %02x sxfer: %02x scid: %02x\n" " 08 sbcl: %02x sbdl: %02x sidl: %02x sfbr: %02x\n" " 0C sstat2:%02x sstat1:%02x sstat0:%02x dstat: %02x\n" - " 10 dsa: %08x\n" + " 10 dsa: %08lx\n" " 14 ctest3:%02x ctest2:%02x ctest1:%02x ctest0:%02x\n" " 18 ctest7:%02x ctest6:%02x ctest5:%02x ctest4:%02x\n" " 1C temp: %08x\n" " 20 lcrc: %02x ctest8:%02x istat: %02x dfifo: %02x\n" - " 24 dbc: %08x dnad: %08x dsp: %08x\n" - " 30 dsps: %08x scratch:%08x\n" + " 24 dbc: %08lx dnad: %08lx dsp: %08lx\n" + " 30 dsps: %08lx scratch:%08lx\n" " 38 dcntl: %02x dwt: %02x dien: %02x dmode: %02x\n" - " 3C adder: %08x\n", + " 3C adder: %08lx\n", NCR_read8(SIEN_REG), NCR_read8(SDID_REG), NCR_read8(SCNTL1_REG), NCR_read8(SCNTL0_REG), NCR_read8(SOCL_REG), NCR_read8(SODL_REG), NCR_read8(SXFER_REG), NCR_read8(SCID_REG), NCR_read8(SBCL_REG), @@ -1018,7 +1018,7 @@ if (!cmd) { printk("scsi%d: No active command!\n", host->host_no); printk("scsi%d: Int %d, istat %02x, sstat0 %02x " - "dstat %02x, dsp [%04x], scratch %02x, dsps %08x\n", + "dstat %02x, dsp [%04x], scratch %02lx, dsps %08x\n", host->host_no, sim710_intrs, istat, sstat0, dstat, (u32 *)(isa_bus_to_virt(NCR_read32(DSP_REG))) - hostdata->script, NCR_read32(SCRATCH_REG), dsps); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/scsi/sim710_d.h linux.2.5.47-ac4/drivers/scsi/sim710_d.h --- linux.2.5.47/drivers/scsi/sim710_d.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.47-ac4/drivers/scsi/sim710_d.h 2002-11-12 17:23:42.000000000 +0000 @@ -0,0 +1,2452 @@ +/* DO NOT EDIT - Generated automatically by script_asm.pl */ +static u32 SCRIPT[] = { +/* + + + + + + +ABSOLUTE dsa_select = 0 +ABSOLUTE dsa_msgout = 8 +ABSOLUTE dsa_cmnd = 16 +ABSOLUTE dsa_status = 24 +ABSOLUTE dsa_msgin = 32 +ABSOLUTE dsa_datain = 40 +ABSOLUTE dsa_dataout = 1064 +ABSOLUTE dsa_size = 2088 + +ABSOLUTE reselected_identify = 0 +ABSOLUTE msgin_buf = 0 +ABSOLUTE msg_reject = 0 +ABSOLUTE test1_src = 0 +ABSOLUTE test1_dst = 0 + + + +ABSOLUTE int_bad_msg1 = 0xab930006 +ABSOLUTE int_bad_msg2 = 0xab930007 +ABSOLUTE int_bad_msg3 = 0xab930008 +ABSOLUTE int_cmd_bad_phase = 0xab930009 +ABSOLUTE int_cmd_complete = 0xab93000a +ABSOLUTE int_data_bad_phase = 0xab93000b +ABSOLUTE int_msg_sdtr1 = 0xab93000c +ABSOLUTE int_msg_sdtr2 = 0xab93000d +ABSOLUTE int_msg_sdtr3 = 0xab93000e +ABSOLUTE int_no_msgout1 = 0xab93000f +ABSOLUTE int_no_msgout2 = 0xab930010 +ABSOLUTE int_no_msgout3 = 0xab930011 +ABSOLUTE int_not_cmd_complete = 0xab930012 +ABSOLUTE int_sel_no_ident = 0xab930013 +ABSOLUTE int_sel_not_cmd = 0xab930014 +ABSOLUTE int_status_not_msgin = 0xab930015 +ABSOLUTE int_resel_not_msgin = 0xab930016 +ABSOLUTE int_reselected = 0xab930017 +ABSOLUTE int_selected = 0xab930018 +ABSOLUTE int_disc1 = 0xab930019 +ABSOLUTE int_disc2 = 0xab93001a +ABSOLUTE int_disc3 = 0xab93001b +ABSOLUTE int_not_rej = 0xab93001c +ABSOLUTE int_test1 = 0xab93001d + + + +ABSOLUTE had_select = 0x01 +ABSOLUTE had_msgout = 0x02 +ABSOLUTE had_cmdout = 0x04 +ABSOLUTE had_datain = 0x08 +ABSOLUTE had_dataout = 0x10 +ABSOLUTE had_status = 0x20 +ABSOLUTE had_msgin = 0x40 +ABSOLUTE had_extmsg = 0x80 + + + +ABSOLUTE did_reject = 0x01 + + + + + +ENTRY do_select +do_select: + CLEAR TARGET + +at 0x00000000 : */ 0x60000200,0x00000000, +/* + ; Enable selection timer + MOVE CTEST7 & 0xef TO CTEST7 + +at 0x00000002 : */ 0x7c1bef00,0x00000000, +/* + SELECT ATN FROM dsa_select, reselect + +at 0x00000004 : */ 0x43000000,0x00000cd0, +/* + JUMP get_status, WHEN STATUS + +at 0x00000006 : */ 0x830b0000,0x00000098, +/* + ; Disable selection timer + MOVE CTEST7 | 0x10 TO CTEST7 + +at 0x00000008 : */ 0x7a1b1000,0x00000000, +/* + MOVE SCRATCH0 | had_select TO SCRATCH0 + +at 0x0000000a : */ 0x7a340100,0x00000000, +/* + INT int_sel_no_ident, IF NOT MSG_OUT + +at 0x0000000c : */ 0x9e020000,0xab930013, +/* + MOVE SCRATCH0 | had_msgout TO SCRATCH0 + +at 0x0000000e : */ 0x7a340200,0x00000000, +/* + MOVE FROM dsa_msgout, when MSG_OUT + +at 0x00000010 : */ 0x1e000000,0x00000008, +/* +ENTRY done_ident +done_ident: + JUMP get_status, IF STATUS + +at 0x00000012 : */ 0x830a0000,0x00000098, +/* +redo_msgin1: + JUMP get_msgin1, WHEN MSG_IN + +at 0x00000014 : */ 0x870b0000,0x00000918, +/* + INT int_sel_not_cmd, IF NOT CMD + +at 0x00000016 : */ 0x9a020000,0xab930014, +/* +ENTRY resume_cmd +resume_cmd: + MOVE SCRATCH0 | had_cmdout TO SCRATCH0 + +at 0x00000018 : */ 0x7a340400,0x00000000, +/* + MOVE FROM dsa_cmnd, WHEN CMD + +at 0x0000001a : */ 0x1a000000,0x00000010, +/* +ENTRY resume_pmm +resume_pmm: +redo_msgin2: + JUMP get_msgin2, WHEN MSG_IN + +at 0x0000001c : */ 0x870b0000,0x00000a48, +/* + JUMP get_status, IF STATUS + +at 0x0000001e : */ 0x830a0000,0x00000098, +/* + JUMP input_data, IF DATA_IN + +at 0x00000020 : */ 0x810a0000,0x000000d8, +/* + JUMP output_data, IF DATA_OUT + +at 0x00000022 : */ 0x800a0000,0x000004f0, +/* + INT int_cmd_bad_phase + +at 0x00000024 : */ 0x98080000,0xab930009, +/* + +get_status: + ; Disable selection timer + MOVE CTEST7 | 0x10 TO CTEST7 + +at 0x00000026 : */ 0x7a1b1000,0x00000000, +/* + MOVE FROM dsa_status, WHEN STATUS + +at 0x00000028 : */ 0x1b000000,0x00000018, +/* + INT int_status_not_msgin, WHEN NOT MSG_IN + +at 0x0000002a : */ 0x9f030000,0xab930015, +/* + MOVE FROM dsa_msgin, WHEN MSG_IN + +at 0x0000002c : */ 0x1f000000,0x00000020, +/* + INT int_not_cmd_complete, IF NOT 0x00 + +at 0x0000002e : */ 0x98040000,0xab930012, +/* + CLEAR ACK + +at 0x00000030 : */ 0x60000040,0x00000000, +/* +ENTRY wait_disc_complete +wait_disc_complete: + WAIT DISCONNECT + +at 0x00000032 : */ 0x48000000,0x00000000, +/* + INT int_cmd_complete + +at 0x00000034 : */ 0x98080000,0xab93000a, +/* + +input_data: + MOVE SCRATCH0 | had_datain TO SCRATCH0 + +at 0x00000036 : */ 0x7a340800,0x00000000, +/* +ENTRY patch_input_data +patch_input_data: + JUMP 0 + +at 0x00000038 : */ 0x80080000,0x00000000, +/* + MOVE FROM dsa_datain+0x0000, WHEN DATA_IN + +at 0x0000003a : */ 0x19000000,0x00000028, +/* + MOVE FROM dsa_datain+0x0008, WHEN DATA_IN + +at 0x0000003c : */ 0x19000000,0x00000030, +/* + MOVE FROM dsa_datain+0x0010, WHEN DATA_IN + +at 0x0000003e : */ 0x19000000,0x00000038, +/* + MOVE FROM dsa_datain+0x0018, WHEN DATA_IN + +at 0x00000040 : */ 0x19000000,0x00000040, +/* + MOVE FROM dsa_datain+0x0020, WHEN DATA_IN + +at 0x00000042 : */ 0x19000000,0x00000048, +/* + MOVE FROM dsa_datain+0x0028, WHEN DATA_IN + +at 0x00000044 : */ 0x19000000,0x00000050, +/* + MOVE FROM dsa_datain+0x0030, WHEN DATA_IN + +at 0x00000046 : */ 0x19000000,0x00000058, +/* + MOVE FROM dsa_datain+0x0038, WHEN DATA_IN + +at 0x00000048 : */ 0x19000000,0x00000060, +/* + MOVE FROM dsa_datain+0x0040, WHEN DATA_IN + +at 0x0000004a : */ 0x19000000,0x00000068, +/* + MOVE FROM dsa_datain+0x0048, WHEN DATA_IN + +at 0x0000004c : */ 0x19000000,0x00000070, +/* + MOVE FROM dsa_datain+0x0050, WHEN DATA_IN + +at 0x0000004e : */ 0x19000000,0x00000078, +/* + MOVE FROM dsa_datain+0x0058, WHEN DATA_IN + +at 0x00000050 : */ 0x19000000,0x00000080, +/* + MOVE FROM dsa_datain+0x0060, WHEN DATA_IN + +at 0x00000052 : */ 0x19000000,0x00000088, +/* + MOVE FROM dsa_datain+0x0068, WHEN DATA_IN + +at 0x00000054 : */ 0x19000000,0x00000090, +/* + MOVE FROM dsa_datain+0x0070, WHEN DATA_IN + +at 0x00000056 : */ 0x19000000,0x00000098, +/* + MOVE FROM dsa_datain+0x0078, WHEN DATA_IN + +at 0x00000058 : */ 0x19000000,0x000000a0, +/* + MOVE FROM dsa_datain+0x0080, WHEN DATA_IN + +at 0x0000005a : */ 0x19000000,0x000000a8, +/* + MOVE FROM dsa_datain+0x0088, WHEN DATA_IN + +at 0x0000005c : */ 0x19000000,0x000000b0, +/* + MOVE FROM dsa_datain+0x0090, WHEN DATA_IN + +at 0x0000005e : */ 0x19000000,0x000000b8, +/* + MOVE FROM dsa_datain+0x0098, WHEN DATA_IN + +at 0x00000060 : */ 0x19000000,0x000000c0, +/* + MOVE FROM dsa_datain+0x00a0, WHEN DATA_IN + +at 0x00000062 : */ 0x19000000,0x000000c8, +/* + MOVE FROM dsa_datain+0x00a8, WHEN DATA_IN + +at 0x00000064 : */ 0x19000000,0x000000d0, +/* + MOVE FROM dsa_datain+0x00b0, WHEN DATA_IN + +at 0x00000066 : */ 0x19000000,0x000000d8, +/* + MOVE FROM dsa_datain+0x00b8, WHEN DATA_IN + +at 0x00000068 : */ 0x19000000,0x000000e0, +/* + MOVE FROM dsa_datain+0x00c0, WHEN DATA_IN + +at 0x0000006a : */ 0x19000000,0x000000e8, +/* + MOVE FROM dsa_datain+0x00c8, WHEN DATA_IN + +at 0x0000006c : */ 0x19000000,0x000000f0, +/* + MOVE FROM dsa_datain+0x00d0, WHEN DATA_IN + +at 0x0000006e : */ 0x19000000,0x000000f8, +/* + MOVE FROM dsa_datain+0x00d8, WHEN DATA_IN + +at 0x00000070 : */ 0x19000000,0x00000100, +/* + MOVE FROM dsa_datain+0x00e0, WHEN DATA_IN + +at 0x00000072 : */ 0x19000000,0x00000108, +/* + MOVE FROM dsa_datain+0x00e8, WHEN DATA_IN + +at 0x00000074 : */ 0x19000000,0x00000110, +/* + MOVE FROM dsa_datain+0x00f0, WHEN DATA_IN + +at 0x00000076 : */ 0x19000000,0x00000118, +/* + MOVE FROM dsa_datain+0x00f8, WHEN DATA_IN + +at 0x00000078 : */ 0x19000000,0x00000120, +/* + MOVE FROM dsa_datain+0x0100, WHEN DATA_IN + +at 0x0000007a : */ 0x19000000,0x00000128, +/* + MOVE FROM dsa_datain+0x0108, WHEN DATA_IN + +at 0x0000007c : */ 0x19000000,0x00000130, +/* + MOVE FROM dsa_datain+0x0110, WHEN DATA_IN + +at 0x0000007e : */ 0x19000000,0x00000138, +/* + MOVE FROM dsa_datain+0x0118, WHEN DATA_IN + +at 0x00000080 : */ 0x19000000,0x00000140, +/* + MOVE FROM dsa_datain+0x0120, WHEN DATA_IN + +at 0x00000082 : */ 0x19000000,0x00000148, +/* + MOVE FROM dsa_datain+0x0128, WHEN DATA_IN + +at 0x00000084 : */ 0x19000000,0x00000150, +/* + MOVE FROM dsa_datain+0x0130, WHEN DATA_IN + +at 0x00000086 : */ 0x19000000,0x00000158, +/* + MOVE FROM dsa_datain+0x0138, WHEN DATA_IN + +at 0x00000088 : */ 0x19000000,0x00000160, +/* + MOVE FROM dsa_datain+0x0140, WHEN DATA_IN + +at 0x0000008a : */ 0x19000000,0x00000168, +/* + MOVE FROM dsa_datain+0x0148, WHEN DATA_IN + +at 0x0000008c : */ 0x19000000,0x00000170, +/* + MOVE FROM dsa_datain+0x0150, WHEN DATA_IN + +at 0x0000008e : */ 0x19000000,0x00000178, +/* + MOVE FROM dsa_datain+0x0158, WHEN DATA_IN + +at 0x00000090 : */ 0x19000000,0x00000180, +/* + MOVE FROM dsa_datain+0x0160, WHEN DATA_IN + +at 0x00000092 : */ 0x19000000,0x00000188, +/* + MOVE FROM dsa_datain+0x0168, WHEN DATA_IN + +at 0x00000094 : */ 0x19000000,0x00000190, +/* + MOVE FROM dsa_datain+0x0170, WHEN DATA_IN + +at 0x00000096 : */ 0x19000000,0x00000198, +/* + MOVE FROM dsa_datain+0x0178, WHEN DATA_IN + +at 0x00000098 : */ 0x19000000,0x000001a0, +/* + MOVE FROM dsa_datain+0x0180, WHEN DATA_IN + +at 0x0000009a : */ 0x19000000,0x000001a8, +/* + MOVE FROM dsa_datain+0x0188, WHEN DATA_IN + +at 0x0000009c : */ 0x19000000,0x000001b0, +/* + MOVE FROM dsa_datain+0x0190, WHEN DATA_IN + +at 0x0000009e : */ 0x19000000,0x000001b8, +/* + MOVE FROM dsa_datain+0x0198, WHEN DATA_IN + +at 0x000000a0 : */ 0x19000000,0x000001c0, +/* + MOVE FROM dsa_datain+0x01a0, WHEN DATA_IN + +at 0x000000a2 : */ 0x19000000,0x000001c8, +/* + MOVE FROM dsa_datain+0x01a8, WHEN DATA_IN + +at 0x000000a4 : */ 0x19000000,0x000001d0, +/* + MOVE FROM dsa_datain+0x01b0, WHEN DATA_IN + +at 0x000000a6 : */ 0x19000000,0x000001d8, +/* + MOVE FROM dsa_datain+0x01b8, WHEN DATA_IN + +at 0x000000a8 : */ 0x19000000,0x000001e0, +/* + MOVE FROM dsa_datain+0x01c0, WHEN DATA_IN + +at 0x000000aa : */ 0x19000000,0x000001e8, +/* + MOVE FROM dsa_datain+0x01c8, WHEN DATA_IN + +at 0x000000ac : */ 0x19000000,0x000001f0, +/* + MOVE FROM dsa_datain+0x01d0, WHEN DATA_IN + +at 0x000000ae : */ 0x19000000,0x000001f8, +/* + MOVE FROM dsa_datain+0x01d8, WHEN DATA_IN + +at 0x000000b0 : */ 0x19000000,0x00000200, +/* + MOVE FROM dsa_datain+0x01e0, WHEN DATA_IN + +at 0x000000b2 : */ 0x19000000,0x00000208, +/* + MOVE FROM dsa_datain+0x01e8, WHEN DATA_IN + +at 0x000000b4 : */ 0x19000000,0x00000210, +/* + MOVE FROM dsa_datain+0x01f0, WHEN DATA_IN + +at 0x000000b6 : */ 0x19000000,0x00000218, +/* + MOVE FROM dsa_datain+0x01f8, WHEN DATA_IN + +at 0x000000b8 : */ 0x19000000,0x00000220, +/* + MOVE FROM dsa_datain+0x0200, WHEN DATA_IN + +at 0x000000ba : */ 0x19000000,0x00000228, +/* + MOVE FROM dsa_datain+0x0208, WHEN DATA_IN + +at 0x000000bc : */ 0x19000000,0x00000230, +/* + MOVE FROM dsa_datain+0x0210, WHEN DATA_IN + +at 0x000000be : */ 0x19000000,0x00000238, +/* + MOVE FROM dsa_datain+0x0218, WHEN DATA_IN + +at 0x000000c0 : */ 0x19000000,0x00000240, +/* + MOVE FROM dsa_datain+0x0220, WHEN DATA_IN + +at 0x000000c2 : */ 0x19000000,0x00000248, +/* + MOVE FROM dsa_datain+0x0228, WHEN DATA_IN + +at 0x000000c4 : */ 0x19000000,0x00000250, +/* + MOVE FROM dsa_datain+0x0230, WHEN DATA_IN + +at 0x000000c6 : */ 0x19000000,0x00000258, +/* + MOVE FROM dsa_datain+0x0238, WHEN DATA_IN + +at 0x000000c8 : */ 0x19000000,0x00000260, +/* + MOVE FROM dsa_datain+0x0240, WHEN DATA_IN + +at 0x000000ca : */ 0x19000000,0x00000268, +/* + MOVE FROM dsa_datain+0x0248, WHEN DATA_IN + +at 0x000000cc : */ 0x19000000,0x00000270, +/* + MOVE FROM dsa_datain+0x0250, WHEN DATA_IN + +at 0x000000ce : */ 0x19000000,0x00000278, +/* + MOVE FROM dsa_datain+0x0258, WHEN DATA_IN + +at 0x000000d0 : */ 0x19000000,0x00000280, +/* + MOVE FROM dsa_datain+0x0260, WHEN DATA_IN + +at 0x000000d2 : */ 0x19000000,0x00000288, +/* + MOVE FROM dsa_datain+0x0268, WHEN DATA_IN + +at 0x000000d4 : */ 0x19000000,0x00000290, +/* + MOVE FROM dsa_datain+0x0270, WHEN DATA_IN + +at 0x000000d6 : */ 0x19000000,0x00000298, +/* + MOVE FROM dsa_datain+0x0278, WHEN DATA_IN + +at 0x000000d8 : */ 0x19000000,0x000002a0, +/* + MOVE FROM dsa_datain+0x0280, WHEN DATA_IN + +at 0x000000da : */ 0x19000000,0x000002a8, +/* + MOVE FROM dsa_datain+0x0288, WHEN DATA_IN + +at 0x000000dc : */ 0x19000000,0x000002b0, +/* + MOVE FROM dsa_datain+0x0290, WHEN DATA_IN + +at 0x000000de : */ 0x19000000,0x000002b8, +/* + MOVE FROM dsa_datain+0x0298, WHEN DATA_IN + +at 0x000000e0 : */ 0x19000000,0x000002c0, +/* + MOVE FROM dsa_datain+0x02a0, WHEN DATA_IN + +at 0x000000e2 : */ 0x19000000,0x000002c8, +/* + MOVE FROM dsa_datain+0x02a8, WHEN DATA_IN + +at 0x000000e4 : */ 0x19000000,0x000002d0, +/* + MOVE FROM dsa_datain+0x02b0, WHEN DATA_IN + +at 0x000000e6 : */ 0x19000000,0x000002d8, +/* + MOVE FROM dsa_datain+0x02b8, WHEN DATA_IN + +at 0x000000e8 : */ 0x19000000,0x000002e0, +/* + MOVE FROM dsa_datain+0x02c0, WHEN DATA_IN + +at 0x000000ea : */ 0x19000000,0x000002e8, +/* + MOVE FROM dsa_datain+0x02c8, WHEN DATA_IN + +at 0x000000ec : */ 0x19000000,0x000002f0, +/* + MOVE FROM dsa_datain+0x02d0, WHEN DATA_IN + +at 0x000000ee : */ 0x19000000,0x000002f8, +/* + MOVE FROM dsa_datain+0x02d8, WHEN DATA_IN + +at 0x000000f0 : */ 0x19000000,0x00000300, +/* + MOVE FROM dsa_datain+0x02e0, WHEN DATA_IN + +at 0x000000f2 : */ 0x19000000,0x00000308, +/* + MOVE FROM dsa_datain+0x02e8, WHEN DATA_IN + +at 0x000000f4 : */ 0x19000000,0x00000310, +/* + MOVE FROM dsa_datain+0x02f0, WHEN DATA_IN + +at 0x000000f6 : */ 0x19000000,0x00000318, +/* + MOVE FROM dsa_datain+0x02f8, WHEN DATA_IN + +at 0x000000f8 : */ 0x19000000,0x00000320, +/* + MOVE FROM dsa_datain+0x0300, WHEN DATA_IN + +at 0x000000fa : */ 0x19000000,0x00000328, +/* + MOVE FROM dsa_datain+0x0308, WHEN DATA_IN + +at 0x000000fc : */ 0x19000000,0x00000330, +/* + MOVE FROM dsa_datain+0x0310, WHEN DATA_IN + +at 0x000000fe : */ 0x19000000,0x00000338, +/* + MOVE FROM dsa_datain+0x0318, WHEN DATA_IN + +at 0x00000100 : */ 0x19000000,0x00000340, +/* + MOVE FROM dsa_datain+0x0320, WHEN DATA_IN + +at 0x00000102 : */ 0x19000000,0x00000348, +/* + MOVE FROM dsa_datain+0x0328, WHEN DATA_IN + +at 0x00000104 : */ 0x19000000,0x00000350, +/* + MOVE FROM dsa_datain+0x0330, WHEN DATA_IN + +at 0x00000106 : */ 0x19000000,0x00000358, +/* + MOVE FROM dsa_datain+0x0338, WHEN DATA_IN + +at 0x00000108 : */ 0x19000000,0x00000360, +/* + MOVE FROM dsa_datain+0x0340, WHEN DATA_IN + +at 0x0000010a : */ 0x19000000,0x00000368, +/* + MOVE FROM dsa_datain+0x0348, WHEN DATA_IN + +at 0x0000010c : */ 0x19000000,0x00000370, +/* + MOVE FROM dsa_datain+0x0350, WHEN DATA_IN + +at 0x0000010e : */ 0x19000000,0x00000378, +/* + MOVE FROM dsa_datain+0x0358, WHEN DATA_IN + +at 0x00000110 : */ 0x19000000,0x00000380, +/* + MOVE FROM dsa_datain+0x0360, WHEN DATA_IN + +at 0x00000112 : */ 0x19000000,0x00000388, +/* + MOVE FROM dsa_datain+0x0368, WHEN DATA_IN + +at 0x00000114 : */ 0x19000000,0x00000390, +/* + MOVE FROM dsa_datain+0x0370, WHEN DATA_IN + +at 0x00000116 : */ 0x19000000,0x00000398, +/* + MOVE FROM dsa_datain+0x0378, WHEN DATA_IN + +at 0x00000118 : */ 0x19000000,0x000003a0, +/* + MOVE FROM dsa_datain+0x0380, WHEN DATA_IN + +at 0x0000011a : */ 0x19000000,0x000003a8, +/* + MOVE FROM dsa_datain+0x0388, WHEN DATA_IN + +at 0x0000011c : */ 0x19000000,0x000003b0, +/* + MOVE FROM dsa_datain+0x0390, WHEN DATA_IN + +at 0x0000011e : */ 0x19000000,0x000003b8, +/* + MOVE FROM dsa_datain+0x0398, WHEN DATA_IN + +at 0x00000120 : */ 0x19000000,0x000003c0, +/* + MOVE FROM dsa_datain+0x03a0, WHEN DATA_IN + +at 0x00000122 : */ 0x19000000,0x000003c8, +/* + MOVE FROM dsa_datain+0x03a8, WHEN DATA_IN + +at 0x00000124 : */ 0x19000000,0x000003d0, +/* + MOVE FROM dsa_datain+0x03b0, WHEN DATA_IN + +at 0x00000126 : */ 0x19000000,0x000003d8, +/* + MOVE FROM dsa_datain+0x03b8, WHEN DATA_IN + +at 0x00000128 : */ 0x19000000,0x000003e0, +/* + MOVE FROM dsa_datain+0x03c0, WHEN DATA_IN + +at 0x0000012a : */ 0x19000000,0x000003e8, +/* + MOVE FROM dsa_datain+0x03c8, WHEN DATA_IN + +at 0x0000012c : */ 0x19000000,0x000003f0, +/* + MOVE FROM dsa_datain+0x03d0, WHEN DATA_IN + +at 0x0000012e : */ 0x19000000,0x000003f8, +/* + MOVE FROM dsa_datain+0x03d8, WHEN DATA_IN + +at 0x00000130 : */ 0x19000000,0x00000400, +/* + MOVE FROM dsa_datain+0x03e0, WHEN DATA_IN + +at 0x00000132 : */ 0x19000000,0x00000408, +/* + MOVE FROM dsa_datain+0x03e8, WHEN DATA_IN + +at 0x00000134 : */ 0x19000000,0x00000410, +/* + MOVE FROM dsa_datain+0x03f0, WHEN DATA_IN + +at 0x00000136 : */ 0x19000000,0x00000418, +/* + MOVE FROM dsa_datain+0x03f8, WHEN DATA_IN + +at 0x00000138 : */ 0x19000000,0x00000420, +/* + JUMP end_data_trans + +at 0x0000013a : */ 0x80080000,0x00000900, +/* + +output_data: + MOVE SCRATCH0 | had_dataout TO SCRATCH0 + +at 0x0000013c : */ 0x7a341000,0x00000000, +/* +ENTRY patch_output_data +patch_output_data: + JUMP 0 + +at 0x0000013e : */ 0x80080000,0x00000000, +/* + MOVE FROM dsa_dataout+0x0000, WHEN DATA_OUT + +at 0x00000140 : */ 0x18000000,0x00000428, +/* + MOVE FROM dsa_dataout+0x0008, WHEN DATA_OUT + +at 0x00000142 : */ 0x18000000,0x00000430, +/* + MOVE FROM dsa_dataout+0x0010, WHEN DATA_OUT + +at 0x00000144 : */ 0x18000000,0x00000438, +/* + MOVE FROM dsa_dataout+0x0018, WHEN DATA_OUT + +at 0x00000146 : */ 0x18000000,0x00000440, +/* + MOVE FROM dsa_dataout+0x0020, WHEN DATA_OUT + +at 0x00000148 : */ 0x18000000,0x00000448, +/* + MOVE FROM dsa_dataout+0x0028, WHEN DATA_OUT + +at 0x0000014a : */ 0x18000000,0x00000450, +/* + MOVE FROM dsa_dataout+0x0030, WHEN DATA_OUT + +at 0x0000014c : */ 0x18000000,0x00000458, +/* + MOVE FROM dsa_dataout+0x0038, WHEN DATA_OUT + +at 0x0000014e : */ 0x18000000,0x00000460, +/* + MOVE FROM dsa_dataout+0x0040, WHEN DATA_OUT + +at 0x00000150 : */ 0x18000000,0x00000468, +/* + MOVE FROM dsa_dataout+0x0048, WHEN DATA_OUT + +at 0x00000152 : */ 0x18000000,0x00000470, +/* + MOVE FROM dsa_dataout+0x0050, WHEN DATA_OUT + +at 0x00000154 : */ 0x18000000,0x00000478, +/* + MOVE FROM dsa_dataout+0x0058, WHEN DATA_OUT + +at 0x00000156 : */ 0x18000000,0x00000480, +/* + MOVE FROM dsa_dataout+0x0060, WHEN DATA_OUT + +at 0x00000158 : */ 0x18000000,0x00000488, +/* + MOVE FROM dsa_dataout+0x0068, WHEN DATA_OUT + +at 0x0000015a : */ 0x18000000,0x00000490, +/* + MOVE FROM dsa_dataout+0x0070, WHEN DATA_OUT + +at 0x0000015c : */ 0x18000000,0x00000498, +/* + MOVE FROM dsa_dataout+0x0078, WHEN DATA_OUT + +at 0x0000015e : */ 0x18000000,0x000004a0, +/* + MOVE FROM dsa_dataout+0x0080, WHEN DATA_OUT + +at 0x00000160 : */ 0x18000000,0x000004a8, +/* + MOVE FROM dsa_dataout+0x0088, WHEN DATA_OUT + +at 0x00000162 : */ 0x18000000,0x000004b0, +/* + MOVE FROM dsa_dataout+0x0090, WHEN DATA_OUT + +at 0x00000164 : */ 0x18000000,0x000004b8, +/* + MOVE FROM dsa_dataout+0x0098, WHEN DATA_OUT + +at 0x00000166 : */ 0x18000000,0x000004c0, +/* + MOVE FROM dsa_dataout+0x00a0, WHEN DATA_OUT + +at 0x00000168 : */ 0x18000000,0x000004c8, +/* + MOVE FROM dsa_dataout+0x00a8, WHEN DATA_OUT + +at 0x0000016a : */ 0x18000000,0x000004d0, +/* + MOVE FROM dsa_dataout+0x00b0, WHEN DATA_OUT + +at 0x0000016c : */ 0x18000000,0x000004d8, +/* + MOVE FROM dsa_dataout+0x00b8, WHEN DATA_OUT + +at 0x0000016e : */ 0x18000000,0x000004e0, +/* + MOVE FROM dsa_dataout+0x00c0, WHEN DATA_OUT + +at 0x00000170 : */ 0x18000000,0x000004e8, +/* + MOVE FROM dsa_dataout+0x00c8, WHEN DATA_OUT + +at 0x00000172 : */ 0x18000000,0x000004f0, +/* + MOVE FROM dsa_dataout+0x00d0, WHEN DATA_OUT + +at 0x00000174 : */ 0x18000000,0x000004f8, +/* + MOVE FROM dsa_dataout+0x00d8, WHEN DATA_OUT + +at 0x00000176 : */ 0x18000000,0x00000500, +/* + MOVE FROM dsa_dataout+0x00e0, WHEN DATA_OUT + +at 0x00000178 : */ 0x18000000,0x00000508, +/* + MOVE FROM dsa_dataout+0x00e8, WHEN DATA_OUT + +at 0x0000017a : */ 0x18000000,0x00000510, +/* + MOVE FROM dsa_dataout+0x00f0, WHEN DATA_OUT + +at 0x0000017c : */ 0x18000000,0x00000518, +/* + MOVE FROM dsa_dataout+0x00f8, WHEN DATA_OUT + +at 0x0000017e : */ 0x18000000,0x00000520, +/* + MOVE FROM dsa_dataout+0x0100, WHEN DATA_OUT + +at 0x00000180 : */ 0x18000000,0x00000528, +/* + MOVE FROM dsa_dataout+0x0108, WHEN DATA_OUT + +at 0x00000182 : */ 0x18000000,0x00000530, +/* + MOVE FROM dsa_dataout+0x0110, WHEN DATA_OUT + +at 0x00000184 : */ 0x18000000,0x00000538, +/* + MOVE FROM dsa_dataout+0x0118, WHEN DATA_OUT + +at 0x00000186 : */ 0x18000000,0x00000540, +/* + MOVE FROM dsa_dataout+0x0120, WHEN DATA_OUT + +at 0x00000188 : */ 0x18000000,0x00000548, +/* + MOVE FROM dsa_dataout+0x0128, WHEN DATA_OUT + +at 0x0000018a : */ 0x18000000,0x00000550, +/* + MOVE FROM dsa_dataout+0x0130, WHEN DATA_OUT + +at 0x0000018c : */ 0x18000000,0x00000558, +/* + MOVE FROM dsa_dataout+0x0138, WHEN DATA_OUT + +at 0x0000018e : */ 0x18000000,0x00000560, +/* + MOVE FROM dsa_dataout+0x0140, WHEN DATA_OUT + +at 0x00000190 : */ 0x18000000,0x00000568, +/* + MOVE FROM dsa_dataout+0x0148, WHEN DATA_OUT + +at 0x00000192 : */ 0x18000000,0x00000570, +/* + MOVE FROM dsa_dataout+0x0150, WHEN DATA_OUT + +at 0x00000194 : */ 0x18000000,0x00000578, +/* + MOVE FROM dsa_dataout+0x0158, WHEN DATA_OUT + +at 0x00000196 : */ 0x18000000,0x00000580, +/* + MOVE FROM dsa_dataout+0x0160, WHEN DATA_OUT + +at 0x00000198 : */ 0x18000000,0x00000588, +/* + MOVE FROM dsa_dataout+0x0168, WHEN DATA_OUT + +at 0x0000019a : */ 0x18000000,0x00000590, +/* + MOVE FROM dsa_dataout+0x0170, WHEN DATA_OUT + +at 0x0000019c : */ 0x18000000,0x00000598, +/* + MOVE FROM dsa_dataout+0x0178, WHEN DATA_OUT + +at 0x0000019e : */ 0x18000000,0x000005a0, +/* + MOVE FROM dsa_dataout+0x0180, WHEN DATA_OUT + +at 0x000001a0 : */ 0x18000000,0x000005a8, +/* + MOVE FROM dsa_dataout+0x0188, WHEN DATA_OUT + +at 0x000001a2 : */ 0x18000000,0x000005b0, +/* + MOVE FROM dsa_dataout+0x0190, WHEN DATA_OUT + +at 0x000001a4 : */ 0x18000000,0x000005b8, +/* + MOVE FROM dsa_dataout+0x0198, WHEN DATA_OUT + +at 0x000001a6 : */ 0x18000000,0x000005c0, +/* + MOVE FROM dsa_dataout+0x01a0, WHEN DATA_OUT + +at 0x000001a8 : */ 0x18000000,0x000005c8, +/* + MOVE FROM dsa_dataout+0x01a8, WHEN DATA_OUT + +at 0x000001aa : */ 0x18000000,0x000005d0, +/* + MOVE FROM dsa_dataout+0x01b0, WHEN DATA_OUT + +at 0x000001ac : */ 0x18000000,0x000005d8, +/* + MOVE FROM dsa_dataout+0x01b8, WHEN DATA_OUT + +at 0x000001ae : */ 0x18000000,0x000005e0, +/* + MOVE FROM dsa_dataout+0x01c0, WHEN DATA_OUT + +at 0x000001b0 : */ 0x18000000,0x000005e8, +/* + MOVE FROM dsa_dataout+0x01c8, WHEN DATA_OUT + +at 0x000001b2 : */ 0x18000000,0x000005f0, +/* + MOVE FROM dsa_dataout+0x01d0, WHEN DATA_OUT + +at 0x000001b4 : */ 0x18000000,0x000005f8, +/* + MOVE FROM dsa_dataout+0x01d8, WHEN DATA_OUT + +at 0x000001b6 : */ 0x18000000,0x00000600, +/* + MOVE FROM dsa_dataout+0x01e0, WHEN DATA_OUT + +at 0x000001b8 : */ 0x18000000,0x00000608, +/* + MOVE FROM dsa_dataout+0x01e8, WHEN DATA_OUT + +at 0x000001ba : */ 0x18000000,0x00000610, +/* + MOVE FROM dsa_dataout+0x01f0, WHEN DATA_OUT + +at 0x000001bc : */ 0x18000000,0x00000618, +/* + MOVE FROM dsa_dataout+0x01f8, WHEN DATA_OUT + +at 0x000001be : */ 0x18000000,0x00000620, +/* + MOVE FROM dsa_dataout+0x0200, WHEN DATA_OUT + +at 0x000001c0 : */ 0x18000000,0x00000628, +/* + MOVE FROM dsa_dataout+0x0208, WHEN DATA_OUT + +at 0x000001c2 : */ 0x18000000,0x00000630, +/* + MOVE FROM dsa_dataout+0x0210, WHEN DATA_OUT + +at 0x000001c4 : */ 0x18000000,0x00000638, +/* + MOVE FROM dsa_dataout+0x0218, WHEN DATA_OUT + +at 0x000001c6 : */ 0x18000000,0x00000640, +/* + MOVE FROM dsa_dataout+0x0220, WHEN DATA_OUT + +at 0x000001c8 : */ 0x18000000,0x00000648, +/* + MOVE FROM dsa_dataout+0x0228, WHEN DATA_OUT + +at 0x000001ca : */ 0x18000000,0x00000650, +/* + MOVE FROM dsa_dataout+0x0230, WHEN DATA_OUT + +at 0x000001cc : */ 0x18000000,0x00000658, +/* + MOVE FROM dsa_dataout+0x0238, WHEN DATA_OUT + +at 0x000001ce : */ 0x18000000,0x00000660, +/* + MOVE FROM dsa_dataout+0x0240, WHEN DATA_OUT + +at 0x000001d0 : */ 0x18000000,0x00000668, +/* + MOVE FROM dsa_dataout+0x0248, WHEN DATA_OUT + +at 0x000001d2 : */ 0x18000000,0x00000670, +/* + MOVE FROM dsa_dataout+0x0250, WHEN DATA_OUT + +at 0x000001d4 : */ 0x18000000,0x00000678, +/* + MOVE FROM dsa_dataout+0x0258, WHEN DATA_OUT + +at 0x000001d6 : */ 0x18000000,0x00000680, +/* + MOVE FROM dsa_dataout+0x0260, WHEN DATA_OUT + +at 0x000001d8 : */ 0x18000000,0x00000688, +/* + MOVE FROM dsa_dataout+0x0268, WHEN DATA_OUT + +at 0x000001da : */ 0x18000000,0x00000690, +/* + MOVE FROM dsa_dataout+0x0270, WHEN DATA_OUT + +at 0x000001dc : */ 0x18000000,0x00000698, +/* + MOVE FROM dsa_dataout+0x0278, WHEN DATA_OUT + +at 0x000001de : */ 0x18000000,0x000006a0, +/* + MOVE FROM dsa_dataout+0x0280, WHEN DATA_OUT + +at 0x000001e0 : */ 0x18000000,0x000006a8, +/* + MOVE FROM dsa_dataout+0x0288, WHEN DATA_OUT + +at 0x000001e2 : */ 0x18000000,0x000006b0, +/* + MOVE FROM dsa_dataout+0x0290, WHEN DATA_OUT + +at 0x000001e4 : */ 0x18000000,0x000006b8, +/* + MOVE FROM dsa_dataout+0x0298, WHEN DATA_OUT + +at 0x000001e6 : */ 0x18000000,0x000006c0, +/* + MOVE FROM dsa_dataout+0x02a0, WHEN DATA_OUT + +at 0x000001e8 : */ 0x18000000,0x000006c8, +/* + MOVE FROM dsa_dataout+0x02a8, WHEN DATA_OUT + +at 0x000001ea : */ 0x18000000,0x000006d0, +/* + MOVE FROM dsa_dataout+0x02b0, WHEN DATA_OUT + +at 0x000001ec : */ 0x18000000,0x000006d8, +/* + MOVE FROM dsa_dataout+0x02b8, WHEN DATA_OUT + +at 0x000001ee : */ 0x18000000,0x000006e0, +/* + MOVE FROM dsa_dataout+0x02c0, WHEN DATA_OUT + +at 0x000001f0 : */ 0x18000000,0x000006e8, +/* + MOVE FROM dsa_dataout+0x02c8, WHEN DATA_OUT + +at 0x000001f2 : */ 0x18000000,0x000006f0, +/* + MOVE FROM dsa_dataout+0x02d0, WHEN DATA_OUT + +at 0x000001f4 : */ 0x18000000,0x000006f8, +/* + MOVE FROM dsa_dataout+0x02d8, WHEN DATA_OUT + +at 0x000001f6 : */ 0x18000000,0x00000700, +/* + MOVE FROM dsa_dataout+0x02e0, WHEN DATA_OUT + +at 0x000001f8 : */ 0x18000000,0x00000708, +/* + MOVE FROM dsa_dataout+0x02e8, WHEN DATA_OUT + +at 0x000001fa : */ 0x18000000,0x00000710, +/* + MOVE FROM dsa_dataout+0x02f0, WHEN DATA_OUT + +at 0x000001fc : */ 0x18000000,0x00000718, +/* + MOVE FROM dsa_dataout+0x02f8, WHEN DATA_OUT + +at 0x000001fe : */ 0x18000000,0x00000720, +/* + MOVE FROM dsa_dataout+0x0300, WHEN DATA_OUT + +at 0x00000200 : */ 0x18000000,0x00000728, +/* + MOVE FROM dsa_dataout+0x0308, WHEN DATA_OUT + +at 0x00000202 : */ 0x18000000,0x00000730, +/* + MOVE FROM dsa_dataout+0x0310, WHEN DATA_OUT + +at 0x00000204 : */ 0x18000000,0x00000738, +/* + MOVE FROM dsa_dataout+0x0318, WHEN DATA_OUT + +at 0x00000206 : */ 0x18000000,0x00000740, +/* + MOVE FROM dsa_dataout+0x0320, WHEN DATA_OUT + +at 0x00000208 : */ 0x18000000,0x00000748, +/* + MOVE FROM dsa_dataout+0x0328, WHEN DATA_OUT + +at 0x0000020a : */ 0x18000000,0x00000750, +/* + MOVE FROM dsa_dataout+0x0330, WHEN DATA_OUT + +at 0x0000020c : */ 0x18000000,0x00000758, +/* + MOVE FROM dsa_dataout+0x0338, WHEN DATA_OUT + +at 0x0000020e : */ 0x18000000,0x00000760, +/* + MOVE FROM dsa_dataout+0x0340, WHEN DATA_OUT + +at 0x00000210 : */ 0x18000000,0x00000768, +/* + MOVE FROM dsa_dataout+0x0348, WHEN DATA_OUT + +at 0x00000212 : */ 0x18000000,0x00000770, +/* + MOVE FROM dsa_dataout+0x0350, WHEN DATA_OUT + +at 0x00000214 : */ 0x18000000,0x00000778, +/* + MOVE FROM dsa_dataout+0x0358, WHEN DATA_OUT + +at 0x00000216 : */ 0x18000000,0x00000780, +/* + MOVE FROM dsa_dataout+0x0360, WHEN DATA_OUT + +at 0x00000218 : */ 0x18000000,0x00000788, +/* + MOVE FROM dsa_dataout+0x0368, WHEN DATA_OUT + +at 0x0000021a : */ 0x18000000,0x00000790, +/* + MOVE FROM dsa_dataout+0x0370, WHEN DATA_OUT + +at 0x0000021c : */ 0x18000000,0x00000798, +/* + MOVE FROM dsa_dataout+0x0378, WHEN DATA_OUT + +at 0x0000021e : */ 0x18000000,0x000007a0, +/* + MOVE FROM dsa_dataout+0x0380, WHEN DATA_OUT + +at 0x00000220 : */ 0x18000000,0x000007a8, +/* + MOVE FROM dsa_dataout+0x0388, WHEN DATA_OUT + +at 0x00000222 : */ 0x18000000,0x000007b0, +/* + MOVE FROM dsa_dataout+0x0390, WHEN DATA_OUT + +at 0x00000224 : */ 0x18000000,0x000007b8, +/* + MOVE FROM dsa_dataout+0x0398, WHEN DATA_OUT + +at 0x00000226 : */ 0x18000000,0x000007c0, +/* + MOVE FROM dsa_dataout+0x03a0, WHEN DATA_OUT + +at 0x00000228 : */ 0x18000000,0x000007c8, +/* + MOVE FROM dsa_dataout+0x03a8, WHEN DATA_OUT + +at 0x0000022a : */ 0x18000000,0x000007d0, +/* + MOVE FROM dsa_dataout+0x03b0, WHEN DATA_OUT + +at 0x0000022c : */ 0x18000000,0x000007d8, +/* + MOVE FROM dsa_dataout+0x03b8, WHEN DATA_OUT + +at 0x0000022e : */ 0x18000000,0x000007e0, +/* + MOVE FROM dsa_dataout+0x03c0, WHEN DATA_OUT + +at 0x00000230 : */ 0x18000000,0x000007e8, +/* + MOVE FROM dsa_dataout+0x03c8, WHEN DATA_OUT + +at 0x00000232 : */ 0x18000000,0x000007f0, +/* + MOVE FROM dsa_dataout+0x03d0, WHEN DATA_OUT + +at 0x00000234 : */ 0x18000000,0x000007f8, +/* + MOVE FROM dsa_dataout+0x03d8, WHEN DATA_OUT + +at 0x00000236 : */ 0x18000000,0x00000800, +/* + MOVE FROM dsa_dataout+0x03e0, WHEN DATA_OUT + +at 0x00000238 : */ 0x18000000,0x00000808, +/* + MOVE FROM dsa_dataout+0x03e8, WHEN DATA_OUT + +at 0x0000023a : */ 0x18000000,0x00000810, +/* + MOVE FROM dsa_dataout+0x03f0, WHEN DATA_OUT + +at 0x0000023c : */ 0x18000000,0x00000818, +/* + MOVE FROM dsa_dataout+0x03f8, WHEN DATA_OUT + +at 0x0000023e : */ 0x18000000,0x00000820, +/* +ENTRY end_data_trans +end_data_trans: +redo_msgin3: + JUMP get_status, WHEN STATUS + +at 0x00000240 : */ 0x830b0000,0x00000098, +/* + JUMP get_msgin3, WHEN MSG_IN + +at 0x00000242 : */ 0x870b0000,0x00000b78, +/* + INT int_data_bad_phase + +at 0x00000244 : */ 0x98080000,0xab93000b, +/* + +get_msgin1: + MOVE SCRATCH0 | had_msgin TO SCRATCH0 + +at 0x00000246 : */ 0x7a344000,0x00000000, +/* + MOVE 1, msgin_buf, WHEN MSG_IN + +at 0x00000248 : */ 0x0f000001,0x00000000, +/* + JUMP ext_msg1, IF 0x01 ; Extended Message + +at 0x0000024a : */ 0x800c0001,0x00000960, +/* + JUMP ignore_msg1, IF 0x02 ; Save Data Pointers + +at 0x0000024c : */ 0x800c0002,0x00000950, +/* + JUMP ignore_msg1, IF 0x03 ; Save Restore Pointers + +at 0x0000024e : */ 0x800c0003,0x00000950, +/* + JUMP disc1, IF 0x04 ; Disconnect + +at 0x00000250 : */ 0x800c0004,0x000009f0, +/* + INT int_bad_msg1 + +at 0x00000252 : */ 0x98080000,0xab930006, +/* +ignore_msg1: + CLEAR ACK + +at 0x00000254 : */ 0x60000040,0x00000000, +/* + JUMP redo_msgin1 + +at 0x00000256 : */ 0x80080000,0x00000050, +/* +ext_msg1: + MOVE SCRATCH0 | had_extmsg TO SCRATCH0 + +at 0x00000258 : */ 0x7a348000,0x00000000, +/* + CLEAR ACK + +at 0x0000025a : */ 0x60000040,0x00000000, +/* + MOVE 1, msgin_buf + 1, WHEN MSG_IN + +at 0x0000025c : */ 0x0f000001,0x00000001, +/* + JUMP reject_msg1, IF NOT 0x03 ; Only handle SDTR + +at 0x0000025e : */ 0x80040003,0x000009b0, +/* + CLEAR ACK + +at 0x00000260 : */ 0x60000040,0x00000000, +/* + MOVE 1, msgin_buf + 2, WHEN MSG_IN + +at 0x00000262 : */ 0x0f000001,0x00000002, +/* + JUMP reject_msg1, IF NOT 0x01 ; Only handle SDTR + +at 0x00000264 : */ 0x80040001,0x000009b0, +/* + CLEAR ACK + +at 0x00000266 : */ 0x60000040,0x00000000, +/* + MOVE 2, msgin_buf + 3, WHEN MSG_IN + +at 0x00000268 : */ 0x0f000002,0x00000003, +/* + INT int_msg_sdtr1 + +at 0x0000026a : */ 0x98080000,0xab93000c, +/* +reject_msg1: + MOVE SCRATCH1 | did_reject TO SCRATCH1 + +at 0x0000026c : */ 0x7a350100,0x00000000, +/* + SET ATN + +at 0x0000026e : */ 0x58000008,0x00000000, +/* + CLEAR ACK + +at 0x00000270 : */ 0x60000040,0x00000000, +/* + JUMP reject_msg1a, WHEN NOT MSG_IN + +at 0x00000272 : */ 0x87030000,0x000009e0, +/* + MOVE 1, msgin_buf + 7, WHEN MSG_IN + +at 0x00000274 : */ 0x0f000001,0x00000007, +/* + JUMP reject_msg1 + +at 0x00000276 : */ 0x80080000,0x000009b0, +/* +reject_msg1a: + MOVE 1, msg_reject, WHEN MSG_OUT + +at 0x00000278 : */ 0x0e000001,0x00000000, +/* + JUMP redo_msgin1 + +at 0x0000027a : */ 0x80080000,0x00000050, +/* +disc1: + CLEAR ACK + +at 0x0000027c : */ 0x60000040,0x00000000, +/* +ENTRY wait_disc1 +wait_disc1: + WAIT DISCONNECT + +at 0x0000027e : */ 0x48000000,0x00000000, +/* + INT int_disc1 + +at 0x00000280 : */ 0x98080000,0xab930019, +/* +ENTRY resume_msgin1a +resume_msgin1a: + CLEAR ACK + +at 0x00000282 : */ 0x60000040,0x00000000, +/* + JUMP redo_msgin1 + +at 0x00000284 : */ 0x80080000,0x00000050, +/* +ENTRY resume_msgin1b +resume_msgin1b: + SET ATN + +at 0x00000286 : */ 0x58000008,0x00000000, +/* + CLEAR ACK + +at 0x00000288 : */ 0x60000040,0x00000000, +/* + INT int_no_msgout1, WHEN NOT MSG_OUT + +at 0x0000028a : */ 0x9e030000,0xab93000f, +/* + MOVE SCRATCH0 | had_msgout TO SCRATCH0 + +at 0x0000028c : */ 0x7a340200,0x00000000, +/* + MOVE FROM dsa_msgout, when MSG_OUT + +at 0x0000028e : */ 0x1e000000,0x00000008, +/* + JUMP redo_msgin1 + +at 0x00000290 : */ 0x80080000,0x00000050, +/* + +get_msgin2: + MOVE SCRATCH0 | had_msgin TO SCRATCH0 + +at 0x00000292 : */ 0x7a344000,0x00000000, +/* + MOVE 1, msgin_buf, WHEN MSG_IN + +at 0x00000294 : */ 0x0f000001,0x00000000, +/* + JUMP ext_msg2, IF 0x01 ; Extended Message + +at 0x00000296 : */ 0x800c0001,0x00000a90, +/* + JUMP ignore_msg2, IF 0x02 ; Save Data Pointers + +at 0x00000298 : */ 0x800c0002,0x00000a80, +/* + JUMP ignore_msg2, IF 0x03 ; Save Restore Pointers + +at 0x0000029a : */ 0x800c0003,0x00000a80, +/* + JUMP disc2, IF 0x04 ; Disconnect + +at 0x0000029c : */ 0x800c0004,0x00000b20, +/* + INT int_bad_msg2 + +at 0x0000029e : */ 0x98080000,0xab930007, +/* +ignore_msg2: + CLEAR ACK + +at 0x000002a0 : */ 0x60000040,0x00000000, +/* + JUMP redo_msgin2 + +at 0x000002a2 : */ 0x80080000,0x00000070, +/* +ext_msg2: + MOVE SCRATCH0 | had_extmsg TO SCRATCH0 + +at 0x000002a4 : */ 0x7a348000,0x00000000, +/* + CLEAR ACK + +at 0x000002a6 : */ 0x60000040,0x00000000, +/* + MOVE 1, msgin_buf + 1, WHEN MSG_IN + +at 0x000002a8 : */ 0x0f000001,0x00000001, +/* + JUMP reject_msg2, IF NOT 0x03 ; Only handle SDTR + +at 0x000002aa : */ 0x80040003,0x00000ae0, +/* + CLEAR ACK + +at 0x000002ac : */ 0x60000040,0x00000000, +/* + MOVE 1, msgin_buf + 2, WHEN MSG_IN + +at 0x000002ae : */ 0x0f000001,0x00000002, +/* + JUMP reject_msg2, IF NOT 0x01 ; Only handle SDTR + +at 0x000002b0 : */ 0x80040001,0x00000ae0, +/* + CLEAR ACK + +at 0x000002b2 : */ 0x60000040,0x00000000, +/* + MOVE 2, msgin_buf + 3, WHEN MSG_IN + +at 0x000002b4 : */ 0x0f000002,0x00000003, +/* + INT int_msg_sdtr2 + +at 0x000002b6 : */ 0x98080000,0xab93000d, +/* +reject_msg2: + MOVE SCRATCH1 | did_reject TO SCRATCH1 + +at 0x000002b8 : */ 0x7a350100,0x00000000, +/* + SET ATN + +at 0x000002ba : */ 0x58000008,0x00000000, +/* + CLEAR ACK + +at 0x000002bc : */ 0x60000040,0x00000000, +/* + JUMP reject_msg2a, WHEN NOT MSG_IN + +at 0x000002be : */ 0x87030000,0x00000b10, +/* + MOVE 1, msgin_buf + 7, WHEN MSG_IN + +at 0x000002c0 : */ 0x0f000001,0x00000007, +/* + JUMP reject_msg2 + +at 0x000002c2 : */ 0x80080000,0x00000ae0, +/* +reject_msg2a: + MOVE 1, msg_reject, WHEN MSG_OUT + +at 0x000002c4 : */ 0x0e000001,0x00000000, +/* + JUMP redo_msgin2 + +at 0x000002c6 : */ 0x80080000,0x00000070, +/* +disc2: + CLEAR ACK + +at 0x000002c8 : */ 0x60000040,0x00000000, +/* +ENTRY wait_disc2 +wait_disc2: + WAIT DISCONNECT + +at 0x000002ca : */ 0x48000000,0x00000000, +/* + INT int_disc2 + +at 0x000002cc : */ 0x98080000,0xab93001a, +/* +ENTRY resume_msgin2a +resume_msgin2a: + CLEAR ACK + +at 0x000002ce : */ 0x60000040,0x00000000, +/* + JUMP redo_msgin2 + +at 0x000002d0 : */ 0x80080000,0x00000070, +/* +ENTRY resume_msgin2b +resume_msgin2b: + SET ATN + +at 0x000002d2 : */ 0x58000008,0x00000000, +/* + CLEAR ACK + +at 0x000002d4 : */ 0x60000040,0x00000000, +/* + INT int_no_msgout2, WHEN NOT MSG_OUT + +at 0x000002d6 : */ 0x9e030000,0xab930010, +/* + MOVE SCRATCH0 | had_msgout TO SCRATCH0 + +at 0x000002d8 : */ 0x7a340200,0x00000000, +/* + MOVE FROM dsa_msgout, when MSG_OUT + +at 0x000002da : */ 0x1e000000,0x00000008, +/* + JUMP redo_msgin2 + +at 0x000002dc : */ 0x80080000,0x00000070, +/* + +get_msgin3: + MOVE SCRATCH0 | had_msgin TO SCRATCH0 + +at 0x000002de : */ 0x7a344000,0x00000000, +/* + MOVE 1, msgin_buf, WHEN MSG_IN + +at 0x000002e0 : */ 0x0f000001,0x00000000, +/* + JUMP ext_msg3, IF 0x01 ; Extended Message + +at 0x000002e2 : */ 0x800c0001,0x00000bc0, +/* + JUMP ignore_msg3, IF 0x02 ; Save Data Pointers + +at 0x000002e4 : */ 0x800c0002,0x00000bb0, +/* + JUMP ignore_msg3, IF 0x03 ; Save Restore Pointers + +at 0x000002e6 : */ 0x800c0003,0x00000bb0, +/* + JUMP disc3, IF 0x04 ; Disconnect + +at 0x000002e8 : */ 0x800c0004,0x00000c50, +/* + INT int_bad_msg3 + +at 0x000002ea : */ 0x98080000,0xab930008, +/* +ignore_msg3: + CLEAR ACK + +at 0x000002ec : */ 0x60000040,0x00000000, +/* + JUMP redo_msgin3 + +at 0x000002ee : */ 0x80080000,0x00000900, +/* +ext_msg3: + MOVE SCRATCH0 | had_extmsg TO SCRATCH0 + +at 0x000002f0 : */ 0x7a348000,0x00000000, +/* + CLEAR ACK + +at 0x000002f2 : */ 0x60000040,0x00000000, +/* + MOVE 1, msgin_buf + 1, WHEN MSG_IN + +at 0x000002f4 : */ 0x0f000001,0x00000001, +/* + JUMP reject_msg3, IF NOT 0x03 ; Only handle SDTR + +at 0x000002f6 : */ 0x80040003,0x00000c10, +/* + CLEAR ACK + +at 0x000002f8 : */ 0x60000040,0x00000000, +/* + MOVE 1, msgin_buf + 2, WHEN MSG_IN + +at 0x000002fa : */ 0x0f000001,0x00000002, +/* + JUMP reject_msg3, IF NOT 0x01 ; Only handle SDTR + +at 0x000002fc : */ 0x80040001,0x00000c10, +/* + CLEAR ACK + +at 0x000002fe : */ 0x60000040,0x00000000, +/* + MOVE 2, msgin_buf + 3, WHEN MSG_IN + +at 0x00000300 : */ 0x0f000002,0x00000003, +/* + INT int_msg_sdtr3 + +at 0x00000302 : */ 0x98080000,0xab93000e, +/* +reject_msg3: + MOVE SCRATCH1 | did_reject TO SCRATCH1 + +at 0x00000304 : */ 0x7a350100,0x00000000, +/* + SET ATN + +at 0x00000306 : */ 0x58000008,0x00000000, +/* + CLEAR ACK + +at 0x00000308 : */ 0x60000040,0x00000000, +/* + JUMP reject_msg3a, WHEN NOT MSG_IN + +at 0x0000030a : */ 0x87030000,0x00000c40, +/* + MOVE 1, msgin_buf + 7, WHEN MSG_IN + +at 0x0000030c : */ 0x0f000001,0x00000007, +/* + JUMP reject_msg3 + +at 0x0000030e : */ 0x80080000,0x00000c10, +/* +reject_msg3a: + MOVE 1, msg_reject, WHEN MSG_OUT + +at 0x00000310 : */ 0x0e000001,0x00000000, +/* + JUMP redo_msgin3 + +at 0x00000312 : */ 0x80080000,0x00000900, +/* +disc3: + CLEAR ACK + +at 0x00000314 : */ 0x60000040,0x00000000, +/* +ENTRY wait_disc3 +wait_disc3: + WAIT DISCONNECT + +at 0x00000316 : */ 0x48000000,0x00000000, +/* + INT int_disc3 + +at 0x00000318 : */ 0x98080000,0xab93001b, +/* +ENTRY resume_msgin3a +resume_msgin3a: + CLEAR ACK + +at 0x0000031a : */ 0x60000040,0x00000000, +/* + JUMP redo_msgin3 + +at 0x0000031c : */ 0x80080000,0x00000900, +/* +ENTRY resume_msgin3b +resume_msgin3b: + SET ATN + +at 0x0000031e : */ 0x58000008,0x00000000, +/* + CLEAR ACK + +at 0x00000320 : */ 0x60000040,0x00000000, +/* + INT int_no_msgout3, WHEN NOT MSG_OUT + +at 0x00000322 : */ 0x9e030000,0xab930011, +/* + MOVE SCRATCH0 | had_msgout TO SCRATCH0 + +at 0x00000324 : */ 0x7a340200,0x00000000, +/* + MOVE FROM dsa_msgout, when MSG_OUT + +at 0x00000326 : */ 0x1e000000,0x00000008, +/* + JUMP redo_msgin3 + +at 0x00000328 : */ 0x80080000,0x00000900, +/* + +ENTRY resume_rej_ident +resume_rej_ident: + CLEAR ATN + +at 0x0000032a : */ 0x60000008,0x00000000, +/* + MOVE 1, msgin_buf, WHEN MSG_IN + +at 0x0000032c : */ 0x0f000001,0x00000000, +/* + INT int_not_rej, IF NOT 0x07 ; Reject + +at 0x0000032e : */ 0x98040007,0xab93001c, +/* + CLEAR ACK + +at 0x00000330 : */ 0x60000040,0x00000000, +/* + JUMP done_ident + +at 0x00000332 : */ 0x80080000,0x00000048, +/* + +ENTRY reselect +reselect: + ; Disable selection timer + MOVE CTEST7 | 0x10 TO CTEST7 + +at 0x00000334 : */ 0x7a1b1000,0x00000000, +/* + WAIT RESELECT resel_err + +at 0x00000336 : */ 0x50000000,0x00000cf8, +/* + INT int_resel_not_msgin, WHEN NOT MSG_IN + +at 0x00000338 : */ 0x9f030000,0xab930016, +/* + MOVE 1, reselected_identify, WHEN MSG_IN + +at 0x0000033a : */ 0x0f000001,0x00000000, +/* + INT int_reselected + +at 0x0000033c : */ 0x98080000,0xab930017, +/* +resel_err: + MOVE CTEST2 & 0x40 TO SFBR + +at 0x0000033e : */ 0x74164000,0x00000000, +/* + JUMP selected, IF 0x00 + +at 0x00000340 : */ 0x800c0000,0x00000d38, +/* + MOVE SFBR & 0 TO SFBR + +at 0x00000342 : */ 0x7c080000,0x00000000, +/* +ENTRY patch_new_dsa +patch_new_dsa: + MOVE SFBR | 0x11 TO DSA0 + +at 0x00000344 : */ 0x6a101100,0x00000000, +/* + MOVE SFBR | 0x22 TO DSA1 + +at 0x00000346 : */ 0x6a112200,0x00000000, +/* + MOVE SFBR | 0x33 TO DSA2 + +at 0x00000348 : */ 0x6a123300,0x00000000, +/* + MOVE SFBR | 0x44 TO DSA3 + +at 0x0000034a : */ 0x6a134400,0x00000000, +/* + JUMP do_select + +at 0x0000034c : */ 0x80080000,0x00000000, +/* + +selected: + INT int_selected + +at 0x0000034e : */ 0x98080000,0xab930018, +/* + +ENTRY test1 +test1: + MOVE MEMORY 4, test1_src, test1_dst + +at 0x00000350 : */ 0xc0000004,0x00000000,0x00000000, +/* + INT int_test1 + +at 0x00000353 : */ 0x98080000,0xab93001d, +}; + +#define A_did_reject 0x00000001 +static u32 A_did_reject_used[] __attribute((unused)) = { + 0x0000026c, + 0x000002b8, + 0x00000304, +}; + +#define A_dsa_cmnd 0x00000010 +static u32 A_dsa_cmnd_used[] __attribute((unused)) = { + 0x0000001b, +}; + +#define A_dsa_datain 0x00000028 +static u32 A_dsa_datain_used[] __attribute((unused)) = { + 0x0000003b, + 0x0000003d, + 0x0000003f, + 0x00000041, + 0x00000043, + 0x00000045, + 0x00000047, + 0x00000049, + 0x0000004b, + 0x0000004d, + 0x0000004f, + 0x00000051, + 0x00000053, + 0x00000055, + 0x00000057, + 0x00000059, + 0x0000005b, + 0x0000005d, + 0x0000005f, + 0x00000061, + 0x00000063, + 0x00000065, + 0x00000067, + 0x00000069, + 0x0000006b, + 0x0000006d, + 0x0000006f, + 0x00000071, + 0x00000073, + 0x00000075, + 0x00000077, + 0x00000079, + 0x0000007b, + 0x0000007d, + 0x0000007f, + 0x00000081, + 0x00000083, + 0x00000085, + 0x00000087, + 0x00000089, + 0x0000008b, + 0x0000008d, + 0x0000008f, + 0x00000091, + 0x00000093, + 0x00000095, + 0x00000097, + 0x00000099, + 0x0000009b, + 0x0000009d, + 0x0000009f, + 0x000000a1, + 0x000000a3, + 0x000000a5, + 0x000000a7, + 0x000000a9, + 0x000000ab, + 0x000000ad, + 0x000000af, + 0x000000b1, + 0x000000b3, + 0x000000b5, + 0x000000b7, + 0x000000b9, + 0x000000bb, + 0x000000bd, + 0x000000bf, + 0x000000c1, + 0x000000c3, + 0x000000c5, + 0x000000c7, + 0x000000c9, + 0x000000cb, + 0x000000cd, + 0x000000cf, + 0x000000d1, + 0x000000d3, + 0x000000d5, + 0x000000d7, + 0x000000d9, + 0x000000db, + 0x000000dd, + 0x000000df, + 0x000000e1, + 0x000000e3, + 0x000000e5, + 0x000000e7, + 0x000000e9, + 0x000000eb, + 0x000000ed, + 0x000000ef, + 0x000000f1, + 0x000000f3, + 0x000000f5, + 0x000000f7, + 0x000000f9, + 0x000000fb, + 0x000000fd, + 0x000000ff, + 0x00000101, + 0x00000103, + 0x00000105, + 0x00000107, + 0x00000109, + 0x0000010b, + 0x0000010d, + 0x0000010f, + 0x00000111, + 0x00000113, + 0x00000115, + 0x00000117, + 0x00000119, + 0x0000011b, + 0x0000011d, + 0x0000011f, + 0x00000121, + 0x00000123, + 0x00000125, + 0x00000127, + 0x00000129, + 0x0000012b, + 0x0000012d, + 0x0000012f, + 0x00000131, + 0x00000133, + 0x00000135, + 0x00000137, + 0x00000139, +}; + +#define A_dsa_dataout 0x00000428 +static u32 A_dsa_dataout_used[] __attribute((unused)) = { + 0x00000141, + 0x00000143, + 0x00000145, + 0x00000147, + 0x00000149, + 0x0000014b, + 0x0000014d, + 0x0000014f, + 0x00000151, + 0x00000153, + 0x00000155, + 0x00000157, + 0x00000159, + 0x0000015b, + 0x0000015d, + 0x0000015f, + 0x00000161, + 0x00000163, + 0x00000165, + 0x00000167, + 0x00000169, + 0x0000016b, + 0x0000016d, + 0x0000016f, + 0x00000171, + 0x00000173, + 0x00000175, + 0x00000177, + 0x00000179, + 0x0000017b, + 0x0000017d, + 0x0000017f, + 0x00000181, + 0x00000183, + 0x00000185, + 0x00000187, + 0x00000189, + 0x0000018b, + 0x0000018d, + 0x0000018f, + 0x00000191, + 0x00000193, + 0x00000195, + 0x00000197, + 0x00000199, + 0x0000019b, + 0x0000019d, + 0x0000019f, + 0x000001a1, + 0x000001a3, + 0x000001a5, + 0x000001a7, + 0x000001a9, + 0x000001ab, + 0x000001ad, + 0x000001af, + 0x000001b1, + 0x000001b3, + 0x000001b5, + 0x000001b7, + 0x000001b9, + 0x000001bb, + 0x000001bd, + 0x000001bf, + 0x000001c1, + 0x000001c3, + 0x000001c5, + 0x000001c7, + 0x000001c9, + 0x000001cb, + 0x000001cd, + 0x000001cf, + 0x000001d1, + 0x000001d3, + 0x000001d5, + 0x000001d7, + 0x000001d9, + 0x000001db, + 0x000001dd, + 0x000001df, + 0x000001e1, + 0x000001e3, + 0x000001e5, + 0x000001e7, + 0x000001e9, + 0x000001eb, + 0x000001ed, + 0x000001ef, + 0x000001f1, + 0x000001f3, + 0x000001f5, + 0x000001f7, + 0x000001f9, + 0x000001fb, + 0x000001fd, + 0x000001ff, + 0x00000201, + 0x00000203, + 0x00000205, + 0x00000207, + 0x00000209, + 0x0000020b, + 0x0000020d, + 0x0000020f, + 0x00000211, + 0x00000213, + 0x00000215, + 0x00000217, + 0x00000219, + 0x0000021b, + 0x0000021d, + 0x0000021f, + 0x00000221, + 0x00000223, + 0x00000225, + 0x00000227, + 0x00000229, + 0x0000022b, + 0x0000022d, + 0x0000022f, + 0x00000231, + 0x00000233, + 0x00000235, + 0x00000237, + 0x00000239, + 0x0000023b, + 0x0000023d, + 0x0000023f, +}; + +#define A_dsa_msgin 0x00000020 +static u32 A_dsa_msgin_used[] __attribute((unused)) = { + 0x0000002d, +}; + +#define A_dsa_msgout 0x00000008 +static u32 A_dsa_msgout_used[] __attribute((unused)) = { + 0x00000011, + 0x0000028f, + 0x000002db, + 0x00000327, +}; + +#define A_dsa_select 0x00000000 +static u32 A_dsa_select_used[] __attribute((unused)) = { + 0x00000004, +}; + +#define A_dsa_size 0x00000828 +static u32 A_dsa_size_used[] __attribute((unused)) = { +}; + +#define A_dsa_status 0x00000018 +static u32 A_dsa_status_used[] __attribute((unused)) = { + 0x00000029, +}; + +#define A_had_cmdout 0x00000004 +static u32 A_had_cmdout_used[] __attribute((unused)) = { + 0x00000018, +}; + +#define A_had_datain 0x00000008 +static u32 A_had_datain_used[] __attribute((unused)) = { + 0x00000036, +}; + +#define A_had_dataout 0x00000010 +static u32 A_had_dataout_used[] __attribute((unused)) = { + 0x0000013c, +}; + +#define A_had_extmsg 0x00000080 +static u32 A_had_extmsg_used[] __attribute((unused)) = { + 0x00000258, + 0x000002a4, + 0x000002f0, +}; + +#define A_had_msgin 0x00000040 +static u32 A_had_msgin_used[] __attribute((unused)) = { + 0x00000246, + 0x00000292, + 0x000002de, +}; + +#define A_had_msgout 0x00000002 +static u32 A_had_msgout_used[] __attribute((unused)) = { + 0x0000000e, + 0x0000028c, + 0x000002d8, + 0x00000324, +}; + +#define A_had_select 0x00000001 +static u32 A_had_select_used[] __attribute((unused)) = { + 0x0000000a, +}; + +#define A_had_status 0x00000020 +static u32 A_had_status_used[] __attribute((unused)) = { +}; + +#define A_int_bad_msg1 0xab930006 +static u32 A_int_bad_msg1_used[] __attribute((unused)) = { + 0x00000253, +}; + +#define A_int_bad_msg2 0xab930007 +static u32 A_int_bad_msg2_used[] __attribute((unused)) = { + 0x0000029f, +}; + +#define A_int_bad_msg3 0xab930008 +static u32 A_int_bad_msg3_used[] __attribute((unused)) = { + 0x000002eb, +}; + +#define A_int_cmd_bad_phase 0xab930009 +static u32 A_int_cmd_bad_phase_used[] __attribute((unused)) = { + 0x00000025, +}; + +#define A_int_cmd_complete 0xab93000a +static u32 A_int_cmd_complete_used[] __attribute((unused)) = { + 0x00000035, +}; + +#define A_int_data_bad_phase 0xab93000b +static u32 A_int_data_bad_phase_used[] __attribute((unused)) = { + 0x00000245, +}; + +#define A_int_disc1 0xab930019 +static u32 A_int_disc1_used[] __attribute((unused)) = { + 0x00000281, +}; + +#define A_int_disc2 0xab93001a +static u32 A_int_disc2_used[] __attribute((unused)) = { + 0x000002cd, +}; + +#define A_int_disc3 0xab93001b +static u32 A_int_disc3_used[] __attribute((unused)) = { + 0x00000319, +}; + +#define A_int_msg_sdtr1 0xab93000c +static u32 A_int_msg_sdtr1_used[] __attribute((unused)) = { + 0x0000026b, +}; + +#define A_int_msg_sdtr2 0xab93000d +static u32 A_int_msg_sdtr2_used[] __attribute((unused)) = { + 0x000002b7, +}; + +#define A_int_msg_sdtr3 0xab93000e +static u32 A_int_msg_sdtr3_used[] __attribute((unused)) = { + 0x00000303, +}; + +#define A_int_no_msgout1 0xab93000f +static u32 A_int_no_msgout1_used[] __attribute((unused)) = { + 0x0000028b, +}; + +#define A_int_no_msgout2 0xab930010 +static u32 A_int_no_msgout2_used[] __attribute((unused)) = { + 0x000002d7, +}; + +#define A_int_no_msgout3 0xab930011 +static u32 A_int_no_msgout3_used[] __attribute((unused)) = { + 0x00000323, +}; + +#define A_int_not_cmd_complete 0xab930012 +static u32 A_int_not_cmd_complete_used[] __attribute((unused)) = { + 0x0000002f, +}; + +#define A_int_not_rej 0xab93001c +static u32 A_int_not_rej_used[] __attribute((unused)) = { + 0x0000032f, +}; + +#define A_int_resel_not_msgin 0xab930016 +static u32 A_int_resel_not_msgin_used[] __attribute((unused)) = { + 0x00000339, +}; + +#define A_int_reselected 0xab930017 +static u32 A_int_reselected_used[] __attribute((unused)) = { + 0x0000033d, +}; + +#define A_int_sel_no_ident 0xab930013 +static u32 A_int_sel_no_ident_used[] __attribute((unused)) = { + 0x0000000d, +}; + +#define A_int_sel_not_cmd 0xab930014 +static u32 A_int_sel_not_cmd_used[] __attribute((unused)) = { + 0x00000017, +}; + +#define A_int_selected 0xab930018 +static u32 A_int_selected_used[] __attribute((unused)) = { + 0x0000034f, +}; + +#define A_int_status_not_msgin 0xab930015 +static u32 A_int_status_not_msgin_used[] __attribute((unused)) = { + 0x0000002b, +}; + +#define A_int_test1 0xab93001d +static u32 A_int_test1_used[] __attribute((unused)) = { + 0x00000354, +}; + +#define A_msg_reject 0x00000000 +static u32 A_msg_reject_used[] __attribute((unused)) = { + 0x00000279, + 0x000002c5, + 0x00000311, +}; + +#define A_msgin_buf 0x00000000 +static u32 A_msgin_buf_used[] __attribute((unused)) = { + 0x00000249, + 0x0000025d, + 0x00000263, + 0x00000269, + 0x00000275, + 0x00000295, + 0x000002a9, + 0x000002af, + 0x000002b5, + 0x000002c1, + 0x000002e1, + 0x000002f5, + 0x000002fb, + 0x00000301, + 0x0000030d, + 0x0000032d, +}; + +#define A_reselected_identify 0x00000000 +static u32 A_reselected_identify_used[] __attribute((unused)) = { + 0x0000033b, +}; + +#define A_test1_dst 0x00000000 +static u32 A_test1_dst_used[] __attribute((unused)) = { + 0x00000352, +}; + +#define A_test1_src 0x00000000 +static u32 A_test1_src_used[] __attribute((unused)) = { + 0x00000351, +}; + +#define Ent_do_select 0x00000000 +#define Ent_done_ident 0x00000048 +#define Ent_end_data_trans 0x00000900 +#define Ent_patch_input_data 0x000000e0 +#define Ent_patch_new_dsa 0x00000d10 +#define Ent_patch_output_data 0x000004f8 +#define Ent_reselect 0x00000cd0 +#define Ent_resume_cmd 0x00000060 +#define Ent_resume_msgin1a 0x00000a08 +#define Ent_resume_msgin1b 0x00000a18 +#define Ent_resume_msgin2a 0x00000b38 +#define Ent_resume_msgin2b 0x00000b48 +#define Ent_resume_msgin3a 0x00000c68 +#define Ent_resume_msgin3b 0x00000c78 +#define Ent_resume_pmm 0x00000070 +#define Ent_resume_rej_ident 0x00000ca8 +#define Ent_test1 0x00000d40 +#define Ent_wait_disc1 0x000009f8 +#define Ent_wait_disc2 0x00000b28 +#define Ent_wait_disc3 0x00000c58 +#define Ent_wait_disc_complete 0x000000c8 +static u32 LABELPATCHES[] __attribute((unused)) = { + 0x00000005, + 0x00000007, + 0x00000013, + 0x00000015, + 0x0000001d, + 0x0000001f, + 0x00000021, + 0x00000023, + 0x0000013b, + 0x00000241, + 0x00000243, + 0x0000024b, + 0x0000024d, + 0x0000024f, + 0x00000251, + 0x00000257, + 0x0000025f, + 0x00000265, + 0x00000273, + 0x00000277, + 0x0000027b, + 0x00000285, + 0x00000291, + 0x00000297, + 0x00000299, + 0x0000029b, + 0x0000029d, + 0x000002a3, + 0x000002ab, + 0x000002b1, + 0x000002bf, + 0x000002c3, + 0x000002c7, + 0x000002d1, + 0x000002dd, + 0x000002e3, + 0x000002e5, + 0x000002e7, + 0x000002e9, + 0x000002ef, + 0x000002f7, + 0x000002fd, + 0x0000030b, + 0x0000030f, + 0x00000313, + 0x0000031d, + 0x00000329, + 0x00000333, + 0x00000337, + 0x00000341, + 0x0000034d, +}; + +static struct { + u32 offset; + void *address; +} EXTERNAL_PATCHES[] __attribute((unused)) = { +}; + +static u32 INSTRUCTIONS __attribute((unused)) = 426; +static u32 PATCHES __attribute((unused)) = 51; +static u32 EXTERNAL_PATCHES_LEN __attribute((unused)) = 0; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.47/drivers/video/68328fb.c linux.2.5.47-ac4/drivers/video/68328fb.c --- linux.2.5.47/drivers/video/68328fb.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.47-ac4/drivers/video/68328fb.c 2002-10-31 15:05:24.000000000 +0000 @@ -0,0 +1,986 @@ +/* + * linux/arch/m68knommu/console/68328fb.c -- Low level implementation of the + * mc68328 LCD frame buffer device + * + * Copyright (C) 1998,1999 Kenneth Albanowski , + * The Silver Hammer Group, Ltd. + * + * + * This file is based on the Amiga CyberVision frame buffer device (Cyberfb.c): + * + * Copyright (C) 1996 Martin Apel + * Geert Uytterhoeven + * + * + * This file is based on the Amiga frame buffer device (amifb.c): + * + * Copyright (C) 1995 Geert Uytterhoeven + * + * + * History: + * - 17 Feb 98: Original version by Kenneth Albanowski + * + * + * 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. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include