diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/alpha/Kconfig linux.2.5.45-ac1/arch/alpha/Kconfig --- linux.2.5.45/arch/alpha/Kconfig 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.45-ac1/arch/alpha/Kconfig 2002-11-01 11:33:52.000000000 +0000 @@ -22,6 +22,14 @@ bool default y +config MMU + bool + default y + +config SWAP + bool + default y + config GENERIC_ISA_DMA bool default y diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/alpha/kernel/sys_titan.c linux.2.5.45-ac1/arch/alpha/kernel/sys_titan.c --- linux.2.5.45/arch/alpha/kernel/sys_titan.c 2002-10-31 14:57:28.000000000 +0000 +++ linux.2.5.45-ac1/arch/alpha/kernel/sys_titan.c 2002-10-31 15:05:54.000000000 +0000 @@ -306,10 +306,7 @@ { u8 irq; - pcibios_read_config_byte(dev->bus->number, - dev->devfn, - PCI_INTERRUPT_LINE, - &irq); + pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); /* is it routed through ISA? */ if ((irq & 0xF0) == 0xE0) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/arm/Kconfig linux.2.5.45-ac1/arch/arm/Kconfig --- linux.2.5.45/arch/arm/Kconfig 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.45-ac1/arch/arm/Kconfig 2002-11-01 11:35:03.000000000 +0000 @@ -42,6 +42,14 @@ (and especially the web page given there) before attempting to build an MCA bus kernel. +config MMU + bool + default y + +config SWAP + bool + default y + config UID16 bool default y diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/cris/Kconfig linux.2.5.45-ac1/arch/cris/Kconfig --- linux.2.5.45/arch/cris/Kconfig 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.45-ac1/arch/cris/Kconfig 2002-11-01 11:35:09.000000000 +0000 @@ -16,6 +16,14 @@ config RWSEM_XCHGADD_ALGORITHM bool +config MMU + bool + default y + +config SWAP + bool + default y + source "init/Kconfig" diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/i386/boot/compressed/head.S linux.2.5.45-ac1/arch/i386/boot/compressed/head.S --- linux.2.5.45/arch/i386/boot/compressed/head.S 2002-10-31 14:57:24.000000000 +0000 +++ linux.2.5.45-ac1/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.45/arch/i386/boot/compressed/misc.c linux.2.5.45-ac1/arch/i386/boot/compressed/misc.c --- linux.2.5.45/arch/i386/boot/compressed/misc.c 2002-10-31 14:57:24.000000000 +0000 +++ linux.2.5.45-ac1/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.45/arch/i386/boot/setup.S linux.2.5.45-ac1/arch/i386/boot/setup.S --- linux.2.5.45/arch/i386/boot/setup.S 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.45-ac1/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.45/arch/i386/boot98/bootsect.S linux.2.5.45-ac1/arch/i386/boot98/bootsect.S --- linux.2.5.45/arch/i386/boot98/bootsect.S 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/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.45/arch/i386/boot98/compressed/head.S linux.2.5.45-ac1/arch/i386/boot98/compressed/head.S --- linux.2.5.45/arch/i386/boot98/compressed/head.S 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/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.45/arch/i386/boot98/compressed/Makefile linux.2.5.45-ac1/arch/i386/boot98/compressed/Makefile --- linux.2.5.45/arch/i386/boot98/compressed/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/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.45/arch/i386/boot98/compressed/misc.c linux.2.5.45-ac1/arch/i386/boot98/compressed/misc.c --- linux.2.5.45/arch/i386/boot98/compressed/misc.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/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.45/arch/i386/boot98/compressed/vmlinux.scr linux.2.5.45-ac1/arch/i386/boot98/compressed/vmlinux.scr --- linux.2.5.45/arch/i386/boot98/compressed/vmlinux.scr 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/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.45/arch/i386/boot98/install.sh linux.2.5.45-ac1/arch/i386/boot98/install.sh --- linux.2.5.45/arch/i386/boot98/install.sh 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/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.45/arch/i386/boot98/Makefile linux.2.5.45-ac1/arch/i386/boot98/Makefile --- linux.2.5.45/arch/i386/boot98/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/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.45/arch/i386/boot98/setup.S linux.2.5.45-ac1/arch/i386/boot98/setup.S --- linux.2.5.45/arch/i386/boot98/setup.S 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/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.45/arch/i386/boot98/tools/build.c linux.2.5.45-ac1/arch/i386/boot98/tools/build.c --- linux.2.5.45/arch/i386/boot98/tools/build.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/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.45/arch/i386/boot98/video.S linux.2.5.45-ac1/arch/i386/boot98/video.S --- linux.2.5.45/arch/i386/boot98/video.S 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/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.45/arch/i386/Kconfig linux.2.5.45-ac1/arch/i386/Kconfig --- linux.2.5.45/arch/i386/Kconfig 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.45-ac1/arch/i386/Kconfig 2002-11-01 14:27:03.000000000 +0000 @@ -25,6 +25,15 @@ bool default y +config MMU + bool + default y + +config SWAP + bool + default y + + source "init/Kconfig" @@ -54,6 +63,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. @@ -118,6 +128,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 @@ -190,7 +207,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 @@ -207,7 +224,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 @@ -237,17 +254,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 @@ -270,9 +287,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 @@ -358,12 +382,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 @@ -422,6 +446,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--- @@ -453,7 +481,7 @@ config X86_MCE_P4THERMAL bool "check for P4 thermal throttling interrupt." - depends on X86_MCE && X86_UP_APIC + depends on X86_MCE && (X86_UP_APIC || SMP) help Enabling this feature will cause a message to be printed when the P4 enters thermal throttling. @@ -474,10 +502,10 @@ bool "/proc/sys/cpu/ interface (2.4.)" depends on CPU_FREQ ---help--- - This enables the /proc/sys/cpu/ sysctl interface for controlling - CPUFreq, as known from the 2.4.-kernel patches for CPUFreq. Note - that some drivers do not support this interface or offer less - functionality. + CPUFreq, as known from the 2.4.-kernel patches for CPUFreq. 2.5 + uses /proc/cpufreq instead. Please note that some drivers do not + work with the 2.4. /proc/sys/cpu sysctl interface, so if in doubt, + say N here. If you say N here, you'll be able to control CPUFreq using the new /proc/cpufreq interface. @@ -961,6 +989,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 +1652,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 +1709,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.45/arch/i386/kernel/bluesmoke.c linux.2.5.45-ac1/arch/i386/kernel/bluesmoke.c --- linux.2.5.45/arch/i386/kernel/bluesmoke.c 2002-10-31 14:57:24.000000000 +0000 +++ linux.2.5.45-ac1/arch/i386/kernel/bluesmoke.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,504 +0,0 @@ -/* - * arch/i386/kernel/bluesmoke.c - x86 Machine Check Exception Reporting - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#ifdef CONFIG_X86_MCE - -/* as supported by the P4/Xeon family */ -struct intel_mce_extended_msrs { - u32 eax; - u32 ebx; - u32 ecx; - u32 edx; - u32 esi; - u32 edi; - u32 ebp; - u32 esp; - u32 eflags; - u32 eip; - /* u32 *reserved[]; */ -}; - -static int mce_disabled __initdata = 0; - -static int mce_num_extended_msrs = 0; -static int banks; - - -#ifdef CONFIG_X86_MCE_P4THERMAL -/* - * P4/Xeon Thermal transition interrupt handler - */ - -static void intel_thermal_interrupt(struct pt_regs *regs) -{ - u32 l, h; - unsigned int cpu = smp_processor_id(); - - ack_APIC_irq(); - - rdmsr(MSR_IA32_THERM_STATUS, l, h); - if (l & 1) { - printk(KERN_EMERG "CPU#%d: Temperature above threshold\n", cpu); - printk(KERN_EMERG "CPU#%d: Running in modulated clock mode\n", cpu); - } else { - printk(KERN_INFO "CPU#%d: Temperature/speed normal\n", cpu); - } -} - -static void unexpected_thermal_interrupt(struct pt_regs *regs) -{ - printk(KERN_ERR "CPU#%d: Unexpected LVT TMR interrupt!\n", smp_processor_id()); -} - -/* - * Thermal interrupt handler for this CPU setup - */ - -static void (*vendor_thermal_interrupt)(struct pt_regs *regs) = unexpected_thermal_interrupt; - -asmlinkage void smp_thermal_interrupt(struct pt_regs regs) -{ - irq_enter(); - vendor_thermal_interrupt(®s); - irq_exit(); -} - -/* P4/Xeon Thermal regulation detect and init */ - -static void __init intel_init_thermal(struct cpuinfo_x86 *c) -{ - u32 l, h; - unsigned int cpu = smp_processor_id(); - - /* Thermal monitoring */ - if (!cpu_has(c, X86_FEATURE_ACPI)) - return; /* -ENODEV */ - - /* Clock modulation */ - if (!cpu_has(c, X86_FEATURE_ACC)) - return; /* -ENODEV */ - - /* first check if its enabled already, in which case there might - * be some SMM goo which handles it, so we can't even put a handler - * since it might be delivered via SMI already -zwanem. - */ - rdmsr(MSR_IA32_MISC_ENABLE, l, h); - h = apic_read(APIC_LVTTHMR); - if ((l & (1<<3)) && (h & APIC_DM_SMI)) { - printk(KERN_DEBUG "CPU#%d: Thermal monitoring handled by SMI\n", cpu); - return; /* -EBUSY */ - } - - /* check whether a vector already exists, temporarily masked? */ - if (h & APIC_VECTOR_MASK) { - printk(KERN_DEBUG "CPU#%d: Thermal LVT vector (%#x) already installed\n", - cpu, (h & APIC_VECTOR_MASK)); - return; /* -EBUSY */ - } - - /* The temperature transition interrupt handler setup */ - h = THERMAL_APIC_VECTOR; /* our delivery vector */ - h |= (APIC_DM_FIXED | APIC_LVT_MASKED); /* we'll mask till we're ready */ - apic_write_around(APIC_LVTTHMR, h); - - rdmsr(MSR_IA32_THERM_INTERRUPT, l, h); - wrmsr(MSR_IA32_THERM_INTERRUPT, l | 0x03 , h); - - /* ok we're good to go... */ - vendor_thermal_interrupt = intel_thermal_interrupt; - - rdmsr(MSR_IA32_MISC_ENABLE, l, h); - wrmsr(MSR_IA32_MISC_ENABLE, l | (1<<3), h); - - l = apic_read(APIC_LVTTHMR); - apic_write_around(APIC_LVTTHMR, l & ~APIC_LVT_MASKED); - printk(KERN_INFO "CPU#%d: Thermal monitoring enabled\n", cpu); - return; -} -#endif /* CONFIG_X86_MCE_P4THERMAL */ - - -/* P4/Xeon Extended MCE MSR retrieval, return 0 if unsupported */ - -static int inline intel_get_extended_msrs(struct intel_mce_extended_msrs *r) -{ - u32 h; - - if (mce_num_extended_msrs == 0) - goto done; - - rdmsr(MSR_IA32_MCG_EAX, r->eax, h); - rdmsr(MSR_IA32_MCG_EBX, r->ebx, h); - rdmsr(MSR_IA32_MCG_ECX, r->ecx, h); - rdmsr(MSR_IA32_MCG_EDX, r->edx, h); - rdmsr(MSR_IA32_MCG_ESI, r->esi, h); - rdmsr(MSR_IA32_MCG_EDI, r->edi, h); - rdmsr(MSR_IA32_MCG_EBP, r->ebp, h); - rdmsr(MSR_IA32_MCG_ESP, r->esp, h); - rdmsr(MSR_IA32_MCG_EFLAGS, r->eflags, h); - rdmsr(MSR_IA32_MCG_EIP, r->eip, h); - - /* can we rely on kmalloc to do a dynamic - * allocation for the reserved registers? - */ -done: - return mce_num_extended_msrs; -} - -/* - * Machine Check Handler For PII/PIII - */ - -static void intel_machine_check(struct pt_regs * regs, long error_code) -{ - int recover=1; - u32 alow, ahigh, high, low; - u32 mcgstl, mcgsth; - int i; - struct intel_mce_extended_msrs dbg; - - rdmsr(MSR_IA32_MCG_STATUS, mcgstl, mcgsth); - if(mcgstl&(1<<0)) /* Recoverable ? */ - recover=0; - - printk(KERN_EMERG "CPU %d: Machine Check Exception: %08x%08x\n", smp_processor_id(), mcgsth, mcgstl); - - if (intel_get_extended_msrs(&dbg)) { - printk(KERN_DEBUG "CPU %d: EIP: %08x EFLAGS: %08x\n", - smp_processor_id(), dbg.eip, dbg.eflags); - printk(KERN_DEBUG "\teax: %08x ebx: %08x ecx: %08x edx: %08x\n", - dbg.eax, dbg.ebx, dbg.ecx, dbg.edx); - printk(KERN_DEBUG "\tesi: %08x edi: %08x ebp: %08x esp: %08x\n", - dbg.esi, dbg.edi, dbg.ebp, dbg.esp); - } - - for (i=0;i 1) - schedule_work(&mce_work); -#else - mce_checkregs(NULL); -#endif - mce_timer.expires = jiffies + MCE_RATE; - add_timer (&mce_timer); -} -#endif - - -/* - * Set up machine check reporting for processors with Intel style MCE - */ - -static void __init intel_mcheck_init(struct cpuinfo_x86 *c) -{ - u32 l, h; - int i; - static int done; - - /* - * Check for MCE support - */ - - if( !cpu_has(c, X86_FEATURE_MCE) ) - return; - - /* - * Pentium machine check - */ - - if(c->x86 == 5) - { - /* Default P5 to off as its often misconnected */ - if(mce_disabled != -1) - return; - machine_check_vector = pentium_machine_check; - wmb(); - /* Read registers before enabling */ - rdmsr(MSR_IA32_P5_MC_ADDR, l, h); - rdmsr(MSR_IA32_P5_MC_TYPE, l, h); - if(done==0) - printk(KERN_INFO "Intel old style machine check architecture supported.\n"); - /* Enable MCE */ - set_in_cr4(X86_CR4_MCE); - printk(KERN_INFO "Intel old style machine check reporting enabled on CPU#%d.\n", smp_processor_id()); - return; - } - - - /* - * Check for PPro style MCA - */ - - if( !cpu_has(c, X86_FEATURE_MCA) ) - return; - - /* Ok machine check is available */ - - machine_check_vector = intel_machine_check; - wmb(); - - if(done==0) - printk(KERN_INFO "Intel machine check architecture supported.\n"); - rdmsr(MSR_IA32_MCG_CAP, l, h); - if(l&(1<<8)) /* Control register present ? */ - wrmsr(MSR_IA32_MCG_CTL, 0xffffffff, 0xffffffff); - banks = l&0xff; - - /* Don't enable bank 0 on intel P6 cores, it goes bang quickly. */ - if (c->x86_vendor == X86_VENDOR_INTEL && c->x86 == 6) { - for(i=1; ix86_vendor == X86_VENDOR_INTEL && c->x86 == 15) { - /* Check for P4/Xeon extended MCE MSRs */ - rdmsr(MSR_IA32_MCG_CAP, l, h); - if (l & (1<<9)) {/* MCG_EXT_P */ - mce_num_extended_msrs = (l >> 16) & 0xff; - printk(KERN_INFO "CPU#%d: Intel P4/Xeon Extended MCE MSRs (%d) available\n", - smp_processor_id(), mce_num_extended_msrs); - } - -#ifdef CONFIG_X86_MCE_P4THERMAL - /* Check for P4/Xeon Thermal monitor */ - intel_init_thermal(c); -#endif - } - - done=1; -} - -/* - * Set up machine check reporting on the Winchip C6 series - */ - -static void __init winchip_mcheck_init(struct cpuinfo_x86 *c) -{ - u32 lo, hi; - /* Not supported on C3 */ - if(c->x86 != 5) - return; - /* Winchip C6 */ - machine_check_vector = winchip_machine_check; - wmb(); - rdmsr(MSR_IDT_FCR1, lo, hi); - lo|= (1<<2); /* Enable EIERRINT (int 18 MCE) */ - lo&= ~(1<<4); /* Enable MCE */ - wrmsr(MSR_IDT_FCR1, lo, hi); - set_in_cr4(X86_CR4_MCE); - printk(KERN_INFO "Winchip machine check reporting enabled on CPU#%d.\n", smp_processor_id()); -} - - -/* - * This has to be run for each processor - */ - -void __init mcheck_init(struct cpuinfo_x86 *c) -{ - - if(mce_disabled==1) - return; - - switch(c->x86_vendor) - { - case X86_VENDOR_AMD: - /* AMD K7 machine check is Intel like */ - if(c->x86 == 6 || c->x86 == 15) { - intel_mcheck_init(c); -#ifdef CONFIG_X86_MCE_NONFATAL - if (timerset == 0) { - /* Set the timer to check for non-fatal - errors every MCE_RATE seconds */ - init_timer (&mce_timer); - mce_timer.expires = jiffies + MCE_RATE; - mce_timer.data = 0; - mce_timer.function = &mce_timerfunc; - add_timer (&mce_timer); - timerset = 1; - printk(KERN_INFO "Machine check exception polling timer started.\n"); - } -#endif - } - break; - - case X86_VENDOR_INTEL: - intel_mcheck_init(c); - break; - - case X86_VENDOR_CENTAUR: - winchip_mcheck_init(c); - break; - - default: - break; - } -} - -static int __init mcheck_disable(char *str) -{ - mce_disabled = 1; - return 0; -} - -static int __init mcheck_enable(char *str) -{ - mce_disabled = -1; - return 0; -} - -__setup("nomce", mcheck_disable); -__setup("mce", mcheck_enable); - -#else -asmlinkage void do_machine_check(struct pt_regs * regs, long error_code) {} -asmlinkage void smp_thermal_interrupt(struct pt_regs regs) {} -void __init mcheck_init(struct cpuinfo_x86 *c) {} -#endif diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/i386/kernel/cpu/common.c linux.2.5.45-ac1/arch/i386/kernel/cpu/common.c --- linux.2.5.45/arch/i386/kernel/cpu/common.c 2002-10-31 14:57:23.000000000 +0000 +++ linux.2.5.45-ac1/arch/i386/kernel/cpu/common.c 2002-10-31 15:05:48.000000000 +0000 @@ -315,9 +315,6 @@ clear_bit(X86_FEATURE_XMM, c->x86_capability); } - /* Init Machine Check Exception if available. */ - mcheck_init(c); - /* If the model name is still unset, do table lookup. */ if ( !c->x86_model_id[0] ) { char *p; @@ -355,17 +352,11 @@ boot_cpu_data.x86_capability[1], boot_cpu_data.x86_capability[2], boot_cpu_data.x86_capability[3]); -} -/* - * 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); + + /* Init Machine Check Exception if available. */ +#ifdef CONFIG_X86_MCE + mcheck_init(c); +#endif } void __init print_cpu_info(struct cpuinfo_x86 *c) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c linux.2.5.45-ac1/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c --- linux.2.5.45/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c 2002-10-31 14:57:23.000000000 +0000 +++ linux.2.5.45-ac1/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c 2002-10-31 15:05:48.000000000 +0000 @@ -50,7 +50,6 @@ MODULE_PARM(stock_freq, "i"); static struct cpufreq_driver *cpufreq_p4_driver; -static unsigned int cpufreq_p4_old_state = 0; static int cpufreq_p4_setdc(unsigned int cpu, unsigned int newstate) @@ -58,24 +57,50 @@ u32 l, h; unsigned long cpus_allowed; struct cpufreq_freqs freqs; + int hyperthreading; + if (!cpu_online(cpu) || (newstate > DC_DISABLE) || (newstate == DC_RESV)) return -EINVAL; - cpu = cpu >> 1; /* physical CPU #nr */ + + /* switch to physical CPU where state is to be changed*/ + cpus_allowed = current->cpus_allowed; + + /* hyperthreading? */ +#ifdef CONFIG_SMP + hyperthreading = ((cpu_has_ht) && (smp_num_siblings == 2)); +#else + hyperthreading = 0; +#endif + if (hyperthreading) { + unsigned int phys_cpu = cpu / 2; + set_cpus_allowed(current, 3 << (phys_cpu)); + BUG_ON((cpu & ~1) != (smp_processor_id() & ~1)); + cpu = phys_cpu * 2; + } else { + set_cpus_allowed(current, 1 << cpu); + BUG_ON(cpu != smp_processor_id()); + } + /* get current state */ + rdmsr(MSR_IA32_THERM_CONTROL, l, h); + l = l >> 1; + l &= 0x7; + + if (l == newstate) { + set_cpus_allowed(current, cpus_allowed); + return 0; + } /* notifiers */ - freqs.old = stock_freq * cpufreq_p4_old_state / 8; + freqs.old = stock_freq * l / 8; freqs.new = stock_freq * newstate / 8; - freqs.cpu = 2*cpu; - cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); - freqs.cpu++; + freqs.cpu = cpu; cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); - - /* switch to physical CPU where state is to be changed*/ - cpus_allowed = current->cpus_allowed; - set_cpus_allowed(current, 3 << (2 * cpu)); - BUG_ON(cpu != (smp_processor_id() >> 1)); + if (hyperthreading) { + freqs.cpu++; + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + } rdmsr(MSR_IA32_THERM_STATUS, l, h); if (l & 0x01) @@ -86,10 +111,10 @@ rdmsr(MSR_IA32_THERM_CONTROL, l, h); if (newstate == DC_DISABLE) { - printk(KERN_INFO PFX "CPU#%d,%d disabling modulation\n", cpu, (cpu + 1)); + printk(KERN_INFO PFX "CPU#%d disabling modulation\n", cpu); wrmsr(MSR_IA32_THERM_CONTROL, l & ~(1<<4), h); } else { - printk(KERN_INFO PFX "CPU#%d,%d setting duty cycle to %d%%\n", cpu, (cpu + 1), ((125 * newstate) / 10)); + printk(KERN_INFO PFX "CPU#%d setting duty cycle to %d%%\n", cpu, ((125 * newstate) / 10)); /* bits 63 - 5 : reserved * bit 4 : enable/disable * bits 3-1 : duty cycle @@ -104,9 +129,10 @@ /* notifiers */ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); - freqs.cpu--; - cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); - cpufreq_p4_old_state = newstate; + if (hyperthreading) { + freqs.cpu--; + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + } return 0; } @@ -143,9 +169,9 @@ /* if (number_states == 1) */ { if (policy->cpu == CPUFREQ_ALL_CPUS) { - for (i=0; i<(NR_CPUS/2); i++) - if (cpu_online(2*i)) - cpufreq_p4_setdc((2*i), newstate); + for (i=0; icpu, newstate); } @@ -235,7 +261,6 @@ for (i=0;icpu_cur_freq[i] = stock_freq; #endif - cpufreq_p4_old_state = DC_DISABLE; driver->verify = &cpufreq_p4_verify; driver->setpolicy = &cpufreq_p4_setpolicy; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/i386/kernel/cpu/cpufreq/speedstep.c linux.2.5.45-ac1/arch/i386/kernel/cpu/cpufreq/speedstep.c --- linux.2.5.45/arch/i386/kernel/cpu/cpufreq/speedstep.c 2002-10-31 14:57:23.000000000 +0000 +++ linux.2.5.45-ac1/arch/i386/kernel/cpu/cpufreq/speedstep.c 2002-10-31 15:05:48.000000000 +0000 @@ -1,5 +1,5 @@ /* - * $Id: speedstep.c,v 1.53 2002/09/29 23:43:11 db Exp $ + * $Id: speedstep.c,v 1.54 2002/10/10 15:52:55 db Exp $ * * (C) 2001 Dave Jones, Arjan van de ven. * (C) 2002 Dominik Brodowski @@ -42,7 +42,7 @@ #define SPEEDSTEP_CHIPSET_ICH2M 0x00000002 #define SPEEDSTEP_CHIPSET_ICH3M 0x00000003 - +#define SPEEDSTEP_CHIPSET_VIA8235 0x00000004 /* speedstep_processor */ @@ -72,7 +72,7 @@ #ifdef SPEEDSTEP_DEBUG #define dprintk(msg...) printk(msg) #else -#define dprintk(msg...) do { } while(0); +#define dprintk(msg...) do { } while(0) #endif @@ -120,6 +120,22 @@ *state = value & 0x01; return 0; + /* VIA seems to be like Intel but at a different base */ + case SPEEDSTEP_CHIPSET_VIA8235: + /* get PMBASE */ + pci_read_config_dword(speedstep_chipset_dev, 0x8B, &pmbase); + if(!(pmbase & 0x01)) + return -EIO; + pmbase &= 0x0000FFFE; + + /* read state */ + value = inb(pmbase + 0x5C); + + dprintk(KERN_DEBUG "cpufreq: read at pmbase 0x%x + 0x5C returned 0x%x\n", pmbase, value); + + /* Bit 1 seems to be doing stuff to but I don't know what */ + *state = value & 0x01; + return 0; } printk (KERN_ERR "cpufreq: setting CPU frequency on this chipset unsupported.\n"); @@ -189,6 +205,9 @@ dprintk(KERN_DEBUG "cpufreq: writing 0x%x to pmbase 0x%x + 0x50\n", value, pmbase); + /* FIXME: surely we need to kill the northbridge during + this sequence to avoid corruption ? */ + /* Disable bus master arbitration */ pm2_blk = inb(pmbase + 0x20); pm2_blk |= 0x01; @@ -215,6 +234,56 @@ printk (KERN_ERR "cpufreq: change failed - I/O error\n"); } break; + + case SPEEDSTEP_CHIPSET_VIA8235: + /* get PMBASE */ + pci_read_config_dword(speedstep_chipset_dev, 0x8B, &pmbase); + if (!(pmbase & 0x01)) + { + printk(KERN_ERR "cpufreq: could not find speedstep register\n"); + return; + } + + pmbase &= 0x0000FFFE; + if (!pmbase) { + printk(KERN_ERR "cpufreq: could not find speedstep register\n"); + return; + } + + /* Disable IRQs */ + local_irq_save(flags); + + /* read state */ + value = inb(pmbase + 0x5C); + + dprintk(KERN_DEBUG "cpufreq: read at pmbase 0x%x + 0x5C returned 0x%x\n", pmbase, value); + + /* write new state */ + value &= 0xFE; + value |= state; + + dprintk(KERN_DEBUG "cpufreq: writing 0x%x to pmbase 0x%x + 0x5C\n", value, pmbase); + + /* FIXME: do we need to do bus master stuff like on intel ? */ + /* Actual transition */ + outb(value, (pmbase + 0x5C)); + + /* check if transition was sucessful */ + value = inb(pmbase + 0x5C); + + /* Enable IRQs */ + local_irq_restore(flags); + + dprintk(KERN_DEBUG "cpufreq: read at pmbase 0x%x + 0x5C returned 0x%x\n", pmbase, value); + + if (state == (value & 0x1)) { + dprintk (KERN_INFO "cpufreq: change to %u MHz succeded\n", (freqs.new / 1000)); + } else { + printk (KERN_ERR "cpufreq: change failed - I/O error\n"); + } + break; + + default: printk (KERN_ERR "cpufreq: setting CPU frequency on this chipset unsupported.\n"); } @@ -254,8 +323,28 @@ return 0; } + case SPEEDSTEP_CHIPSET_VIA8235: + { + u16 value; + u8 byte; + + pci_read_config_word(speedstep_chipset_dev, + 0x00E5, &value); + value &= ~(1<<3); /* What is bit 4 about ? */ + + pci_write_config_word(speedstep_chipset_dev, + 0x00E5, value); + + /* Otherwise it seems the pmbase doesnt exist ? */ + pci_read_config_byte(speedstep_chipset_dev, + 0x0081, &byte); + byte |= 1<<7; + pci_write_config_byte(speedstep_chipset_dev, + 0x0081, byte); + return 0; } - + } + printk (KERN_ERR "cpufreq: SpeedStep (TM) on this chipset unsupported.\n"); return -EINVAL; } @@ -264,13 +353,29 @@ /** * speedstep_detect_chipset - detect the Southbridge which contains SpeedStep logic * - * Detects PIIX4, ICH2-M and ICH3-M so far. The pci_dev points to + * Detects 8235, PIIX4, ICH2-M and ICH3-M so far. The pci_dev points to * the LPC bridge / PM module which contains all power-management * functions. Returns the SPEEDSTEP_CHIPSET_-number for the detected * chipset, or zero on failure. */ static unsigned int speedstep_detect_chipset (void) { +#ifdef TESTING_VIA8235 + /* + * The VIA 8601 (Apollo ProMedia) is also known to + * have speedstep but this code hasn't been tried + * to see if it works there also. + * See reports on Compaq Armada 110 slow boots + */ + speedstep_chipset_dev = pci_find_subsys(PCI_VENDOR_ID_VIA, + PCI_DEVICE_ID_VIA_8235, + PCI_ANY_ID, + PCI_ANY_ID, + NULL); + if (speedstep_chipset_dev) + return SPEEDSTEP_CHIPSET_VIA8235; +#endif + speedstep_chipset_dev = pci_find_subsys(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, PCI_ANY_ID, @@ -490,14 +595,14 @@ /* platform ID seems to be 0x00140000 */ rdmsr(MSR_IA32_PLATFORM_ID, msr_lo, msr_hi); dprintk(KERN_DEBUG "cpufreq: Coppermine: MSR_IA32_PLATFORM ID is 0x%x, 0x%x\n", msr_lo, msr_hi); - msr_hi = msr_lo & 0x001c0000; - if (msr_hi != 0x00140000) + msr_lo = msr_hi & 0x001c0000; + if (msr_lo != 0x00140000) return 0; /* and these bits seem to be either 00_b, 01_b or * 10_b but never 11_b */ - msr_lo &= 0x00030000; - if (msr_lo == 0x0030000) + msr_hi &= 0x00030000; + if (msr_hi == 0x0030000) return 0; /* let's hope this is correct... */ @@ -644,11 +749,11 @@ speedstep_processor = speedstep_detect_processor(); if ((!speedstep_chipset) || (!speedstep_processor)) { - dprintk(KERN_INFO "cpufreq: Intel(R) SpeedStep(TM) for this %s not (yet) available.\n", speedstep_processor ? "chipset" : "processor"); + printk(KERN_INFO "cpufreq: Intel(R) SpeedStep(TM) for this %s not (yet) available.\n", speedstep_processor ? "chipset" : "processor"); return -ENODEV; } - dprintk(KERN_INFO "cpufreq: Intel(R) SpeedStep(TM) support $Revision: 1.53 $\n"); + dprintk(KERN_INFO "cpufreq: Intel(R) SpeedStep(TM) support $Revision: 1.54 $\n"); dprintk(KERN_DEBUG "cpufreq: chipset 0x%x - processor 0x%x\n", speedstep_chipset, speedstep_processor); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/i386/kernel/cpu/cyrix.c linux.2.5.45-ac1/arch/i386/kernel/cpu/cyrix.c --- linux.2.5.45/arch/i386/kernel/cpu/cyrix.c 2002-10-31 14:57:23.000000000 +0000 +++ linux.2.5.45-ac1/arch/i386/kernel/cpu/cyrix.c 2002-10-31 15:05:48.000000000 +0000 @@ -5,6 +5,7 @@ #include #include #include +#include #include "cpu.h" @@ -170,7 +171,7 @@ c->coma_bug = 1; break; - case 4: /* MediaGX/GXm */ + case 4: /* MediaGX/GXm or Geode GXM/GXLV/GX1 */ #ifdef CONFIG_PCI /* It isn't really a PCI quirk directly, but the cure is the same. The MediaGX has deep magic SMM stuff that handles the @@ -188,29 +189,26 @@ isa_dma_bridge_buggy = 2; #endif c->x86_cache_size=16; /* Yep 16K integrated cache thats it */ + + /* + * The 5510/5520 companion chips have a funky PIT. + */ + if (pci_find_device(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5510, NULL) || + pci_find_device(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5520, NULL)) + pit_latch_buggy = 1; /* GXm supports extended cpuid levels 'ala' AMD */ if (c->cpuid_level == 2) { - /* Enable Natsemi MMX extensions */ - setCx86(CX86_CCR7, getCx86(CX86_CCR7) | 1); + /* Enable cxMMX extensions (GX1 Datasheet 54) */ + setCx86(CX86_CCR7, getCx86(CX86_CCR7)|1); get_model_name(c); /* get CPU marketing name */ - /* - * The 5510/5520 companion chips have a funky PIT - * that breaks the TSC synchronizing, so turn it off - */ - if (pci_find_device(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5510, NULL) || - pci_find_device(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5520, NULL)) - clear_bit(X86_FEATURE_TSC, c->x86_capability); return; } else { /* MediaGX */ Cx86_cb[2] = (dir0_lsn & 1) ? '3' : '4'; p = Cx86_cb+2; c->x86_model = (dir1 & 0x20) ? 1 : 2; -#ifndef CONFIG_CS5520 - clear_bit(X86_FEATURE_TSC, c->x86_capability); -#endif } break; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/i386/kernel/cpu/Makefile linux.2.5.45-ac1/arch/i386/kernel/cpu/Makefile --- linux.2.5.45/arch/i386/kernel/cpu/Makefile 2002-10-31 14:57:23.000000000 +0000 +++ linux.2.5.45-ac1/arch/i386/kernel/cpu/Makefile 2002-10-31 15:05:48.000000000 +0000 @@ -13,7 +13,10 @@ obj-y += nexgen.o obj-y += umc.o +obj-$(CONFIG_X86_MCE) += mcheck/ + obj-$(CONFIG_MTRR) += mtrr/ obj-$(CONFIG_CPU_FREQ) += cpufreq/ + include $(TOPDIR)/Rules.make diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/i386/kernel/cpu/mcheck/k7.c linux.2.5.45-ac1/arch/i386/kernel/cpu/mcheck/k7.c --- linux.2.5.45/arch/i386/kernel/cpu/mcheck/k7.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/i386/kernel/cpu/mcheck/k7.c 2002-10-31 15:05:48.000000000 +0000 @@ -0,0 +1,159 @@ +/* + * Athlon specific Machine Check Exception Reporting + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "mce.h" + +static int banks; + +/* Machine Check Handler For AMD Athlon/Duron */ +static void k7_machine_check(struct pt_regs * regs, long error_code) +{ + int recover=1; + u32 alow, ahigh, high, low; + u32 mcgstl, mcgsth; + int i; + + rdmsr(MSR_IA32_MCG_STATUS, mcgstl, mcgsth); + if(mcgstl&(1<<0)) /* Recoverable ? */ + recover=0; + + printk(KERN_EMERG "CPU %d: Machine Check Exception: %08x%08x\n", smp_processor_id(), mcgsth, mcgstl); + + for (i=0;i 1) + schedule_work(&mce_work); +#else + mce_checkregs(NULL); +#endif /* SMP */ + mce_timer.expires = jiffies + MCE_RATE; + add_timer (&mce_timer); +} +#endif /* NON_FATAL */ + + +/* AMD K7 machine check is Intel like */ +void __init amd_mcheck_init(struct cpuinfo_x86 *c) +{ + u32 l, h; + int i; + + machine_check_vector = k7_machine_check; + wmb(); + + printk(KERN_INFO "Intel machine check architecture supported.\n"); + rdmsr(MSR_IA32_MCG_CAP, l, h); + if(l&(1<<8)) /* Control register present ? */ + wrmsr(MSR_IA32_MCG_CTL, 0xffffffff, 0xffffffff); + banks = l&0xff; + + for(i=0; i +#include +#include +#include +#include +#include +#include +#include + +#include "mce.h" + +int mce_disabled __initdata = 0; + +/* Handle unconfigured int18 (should never happen) */ +static void unexpected_machine_check(struct pt_regs * regs, long error_code) +{ + printk(KERN_ERR "CPU#%d: Unexpected int18 (Machine Check).\n", smp_processor_id()); +} + +/* Call the installed machine check handler for this CPU setup. */ +void (*machine_check_vector)(struct pt_regs *, long error_code) = unexpected_machine_check; + +asmlinkage void do_machine_check(struct pt_regs * regs, long error_code) +{ + machine_check_vector(regs, error_code); +} + +/* This has to be run for each processor */ +void __init mcheck_init(struct cpuinfo_x86 *c) +{ + if(mce_disabled==1) + return; + + switch(c->x86_vendor) { + case X86_VENDOR_AMD: + if (c->x86==6 || c->x86==15) + amd_mcheck_init(c); + break; + + case X86_VENDOR_INTEL: + if (c->x86==5) + intel_p5_mcheck_init(c); + if (c->x86==6) + intel_p6_mcheck_init(c); + if (c->x86==15) + intel_p4_mcheck_init(c); + break; + + case X86_VENDOR_CENTAUR: + if (c->x86==5) + winchip_mcheck_init(c); + break; + + default: + break; + } +} + +static int __init mcheck_disable(char *str) +{ + mce_disabled = 1; + return 0; +} + +static int __init mcheck_enable(char *str) +{ + mce_disabled = -1; + return 0; +} + +__setup("nomce", mcheck_disable); +__setup("mce", mcheck_enable); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/i386/kernel/cpu/mcheck/mce.h linux.2.5.45-ac1/arch/i386/kernel/cpu/mcheck/mce.h --- linux.2.5.45/arch/i386/kernel/cpu/mcheck/mce.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/i386/kernel/cpu/mcheck/mce.h 2002-10-31 15:05:48.000000000 +0000 @@ -0,0 +1,12 @@ +#include + +void amd_mcheck_init(struct cpuinfo_x86 *c); +void intel_p4_mcheck_init(struct cpuinfo_x86 *c); +void intel_p5_mcheck_init(struct cpuinfo_x86 *c); +void intel_p6_mcheck_init(struct cpuinfo_x86 *c); +void winchip_mcheck_init(struct cpuinfo_x86 *c); + +/* Call the installed machine check handler for this CPU setup. */ +extern void (*machine_check_vector)(struct pt_regs *, long error_code); + +extern int mce_disabled __initdata; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/i386/kernel/cpu/mcheck/p4.c linux.2.5.45-ac1/arch/i386/kernel/cpu/mcheck/p4.c --- linux.2.5.45/arch/i386/kernel/cpu/mcheck/p4.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/i386/kernel/cpu/mcheck/p4.c 2002-10-31 15:05:48.000000000 +0000 @@ -0,0 +1,244 @@ +/* + * P4 specific Machine Check Exception Reporting + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "mce.h" + +/* as supported by the P4/Xeon family */ +struct intel_mce_extended_msrs { + u32 eax; + u32 ebx; + u32 ecx; + u32 edx; + u32 esi; + u32 edi; + u32 ebp; + u32 esp; + u32 eflags; + u32 eip; + /* u32 *reserved[]; */ +}; + +static int mce_num_extended_msrs = 0; +static int banks; + + +#ifdef CONFIG_X86_MCE_P4THERMAL +static void unexpected_thermal_interrupt(struct pt_regs *regs) +{ + printk(KERN_ERR "CPU#%d: Unexpected LVT TMR interrupt!\n", smp_processor_id()); +} + +/* P4/Xeon Thermal transition interrupt handler */ +static void intel_thermal_interrupt(struct pt_regs *regs) +{ + u32 l, h; + unsigned int cpu = smp_processor_id(); + + ack_APIC_irq(); + + rdmsr(MSR_IA32_THERM_STATUS, l, h); + if (l & 1) { + printk(KERN_EMERG "CPU#%d: Temperature above threshold\n", cpu); + printk(KERN_EMERG "CPU#%d: Running in modulated clock mode\n", cpu); + } else { + printk(KERN_INFO "CPU#%d: Temperature/speed normal\n", cpu); + } +} + +/* Thermal interrupt handler for this CPU setup */ +static void (*vendor_thermal_interrupt)(struct pt_regs *regs) = unexpected_thermal_interrupt; + +asmlinkage void smp_thermal_interrupt(struct pt_regs regs) +{ + irq_enter(); + vendor_thermal_interrupt(®s); + irq_exit(); +} + +/* P4/Xeon Thermal regulation detect and init */ +static void __init intel_init_thermal(struct cpuinfo_x86 *c) +{ + u32 l, h; + unsigned int cpu = smp_processor_id(); + + /* Thermal monitoring */ + if (!cpu_has(c, X86_FEATURE_ACPI)) + return; /* -ENODEV */ + + /* Clock modulation */ + if (!cpu_has(c, X86_FEATURE_ACC)) + return; /* -ENODEV */ + + /* first check if its enabled already, in which case there might + * be some SMM goo which handles it, so we can't even put a handler + * since it might be delivered via SMI already -zwanem. + */ + rdmsr(MSR_IA32_MISC_ENABLE, l, h); + h = apic_read(APIC_LVTTHMR); + if ((l & (1<<3)) && (h & APIC_DM_SMI)) { + printk(KERN_DEBUG "CPU#%d: Thermal monitoring handled by SMI\n", cpu); + return; /* -EBUSY */ + } + + /* check whether a vector already exists, temporarily masked? */ + if (h & APIC_VECTOR_MASK) { + printk(KERN_DEBUG "CPU#%d: Thermal LVT vector (%#x) already installed\n", + cpu, (h & APIC_VECTOR_MASK)); + return; /* -EBUSY */ + } + + /* The temperature transition interrupt handler setup */ + h = THERMAL_APIC_VECTOR; /* our delivery vector */ + h |= (APIC_DM_FIXED | APIC_LVT_MASKED); /* we'll mask till we're ready */ + apic_write_around(APIC_LVTTHMR, h); + + rdmsr(MSR_IA32_THERM_INTERRUPT, l, h); + wrmsr(MSR_IA32_THERM_INTERRUPT, l | 0x03 , h); + + /* ok we're good to go... */ + vendor_thermal_interrupt = intel_thermal_interrupt; + + rdmsr(MSR_IA32_MISC_ENABLE, l, h); + wrmsr(MSR_IA32_MISC_ENABLE, l | (1<<3), h); + + l = apic_read(APIC_LVTTHMR); + apic_write_around(APIC_LVTTHMR, l & ~APIC_LVT_MASKED); + printk(KERN_INFO "CPU#%d: Thermal monitoring enabled\n", cpu); + return; +} +#endif /* CONFIG_X86_MCE_P4THERMAL */ + + +/* P4/Xeon Extended MCE MSR retrieval, return 0 if unsupported */ +static int inline intel_get_extended_msrs(struct intel_mce_extended_msrs *r) +{ + u32 h; + + if (mce_num_extended_msrs == 0) + goto done; + + rdmsr(MSR_IA32_MCG_EAX, r->eax, h); + rdmsr(MSR_IA32_MCG_EBX, r->ebx, h); + rdmsr(MSR_IA32_MCG_ECX, r->ecx, h); + rdmsr(MSR_IA32_MCG_EDX, r->edx, h); + rdmsr(MSR_IA32_MCG_ESI, r->esi, h); + rdmsr(MSR_IA32_MCG_EDI, r->edi, h); + rdmsr(MSR_IA32_MCG_EBP, r->ebp, h); + rdmsr(MSR_IA32_MCG_ESP, r->esp, h); + rdmsr(MSR_IA32_MCG_EFLAGS, r->eflags, h); + rdmsr(MSR_IA32_MCG_EIP, r->eip, h); + + /* can we rely on kmalloc to do a dynamic + * allocation for the reserved registers? + */ +done: + return mce_num_extended_msrs; +} + +static void intel_machine_check(struct pt_regs * regs, long error_code) +{ + int recover=1; + u32 alow, ahigh, high, low; + u32 mcgstl, mcgsth; + int i; + struct intel_mce_extended_msrs dbg; + + rdmsr(MSR_IA32_MCG_STATUS, mcgstl, mcgsth); + if(mcgstl&(1<<0)) /* Recoverable ? */ + recover=0; + + printk(KERN_EMERG "CPU %d: Machine Check Exception: %08x%08x\n", smp_processor_id(), mcgsth, mcgstl); + + if (intel_get_extended_msrs(&dbg)) { + printk(KERN_DEBUG "CPU %d: EIP: %08x EFLAGS: %08x\n", + smp_processor_id(), dbg.eip, dbg.eflags); + printk(KERN_DEBUG "\teax: %08x ebx: %08x ecx: %08x edx: %08x\n", + dbg.eax, dbg.ebx, dbg.ecx, dbg.edx); + printk(KERN_DEBUG "\tesi: %08x edi: %08x ebp: %08x esp: %08x\n", + dbg.esi, dbg.edi, dbg.ebp, dbg.esp); + } + + for (i=0;i> 16) & 0xff; + printk(KERN_INFO "CPU#%d: Intel P4/Xeon Extended MCE MSRs (%d) available\n", + smp_processor_id(), mce_num_extended_msrs); + +#ifdef CONFIG_X86_MCE_P4THERMAL + /* Check for P4/Xeon Thermal monitor */ + intel_init_thermal(c); +#endif + } +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/i386/kernel/cpu/mcheck/p5.c linux.2.5.45-ac1/arch/i386/kernel/cpu/mcheck/p5.c --- linux.2.5.45/arch/i386/kernel/cpu/mcheck/p5.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/i386/kernel/cpu/mcheck/p5.c 2002-10-31 15:05:48.000000000 +0000 @@ -0,0 +1,52 @@ +/* + * P5 specific Machine Check Exception Reporting + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "mce.h" + +/* Machine check handler for Pentium class Intel */ +static void pentium_machine_check(struct pt_regs * regs, long error_code) +{ + u32 loaddr, hi, lotype; + rdmsr(MSR_IA32_P5_MC_ADDR, loaddr, hi); + rdmsr(MSR_IA32_P5_MC_TYPE, lotype, hi); + printk(KERN_EMERG "CPU#%d: Machine Check Exception: 0x%8X (type 0x%8X).\n", smp_processor_id(), loaddr, lotype); + if(lotype&(1<<5)) + printk(KERN_EMERG "CPU#%d: Possible thermal failure (CPU on fire ?).\n", smp_processor_id()); +} + +/* Set up machine check reporting for processors with Intel style MCE */ +void __init intel_p5_mcheck_init(struct cpuinfo_x86 *c) +{ + u32 l, h; + + /*Check for MCE support */ + if( !cpu_has(c, X86_FEATURE_MCE) ) + return; + + /* Default P5 to off as its often misconnected */ + if(mce_disabled != -1) + return; + machine_check_vector = pentium_machine_check; + wmb(); + + /* Read registers before enabling */ + rdmsr(MSR_IA32_P5_MC_ADDR, l, h); + rdmsr(MSR_IA32_P5_MC_TYPE, l, h); + printk(KERN_INFO "Intel old style machine check architecture supported.\n"); + + /* Enable MCE */ + set_in_cr4(X86_CR4_MCE); + printk(KERN_INFO "Intel old style machine check reporting enabled on CPU#%d.\n", smp_processor_id()); +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/i386/kernel/cpu/mcheck/p6.c linux.2.5.45-ac1/arch/i386/kernel/cpu/mcheck/p6.c --- linux.2.5.45/arch/i386/kernel/cpu/mcheck/p6.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/i386/kernel/cpu/mcheck/p6.c 2002-10-31 15:05:48.000000000 +0000 @@ -0,0 +1,101 @@ +/* + * P6 specific Machine Check Exception Reporting + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "mce.h" + +static int banks; + +/* Machine Check Handler For PII/PIII */ +static void intel_machine_check(struct pt_regs * regs, long error_code) +{ + int recover=1; + u32 alow, ahigh, high, low; + u32 mcgstl, mcgsth; + int i; + + rdmsr(MSR_IA32_MCG_STATUS, mcgstl, mcgsth); + if(mcgstl&(1<<0)) /* Recoverable ? */ + recover=0; + + printk(KERN_EMERG "CPU %d: Machine Check Exception: %08x%08x\n", smp_processor_id(), mcgsth, mcgstl); + + for (i=0;i +#include +#include +#include +#include + +#include +#include +#include + +#include "mce.h" + +/* Machine check handler for WinChip C6 */ +static void winchip_machine_check(struct pt_regs * regs, long error_code) +{ + printk(KERN_EMERG "CPU0: Machine Check Exception.\n"); +} + +/* Set up machine check reporting on the Winchip C6 series */ +void __init winchip_mcheck_init(struct cpuinfo_x86 *c) +{ + u32 lo, hi; + machine_check_vector = winchip_machine_check; + wmb(); + rdmsr(MSR_IDT_FCR1, lo, hi); + lo|= (1<<2); /* Enable EIERRINT (int 18 MCE) */ + lo&= ~(1<<4); /* Enable MCE */ + wrmsr(MSR_IDT_FCR1, lo, hi); + set_in_cr4(X86_CR4_MCE); + printk(KERN_INFO "Winchip machine check reporting enabled on CPU#0.\n"); +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/i386/kernel/cpu/mtrr/generic.c linux.2.5.45-ac1/arch/i386/kernel/cpu/mtrr/generic.c --- linux.2.5.45/arch/i386/kernel/cpu/mtrr/generic.c 2002-10-31 14:57:23.000000000 +0000 +++ linux.2.5.45-ac1/arch/i386/kernel/cpu/mtrr/generic.c 2002-10-31 15:05:48.000000000 +0000 @@ -312,8 +312,6 @@ { prepare_set(); - printk("MTRR: setting reg %x\n",reg); - if (size == 0) { /* The invalid bit is kept in the mask, so we simply clear the relevant mask register to disable a range. */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/i386/kernel/cpu/proc.c linux.2.5.45-ac1/arch/i386/kernel/cpu/proc.c --- linux.2.5.45/arch/i386/kernel/cpu/proc.c 2002-10-31 14:57:23.000000000 +0000 +++ linux.2.5.45-ac1/arch/i386/kernel/cpu/proc.c 2002-10-31 15:05:48.000000000 +0000 @@ -17,6 +17,7 @@ * applications want to get the raw CPUID data, they should access * /dev/cpu//cpuid instead. */ + extern int phys_proc_id[NR_CPUS]; static char *x86_cap_flags[] = { /* Intel-defined */ "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce", @@ -74,9 +75,15 @@ /* Cache size */ if (c->x86_cache_size >= 0) seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size); +#ifdef CONFIG_SMP + if (cpu_has_ht) { + seq_printf(m, "physical id\t: %d\n", phys_proc_id[n]); + seq_printf(m, "siblings\t: %d\n", smp_num_siblings); + } +#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.45/arch/i386/kernel/dmi_scan.c linux.2.5.45-ac1/arch/i386/kernel/dmi_scan.c --- linux.2.5.45/arch/i386/kernel/dmi_scan.c 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.45-ac1/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.45/arch/i386/kernel/entry.S linux.2.5.45-ac1/arch/i386/kernel/entry.S --- linux.2.5.45/arch/i386/kernel/entry.S 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.45-ac1/arch/i386/kernel/entry.S 2002-10-31 15:18:12.000000000 +0000 @@ -136,7 +136,7 @@ movl %ecx,CS(%esp) # 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 @@ -158,7 +158,7 @@ movl %ecx,CS(%esp) # 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 +334,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) \ @@ -471,16 +509,73 @@ pushl $do_page_fault jmp error_code +#ifdef CONFIG_X86_MCE ENTRY(machine_check) pushl $0 pushl $do_machine_check jmp error_code +#endif ENTRY(spurious_interrupt_bug) pushl $0 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.45/arch/i386/kernel/head.S linux.2.5.45-ac1/arch/i386/kernel/head.S --- linux.2.5.45/arch/i386/kernel/head.S 2002-10-31 14:57:24.000000000 +0000 +++ linux.2.5.45-ac1/arch/i386/kernel/head.S 2002-10-31 15:05:48.000000000 +0000 @@ -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.45/arch/i386/kernel/i386_ksyms.c linux.2.5.45-ac1/arch/i386/kernel/i386_ksyms.c --- linux.2.5.45/arch/i386/kernel/i386_ksyms.c 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.45-ac1/arch/i386/kernel/i386_ksyms.c 2002-10-31 15:18:45.000000000 +0000 @@ -211,3 +211,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.45/arch/i386/kernel/i8259.c linux.2.5.45-ac1/arch/i386/kernel/i8259.c --- linux.2.5.45/arch/i386/kernel/i8259.c 2002-10-31 14:57:24.000000000 +0000 +++ linux.2.5.45-ac1/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.45/arch/i386/kernel/init_task.c linux.2.5.45-ac1/arch/i386/kernel/init_task.c --- linux.2.5.45/arch/i386/kernel/init_task.c 2002-10-31 14:57:24.000000000 +0000 +++ linux.2.5.45-ac1/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.45/arch/i386/kernel/irq.c linux.2.5.45-ac1/arch/i386/kernel/irq.c --- linux.2.5.45/arch/i386/kernel/irq.c 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.45-ac1/arch/i386/kernel/irq.c 2002-10-31 15:18:56.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.45/arch/i386/kernel/Makefile linux.2.5.45-ac1/arch/i386/kernel/Makefile --- linux.2.5.45/arch/i386/kernel/Makefile 2002-10-31 14:57:24.000000000 +0000 +++ linux.2.5.45-ac1/arch/i386/kernel/Makefile 2002-10-31 15:05:48.000000000 +0000 @@ -4,12 +4,11 @@ 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 \ - pci-dma.o i386_ksyms.o i387.o bluesmoke.o dmi_scan.o \ - bootflag.o + pci-dma.o i386_ksyms.o i387.o dmi_scan.o bootflag.o obj-y += cpu/ obj-y += timers/ @@ -21,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.45/arch/i386/kernel/pci-dma.c linux.2.5.45-ac1/arch/i386/kernel/pci-dma.c --- linux.2.5.45/arch/i386/kernel/pci-dma.c 2002-10-31 14:57:24.000000000 +0000 +++ linux.2.5.45-ac1/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.45/arch/i386/kernel/process.c linux.2.5.45-ac1/arch/i386/kernel/process.c --- linux.2.5.45/arch/i386/kernel/process.c 2002-10-31 14:57:23.000000000 +0000 +++ linux.2.5.45-ac1/arch/i386/kernel/process.c 2002-10-31 15:05:48.000000000 +0000 @@ -156,7 +156,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; @@ -413,6 +431,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.45/arch/i386/kernel/reboot.c linux.2.5.45-ac1/arch/i386/kernel/reboot.c --- linux.2.5.45/arch/i386/kernel/reboot.c 2002-10-31 14:57:24.000000000 +0000 +++ linux.2.5.45-ac1/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.45/arch/i386/kernel/setup.c linux.2.5.45-ac1/arch/i386/kernel/setup.c --- linux.2.5.45/arch/i386/kernel/setup.c 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.45-ac1/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.45/arch/i386/kernel/smpboot.c linux.2.5.45-ac1/arch/i386/kernel/smpboot.c --- linux.2.5.45/arch/i386/kernel/smpboot.c 2002-10-31 14:57:24.000000000 +0000 +++ linux.2.5.45-ac1/arch/i386/kernel/smpboot.c 2002-10-31 15:05:48.000000000 +0000 @@ -58,7 +58,7 @@ /* Number of siblings per CPU package */ int smp_num_siblings = 1; -int __initdata phys_proc_id[NR_CPUS]; /* Package ID of each logical CPU */ +int phys_proc_id[NR_CPUS]; /* Package ID of each logical CPU */ /* Bitmask of currently online CPUs */ unsigned long cpu_online_map; @@ -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; @@ -764,6 +769,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) @@ -787,6 +814,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: @@ -804,7 +833,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 diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/i386/kernel/time.c linux.2.5.45-ac1/arch/i386/kernel/time.c --- linux.2.5.45/arch/i386/kernel/time.c 2002-10-31 14:57:24.000000000 +0000 +++ linux.2.5.45-ac1/arch/i386/kernel/time.c 2002-10-31 15:05:48.000000000 +0000 @@ -61,6 +61,7 @@ #include extern spinlock_t i8259A_lock; +int pit_latch_buggy; /* extern */ #include "do_timer.h" diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/i386/kernel/timers/Makefile linux.2.5.45-ac1/arch/i386/kernel/timers/Makefile --- linux.2.5.45/arch/i386/kernel/timers/Makefile 2002-10-31 14:57:24.000000000 +0000 +++ linux.2.5.45-ac1/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.45/arch/i386/kernel/timers/timer.c linux.2.5.45-ac1/arch/i386/kernel/timers/timer.c --- linux.2.5.45/arch/i386/kernel/timers/timer.c 2002-10-31 14:57:24.000000000 +0000 +++ linux.2.5.45-ac1/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.45/arch/i386/kernel/timers/timer_pit.c linux.2.5.45-ac1/arch/i386/kernel/timers/timer_pit.c --- linux.2.5.45/arch/i386/kernel/timers/timer_pit.c 2002-10-31 14:57:24.000000000 +0000 +++ linux.2.5.45-ac1/arch/i386/kernel/timers/timer_pit.c 2002-10-31 15:05:48.000000000 +0000 @@ -8,7 +8,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.45/arch/i386/kernel/timers/timer_tsc.c linux.2.5.45-ac1/arch/i386/kernel/timers/timer_tsc.c --- linux.2.5.45/arch/i386/kernel/timers/timer_tsc.c 2002-10-31 14:57:24.000000000 +0000 +++ linux.2.5.45-ac1/arch/i386/kernel/timers/timer_tsc.c 2002-10-31 15:05:48.000000000 +0000 @@ -60,6 +60,8 @@ static void mark_offset_tsc(void) { int count; + int countmp; + static int count1=0, count2=LATCH; /* * It is important that these two operations happen almost at * the same time. We do the RDTSC stuff first, since it's @@ -83,6 +85,20 @@ count |= inb(0x40) << 8; spin_unlock(&i8253_lock); + if (pit_latch_buggy) { + /* get center value of last 3 time lutch */ + if ((count2 >= count && count >= count1) + || (count1 >= count && count >= count2)) { + count2 = count1; count1 = count; + } else if ((count1 >= count2 && count2 >= count) + || (count >= count2 && count2 >= count1)) { + countmp = count;count = count2; + count2 = count1;count1 = countmp; + } else { + count2 = count1; count1 = count; count = count1; + } + } + count = ((LATCH-1) - count) * TICK_SIZE; delay_at_last_interrupt = (count + LATCH/2) / LATCH; } @@ -111,10 +127,12 @@ * Set the Gate high, program CTC channel 2 for mode 0, * (interrupt on terminal count mode), binary count, * load 5 * LATCH count, (LSB and MSB) to begin countdown. + * + * Some devices need a delay here. */ outb(0xb0, 0x43); /* binary, mode 0, LSB/MSB, Ch 2 */ - outb(CALIBRATE_LATCH & 0xff, 0x42); /* LSB of count */ - outb(CALIBRATE_LATCH >> 8, 0x42); /* MSB of count */ + outb_p(CALIBRATE_LATCH & 0xff, 0x42); /* LSB of count */ + outb_p(CALIBRATE_LATCH >> 8, 0x42); /* MSB of count */ { unsigned long startlow, starthigh; @@ -238,8 +256,6 @@ * moaned if you have the only one in the world - you fix it! */ - dodgy_tsc(); - if (cpu_has_tsc) { unsigned long tsc_quotient = calibrate_tsc(); if (tsc_quotient) { diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/i386/kernel/trampoline.S linux.2.5.45-ac1/arch/i386/kernel/trampoline.S --- linux.2.5.45/arch/i386/kernel/trampoline.S 2002-10-31 14:57:24.000000000 +0000 +++ linux.2.5.45-ac1/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.45/arch/i386/kernel/traps.c linux.2.5.45-ac1/arch/i386/kernel/traps.c --- linux.2.5.45/arch/i386/kernel/traps.c 2002-10-31 14:57:24.000000000 +0000 +++ linux.2.5.45-ac1/arch/i386/kernel/traps.c 2002-10-31 15:05:48.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 @@ -697,7 +700,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); } @@ -754,7 +757,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 { /* @@ -906,7 +909,9 @@ set_trap_gate(15,&spurious_interrupt_bug); set_trap_gate(16,&coprocessor_error); set_trap_gate(17,&alignment_check); +#ifdef CONFIG_X86_MCE set_trap_gate(18,&machine_check); +#endif set_trap_gate(19,&simd_coprocessor_error); set_system_gate(SYSCALL_VECTOR,&system_call); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/i386/kernel/vm86.c linux.2.5.45-ac1/arch/i386/kernel/vm86.c --- linux.2.5.45/arch/i386/kernel/vm86.c 2002-10-31 14:57:24.000000000 +0000 +++ linux.2.5.45-ac1/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.45/arch/i386/lib/mmx.c linux.2.5.45-ac1/arch/i386/lib/mmx.c --- linux.2.5.45/arch/i386/lib/mmx.c 2002-10-31 14:57:24.000000000 +0000 +++ linux.2.5.45-ac1/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.45/arch/i386/mach-defaults/pci-functions.h linux.2.5.45-ac1/arch/i386/mach-defaults/pci-functions.h --- linux.2.5.45/arch/i386/mach-defaults/pci-functions.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/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.45/arch/i386/mach-generic/io_ports.h linux.2.5.45-ac1/arch/i386/mach-generic/io_ports.h --- linux.2.5.45/arch/i386/mach-generic/io_ports.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/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.45/arch/i386/mach-generic/irq_vectors.h linux.2.5.45-ac1/arch/i386/mach-generic/irq_vectors.h --- linux.2.5.45/arch/i386/mach-generic/irq_vectors.h 2002-10-31 14:57:24.000000000 +0000 +++ linux.2.5.45-ac1/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.45/arch/i386/mach-generic/mach_reboot.h linux.2.5.45-ac1/arch/i386/mach-generic/mach_reboot.h --- linux.2.5.45/arch/i386/mach-generic/mach_reboot.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/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.45/arch/i386/mach-pc9800/entry_arch.h linux.2.5.45-ac1/arch/i386/mach-pc9800/entry_arch.h --- linux.2.5.45/arch/i386/mach-pc9800/entry_arch.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/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.45/arch/i386/mach-pc9800/io_ports.h linux.2.5.45-ac1/arch/i386/mach-pc9800/io_ports.h --- linux.2.5.45/arch/i386/mach-pc9800/io_ports.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/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.45/arch/i386/mach-pc9800/irq_vectors.h linux.2.5.45-ac1/arch/i386/mach-pc9800/irq_vectors.h --- linux.2.5.45/arch/i386/mach-pc9800/irq_vectors.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/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.45/arch/i386/mach-pc9800/mach_apic.h linux.2.5.45-ac1/arch/i386/mach-pc9800/mach_apic.h --- linux.2.5.45/arch/i386/mach-pc9800/mach_apic.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/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.45/arch/i386/mach-pc9800/mach_reboot.h linux.2.5.45-ac1/arch/i386/mach-pc9800/mach_reboot.h --- linux.2.5.45/arch/i386/mach-pc9800/mach_reboot.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/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.45/arch/i386/mach-pc9800/Makefile linux.2.5.45-ac1/arch/i386/mach-pc9800/Makefile --- linux.2.5.45/arch/i386/mach-pc9800/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/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.45/arch/i386/mach-pc9800/pci-functions.h linux.2.5.45-ac1/arch/i386/mach-pc9800/pci-functions.h --- linux.2.5.45/arch/i386/mach-pc9800/pci-functions.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/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.45/arch/i386/mach-pc9800/setup_arch_post.h linux.2.5.45-ac1/arch/i386/mach-pc9800/setup_arch_post.h --- linux.2.5.45/arch/i386/mach-pc9800/setup_arch_post.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/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.45/arch/i386/mach-pc9800/setup_arch_pre.h linux.2.5.45-ac1/arch/i386/mach-pc9800/setup_arch_pre.h --- linux.2.5.45/arch/i386/mach-pc9800/setup_arch_pre.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/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.45/arch/i386/mach-pc9800/setup.c linux.2.5.45-ac1/arch/i386/mach-pc9800/setup.c --- linux.2.5.45/arch/i386/mach-pc9800/setup.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/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.45/arch/i386/mach-summit/io_ports.h linux.2.5.45-ac1/arch/i386/mach-summit/io_ports.h --- linux.2.5.45/arch/i386/mach-summit/io_ports.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/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.45/arch/i386/mach-summit/mach_reboot.h linux.2.5.45-ac1/arch/i386/mach-summit/mach_reboot.h --- linux.2.5.45/arch/i386/mach-summit/mach_reboot.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/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.45/arch/i386/mach-visws/io_ports.h linux.2.5.45-ac1/arch/i386/mach-visws/io_ports.h --- linux.2.5.45/arch/i386/mach-visws/io_ports.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/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.45/arch/i386/mach-visws/irq_vectors.h linux.2.5.45-ac1/arch/i386/mach-visws/irq_vectors.h --- linux.2.5.45/arch/i386/mach-visws/irq_vectors.h 2002-10-31 14:57:24.000000000 +0000 +++ linux.2.5.45-ac1/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.45/arch/i386/mach-visws/mach_reboot.h linux.2.5.45-ac1/arch/i386/mach-visws/mach_reboot.h --- linux.2.5.45/arch/i386/mach-visws/mach_reboot.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/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.45/arch/i386/mach-voyager/irq_vectors.h linux.2.5.45-ac1/arch/i386/mach-voyager/irq_vectors.h --- linux.2.5.45/arch/i386/mach-voyager/irq_vectors.h 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.45-ac1/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.45/arch/i386/Makefile linux.2.5.45-ac1/arch/i386/Makefile --- linux.2.5.45/arch/i386/Makefile 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.45-ac1/arch/i386/Makefile 2002-10-31 15:16:13.000000000 +0000 @@ -48,8 +48,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 @@ -62,8 +70,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)) @@ -90,6 +98,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.45/arch/i386/pci/direct.c linux.2.5.45-ac1/arch/i386/pci/direct.c --- linux.2.5.45/arch/i386/pci/direct.c 2002-10-31 14:57:24.000000000 +0000 +++ linux.2.5.45-ac1/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.45/arch/i386/pci/pcbios.c linux.2.5.45-ac1/arch/i386/pci/pcbios.c --- linux.2.5.45/arch/i386/pci/pcbios.c 2002-10-31 14:57:24.000000000 +0000 +++ linux.2.5.45-ac1/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.45/arch/ia64/Kconfig linux.2.5.45-ac1/arch/ia64/Kconfig --- linux.2.5.45/arch/ia64/Kconfig 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.45-ac1/arch/ia64/Kconfig 2002-11-01 11:34:55.000000000 +0000 @@ -14,6 +14,14 @@ of early 2001 it is not yet in widespread production use. The Linux IA-64 project has a home page at . +config MMU + bool + default y + +config SWAP + bool + default y + config ISA bool help diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68k/atari/hades-pci.c linux.2.5.45-ac1/arch/m68k/atari/hades-pci.c --- linux.2.5.45/arch/m68k/atari/hades-pci.c 2002-10-31 14:57:24.000000000 +0000 +++ linux.2.5.45-ac1/arch/m68k/atari/hades-pci.c 2002-10-31 15:05:53.000000000 +0000 @@ -311,26 +311,24 @@ slot = PCI_SLOT(dev->devfn); /* Determine slot number. */ dev->irq = irq_tab[slot]; if (pci_modify) - pcibios_write_config_byte(dev->bus->number, dev->devfn, - PCI_INTERRUPT_LINE, dev->irq); + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); } } } /* - * static void hades_conf_device(unsigned char bus, unsigned char device_fn) + * static void hades_conf_device(struct pci_dev *dev) * * Machine dependent Configure the given device. * * Parameters: * - * bus - bus number of the device. - * device_fn - device and function number of the device. + * dev - the pci device. */ -static void __init hades_conf_device(unsigned char bus, unsigned char device_fn) +static void __init hades_conf_device(struct pci_dev *dev) { - pcibios_write_config_byte(bus, device_fn, PCI_CACHE_LINE_SIZE, 0); + pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 0); } static struct pci_ops hades_pci_ops = { diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68k/Kconfig linux.2.5.45-ac1/arch/m68k/Kconfig --- linux.2.5.45/arch/m68k/Kconfig 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.45-ac1/arch/m68k/Kconfig 2002-11-01 11:34:30.000000000 +0000 @@ -21,6 +21,13 @@ bool default y +config MMU + bool + default y + +config SWAP + bool + default y mainmenu "Linux/68k Kernel Configuration" diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68k/kernel/bios32.c linux.2.5.45-ac1/arch/m68k/kernel/bios32.c --- linux.2.5.45/arch/m68k/kernel/bios32.c 2002-10-31 14:57:24.000000000 +0000 +++ linux.2.5.45-ac1/arch/m68k/kernel/bios32.c 2002-10-31 15:05:53.000000000 +0000 @@ -95,7 +95,6 @@ static void __init disable_dev(struct pci_dev *dev) { - struct pci_bus *bus; unsigned short cmd; if (((dev->class >> 8 == PCI_CLASS_NOT_DEFINED_VGA) || @@ -103,11 +102,10 @@ (dev->class >> 8 == PCI_CLASS_DISPLAY_XGA)) && skip_vga) return; - bus = dev->bus; - pcibios_read_config_word(bus->number, dev->devfn, PCI_COMMAND, &cmd); + pci_read_config_word(dev, PCI_COMMAND, &cmd); cmd &= (~PCI_COMMAND_IO & ~PCI_COMMAND_MEMORY & ~PCI_COMMAND_MASTER); - pcibios_write_config_word(bus->number, dev->devfn, PCI_COMMAND, cmd); + pci_write_config_word(dev, PCI_COMMAND, cmd); } /* @@ -122,7 +120,6 @@ static void __init layout_dev(struct pci_dev *dev) { - struct pci_bus *bus; unsigned short cmd; unsigned int base, mask, size, reg; unsigned int alignto; @@ -137,8 +134,7 @@ (dev->class >> 8 == PCI_CLASS_DISPLAY_XGA)) && skip_vga) return; - bus = dev->bus; - pcibios_read_config_word(bus->number, dev->devfn, PCI_COMMAND, &cmd); + pci_read_config_word(dev, PCI_COMMAND, &cmd); for (reg = PCI_BASE_ADDRESS_0, i = 0; reg <= PCI_BASE_ADDRESS_5; reg += 4, i++) { @@ -147,9 +143,8 @@ * device wants. */ - pcibios_write_config_dword(bus->number, dev->devfn, reg, - 0xffffffff); - pcibios_read_config_dword(bus->number, dev->devfn, reg, &base); + pci_write_config_dword(dev, reg, 0xffffffff); + pci_read_config_dword(dev, reg, &base); if (!base) { @@ -184,8 +179,7 @@ alignto = MAX(0x040, size) ; base = ALIGN(io_base, alignto); io_base = base + size; - pcibios_write_config_dword(bus->number, dev->devfn, - reg, base | PCI_BASE_ADDRESS_SPACE_IO); + pci_write_config_dword(dev, reg, base | PCI_BASE_ADDRESS_SPACE_IO); dev->resource[i].start = base; dev->resource[i].end = dev->resource[i].start + size - 1; @@ -228,8 +222,7 @@ alignto = MAX(0x1000, size) ; base = ALIGN(mem_base, alignto); mem_base = base + size; - pcibios_write_config_dword(bus->number, dev->devfn, - reg, base); + pci_write_config_dword(dev, reg, base); dev->resource[i].start = base; dev->resource[i].end = dev->resource[i].start + size - 1; @@ -243,8 +236,7 @@ */ reg += 4; - pcibios_write_config_dword(bus->number, dev->devfn, - reg, 0); + pci_write_config_dword(dev, reg, 0); i++; dev->resource[i].start = 0; @@ -272,17 +264,15 @@ cmd |= PCI_COMMAND_IO; } - pcibios_write_config_word(bus->number, dev->devfn, PCI_COMMAND, - cmd | PCI_COMMAND_MASTER); + pci_write_config_word(dev, PCI_COMMAND, cmd | PCI_COMMAND_MASTER); - pcibios_write_config_byte(bus->number, dev->devfn, PCI_LATENCY_TIMER, - (disable_pci_burst) ? 0 : 32); + pci_write_config_byte(dev, PCI_LATENCY_TIMER, (disable_pci_burst) ? 0 : 32); if (bus_info != NULL) - bus_info->conf_device(bus->number, dev->devfn); /* Machine dependent configuration. */ + bus_info->conf_device(dev); /* Machine dependent configuration. */ DBG_DEVS(("layout_dev: bus %d slot 0x%x VID 0x%x DID 0x%x class 0x%x\n", - bus->number, PCI_SLOT(dev->devfn), dev->vendor, dev->device, dev->class)); + dev->bus->number, PCI_SLOT(dev->devfn), dev->vendor, dev->device, dev->class)); } /* diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/defconfig linux.2.5.45-ac1/arch/m68knommu/defconfig --- linux.2.5.45/arch/m68knommu/defconfig 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/defconfig 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,538 @@ +# +# Automatically generated by make menuconfig: don't edit +# +# CONFIG_MMU is not set +# CONFIG_SWAP is not set +CONFIG_UID16=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y + +# +# Loadable module support +# +# CONFIG_MODULES is not set + +# +# Processor type and features +# +# CONFIG_M68000 is not set +# CONFIG_M68EN302 is not set +# CONFIG_M68328 is not set +# CONFIG_M68EZ328 is not set +# CONFIG_M68VZ328 is not set +# CONFIG_M68332 is not set +# CONFIG_M68360 is not set +# CONFIG_M5204 is not set +# CONFIG_M5206 is not set +# CONFIG_M5206e is not set +# CONFIG_M5249 is not set +CONFIG_M5272=y +# CONFIG_M5307 is not set +# CONFIG_M5407 is not set +CONFIG_COLDFIRE=y +# CONFIG_CLOCK_AUTO is not set +# CONFIG_CLOCK_11MHz is not set +# CONFIG_CLOCK_16MHz is not set +# CONFIG_CLOCK_20MHz is not set +# CONFIG_CLOCK_24MHz is not set +# CONFIG_CLOCK_25MHz is not set +# CONFIG_CLOCK_33MHz is not set +# CONFIG_CLOCK_40MHz is not set +# CONFIG_CLOCK_45MHz is not set +# CONFIG_CLOCK_48MHz is not set +# CONFIG_CLOCK_50MHz is not set +# CONFIG_CLOCK_54MHz is not set +# CONFIG_CLOCK_60MHz is not set +CONFIG_CLOCK_66MHz=y +# CONFIG_CLOCK_70MHz is not set +# CONFIG_CLOCK_140MHz is not set +CONFIG_M5272C3=y +# CONFIG_GILBARCONAP is not set +# CONFIG_NETtel is not set +# CONFIG_SNAPGEAR is not set +# CONFIG_ROMFS_FROM_ROM is not set +CONFIG_MOTOROLA=y +# CONFIG_LARGE_ALLOCS is not set +# CONFIG_RAMAUTO is not set +# CONFIG_RAM4MB is not set +# CONFIG_RAM8MB is not set +CONFIG_RAM16MB=y +# CONFIG_RAM32MB is not set +CONFIG_AUTOBIT=y +# CONFIG_RAM8BIT is not set +# CONFIG_RAM16BIT is not set +# CONFIG_RAM32bit is not set +CONFIG_RAMKERNEL=y +# CONFIG_ROMKERNEL is not set +# CONFIG_HIMEMKERNEL is not set + +# +# General setup +# +CONFIG_NET=y +# CONFIG_PCI is not set +# CONFIG_HOTPLUG is not set +# CONFIG_PCMCIA is not set +# CONFIG_SYSVIPC is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_SYSCTL is not set +# CONFIG_KCORE_ELF is not set +CONFIG_KCORE_AOUT=y +CONFIG_BINFMT_FLAT=y +# CONFIG_BINFMT_ZFLAT is not set +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_ELF is not set +# CONFIG_BINFMT_MISC is not set +# CONFIG_PM is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_CONCAT is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set + +# +# RAM/ROM/Flash chip drivers +# +# CONFIG_MTD_CFI is not set +# CONFIG_MTD_JEDECPROBE is not set +# CONFIG_MTD_GEN_PROBE is not set +# CONFIG_MTD_CFI_INTELEXT is not set +# CONFIG_MTD_CFI_AMDSTD is not set +CONFIG_MTD_RAM=y +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_OBSOLETE_CHIPS is not set +# CONFIG_MTD_AMDSTD is not set +# CONFIG_MTD_SHARP is not set +# CONFIG_MTD_JEDEC is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_PHYSMAP is not set +# CONFIG_MTD_PCI is not set +# CONFIG_MTD_PCMCIA is not set +CONFIG_MTD_UCLINUX=y +# CONFIG_MTD_SNAPGEARuC is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLKMTD is not set +# CONFIG_MTD_DOC1000 is not set +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOCPROBE is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play configuration +# +# CONFIG_PNP is not set +# CONFIG_PNP_NAMES is not set +# CONFIG_PNP_DEBUG is not set +# CONFIG_ISAPNP is not set +# CONFIG_PNPBIOS is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_XD is not set +# CONFIG_PARIDE is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_CISS_SCSI_TAPE is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=4096 +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_BLK_DEV_BLKMEM is not set + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +# CONFIG_NETLINK_DEV is not set +# CONFIG_NETFILTER is not set +# CONFIG_FILTER is not set +CONFIG_UNIX=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_IPV6 is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_DEV_APPLETALK is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set +# CONFIG_PHONE_IXJ is not set +# CONFIG_PHONE_IXJ_PCMCIA is not set + +# +# ATA/IDE/MFM/RLL support +# +# CONFIG_IDE is not set +# CONFIG_BLK_DEV_IDE_MODES is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI support +# +# CONFIG_SCSI is not set + +# +# I2O device support +# +# CONFIG_I2O is not set +# CONFIG_I2O_BLOCK is not set +# CONFIG_I2O_LAN is not set +# CONFIG_I2O_SCSI is not set +# CONFIG_I2O_PROC is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_SUNLANCE is not set +# CONFIG_SUNBMAC is not set +# CONFIG_SUNQE is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_LANCE is not set +# CONFIG_NET_VENDOR_SMC is not set +# CONFIG_NET_VENDOR_RACAL is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_NET_ISA is not set +# CONFIG_NET_PCI is not set +# CONFIG_NET_POCKET is not set +CONFIG_FEC=y + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_E1000_NAPI is not set +# CONFIG_MYRI_SBUS is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PLIP is not set +CONFIG_PPP=y +# CONFIG_PPP_MULTILINK is not set +# CONFIG_PPP_FILTER is not set +# CONFIG_PPP_ASYNC is not set +# CONFIG_PPP_SYNC_TTY is not set +# CONFIG_PPP_DEFLATE is not set +# CONFIG_PPP_BSDCOMP is not set +# CONFIG_PPPOE is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set +# CONFIG_NET_FC is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Old CD-ROM drivers (not SCSI, not IDE) +# +# CONFIG_CD_NO_IDESCSI is not set + +# +# Character devices +# +# CONFIG_VT is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_RESETSWITCH is not set +# CONFIG_LEDMAN is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set +# CONFIG_SERIAL_8250_CONSOLE is not set +# CONFIG_SERIAL_8250_CS is not set +# CONFIG_SERIAL_8250_EXTENDED is not set +# CONFIG_SERIAL_8250_MANY_PORTS is not set +# CONFIG_SERIAL_8250_SHARE_IRQ is not set +# CONFIG_SERIAL_8250_DETECT_IRQ is not set +# CONFIG_SERIAL_8250_MULTIPORT is not set +# CONFIG_SERIAL_8250_RSA is not set +CONFIG_SERIAL_COLDFIRE=y +# CONFIG_UNIX98_PTYS is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set +# CONFIG_SCx200_GPIO is not set +# CONFIG_RAW_DRIVER is not set + +# +# File systems +# +# CONFIG_QUOTA is not set +# CONFIG_QFMT_V1 is not set +# CONFIG_QFMT_V2 is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set +# CONFIG_ADFS_FS is not set +# CONFIG_ADFS_FS_RW is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_JBD_DEBUG is not set +# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_UMSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +# CONFIG_JFFS2_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_TMPFS is not set +CONFIG_RAMFS=y +# CONFIG_ISO9660_FS is not set +# CONFIG_JOLIET is not set +# CONFIG_ZISOFS is not set +# CONFIG_JFS_FS is not set +# CONFIG_JFS_DEBUG is not set +# CONFIG_JFS_STATISTICS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_NTFS_FS is not set +# CONFIG_NTFS_DEBUG is not set +# CONFIG_NTFS_RW is not set +# CONFIG_HPFS_FS is not set +CONFIG_PROC_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 +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX4FS_RW is not set +CONFIG_ROMFS_FS=y +CONFIG_EXT2_FS=y +# CONFIG_SYSV_FS is not set +# CONFIG_UDF_FS is not set +# CONFIG_UDF_RW is not set +# CONFIG_UFS_FS is not set +# CONFIG_UFS_FS_WRITE is not set +# CONFIG_XFS_FS is not set +# CONFIG_XFS_RT is not set +# CONFIG_XFS_QUOTA is not set + +# +# Network File Systems +# +# CONFIG_CODA_FS is not set +# 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 +# CONFIG_NCPFS_IOCTL_LOCKING is not set +# CONFIG_NCPFS_STRONG is not set +# CONFIG_NCPFS_NFS_NS is not set +# CONFIG_NCPFS_OS2_NS is not set +# 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 + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_SMB_NLS is not set +# CONFIG_NLS is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# Kernel hacking +# +# CONFIG_FULLDEBUG is not set +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_PROFILE is not set +# CONFIG_DUMPTOFLASH is not set +# CONFIG_NO_KERNEL_MSG is not set +# CONFIG_SMALL_TASKS is not set +# CONFIG_BDM_DISABLE is not set + +# +# Security options +# +CONFIG_SECURITY_CAPABILITIES=y + +# +# Library routines +# +# CONFIG_CRC32 is not set +# CONFIG_ZLIB_INFLATE is not set +# CONFIG_ZLIB_DEFLATE is not set diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/Kconfig linux.2.5.45-ac1/arch/m68knommu/Kconfig --- linux.2.5.45/arch/m68knommu/Kconfig 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/Kconfig 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,796 @@ +# +# For a description of the syntax of this configuration file, +# see Documentation/kbuild/config-language.txt. +# + +mainmenu "uClinux/68k (w/o MMU) Kernel Configuration" + +config MMU + bool + default n + +config SWAP + bool + default n + +config FPU + bool + default n + +config UID16 + bool + default y + +config RWSEM_GENERIC_SPINLOCK + bool + default y + +config RWSEM_XCHGADD_ALGORITHM + bool + default n + + +source "init/Kconfig" + +menu "Processor type and features" + +choice + prompt "CPU" + default M68EZ328 + +config M68328 + bool "MC68328" + help + Motorola 68328 processor support. + +config M68EZ328 + bool "MC68EZ328" + help + Motorola 68EX328 processor support. + +config M68VZ328 + bool "MC68VZ328" + help + Motorola 68VZ328 processor support. + +config M68360 + bool "MC68360" + help + Motorola 68360 processor support. + +config M5206 + bool "MCF5206" + help + Motorola ColdFire 5206 processor support. + +config M5206e + bool "MCF5206e" + help + Motorola ColdFire 5206e processor support. + +config M5249 + bool "MCF5249" + help + Motorola ColdFire 5249 processor support. + +config M5272 + bool "MCF5272" + help + Motorola ColdFire 5272 processor support. + +config M5307 + bool "MCF5307" + help + Motorola ColdFire 5307 processor support. + +config M5407 + bool "MCF5407" + help + Motorola ColdFire 5407 processor support. + +endchoice + +config COLDFIRE + bool + depends on (M5206 || M5206e || M5249 || M5272 || M5307 || M5407) + default y + +choice + prompt "CPU CLOCK Frequency" + default AUTO + +config CLOCK_AUTO + bool "AUTO" + ---help--- + Define the CPU clock frequency in use. On many boards you don't + really need to know, so you can select the AUTO option. On some + boards you need to know the real clock frequency to determine other + system timing (for example baud rate dividors, etc). Some processors + have an internal PLL and you can seletc a frequency to set that too. + You need to know a little about the internals of your processor to + set this. If in doubt choose the AUTO option. + +config CLOCK_11MHz + bool "11MHz" + help + Select an 11MHz CPU clock frequency. + +config CLOCK_16MHz + bool "16MHz" + help + Select an 16MHz CPU clock frequency. + +config CLOCK_20MHz + bool "20MHz" + help + Select an 20MHz CPU clock frequency. + +config CLOCK_24MHz + bool "24MHz" + help + Select an 24MHz CPU clock frequency. + +config CLOCK_25MHz + bool "25MHz" + help + Select an 25MHz CPU clock frequency. + +config CLOCK_33MHz + bool "33MHz" + help + Select an 33MHz CPU clock frequency. + +config CLOCK_40MHz + bool "40MHz" + help + Select an 40MHz CPU clock frequency. + +config CLOCK_45MHz + bool "45MHz" + help + Select an 45MHz CPU clock frequency. + +config CLOCK_48MHz + bool "48MHz" + help + Select an 48MHz CPU clock frequency. + +config CLOCK_50MHz + bool "50MHz" + help + Select an 50MHz CPU clock frequency. + +config CLOCK_54MHz + bool "54MHz" + help + Select an 54MHz CPU clock frequency. + +config CLOCK_60MHz + bool "60MHz" + help + Select an 60MHz CPU clock frequency. + +config CLOCK_66MHz + bool "66MHz" + help + Select an 66MHz CPU clock frequency. + +config CLOCK_70MHz + bool "70MHz" + help + Select an 70MHz CPU clock frequency. + +config CLOCK_140MHz + bool "140MHz" + help + Select an 140MHz CPU clock frequency. + +endchoice + +config OLDMASK + bool "Old mask 5307 (1H55J) silicon" + depends on M5307 + help + Build support for the older revision ColdFire 5307 silicon. + Specifically this is the 1H55J mask revision. + +comment "Platform" + +config PILOT3 + bool "Pilot 1000/5000, PalmPilot Personal/Pro, or PalmIII support" + depends on M68328 + help + Support for the Palm Pilot 1000/5000, Personal/Pro and PalmIII. + +config XCOPILOT_BUGS + bool " (X)Copilot support" + depends on PILOT3 + help + Support the bugs of Xcopilot. + +config UCSIMM + bool "uCsimm module support" + depends on M68EZ328 + help + Support for the Arcturus Networks uCsimm module. + +config UCDIMM + bool "uDsimm module support" + depends on M68VZ328 + help + Support for the Arcturus Networks uDsimm module. + +config DRAGEN2 + bool "Dragen Engine II board support" + depends on M68VZ328 + help + Support for the Dragen Engine II board. + +config HWADDR_FROMEEPROM + bool " Read ETH address from EEPROM" + depends on DRAGEN2 + help + Use MAC address from EEPROM. + +config HWADDR_OFFSET + int " Offset from start of EEPROM" + default "2" + depends on HWADDR_FROMEEPROM + +config INIT_LCD + bool " Initialize LCD" + depends on (UCSIMM || UCDIMM || DRAGEN2) + help + Initialize the LCD controller of the 68x328 processor. + +config MEMORY_RESERVE + int " Memory reservation (MiB)" + depends on (UCSIMM || UCDIMM || DRAGEN2) + help + Reserve certain memory regions on 68x328 based boards. + +config UCQUICC + bool "Lineo uCquicc board support" + depends on M68360 + help + Support for the Lineo uCquicc board. + +config ARN5206 + bool "Arnewsh 5206 board support" + depends on M5206 + help + Support for the Arnewsh 5206 board. + +config M5206eC3 + bool "Motorola M5206eC3 board support" + depends on M5206e + help + Support for the Motorola M5206eC3 board. + +config ELITE + bool "Motorola M5206eLITE board support" + depends on M5206e + help + Support for the Motorola M5206eLITE board. + +config M5249C3 + bool "Motorola M5249C3 board support" + depends on M5249 + help + Support for the Motorola M5249C3 board. + +config M5272C3 + bool "Motorola M5272C3 board support" + depends on M5272 + help + Support for the Motorola M5272C3 board. + +config ARN5307 + bool "Arnewsh 5307 board support" + depends on M5307 + help + Support for the Arnewsh 5307 board. + +config M5307C3 + bool "Motorola M5307C3 board support" + depends on M5307 + help + Support for the Motorola M5307C3 board. + +config eLIA + bool "Moreton Bay eLIA board support" + depends on M5307 + help + Support for the Moreton Bay eLIA board. + +config SECUREEDGEMP3 + bool "SnapGear SecureEdge/MP3 platform support" + depends on M5307 + help + Support for the SnapGear SecureEdge/MP3 platform. + +config M5407C3 + bool "Motorola M5407C3 board support" + depends on M5407 + help + Support for the Motorola M5407C3 board. + +config CLEOPATRA + bool "Feith CLEOPATRA board support" + depends on (M5307 || M5407) + help + Support for the Feith Cleopatra boards. + +config NETtel + bool "SecureEdge/NETtel board support" + depends on (M5206e || M5272 || M5307) + help + Support for the SnapGear NETtel/SecureEdge/SnapGear boards. + +config SNAPGEAR + bool "SnapGear router board support" + depends on NETtel + help + Special additional support for SnapGear router boards. + +config ROMFS_FROM_ROM + bool " ROMFS image not RAM resident" + depends on (NETtel || SNAPGEAR) + help + The ROMfs filesystem will stay resident in the FLASH/ROM, not be + moved into RAM. + +config PILOT + bool + default y + depends on (PILOT3 || PILOT5) + +config ARNEWSH + bool + default y + depends on (ARN5206 || ARN5307) + +config MOTOROLA + bool + default y + depends on (M5206eC3 || M5249C3 || M5272C3 || M5307C3 || M5407C3) + +config LARGE_ALLOCS + bool "Allow allocating large blocks (> 1MB) of memory" + help + Allow the slab memory allocator to keep chains for very large + memory sizes - upto 32MB. You may need this if your system has + a lot of RAM, and you need to able to allocate very large + contiguous chunks. If unsure, say N. + +choice + prompt "RAM size" + default AUTO + +config RAMAUTO + bool "AUTO" + ---help--- + Configure the RAM size on your platform. Many platforms can auto + detect this, on those choose the AUTO option. Otherwise set the + RAM size you intend using. + +config RAM4MB + bool "4MiB" + help + Set RAM size to be 4MiB. + +config RAM4MB + bool "4MiB" + help + Set RAM size to be 4MiB. + +config RAM8MB + bool "8MiB" + help + Set RAM size to be 8MiB. + +config RAM16MB + bool "16MiB" + help + Set RAM size to be 16MiB. + +config RAM32MB + bool "32MiB" + help + Set RAM size to be 32MiB. + +endchoice + +choice + prompt "RAM bus width" + default RAMAUTOBIT + +config RAMAUTOBIT + bool "AUTO" + ---help--- + Select the physical RAM data bus size. Not needed on most platforms, + so you can generally choose AUTO. + +config RAM8BIT + bool "8bit" + help + Configure RAM bus to be 8 bits wide. + +config RAM16BIT + bool "16bit" + help + Configure RAM bus to be 16 bits wide. + +config RAM32BIT + bool "32bit" + help + Configure RAM bus to be 32 bits wide. + +endchoice + +choice + prompt "Kernel executes from" + ---help--- + Choose the memory type that the kernel will be running in. + +config RAMKERNEL + bool "RAM" + help + The kernel will be resident in RAM when running. + +config ROMKERNEL + bool "ROM" + help + The kernel will be resident in FLASH/ROM when running. + +config HIMEMKERNEL + bool "HIMEM" + help + The kernel will be resident in high memory when running. + +endchoice + +endmenu + + +menu "Bus options (PCI, PCMCIA, EISA, MCA, ISA)" + +config PCI + bool "PCI support" + help + Support for PCI bus. + +config COMEMPCI + bool "CO-MEM lite PCI controller support" + depends on (M5307 || M5407) + +source "drivers/pci/Kconfig" + +config HOTPLUG + bool "Support for hot-pluggable device" + ---help--- + Say Y here if you want to plug devices into your computer while + the system is running, and be able to use them quickly. In many + cases, the devices can likewise be unplugged at any time too. + + One well known example of this is PCMCIA- or PC-cards, credit-card + size devices such as network cards, modems or hard drives which are + plugged into slots found on all modern laptop computers. Another + example, used on modern desktops as well as laptops, is USB. + + Enable HOTPLUG and KMOD, and build a modular kernel. Get agent + software (at ) and install it. + Then your kernel will automatically call out to a user mode "policy + agent" (/sbin/hotplug) to load modules and set up software needed + to use devices as you hotplug them. + +source "drivers/pcmcia/Kconfig" + +source "drivers/hotplug/Kconfig" + +endmenu + +menu "Executable file formats" + +config KCORE_AOUT + bool + default y + +config KCORE_ELF + default y + +config BINFMT_FLAT + tristate "Kernel support for flat binaries" + help + Support uClinux FLAT format binaries. + +config BINFMT_ZFLAT + bool " Enable ZFLAT support" + depends on BINFMT_FLAT + help + Supoprt FLAT format compressed binaries + +endmenu + +menu "Power management options" + +config PM + bool "Power Management support" + help + Support processor power management modes + +endmenu + + +source "drivers/mtd/Kconfig" + +source "drivers/parport/Kconfig" + +source "drivers/pnp/Kconfig" + +source "drivers/block/Kconfig" + + +menu "ATA/IDE/MFM/RLL support" + +config IDE + tristate "ATA/ATAPI/MFM/RLL device support" + ---help--- + If you say Y here, your kernel will be able to manage low cost mass + storage units such as ATA/(E)IDE and ATAPI units. The most common + cases are IDE hard drives and ATAPI CD-ROM drives. + + It only makes sense to choose this option if your board actually + has an IDE interface. If unsure, say N. + +source "drivers/ide/Kconfig" + +endmenu + + +menu "SCSI device support" + +config SCSI + tristate "SCSI device support" + help + If you want to use a SCSI hard disk, SCSI tape drive, SCSI CD-ROM or + any other SCSI device under Linux, say Y and make sure that you know + the name of your SCSI host adapter (the card inside your computer + that "speaks" the SCSI protocol, also called SCSI controller), + because you will be asked for it. + +source "drivers/scsi/Kconfig" + +endmenu + + +menu "Old CD-ROM drivers (not SCSI, not IDE)" + depends on ISA + +config CD_NO_IDESCSI + bool "Support non-SCSI/IDE/ATAPI CDROM drives" + ---help--- + If you have a CD-ROM drive that is neither SCSI nor IDE/ATAPI, say Y + here, otherwise N. Read the CD-ROM-HOWTO, available from + . + + Note that the answer to this question doesn't directly affect the + kernel: saying N will just cause the configurator to skip all + the questions about these CD-ROM drives. If you are unsure what you + have, say Y and find out whether you have one of the following + drives. + + For each of these drivers, a file Documentation/cdrom/{driver_name} + exists. Especially in cases where you do not know exactly which kind + of drive you have you should read there. Most of these drivers use a + file drivers/cdrom/{driver_name}.h where you can define your + interface parameters and switch some internal goodies. + + All these CD-ROM drivers are also usable as a module ( = code which + can be inserted in and removed from the running kernel whenever you + want). If you want to compile them as module, say M instead of Y and + read . + + If you want to use any of these CD-ROM drivers, you also have to + answer Y or M to "ISO 9660 CD-ROM file system support" below (this + answer will get "defaulted" for you if you enable any of the Linux + CD-ROM drivers). + +source "drivers/cdrom/Kconfig" + +endmenu + + +source "drivers/md/Kconfig" + +source "drivers/message/fusion/Kconfig" + +source "drivers/ieee1394/Kconfig" + +source "drivers/message/i2o/Kconfig" + +source "net/Kconfig" + + +menu "Network device support" + depends on NET + +config NETDEVICES + bool "Network device support" + ---help--- + You can say N here if you don't intend to connect your Linux box to + any other computer at all or if all your connections will be over a + telephone line with a modem either via UUCP (UUCP is a protocol to + forward mail and news between unix hosts over telephone lines; read + the UUCP-HOWTO, available from + ) or dialing up a shell + account or a BBS, even using term (term is a program which gives you + almost full Internet connectivity if you have a regular dial up + shell account on some Internet connected Unix computer. Read + ). + + You'll have to say Y if your computer contains a network card that + you want to use under Linux (make sure you know its name because you + will be asked for it and read the Ethernet-HOWTO (especially if you + plan to use more than one network card under Linux)) or if you want + to use SLIP (Serial Line Internet Protocol is the protocol used to + send Internet traffic over telephone lines or null modem cables) or + CSLIP (compressed SLIP) or PPP (Point to Point Protocol, a better + and newer replacement for SLIP) or PLIP (Parallel Line Internet + Protocol is mainly used to create a mini network by connecting the + parallel ports of two local machines) or AX.25/KISS (protocol for + sending Internet traffic over amateur radio links). + + Make sure to read the NET-3-HOWTO. Eventually, you will have to read + Olaf Kirch's excellent and free book "Network Administrator's + Guide", to be found in . If + unsure, say Y. + +source "drivers/net/Kconfig" + +source "drivers/atm/Kconfig" + +endmenu + +source "net/ax25/Kconfig" + +source "net/irda/Kconfig" + +source "drivers/isdn/Kconfig" + +source "drivers/telephony/Kconfig" + +# +# input before char - char/joystick depends on it. As does USB. +# +source "drivers/input/Kconfig" + +source "drivers/char/Kconfig" + +#source drivers/misc/Config.in +source "drivers/media/Kconfig" + +source "fs/Kconfig" + + +menu "Console drivers" + depends on VT + +config VGA_CONSOLE + bool "VGA text console" + help + Saying Y here will allow you to use Linux in text mode through a + display that complies with the generic VGA standard. Virtually + everyone wants that. + + The program SVGATextMode can be used to utilize SVGA video cards to + their full potential in text mode. Download it from + . + + If unsure, say N. + +config VIDEO_SELECT + bool "Video mode selection support" + ---help--- + This enables support for text mode selection on kernel startup. If + you want to take advantage of some high-resolution text mode your + card's BIOS offers, but the traditional Linux utilities like + SVGATextMode don't, you can say Y here and set the mode using the + "vga=" option from your boot loader (lilo or loadlin) or set + "vga=ask" which brings up a video mode menu on kernel startup. (Try + "man bootparam" or see the documentation of your boot loader about + how to pass options to the kernel.) + + Read the file for more information + about the Video mode selection support. If unsure, say N. + +source "drivers/video/Kconfig" + +endmenu + + +menu "Sound" + +config SOUND + tristate "Sound card support" + ---help--- + If you have a sound card in your computer, i.e. if it can say more + than an occasional beep, say Y. Be sure to have all the information + about your sound card and its configuration down (I/O port, + interrupt and DMA channel), because you will be asked for it. + + You want to read the Sound-HOWTO, available from + . General information about + the modular sound system is contained in the files + . The file + contains some slightly + outdated but still useful information as well. + + If you have a PnP sound card and you want to configure it at boot + time using the ISA PnP tools (read + ), then you need to + compile the sound card support as a module ( = code which can be + inserted in and removed from the running kernel whenever you want) + and load that module after the PnP configuration is finished. To do + this, say M here and read as well + as ; the module will be + called soundcore.o. + + I'm told that even without a sound card, you can make your computer + say more than an occasional beep, by programming the PC speaker. + Kernel patches and supporting utilities to do that are in the pcsp + package, available at . + +source "sound/Kconfig" + +endmenu + +source "drivers/usb/Kconfig" + +source "net/bluetooth/Kconfig" + + +menu "Kernel hacking" + +config FULLDEBUG + bool "Full Symbolic/Source Debugging support" + help + Enable debuging symbols on kernel build. + +config MAGIC_SYSRQ + bool "Magic SysRq key" + help + Enables console device to interprent special characters as + commands to dump state information. + +config HIGHPROFILE + bool "Use fast second timer for profiling" + help + Use a fast secondary clock to produce profiling information. + +config DUMPTOFLASH + bool "Panic/Dump to FLASH" + depends on COLDFIRE + help + Dump any panic of trap output into a flash memory segment + for later analysis. + +config NO_KERNEL_MSG + bool "Suppress Kernel BUG Messages" + help + Do not output any debug BUG messages within the kernel. + +config BDM_DISABLE + bool "Disable BDM signals" + depends on (EXPERIMENTAL && COLDFIRE) + help + Disable the CPU's BDM signals. + +endmenu + +source "security/Kconfig" + +source "crypto/Kconfig" + +source "lib/Kconfig" + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/kernel/asm-offsets.c linux.2.5.45-ac1/arch/m68knommu/kernel/asm-offsets.c --- linux.2.5.45/arch/m68knommu/kernel/asm-offsets.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/kernel/asm-offsets.c 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,85 @@ +/* + * This program is used to generate definitions needed by + * assembly language modules. + * + * We use the technique used in the OSF Mach kernel code: + * generate asm statements containing #defines, + * compile this file to assembler, and then extract the + * #defines from the assembly-language output. + */ + +#include +#include +#include +#include +#include +#include + +#define DEFINE(sym, val) \ + asm volatile("\n->" #sym " %0 " #val : : "i" (val)) + +#define BLANK() asm volatile("\n->" : : ) + +int main(void) +{ + /* offsets into the task struct */ + DEFINE(TASK_STATE, offsetof(struct task_struct, state)); + DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags)); + DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace)); + DEFINE(TASK_BLOCKED, offsetof(struct task_struct, blocked)); + DEFINE(TASK_THREAD, offsetof(struct task_struct, thread)); + DEFINE(TASK_THREAD_INFO, offsetof(struct task_struct, thread_info)); + DEFINE(TASK_MM, offsetof(struct task_struct, mm)); + DEFINE(TASK_ACTIVE_MM, offsetof(struct task_struct, active_mm)); + + /* offsets into the irq_cpustat_t struct */ + DEFINE(CPUSTAT_SOFTIRQ_PENDING, offsetof(irq_cpustat_t, __softirq_pending)); + + /* offsets into the thread struct */ + DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp)); + DEFINE(THREAD_USP, offsetof(struct thread_struct, usp)); + DEFINE(THREAD_SR, offsetof(struct thread_struct, sr)); + DEFINE(THREAD_FS, offsetof(struct thread_struct, fs)); + DEFINE(THREAD_CRP, offsetof(struct thread_struct, crp)); + DEFINE(THREAD_ESP0, offsetof(struct thread_struct, esp0)); + DEFINE(THREAD_FPREG, offsetof(struct thread_struct, fp)); + DEFINE(THREAD_FPCNTL, offsetof(struct thread_struct, fpcntl)); + DEFINE(THREAD_FPSTATE, offsetof(struct thread_struct, fpstate)); + + /* offsets into the pt_regs */ + DEFINE(PT_D0, offsetof(struct pt_regs, d0)); + DEFINE(PT_ORIG_D0, offsetof(struct pt_regs, orig_d0)); + DEFINE(PT_D1, offsetof(struct pt_regs, d1)); + DEFINE(PT_D2, offsetof(struct pt_regs, d2)); + DEFINE(PT_D3, offsetof(struct pt_regs, d3)); + DEFINE(PT_D4, offsetof(struct pt_regs, d4)); + DEFINE(PT_D5, offsetof(struct pt_regs, d5)); + DEFINE(PT_A0, offsetof(struct pt_regs, a0)); + DEFINE(PT_A1, offsetof(struct pt_regs, a1)); + DEFINE(PT_A2, offsetof(struct pt_regs, a2)); + DEFINE(PT_PC, offsetof(struct pt_regs, pc)); + DEFINE(PT_SR, offsetof(struct pt_regs, sr)); + /* bitfields are a bit difficult */ + DEFINE(PT_VECTOR, offsetof(struct pt_regs, pc) + 4); + +#ifndef CONFIG_COLDFIRE + /* offsets into the irq_handler struct */ + DEFINE(IRQ_HANDLER, offsetof(struct irq_node, handler)); + DEFINE(IRQ_DEVID, offsetof(struct irq_node, dev_id)); + DEFINE(IRQ_NEXT, offsetof(struct irq_node, next)); +#endif + + /* offsets into the kernel_stat struct */ + DEFINE(STAT_IRQ, offsetof(struct kernel_stat, irqs)); + + /* signal defines */ + DEFINE(SIGSEGV, SIGSEGV); + DEFINE(SEGV_MAPERR, SEGV_MAPERR); + DEFINE(SIGTRAP, SIGTRAP); + DEFINE(TRAP_TRACE, TRAP_TRACE); + + DEFINE(PT_PTRACED, PT_PTRACED); + DEFINE(PT_DTRACE, PT_DTRACE); + + return 0; +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/kernel/comempci.c linux.2.5.45-ac1/arch/m68knommu/kernel/comempci.c --- linux.2.5.45/arch/m68knommu/kernel/comempci.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/kernel/comempci.c 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,1171 @@ +/*****************************************************************************/ + +/* + * comemlite.c -- PCI access code for embedded CO-MEM Lite PCI controller. + * + * (C) Copyright 1999-2002, Greg Ungerer (gerg@snapgear.com). + * (C) Copyright 2000, Lineo (www.lineo.com) + */ + +/*****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_eLIA +#include +#endif + +/*****************************************************************************/ + +/* + * Debug configuration defines. DEBUGRES sets debugging output for + * the resource allocation phase. DEBUGPCI traces on pcibios_ function + * calls, and DEBUGIO traces all accesses to devices on the PCI bus. + */ +/*#define DEBUGRES 1*/ +/*#define DEBUGPCI 1*/ +/*#define DEBUGIO 1*/ + +/*****************************************************************************/ + +/* + * PCI markers for bus present and active slots. + */ +int pci_bus_is_present = 0; +unsigned long pci_slotmask = 0; + +/* + * We may or may not need to swap the bytes of PCI bus tranfers. + * The endianess is re-roder automatically by the CO-MEM, but it + * will get the wrong byte order for a pure data stream. + */ +#define pci_byteswap 0 + + +/* + * Resource tracking. The CO-MEM part creates a virtual address + * space that all the PCI devices live in - it is not in any way + * directly mapped into the ColdFire address space. So we can + * really assign any resources we like to devices, as long as + * they do not clash with other PCI devices. + */ +unsigned int pci_iobase = 0x100; /* Arbitary start address */ +unsigned int pci_membase = 0x00010000; /* Arbitary start address */ + +#define PCI_MINIO 0x100 /* 256 byte minimum I/O */ +#define PCI_MINMEM 0x00010000 /* 64k minimum chunk */ + +/* + * The CO-MEM's shared memory segment is visible inside the PCI + * memory address space. We need to keep track of the address that + * this is mapped at, to setup the bus masters pointers. + */ +unsigned int pci_shmemaddr; + +/*****************************************************************************/ + +void pci_interrupt(int irq, void *id, struct pt_regs *fp); + +/*****************************************************************************/ + +/* + * Some platforms have custom ways of reseting the PCI bus. + */ + +void pci_resetbus(void) +{ +#ifdef CONFIG_eLIA + int i; + +#ifdef DEBUGPCI + printk("pci_resetbus()\n"); +#endif + + *((volatile unsigned short *) (MCF_MBAR+MCFSIM_PADDR)) |= eLIA_PCIRESET; + for (i = 0; (i < 1000); i++) { + *((volatile unsigned short *) (MCF_MBAR + MCFSIM_PADAT)) = + (ppdata | eLIA_PCIRESET); + } + + + *((volatile unsigned short *) (MCF_MBAR + MCFSIM_PADAT)) = ppdata; +#endif +} + +/*****************************************************************************/ + +int pcibios_assignres(int slot) +{ + volatile unsigned long *rp; + volatile unsigned char *ip; + unsigned int idsel, addr, val, align, i; + int bar; + +#ifdef DEBUGPCI + printk("pcibios_assignres(slot=%x)\n", slot); +#endif + + rp = (volatile unsigned long *) COMEM_BASE; + idsel = COMEM_DA_ADDR(0x1 << (slot + 16)); + + /* Try to assign resource to each BAR */ + for (bar = 0; (bar < 6); bar++) { + addr = COMEM_PCIBUS + PCI_BASE_ADDRESS_0 + (bar * 4); + rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGRD | idsel; + val = rp[LREG(addr)]; +#ifdef DEBUGRES + printk("-----------------------------------" + "-------------------------------------\n"); + printk("BAR[%d]: read=%08x ", bar, val); +#endif + + rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGWR | idsel; + rp[LREG(addr)] = 0xffffffff; + + rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGRD | idsel; + val = rp[LREG(addr)]; +#ifdef DEBUGRES + printk("write=%08x ", val); +#endif + if (val == 0) { +#ifdef DEBUGRES + printk("\n"); +#endif + continue; + } + + /* Determine space required by BAR */ + /* FIXME: this should go backwords from 0x80000000... */ + for (i = 0; (i < 32); i++) { + if ((0x1 << i) & (val & 0xfffffffc)) + break; + } + +#ifdef DEBUGRES + printk("size=%08x(%d)\n", (0x1 << i), i); +#endif + i = 0x1 << i; + + /* Assign a resource */ + if (val & PCI_BASE_ADDRESS_SPACE_IO) { + if (i < PCI_MINIO) + i = PCI_MINIO; +#ifdef DEBUGRES + printk("BAR[%d]: IO size=%08x iobase=%08x\n", + bar, i, pci_iobase); +#endif + if (i > 0xffff) { + /* Invalid size?? */ + val = 0 | PCI_BASE_ADDRESS_SPACE_IO; +#ifdef DEBUGRES + printk("BAR[%d]: too big for IO??\n", bar); +#endif + } else { + /* Check for un-alignment */ + if ((align = pci_iobase % i)) + pci_iobase += (i - align); + val = pci_iobase | PCI_BASE_ADDRESS_SPACE_IO; + pci_iobase += i; + } + } else { + if (i < PCI_MINMEM) + i = PCI_MINMEM; +#ifdef DEBUGRES + printk("BAR[%d]: MEMORY size=%08x membase=%08x\n", + bar, i, pci_membase); +#endif + /* Check for un-alignment */ + if ((align = pci_membase % i)) + pci_membase += (i - align); + val = pci_membase | PCI_BASE_ADDRESS_SPACE_MEMORY; + pci_membase += i; + } + + /* Write resource back into BAR register */ + rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGWR | idsel; + rp[LREG(addr)] = val; +#ifdef DEBUGRES + printk("BAR[%d]: assigned bar=%08x\n", bar, val); +#endif + } + +#ifdef DEBUGRES + printk("-----------------------------------" + "-------------------------------------\n"); +#endif + + /* Assign IRQ if one is wanted... */ + ip = (volatile unsigned char *) (COMEM_BASE + COMEM_PCIBUS); + rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGRD | idsel; + + addr = (PCI_INTERRUPT_PIN & 0xfc) + (~PCI_INTERRUPT_PIN & 0x03); + if (ip[addr]) { + rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGWR | idsel; + addr = (PCI_INTERRUPT_LINE & 0xfc)+(~PCI_INTERRUPT_LINE & 0x03); + ip[addr] = 25; +#ifdef DEBUGRES + printk("IRQ LINE=25\n"); +#endif + } + + return(0); +} + +/*****************************************************************************/ + +int pcibios_enable(int slot) +{ + volatile unsigned long *rp; + volatile unsigned short *wp; + unsigned int idsel, addr; + unsigned short cmd; + +#ifdef DEBUGPCI + printk("pcibios_enbale(slot=%x)\n", slot); +#endif + + rp = (volatile unsigned long *) COMEM_BASE; + wp = (volatile unsigned short *) COMEM_BASE; + idsel = COMEM_DA_ADDR(0x1 << (slot + 16)); + + /* Get current command settings */ + addr = COMEM_PCIBUS + PCI_COMMAND; + addr = (addr & ~0x3) + (~addr & 0x02); + rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGRD | idsel; + cmd = wp[WREG(addr)]; + /*val = ((val & 0xff) << 8) | ((val >> 8) & 0xff);*/ + + /* Enable I/O and memory accesses to this device */ + rp[LREG(COMEM_DAHBASE)] = COMEM_DA_CFGWR | idsel; + cmd |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; + wp[WREG(addr)] = cmd; + + return(0); +} + +/*****************************************************************************/ + +unsigned long pcibios_init(unsigned long mem_start, unsigned long mem_end) +{ + volatile unsigned long *rp; + unsigned long sel, id; + int slot; + +#ifdef DEBUGPCI + printk("pcibios_init()\n"); +#endif + + pci_resetbus(); + + /* + * Do some sort of basic check to see if the CO-MEM part + * is present... This works ok, but I think we really need + * something better... + */ + rp = (volatile unsigned long *) COMEM_BASE; + if ((rp[LREG(COMEM_LBUSCFG)] & 0xff) != 0x50) { + printk("PCI: no PCI bus present\n"); + return(mem_start); + } + +#ifdef COMEM_BRIDGEDEV + /* + * Setup the PCI bridge device first. It needs resources too, + * so that bus masters can get to its shared memory. + */ + slot = COMEM_BRIDGEDEV; + sel = COMEM_DA_CFGRD | COMEM_DA_ADDR(0x1 << (slot + 16)); + rp[LREG(COMEM_DAHBASE)] = sel; + rp[LREG(COMEM_PCIBUS)] = 0; /* Clear bus */ + id = rp[LREG(COMEM_PCIBUS)]; + if ((id == 0) || ((id & 0xffff0000) == (sel & 0xffff0000))) { + printk("PCI: no PCI bus bridge present\n"); + return(mem_start); + } + + printk("PCI: bridge device at slot=%d id=%08x\n", slot, (int) id); + pci_slotmask |= 0x1 << slot; + pci_shmemaddr = pci_membase; + pcibios_assignres(slot); + pcibios_enable(slot); +#endif + + pci_bus_is_present = 1; + + /* + * Do a quick scan of the PCI bus and see what is here. + */ + for (slot = COMEM_MINDEV; (slot <= COMEM_MAXDEV); slot++) { + sel = COMEM_DA_CFGRD | COMEM_DA_ADDR(0x1 << (slot + 16)); + rp[LREG(COMEM_DAHBASE)] = sel; + rp[LREG(COMEM_PCIBUS)] = 0; /* Clear bus */ + id = rp[LREG(COMEM_PCIBUS)]; + if ((id != 0) && ((id & 0xffff0000) != (sel & 0xffff0000))) { + printk("PCI: slot=%d id=%08x\n", slot, (int) id); + pci_slotmask |= 0x1 << slot; + pcibios_assignres(slot); + pcibios_enable(slot); + } + } + + /* Get PCI irq for local vectoring */ + if (request_irq(COMEM_IRQ, pci_interrupt, 0, "PCI bridge", NULL)) { + printk("PCI: failed to acquire interrupt %d\n", COMEM_IRQ); + } else { + mcf_autovector(COMEM_IRQ); + } + + return(mem_start); +} + +/*****************************************************************************/ + +unsigned long pcibios_fixup(unsigned long mem_start, unsigned long mem_end) +{ + return(mem_start); +} + +/*****************************************************************************/ + +int pcibios_present(void) +{ + return(pci_bus_is_present); +} + +/*****************************************************************************/ + +int pcibios_read_config_dword(unsigned char bus, unsigned char dev, + unsigned char offset, unsigned int *val) +{ + volatile unsigned long *rp; + unsigned long idsel, fnsel; + +#ifdef DEBUGPCI + printk("pcibios_read_config_dword(bus=%x,dev=%x,offset=%x,val=%x)\n", + bus, dev, offset, val); +#endif + + if (bus || ((pci_slotmask & (0x1 << PCI_SLOT(dev))) == 0)) { + *val = 0xffffffff; + return(PCIBIOS_SUCCESSFUL); + } + + rp = (volatile unsigned long *) COMEM_BASE; + idsel = COMEM_DA_CFGRD | COMEM_DA_ADDR(0x1 << ((dev >> 3) + 16)); + fnsel = (dev & 0x7) << 8; + + rp[LREG(COMEM_DAHBASE)] = idsel; + *val = rp[LREG(COMEM_PCIBUS + (offset & 0xfc) + fnsel)]; + +#if 1 + /* If we get back what we wrote, then nothing there */ + /* This is pretty dodgy, but, hey, what else do we do?? */ + if (!offset && (*val == ((idsel & 0xfffff000) | (offset & 0x00000fff)))) + *val = 0xffffffff; +#endif + + return(PCIBIOS_SUCCESSFUL); +} + +/*****************************************************************************/ + +int pcibios_read_config_word(unsigned char bus, unsigned char dev, + unsigned char offset, unsigned short *val) +{ + volatile unsigned long *rp; + volatile unsigned short *bp; + unsigned long idsel, fnsel; + unsigned char swapoffset; + +#ifdef DEBUGPCI + printk("pcibios_read_config_word(bus=%x,dev=%x,offset=%x)\n", + bus, dev, offset); +#endif + + if (bus || ((pci_slotmask & (0x1 << PCI_SLOT(dev))) == 0)) { + *val = 0xffff; + return(PCIBIOS_SUCCESSFUL); + } + + rp = (volatile unsigned long *) COMEM_BASE; + bp = (volatile unsigned short *) COMEM_BASE; + idsel = COMEM_DA_CFGRD | COMEM_DA_ADDR(0x1 << ((dev >> 3) + 16)); + fnsel = (dev & 0x7) << 8; + swapoffset = (offset & 0xfc) + (~offset & 0x02); + + rp[LREG(COMEM_DAHBASE)] = idsel; + *val = bp[WREG(COMEM_PCIBUS + swapoffset + fnsel)]; + + return(PCIBIOS_SUCCESSFUL); +} + +/*****************************************************************************/ + +int pcibios_read_config_byte(unsigned char bus, unsigned char dev, + unsigned char offset, unsigned char *val) +{ + volatile unsigned long *rp; + volatile unsigned char *bp; + unsigned long idsel, fnsel; + unsigned char swapoffset; + +#ifdef DEBUGPCI + printk("pcibios_read_config_byte(bus=%x,dev=%x,offset=%x)\n", + bus, dev, offset); +#endif + + if (bus || ((pci_slotmask & (0x1 << PCI_SLOT(dev))) == 0)) { + *val = 0xff; + return(PCIBIOS_SUCCESSFUL); + } + + rp = (volatile unsigned long *) COMEM_BASE; + bp = (volatile unsigned char *) COMEM_BASE; + idsel = COMEM_DA_CFGRD | COMEM_DA_ADDR(0x1 << ((dev >> 3) + 16)); + fnsel = (dev & 0x7) << 8; + swapoffset = (offset & 0xfc) + (~offset & 0x03); + + rp[LREG(COMEM_DAHBASE)] = idsel; + *val = bp[(COMEM_PCIBUS + swapoffset + fnsel)]; + + return(PCIBIOS_SUCCESSFUL); +} + +/*****************************************************************************/ + +int pcibios_write_config_dword(unsigned char bus, unsigned char dev, + unsigned char offset, unsigned int val) +{ + volatile unsigned long *rp; + unsigned long idsel, fnsel; + +#ifdef DEBUGPCI + printk("pcibios_write_config_dword(bus=%x,dev=%x,offset=%x,val=%x)\n", + bus, dev, offset, val); +#endif + + if (bus || ((pci_slotmask & (0x1 << PCI_SLOT(dev))) == 0)) + return(PCIBIOS_SUCCESSFUL); + + rp = (volatile unsigned long *) COMEM_BASE; + idsel = COMEM_DA_CFGRD | COMEM_DA_ADDR(0x1 << ((dev >> 3) + 16)); + fnsel = (dev & 0x7) << 8; + + rp[LREG(COMEM_DAHBASE)] = idsel; + rp[LREG(COMEM_PCIBUS + (offset & 0xfc) + fnsel)] = val; + return(PCIBIOS_SUCCESSFUL); +} + +/*****************************************************************************/ + +int pcibios_write_config_word(unsigned char bus, unsigned char dev, + unsigned char offset, unsigned short val) +{ + + volatile unsigned long *rp; + volatile unsigned short *bp; + unsigned long idsel, fnsel; + unsigned char swapoffset; + +#ifdef DEBUGPCI + printk("pcibios_write_config_word(bus=%x,dev=%x,offset=%x,val=%x)\n", + bus, dev, offset, val); +#endif + + if (bus || ((pci_slotmask & (0x1 << PCI_SLOT(dev))) == 0)) + return(PCIBIOS_SUCCESSFUL); + + rp = (volatile unsigned long *) COMEM_BASE; + bp = (volatile unsigned short *) COMEM_BASE; + idsel = COMEM_DA_CFGRD | COMEM_DA_ADDR(0x1 << ((dev >> 3) + 16)); + fnsel = (dev & 0x7) << 8; + swapoffset = (offset & 0xfc) + (~offset & 0x02); + + rp[LREG(COMEM_DAHBASE)] = idsel; + bp[WREG(COMEM_PCIBUS + swapoffset + fnsel)] = val; + return(PCIBIOS_SUCCESSFUL); +} + +/*****************************************************************************/ + +int pcibios_write_config_byte(unsigned char bus, unsigned char dev, + unsigned char offset, unsigned char val) +{ + volatile unsigned long *rp; + volatile unsigned char *bp; + unsigned long idsel, fnsel; + unsigned char swapoffset; + +#ifdef DEBUGPCI + printk("pcibios_write_config_byte(bus=%x,dev=%x,offset=%x,val=%x)\n", + bus, dev, offset, val); +#endif + + if (bus || ((pci_slotmask & (0x1 << PCI_SLOT(dev))) == 0)) + return(PCIBIOS_SUCCESSFUL); + + rp = (volatile unsigned long *) COMEM_BASE; + bp = (volatile unsigned char *) COMEM_BASE; + idsel = COMEM_DA_CFGRD | COMEM_DA_ADDR(0x1 << ((dev >> 3) + 16)); + fnsel = (dev & 0x7) << 8; + swapoffset = (offset & 0xfc) + (~offset & 0x03); + + rp[LREG(COMEM_DAHBASE)] = idsel; + bp[(COMEM_PCIBUS + swapoffset + fnsel)] = val; + return(PCIBIOS_SUCCESSFUL); +} + +/*****************************************************************************/ + +int pcibios_find_device(unsigned short vendor, unsigned short devid, + unsigned short index, unsigned char *bus, unsigned char *dev) +{ + unsigned int vendev, val; + unsigned char devnr; + +#ifdef DEBUGPCI + printk("pcibios_find_device(vendor=%04x,devid=%04x,index=%d)\n", + vendor, devid, index); +#endif + + if (vendor == 0xffff) + return(PCIBIOS_BAD_VENDOR_ID); + + vendev = (devid << 16) | vendor; + for (devnr = 0; (devnr < 32); devnr++) { + pcibios_read_config_dword(0, devnr, PCI_VENDOR_ID, &val); + if (vendev == val) { + if (index-- == 0) { + *bus = 0; + *dev = devnr; + return(PCIBIOS_SUCCESSFUL); + } + } + } + + return(PCIBIOS_DEVICE_NOT_FOUND); +} + +/*****************************************************************************/ + +int pcibios_find_class(unsigned int class, unsigned short index, + unsigned char *bus, unsigned char *dev) +{ + unsigned int val; + unsigned char devnr; + +#ifdef DEBUGPCI + printk("pcibios_find_class(class=%04x,index=%d)\n", class, index); +#endif + + /* FIXME: this ignores multi-function devices... */ + for (devnr = 0; (devnr < 128); devnr += 8) { + pcibios_read_config_dword(0, devnr, PCI_CLASS_REVISION, &val); + if ((val >> 8) == class) { + if (index-- == 0) { + *bus = 0; + *dev = devnr; + return(PCIBIOS_SUCCESSFUL); + } + } + } + + return(PCIBIOS_DEVICE_NOT_FOUND); +} + +/*****************************************************************************/ + +/* + * Local routines to interrcept the standard I/O and vector handling + * code. Don't include this 'till now - initialization code above needs + * access to the real code too. + */ +#include + +/*****************************************************************************/ + +void pci_outb(unsigned char val, unsigned int addr) +{ + volatile unsigned long *rp; + volatile unsigned char *bp; + +#ifdef DEBUGIO + printk("pci_outb(val=%02x,addr=%x)\n", val, addr); +#endif + + rp = (volatile unsigned long *) COMEM_BASE; + bp = (volatile unsigned char *) COMEM_BASE; + rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IOWR | COMEM_DA_ADDR(addr); + addr = (addr & ~0x3) + (~addr & 0x03); + bp[(COMEM_PCIBUS + COMEM_DA_OFFSET(addr))] = val; +} + +/*****************************************************************************/ + +void pci_outw(unsigned short val, unsigned int addr) +{ + volatile unsigned long *rp; + volatile unsigned short *sp; + +#ifdef DEBUGIO + printk("pci_outw(val=%04x,addr=%x)", val, addr); +#endif + + rp = (volatile unsigned long *) COMEM_BASE; + sp = (volatile unsigned short *) COMEM_BASE; + rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IOWR | COMEM_DA_ADDR(addr); + addr = (addr & ~0x3) + (~addr & 0x02); + if (pci_byteswap) + val = ((val & 0xff) << 8) | ((val >> 8) & 0xff); + sp[WREG(COMEM_PCIBUS + COMEM_DA_OFFSET(addr))] = val; +} + +/*****************************************************************************/ + +void pci_outl(unsigned int val, unsigned int addr) +{ + volatile unsigned long *rp; + volatile unsigned int *lp; + +#ifdef DEBUGIO + printk("pci_outl(val=%08x,addr=%x)\n", val, addr); +#endif + + rp = (volatile unsigned long *) COMEM_BASE; + lp = (volatile unsigned int *) COMEM_BASE; + rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IOWR | COMEM_DA_ADDR(addr); + + if (pci_byteswap) + val = (val << 24) | ((val & 0x0000ff00) << 8) | + ((val & 0x00ff0000) >> 8) | (val >> 24); + + lp[LREG(COMEM_PCIBUS + COMEM_DA_OFFSET(addr))] = val; +} + +/*****************************************************************************/ + +unsigned long pci_blmask[] = { + 0x000000e0, + 0x000000d0, + 0x000000b0, + 0x00000070 +}; + +unsigned char pci_inb(unsigned int addr) +{ + volatile unsigned long *rp; + volatile unsigned char *bp; + unsigned long r; + unsigned char val; + +#ifdef DEBUGIO + printk("pci_inb(addr=%x)", addr); +#endif + + rp = (volatile unsigned long *) COMEM_BASE; + bp = (volatile unsigned char *) COMEM_BASE; + + r = COMEM_DA_IORD | COMEM_DA_ADDR(addr) | pci_blmask[(addr & 0x3)]; + rp[LREG(COMEM_DAHBASE)] = r; + + addr = (addr & ~0x3) + (~addr & 0x3); + val = bp[(COMEM_PCIBUS + COMEM_DA_OFFSET(addr))]; + return(val); +} + +/*****************************************************************************/ + +unsigned long pci_bwmask[] = { + 0x000000c0, + 0x000000c0, + 0x00000030, + 0x00000030 +}; + +unsigned short pci_inw(unsigned int addr) +{ + volatile unsigned long *rp; + volatile unsigned short *sp; + unsigned long r; + unsigned short val; + +#ifdef DEBUGIO + printk("pci_inw(addr=%x)", addr); +#endif + + rp = (volatile unsigned long *) COMEM_BASE; + r = COMEM_DA_IORD | COMEM_DA_ADDR(addr) | pci_bwmask[(addr & 0x3)]; + rp[LREG(COMEM_DAHBASE)] = r; + + sp = (volatile unsigned short *) COMEM_BASE; + addr = (addr & ~0x3) + (~addr & 0x02); + val = sp[WREG(COMEM_PCIBUS + COMEM_DA_OFFSET(addr))]; + if (pci_byteswap) + val = ((val & 0xff) << 8) | ((val >> 8) & 0xff); +#ifdef DEBUGIO + printk("=%04x\n", val); +#endif + return(val); +} + +/*****************************************************************************/ + +unsigned int pci_inl(unsigned int addr) +{ + volatile unsigned long *rp; + volatile unsigned int *lp; + unsigned int val; + +#ifdef DEBUGIO + printk("pci_inl(addr=%x)", addr); +#endif + + rp = (volatile unsigned long *) COMEM_BASE; + lp = (volatile unsigned int *) COMEM_BASE; + rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IORD | COMEM_DA_ADDR(addr); + val = lp[LREG(COMEM_PCIBUS + COMEM_DA_OFFSET(addr))]; + + if (pci_byteswap) + val = (val << 24) | ((val & 0x0000ff00) << 8) | + ((val & 0x00ff0000) >> 8) | (val >> 24); + +#ifdef DEBUGIO + printk("=%08x\n", val); +#endif + return(val); +} + +/*****************************************************************************/ + +void pci_outsb(void *addr, void *buf, int len) +{ + volatile unsigned long *rp; + volatile unsigned char *bp; + unsigned char *dp = (unsigned char *) buf; + unsigned int a = (unsigned int) addr; + +#ifdef DEBUGIO + printk("pci_outsb(addr=%x,buf=%x,len=%d)\n", (int)addr, (int)buf, len); +#endif + + rp = (volatile unsigned long *) COMEM_BASE; + rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IOWR | COMEM_DA_ADDR(a); + + a = (a & ~0x3) + (~a & 0x03); + bp = (volatile unsigned char *) + (COMEM_BASE + COMEM_PCIBUS + COMEM_DA_OFFSET(a)); + + while (len--) + *bp = *dp++; +} + +/*****************************************************************************/ + +void pci_outsw(void *addr, void *buf, int len) +{ + volatile unsigned long *rp; + volatile unsigned short *wp; + unsigned short w, *dp = (unsigned short *) buf; + unsigned int a = (unsigned int) addr; + +#ifdef DEBUGIO + printk("pci_outsw(addr=%x,buf=%x,len=%d)\n", (int)addr, (int)buf, len); +#endif + + rp = (volatile unsigned long *) COMEM_BASE; + rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IOWR | COMEM_DA_ADDR(a); + + a = (a & ~0x3) + (~a & 0x2); + wp = (volatile unsigned short *) + (COMEM_BASE + COMEM_PCIBUS + COMEM_DA_OFFSET(a)); + + while (len--) { + w = *dp++; + if (pci_byteswap) + w = ((w & 0xff) << 8) | ((w >> 8) & 0xff); + *wp = w; + } +} + +/*****************************************************************************/ + +void pci_outsl(void *addr, void *buf, int len) +{ + volatile unsigned long *rp; + volatile unsigned long *lp; + unsigned long l, *dp = (unsigned long *) buf; + unsigned int a = (unsigned int) addr; + +#ifdef DEBUGIO + printk("pci_outsl(addr=%x,buf=%x,len=%d)\n", (int)addr, (int)buf, len); +#endif + + rp = (volatile unsigned long *) COMEM_BASE; + rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IOWR | COMEM_DA_ADDR(a); + + lp = (volatile unsigned long *) + (COMEM_BASE + COMEM_PCIBUS + COMEM_DA_OFFSET(a)); + + while (len--) { + l = *dp++; + if (pci_byteswap) + l = (l << 24) | ((l & 0x0000ff00) << 8) | + ((l & 0x00ff0000) >> 8) | (l >> 24); + *lp = l; + } +} + +/*****************************************************************************/ + +void pci_insb(void *addr, void *buf, int len) +{ + volatile unsigned long *rp; + volatile unsigned char *bp; + unsigned char *dp = (unsigned char *) buf; + unsigned int a = (unsigned int) addr; + +#ifdef DEBUGIO + printk("pci_insb(addr=%x,buf=%x,len=%d)\n", (int)addr, (int)buf, len); +#endif + + rp = (volatile unsigned long *) COMEM_BASE; + rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IORD | COMEM_DA_ADDR(a); + + a = (a & ~0x3) + (~a & 0x03); + bp = (volatile unsigned char *) + (COMEM_BASE + COMEM_PCIBUS + COMEM_DA_OFFSET(a)); + + while (len--) + *dp++ = *bp; +} + +/*****************************************************************************/ + +void pci_insw(void *addr, void *buf, int len) +{ + volatile unsigned long *rp; + volatile unsigned short *wp; + unsigned short w, *dp = (unsigned short *) buf; + unsigned int a = (unsigned int) addr; + +#ifdef DEBUGIO + printk("pci_insw(addr=%x,buf=%x,len=%d)\n", (int)addr, (int)buf, len); +#endif + + rp = (volatile unsigned long *) COMEM_BASE; + rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IORD | COMEM_DA_ADDR(a); + + a = (a & ~0x3) + (~a & 0x2); + wp = (volatile unsigned short *) + (COMEM_BASE + COMEM_PCIBUS + COMEM_DA_OFFSET(a)); + + while (len--) { + w = *wp; + if (pci_byteswap) + w = ((w & 0xff) << 8) | ((w >> 8) & 0xff); + *dp++ = w; + } +} + +/*****************************************************************************/ + +void pci_insl(void *addr, void *buf, int len) +{ + volatile unsigned long *rp; + volatile unsigned long *lp; + unsigned long l, *dp = (unsigned long *) buf; + unsigned int a = (unsigned int) addr; + +#ifdef DEBUGIO + printk("pci_insl(addr=%x,buf=%x,len=%d)\n", (int)addr, (int)buf, len); +#endif + + rp = (volatile unsigned long *) COMEM_BASE; + rp[LREG(COMEM_DAHBASE)] = COMEM_DA_IORD | COMEM_DA_ADDR(a); + + lp = (volatile unsigned long *) + (COMEM_BASE + COMEM_PCIBUS + COMEM_DA_OFFSET(a)); + + while (len--) { + l = *lp; + if (pci_byteswap) + l = (l << 24) | ((l & 0x0000ff00) << 8) | + ((l & 0x00ff0000) >> 8) | (l >> 24); + *dp++ = l; + } +} + +/*****************************************************************************/ + +struct pci_localirqlist { + void (*handler)(int, void *, struct pt_regs *); + const char *device; + void *dev_id; +}; + +struct pci_localirqlist pci_irqlist[COMEM_MAXPCI]; + +/*****************************************************************************/ + +int pci_request_irq(unsigned int irq, + void (*handler)(int, void *, struct pt_regs *), + unsigned long flags, const char *device, void *dev_id) +{ + int i; + +#ifdef DEBUGIO + printk("pci_request_irq(irq=%d,handler=%x,flags=%x,device=%s," + "dev_id=%x)\n", irq, (int) handler, (int) flags, device, + (int) dev_id); +#endif + + /* Check if this interrupt handler is already lodged */ + for (i = 0; (i < COMEM_MAXPCI); i++) { + if (pci_irqlist[i].handler == handler) + return(0); + } + + /* Find a free spot to put this handler */ + for (i = 0; (i < COMEM_MAXPCI); i++) { + if (pci_irqlist[i].handler == 0) { + pci_irqlist[i].handler = handler; + pci_irqlist[i].device = device; + pci_irqlist[i].dev_id = dev_id; + return(0); + } + } + + /* Couldn't fit?? */ + return(1); +} + +/*****************************************************************************/ + +void pci_free_irq(unsigned int irq, void *dev_id) +{ + int i; + +#ifdef DEBUGIO + printk("pci_free_irq(irq=%d,dev_id=%x)\n", irq, (int) dev_id); +#endif + + if (dev_id == (void *) NULL) + return; + + /* Check if this interrupt handler is lodged */ + for (i = 0; (i < COMEM_MAXPCI); i++) { + if (pci_irqlist[i].dev_id == dev_id) { + pci_irqlist[i].handler = NULL; + pci_irqlist[i].device = NULL; + pci_irqlist[i].dev_id = NULL; + break; + } + } +} + +/*****************************************************************************/ + +void pci_interrupt(int irq, void *id, struct pt_regs *fp) +{ + int i; + +#ifdef DEBUGIO + printk("pci_interrupt(irq=%d,id=%x,fp=%x)\n", irq, (int) id, (int) fp); +#endif + + for (i = 0; (i < COMEM_MAXPCI); i++) { + if (pci_irqlist[i].handler) + (*pci_irqlist[i].handler)(irq,pci_irqlist[i].dev_id,fp); + } +} + +/*****************************************************************************/ + +/* + * The shared memory region is broken up into contiguous 512 byte + * regions for easy allocation... This is not an optimal solution + * but it makes allocation and freeing regions really easy. + */ + +#define PCI_MEMSLOTSIZE 512 +#define PCI_MEMSLOTS (COMEM_SHMEMSIZE / PCI_MEMSLOTSIZE) + +char pci_shmemmap[PCI_MEMSLOTS]; + + +void *pci_bmalloc(int size) +{ + int i, j, nrslots; + +#ifdef DEBUGIO + printk("pci_bmalloc(size=%d)\n", size); +#endif + + if (size <= 0) + return((void *) NULL); + + nrslots = (size - 1) / PCI_MEMSLOTSIZE; + + for (i = 0; (i < (PCI_MEMSLOTS-nrslots)); i++) { + if (pci_shmemmap[i] == 0) { + for (j = i+1; (j < (i+nrslots)); j++) { + if (pci_shmemmap[j]) + goto restart; + } + + for (j = i; (j <= i+nrslots); j++) + pci_shmemmap[j] = 1; + break; + } +restart: + } + + return((void *) (COMEM_BASE + COMEM_SHMEM + (i * PCI_MEMSLOTSIZE))); +} + +/*****************************************************************************/ + +void pci_bmfree(void *mp, int size) +{ + int i, j, nrslots; + +#ifdef DEBUGIO + printk("pci_bmfree(mp=%x,size=%d)\n", (int) mp, size); +#endif + + nrslots = size / PCI_MEMSLOTSIZE; + i = (((unsigned long) mp) - (COMEM_BASE + COMEM_SHMEM)) / + PCI_MEMSLOTSIZE; + + for (j = i; (j < (i+nrslots)); j++) + pci_shmemmap[j] = 0; +} + +/*****************************************************************************/ + +unsigned long pci_virt_to_bus(volatile void *address) +{ + unsigned long l; + +#ifdef DEBUGIO + printk("pci_virt_to_bus(address=%x)", (int) address); +#endif + + l = ((unsigned long) address) - COMEM_BASE; +#ifdef DEBUGIO + printk("=%x\n", (int) (l+pci_shmemaddr)); +#endif + return(l + pci_shmemaddr); +} + +/*****************************************************************************/ + +void *pci_bus_to_virt(unsigned long address) +{ + unsigned long l; + +#ifdef DEBUGIO + printk("pci_bus_to_virt(address=%x)", (int) address); +#endif + + l = address - pci_shmemaddr; +#ifdef DEBUGIO + printk("=%x\n", (int) (address + COMEM_BASE)); +#endif + return((void *) (address + COMEM_BASE)); +} + +/*****************************************************************************/ + +void pci_bmcpyto(void *dst, void *src, int len) +{ + unsigned long *dp, *sp, val; + unsigned char *dcp, *scp; + int i, j; + +#ifdef DEBUGIO + printk("pci_bmcpyto(dst=%x,src=%x,len=%d)\n", (int)dst, (int)src, len); +#endif + + dp = (unsigned long *) dst; + sp = (unsigned long *) src; + i = len >> 2; + +#if 0 + printk("DATA:"); + scp = (unsigned char *) sp; + for (i = 0; (i < len); i++) { + if ((i % 16) == 0) printk("\n%04x: ", i); + printk("%02x ", *scp++); + } + printk("\n"); +#endif + + for (j = 0; (i >= 0); i--, j++) { + val = *sp++; + val = (val << 24) | ((val & 0x0000ff00) << 8) | + ((val & 0x00ff0000) >> 8) | (val >> 24); + *dp++ = val; + } + + if (len & 0x3) { + dcp = (unsigned char *) dp; + scp = ((unsigned char *) sp) + 3; + for (i = 0; (i < (len & 0x3)); i++) + *dcp++ = *scp--; + } +} + +/*****************************************************************************/ + +void pci_bmcpyfrom(void *dst, void *src, int len) +{ + unsigned long *dp, *sp, val; + unsigned char *dcp, *scp; + int i; + +#ifdef DEBUGIO + printk("pci_bmcpyfrom(dst=%x,src=%x,len=%d)\n",(int)dst,(int)src,len); +#endif + + dp = (unsigned long *) dst; + sp = (unsigned long *) src; + i = len >> 2; + + for (; (i >= 0); i--) { + val = *sp++; + val = (val << 24) | ((val & 0x0000ff00) << 8) | + ((val & 0x00ff0000) >> 8) | (val >> 24); + *dp++ = val; + } + + if (len & 0x3) { + dcp = ((unsigned char *) dp) + 3; + scp = (unsigned char *) sp; + for (i = 0; (i < (len & 0x3)); i++) + *dcp++ = *scp--; + } + +#if 0 + printk("DATA:"); + dcp = (unsigned char *) dst; + for (i = 0; (i < len); i++) { + if ((i % 16) == 0) printk("\n%04x: ", i); + printk("%02x ", *dcp++); + } + printk("\n"); +#endif +} + +/*****************************************************************************/ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/kernel/init_task.c linux.2.5.45-ac1/arch/m68knommu/kernel/init_task.c --- linux.2.5.45/arch/m68knommu/kernel/init_task.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/kernel/init_task.c 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,37 @@ +/* + * linux/arch/m68knommu/kernel/init_task.c + */ +#include +#include +#include +#include +#include + +#include +#include + +static struct fs_struct init_fs = INIT_FS; +static struct files_struct init_files = INIT_FILES; +static struct signal_struct init_signals = INIT_SIGNALS(init_signals); +struct mm_struct init_mm = INIT_MM(init_mm); + +/* + * Initial task structure. + * + * All other task structs will be allocated on slabs in fork.c + */ +__asm__(".align 4"); +struct task_struct init_task = INIT_TASK(init_task); + + +/* + * Initial thread structure. + * + * We need to make sure that this is 8192-byte aligned due to the + * way process stacks are handled. This is done by having a special + * "init_task" linker map entry.. + */ +union thread_union init_thread_union + __attribute__((__section__(".data.init_task"))) = + { INIT_THREAD_INFO(init_task) }; + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/kernel/ints.c linux.2.5.45-ac1/arch/m68knommu/kernel/ints.c --- linux.2.5.45/arch/m68knommu/kernel/ints.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/kernel/ints.c 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,274 @@ +/* + * linux/arch/m68knommu/kernel/ints.c -- General interrupt handling code + * + * Copyright (C) 1999-2002 Greg Ungerer (gerg@snapgear.com) + * Copyright (C) 1998 D. Jeff Dionne , + * Kenneth Albanowski , + * Copyright (C) 2000 Lineo Inc. (www.lineo.com) + * + * Based on: + * + * linux/arch/m68k/kernel/ints.c -- Linux/m68k general interrupt handling code + * + * 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 + +/* + * This table stores the address info for each vector handler. + */ +irq_handler_t irq_list[SYS_IRQS]; +unsigned int *mach_kstat_irqs; + +#define NUM_IRQ_NODES 16 +static irq_node_t nodes[NUM_IRQ_NODES]; + +/* The number of spurious interrupts */ +volatile unsigned int num_spurious; + +unsigned int local_bh_count[NR_CPUS]; +unsigned int local_irq_count[NR_CPUS]; + +static void default_irq_handler(int irq, void *ptr, struct pt_regs *regs) +{ +#if 1 + printk("%s(%d): default irq handler vec=%d [0x%x]\n", + __FILE__, __LINE__, irq, irq); +#endif +} + +/* + * void init_IRQ(void) + * + * Parameters: None + * + * Returns: Nothing + * + * This function should be called during kernel startup to initialize + * the IRQ handling routines. + */ + +void __init init_IRQ(void) +{ + int i; + + for (i = 0; i < SYS_IRQS; i++) { + if (mach_default_handler) + irq_list[i].handler = (*mach_default_handler)[i]; + else + irq_list[i].handler = default_irq_handler; + irq_list[i].flags = IRQ_FLG_STD; + irq_list[i].dev_id = NULL; + irq_list[i].devname = NULL; + } + + for (i = 0; i < NUM_IRQ_NODES; i++) + nodes[i].handler = NULL; + + if (mach_init_IRQ) + mach_init_IRQ(); + + mach_kstat_irqs = &kstat.irqs[0][0]; +} + +irq_node_t *new_irq_node(void) +{ + irq_node_t *node; + short i; + + for (node = nodes, i = NUM_IRQ_NODES-1; i >= 0; node++, i--) + if (!node->handler) + return node; + + printk("new_irq_node: out of nodes\n"); + return NULL; +} + +int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), + unsigned long flags, const char *devname, void *dev_id) +{ + if (irq < 0 || irq >= NR_IRQS) { + printk("%s: Incorrect IRQ %d from %s\n", __FUNCTION__, + irq, devname); + return -ENXIO; + } + + if (!(irq_list[irq].flags & IRQ_FLG_STD)) { + if (irq_list[irq].flags & IRQ_FLG_LOCK) { + printk("%s: IRQ %d from %s is not replaceable\n", + __FUNCTION__, irq, irq_list[irq].devname); + return -EBUSY; + } + if (flags & IRQ_FLG_REPLACE) { + printk("%s: %s can't replace IRQ %d from %s\n", + __FUNCTION__, devname, irq, irq_list[irq].devname); + return -EBUSY; + } + } + +#ifdef CONFIG_COLDFIRE + if (flags & IRQ_FLG_FAST) { + extern asmlinkage void fasthandler(void); + extern void set_evector(int vecnum, void (*handler)(void)); + set_evector(irq, fasthandler); + } +#endif + + irq_list[irq].handler = handler; + irq_list[irq].flags = flags; + irq_list[irq].dev_id = dev_id; + irq_list[irq].devname = devname; + return 0; +} + +void free_irq(unsigned int irq, void *dev_id) +{ + if (irq >= NR_IRQS) { + printk("%s: Incorrect IRQ %d\n", __FUNCTION__, irq); + return; + } + + if (irq_list[irq].dev_id != dev_id) + printk("%s: Removing probably wrong IRQ %d from %s\n", + __FUNCTION__, irq, irq_list[irq].devname); + +#ifdef CONFIG_COLDFIRE + if (irq_list[irq].flags & IRQ_FLG_FAST) { + extern asmlinkage void inthandler(void); + extern void set_evector(int vecnum, void (*handler)(void)); + set_evector(irq, inthandler); + } +#endif + + if (mach_default_handler) + irq_list[irq].handler = (*mach_default_handler)[irq]; + else + irq_list[irq].handler = default_irq_handler; + irq_list[irq].flags = IRQ_FLG_STD; + irq_list[irq].dev_id = NULL; + irq_list[irq].devname = NULL; +} + + +int sys_request_irq(unsigned int irq, + void (*handler)(int, void *, struct pt_regs *), + unsigned long flags, const char *devname, void *dev_id) +{ + if (irq > IRQ7) { + printk("%s: Incorrect IRQ %d from %s\n", + __FUNCTION__, irq, devname); + return -ENXIO; + } + +#if 0 + if (!(irq_list[irq].flags & IRQ_FLG_STD)) { + if (irq_list[irq].flags & IRQ_FLG_LOCK) { + printk("%s: IRQ %d from %s is not replaceable\n", + __FUNCTION__, irq, irq_list[irq].devname); + return -EBUSY; + } + if (!(flags & IRQ_FLG_REPLACE)) { + printk("%s: %s can't replace IRQ %d from %s\n", + __FUNCTION__, devname, irq, irq_list[irq].devname); + return -EBUSY; + } + } +#endif + + irq_list[irq].handler = handler; + irq_list[irq].flags = flags; + irq_list[irq].dev_id = dev_id; + irq_list[irq].devname = devname; + return 0; +} + +void sys_free_irq(unsigned int irq, void *dev_id) +{ + if (irq > IRQ7) { + printk("%s: Incorrect IRQ %d\n", __FUNCTION__, irq); + return; + } + + if (irq_list[irq].dev_id != dev_id) + printk("%s: Removing probably wrong IRQ %d from %s\n", + __FUNCTION__, irq, irq_list[irq].devname); + + irq_list[irq].handler = (*mach_default_handler)[irq]; + irq_list[irq].flags = 0; + irq_list[irq].dev_id = NULL; + irq_list[irq].devname = NULL; +} + +/* + * Do we need these probe functions on the m68k? + * + * ... may be usefull with ISA devices + */ +unsigned long probe_irq_on (void) +{ + return 0; +} + +int probe_irq_off (unsigned long irqs) +{ + return 0; +} + +asmlinkage void process_int(unsigned long vec, struct pt_regs *fp) +{ + if (vec >= VEC_INT1 && vec <= VEC_INT7) { + vec -= VEC_SPUR; + kstat.irqs[0][vec]++; + irq_list[vec].handler(vec, irq_list[vec].dev_id, fp); + } else { + if (mach_process_int) + mach_process_int(vec, fp); + else + panic("Can't process interrupt vector %ld\n", vec); + return; + } +} + + +int show_interrupts(struct seq_file *p, void *v) +{ + int i; + + for (i = 0; i < NR_IRQS; i++) { + if (irq_list[i].flags & IRQ_FLG_STD) + continue; + + seq_printf(p, "%3d: %10u ", i, + (i ? kstat.irqs[0][i] : num_spurious)); + if (irq_list[i].flags & IRQ_FLG_LOCK) + seq_printf(p, "L "); + else + seq_printf(p, " "); + seq_printf(p, "%s\n", irq_list[i].devname); + } + + if (mach_get_irq_list) + mach_get_irq_list(p, v); + return(0); +} + +void init_irq_proc(void) +{ + /* Insert /proc/irq driver here */ +} + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/kernel/m68k_ksyms.c linux.2.5.45-ac1/arch/m68knommu/kernel/m68k_ksyms.c --- linux.2.5.45/arch/m68knommu/kernel/m68k_ksyms.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/kernel/m68k_ksyms.c 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,124 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern void dump_thread(struct pt_regs *, struct user *); +extern int dump_fpu(elf_fpregset_t *); + +/* platform dependent support */ + +EXPORT_SYMBOL(__ioremap); +EXPORT_SYMBOL(iounmap); +EXPORT_SYMBOL(dump_fpu); +EXPORT_SYMBOL(dump_thread); +EXPORT_SYMBOL(strnlen); +EXPORT_SYMBOL(strrchr); +EXPORT_SYMBOL(strstr); +EXPORT_SYMBOL(strchr); +EXPORT_SYMBOL(strcat); +EXPORT_SYMBOL(strlen); +EXPORT_SYMBOL(strcmp); +EXPORT_SYMBOL(strncmp); + +EXPORT_SYMBOL(ip_fast_csum); + +EXPORT_SYMBOL(mach_enable_irq); +EXPORT_SYMBOL(mach_disable_irq); +EXPORT_SYMBOL(kernel_thread); + +/* Networking helper routines. */ +EXPORT_SYMBOL(csum_partial_copy); + +/* The following are special because they're not called + explicitly (the C compiler generates them). Fortunately, + their interface isn't gonna change any time soon now, so + it's OK to leave it out of version control. */ +EXPORT_SYMBOL_NOVERS(memcpy); +EXPORT_SYMBOL_NOVERS(memset); +EXPORT_SYMBOL_NOVERS(memcmp); +EXPORT_SYMBOL_NOVERS(memscan); +EXPORT_SYMBOL_NOVERS(memmove); + +EXPORT_SYMBOL_NOVERS(__down_failed); +EXPORT_SYMBOL_NOVERS(__down_failed_interruptible); +EXPORT_SYMBOL_NOVERS(__down_failed_trylock); +EXPORT_SYMBOL_NOVERS(__up_wakeup); + +EXPORT_SYMBOL(get_wchan); + +/* + * libgcc functions - functions that are used internally by the + * compiler... (prototypes are not correct though, but that + * doesn't really matter since they're not versioned). + */ +extern void __gcc_bcmp(void); +extern void __ashldi3(void); +extern void __ashrdi3(void); +extern void __cmpdi2(void); +extern void __divdi3(void); +extern void __divsi3(void); +extern void __lshrdi3(void); +extern void __moddi3(void); +extern void __modsi3(void); +extern void __muldi3(void); +extern void __mulsi3(void); +extern void __negdi2(void); +extern void __ucmpdi2(void); +extern void __udivdi3(void); +extern void __udivmoddi4(void); +extern void __udivsi3(void); +extern void __umoddi3(void); +extern void __umodsi3(void); + + /* gcc lib functions */ +EXPORT_SYMBOL_NOVERS(__gcc_bcmp); +EXPORT_SYMBOL_NOVERS(__ashldi3); +EXPORT_SYMBOL_NOVERS(__ashrdi3); +EXPORT_SYMBOL_NOVERS(__cmpdi2); +EXPORT_SYMBOL_NOVERS(__divdi3); +EXPORT_SYMBOL_NOVERS(__divsi3); +EXPORT_SYMBOL_NOVERS(__lshrdi3); +EXPORT_SYMBOL_NOVERS(__moddi3); +EXPORT_SYMBOL_NOVERS(__modsi3); +EXPORT_SYMBOL_NOVERS(__muldi3); +EXPORT_SYMBOL_NOVERS(__mulsi3); +EXPORT_SYMBOL_NOVERS(__negdi2); +EXPORT_SYMBOL_NOVERS(__ucmpdi2); +EXPORT_SYMBOL_NOVERS(__udivdi3); +EXPORT_SYMBOL_NOVERS(__udivmoddi4); +EXPORT_SYMBOL_NOVERS(__udivsi3); +EXPORT_SYMBOL_NOVERS(__umoddi3); +EXPORT_SYMBOL_NOVERS(__umodsi3); + +EXPORT_SYMBOL_NOVERS(is_in_rom); + +#ifdef CONFIG_COLDFIRE +extern unsigned int *dma_device_address; +extern unsigned long dma_base_addr, _ramend; +EXPORT_SYMBOL_NOVERS(dma_base_addr); +EXPORT_SYMBOL_NOVERS(dma_device_address); +EXPORT_SYMBOL_NOVERS(_ramend); + +extern asmlinkage void trap(void); +extern void *_ramvec; +EXPORT_SYMBOL_NOVERS(trap); +EXPORT_SYMBOL_NOVERS(_ramvec); +#endif /* CONFIG_COLDFIRE */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/kernel/Makefile linux.2.5.45-ac1/arch/m68knommu/kernel/Makefile --- linux.2.5.45/arch/m68knommu/kernel/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/kernel/Makefile 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,13 @@ +# +# Makefile for arch/m68knommu/kernel. +# + +export-objs := m68k_ksyms.o + +obj-y += init_task.o ints.o m68k_ksyms.o process.o ptrace.o semaphore.o \ + setup.o signal.o syscalltable.o sys_m68k.o time.o traps.o + +obj-$(CONFIG_COMEMPCI) += comempci.o + +include $(TOPDIR)/Rules.make + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/kernel/process.c linux.2.5.45-ac1/arch/m68knommu/kernel/process.c --- linux.2.5.45/arch/m68knommu/kernel/process.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/kernel/process.c 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,450 @@ +/* + * linux/arch/m68knommu/kernel/process.c + * + * Copyright (C) 1995 Hamish Macdonald + * + * 68060 fixes by Jesper Skov + * + * uClinux changes + * Copyright (C) 2000-2002, David McCullough + */ + +/* + * This file handles the architecture-dependent parts of process handling.. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +asmlinkage void ret_from_fork(void); + + +/* + * The idle loop on an m68knommu.. + */ +void default_idle(void) +{ + while(1) { + if (need_resched()) + __asm__("stop #0x2000" : : : "cc"); + schedule(); + } +} + +void (*idle)(void) = default_idle; + +/* + * The idle thread. There's no useful work to be + * done, so just try to conserve power and have a + * low exit latency (ie sit in a loop waiting for + * somebody to say that they'd like to reschedule) + */ +void cpu_idle(void) +{ + /* endless idle loop with no priority at all */ + idle(); +} + +void machine_restart(char * __unused) +{ + if (mach_reset) + mach_reset(); + for (;;); +} + +void machine_halt(void) +{ + if (mach_halt) + mach_halt(); + for (;;); +} + +void machine_power_off(void) +{ + if (mach_power_off) + mach_power_off(); + for (;;); +} + +void show_regs(struct pt_regs * regs) +{ + printk("\n"); + printk("Format %02x Vector: %04x PC: %08lx Status: %04x %s\n", + regs->format, regs->vector, regs->pc, regs->sr, print_tainted()); + printk("ORIG_D0: %08lx D0: %08lx A2: %08lx A1: %08lx\n", + regs->orig_d0, regs->d0, regs->a2, regs->a1); + printk("A0: %08lx D5: %08lx D4: %08lx\n", + regs->a0, regs->d5, regs->d4); + printk("D3: %08lx D2: %08lx D1: %08lx\n", + regs->d3, regs->d2, regs->d1); + if (!(regs->sr & PS_S)) + printk("USP: %08lx\n", rdusp()); +} + +/* + * Create a kernel thread + */ +int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) +{ + long retval; + long clone_arg = flags | CLONE_VM; + mm_segment_t fs; + + fs = get_fs(); + set_fs(KERNEL_DS); + + __asm__ __volatile__ ( + "movel %%sp, %%d2\n\t" + "movel %5, %%d1\n\t" + "movel %1, %%d0\n\t" + "trap #0\n\t" + "cmpl %%sp, %%d2\n\t" + "jeq 1f\n\t" + "movel %3, %%sp@-\n\t" + "jsr %4@\n\t" + "movel %2, %%d0\n\t" + "trap #0\n" + "1:" + : "=d" (retval) + : "i" (__NR_clone), + "i" (__NR_exit), + "a" (arg), + "a" (fn), + "a" (clone_arg) + : "cc", "%d0", "%d1", "%d2"); + + set_fs(fs); + return retval; +} + +void flush_thread(void) +{ +#ifdef CONFIG_FPU + unsigned long zero = 0; +#endif + set_fs(USER_DS); + current->thread.fs = __USER_DS; +#ifdef CONFIG_FPU + if (!FPU_IS_EMU) + asm volatile (".chip 68k/68881\n\t" + "frestore %0@\n\t" + ".chip 68k" : : "a" (&zero)); +#endif +} + +/* + * "m68k_fork()".. By the time we get here, the + * non-volatile registers have also been saved on the + * stack. We do some ugly pointer stuff here.. (see + * also copy_thread) + */ + +asmlinkage int m68k_fork(struct pt_regs *regs) +{ + /* fork almost works, enough to trick you into looking elsewhere :-( */ + return(-EINVAL); +} + +asmlinkage int m68k_vfork(struct pt_regs *regs) +{ + struct task_struct *p; + p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0, NULL); + return IS_ERR(p) ? PTR_ERR(p) : p->pid; +} + +asmlinkage int m68k_clone(struct pt_regs *regs) +{ + unsigned long clone_flags; + unsigned long newsp; + struct task_struct *p; + + /* syscall2 puts clone_flags in d1 and usp in d2 */ + clone_flags = regs->d1; + newsp = regs->d2; + if (!newsp) + newsp = rdusp(); + p = do_fork(clone_flags & ~CLONE_IDLETASK, newsp, regs, 0, NULL); + return IS_ERR(p) ? PTR_ERR(p) : p->pid; +} + +int copy_thread(int nr, unsigned long clone_flags, + unsigned long usp, unsigned long topstk, + struct task_struct * p, struct pt_regs * regs) +{ + struct pt_regs * childregs; + struct switch_stack * childstack, *stack; + unsigned long stack_offset, *retp; + + stack_offset = KTHREAD_SIZE - sizeof(struct pt_regs); + childregs = (struct pt_regs *) ((unsigned long) p->thread_info + stack_offset); + + *childregs = *regs; + childregs->d0 = 0; + + retp = ((unsigned long *) regs); + stack = ((struct switch_stack *) retp) - 1; + + childstack = ((struct switch_stack *) childregs) - 1; + *childstack = *stack; + childstack->retpc = (unsigned long)ret_from_fork; + + p->thread.usp = usp; + p->thread.ksp = (unsigned long)childstack; + /* + * Must save the current SFC/DFC value, NOT the value when + * the parent was last descheduled - RGH 10-08-96 + */ + p->thread.fs = get_fs().seg; + +#ifdef CONFIG_FPU + if (!FPU_IS_EMU) { + /* Copy the current fpu state */ + asm volatile ("fsave %0" : : "m" (p->thread.fpstate[0]) : "memory"); + + if (p->thread.fpstate[0]) + asm volatile ("fmovemx %/fp0-%/fp7,%0\n\t" + "fmoveml %/fpiar/%/fpcr/%/fpsr,%1" + : : "m" (p->thread.fp[0]), "m" (p->thread.fpcntl[0]) + : "memory"); + /* Restore the state in case the fpu was busy */ + asm volatile ("frestore %0" : : "m" (p->thread.fpstate[0])); + } +#endif + + return 0; +} + +/* Fill in the fpu structure for a core dump. */ + +int dump_fpu(struct pt_regs *regs, struct user_m68kfp_struct *fpu) +{ +#ifdef CONFIG_FPU + char fpustate[216]; + + if (FPU_IS_EMU) { + int i; + + memcpy(fpu->fpcntl, current->thread.fpcntl, 12); + memcpy(fpu->fpregs, current->thread.fp, 96); + /* Convert internal fpu reg representation + * into long double format + */ + for (i = 0; i < 24; i += 3) + fpu->fpregs[i] = ((fpu->fpregs[i] & 0xffff0000) << 15) | + ((fpu->fpregs[i] & 0x0000ffff) << 16); + return 1; + } + + /* First dump the fpu context to avoid protocol violation. */ + asm volatile ("fsave %0" :: "m" (fpustate[0]) : "memory"); + if (!fpustate[0]) + return 0; + + asm volatile ("fmovem %/fpiar/%/fpcr/%/fpsr,%0" + :: "m" (fpu->fpcntl[0]) + : "memory"); + asm volatile ("fmovemx %/fp0-%/fp7,%0" + :: "m" (fpu->fpregs[0]) + : "memory"); +#endif + return 1; +} + +/* + * fill in the user structure for a core dump.. + */ +void dump_thread(struct pt_regs * regs, struct user * dump) +{ + struct switch_stack *sw; + + /* changed the size calculations - should hopefully work better. lbt */ + dump->magic = CMAGIC; + dump->start_code = 0; + dump->start_stack = rdusp() & ~(PAGE_SIZE - 1); + dump->u_tsize = ((unsigned long) current->mm->end_code) >> PAGE_SHIFT; + dump->u_dsize = ((unsigned long) (current->mm->brk + + (PAGE_SIZE-1))) >> PAGE_SHIFT; + dump->u_dsize -= dump->u_tsize; + dump->u_ssize = 0; + + if (dump->start_stack < TASK_SIZE) + dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> PAGE_SHIFT; + + dump->u_ar0 = (struct user_regs_struct *)((int)&dump->regs - (int)dump); + sw = ((struct switch_stack *)regs) - 1; + dump->regs.d1 = regs->d1; + dump->regs.d2 = regs->d2; + dump->regs.d3 = regs->d3; + dump->regs.d4 = regs->d4; + dump->regs.d5 = regs->d5; + dump->regs.d6 = sw->d6; + dump->regs.d7 = sw->d7; + dump->regs.a0 = regs->a0; + dump->regs.a1 = regs->a1; + dump->regs.a2 = regs->a2; + dump->regs.a3 = sw->a3; + dump->regs.a4 = sw->a4; + dump->regs.a5 = sw->a5; + dump->regs.a6 = sw->a6; + dump->regs.d0 = regs->d0; + dump->regs.orig_d0 = regs->orig_d0; + dump->regs.stkadj = regs->stkadj; + dump->regs.sr = regs->sr; + dump->regs.pc = regs->pc; + dump->regs.fmtvec = (regs->format << 12) | regs->vector; + /* dump floating point stuff */ + dump->u_fpvalid = dump_fpu (regs, &dump->m68kfp); +} + +/* + * Generic dumping code. Used for panic and debug. + */ +void dump(struct pt_regs *fp) +{ + unsigned long *sp; + unsigned char *tp; + int i; + + printk("\nCURRENT PROCESS:\n\n"); + printk("COMM=%s PID=%d\n", current->comm, current->pid); + + if (current->mm) { + printk("TEXT=%08x-%08x DATA=%08x-%08x BSS=%08x-%08x\n", + (int) current->mm->start_code, + (int) current->mm->end_code, + (int) current->mm->start_data, + (int) current->mm->end_data, + (int) current->mm->end_data, + (int) current->mm->brk); + printk("USER-STACK=%08x KERNEL-STACK=%08x\n\n", + (int) current->mm->start_stack, + (int)(((unsigned long) current) + KTHREAD_SIZE)); + } + + printk("PC: %08lx\n", fp->pc); + printk("SR: %08lx SP: %08lx\n", (long) fp->sr, (long) fp); + printk("d0: %08lx d1: %08lx d2: %08lx d3: %08lx\n", + fp->d0, fp->d1, fp->d2, fp->d3); + printk("d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n", + fp->d4, fp->d5, fp->a0, fp->a1); + printk("\nUSP: %08x TRAPFRAME: %08x\n", (unsigned int) rdusp(), + (unsigned int) fp); + + printk("\nCODE:"); + tp = ((unsigned char *) fp->pc) - 0x20; + for (sp = (unsigned long *) tp, i = 0; (i < 0x40); i += 4) { + if ((i % 0x10) == 0) + printk("\n%08x: ", (int) (tp + i)); + printk("%08x ", (int) *sp++); + } + printk("\n"); + + printk("\nKERNEL STACK:"); + tp = ((unsigned char *) fp) - 0x40; + for (sp = (unsigned long *) tp, i = 0; (i < 0xc0); i += 4) { + if ((i % 0x10) == 0) + printk("\n%08x: ", (int) (tp + i)); + printk("%08x ", (int) *sp++); + } + printk("\n"); + printk("\n"); + + printk("\nUSER STACK:"); + tp = (unsigned char *) (rdusp() - 0x10); + for (sp = (unsigned long *) tp, i = 0; (i < 0x80); i += 4) { + if ((i % 0x10) == 0) + printk("\n%08x: ", (int) (tp + i)); + printk("%08x ", (int) *sp++); + } + printk("\n\n"); +} + +/* + * sys_execve() executes a new program. + */ +asmlinkage int sys_execve(char *name, char **argv, char **envp) +{ + int error; + char * filename; + struct pt_regs *regs = (struct pt_regs *) &name; + + lock_kernel(); + filename = getname(name); + error = PTR_ERR(filename); + if (IS_ERR(filename)) + goto out; + error = do_execve(filename, argv, envp, regs); + putname(filename); +out: + unlock_kernel(); + return error; +} + +/* + * These bracket the sleeping functions.. + */ +extern void scheduling_functions_start_here(void); +extern void scheduling_functions_end_here(void); +#define first_sched ((unsigned long) scheduling_functions_start_here) +#define last_sched ((unsigned long) scheduling_functions_end_here) + +unsigned long get_wchan(struct task_struct *p) +{ + unsigned long fp, pc; + unsigned long stack_page; + int count = 0; + if (!p || p == current || p->state == TASK_RUNNING) + return 0; + + stack_page = (unsigned long)p; + fp = ((struct switch_stack *)p->thread.ksp)->a6; + do { + if (fp < stack_page+sizeof(struct task_struct) || + fp >= 8184+stack_page) + return 0; + pc = ((unsigned long *)fp)[1]; + /* FIXME: This depends on the order of these functions. */ + if (pc < first_sched || pc >= last_sched) + return pc; + fp = *(unsigned long *) fp; + } while (count++ < 16); + return 0; +} + +/* + * Return saved PC of a blocked thread. + */ +unsigned long thread_saved_pc(struct task_struct *tsk) +{ + extern void scheduling_functions_start_here(void); + extern void scheduling_functions_end_here(void); + struct switch_stack *sw = (struct switch_stack *)tsk->thread.ksp; + + /* Check whether the thread is blocked in resume() */ + if (sw->retpc > (unsigned long)scheduling_functions_start_here && + sw->retpc < (unsigned long)scheduling_functions_end_here) + return ((unsigned long *)sw->a6)[1]; + else + return sw->retpc; +} + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/kernel/ptrace.c linux.2.5.45-ac1/arch/m68knommu/kernel/ptrace.c --- linux.2.5.45/arch/m68knommu/kernel/ptrace.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/kernel/ptrace.c 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,392 @@ +/* + * linux/arch/m68knommu/kernel/ptrace.c + * + * Copyright (C) 1994 by Hamish Macdonald + * Taken from linux/kernel/ptrace.c and modified for M680x0. + * linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds + * + * 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 + +/* + * does not yet catch signals sent when the child dies. + * in exit.c or in signal.c. + */ + +/* determines which bits in the SR the user has access to. */ +/* 1 = access 0 = no access */ +#define SR_MASK 0x001f + +/* sets the trace bits. */ +#define TRACE_BITS 0x8000 + +/* Find the stack offset for a register, relative to thread.esp0. */ +#define PT_REG(reg) ((long)&((struct pt_regs *)0)->reg) +#define SW_REG(reg) ((long)&((struct switch_stack *)0)->reg \ + - sizeof(struct switch_stack)) +/* Mapping from PT_xxx to the stack offset at which the register is + saved. Notice that usp has no stack-slot and needs to be treated + specially (see get_reg/put_reg below). */ +static int regoff[] = { + PT_REG(d1), PT_REG(d2), PT_REG(d3), PT_REG(d4), + PT_REG(d5), SW_REG(d6), SW_REG(d7), PT_REG(a0), + PT_REG(a1), PT_REG(a2), SW_REG(a3), SW_REG(a4), + SW_REG(a5), SW_REG(a6), PT_REG(d0), -1, + PT_REG(orig_d0), PT_REG(sr), PT_REG(pc), +}; + +/* + * Get contents of register REGNO in task TASK. + */ +static inline long get_reg(struct task_struct *task, int regno) +{ + unsigned long *addr; + + if (regno == PT_USP) + addr = &task->thread.usp; + else if (regno < sizeof(regoff)/sizeof(regoff[0])) + addr = (unsigned long *)(task->thread.esp0 + regoff[regno]); + else + return 0; + return *addr; +} + +/* + * Write contents of register REGNO in task TASK. + */ +static inline int put_reg(struct task_struct *task, int regno, + unsigned long data) +{ + unsigned long *addr; + + if (regno == PT_USP) + addr = &task->thread.usp; + else if (regno < sizeof(regoff)/sizeof(regoff[0])) + addr = (unsigned long *) (task->thread.esp0 + regoff[regno]); + else + return -1; + *addr = data; + return 0; +} + +/* + * Called by kernel/ptrace.c when detaching.. + * + * Make sure the single step bit is not set. + */ +void ptrace_disable(struct task_struct *child) +{ + unsigned long tmp; + /* make sure the single step bit is not set. */ + tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16); + put_reg(child, PT_SR, tmp); +} + +asmlinkage int sys_ptrace(long request, long pid, long addr, long data) +{ + struct task_struct *child; + int ret; + + lock_kernel(); + ret = -EPERM; + if (request == PTRACE_TRACEME) { + /* are we already being traced? */ + if (current->ptrace & PT_PTRACED) + goto out; + /* set the ptrace bit in the process flags. */ + current->ptrace |= PT_PTRACED; + ret = 0; + goto out; + } + ret = -ESRCH; + read_lock(&tasklist_lock); + child = find_task_by_pid(pid); + if (child) + get_task_struct(child); + read_unlock(&tasklist_lock); + if (!child) + goto out; + + ret = -EPERM; + if (pid == 1) /* you may not mess with init */ + goto out_tsk; + + if (request == PTRACE_ATTACH) { + ret = ptrace_attach(child); + goto out_tsk; + } + ret = -ESRCH; + if (!(child->ptrace & PT_PTRACED)) + goto out_tsk; + if (child->state != TASK_STOPPED) { + if (request != PTRACE_KILL) + goto out_tsk; + } + ret = ptrace_check_attach(child, request == PTRACE_KILL); + if (ret < 0) + goto out_tsk; + + switch (request) { + /* when I and D space are separate, these will need to be fixed. */ + case PTRACE_PEEKTEXT: /* read word at location addr. */ + case PTRACE_PEEKDATA: { + unsigned long tmp; + int copied; + + copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); + ret = -EIO; + if (copied != sizeof(tmp)) + break; + ret = put_user(tmp,(unsigned long *) data); + break; + } + + /* read the word at location addr in the USER area. */ + case PTRACE_PEEKUSR: { + unsigned long tmp; + + ret = -EIO; + if ((addr & 3) || addr < 0 || + addr > sizeof(struct user) - 3) + break; + + tmp = 0; /* Default return condition */ + addr = addr >> 2; /* temporary hack. */ + ret = -EIO; + if (addr < 19) { + tmp = get_reg(child, addr); + if (addr == PT_SR) + tmp >>= 16; + } else if (addr >= 21 && addr < 49) { + tmp = child->thread.fp[addr - 21]; +#ifdef CONFIG_M68KFPU_EMU + /* Convert internal fpu reg representation + * into long double format + */ + if (FPU_IS_EMU && (addr < 45) && !(addr % 3)) + tmp = ((tmp & 0xffff0000) << 15) | + ((tmp & 0x0000ffff) << 16); +#endif + } else if (addr == 49) { + tmp = child->mm->start_code; + } else if (addr == 50) { + tmp = child->mm->start_data; + } else if (addr == 51) { + tmp = child->mm->end_code; + } else + break; + ret = put_user(tmp,(unsigned long *) data); + break; + } + + /* when I and D space are separate, this will have to be fixed. */ + case PTRACE_POKETEXT: /* write the word at location addr. */ + case PTRACE_POKEDATA: + ret = 0; + if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data)) + break; + ret = -EIO; + break; + + case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ + ret = -EIO; + if ((addr & 3) || addr < 0 || + addr > sizeof(struct user) - 3) + break; + + addr = addr >> 2; /* temporary hack. */ + + if (addr == PT_SR) { + data &= SR_MASK; + data <<= 16; + data |= get_reg(child, PT_SR) & ~(SR_MASK << 16); + } + if (addr < 19) { + if (put_reg(child, addr, data)) + break; + ret = 0; + break; + } + if (addr >= 21 && addr < 48) + { +#ifdef CONFIG_M68KFPU_EMU + /* Convert long double format + * into internal fpu reg representation + */ + if (FPU_IS_EMU && (addr < 45) && !(addr % 3)) { + data = (unsigned long)data << 15; + data = (data & 0xffff0000) | + ((data & 0x0000ffff) >> 1); + } +#endif + child->thread.fp[addr - 21] = data; + ret = 0; + } + break; + + case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ + case PTRACE_CONT: { /* restart after signal. */ + long tmp; + + ret = -EIO; + if ((unsigned long) data > _NSIG) + break; + if (request == PTRACE_SYSCALL) + set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); + else + clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); + child->exit_code = data; + /* make sure the single step bit is not set. */ + tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16); + put_reg(child, PT_SR, tmp); + wake_up_process(child); + ret = 0; + break; + } + + /* + * make the child exit. Best I can do is send it a sigkill. + * perhaps it should be put in the status that it wants to + * exit. + */ + case PTRACE_KILL: { + long tmp; + + ret = 0; + if (child->state == TASK_ZOMBIE) /* already dead */ + break; + child->exit_code = SIGKILL; + /* make sure the single step bit is not set. */ + tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16); + put_reg(child, PT_SR, tmp); + wake_up_process(child); + break; + } + + case PTRACE_SINGLESTEP: { /* set the trap flag. */ + long tmp; + + ret = -EIO; + if ((unsigned long) data > _NSIG) + break; + clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); + tmp = get_reg(child, PT_SR) | (TRACE_BITS << 16); + put_reg(child, PT_SR, tmp); + + child->exit_code = data; + /* give it a chance to run. */ + wake_up_process(child); + ret = 0; + break; + } + + case PTRACE_DETACH: /* detach a process that was attached. */ + ret = ptrace_detach(child, data); + break; + + case PTRACE_GETREGS: { /* Get all gp regs from the child. */ + int i; + unsigned long tmp; + for (i = 0; i < 19; i++) { + tmp = get_reg(child, i); + if (i == PT_SR) + tmp >>= 16; + if (put_user(tmp, (unsigned long *) data)) { + ret = -EFAULT; + break; + } + data += sizeof(long); + } + ret = 0; + break; + } + + case PTRACE_SETREGS: { /* Set all gp regs in the child. */ + int i; + unsigned long tmp; + for (i = 0; i < 19; i++) { + if (get_user(tmp, (unsigned long *) data)) { + ret = -EFAULT; + break; + } + if (i == PT_SR) { + tmp &= SR_MASK; + tmp <<= 16; + tmp |= get_reg(child, PT_SR) & ~(SR_MASK << 16); + } + put_reg(child, i, tmp); + data += sizeof(long); + } + ret = 0; + break; + } + +#ifdef PTRACE_GETFPREGS + case PTRACE_GETFPREGS: { /* Get the child FPU state. */ + ret = 0; + if (copy_to_user((void *)data, &child->thread.fp, + sizeof(struct user_m68kfp_struct))) + ret = -EFAULT; + break; + } +#endif + +#ifdef PTRACE_SETFPREGS + case PTRACE_SETFPREGS: { /* Set the child FPU state. */ + ret = 0; + if (copy_from_user(&child->thread.fp, (void *)data, + sizeof(struct user_m68kfp_struct))) + ret = -EFAULT; + break; + } +#endif + + default: + ret = -EIO; + break; + } +out_tsk: + put_task_struct(child); +out: + unlock_kernel(); + return ret; +} + +asmlinkage void syscall_trace(void) +{ + if (!test_thread_flag(TIF_SYSCALL_TRACE)) + return; + if (!(current->ptrace & PT_PTRACED)) + return; + current->exit_code = SIGTRAP; + current->state = TASK_STOPPED; + notify_parent(current, SIGCHLD); + schedule(); + /* + * this isn't the same as continuing with a signal, but it will do + * for normal use. strace only continues with a signal if the + * stopping signal is not SIGTRAP. -brl + */ + if (current->exit_code) { + send_sig(current->exit_code, current, 1); + current->exit_code = 0; + } +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/kernel/semaphore.c linux.2.5.45-ac1/arch/m68knommu/kernel/semaphore.c --- linux.2.5.45/arch/m68knommu/kernel/semaphore.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/kernel/semaphore.c 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,133 @@ +/* + * Generic semaphore code. Buyer beware. Do your own + * specific changes in + */ + +#include +#include +#include +#include + +#ifndef CONFIG_RMW_INSNS +spinlock_t semaphore_wake_lock; +#endif + +/* + * Semaphores are implemented using a two-way counter: + * The "count" variable is decremented for each process + * that tries to sleep, while the "waking" variable is + * incremented when the "up()" code goes to wake up waiting + * processes. + * + * Notably, the inline "up()" and "down()" functions can + * efficiently test if they need to do any extra work (up + * needs to do something only if count was negative before + * the increment operation. + * + * waking_non_zero() (from asm/semaphore.h) must execute + * atomically. + * + * When __up() is called, the count was negative before + * incrementing it, and we need to wake up somebody. + * + * This routine adds one to the count of processes that need to + * wake up and exit. ALL waiting processes actually wake up but + * only the one that gets to the "waking" field first will gate + * through and acquire the semaphore. The others will go back + * to sleep. + * + * Note that these functions are only called when there is + * contention on the lock, and as such all this is the + * "non-critical" part of the whole semaphore business. The + * critical part is the inline stuff in + * where we want to avoid any extra jumps and calls. + */ +void __up(struct semaphore *sem) +{ + wake_one_more(sem); + wake_up(&sem->wait); +} + +/* + * Perform the "down" function. Return zero for semaphore acquired, + * return negative for signalled out of the function. + * + * If called from __down, the return is ignored and the wait loop is + * not interruptible. This means that a task waiting on a semaphore + * using "down()" cannot be killed until someone does an "up()" on + * the semaphore. + * + * If called from __down_interruptible, the return value gets checked + * upon return. If the return value is negative then the task continues + * with the negative value in the return register (it can be tested by + * the caller). + * + * Either form may be used in conjunction with "up()". + * + */ + + +#define DOWN_HEAD(task_state) \ + \ + \ + current->state = (task_state); \ + add_wait_queue(&sem->wait, &wait); \ + \ + /* \ + * Ok, we're set up. sem->count is known to be less than zero \ + * so we must wait. \ + * \ + * We can let go the lock for purposes of waiting. \ + * We re-acquire it after awaking so as to protect \ + * all semaphore operations. \ + * \ + * If "up()" is called before we call waking_non_zero() then \ + * we will catch it right away. If it is called later then \ + * we will have to go through a wakeup cycle to catch it. \ + * \ + * Multiple waiters contend for the semaphore lock to see \ + * who gets to gate through and who has to wait some more. \ + */ \ + for (;;) { + +#define DOWN_TAIL(task_state) \ + current->state = (task_state); \ + } \ + current->state = TASK_RUNNING; \ + remove_wait_queue(&sem->wait, &wait); + +void __down(struct semaphore * sem) +{ + DECLARE_WAITQUEUE(wait, current); + + DOWN_HEAD(TASK_UNINTERRUPTIBLE) + if (waking_non_zero(sem)) + break; + schedule(); + DOWN_TAIL(TASK_UNINTERRUPTIBLE) +} + +int __down_interruptible(struct semaphore * sem) +{ + DECLARE_WAITQUEUE(wait, current); + int ret = 0; + + DOWN_HEAD(TASK_INTERRUPTIBLE) + + ret = waking_non_zero_interruptible(sem, current); + if (ret) + { + if (ret == 1) + /* ret != 0 only if we get interrupted -arca */ + ret = 0; + break; + } + schedule(); + DOWN_TAIL(TASK_INTERRUPTIBLE) + return ret; +} + +int __down_trylock(struct semaphore * sem) +{ + return waking_non_zero_trylock(sem); +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/kernel/setup.c linux.2.5.45-ac1/arch/m68knommu/kernel/setup.c --- linux.2.5.45/arch/m68knommu/kernel/setup.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/kernel/setup.c 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,360 @@ +/* + * linux/arch/m68knommu/kernel/setup.c + * + * Copyright (C) 1999-2002 Greg Ungerer (gerg@snapgear.com) + * Copyright (C) 1998,1999 D. Jeff Dionne + * Copyleft ()) 2000 James D. Schettine {james@telos-systems.com} + * Copyright (C) 1998 Kenneth Albanowski + * Copyright (C) 1995 Hamish Macdonald + * Copyright (C) 2000 Lineo Inc. (www.lineo.com) + * Copyright (C) 2001 Lineo, Inc. + * + * 68VZ328 Fixes/support Evan Stawnyczy + */ + +/* + * This file handles the architecture-dependent parts of system setup + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#ifdef CONFIG_BLK_DEV_INITRD +#include +#include +#endif + +#ifdef CONFIG_CONSOLE +extern struct consw *conswitchp; +#ifdef CONFIG_FRAMEBUFFER +extern struct consw fb_con; +#endif +#endif + +unsigned long rom_length; +unsigned long memory_start; +unsigned long memory_end; + +char command_line[512]; +char saved_command_line[512]; + +/* setup some dummy routines */ +static void dummy_waitbut(void) +{ +} + +void (*mach_sched_init) (void (*handler)(int, void *, struct pt_regs *)) = NULL; +void (*mach_tick)( void ) = NULL; +/* machine dependent keyboard functions */ +int (*mach_keyb_init) (void) = NULL; +int (*mach_kbdrate) (struct kbd_repeat *) = NULL; +void (*mach_kbd_leds) (unsigned int) = NULL; +/* machine dependent irq functions */ +void (*mach_init_IRQ) (void) = NULL; +void (*(*mach_default_handler)[]) (int, void *, struct pt_regs *) = NULL; +int (*mach_request_irq) (unsigned int, void (*)(int, void *, struct pt_regs *), + unsigned long, const char *, void *); +void (*mach_free_irq) (unsigned int irq, void *dev_id) = NULL; +void (*mach_enable_irq) (unsigned int) = NULL; +void (*mach_disable_irq) (unsigned int) = NULL; +int (*mach_get_irq_list) (struct seq_file *, void *) = NULL; +void (*mach_process_int) (int irq, struct pt_regs *fp) = NULL; +void (*mach_trap_init) (void); +/* machine dependent timer functions */ +unsigned long (*mach_gettimeoffset) (void) = NULL; +void (*mach_gettod) (int*, int*, int*, int*, int*, int*) = NULL; +int (*mach_hwclk) (int, struct hwclk_time*) = NULL; +int (*mach_set_clock_mmss) (unsigned long) = NULL; +void (*mach_mksound)( unsigned int count, unsigned int ticks ) = NULL; +void (*mach_reset)( void ) = NULL; +void (*waitbut)(void) = dummy_waitbut; +void (*mach_debug_init)(void) = NULL; +void (*mach_halt)( void ) = NULL; +void (*mach_power_off)( void ) = NULL; + + +#ifdef CONFIG_M68000 + #define CPU "MC68000" +#endif +#ifdef CONFIG_M68328 + #define CPU "MC68328" +#endif +#ifdef CONFIG_M68EZ328 + #define CPU "MC68EZ328" +#endif +#ifdef CONFIG_M68VZ328 + #define CPU "MC68VZ328" +#endif +#ifdef CONFIG_M68332 + #define CPU "MC68332" +#endif +#ifdef CONFIG_M68360 + #define CPU "MC68360" +#endif +#if defined(CONFIG_M5206) + #define CPU "COLDFIRE(m5206)" +#endif +#if defined(CONFIG_M5206e) + #define CPU "COLDFIRE(m5206e)" +#endif +#if defined(CONFIG_M5249) + #define CPU "COLDFIRE(m5249)" +#endif +#if defined(CONFIG_M5272) + #define CPU "COLDFIRE(m5272)" +#endif +#if defined(CONFIG_M5307) + #define CPU "COLDFIRE(m5307)" +#endif +#if defined(CONFIG_M5407) + #define CPU "COLDFIRE(m5407)" +#endif +#ifndef CPU + #define CPU "UNKOWN" +#endif + +/* (es) */ +/* note: why is this defined here? the must be a better place to put this */ +#if defined( CONFIG_TELOS) || defined( CONFIG_UCDIMM ) || defined( CONFIG_UCSIMM ) || defined(CONFIG_DRAGEN2) || (defined( CONFIG_PILOT ) && defined( CONFIG_M68328 )) +#define CAT_ROMARRAY +#endif +/* (/es) */ + +extern int _stext, _etext, _sdata, _edata, _sbss, _ebss, _end; +extern int _ramstart, _ramend; + +void setup_arch(char **cmdline_p) +{ + int bootmap_size; + +#if defined(CAT_ROMARRAY) && defined(DEBUG) + extern int __data_rom_start; + extern int __data_start; + int *romarray = (int *)((int) &__data_rom_start + + (int)&_edata - (int)&__data_start); +#endif + + memory_start = PAGE_ALIGN(_ramstart); + memory_end = _ramend; /* by now the stack is part of the init task */ + + init_mm.start_code = (unsigned long) &_stext; + init_mm.end_code = (unsigned long) &_etext; + init_mm.end_data = (unsigned long) &_edata; + init_mm.brk = (unsigned long) 0; + + config_BSP(&command_line[0], sizeof(command_line)); + + printk("\x0F\r\n\nuClinux/" CPU "\n"); + +#ifdef CONFIG_UCDIMM + printk("uCdimm by Lineo, Inc. \n"); +#endif +#ifdef CONFIG_M68VZ328 + printk("M68VZ328 support by Evan Stawnyczy \n"); +#endif +#ifdef CONFIG_COLDFIRE + printk("COLDFIRE port done by Greg Ungerer, gerg@snapgear.com\n"); +#ifdef CONFIG_M5307 + printk("Modified for M5307 by Dave Miller, dmiller@intellistor.com\n"); +#endif +#ifdef CONFIG_ELITE + printk("Modified for M5206eLITE by Rob Scott, rscott@mtrob.fdns.net\n"); +#endif +#ifdef CONFIG_TELOS + printk("Modified for Omnia ToolVox by James D. Schettine, james@telos-systems.com\n"); +#endif +#endif + printk("Flat model support (C) 1998,1999 Kenneth Albanowski, D. Jeff Dionne\n"); + +#if defined( CONFIG_PILOT ) && defined( CONFIG_M68328 ) + printk("TRG SuperPilot FLASH card support \n"); +#endif + +#if defined( CONFIG_PILOT ) && defined( CONFIG_M68EZ328 ) + printk("PalmV support by Lineo Inc. \n"); +#endif + +#ifdef CONFIG_M68EZ328ADS + printk("M68EZ328ADS board support (C) 1999 Vladimir Gurevich \n"); +#endif + +#ifdef CONFIG_ALMA_ANS + printk("Alma Electronics board support (C) 1999 Vladimir Gurevich \n"); +#endif +#if defined (CONFIG_M68360) + printk("QUICC port done by SED Systems ,\n"); + printk("based on 2.0.38 port by Lineo Inc. .\n"); +#endif +#ifdef CONFIG_DRAGEN2 + printk("Dragon Engine II board support by Georges Menie\n"); +#endif + +#ifdef DEBUG + printk("KERNEL -> TEXT=0x%06x-0x%06x DATA=0x%06x-0x%06x " + "BSS=0x%06x-0x%06x\n", (int) &_stext, (int) &_etext, + (int) &_sdata, (int) &_edata, + (int) &_sbss, (int) &_ebss); + printk("KERNEL -> ROMFS=0x%06x-0x%06x MEM=0x%06x-0x%06x " + "STACK=0x%06x-0x%06x\n", +#ifdef CAT_ROMARRAY + (int) romarray, ((int) romarray) + romarray[2], +#else + (int) &_ebss, (int) memory_start, +#endif + (int) memory_start, (int) memory_end, + (int) memory_end, (int) _ramend); +#endif + +#ifdef CONFIG_BLK_DEV_BLKMEM + ROOT_DEV = MKDEV(BLKMEM_MAJOR, 0); +#endif + + /* Keep a copy of command line */ + *cmdline_p = &command_line[0]; + memcpy(saved_command_line, command_line, sizeof(saved_command_line)); + saved_command_line[sizeof(saved_command_line)-1] = 0; + +#ifdef DEBUG + if (strlen(*cmdline_p)) + printk("Command line: '%s'\n", *cmdline_p); +#endif + +#ifdef CONFIG_CONSOLE +#ifdef CONFIG_FRAMEBUFFER + conswitchp = &fb_con; +#else + conswitchp = 0; +#endif +#endif + + /* + * Give all the memory to the bootmap allocator, tell it to put the + * boot mem_map at the start of memory. + */ + bootmap_size = init_bootmem_node( + NODE_DATA(0), + memory_start >> PAGE_SHIFT, /* map goes here */ + PAGE_OFFSET >> PAGE_SHIFT, /* 0 on coldfire */ + memory_end >> PAGE_SHIFT); + /* + * Free the usable memory, we have to make sure we do not free + * the bootmem bitmap so we then reserve it after freeing it :-) + */ + free_bootmem(memory_start, memory_end - memory_start); + reserve_bootmem(memory_start, bootmap_size); + + /* + * Get kmalloc into gear. + */ + paging_init(); +} + +int get_cpuinfo(char * buffer) +{ + char *cpu, *mmu, *fpu; + u_long clockfreq; + + cpu = CPU; + mmu = "none"; + fpu = "none"; + +#ifdef CONFIG_COLDFIRE + clockfreq = (loops_per_jiffy*HZ)*3; +#else + clockfreq = (loops_per_jiffy*HZ)*16; +#endif + + return(sprintf(buffer, "CPU:\t\t%s\n" + "MMU:\t\t%s\n" + "FPU:\t\t%s\n" + "Clocking:\t%lu.%1luMHz\n" + "BogoMips:\t%lu.%02lu\n" + "Calibration:\t%lu loops\n", + cpu, mmu, fpu, + clockfreq/1000000,(clockfreq/100000)%10, + (loops_per_jiffy*HZ)/500000,((loops_per_jiffy*HZ)/5000)%100, + (loops_per_jiffy*HZ))); + +} + +/* + * Get CPU information for use by the procfs. + */ + +static int show_cpuinfo(struct seq_file *m, void *v) +{ + char *cpu, *mmu, *fpu; + u_long clockfreq; + + cpu = CPU; + mmu = "none"; + fpu = "none"; + +#ifdef CONFIG_COLDFIRE + clockfreq = (loops_per_jiffy*HZ)*3; +#else + clockfreq = (loops_per_jiffy*HZ)*16; +#endif + + seq_printf(m, "CPU:\t\t%s\n" + "MMU:\t\t%s\n" + "FPU:\t\t%s\n" + "Clocking:\t%lu.%1luMHz\n" + "BogoMips:\t%lu.%02lu\n" + "Calibration:\t%lu loops\n", + cpu, mmu, fpu, + clockfreq/1000000,(clockfreq/100000)%10, + (loops_per_jiffy*HZ)/500000,((loops_per_jiffy*HZ)/5000)%100, + (loops_per_jiffy*HZ)); + + return 0; +} + +static void *c_start(struct seq_file *m, loff_t *pos) +{ + return *pos < NR_CPUS ? ((void *) 0x12345678) : NULL; +} + +static void *c_next(struct seq_file *m, void *v, loff_t *pos) +{ + ++*pos; + return c_start(m, pos); +} + +static void c_stop(struct seq_file *m, void *v) +{ +} + +struct seq_operations cpuinfo_op = { + start: c_start, + next: c_next, + stop: c_stop, + show: show_cpuinfo, +}; + +void arch_gettod(int *year, int *mon, int *day, int *hour, + int *min, int *sec) +{ + if (mach_gettod) + mach_gettod(year, mon, day, hour, min, sec); + else + *year = *mon = *day = *hour = *min = *sec = 0; +} + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/kernel/signal.c linux.2.5.45-ac1/arch/m68knommu/kernel/signal.c --- linux.2.5.45/arch/m68knommu/kernel/signal.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/kernel/signal.c 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,886 @@ +/* + * linux/arch/m68knommu/kernel/signal.c + * + * Copyright (C) 1991, 1992 Linus Torvalds + * + * 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. + */ + +/* + * Linux/m68k support by Hamish Macdonald + * + * 68060 fixes by Jesper Skov + * + * 1997-12-01 Modified for POSIX.1b signals by Andreas Schwab + * + * mathemu support by Roman Zippel + * (Note: fpstate in the signal context is completly ignored for the emulator + * and the internal floating point format is put on stack) + */ + +/* + * ++roman (07/09/96): implemented signal stacks (specially for tosemu on + * Atari :-) Current limitation: Only one sigstack can be active at one time. + * If a second signal with SA_ONSTACK set arrives while working on a sigstack, + * SA_ONSTACK is ignored. This behaviour avoids lots of trouble with nested + * signal handlers! + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) + +asmlinkage long sys_wait4(pid_t pid, unsigned int * stat_addr, int options, + struct rusage * ru); +asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs); + +/* + * Atomically swap in the new signal mask, and wait for a signal. + */ +asmlinkage int do_sigsuspend(struct pt_regs *regs) +{ + old_sigset_t mask = regs->d3; + sigset_t saveset; + + mask &= _BLOCKABLE; + saveset = current->blocked; + siginitset(¤t->blocked, mask); + recalc_sigpending(); + + regs->d0 = -EINTR; + while (1) { + current->state = TASK_INTERRUPTIBLE; + schedule(); + if (do_signal(&saveset, regs)) + return -EINTR; + } +} + +asmlinkage int +do_rt_sigsuspend(struct pt_regs *regs) +{ + sigset_t *unewset = (sigset_t *)regs->d1; + size_t sigsetsize = (size_t)regs->d2; + sigset_t saveset, newset; + + /* XXX: Don't preclude handling different sized sigset_t's. */ + if (sigsetsize != sizeof(sigset_t)) + return -EINVAL; + + if (copy_from_user(&newset, unewset, sizeof(newset))) + return -EFAULT; + sigdelsetmask(&newset, ~_BLOCKABLE); + + saveset = current->blocked; + current->blocked = newset; + recalc_sigpending(); + + regs->d0 = -EINTR; + while (1) { + current->state = TASK_INTERRUPTIBLE; + schedule(); + if (do_signal(&saveset, regs)) + return -EINTR; + } +} + +asmlinkage int +sys_sigaction(int sig, const struct old_sigaction *act, + struct old_sigaction *oact) +{ + struct k_sigaction new_ka, old_ka; + int ret; + + if (act) { + old_sigset_t mask; + if (verify_area(VERIFY_READ, act, sizeof(*act)) || + __get_user(new_ka.sa.sa_handler, &act->sa_handler) || + __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) + return -EFAULT; + __get_user(new_ka.sa.sa_flags, &act->sa_flags); + __get_user(mask, &act->sa_mask); + siginitset(&new_ka.sa.sa_mask, mask); + } + + ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); + + if (!ret && oact) { + if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) || + __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || + __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) + return -EFAULT; + __put_user(old_ka.sa.sa_flags, &oact->sa_flags); + __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); + } + + return ret; +} + +asmlinkage int +sys_sigaltstack(const stack_t *uss, stack_t *uoss) +{ + return do_sigaltstack(uss, uoss, rdusp()); +} + + +/* + * Do a signal return; undo the signal stack. + * + * Keep the return code on the stack quadword aligned! + * That makes the cache flush below easier. + */ + +struct sigframe +{ + char *pretcode; + int sig; + int code; + struct sigcontext *psc; + char retcode[8]; + unsigned long extramask[_NSIG_WORDS-1]; + struct sigcontext sc; +}; + +struct rt_sigframe +{ + char *pretcode; + int sig; + struct siginfo *pinfo; + void *puc; + char retcode[8]; + struct siginfo info; + struct ucontext uc; +}; + +#ifdef CONFIG_FPU + +static unsigned char fpu_version = 0; /* version number of fpu, set by setup_frame */ + +static inline int restore_fpu_state(struct sigcontext *sc) +{ + int err = 1; + + if (FPU_IS_EMU) { + /* restore registers */ + memcpy(current->thread.fpcntl, sc->sc_fpcntl, 12); + memcpy(current->thread.fp, sc->sc_fpregs, 24); + return 0; + } + + if (sc->sc_fpstate[0]) { + /* Verify the frame format. */ + if (sc->sc_fpstate[0] != fpu_version) + goto out; + + __asm__ volatile (".chip 68k/68881\n\t" + "fmovemx %0,%/fp0-%/fp1\n\t" + "fmoveml %1,%/fpcr/%/fpsr/%/fpiar\n\t" + ".chip 68k" + : /* no outputs */ + : "m" (*sc->sc_fpregs), "m" (*sc->sc_fpcntl)); + } + __asm__ volatile (".chip 68k/68881\n\t" + "frestore %0\n\t" + ".chip 68k" : : "m" (*sc->sc_fpstate)); + err = 0; + +out: + return err; +} + +#define FPCONTEXT_SIZE 216 +#define uc_fpstate uc_filler[0] +#define uc_formatvec uc_filler[FPCONTEXT_SIZE/4] +#define uc_extra uc_filler[FPCONTEXT_SIZE/4+1] + +static inline int rt_restore_fpu_state(struct ucontext *uc) +{ + unsigned char fpstate[FPCONTEXT_SIZE]; + int context_size = 0; + fpregset_t fpregs; + int err = 1; + + if (FPU_IS_EMU) { + /* restore fpu control register */ + if (__copy_from_user(current->thread.fpcntl, + &uc->uc_mcontext.fpregs.f_pcr, 12)) + goto out; + /* restore all other fpu register */ + if (__copy_from_user(current->thread.fp, + uc->uc_mcontext.fpregs.f_fpregs, 96)) + goto out; + return 0; + } + + if (__get_user(*(long *)fpstate, (long *)&uc->uc_fpstate)) + goto out; + if (fpstate[0]) { + context_size = fpstate[1]; + + /* Verify the frame format. */ + if (fpstate[0] != fpu_version) + goto out; + if (__copy_from_user(&fpregs, &uc->uc_mcontext.fpregs, + sizeof(fpregs))) + goto out; + __asm__ volatile (".chip 68k/68881\n\t" + "fmovemx %0,%/fp0-%/fp7\n\t" + "fmoveml %1,%/fpcr/%/fpsr/%/fpiar\n\t" + ".chip 68k" + : /* no outputs */ + : "m" (*fpregs.f_fpregs), + "m" (fpregs.f_pcr)); + } + if (context_size && + __copy_from_user(fpstate + 4, (long *)&uc->uc_fpstate + 1, + context_size)) + goto out; + __asm__ volatile (".chip 68k/68881\n\t" + "frestore %0\n\t" + ".chip 68k" : : "m" (*fpstate)); + err = 0; + +out: + return err; +} + +#endif + +static inline int +restore_sigcontext(struct pt_regs *regs, struct sigcontext *usc, void *fp, + int *pd0) +{ + int formatvec; + struct sigcontext context; + int err = 0; + + /* get previous context */ + if (copy_from_user(&context, usc, sizeof(context))) + goto badframe; + + /* restore passed registers */ + regs->d1 = context.sc_d1; + regs->a0 = context.sc_a0; + regs->a1 = context.sc_a1; + regs->sr = (regs->sr & 0xff00) | (context.sc_sr & 0xff); + regs->pc = context.sc_pc; + regs->orig_d0 = -1; /* disable syscall checks */ + wrusp(context.sc_usp); + formatvec = context.sc_formatvec; + regs->format = formatvec >> 12; + regs->vector = formatvec & 0xfff; + +#ifdef CONFIG_FPU + err = restore_fpu_state(&context); +#endif + + *pd0 = context.sc_d0; + return err; + +badframe: + return 1; +} + +static inline int +rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw, + struct ucontext *uc, int *pd0) +{ + int temp; + greg_t *gregs = uc->uc_mcontext.gregs; + unsigned long usp; + int err; + + err = __get_user(temp, &uc->uc_mcontext.version); + if (temp != MCONTEXT_VERSION) + goto badframe; + /* restore passed registers */ + err |= __get_user(regs->d0, &gregs[0]); + err |= __get_user(regs->d1, &gregs[1]); + err |= __get_user(regs->d2, &gregs[2]); + err |= __get_user(regs->d3, &gregs[3]); + err |= __get_user(regs->d4, &gregs[4]); + err |= __get_user(regs->d5, &gregs[5]); + err |= __get_user(sw->d6, &gregs[6]); + err |= __get_user(sw->d7, &gregs[7]); + err |= __get_user(regs->a0, &gregs[8]); + err |= __get_user(regs->a1, &gregs[9]); + err |= __get_user(regs->a2, &gregs[10]); + err |= __get_user(sw->a3, &gregs[11]); + err |= __get_user(sw->a4, &gregs[12]); + err |= __get_user(sw->a5, &gregs[13]); + err |= __get_user(sw->a6, &gregs[14]); + err |= __get_user(usp, &gregs[15]); + wrusp(usp); + err |= __get_user(regs->pc, &gregs[16]); + err |= __get_user(temp, &gregs[17]); + regs->sr = (regs->sr & 0xff00) | (temp & 0xff); + regs->orig_d0 = -1; /* disable syscall checks */ + regs->format = temp >> 12; + regs->vector = temp & 0xfff; + + if (do_sigaltstack(&uc->uc_stack, NULL, usp) == -EFAULT) + goto badframe; + + *pd0 = regs->d0; + return err; + +badframe: + return 1; +} + +asmlinkage int do_sigreturn(unsigned long __unused) +{ + struct switch_stack *sw = (struct switch_stack *) &__unused; + struct pt_regs *regs = (struct pt_regs *) (sw + 1); + unsigned long usp = rdusp(); + struct sigframe *frame = (struct sigframe *)(usp - 4); + sigset_t set; + int d0; + + if (verify_area(VERIFY_READ, frame, sizeof(*frame))) + goto badframe; + if (__get_user(set.sig[0], &frame->sc.sc_mask) || + (_NSIG_WORDS > 1 && + __copy_from_user(&set.sig[1], &frame->extramask, + sizeof(frame->extramask)))) + goto badframe; + + sigdelsetmask(&set, ~_BLOCKABLE); + current->blocked = set; + recalc_sigpending(); + + if (restore_sigcontext(regs, &frame->sc, frame + 1, &d0)) + goto badframe; + return d0; + +badframe: + force_sig(SIGSEGV, current); + return 0; +} + +asmlinkage int do_rt_sigreturn(unsigned long __unused) +{ + struct switch_stack *sw = (struct switch_stack *) &__unused; + struct pt_regs *regs = (struct pt_regs *) (sw + 1); + unsigned long usp = rdusp(); + struct rt_sigframe *frame = (struct rt_sigframe *)(usp - 4); + sigset_t set; + int d0; + + if (verify_area(VERIFY_READ, frame, sizeof(*frame))) + goto badframe; + if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) + goto badframe; + + sigdelsetmask(&set, ~_BLOCKABLE); + current->blocked = set; + recalc_sigpending(); + + if (rt_restore_ucontext(regs, sw, &frame->uc, &d0)) + goto badframe; + return d0; + +badframe: + force_sig(SIGSEGV, current); + return 0; +} + +#ifdef CONFIG_FPU +/* + * Set up a signal frame. + */ + +static inline void save_fpu_state(struct sigcontext *sc, struct pt_regs *regs) +{ + if (FPU_IS_EMU) { + /* save registers */ + memcpy(sc->sc_fpcntl, current->thread.fpcntl, 12); + memcpy(sc->sc_fpregs, current->thread.fp, 24); + return; + } + + __asm__ volatile (".chip 68k/68881\n\t" + "fsave %0\n\t" + ".chip 68k" + : : "m" (*sc->sc_fpstate) : "memory"); + + if (sc->sc_fpstate[0]) { + fpu_version = sc->sc_fpstate[0]; + __asm__ volatile (".chip 68k/68881\n\t" + "fmovemx %/fp0-%/fp1,%0\n\t" + "fmoveml %/fpcr/%/fpsr/%/fpiar,%1\n\t" + ".chip 68k" + : /* no outputs */ + : "m" (*sc->sc_fpregs), + "m" (*sc->sc_fpcntl) + : "memory"); + } +} + +static inline int rt_save_fpu_state(struct ucontext *uc, struct pt_regs *regs) +{ + unsigned char fpstate[FPCONTEXT_SIZE]; + int context_size = 0; + int err = 0; + + if (FPU_IS_EMU) { + /* save fpu control register */ + err |= copy_to_user(&uc->uc_mcontext.fpregs.f_pcr, + current->thread.fpcntl, 12); + /* save all other fpu register */ + err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpregs, + current->thread.fp, 96); + return err; + } + + __asm__ volatile (".chip 68k/68881\n\t" + "fsave %0\n\t" + ".chip 68k" + : : "m" (*fpstate) : "memory"); + + err |= __put_user(*(long *)fpstate, (long *)&uc->uc_fpstate); + if (fpstate[0]) { + fpregset_t fpregs; + context_size = fpstate[1]; + fpu_version = fpstate[0]; + __asm__ volatile (".chip 68k/68881\n\t" + "fmovemx %/fp0-%/fp7,%0\n\t" + "fmoveml %/fpcr/%/fpsr/%/fpiar,%1\n\t" + ".chip 68k" + : /* no outputs */ + : "m" (*fpregs.f_fpregs), + "m" (fpregs.f_pcr) + : "memory"); + err |= copy_to_user(&uc->uc_mcontext.fpregs, &fpregs, + sizeof(fpregs)); + } + if (context_size) + err |= copy_to_user((long *)&uc->uc_fpstate + 1, fpstate + 4, + context_size); + return err; +} + +#endif + +static void setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs, + unsigned long mask) +{ + sc->sc_mask = mask; + sc->sc_usp = rdusp(); + sc->sc_d0 = regs->d0; + sc->sc_d1 = regs->d1; + sc->sc_a0 = regs->a0; + sc->sc_a1 = regs->a1; + sc->sc_sr = regs->sr; + sc->sc_pc = regs->pc; + sc->sc_formatvec = regs->format << 12 | regs->vector; +#ifdef CONFIG_FPU + save_fpu_state(sc, regs); +#endif +} + +static inline int rt_setup_ucontext(struct ucontext *uc, struct pt_regs *regs) +{ + struct switch_stack *sw = (struct switch_stack *)regs - 1; + greg_t *gregs = uc->uc_mcontext.gregs; + int err = 0; + + err |= __put_user(MCONTEXT_VERSION, &uc->uc_mcontext.version); + err |= __put_user(regs->d0, &gregs[0]); + err |= __put_user(regs->d1, &gregs[1]); + err |= __put_user(regs->d2, &gregs[2]); + err |= __put_user(regs->d3, &gregs[3]); + err |= __put_user(regs->d4, &gregs[4]); + err |= __put_user(regs->d5, &gregs[5]); + err |= __put_user(sw->d6, &gregs[6]); + err |= __put_user(sw->d7, &gregs[7]); + err |= __put_user(regs->a0, &gregs[8]); + err |= __put_user(regs->a1, &gregs[9]); + err |= __put_user(regs->a2, &gregs[10]); + err |= __put_user(sw->a3, &gregs[11]); + err |= __put_user(sw->a4, &gregs[12]); + err |= __put_user(sw->a5, &gregs[13]); + err |= __put_user(sw->a6, &gregs[14]); + err |= __put_user(rdusp(), &gregs[15]); + err |= __put_user(regs->pc, &gregs[16]); + err |= __put_user(regs->sr, &gregs[17]); +#ifdef CONFIG_FPU + err |= rt_save_fpu_state(uc, regs); +#endif + return err; +} + +static inline void push_cache (unsigned long vaddr) +{ +} + +static inline void * +get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) +{ + unsigned long usp; + + /* Default to using normal stack. */ + usp = rdusp(); + + /* This is the X/Open sanctioned signal stack switching. */ + if (ka->sa.sa_flags & SA_ONSTACK) { + if (!on_sig_stack(usp)) + usp = current->sas_ss_sp + current->sas_ss_size; + } + return (void *)((usp - frame_size) & -8UL); +} + +static void setup_frame (int sig, struct k_sigaction *ka, + sigset_t *set, struct pt_regs *regs) +{ + struct sigframe *frame; + struct sigcontext context; + int err = 0; + + frame = get_sigframe(ka, regs, sizeof(*frame)); + + err |= __put_user((current_thread_info()->exec_domain + && current_thread_info()->exec_domain->signal_invmap + && sig < 32 + ? current_thread_info()->exec_domain->signal_invmap[sig] + : sig), + &frame->sig); + + err |= __put_user(regs->vector, &frame->code); + err |= __put_user(&frame->sc, &frame->psc); + + if (_NSIG_WORDS > 1) + err |= copy_to_user(frame->extramask, &set->sig[1], + sizeof(frame->extramask)); + + setup_sigcontext(&context, regs, set->sig[0]); + err |= copy_to_user (&frame->sc, &context, sizeof(context)); + + /* Set up to return from userspace. */ + err |= __put_user(frame->retcode, &frame->pretcode); + /* moveq #,d0; trap #0 */ + err |= __put_user(0x70004e40 + (__NR_sigreturn << 16), + (long *)(frame->retcode)); + + if (err) + goto give_sigsegv; + + push_cache ((unsigned long) &frame->retcode); + + /* Set up registers for signal handler */ + wrusp ((unsigned long) frame); + regs->pc = (unsigned long) ka->sa.sa_handler; + +adjust_stack: + /* Prepare to skip over the extra stuff in the exception frame. */ + if (regs->stkadj) { + struct pt_regs *tregs = + (struct pt_regs *)((ulong)regs + regs->stkadj); +#if DEBUG + printk("Performing stackadjust=%04x\n", regs->stkadj); +#endif + /* This must be copied with decreasing addresses to + handle overlaps. */ + tregs->vector = 0; + tregs->format = 0; + tregs->pc = regs->pc; + tregs->sr = regs->sr; + } + return; + +give_sigsegv: + if (sig == SIGSEGV) + ka->sa.sa_handler = SIG_DFL; + force_sig(SIGSEGV, current); + goto adjust_stack; +} + +static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, + sigset_t *set, struct pt_regs *regs) +{ + struct rt_sigframe *frame; + int err = 0; + + frame = get_sigframe(ka, regs, sizeof(*frame)); + + err |= __put_user((current_thread_info()->exec_domain + && current_thread_info()->exec_domain->signal_invmap + && sig < 32 + ? current_thread_info()->exec_domain->signal_invmap[sig] + : sig), + &frame->sig); + err |= __put_user(&frame->info, &frame->pinfo); + err |= __put_user(&frame->uc, &frame->puc); + err |= copy_siginfo_to_user(&frame->info, info); + + /* Create the ucontext. */ + err |= __put_user(0, &frame->uc.uc_flags); + err |= __put_user(0, &frame->uc.uc_link); + err |= __put_user((void *)current->sas_ss_sp, + &frame->uc.uc_stack.ss_sp); + err |= __put_user(sas_ss_flags(rdusp()), + &frame->uc.uc_stack.ss_flags); + err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); + err |= rt_setup_ucontext(&frame->uc, regs); + err |= copy_to_user (&frame->uc.uc_sigmask, set, sizeof(*set)); + + /* Set up to return from userspace. */ + err |= __put_user(frame->retcode, &frame->pretcode); + /* moveq #,d0; notb d0; trap #0 */ + err |= __put_user(0x70004600 + ((__NR_rt_sigreturn ^ 0xff) << 16), + (long *)(frame->retcode + 0)); + err |= __put_user(0x4e40, (short *)(frame->retcode + 4)); + + if (err) + goto give_sigsegv; + + push_cache ((unsigned long) &frame->retcode); + + /* Set up registers for signal handler */ + wrusp ((unsigned long) frame); + regs->pc = (unsigned long) ka->sa.sa_handler; + +adjust_stack: + /* Prepare to skip over the extra stuff in the exception frame. */ + if (regs->stkadj) { + struct pt_regs *tregs = + (struct pt_regs *)((ulong)regs + regs->stkadj); +#if DEBUG + printk("Performing stackadjust=%04x\n", regs->stkadj); +#endif + /* This must be copied with decreasing addresses to + handle overlaps. */ + tregs->vector = 0; + tregs->format = 0; + tregs->pc = regs->pc; + tregs->sr = regs->sr; + } + return; + +give_sigsegv: + if (sig == SIGSEGV) + ka->sa.sa_handler = SIG_DFL; + force_sig(SIGSEGV, current); + goto adjust_stack; +} + +static inline void +handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler) +{ + switch (regs->d0) { + case -ERESTARTNOHAND: + if (!has_handler) + goto do_restart; + regs->d0 = -EINTR; + break; + + case -ERESTARTSYS: + if (has_handler && !(ka->sa.sa_flags & SA_RESTART)) { + regs->d0 = -EINTR; + break; + } + /* fallthrough */ + case -ERESTARTNOINTR: + do_restart: + regs->d0 = regs->orig_d0; + regs->pc -= 2; + break; + } +} + +/* + * OK, we're invoking a handler + */ +static void +handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, + sigset_t *oldset, struct pt_regs *regs) +{ + /* are we from a system call? */ + if (regs->orig_d0 >= 0) + /* If so, check system call restarting.. */ + handle_restart(regs, ka, 1); + + /* set up the stack frame */ + if (ka->sa.sa_flags & SA_SIGINFO) + setup_rt_frame(sig, ka, info, oldset, regs); + else + setup_frame(sig, ka, oldset, regs); + + if (ka->sa.sa_flags & SA_ONESHOT) + ka->sa.sa_handler = SIG_DFL; + + sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); + if (!(ka->sa.sa_flags & SA_NODEFER)) + sigaddset(¤t->blocked,sig); + recalc_sigpending(); +} + +/* + * Note that 'init' is a special process: it doesn't get signals it doesn't + * want to handle. Thus you cannot kill init even with a SIGKILL even by + * mistake. + * + * Note that we go through the signals twice: once to check the signals + * that the kernel can handle, and then we build all the user-level signal + * handling stack-frames in one go after that. + */ +asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) +{ + siginfo_t info; + struct k_sigaction *ka; + + current->thread.esp0 = (unsigned long) regs; + + if (!oldset) + oldset = ¤t->blocked; + + for (;;) { + int signr; + + signr = get_signal_to_deliver(&info, regs); + + if (!signr) + break; + + if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) { + current->exit_code = signr; + current->state = TASK_STOPPED; + regs->sr &= ~PS_T; + + /* Did we come from a system call? */ + if (regs->orig_d0 >= 0) { + /* Restart the system call the same way as + if the process were not traced. */ + struct k_sigaction *ka = + ¤t->sig->action[signr-1]; + int has_handler = + (ka->sa.sa_handler != SIG_IGN && + ka->sa.sa_handler != SIG_DFL); + handle_restart(regs, ka, has_handler); + } + notify_parent(current, SIGCHLD); + schedule(); + + /* We're back. Did the debugger cancel the sig? */ + if (!(signr = current->exit_code)) { + discard_frame: + continue; + } + current->exit_code = 0; + + /* The debugger continued. Ignore SIGSTOP. */ + if (signr == SIGSTOP) + goto discard_frame; + + /* Update the siginfo structure. Is this good? */ + if (signr != info.si_signo) { + info.si_signo = signr; + info.si_errno = 0; + info.si_code = SI_USER; + info.si_pid = current->parent->pid; + info.si_uid = current->parent->uid; + } + + /* If the (new) signal is now blocked, requeue it. */ + if (sigismember(¤t->blocked, signr)) { + send_sig_info(signr, &info, current); + continue; + } + } + + ka = ¤t->sig->action[signr-1]; + if (ka->sa.sa_handler == SIG_IGN) { + if (signr != SIGCHLD) + continue; + /* Check for SIGCHLD: it's special. */ + while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0) + /* nothing */; + continue; + } + + if (ka->sa.sa_handler == SIG_DFL) { + int exit_code = signr; + + if (current->pid == 1) + continue; + + switch (signr) { + case SIGCONT: case SIGCHLD: + case SIGWINCH: case SIGURG: + continue; + + case SIGTSTP: case SIGTTIN: case SIGTTOU: + if (is_orphaned_pgrp(current->pgrp)) + continue; + /* FALLTHRU */ + + case SIGSTOP: + current->state = TASK_STOPPED; + current->exit_code = signr; + if (!(current->parent->sig->action[SIGCHLD-1] + .sa.sa_flags & SA_NOCLDSTOP)) + notify_parent(current, SIGCHLD); + schedule(); + continue; + + case SIGQUIT: case SIGILL: case SIGTRAP: + case SIGIOT: case SIGFPE: case SIGSEGV: + case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ: + if (do_coredump(signr, regs)) + exit_code |= 0x80; + /* FALLTHRU */ + + default: + sigaddset(¤t->pending.signal, signr); + recalc_sigpending(); + current->flags |= PF_SIGNALED; + do_exit(exit_code); + /* NOTREACHED */ + } + } + + /* Whee! Actually deliver the signal. */ + handle_signal(signr, ka, &info, oldset, regs); + return 1; + } + + /* Did we come from a system call? */ + if (regs->orig_d0 >= 0) + /* Restart the system call - no handlers present */ + handle_restart(regs, NULL, 0); + + /* If we are about to discard some frame stuff we must copy + over the remaining frame. */ + if (regs->stkadj) { + struct pt_regs *tregs = + (struct pt_regs *) ((ulong) regs + regs->stkadj); + + /* This must be copied with decreasing addresses to + handle overlaps. */ + tregs->vector = 0; + tregs->format = 0; + tregs->pc = regs->pc; + tregs->sr = regs->sr; + } + return 0; +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/kernel/syscalltable.S linux.2.5.45-ac1/arch/m68knommu/kernel/syscalltable.S --- linux.2.5.45/arch/m68knommu/kernel/syscalltable.S 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/kernel/syscalltable.S 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,279 @@ +/* + * linux/arch/m68knommu/kernel/syscalltable.S + * + * Copyright (C) 2002, Greg Ungerer (gerg@snapgear.com) + * + * Based on older entry.S files, the following copyrights apply: + * + * Copyright (C) 1998 D. Jeff Dionne , + * Kenneth Albanowski , + * Copyright (C) 2000 Lineo Inc. (www.lineo.com) + * Copyright (C) 1991, 1992 Linus Torvalds + */ + +#include +#include +#include + +.text +ALIGN +ENTRY(sys_call_table) + .long sys_ni_syscall /* 0 - old "setup()" system call*/ + .long sys_exit + .long sys_fork + .long sys_read + .long sys_write + .long sys_open /* 5 */ + .long sys_close + .long sys_waitpid + .long sys_creat + .long sys_link + .long sys_unlink /* 10 */ + .long sys_execve + .long sys_chdir + .long sys_time + .long sys_mknod + .long sys_chmod /* 15 */ + .long sys_chown16 + .long sys_ni_syscall /* old break syscall holder */ + .long sys_stat + .long sys_lseek + .long sys_getpid /* 20 */ + .long sys_mount + .long sys_oldumount + .long sys_setuid16 + .long sys_getuid16 + .long sys_stime /* 25 */ + .long sys_ptrace + .long sys_alarm + .long sys_fstat + .long sys_pause + .long sys_utime /* 30 */ + .long sys_ni_syscall /* old stty syscall holder */ + .long sys_ni_syscall /* old gtty syscall holder */ + .long sys_access + .long sys_nice + .long sys_ni_syscall /* 35 */ /* old ftime syscall holder */ + .long sys_sync + .long sys_kill + .long sys_rename + .long sys_mkdir + .long sys_rmdir /* 40 */ + .long sys_dup + .long sys_pipe + .long sys_times + .long sys_ni_syscall /* old prof syscall holder */ + .long sys_brk /* 45 */ + .long sys_setgid16 + .long sys_getgid16 + .long sys_signal + .long sys_geteuid16 + .long sys_getegid16 /* 50 */ + .long sys_acct + .long sys_umount /* recycled never used phys() */ + .long sys_ni_syscall /* old lock syscall holder */ + .long sys_ioctl + .long sys_fcntl /* 55 */ + .long sys_ni_syscall /* old mpx syscall holder */ + .long sys_setpgid + .long sys_ni_syscall /* old ulimit syscall holder */ + .long sys_ni_syscall + .long sys_umask /* 60 */ + .long sys_chroot + .long sys_ustat + .long sys_dup2 + .long sys_getppid + .long sys_getpgrp /* 65 */ + .long sys_setsid + .long sys_sigaction + .long sys_sgetmask + .long sys_ssetmask + .long sys_setreuid16 /* 70 */ + .long sys_setregid16 + .long sys_sigsuspend + .long sys_sigpending + .long sys_sethostname + .long sys_setrlimit /* 75 */ + .long sys_old_getrlimit + .long sys_getrusage + .long sys_gettimeofday + .long sys_settimeofday + .long sys_getgroups16 /* 80 */ + .long sys_setgroups16 + .long old_select + .long sys_symlink + .long sys_lstat + .long sys_readlink /* 85 */ + .long sys_uselib + .long sys_ni_syscall /* sys_swapon */ + .long sys_reboot + .long old_readdir + .long old_mmap /* 90 */ + .long sys_munmap + .long sys_truncate + .long sys_ftruncate + .long sys_fchmod + .long sys_fchown16 /* 95 */ + .long sys_getpriority + .long sys_setpriority + .long sys_ni_syscall /* old profil syscall holder */ + .long sys_statfs + .long sys_fstatfs /* 100 */ + .long sys_ioperm + .long sys_socketcall + .long sys_syslog + .long sys_setitimer + .long sys_getitimer /* 105 */ + .long sys_newstat + .long sys_newlstat + .long sys_newfstat + .long sys_ni_syscall + .long sys_ni_syscall /* iopl for i386 */ /* 110 */ + .long sys_vhangup + .long sys_ni_syscall /* obsolete idle() syscall */ + .long sys_ni_syscall /* vm86old for i386 */ + .long sys_wait4 + .long sys_ni_syscall /* 115 */ /* sys_swapoff */ + .long sys_sysinfo + .long sys_ipc + .long sys_fsync + .long sys_sigreturn + .long sys_clone /* 120 */ + .long sys_setdomainname + .long sys_newuname + .long sys_cacheflush /* modify_ldt for i386 */ + .long sys_adjtimex + .long sys_ni_syscall /* 125 */ /* sys_mprotect */ + .long sys_sigprocmask + .long sys_create_module + .long sys_init_module + .long sys_delete_module + .long sys_get_kernel_syms /* 130 */ + .long sys_quotactl + .long sys_getpgid + .long sys_fchdir + .long sys_bdflush + .long sys_sysfs /* 135 */ + .long sys_personality + .long sys_ni_syscall /* for afs_syscall */ + .long sys_setfsuid16 + .long sys_setfsgid16 + .long sys_llseek /* 140 */ + .long sys_getdents + .long sys_select + .long sys_flock + .long sys_ni_syscall /* sys_msync */ + .long sys_readv /* 145 */ + .long sys_writev + .long sys_getsid + .long sys_fdatasync + .long sys_sysctl + .long sys_ni_syscall /* 150 */ /* sys_mlock */ + .long sys_ni_syscall /* sys_munlock */ + .long sys_ni_syscall /* sys_mlockall */ + .long sys_ni_syscall /* sys_munlockall */ + .long sys_sched_setparam + .long sys_sched_getparam /* 155 */ + .long sys_sched_setscheduler + .long sys_sched_getscheduler + .long sys_sched_yield + .long sys_sched_get_priority_max + .long sys_sched_get_priority_min /* 160 */ + .long sys_sched_rr_get_interval + .long sys_nanosleep + .long sys_ni_syscall /* sys_mremap */ + .long sys_setresuid16 + .long sys_getresuid16 /* 165 */ + .long sys_ni_syscall /* for vm86 */ + .long sys_query_module + .long sys_poll + .long sys_ni_syscall /*sys_nfsservctl*/ + .long sys_setresgid16 /* 170 */ + .long sys_getresgid16 + .long sys_prctl + .long sys_rt_sigreturn + .long sys_rt_sigaction + .long sys_rt_sigprocmask /* 175 */ + .long sys_rt_sigpending + .long sys_rt_sigtimedwait + .long sys_rt_sigqueueinfo + .long sys_rt_sigsuspend + .long sys_pread64 /* 180 */ + .long sys_pwrite64 + .long sys_lchown16 + .long sys_getcwd + .long sys_capget + .long sys_capset /* 185 */ + .long sys_sigaltstack + .long sys_sendfile + .long sys_ni_syscall /* streams1 */ + .long sys_ni_syscall /* streams2 */ + .long sys_vfork /* 190 */ + .long sys_getrlimit + .long sys_mmap2 + .long sys_truncate64 + .long sys_ftruncate64 + .long sys_stat64 /* 195 */ + .long sys_lstat64 + .long sys_fstat64 + .long sys_chown + .long sys_getuid + .long sys_getgid /* 200 */ + .long sys_geteuid + .long sys_getegid + .long sys_setreuid + .long sys_setregid + .long sys_getgroups /* 205 */ + .long sys_setgroups + .long sys_fchown + .long sys_setresuid + .long sys_getresuid + .long sys_setresgid /* 210 */ + .long sys_getresgid + .long sys_lchown + .long sys_setuid + .long sys_setgid + .long sys_setfsuid /* 215 */ + .long sys_setfsgid + .long sys_pivot_root + .long sys_mincore + .long sys_ni_syscall /* sys_madvise */ + .long sys_getdents64 /* 220 */ + .long sys_fcntl64 + .long sys_ni_syscall /* reserved for TUX */ + .long sys_security /* reserved for Security */ + .long sys_gettid + .long sys_ni_syscall /* 225 */ /* sys_readahead */ + .long sys_setxattr + .long sys_lsetxattr + .long sys_fsetxattr + .long sys_getxattr + .long sys_lgetxattr /* 230 */ + .long sys_fgetxattr + .long sys_listxattr + .long sys_llistxattr + .long sys_flistxattr + .long sys_removexattr /* 235 */ + .long sys_lremovexattr + .long sys_fremovexattr + .long sys_tkill + .long sys_sendfile64 + .long sys_futex /* 240 */ + .long sys_sched_setaffinity + .long sys_sched_getaffinity + .long sys_ni_syscall /* sys_set_thread_area */ + .long sys_ni_syscall /* sys_get_thread_area */ + .long sys_io_setup /* 245 */ + .long sys_io_destroy + .long sys_io_getevents + .long sys_io_submit + .long sys_io_cancel + .long sys_ni_syscall /* 250 */ /* sys_alloc_hugepages */ + .long sys_ni_syscall /* sys_freec_hugepages */ + .long sys_exit_group + .long sys_lookup_dcookie + + .rept NR_syscalls-(.-sys_call_table)/4 + .long sys_ni_syscall + .endr + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/kernel/sys_m68k.c linux.2.5.45-ac1/arch/m68knommu/kernel/sys_m68k.c --- linux.2.5.45/arch/m68knommu/kernel/sys_m68k.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/kernel/sys_m68k.c 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,215 @@ +/* + * linux/arch/m68knommu/kernel/sys_m68k.c + * + * This file contains various random system calls that + * have a non-standard calling sequence on the Linux/m68k + * platform. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +/* + * sys_pipe() is the normal C calling standard for creating + * a pipe. It's not the way unix traditionally does this, though. + */ +asmlinkage int sys_pipe(unsigned long * fildes) +{ + int fd[2]; + int error; + + error = do_pipe(fd); + if (!error) { + if (copy_to_user(fildes, fd, 2*sizeof(int))) + error = -EFAULT; + } + return error; +} + +/* common code for old and new mmaps */ +static inline long do_mmap2( + unsigned long addr, unsigned long len, + unsigned long prot, unsigned long flags, + unsigned long fd, unsigned long pgoff) +{ + int error = -EBADF; + struct file * file = NULL; + + flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); + if (!(flags & MAP_ANONYMOUS)) { + file = fget(fd); + if (!file) + goto out; + } + + down_write(¤t->mm->mmap_sem); + error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); + up_write(¤t->mm->mmap_sem); + + if (file) + fput(file); +out: + return error; +} + +asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, + unsigned long prot, unsigned long flags, + unsigned long fd, unsigned long pgoff) +{ + return do_mmap2(addr, len, prot, flags, fd, pgoff); +} + +/* + * Perform the select(nd, in, out, ex, tv) and mmap() system + * calls. Linux/m68k cloned Linux/i386, which didn't use to be able to + * handle more than 4 system call parameters, so these system calls + * used a memory block for parameter passing.. + */ + +struct mmap_arg_struct { + unsigned long addr; + unsigned long len; + unsigned long prot; + unsigned long flags; + unsigned long fd; + unsigned long offset; +}; + +asmlinkage int old_mmap(struct mmap_arg_struct *arg) +{ + struct mmap_arg_struct a; + int error = -EFAULT; + + if (copy_from_user(&a, arg, sizeof(a))) + goto out; + + error = -EINVAL; + if (a.offset & ~PAGE_MASK) + goto out; + + a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); + + error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT); +out: + return error; +} + +extern asmlinkage int sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *); + +struct sel_arg_struct { + unsigned long n; + fd_set *inp, *outp, *exp; + struct timeval *tvp; +}; + +asmlinkage int old_select(struct sel_arg_struct *arg) +{ + struct sel_arg_struct a; + + if (copy_from_user(&a, arg, sizeof(a))) + return -EFAULT; + /* sys_select() does the appropriate kernel locking */ + return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp); +} + +/* + * sys_ipc() is the de-multiplexer for the SysV IPC calls.. + * + * This is really horribly ugly. + */ +asmlinkage int sys_ipc (uint call, int first, int second, + int third, void *ptr, long fifth) +{ + int version; + + version = call >> 16; /* hack for backward compatibility */ + call &= 0xffff; + + if (call <= SEMCTL) + switch (call) { + case SEMOP: + return sys_semop (first, (struct sembuf *)ptr, second); + case SEMGET: + return sys_semget (first, second, third); + case SEMCTL: { + union semun fourth; + if (!ptr) + return -EINVAL; + if (get_user(fourth.__pad, (void **) ptr)) + return -EFAULT; + return sys_semctl (first, second, third, fourth); + } + default: + return -EINVAL; + } + if (call <= MSGCTL) + switch (call) { + case MSGSND: + return sys_msgsnd (first, (struct msgbuf *) ptr, + second, third); + case MSGRCV: + switch (version) { + case 0: { + struct ipc_kludge tmp; + if (!ptr) + return -EINVAL; + if (copy_from_user (&tmp, + (struct ipc_kludge *)ptr, + sizeof (tmp))) + return -EFAULT; + return sys_msgrcv (first, tmp.msgp, second, + tmp.msgtyp, third); + } + default: + return sys_msgrcv (first, + (struct msgbuf *) ptr, + second, fifth, third); + } + case MSGGET: + return sys_msgget ((key_t) first, second); + case MSGCTL: + return sys_msgctl (first, second, + (struct msqid_ds *) ptr); + default: + return -EINVAL; + } + + return -EINVAL; +} + +asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on) +{ + return -ENOSYS; +} + + +/* sys_cacheflush -- flush (part of) the processor cache. */ +asmlinkage int +sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len) +{ + flush_cache_all(); + return(0); +} + +asmlinkage int sys_getpagesize(void) +{ + return PAGE_SIZE; +} + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/kernel/time.c linux.2.5.45-ac1/arch/m68knommu/kernel/time.c --- linux.2.5.45/arch/m68knommu/kernel/time.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/kernel/time.c 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,178 @@ +/* + * linux/arch/m68knommu/kernel/time.c + * + * Copyright (C) 1991, 1992, 1995 Linus Torvalds + * + * This file contains the m68k-specific time handling details. + * Most of the stuff is located in the machine specific files. + * + * 1997-09-10 Updated NTP code according to technical memorandum Jan '96 + * "A Kernel Model for Precision Timekeeping" by Dave Mills + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define TICK_SIZE (tick_nsec / 1000) + +u64 jiffies_64; + +static inline int set_rtc_mmss(unsigned long nowtime) +{ + if (mach_set_clock_mmss) + return mach_set_clock_mmss (nowtime); + return -1; +} + +static inline void do_profile (unsigned long pc) +{ + if (prof_buffer && current->pid) { + extern int _stext; + pc -= (unsigned long) &_stext; + pc >>= prof_shift; + if (pc < prof_len) + ++prof_buffer[pc]; + else + /* + * Don't ignore out-of-bounds PC values silently, + * put them into the last histogram slot, so if + * present, they will show up as a sharp peak. + */ + ++prof_buffer[prof_len-1]; + } +} + +/* + * timer_interrupt() needs to keep up the real-time clock, + * as well as call the "do_timer()" routine every clocktick + */ +static void timer_interrupt(int irq, void *dummy, struct pt_regs * regs) +{ + /* last time the cmos clock got updated */ + static long last_rtc_update=0; + + /* may need to kick the hardware timer */ + if (mach_tick) + mach_tick(); + + do_timer(regs); + + if (!user_mode(regs)) + do_profile(regs->pc); + + /* + * If we have an externally synchronized Linux clock, then update + * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be + * called as close as possible to 500 ms before the new second starts. + */ + if ((time_status & STA_UNSYNC) == 0 && + xtime.tv_sec > last_rtc_update + 660 && + (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 && + (xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) { + if (set_rtc_mmss(xtime.tv_sec) == 0) + last_rtc_update = xtime.tv_sec; + else + last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */ + } +#ifdef CONFIG_HEARTBEAT + /* use power LED as a heartbeat instead -- much more useful + for debugging -- based on the version for PReP by Cort */ + /* acts like an actual heart beat -- ie thump-thump-pause... */ + if (mach_heartbeat) { + static unsigned cnt = 0, period = 0, dist = 0; + + if (cnt == 0 || cnt == dist) + mach_heartbeat( 1 ); + else if (cnt == 7 || cnt == dist+7) + mach_heartbeat( 0 ); + + if (++cnt > period) { + cnt = 0; + /* The hyperbolic function below modifies the heartbeat period + * length in dependency of the current (5min) load. It goes + * through the points f(0)=126, f(1)=86, f(5)=51, + * f(inf)->30. */ + period = ((672<= 1000000) { + usec -= 1000000; + sec++; + } + + tv->tv_sec = sec; + tv->tv_usec = usec; +} + +void do_settimeofday(struct timeval *tv) +{ + write_lock_irq(&xtime_lock); + /* This is revolting. We need to set the xtime.tv_usec + * correctly. However, the value in this location is + * is value at the last tick. + * Discover what correction gettimeofday + * would have done, and then undo it! + */ + if (mach_gettimeoffset) + tv->tv_usec -= mach_gettimeoffset(); + + while (tv->tv_usec < 0) { + tv->tv_usec += 1000000; + tv->tv_sec--; + } + + xtime.tv_sec = tv->tv_sec; + xtime.tv_nsec = (tv->tv_usec * 1000); + time_adjust = 0; /* stop active adjtime() */ + time_status |= STA_UNSYNC; + time_maxerror = NTP_PHASE_LIMIT; + time_esterror = NTP_PHASE_LIMIT; + write_unlock_irq(&xtime_lock); +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/kernel/traps.c linux.2.5.45-ac1/arch/m68knommu/kernel/traps.c --- linux.2.5.45/arch/m68knommu/kernel/traps.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/kernel/traps.c 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,313 @@ +/* + * linux/arch/m68knommu/kernel/traps.c + * + * Copyright (C) 1993, 1994 by Hamish Macdonald + * + * 68040 fixes by Michael Rausch + * 68040 fixes by Martin Apel + * 68060 fixes by Roman Hodek + * 68060 fixes by Jesper Skov + * + * 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. + */ + +/* + * Sets up all exception vectors + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +static char *vec_names[] = { + "RESET SP", "RESET PC", "BUS ERROR", "ADDRESS ERROR", + "ILLEGAL INSTRUCTION", "ZERO DIVIDE", "CHK", "TRAPcc", + "PRIVILEGE VIOLATION", "TRACE", "LINE 1010", "LINE 1111", + "UNASSIGNED RESERVED 12", "COPROCESSOR PROTOCOL VIOLATION", + "FORMAT ERROR", "UNINITIALIZED INTERRUPT", + "UNASSIGNED RESERVED 16", "UNASSIGNED RESERVED 17", + "UNASSIGNED RESERVED 18", "UNASSIGNED RESERVED 19", + "UNASSIGNED RESERVED 20", "UNASSIGNED RESERVED 21", + "UNASSIGNED RESERVED 22", "UNASSIGNED RESERVED 23", + "SPURIOUS INTERRUPT", "LEVEL 1 INT", "LEVEL 2 INT", "LEVEL 3 INT", + "LEVEL 4 INT", "LEVEL 5 INT", "LEVEL 6 INT", "LEVEL 7 INT", + "SYSCALL", "TRAP #1", "TRAP #2", "TRAP #3", + "TRAP #4", "TRAP #5", "TRAP #6", "TRAP #7", + "TRAP #8", "TRAP #9", "TRAP #10", "TRAP #11", + "TRAP #12", "TRAP #13", "TRAP #14", "TRAP #15", + "FPCP BSUN", "FPCP INEXACT", "FPCP DIV BY 0", "FPCP UNDERFLOW", + "FPCP OPERAND ERROR", "FPCP OVERFLOW", "FPCP SNAN", + "FPCP UNSUPPORTED OPERATION", + "MMU CONFIGURATION ERROR" +}; + +void __init trap_init(void) +{ + if (mach_trap_init) + mach_trap_init(); +} + +void die_if_kernel(char *str, struct pt_regs *fp, int nr) +{ + if (!(fp->sr & PS_S)) + return; + + console_verbose(); + printk("%s: %08x\n",str,nr); + printk("PC: [<%08lx>]\nSR: %04x SP: %p a2: %08lx\n", + fp->pc, fp->sr, fp, fp->a2); + printk("d0: %08lx d1: %08lx d2: %08lx d3: %08lx\n", + fp->d0, fp->d1, fp->d2, fp->d3); + printk("d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n", + fp->d4, fp->d5, fp->a0, fp->a1); + + printk("Process %s (pid: %d, stackpage=%08lx)\n", + current->comm, current->pid, PAGE_SIZE+(unsigned long)current); + show_stack((unsigned long *)fp); + do_exit(SIGSEGV); +} + +asmlinkage void buserr_c(struct frame *fp) +{ + /* Only set esp0 if coming from user mode */ + if (user_mode(&fp->ptregs)) + current->thread.esp0 = (unsigned long) fp; + +#if DEBUG + printk ("*** Bus Error *** Format is %x\n", fp->ptregs.format); +#endif + + die_if_kernel("bad frame format",&fp->ptregs,0); +#if DEBUG + printk("Unknown SIGSEGV - 4\n"); +#endif + force_sig(SIGSEGV, current); +} + + +int kstack_depth_to_print = 48; + +void show_stack(unsigned long *esp) +{ + unsigned long *stack, *endstack, addr; + extern char _start, _etext; + int i; + + if (esp == NULL) + esp = (unsigned long *) &esp; + + stack = esp; + addr = (unsigned long) esp; + endstack = (unsigned long *) PAGE_ALIGN(addr); + + printk("Stack from %08lx:", (unsigned long)stack); + for (i = 0; i < kstack_depth_to_print; i++) { + if (stack + 1 > endstack) + break; + if (i % 8 == 0) + printk("\n "); + printk(" %08lx", *stack++); + } + + printk("\nCall Trace:"); + i = 0; + while (stack + 1 <= endstack) { + addr = *stack++; + /* + * If the address is either in the text segment of the + * kernel, or in the region which contains vmalloc'ed + * memory, it *may* be the address of a calling + * routine; if so, print it so that someone tracing + * down the cause of the crash will be able to figure + * out the call path that was taken. + */ + if (((addr >= (unsigned long) &_start) && + (addr <= (unsigned long) &_etext))) { + if (i % 4 == 0) + printk("\n "); + printk(" [<%08lx>]", addr); + i++; + } + } + printk("\n"); +} + +void bad_super_trap(struct frame *fp) +{ + console_verbose(); + if (fp->ptregs.vector < 4*sizeof(vec_names)/sizeof(vec_names[0])) + printk ("*** %s *** FORMAT=%X\n", + vec_names[(fp->ptregs.vector) >> 2], + fp->ptregs.format); + else + printk ("*** Exception %d *** FORMAT=%X\n", + (fp->ptregs.vector) >> 2, + fp->ptregs.format); + printk ("Current process id is %d\n", current->pid); + die_if_kernel("BAD KERNEL TRAP", &fp->ptregs, 0); +} + +asmlinkage void trap_c(struct frame *fp) +{ + int sig; + siginfo_t info; + + if (fp->ptregs.sr & PS_S) { + if ((fp->ptregs.vector >> 2) == VEC_TRACE) { + /* traced a trapping instruction */ + current->ptrace |= PT_DTRACE; + } else + bad_super_trap(fp); + return; + } + + /* send the appropriate signal to the user program */ + switch ((fp->ptregs.vector) >> 2) { + case VEC_ADDRERR: + info.si_code = BUS_ADRALN; + sig = SIGBUS; + break; + case VEC_ILLEGAL: + case VEC_LINE10: + case VEC_LINE11: + info.si_code = ILL_ILLOPC; + sig = SIGILL; + break; + case VEC_PRIV: + info.si_code = ILL_PRVOPC; + sig = SIGILL; + break; + case VEC_COPROC: + info.si_code = ILL_COPROC; + sig = SIGILL; + break; + case VEC_TRAP1: /* gdbserver breakpoint */ + fp->ptregs.pc -= 2; + info.si_code = TRAP_TRACE; + sig = SIGTRAP; + break; + case VEC_TRAP2: + case VEC_TRAP3: + case VEC_TRAP4: + case VEC_TRAP5: + case VEC_TRAP6: + case VEC_TRAP7: + case VEC_TRAP8: + case VEC_TRAP9: + case VEC_TRAP10: + case VEC_TRAP11: + case VEC_TRAP12: + case VEC_TRAP13: + case VEC_TRAP14: + info.si_code = ILL_ILLTRP; + sig = SIGILL; + break; + case VEC_FPBRUC: + case VEC_FPOE: + case VEC_FPNAN: + info.si_code = FPE_FLTINV; + sig = SIGFPE; + break; + case VEC_FPIR: + info.si_code = FPE_FLTRES; + sig = SIGFPE; + break; + case VEC_FPDIVZ: + info.si_code = FPE_FLTDIV; + sig = SIGFPE; + break; + case VEC_FPUNDER: + info.si_code = FPE_FLTUND; + sig = SIGFPE; + break; + case VEC_FPOVER: + info.si_code = FPE_FLTOVF; + sig = SIGFPE; + break; + case VEC_ZERODIV: + info.si_code = FPE_INTDIV; + sig = SIGFPE; + break; + case VEC_CHK: + case VEC_TRAP: + info.si_code = FPE_INTOVF; + sig = SIGFPE; + break; + case VEC_TRACE: /* ptrace single step */ + info.si_code = TRAP_TRACE; + sig = SIGTRAP; + break; + case VEC_TRAP15: /* breakpoint */ + info.si_code = TRAP_BRKPT; + sig = SIGTRAP; + break; + default: + info.si_code = ILL_ILLOPC; + sig = SIGILL; + break; + } + info.si_signo = sig; + info.si_errno = 0; + switch (fp->ptregs.format) { + default: + info.si_addr = (void *) fp->ptregs.pc; + break; + case 2: + info.si_addr = (void *) fp->un.fmt2.iaddr; + break; + case 7: + info.si_addr = (void *) fp->un.fmt7.effaddr; + break; + case 9: + info.si_addr = (void *) fp->un.fmt9.iaddr; + break; + case 10: + info.si_addr = (void *) fp->un.fmta.daddr; + break; + case 11: + info.si_addr = (void *) fp->un.fmtb.daddr; + break; + } + force_sig_info (sig, &info, current); +} + +asmlinkage void set_esp0(unsigned long ssp) +{ + current->thread.esp0 = ssp; +} + +void show_trace_task(struct task_struct *tsk) +{ + printk("STACK ksp=0x%lx, usp=0x%lx\n", tsk->thread.ksp, tsk->thread.usp); +} + +#ifdef CONFIG_M68KFPU_EMU +asmlinkage void fpemu_signal(int signal, int code, void *addr) +{ + siginfo_t info; + + info.si_signo = signal; + info.si_errno = 0; + info.si_code = code; + info.si_addr = addr; + force_sig_info(signal, &info, current); +} +#endif diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/lib/ashldi3.c linux.2.5.45-ac1/arch/m68knommu/lib/ashldi3.c --- linux.2.5.45/arch/m68knommu/lib/ashldi3.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/lib/ashldi3.c 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,62 @@ +/* ashrdi3.c extracted from gcc-2.95.2/libgcc2.c which is: */ +/* Copyright (C) 1989, 92-98, 1999 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC 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. + +GNU CC 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 GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#define BITS_PER_UNIT 8 + +typedef int SItype __attribute__ ((mode (SI))); +typedef unsigned int USItype __attribute__ ((mode (SI))); +typedef int DItype __attribute__ ((mode (DI))); +typedef int word_type __attribute__ ((mode (__word__))); + +struct DIstruct {SItype high, low;}; + +typedef union +{ + struct DIstruct s; + DItype ll; +} DIunion; + +DItype +__ashldi3 (DItype u, word_type b) +{ + DIunion w; + word_type bm; + DIunion uu; + + if (b == 0) + return u; + + uu.ll = u; + + bm = (sizeof (SItype) * BITS_PER_UNIT) - b; + if (bm <= 0) + { + w.s.low = 0; + w.s.high = (USItype)uu.s.low << -bm; + } + else + { + USItype carries = (USItype)uu.s.low >> bm; + w.s.low = (USItype)uu.s.low << b; + w.s.high = ((USItype)uu.s.high << b) | carries; + } + + return w.ll; +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/lib/ashrdi3.c linux.2.5.45-ac1/arch/m68knommu/lib/ashrdi3.c --- linux.2.5.45/arch/m68knommu/lib/ashrdi3.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/lib/ashrdi3.c 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,63 @@ +/* ashrdi3.c extracted from gcc-2.7.2/libgcc2.c which is: */ +/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC 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. + +GNU CC 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 GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#define BITS_PER_UNIT 8 + +typedef int SItype __attribute__ ((mode (SI))); +typedef unsigned int USItype __attribute__ ((mode (SI))); +typedef int DItype __attribute__ ((mode (DI))); +typedef int word_type __attribute__ ((mode (__word__))); + +struct DIstruct {SItype high, low;}; + +typedef union +{ + struct DIstruct s; + DItype ll; +} DIunion; + +DItype +__ashrdi3 (DItype u, word_type b) +{ + DIunion w; + word_type bm; + DIunion uu; + + if (b == 0) + return u; + + uu.ll = u; + + bm = (sizeof (SItype) * BITS_PER_UNIT) - b; + if (bm <= 0) + { + /* w.s.high = 1..1 or 0..0 */ + w.s.high = uu.s.high >> (sizeof (SItype) * BITS_PER_UNIT - 1); + w.s.low = uu.s.high >> -bm; + } + else + { + USItype carries = (USItype)uu.s.high << bm; + w.s.high = uu.s.high >> b; + w.s.low = ((USItype)uu.s.low >> b) | carries; + } + + return w.ll; +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/lib/checksum.c linux.2.5.45-ac1/arch/m68knommu/lib/checksum.c --- linux.2.5.45/arch/m68knommu/lib/checksum.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/lib/checksum.c 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,156 @@ +/* + * INET An implementation of the TCP/IP protocol suite for the LINUX + * operating system. INET is implemented using the BSD Socket + * interface as the means of communication with the user level. + * + * IP/TCP/UDP checksumming routines + * + * Authors: Jorge Cwik, + * Arnt Gulbrandsen, + * Tom May, + * Andreas Schwab, + * Lots of code moved from tcp.c and ip.c; see those files + * for more names. + * + * 03/02/96 Jes Sorensen, Andreas Schwab, Roman Hodek: + * Fixed some nasty bugs, causing some horrible crashes. + * A: At some points, the sum (%0) was used as + * length-counter instead of the length counter + * (%1). Thanks to Roman Hodek for pointing this out. + * B: GCC seems to mess up if one uses too many + * data-registers to hold input values and one tries to + * specify d0 and d1 as scratch registers. Letting gcc choose these + * registers itself solves the problem. + * + * 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. + */ + +/* Revised by Kenneth Albanowski for m68knommu. Basic problem: unaligned access kills, so most + of the assembly has to go. */ + +#include + +static inline unsigned short from32to16(unsigned long x) +{ + /* add up 16-bit and 16-bit for 16+c bit */ + x = (x & 0xffff) + (x >> 16); + /* add up carry.. */ + x = (x & 0xffff) + (x >> 16); + return x; +} + +static unsigned long do_csum(const unsigned char * buff, int len) +{ + int odd, count; + unsigned long result = 0; + + if (len <= 0) + goto out; + odd = 1 & (unsigned long) buff; + if (odd) { + result = *buff; + len--; + buff++; + } + count = len >> 1; /* nr of 16-bit words.. */ + if (count) { + if (2 & (unsigned long) buff) { + result += *(unsigned short *) buff; + count--; + len -= 2; + buff += 2; + } + count >>= 1; /* nr of 32-bit words.. */ + if (count) { + unsigned long carry = 0; + do { + unsigned long w = *(unsigned long *) buff; + count--; + buff += 4; + result += carry; + result += w; + carry = (w > result); + } while (count); + result += carry; + result = (result & 0xffff) + (result >> 16); + } + if (len & 2) { + result += *(unsigned short *) buff; + buff += 2; + } + } + if (len & 1) + result += (*buff << 8); + result = from32to16(result); + if (odd) + result = ((result >> 8) & 0xff) | ((result & 0xff) << 8); +out: + return result; +} + +/* + * This is a version of ip_compute_csum() optimized for IP headers, + * which always checksum on 4 octet boundaries. + */ +unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl) +{ + return ~do_csum(iph,ihl*4); +} + +/* + * computes the checksum of a memory block at buff, length len, + * and adds in "sum" (32-bit) + * + * returns a 32-bit number suitable for feeding into itself + * or csum_tcpudp_magic + * + * this function must be called with even lengths, except + * for the last fragment, which may be odd + * + * it's best to have buff aligned on a 32-bit boundary + */ +unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum) +{ + unsigned int result = do_csum(buff, len); + + /* add in old sum, and carry.. */ + result += sum; + if (sum > result) + result += 1; + return result; +} + +/* + * this routine is used for miscellaneous IP-like checksums, mainly + * in icmp.c + */ +unsigned short ip_compute_csum(const unsigned char * buff, int len) +{ + return ~do_csum(buff,len); +} + +/* + * copy from fs while checksumming, otherwise like csum_partial + */ + +unsigned int +csum_partial_copy_from_user(const char *src, char *dst, int len, int sum, int *csum_err) +{ + if (csum_err) *csum_err = 0; + memcpy(dst, src, len); + return csum_partial(dst, len, sum); +} + +/* + * copy from ds while checksumming, otherwise like csum_partial + */ + +unsigned int +csum_partial_copy(const char *src, char *dst, int len, int sum) +{ + memcpy(dst, src, len); + return csum_partial(dst, len, sum); +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/lib/divsi3.S linux.2.5.45-ac1/arch/m68knommu/lib/divsi3.S --- linux.2.5.45/arch/m68knommu/lib/divsi3.S 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/lib/divsi3.S 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,125 @@ +/* libgcc1 routines for 68000 w/o floating-point hardware. + Copyright (C) 1994, 1996, 1997, 1998 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC 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. + +In addition to the permissions in the GNU General Public License, the +Free Software Foundation gives you unlimited permission to link the +compiled version of this file with other programs, and to distribute +those programs without any restriction coming from the use of this +file. (The General Public License restrictions do apply in other +respects; for example, they cover modification of the file, and +distribution when not linked into another program.) + +This file 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; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* As a special exception, if you link this library with files + compiled with GCC to produce an executable, this does not cause + the resulting executable to be covered by the GNU General Public License. + This exception does not however invalidate any other reasons why + the executable file might be covered by the GNU General Public License. */ + +/* Use this one for any 680x0; assumes no floating point hardware. + The trailing " '" appearing on some lines is for ANSI preprocessors. Yuk. + Some of this code comes from MINIX, via the folks at ericsson. + D. V. Henkel-Wallace (gumby@cygnus.com) Fete Bastille, 1992 +*/ + +/* These are predefined by new versions of GNU cpp. */ + +#ifndef __USER_LABEL_PREFIX__ +#define __USER_LABEL_PREFIX__ _ +#endif + +#ifndef __REGISTER_PREFIX__ +#define __REGISTER_PREFIX__ +#endif + +#ifndef __IMMEDIATE_PREFIX__ +#define __IMMEDIATE_PREFIX__ # +#endif + +/* ANSI concatenation macros. */ + +#define CONCAT1(a, b) CONCAT2(a, b) +#define CONCAT2(a, b) a ## b + +/* Use the right prefix for global labels. */ + +#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x) + +/* Use the right prefix for registers. */ + +#define REG(x) CONCAT1 (__REGISTER_PREFIX__, x) + +/* Use the right prefix for immediate values. */ + +#define IMM(x) CONCAT1 (__IMMEDIATE_PREFIX__, x) + +#define d0 REG (d0) +#define d1 REG (d1) +#define d2 REG (d2) +#define d3 REG (d3) +#define d4 REG (d4) +#define d5 REG (d5) +#define d6 REG (d6) +#define d7 REG (d7) +#define a0 REG (a0) +#define a1 REG (a1) +#define a2 REG (a2) +#define a3 REG (a3) +#define a4 REG (a4) +#define a5 REG (a5) +#define a6 REG (a6) +#define fp REG (fp) +#define sp REG (sp) + + .text + .proc + .globl SYM (__divsi3) +SYM (__divsi3): + movel d2, sp@- + + moveq IMM (1), d2 /* sign of result stored in d2 (=1 or =-1) */ + movel sp@(12), d1 /* d1 = divisor */ + jpl L1 + negl d1 +#ifndef __mcf5200__ + negb d2 /* change sign because divisor <0 */ +#else + negl d2 /* change sign because divisor <0 */ +#endif +L1: movel sp@(8), d0 /* d0 = dividend */ + jpl L2 + negl d0 +#ifndef __mcf5200__ + negb d2 +#else + negl d2 +#endif + +L2: movel d1, sp@- + movel d0, sp@- + jbsr SYM (__udivsi3) /* divide abs(dividend) by abs(divisor) */ + addql IMM (8), sp + + tstb d2 + jpl L3 + negl d0 + +L3: movel sp@+, d2 + rts + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/lib/lshrdi3.c linux.2.5.45-ac1/arch/m68knommu/lib/lshrdi3.c --- linux.2.5.45/arch/m68knommu/lib/lshrdi3.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/lib/lshrdi3.c 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,62 @@ +/* lshrdi3.c extracted from gcc-2.7.2/libgcc2.c which is: */ +/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC 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. + +GNU CC 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 GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#define BITS_PER_UNIT 8 + +typedef int SItype __attribute__ ((mode (SI))); +typedef unsigned int USItype __attribute__ ((mode (SI))); +typedef int DItype __attribute__ ((mode (DI))); +typedef int word_type __attribute__ ((mode (__word__))); + +struct DIstruct {SItype high, low;}; + +typedef union +{ + struct DIstruct s; + DItype ll; +} DIunion; + +DItype +__lshrdi3 (DItype u, word_type b) +{ + DIunion w; + word_type bm; + DIunion uu; + + if (b == 0) + return u; + + uu.ll = u; + + bm = (sizeof (SItype) * BITS_PER_UNIT) - b; + if (bm <= 0) + { + w.s.high = 0; + w.s.low = (USItype)uu.s.high >> -bm; + } + else + { + USItype carries = (USItype)uu.s.high << bm; + w.s.high = (USItype)uu.s.high >> b; + w.s.low = ((USItype)uu.s.low >> b) | carries; + } + + return w.ll; +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/lib/Makefile linux.2.5.45-ac1/arch/m68knommu/lib/Makefile --- linux.2.5.45/arch/m68knommu/lib/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/lib/Makefile 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,10 @@ +# +# Makefile for m68knommu specific library files.. +# + +L_TARGET = lib.a +obj-y := ashldi3.o ashrdi3.o lshrdi3.o \ + muldi3.o mulsi3.o divsi3.o udivsi3.o modsi3.o umodsi3.o \ + checksum.o semaphore.o memcpy.o memset.o + +include $(TOPDIR)/Rules.make diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/lib/memcpy.c linux.2.5.45-ac1/arch/m68knommu/lib/memcpy.c --- linux.2.5.45/arch/m68knommu/lib/memcpy.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/lib/memcpy.c 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,63 @@ + +#include +#include + +void * memcpy(void * to, const void * from, size_t n) +{ +#ifdef CONFIG_COLDFIRE + void *xto = to; + size_t temp; + + if (!n) + return xto; + if ((long) to & 1) + { + char *cto = to; + const char *cfrom = from; + *cto++ = *cfrom++; + to = cto; + from = cfrom; + n--; + } + if (n > 2 && (long) to & 2) + { + short *sto = to; + const short *sfrom = from; + *sto++ = *sfrom++; + to = sto; + from = sfrom; + n -= 2; + } + temp = n >> 2; + if (temp) + { + long *lto = to; + const long *lfrom = from; + for (; temp; temp--) + *lto++ = *lfrom++; + to = lto; + from = lfrom; + } + if (n & 2) + { + short *sto = to; + const short *sfrom = from; + *sto++ = *sfrom++; + to = sto; + from = sfrom; + } + if (n & 1) + { + char *cto = to; + const char *cfrom = from; + *cto = *cfrom; + } + return xto; +#else + const char *c_from = from; + char *c_to = to; + while (n-- > 0) + *c_to++ = *c_from++; + return((void *) to); +#endif +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/lib/memset.c linux.2.5.45-ac1/arch/m68knommu/lib/memset.c --- linux.2.5.45/arch/m68knommu/lib/memset.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/lib/memset.c 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,47 @@ +#include + +void * memset(void * s, int c, size_t count) +{ + void *xs = s; + size_t temp; + + if (!count) + return xs; + c &= 0xff; + c |= c << 8; + c |= c << 16; + if ((long) s & 1) + { + char *cs = s; + *cs++ = c; + s = cs; + count--; + } + if (count > 2 && (long) s & 2) + { + short *ss = s; + *ss++ = c; + s = ss; + count -= 2; + } + temp = count >> 2; + if (temp) + { + long *ls = s; + for (; temp; temp--) + *ls++ = c; + s = ls; + } + if (count & 2) + { + short *ss = s; + *ss++ = c; + s = ss; + } + if (count & 1) + { + char *cs = s; + *cs = c; + } + return xs; +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/lib/modsi3.S linux.2.5.45-ac1/arch/m68knommu/lib/modsi3.S --- linux.2.5.45/arch/m68knommu/lib/modsi3.S 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/lib/modsi3.S 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,113 @@ +/* libgcc1 routines for 68000 w/o floating-point hardware. + Copyright (C) 1994, 1996, 1997, 1998 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC 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. + +In addition to the permissions in the GNU General Public License, the +Free Software Foundation gives you unlimited permission to link the +compiled version of this file with other programs, and to distribute +those programs without any restriction coming from the use of this +file. (The General Public License restrictions do apply in other +respects; for example, they cover modification of the file, and +distribution when not linked into another program.) + +This file 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; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* As a special exception, if you link this library with files + compiled with GCC to produce an executable, this does not cause + the resulting executable to be covered by the GNU General Public License. + This exception does not however invalidate any other reasons why + the executable file might be covered by the GNU General Public License. */ + +/* Use this one for any 680x0; assumes no floating point hardware. + The trailing " '" appearing on some lines is for ANSI preprocessors. Yuk. + Some of this code comes from MINIX, via the folks at ericsson. + D. V. Henkel-Wallace (gumby@cygnus.com) Fete Bastille, 1992 +*/ + +/* These are predefined by new versions of GNU cpp. */ + +#ifndef __USER_LABEL_PREFIX__ +#define __USER_LABEL_PREFIX__ _ +#endif + +#ifndef __REGISTER_PREFIX__ +#define __REGISTER_PREFIX__ +#endif + +#ifndef __IMMEDIATE_PREFIX__ +#define __IMMEDIATE_PREFIX__ # +#endif + +/* ANSI concatenation macros. */ + +#define CONCAT1(a, b) CONCAT2(a, b) +#define CONCAT2(a, b) a ## b + +/* Use the right prefix for global labels. */ + +#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x) + +/* Use the right prefix for registers. */ + +#define REG(x) CONCAT1 (__REGISTER_PREFIX__, x) + +/* Use the right prefix for immediate values. */ + +#define IMM(x) CONCAT1 (__IMMEDIATE_PREFIX__, x) + +#define d0 REG (d0) +#define d1 REG (d1) +#define d2 REG (d2) +#define d3 REG (d3) +#define d4 REG (d4) +#define d5 REG (d5) +#define d6 REG (d6) +#define d7 REG (d7) +#define a0 REG (a0) +#define a1 REG (a1) +#define a2 REG (a2) +#define a3 REG (a3) +#define a4 REG (a4) +#define a5 REG (a5) +#define a6 REG (a6) +#define fp REG (fp) +#define sp REG (sp) + + .text + .proc + .globl SYM (__modsi3) +SYM (__modsi3): + movel sp@(8), d1 /* d1 = divisor */ + movel sp@(4), d0 /* d0 = dividend */ + movel d1, sp@- + movel d0, sp@- + jbsr SYM (__divsi3) + addql IMM (8), sp + movel sp@(8), d1 /* d1 = divisor */ +#ifndef __mcf5200__ + movel d1, sp@- + movel d0, sp@- + jbsr SYM (__mulsi3) /* d0 = (a/b)*b */ + addql IMM (8), sp +#else + mulsl d1,d0 +#endif + movel sp@(4), d1 /* d1 = dividend */ + subl d0, d1 /* d1 = a - (a/b)*b */ + movel d1, d0 + rts + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/lib/muldi3.c linux.2.5.45-ac1/arch/m68knommu/lib/muldi3.c --- linux.2.5.45/arch/m68knommu/lib/muldi3.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/lib/muldi3.c 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,86 @@ +/* muldi3.c extracted from gcc-2.7.2.3/libgcc2.c and + gcc-2.7.2.3/longlong.h which is: */ +/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC 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. + +GNU CC 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 GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#define BITS_PER_UNIT 8 +#define SI_TYPE_SIZE 32 + +#define __BITS4 (SI_TYPE_SIZE / 4) +#define __ll_B (1L << (SI_TYPE_SIZE / 2)) +#define __ll_lowpart(t) ((USItype) (t) % __ll_B) +#define __ll_highpart(t) ((USItype) (t) / __ll_B) + +#define umul_ppmm(w1, w0, u, v) \ + do { \ + USItype __x0, __x1, __x2, __x3; \ + USItype __ul, __vl, __uh, __vh; \ + \ + __ul = __ll_lowpart (u); \ + __uh = __ll_highpart (u); \ + __vl = __ll_lowpart (v); \ + __vh = __ll_highpart (v); \ + \ + __x0 = (USItype) __ul * __vl; \ + __x1 = (USItype) __ul * __vh; \ + __x2 = (USItype) __uh * __vl; \ + __x3 = (USItype) __uh * __vh; \ + \ + __x1 += __ll_highpart (__x0);/* this can't give carry */ \ + __x1 += __x2; /* but this indeed can */ \ + if (__x1 < __x2) /* did we get it? */ \ + __x3 += __ll_B; /* yes, add it in the proper pos. */ \ + \ + (w1) = __x3 + __ll_highpart (__x1); \ + (w0) = __ll_lowpart (__x1) * __ll_B + __ll_lowpart (__x0); \ + } while (0) + +#define __umulsidi3(u, v) \ + ({DIunion __w; \ + umul_ppmm (__w.s.high, __w.s.low, u, v); \ + __w.ll; }) + +typedef int SItype __attribute__ ((mode (SI))); +typedef unsigned int USItype __attribute__ ((mode (SI))); +typedef int DItype __attribute__ ((mode (DI))); +typedef int word_type __attribute__ ((mode (__word__))); + +struct DIstruct {SItype high, low;}; + +typedef union +{ + struct DIstruct s; + DItype ll; +} DIunion; + +DItype +__muldi3 (DItype u, DItype v) +{ + DIunion w; + DIunion uu, vv; + + uu.ll = u, + vv.ll = v; + + w.ll = __umulsidi3 (uu.s.low, vv.s.low); + w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high + + (USItype) uu.s.high * (USItype) vv.s.low); + + return w.ll; +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/lib/mulsi3.S linux.2.5.45-ac1/arch/m68knommu/lib/mulsi3.S --- linux.2.5.45/arch/m68knommu/lib/mulsi3.S 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/lib/mulsi3.S 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,110 @@ +/* libgcc1 routines for 68000 w/o floating-point hardware. + Copyright (C) 1994, 1996, 1997, 1998 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC 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. + +In addition to the permissions in the GNU General Public License, the +Free Software Foundation gives you unlimited permission to link the +compiled version of this file with other programs, and to distribute +those programs without any restriction coming from the use of this +file. (The General Public License restrictions do apply in other +respects; for example, they cover modification of the file, and +distribution when not linked into another program.) + +This file 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; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* As a special exception, if you link this library with files + compiled with GCC to produce an executable, this does not cause + the resulting executable to be covered by the GNU General Public License. + This exception does not however invalidate any other reasons why + the executable file might be covered by the GNU General Public License. */ + +/* Use this one for any 680x0; assumes no floating point hardware. + The trailing " '" appearing on some lines is for ANSI preprocessors. Yuk. + Some of this code comes from MINIX, via the folks at ericsson. + D. V. Henkel-Wallace (gumby@cygnus.com) Fete Bastille, 1992 +*/ + +/* These are predefined by new versions of GNU cpp. */ + +#ifndef __USER_LABEL_PREFIX__ +#define __USER_LABEL_PREFIX__ _ +#endif + +#ifndef __REGISTER_PREFIX__ +#define __REGISTER_PREFIX__ +#endif + +#ifndef __IMMEDIATE_PREFIX__ +#define __IMMEDIATE_PREFIX__ # +#endif + +/* ANSI concatenation macros. */ + +#define CONCAT1(a, b) CONCAT2(a, b) +#define CONCAT2(a, b) a ## b + +/* Use the right prefix for global labels. */ + +#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x) + +/* Use the right prefix for registers. */ + +#define REG(x) CONCAT1 (__REGISTER_PREFIX__, x) + +/* Use the right prefix for immediate values. */ + +#define IMM(x) CONCAT1 (__IMMEDIATE_PREFIX__, x) + +#define d0 REG (d0) +#define d1 REG (d1) +#define d2 REG (d2) +#define d3 REG (d3) +#define d4 REG (d4) +#define d5 REG (d5) +#define d6 REG (d6) +#define d7 REG (d7) +#define a0 REG (a0) +#define a1 REG (a1) +#define a2 REG (a2) +#define a3 REG (a3) +#define a4 REG (a4) +#define a5 REG (a5) +#define a6 REG (a6) +#define fp REG (fp) +#define sp REG (sp) + + .text + .proc + .globl SYM (__mulsi3) +SYM (__mulsi3): + movew sp@(4), d0 /* x0 -> d0 */ + muluw sp@(10), d0 /* x0*y1 */ + movew sp@(6), d1 /* x1 -> d1 */ + muluw sp@(8), d1 /* x1*y0 */ +#ifndef __mcf5200__ + addw d1, d0 +#else + addl d1, d0 +#endif + swap d0 + clrw d0 + movew sp@(6), d1 /* x1 -> d1 */ + muluw sp@(10), d1 /* x1*y1 */ + addl d1, d0 + + rts + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/lib/semaphore.S linux.2.5.45-ac1/arch/m68knommu/lib/semaphore.S --- linux.2.5.45/arch/m68knommu/lib/semaphore.S 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/lib/semaphore.S 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,67 @@ +/* + * linux/arch/m68k/lib/semaphore.S + * + * Copyright (C) 1996 Linus Torvalds + * + * m68k version by Andreas Schwab + * + * MAR/1999 -- modified to support ColdFire (gerg@snapgear.com) + */ + +#include +#include +#include + +/* + * "down_failed" is called with the eventual return address + * in %a0, and the address of the semaphore in %a1. We need + * to increment the number of waiters on the semaphore, + * call "__down()", and then eventually return to try again. + */ +ENTRY(__down_failed) +#ifdef CONFIG_COLDFIRE + subl #12,%sp + moveml %a0/%d0/%d1,(%sp) +#else + moveml %a0/%d0/%d1,-(%sp) +#endif + movel %a1,-(%sp) + jbsr __down + movel (%sp)+,%a1 + movel (%sp)+,%d0 + movel (%sp)+,%d1 + rts + +ENTRY(__down_failed_interruptible) + movel %a0,-(%sp) + movel %d1,-(%sp) + movel %a1,-(%sp) + jbsr __down_interruptible + movel (%sp)+,%a1 + movel (%sp)+,%d1 + rts + +ENTRY(__up_wakeup) +#ifdef CONFIG_COLDFIRE + subl #12,%sp + moveml %a0/%d0/%d1,(%sp) +#else + moveml %a0/%d0/%d1,-(%sp) +#endif + movel %a1,-(%sp) + jbsr __up + movel (%sp)+,%a1 + movel (%sp)+,%d0 + movel (%sp)+,%d1 + rts + +ENTRY(__down_failed_trylock) + movel %a0,-(%sp) + movel %d1,-(%sp) + movel %a1,-(%sp) + jbsr __down_trylock + movel (%sp)+,%a1 + movel (%sp)+,%d1 + movel (%sp)+,%a0 + rts + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/lib/udivsi3.S linux.2.5.45-ac1/arch/m68knommu/lib/udivsi3.S --- linux.2.5.45/arch/m68knommu/lib/udivsi3.S 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/lib/udivsi3.S 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,162 @@ +/* libgcc1 routines for 68000 w/o floating-point hardware. + Copyright (C) 1994, 1996, 1997, 1998 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC 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. + +In addition to the permissions in the GNU General Public License, the +Free Software Foundation gives you unlimited permission to link the +compiled version of this file with other programs, and to distribute +those programs without any restriction coming from the use of this +file. (The General Public License restrictions do apply in other +respects; for example, they cover modification of the file, and +distribution when not linked into another program.) + +This file 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; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* As a special exception, if you link this library with files + compiled with GCC to produce an executable, this does not cause + the resulting executable to be covered by the GNU General Public License. + This exception does not however invalidate any other reasons why + the executable file might be covered by the GNU General Public License. */ + +/* Use this one for any 680x0; assumes no floating point hardware. + The trailing " '" appearing on some lines is for ANSI preprocessors. Yuk. + Some of this code comes from MINIX, via the folks at ericsson. + D. V. Henkel-Wallace (gumby@cygnus.com) Fete Bastille, 1992 +*/ + +/* These are predefined by new versions of GNU cpp. */ + +#ifndef __USER_LABEL_PREFIX__ +#define __USER_LABEL_PREFIX__ _ +#endif + +#ifndef __REGISTER_PREFIX__ +#define __REGISTER_PREFIX__ +#endif + +#ifndef __IMMEDIATE_PREFIX__ +#define __IMMEDIATE_PREFIX__ # +#endif + +/* ANSI concatenation macros. */ + +#define CONCAT1(a, b) CONCAT2(a, b) +#define CONCAT2(a, b) a ## b + +/* Use the right prefix for global labels. */ + +#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x) + +/* Use the right prefix for registers. */ + +#define REG(x) CONCAT1 (__REGISTER_PREFIX__, x) + +/* Use the right prefix for immediate values. */ + +#define IMM(x) CONCAT1 (__IMMEDIATE_PREFIX__, x) + +#define d0 REG (d0) +#define d1 REG (d1) +#define d2 REG (d2) +#define d3 REG (d3) +#define d4 REG (d4) +#define d5 REG (d5) +#define d6 REG (d6) +#define d7 REG (d7) +#define a0 REG (a0) +#define a1 REG (a1) +#define a2 REG (a2) +#define a3 REG (a3) +#define a4 REG (a4) +#define a5 REG (a5) +#define a6 REG (a6) +#define fp REG (fp) +#define sp REG (sp) + + .text + .proc + .globl SYM (__udivsi3) +SYM (__udivsi3): +#ifndef __mcf5200__ + movel d2, sp@- + movel sp@(12), d1 /* d1 = divisor */ + movel sp@(8), d0 /* d0 = dividend */ + + cmpl IMM (0x10000), d1 /* divisor >= 2 ^ 16 ? */ + jcc L3 /* then try next algorithm */ + movel d0, d2 + clrw d2 + swap d2 + divu d1, d2 /* high quotient in lower word */ + movew d2, d0 /* save high quotient */ + swap d0 + movew sp@(10), d2 /* get low dividend + high rest */ + divu d1, d2 /* low quotient */ + movew d2, d0 + jra L6 + +L3: movel d1, d2 /* use d2 as divisor backup */ +L4: lsrl IMM (1), d1 /* shift divisor */ + lsrl IMM (1), d0 /* shift dividend */ + cmpl IMM (0x10000), d1 /* still divisor >= 2 ^ 16 ? */ + jcc L4 + divu d1, d0 /* now we have 16 bit divisor */ + andl IMM (0xffff), d0 /* mask out divisor, ignore remainder */ + +/* Multiply the 16 bit tentative quotient with the 32 bit divisor. Because of + the operand ranges, this might give a 33 bit product. If this product is + greater than the dividend, the tentative quotient was too large. */ + movel d2, d1 + mulu d0, d1 /* low part, 32 bits */ + swap d2 + mulu d0, d2 /* high part, at most 17 bits */ + swap d2 /* align high part with low part */ + tstw d2 /* high part 17 bits? */ + jne L5 /* if 17 bits, quotient was too large */ + addl d2, d1 /* add parts */ + jcs L5 /* if sum is 33 bits, quotient was too large */ + cmpl sp@(8), d1 /* compare the sum with the dividend */ + jls L6 /* if sum > dividend, quotient was too large */ +L5: subql IMM (1), d0 /* adjust quotient */ + +L6: movel sp@+, d2 + rts + +#else /* __mcf5200__ */ + +/* Coldfire implementation of non-restoring division algorithm from + Hennessy & Patterson, Appendix A. */ + link a6,IMM (-12) + moveml d2-d4,sp@ + movel a6@(8),d0 + movel a6@(12),d1 + clrl d2 | clear p + moveq IMM (31),d4 +L1: addl d0,d0 | shift reg pair (p,a) one bit left + addxl d2,d2 + movl d2,d3 | subtract b from p, store in tmp. + subl d1,d3 + jcs L2 | if no carry, + bset IMM (0),d0 | set the low order bit of a to 1, + movl d3,d2 | and store tmp in p. +L2: subql IMM (1),d4 + jcc L1 + moveml sp@,d2-d4 | restore data registers + unlk a6 | and return + rts +#endif /* __mcf5200__ */ + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/lib/umodsi3.S linux.2.5.45-ac1/arch/m68knommu/lib/umodsi3.S --- linux.2.5.45/arch/m68knommu/lib/umodsi3.S 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/lib/umodsi3.S 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,113 @@ +/* libgcc1 routines for 68000 w/o floating-point hardware. + Copyright (C) 1994, 1996, 1997, 1998 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC 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. + +In addition to the permissions in the GNU General Public License, the +Free Software Foundation gives you unlimited permission to link the +compiled version of this file with other programs, and to distribute +those programs without any restriction coming from the use of this +file. (The General Public License restrictions do apply in other +respects; for example, they cover modification of the file, and +distribution when not linked into another program.) + +This file 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; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* As a special exception, if you link this library with files + compiled with GCC to produce an executable, this does not cause + the resulting executable to be covered by the GNU General Public License. + This exception does not however invalidate any other reasons why + the executable file might be covered by the GNU General Public License. */ + +/* Use this one for any 680x0; assumes no floating point hardware. + The trailing " '" appearing on some lines is for ANSI preprocessors. Yuk. + Some of this code comes from MINIX, via the folks at ericsson. + D. V. Henkel-Wallace (gumby@cygnus.com) Fete Bastille, 1992 +*/ + +/* These are predefined by new versions of GNU cpp. */ + +#ifndef __USER_LABEL_PREFIX__ +#define __USER_LABEL_PREFIX__ _ +#endif + +#ifndef __REGISTER_PREFIX__ +#define __REGISTER_PREFIX__ +#endif + +#ifndef __IMMEDIATE_PREFIX__ +#define __IMMEDIATE_PREFIX__ # +#endif + +/* ANSI concatenation macros. */ + +#define CONCAT1(a, b) CONCAT2(a, b) +#define CONCAT2(a, b) a ## b + +/* Use the right prefix for global labels. */ + +#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x) + +/* Use the right prefix for registers. */ + +#define REG(x) CONCAT1 (__REGISTER_PREFIX__, x) + +/* Use the right prefix for immediate values. */ + +#define IMM(x) CONCAT1 (__IMMEDIATE_PREFIX__, x) + +#define d0 REG (d0) +#define d1 REG (d1) +#define d2 REG (d2) +#define d3 REG (d3) +#define d4 REG (d4) +#define d5 REG (d5) +#define d6 REG (d6) +#define d7 REG (d7) +#define a0 REG (a0) +#define a1 REG (a1) +#define a2 REG (a2) +#define a3 REG (a3) +#define a4 REG (a4) +#define a5 REG (a5) +#define a6 REG (a6) +#define fp REG (fp) +#define sp REG (sp) + + .text + .proc + .globl SYM (__umodsi3) +SYM (__umodsi3): + movel sp@(8), d1 /* d1 = divisor */ + movel sp@(4), d0 /* d0 = dividend */ + movel d1, sp@- + movel d0, sp@- + jbsr SYM (__udivsi3) + addql IMM (8), sp + movel sp@(8), d1 /* d1 = divisor */ +#ifndef __mcf5200__ + movel d1, sp@- + movel d0, sp@- + jbsr SYM (__mulsi3) /* d0 = (a/b)*b */ + addql IMM (8), sp +#else + mulsl d1,d0 +#endif + movel sp@(4), d1 /* d1 = dividend */ + subl d0, d1 /* d1 = a - (a/b)*b */ + movel d1, d0 + rts + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/Makefile linux.2.5.45-ac1/arch/m68knommu/Makefile --- linux.2.5.45/arch/m68knommu/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/Makefile 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,108 @@ +# +# arch/m68knommu/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. +# +# (C) Copyright 2002, Greg Ungerer +# + +platform-$(CONFIG_M68328) := 68328 +platform-$(CONFIG_M68EZ328) := 68EZ328 +platform-$(CONFIG_M68VZ328) := 68VZ328 +platform-$(CONFIG_M68360) := 68360 +platform-$(CONFIG_M5206) := 5206 +platform-$(CONFIG_M5206e) := 5206e +platform-$(CONFIG_M5249) := 5249 +platform-$(CONFIG_M5272) := 5272 +platform-$(CONFIG_M5307) := 5307 +platform-$(CONFIG_M5407) := 5407 +PLATFORM := $(platform-y) + +board-$(CONFIG_PILOT) := pilot +board-$(CONFIG_UCSIMM) := ucsimm +board-$(CONFIG_UCDIMM) := ucdimm +board-$(CONFIG_UCQUICC) := uCquicc +board-$(CONFIG_DRAGEN2) := de2 +board-$(CONFIG_ARNEWSH) := ARNEWSH +board-$(CONFIG_MOTOROLA) := MOTOROLA +board-$(CONFIG_ELITE) := eLITE +board-$(CONFIG_eLIA) := eLIA +board-$(CONFIG_NETtel) := NETtel +board-$(CONFIG_SECUREEDGEMP3) := MP3 +board-$(CONFIG_CLEOPATRA) := CLEOPATRA +BOARD := $(board-y) + +model-$(CONFIG_RAMKERNEL) := ram +model-$(CONFIG_ROMKERNEL) := rom +model-$(CONFIG_HIMEMKERNEL) := himem +MODEL := $(model-y) + +# +# Some code support is grouped together for a common cpu-subclass (for +# example all ColdFire cpu's are very similar). Determine the sub-class +# for the selected cpu. ONLY need to define this for the non-core member +# of the family. +# +cpuclass-$(CONFIG_M5206) := 5307 +cpuclass-$(CONFIG_M5206e) := 5307 +cpuclass-$(CONFIG_M5249) := 5307 +cpuclass-$(CONFIG_M5272) := 5307 +cpuclass-$(CONFIG_M5407) := 5307 +cpuclass-$(CONFIG_M68EZ328) := 68328 +cpuclass-$(CONFIG_M68VZ328) := 68328 +CPUCLASS := $(cpuclass-y) +CLASSDIR := arch/m68knommu/platform/$(cpuclass-y)/ + +export PLATFORM BOARD MODEL CPUCLASS + +# +# Some CFLAG additions based on specific CPU type. +# +cflags-$(CONFIG_M5206) := -m5200 -Wa,-S -Wa,-m5200 +cflags-$(CONFIG_M5206e) := -m5200 -Wa,-S -Wa,-m5200 +cflags-$(CONFIG_M5249) := -m5200 -Wa,-S -Wa,-m5200 +cflags-$(CONFIG_M5272) := -m5307 -Wa,-S -Wa,-m5307 +cflags-$(CONFIG_M5307) := -m5307 -Wa,-S -Wa,-m5307 +cflags-$(CONFIG_M5407) := -m5200 -Wa,-S -Wa,-m5200 +cflags-$(CONFIG_M68328) := -m68000 +cflags-$(CONFIG_M68EZ328) := -m68000 +cflags-$(CONFIG_M68VZ328) := -m68000 +cflags-$(CONFIG_M68360) := -m68332 + +AFLAGS += $(cflags-y) + +CFLAGS += $(cflags-y) +CFLAGS += -fno-builtin +CFLAGS += -O2 -g +CFLAGS += -D__linux__ +CFLAGS += -DUTS_SYSNAME=\"uClinux\" + +HEAD := arch/m68knommu/platform/$(platform-y)/$(board-y)/crt0_$(model-y).o + +clean-files := include/asm-$(ARCH)/asm-offsets.h.tmp \ + include/asm-$(ARCH)/asm-offsets.h \ + arch/$(ARCH)/kernel/asm-offsets.s + +core-y += arch/m68knommu/kernel/ \ + arch/m68knommu/mm/ \ + $(CLASSDIR) \ + arch/m68knommu/platform/$(PLATFORM)/ +libs-y += arch/m68knommu/lib/ + +include $(TOPDIR)/Rules.make + +prepare: include/asm-$(ARCH)/asm-offsets.h + +archmrproper: + +archclean: + $(call descend arch/$(ARCH)/boot, subdirclean) + +include/asm-$(ARCH)/asm-offsets.h: arch/$(ARCH)/kernel/asm-offsets.s \ + include/asm include/linux/version.h \ + include/config/MARKER + @echo -n ' Generating $@' + @$(generate-asm-offsets.h) < $< > $@.tmp + @$(update-if-changed) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/mm/fault.c linux.2.5.45-ac1/arch/m68knommu/mm/fault.c --- linux.2.5.45/arch/m68knommu/mm/fault.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/mm/fault.c 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,57 @@ +/* + * linux/arch/m68knommu/mm/fault.c + * + * Copyright (C) 1998 D. Jeff Dionne , + * Copyright (C) 2000 Lineo, Inc. (www.lineo.com) + * + * Based on: + * + * linux/arch/m68k/mm/fault.c + * + * Copyright (C) 1995 Hamish Macdonald + */ + +#include +#include +#include +#include + +#include +#include + +extern void die_if_kernel(char *, struct pt_regs *, long); + +/* + * This routine handles page faults. It determines the problem, and + * then passes it off to one of the appropriate routines. + * + * error_code: + * bit 0 == 0 means no page found, 1 means protection fault + * bit 1 == 0 means read, 1 means write + * + * If this routine detects a bad access, it returns 1, otherwise it + * returns 0. + */ +asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address, + unsigned long error_code) +{ +#ifdef DEBUG + printk ("regs->sr=%#x, regs->pc=%#lx, address=%#lx, %ld\n", + regs->sr, regs->pc, address, error_code); +#endif + + /* + * Oops. The kernel tried to access some bad page. We'll have to + * terminate things with extreme prejudice. + */ + if ((unsigned long) address < PAGE_SIZE) { + printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference"); + } else + printk(KERN_ALERT "Unable to handle kernel access"); + printk(" at virtual address %08lx\n",address); + die_if_kernel("Oops", regs, error_code); + do_exit(SIGKILL); + + return 1; +} + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/mm/init.c linux.2.5.45-ac1/arch/m68knommu/mm/init.c --- linux.2.5.45/arch/m68knommu/mm/init.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/mm/init.c 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,235 @@ +/* + * linux/arch/m68knommu/mm/init.c + * + * Copyright (C) 1998 D. Jeff Dionne , + * Kenneth Albanowski , + * Copyright (C) 2000 Lineo, Inc. (www.lineo.com) + * + * Based on: + * + * linux/arch/m68k/mm/init.c + * + * Copyright (C) 1995 Hamish Macdonald + * + * JAN/1999 -- hacked to support ColdFire (gerg@snapgear.com) + * DEC/2000 -- linux 2.4 support + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_BLK_DEV_RAM +#include +#endif +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#undef DEBUG + +extern void die_if_kernel(char *,struct pt_regs *,long); +extern void free_initmem(void); + +/* + * BAD_PAGE is the page that is used for page faults when linux + * is out-of-memory. Older versions of linux just did a + * do_exit(), but using this instead means there is less risk + * for a process dying in kernel mode, possibly leaving a inode + * unused etc.. + * + * BAD_PAGETABLE is the accompanying page-table: it is initialized + * to point to BAD_PAGE entries. + * + * ZERO_PAGE is a special page that is used for zero-initialized + * data and COW. + */ +static unsigned long empty_bad_page_table; + +static unsigned long empty_bad_page; + +unsigned long empty_zero_page; + +extern unsigned long rom_length; + +void show_mem(void) +{ + unsigned long i; + int free = 0, total = 0, reserved = 0, shared = 0; + int cached = 0; + + printk("\nMem-info:\n"); + show_free_areas(); + i = max_mapnr; + while (i-- > 0) { + total++; + if (PageReserved(mem_map+i)) + reserved++; + else if (PageSwapCache(mem_map+i)) + cached++; + else if (!page_count(mem_map+i)) + free++; + else + shared += page_count(mem_map+i) - 1; + } + printk("%d pages of RAM\n",total); + printk("%d free pages\n",free); + printk("%d reserved pages\n",reserved); + printk("%d pages shared\n",shared); + printk("%d pages swap cached\n",cached); +} + +extern unsigned long memory_start; +extern unsigned long memory_end; + +/* + * paging_init() continues the virtual memory environment setup which + * was begun by the code in arch/head.S. + * The parameters are pointers to where to stick the starting and ending + * addresses of available kernel virtual memory. + */ +void paging_init(void) +{ + /* + * Make sure start_mem is page aligned, otherwise bootmem and + * page_alloc get different views of the world. + */ +#ifdef DEBUG + unsigned long start_mem = PAGE_ALIGN(memory_start); +#endif + unsigned long end_mem = memory_end & PAGE_MASK; + +#ifdef DEBUG + printk ("start_mem is %#lx\nvirtual_end is %#lx\n", + start_mem, end_mem); +#endif + + /* + * Initialize the bad page table and bad page to point + * to a couple of allocated pages. + */ + empty_bad_page_table = (unsigned long)alloc_bootmem_pages(PAGE_SIZE); + empty_bad_page = (unsigned long)alloc_bootmem_pages(PAGE_SIZE); + empty_zero_page = (unsigned long)alloc_bootmem_pages(PAGE_SIZE); + memset((void *)empty_zero_page, 0, PAGE_SIZE); + + /* + * Set up SFC/DFC registers (user data space). + */ + set_fs (USER_DS); + +#ifdef DEBUG + printk ("before free_area_init\n"); + + printk ("free_area_init -> start_mem is %#lx\nvirtual_end is %#lx\n", + start_mem, end_mem); +#endif + + { + unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0}; + + zones_size[ZONE_DMA] = 0 >> PAGE_SHIFT; + zones_size[ZONE_NORMAL] = (end_mem - PAGE_OFFSET) >> PAGE_SHIFT; +#ifdef CONFIG_HIGHMEM + zones_size[ZONE_HIGHMEM] = 0; +#endif + free_area_init(zones_size); + } +} + +void mem_init(void) +{ + int codek = 0, datak = 0, initk = 0; + unsigned long tmp; + extern char _etext, _stext, _sdata, _ebss, __init_begin, __init_end; + extern unsigned int _ramend, _rambase; + unsigned long len = _ramend - _rambase; + unsigned long start_mem = memory_start; /* DAVIDM - these must start at end of kernel */ + unsigned long end_mem = memory_end; /* DAVIDM - this must not include kernel stack at top */ + +#ifdef DEBUG + printk("Mem_init: start=%lx, end=%lx\n", start_mem, end_mem); +#endif + + end_mem &= PAGE_MASK; + high_memory = (void *) end_mem; + + start_mem = PAGE_ALIGN(start_mem); + max_mapnr = num_physpages = MAP_NR(high_memory); + + /* this will put all memory onto the freelists */ + totalram_pages = free_all_bootmem(); + + codek = (&_etext - &_stext) >> 10; + datak = (&_ebss - &_sdata) >> 10; + initk = (&__init_begin - &__init_end) >> 10; + + tmp = nr_free_pages() << PAGE_SHIFT; + printk("Memory available: %luk/%luk RAM, %luk/%luk ROM (%dk kernel code, %dk data)\n", + tmp >> 10, + len >> 10, + (rom_length > 0) ? ((rom_length >> 10) - codek) : 0, + rom_length >> 10, + codek, + datak + ); +} + + +#ifdef CONFIG_BLK_DEV_INITRD +void free_initrd_mem(unsigned long start, unsigned long end) +{ + int pages = 0; + for (; start < end; start += PAGE_SIZE) { + ClearPageReserved(virt_to_page(start)); + set_page_count(virt_to_page(start), 1); + free_page(start); + totalram_pages++; + pages++; + } + printk ("Freeing initrd memory: %dk freed\n", pages); +} +#endif + +void +free_initmem() +{ +#ifdef CONFIG_RAMKERNEL + unsigned long addr; + extern char __init_begin, __init_end; + /* + * The following code should be cool even if these sections + * are not page aligned. + */ + addr = PAGE_ALIGN((unsigned long)(&__init_begin)); + /* next to check that the page we free is not a partial page */ + for (; addr + PAGE_SIZE < (unsigned long)(&__init_end); addr +=PAGE_SIZE) { + ClearPageReserved(virt_to_page(addr)); + set_page_count(virt_to_page(addr), 1); + free_page(addr); + totalram_pages++; + } + printk("Freeing unused kernel memory: %ldk freed (0x%x - 0x%x)\n", + (addr - PAGE_ALIGN((long) &__init_begin)) >> 10, + (int)(PAGE_ALIGN((unsigned long)(&__init_begin))), + (int)(addr - PAGE_SIZE)); +#endif +} + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/mm/kmap.c linux.2.5.45-ac1/arch/m68knommu/mm/kmap.c --- linux.2.5.45/arch/m68knommu/mm/kmap.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/mm/kmap.c 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,56 @@ +/* + * linux/arch/m68knommu/mm/kmap.c + * + * Copyright (C) 2000 Lineo, + * Copyright (C) 2000-2002 David McCullough + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#undef DEBUG + +/* + * Map some physical address range into the kernel address space. + */ +void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag) +{ + return (void *)physaddr; +} + +/* + * Unmap a ioremap()ed region again. + */ +void iounmap(void *addr) +{ +} + +/* + * __iounmap unmaps nearly everything, so be careful + * it doesn't free currently pointer/page tables anymore but it + * wans't used anyway and might be added later. + */ +void __iounmap(void *addr, unsigned long size) +{ +} + +/* + * Set new cache mode for some kernel address space. + * The caller must push data for that range itself, if such data may already + * be in the cache. + */ +void kernel_set_cachemode(void *addr, unsigned long size, int cmode) +{ +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/mm/Makefile linux.2.5.45-ac1/arch/m68knommu/mm/Makefile --- linux.2.5.45/arch/m68knommu/mm/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/mm/Makefile 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,7 @@ +# +# Makefile for the linux m68knommu specific parts of the memory manager. +# + +obj-y += init.o fault.o memory.o kmap.o + +include $(TOPDIR)/Rules.make diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/mm/memory.c linux.2.5.45-ac1/arch/m68knommu/mm/memory.c --- linux.2.5.45/arch/m68knommu/mm/memory.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/mm/memory.c 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,166 @@ +/* + * linux/arch/m68knommu/mm/memory.c + * + * Copyright (C) 1998 Kenneth Albanowski , + * Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com) + * + * Based on: + * + * linux/arch/m68k/mm/memory.c + * + * Copyright (C) 1995 Hamish Macdonald + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * cache_clear() semantics: Clear any cache entries for the area in question, + * without writing back dirty entries first. This is useful if the data will + * be overwritten anyway, e.g. by DMA to memory. The range is defined by a + * _physical_ address. + */ + +void cache_clear (unsigned long paddr, int len) +{ +} + + +/* + * Define cache invalidate functions. The ColdFire 5407 is really + * the only processor that needs to do some work here. Anything + * that has separate data and instruction caches will be a problem. + */ +#ifdef CONFIG_M5407 + +static __inline__ void cache_invalidate_lines(unsigned long paddr, int len) +{ + unsigned long sset, eset; + + sset = (paddr & 0x00000ff0); + eset = ((paddr + len) & 0x0000ff0) + 0x10; + + __asm__ __volatile__ ( + "nop\n\t" + "clrl %%d0\n\t" + "1:\n\t" + "movel %0,%%a0\n\t" + "addl %%d0,%%a0\n\t" + "2:\n\t" + ".word 0xf4e8\n\t" + "addl #0x10,%%a0\n\t" + "cmpl %1,%%a0\n\t" + "blt 2b\n\t" + "addql #1,%%d0\n\t" + "cmpil #4,%%d0\n\t" + "bne 1b" + : : "a" (sset), "a" (eset) : "d0", "a0" ); +} + +#else +#define cache_invalidate_lines(a,b) +#endif + + +/* + * cache_push() semantics: Write back any dirty cache data in the given area, + * and invalidate the range in the instruction cache. It needs not (but may) + * invalidate those entries also in the data cache. The range is defined by a + * _physical_ address. + */ + +void cache_push (unsigned long paddr, int len) +{ + cache_invalidate_lines(paddr, len); +} + + +/* + * cache_push_v() semantics: Write back any dirty cache data in the given + * area, and invalidate those entries at least in the instruction cache. This + * is intended to be used after data has been written that can be executed as + * code later. The range is defined by a _user_mode_ _virtual_ address (or, + * more exactly, the space is defined by the %sfc/%dfc register.) + */ + +void cache_push_v (unsigned long vaddr, int len) +{ + cache_invalidate_lines(vaddr, len); +} + +/* Map some physical address range into the kernel address space. The + * code is copied and adapted from map_chunk(). + */ + +unsigned long kernel_map(unsigned long paddr, unsigned long size, + int nocacheflag, unsigned long *memavailp ) +{ + return paddr; +} + + +int is_in_rom(unsigned long addr) +{ + +#ifdef CONFIG_COLDFIRE + { + extern unsigned long _ramstart, _ramend; + + /* Anything not in operational RAM is returned as in rom! */ + if (addr < _ramstart || addr >= _ramend) + return(1); + } +#endif + +#if defined(CONFIG_PILOT) || defined(CONFIG_UCSIMM) + if (addr >= 0x10c00000) + return 1; +#endif + +#ifdef CONFIG_M68EZ328ADS + if ( 0x00200000 <= addr && addr < 0x00400000) + return 1; +#endif + +#ifdef CONFIG_M68332 + extern char _etext; + + #ifdef SHGLCORE_ROM_BANK_0_ADDR + if ((addr >= SHGLCORE_ROM_BANK_0_ADDR) && + (addr < (SHGLCORE_ROM_BANK_0_ADDR+SHGLCORE_ROM_BANK_0_LENGTH))) + return 1; + #endif + #ifdef SHGLCORE_ROM_BANK_1_ADDR + else if ((addr >= SHGLCORE_ROM_BANK_1_ADDR) && + (addr < (SHGLCORE_ROM_BANK_1_ADDR+SHGLCORE_ROM_BANK_1_LENGTH))) + return 1; + #endif + #ifdef SHGLCORE_FLASH_BANK_0_ADDR + else if ((addr >= SHGLCORE_FLASH_BANK_0_ADDR) && + (addr < (SHGLCORE_FLASH_BANK_0_ADDR+SHGLCORE_FLASH_BANK_0_LENGTH))) + return 1; + #endif + #ifdef SHGLCORE_FLASH_BANK_1_ADDR + else if ((addr >= SHGLCORE_FLASH_BANK_1_ADDR) && + (addr < (SHGLCORE_FLASH_BANK_1_ADDR+SHGLCORE_FLASH_BANK_1_LENGTH))) + return 1; + #endif +#endif + + /* Default case, not in ROM */ + return(0); +} + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/5206/ARNEWSH/crt0_ram.S linux.2.5.45-ac1/arch/m68knommu/platform/5206/ARNEWSH/crt0_ram.S --- linux.2.5.45/arch/m68knommu/platform/5206/ARNEWSH/crt0_ram.S 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/5206/ARNEWSH/crt0_ram.S 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,206 @@ +/*****************************************************************************/ + +/* + * crt0_ram.S -- startup code for MCF5206 ColdFire Arnewsh board. + * + * (C) Copyright 1999-2002, Greg Ungerer (gerg@snapgear.com). + * + * 1999/02/24 Modified for the 5307 processor David W. Miller + */ + +/*****************************************************************************/ + +#include "linux/autoconf.h" +#include "asm/coldfire.h" +#include "asm/mcfsim.h" + +/*****************************************************************************/ + +/* + * Arnewsh m5206 ColdFire eval board, chip select and memory setup. + */ + +#define MEM_BASE 0x00000000 /* Memory base at address 0 */ +#define VBR_BASE MEM_BASE /* Vector address */ + +/* + * The following define the limits within which to search for + * available RAM. + */ +#define MEM_MIN 0x00100000 /* Search from 1Mb */ +#define MEM_MAX 0x02000000 /* Max DRAM 32Mb! */ +#define MEM_LUMP 0x00010000 /* 64 Kb chunks */ + +#define MEM_TMPSTACK 0x00010000 /* At 64k - for exceptions */ + +/* + * Chip Select setup. + */ +#define CS0_ADDR 0x0000f000 /* CS0 connected to Flash ROM */ +#define CS0_MASK 0xf0000000 /* is 1Mbyte */ +#define CS0_CTRL 0x00000000 /* read-only */ +#define CS1_ADDR 0x00000000 /* CS1 not connected */ +#define CS1_MASK 0x00000000 +#define CS1_CTRL 0x00000000 +#define CS2_ADDR 0x00003000 /* CS2 connected to SRAM */ +#define CS2_MASK 0x0000f000 /* is 1Mbyte */ +#define CS2_CTRL 0x00001903 /* read-write */ +#define CS3_ADDR 0x00004000 /* CS3 connected to LED, par port */ +#define CS3_MASK 0x0000f000 /* is 1Mbyte */ +#define CS3_CTRL 0x00000083 /* read-write */ +#define CS4_ADDR 0x00000000 /* CS4 not connected */ +#define CS4_MASK 0x00000000 +#define CS4_CTRL 0x00000123 +#define CS5_ADDR 0x00000000 /* CS5 not connected */ +#define CS5_MASK 0x00000000 +#define CS5_CTRL 0x00000000 +#define CS6_ADDR 0x00000000 /* CS6 not connected */ +#define CS6_MASK 0x00000000 +#define CS6_CTRL 0x00000000 +#define CS7_ADDR 0x00000000 /* CS7 not connected */ +#define CS7_MASK 0x00000000 +#define CS7_CTRL 0x00000000 +#define DMC_CTRL 0x00000000 /* default memory control */ + +/*****************************************************************************/ + +.global _start +.global _rambase +.global _ramvec +.global _ramstart +.global _ramend + +/*****************************************************************************/ + +.data + +/* + * Set up the usable of RAM stuff. Size of RAM is determined then + * an initial stack set up at the end. + */ +_rambase: +.long 0 +_ramvec: +.long 0 +_ramstart: +.long 0 +_ramend: +.long 0 + +/*****************************************************************************/ + +.text + +/* + * This is the codes first entry point. This is where it all + * begins... + */ + +_start: + nop /* Filler */ + move.w #0x2700, %sr /* No interrupts */ + + + /* + * Setup VBR here, otherwise buserror remap will not work. + * if dBug was active before (on my SBC with dBug 1.1 of Dec 16 1996) + * + * bkr@cut.de 19990306 + * + * Note: this is because dBUG points VBR to ROM, making vectors read + * only, so the bus trap can't be changed. (RS) + */ + move.l #VBR_BASE, %a7 /* Note VBR can't be read */ + movec %a7, %VBR + move.l %a7, _ramvec /* Set up vector addr */ + move.l %a7, _rambase /* Set up base RAM addr */ + + + /* + * Determine size of RAM, then set up initial stack. + * + * On the Arnewsh 5206 board we can probe for the amount + * of DRAM present... + */ + move.l #MEM_MIN, %a0 /* Start at bottom */ + move.l #MEM_MAX, %a1 /* Set stop point */ + lea.l MEM_TMPSTACK, %sp /* Set up tmp stack ptr */ + + move.l #VBR_BASE+8, %a2 /* Address of bus trap */ + lea.l _ram_buserr, %a3 /* Get RAM trap address */ + move.l %a3, (%a2) /* Set trap to local ptr */ + +_find_ram: + move.l (%a0), %d0 /* Attempt read */ + add.l #MEM_LUMP, %a0 /* Try next bank */ + cmp.l %a1, %a0 /* Check more? */ + bne _find_ram + + /* + * BUS error trap handler - used for RAM probing. + */ +_ram_buserr: + bra _found_ram + +_found_ram: /* Vectored here on bus err */ + move.l %a0, %d0 /* Mem end addr is in a0 */ + move.l %d0, %sp /* Set up initial stack ptr */ + move.l %d0, _ramend /* Set end ram addr */ + + + /* + * Enable CPU internal cache. + */ + move.l #0x01000000, %d0 /* Invalidate cache cmd */ + movec %d0, %CACR /* Invalidate cache */ + move.l #0x80000100, %d0 /* Setup cache mask */ + movec %d0, %CACR /* Enable cache */ + + + /* + * Move ROM filesystem above bss :-) + */ + lea.l _sbss, %a0 /* Get start of bss */ + lea.l _ebss, %a1 /* Set up destination */ + move.l %a0, %a2 /* Copy of bss start */ + + move.l 8(%a0), %d0 /* Get size of ROMFS */ + addq.l #8, %d0 /* Allow for rounding */ + and.l #0xfffffffc, %d0 /* Whole words */ + + add.l %d0, %a0 /* Copy from end */ + add.l %d0, %a1 /* Copy from end */ + move.l %a1, _ramstart /* Set start of ram */ + +_copy_romfs: + move.l -(%a0), %d0 /* Copy dword */ + move.l %d0, -(%a1) + cmp.l %a0, %a2 /* Check if at end */ + bne _copy_romfs + + /* + * Zero out the bss region. + */ + lea.l _sbss, %a0 /* Get start of bss */ + lea.l _ebss, %a1 /* Get end of bss */ + clr.l %d0 /* Set value */ +_clear_bss: + move.l %d0, (%a0)+ /* Clear each word */ + cmp.l %a0, %a1 /* Check if at end */ + bne _clear_bss + + /* + * Load the current task pointer and stack. + */ + lea init_thread_union, %a0 + lea 0x2000(%a0), %sp + + /* + * Assember start up done, start code proper. + */ + jsr start_kernel /* Start Linux kernel */ + +_exit: + jmp _exit /* Should never get here */ + +/*****************************************************************************/ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/5206/ARNEWSH/ram.ld linux.2.5.45-ac1/arch/m68knommu/platform/5206/ARNEWSH/ram.ld --- linux.2.5.45/arch/m68knommu/platform/5206/ARNEWSH/ram.ld 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/5206/ARNEWSH/ram.ld 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,72 @@ + +MEMORY { + ram : ORIGIN = 0x10000, LENGTH = 0x200000 +} + +jiffies = jiffies_64 + 4; + +SECTIONS { + + .text : { + _stext = . ; + *(.text) + *(.exit.text) + *(.text.lock) + *(.exitcall.exit) + *(.rodata) + . = ALIGN(0x4) ; + *(.kstrtab) + . = ALIGN(16); /* Exception table */ + __start___ex_table = .; + *(__ex_table) + __stop___ex_table = .; + + __start___ksymtab = .; /* Kernel symbol table */ + *(__ksymtab) + __stop___ksymtab = .; + . = ALIGN(4) ; + _etext = . ; + } > ram + + .data BLOCK(0x4) : { + _sdata = . ; + __data_start = . ; + *(.data) + *(.data.exit) + . = ALIGN(0x2000) ; + *(.data.init_task) + . = ALIGN(0x2000) ; + _edata = . ; + } > ram + + .init BLOCK(4096) : { + __init_begin = .; + *(.init.text) + *(.init.data) + . = ALIGN(16); + __setup_start = .; + *(.init.setup) + __setup_end = .; + __initcall_start = .; + *(.initcall1.init) + *(.initcall2.init) + *(.initcall3.init) + *(.initcall4.init) + *(.initcall5.init) + *(.initcall6.init) + *(.initcall7.init) + __initcall_end = .; + . = ALIGN(4) ; + __init_end = .; + } > ram + + .bss BLOCK(0x4) : { + _sbss = . ; + *(.bss) + *(COMMON) + . = ALIGN(4) ; + _ebss = . ; + _end = . ; + } > ram +} + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/5206/config.c linux.2.5.45-ac1/arch/m68knommu/platform/5206/config.c --- linux.2.5.45/arch/m68knommu/platform/5206/config.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/5206/config.c 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,155 @@ +/***************************************************************************/ + +/* + * linux/arch/m68knommu/platform/5206/config.c + * + * Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com) + * Copyright (C) 2000-2001, Lineo Inc. (www.lineo.com) + */ + +/***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/***************************************************************************/ + +/* + * DMA channel base address table. + */ +unsigned int dma_base_addr[MAX_M68K_DMA_CHANNELS] = { + MCF_MBAR + MCFDMA_BASE0, + MCF_MBAR + MCFDMA_BASE1, +}; + +unsigned int dma_device_address[MAX_M68K_DMA_CHANNELS]; + +/***************************************************************************/ + +void coldfire_tick(void) +{ + volatile unsigned char *timerp; + + /* Reset the ColdFire timer */ + timerp = (volatile unsigned char *) (MCF_MBAR + MCFTIMER_BASE1); + timerp[MCFTIMER_TER] = MCFTIMER_TER_CAP | MCFTIMER_TER_REF; +} + +/***************************************************************************/ + +void coldfire_timer_init(void (*handler)(int, void *, struct pt_regs *)) +{ + volatile unsigned short *timerp; + volatile unsigned char *icrp; + + /* Set up TIMER 1 as poll clock */ + timerp = (volatile unsigned short *) (MCF_MBAR + MCFTIMER_BASE1); + timerp[MCFTIMER_TMR] = MCFTIMER_TMR_DISABLE; + + timerp[MCFTIMER_TRR] = (unsigned short) ((MCF_CLK / 16) / HZ); + timerp[MCFTIMER_TMR] = MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 | + MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE; + + icrp = (volatile unsigned char *) (MCF_MBAR + MCFSIM_TIMER1ICR); + + *icrp = MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL5 | MCFSIM_ICR_PRI3; + request_irq(29, handler, SA_INTERRUPT, "ColdFire Timer", NULL); + mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_TIMER1); +} + +/***************************************************************************/ + +/* + * Program the vector to be an auto-vectored. + */ + +void mcf_autovector(unsigned int vec) +{ + volatile unsigned char *mbar; + unsigned char icr; + + if ((vec >= 25) && (vec <= 31)) { + vec -= 25; + mbar = (volatile unsigned char *) MCF_MBAR; + icr = MCFSIM_ICR_AUTOVEC | (vec << 3); + *(mbar + MCFSIM_ICR1 + vec) = icr; + vec = 0x1 << (vec + 1); + mcf_setimr(mcf_getimr() & ~vec); + } +} + +/***************************************************************************/ + +extern e_vector *_ramvec; + +void set_evector(int vecnum, void (*handler)(void)) +{ + if (vecnum >= 0 && vecnum <= 255) + _ramvec[vecnum] = handler; +} + +/***************************************************************************/ + +/* assembler routines */ +asmlinkage void buserr(void); +asmlinkage void trap(void); +asmlinkage void system_call(void); +asmlinkage void inthandler(void); + +void coldfire_trap_init(void) +{ + int i; + +#ifndef ENABLE_dBUG + mcf_setimr(MCFSIM_IMR_MASKALL); +#endif + + /* + * There is a common trap handler and common interrupt + * handler that handle almost every vector. We treat + * the system call and bus error special, they get their + * own first level handlers. + */ +#ifndef ENABLE_dBUG + for (i = 3; (i <= 23); i++) + _ramvec[i] = trap; + for (i = 33; (i <= 63); i++) + _ramvec[i] = trap; +#endif + + for (i = 24; (i <= 30); i++) + _ramvec[i] = inthandler; +#ifndef ENABLE_dBUG + _ramvec[31] = inthandler; // Disables the IRQ7 button +#endif + + for (i = 64; (i < 255); i++) + _ramvec[i] = inthandler; + _ramvec[255] = 0; + + _ramvec[2] = buserr; + _ramvec[32] = system_call; +} + +/***************************************************************************/ + +void config_BSP(char *commandp, int size) +{ + memset(commandp, 0, size); + mach_sched_init = coldfire_timer_init; + mach_tick = coldfire_tick; + mach_trap_init = coldfire_trap_init; +} + +/***************************************************************************/ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/5206/Makefile linux.2.5.45-ac1/arch/m68knommu/platform/5206/Makefile --- linux.2.5.45/arch/m68knommu/platform/5206/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/5206/Makefile 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,24 @@ +# +# Makefile for the m68knommu linux kernel. +# + +# +# If you want to play with the HW breakpoints then you will +# need to add define this, which will give you a stack backtrace +# on the console port whenever a DBG interrupt occurs. You have to +# set up you HW breakpoints to trigger a DBG interrupt: +# +# EXTRA_CFLAGS += -DTRAP_DBG_INTERRUPT +# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT +# + +ifdef CONFIG_FULLDEBUG +AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1 +endif + +obj-y := config.o + +EXTRA_TARGETS := $(BOARD)/crt0_$(MODEL).o + +include $(TOPDIR)/Rules.make + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/5206e/config.c linux.2.5.45-ac1/arch/m68knommu/platform/5206e/config.c --- linux.2.5.45/arch/m68knommu/platform/5206e/config.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/5206e/config.c 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,233 @@ +/***************************************************************************/ + +/* + * linux/arch/m68knommu/platform/5206e/config.c + * + * Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com) + */ + +/***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_NETtel +#include +#include +#endif + +/***************************************************************************/ + +#ifdef CONFIG_NETtel +void reset_setupbutton(void); +#endif + +/***************************************************************************/ + +/* + * DMA channel base address table. + */ +unsigned int dma_base_addr[MAX_M68K_DMA_CHANNELS] = { + MCF_MBAR + MCFDMA_BASE0, + MCF_MBAR + MCFDMA_BASE1, +}; + +unsigned int dma_device_address[MAX_M68K_DMA_CHANNELS]; + +/***************************************************************************/ + +void coldfire_tick(void) +{ + volatile unsigned char *timerp; + + /* Reset the ColdFire timer */ + timerp = (volatile unsigned char *) (MCF_MBAR + MCFTIMER_BASE1); + timerp[MCFTIMER_TER] = MCFTIMER_TER_CAP | MCFTIMER_TER_REF; +} + +/***************************************************************************/ + +void coldfire_timer_init(void (*handler)(int, void *, struct pt_regs *)) +{ + volatile unsigned short *timerp; + volatile unsigned char *icrp; + + /* Set up TIMER 1 as poll clock */ + timerp = (volatile unsigned short *) (MCF_MBAR + MCFTIMER_BASE1); + timerp[MCFTIMER_TMR] = MCFTIMER_TMR_DISABLE; + + timerp[MCFTIMER_TRR] = (unsigned short) ((MCF_CLK / 16) / HZ); + timerp[MCFTIMER_TMR] = MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 | + MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE; + + icrp = (volatile unsigned char *) (MCF_MBAR + MCFSIM_TIMER1ICR); + +#ifdef CONFIG_NETtel + *icrp = MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI3; + request_irq(30, handler, SA_INTERRUPT, "ColdFire Timer", NULL); + reset_setupbutton(); +#else + *icrp = MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL5 | MCFSIM_ICR_PRI3; + request_irq(29, handler, SA_INTERRUPT, "ColdFire Timer", NULL); +#endif + mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_TIMER1); +} + +/***************************************************************************/ + +/* + * Program the vector to be an auto-vectored. + */ + +void mcf_autovector(unsigned int vec) +{ + volatile unsigned char *mbar; + unsigned char icr; + + if ((vec >= 25) && (vec <= 31)) { + vec -= 25; + mbar = (volatile unsigned char *) MCF_MBAR; + icr = MCFSIM_ICR_AUTOVEC | (vec << 3); + *(mbar + MCFSIM_ICR1 + vec) = icr; + vec = 0x1 << (vec + 1); + mcf_setimr(mcf_getimr() & ~vec); + } +} + +/***************************************************************************/ + +extern e_vector *_ramvec; + +void set_evector(int vecnum, void (*handler)(void)) +{ + if (vecnum >= 0 && vecnum <= 255) + _ramvec[vecnum] = handler; +} + +/***************************************************************************/ + +/* assembler routines */ +asmlinkage void buserr(void); +asmlinkage void trap(void); +asmlinkage void system_call(void); +asmlinkage void inthandler(void); + +void coldfire_trap_init(void) +{ + int i; +#ifdef MCF_MEMORY_PROTECT + extern unsigned long _end; + extern unsigned long memory_end; +#endif + +#ifndef ENABLE_dBUG + mcf_setimr(MCFSIM_IMR_MASKALL); +#endif + + /* + * There is a common trap handler and common interrupt + * handler that handle almost every vector. We treat + * the system call and bus error special, they get their + * own first level handlers. + */ +#ifndef ENABLE_dBUG + for (i = 3; (i <= 23); i++) + _ramvec[i] = trap; + for (i = 33; (i <= 63); i++) + _ramvec[i] = trap; +#endif + + for (i = 24; (i <= 30); i++) + _ramvec[i] = inthandler; +#ifndef ENABLE_dBUG + _ramvec[31] = inthandler; // Disables the IRQ7 button +#endif + + for (i = 64; (i < 255); i++) + _ramvec[i] = inthandler; + _ramvec[255] = 0; + + _ramvec[2] = buserr; + _ramvec[32] = system_call; +} + +/***************************************************************************/ + +#ifdef CONFIG_NETtel + +/* + * Routines to support the NETtel software reset button. + */ +void reset_button(int irq, void *dev_id, struct pt_regs *regs) +{ + extern void flash_eraseconfig(void); + static int inbutton = 0; + + /* + * IRQ7 is not maskable by the CPU core. It is possible + * that switch bounce may get us back here before we have + * really serviced the interrupt. + */ + if (inbutton) + return; + inbutton = 1; + /* Disable interrupt at SIM - best we can do... */ + mcf_setimr(mcf_getimr() | MCFSIM_IMR_EINT7); + /* Try and de-bounce the switch a little... */ + udelay(10000); + + flash_eraseconfig(); + + /* Don't leave here 'till button is no longer pushed! */ + for (;;) { + if ((mcf_getipr() & MCFSIM_IMR_EINT7) == 0) + break; + } + + HARD_RESET_NOW(); + /* Should never get here... */ + + inbutton = 0; + /* Interrupt service done, enable it again */ + mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_EINT7); +} + +/***************************************************************************/ + +void reset_setupbutton(void) +{ + mcf_autovector(31); + request_irq(31, reset_button, (SA_INTERRUPT | IRQ_FLG_FAST), + "Reset Button", NULL); +} + +#endif /* CONFIG_NETtel */ + +/***************************************************************************/ + +void config_BSP(char *commandp, int size) +{ +#ifdef CONFIG_NETtel + /* Copy command line from FLASH to local buffer... */ + memcpy(commandp, (char *) 0xf0004000, size); + commandp[size-1] = 0; +#else + memset(commandp, 0, size); +#endif /* CONFIG_NETtel */ + + mach_sched_init = coldfire_timer_init; + mach_tick = coldfire_tick; + mach_trap_init = coldfire_trap_init; +} + +/***************************************************************************/ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/5206e/eLITE/crt0_ram.S linux.2.5.45-ac1/arch/m68knommu/platform/5206e/eLITE/crt0_ram.S --- linux.2.5.45/arch/m68knommu/platform/5206e/eLITE/crt0_ram.S 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/5206e/eLITE/crt0_ram.S 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,339 @@ +/*****************************************************************************/ + +/* + * crt0_ram.S -- startup code for MCF5206e ColdFire based eLITE boards. + * + * (C) Copyright 1999-2002, Greg Ungerer (gerg@snapgear.com). + * Copyright (C) 1999 Rob Scott (rscott@mtrob.fdns.net) + * + * 1999/02/24 Modified for the 5307 processor David W. Miller + */ + +/*****************************************************************************/ + +#include "linux/autoconf.h" +#include "asm/coldfire.h" +#include "asm/mcfsim.h" + +/*****************************************************************************/ + +/* + * M5206eLITE ColdFire eval board, chip select and memory setup. + */ + +#ifdef CONFIG_SMALL +#define MEM_BASE 0x30000000 /* Base memory for M5206eLITE */ +#define MEM_RESERVED 0x00020000 /* Don't use memory reserved by dBUG */ +#define MEM_SIZE 0x00100000 /* 1 MB of SRAM on M5206eLITE */ +#else +#define MEM_BASE 0x00000000 /* Base memory for M5206eLITE */ +#define MEM_RESERVED 0x00010000 /* Skip first MEM_LUMP for colilo */ +#define MEM_SIZE 0x02000000 /* Max DRAM 32Mb */ +#endif +#define MEM_MIN MEM_BASE+MEM_RESERVED +/* Define end of probeable memory space */ +#define MEM_MAX MEM_BASE+MEM_SIZE +#define MEM_BUILTIN 0x20000000 /* Put built in SRAM at dBUG loc */ +#define MEM_TMPSTACK MEM_BUILTIN+0x800 /* Use built in SRAM for tmp stack */ +#define MEM_LUMP 0x00010000 /* 64 Kb chunks */ +#define VBR_BASE MEM_BUILTIN /* Use built in SRAM for vectors */ + +#define CS0_ADDR 0x0000ffe0 /* CS0 connected to Flash ROM */ +#define CS0_MASK 0x000f0000 /* is 1Mbyte */ +#define CS0_CTRL 0x00001da3 /* read-write (for flash) */ +#define CS1_ADDR 0x00000000 /* CS1 not connected */ +#define CS1_MASK 0x00000000 +#define CS1_CTRL 0x00000000 +#define CS2_ADDR 0x00003000 /* CS2 connected to SRAM */ +#define CS2_MASK 0x000f0000 /* is 1Mbyte */ +#define CS2_CTRL 0x00001903 /* read-write */ +#define CS3_ADDR 0x00004000 /* CS3 connected to LED, par port */ +#define CS3_MASK 0x000f0000 /* is 1Mbyte */ +#define CS3_CTRL 0x00000183 /* read-write */ +#define CS4_ADDR 0x00000000 /* CS4 not connected */ +#define CS4_MASK 0x00000000 +#define CS4_CTRL 0x00000000 +#define CS5_ADDR 0x00000000 /* CS5 not connected */ +#define CS5_MASK 0x00000000 +#define CS5_CTRL 0x00000000 +#define CS6_ADDR 0x00000000 /* CS6 not connected */ +#define CS6_MASK 0x00000000 +#define CS6_CTRL 0x00000000 +#define CS7_ADDR 0x00000000 /* CS7 not connected */ +#define CS7_MASK 0x00000000 +#define CS7_CTRL 0x00000000 +#define DMC_CTRL 0x00000000 /* default memory control */ + +#define DCRR 0x00000034 /* Refresh period */ +/* DCTR definition: + <15>: DAEM, 1 = Drive Multiplexed Address During External Master DRAM xfer + <14>: EDO, 1 = EDO, 0 = Normal + <12>: RCD, 1 = 2 clk RAS-to-CAS, 0 = 1.0 clk RAS-to-CAS + <10:09>: RSH, 10 = 3.5 clk RAS low, 01 = 2.5 clk, 00 = 1.5 clk + <06:05>: RP, 10 = 3.5 clk RAS Precharge, 01 = 2.5 clk, 00 = 1.5 clk + <03>: CAS, 1 = 2.5 clk CAS assertion, 0 = 1.5 clk + <01>: CP, 1 = 1.5 CAS clk precharge, 0 = .5 clk + <00>: CSR, 1 = 2.0 clk CAS before RAS setup, 0 = 1.0 clk +*/ +#define DCTR 0x0000144B /* Slow DRAM */ +#define DCAR0 0x00000000 /* DRAM0 address, 0 base addr */ +#define DCMR0 0x003e0000 /* DRAM0 mask, 4Mb DRAM */ +#define DCCR0 0x00000007 /* DRAM0 control, R/W, burst pg mde */ +#define DCAR1 0x00000000 /* DRAM1 address, 0 base addr */ +#define DCMR1 0x00000000 /* DRAM1 mask, no DRAM */ +#define DCCR1 0x00000000 /* DRAM1 control, off */ + +/*****************************************************************************/ + +.global _start +.global _rambase +.global _ramvec +.global _ramstart +.global _ramend + +/*****************************************************************************/ + +.data + +/* + * Set up the usable of RAM stuff. Size of RAM is determined then + * an initial stack set up at the end. + */ +_rambase: +.long 0 +_ramvec: +.long 0 +_ramstart: +.long 0 +_ramend: +.long 0 + +/*****************************************************************************/ + +.text + +/* + * This is the codes first entry point. This is where it all + * begins... + */ + +_start: + nop /* Filler */ + move.w #0x2700, %sr /* No interrupts */ + + move.l #MCF_MBAR+1, %a0 /* Set I/O base addr */ + movec %a0, %MBAR /* Note: bit 0 is Validate */ + move.l #MEM_BUILTIN+1,%a0 /* Set SRAM base addr */ + movec %a0, %RAMBAR0 /* Note: bit 0 is Validate */ + + move.l #MCF_MBAR, %a0 /* Get I/O base addr */ + + /* ----------------------- CS1 ----------------------- */ + move.w #CS1_ADDR, %d0 /* CS1 address */ + move.w %d0, MCFSIM_CSAR1(%a0) /* CS1 address */ + move.l #CS1_MASK, %d0 /* CS1 mask */ + move.l %d0, MCFSIM_CSMR1(%a0) /* CS1 mask */ + move.w #CS1_CTRL, %d0 /* CS1 control */ + move.w %d0, MCFSIM_CSCR1(%a0) /* CS1 control */ + + /* ----------------------- CS2 ----------------------- */ + move.w #CS2_ADDR, %d0 /* CS2 address */ + move.w %d0, MCFSIM_CSAR2(%a0) /* CS2 address */ + move.l #CS2_MASK, %d0 /* CS2 mask */ + move.l %d0, MCFSIM_CSMR2(%a0) /* CS2 mask */ + move.w #CS2_CTRL, %d0 /* CS2 control */ + move.w %d0, MCFSIM_CSCR2(%a0) /* CS2 control */ + + /* ----------------------- CS3 ----------------------- */ + move.w #CS3_ADDR, %d0 /* CS3 address */ + move.w %d0, MCFSIM_CSAR3(%a0) /* CS3 address */ + move.l #CS3_MASK, %d0 /* CS3 mask */ + move.l %d0, MCFSIM_CSMR3(%a0) /* CS3 mask */ + move.w #CS3_CTRL, %d0 /* CS3 control */ + move.w %d0, MCFSIM_CSCR3(%a0) /* CS3 control */ + + /* ----------------------- CS4 ----------------------- */ + move.w #CS4_ADDR, %d0 /* CS4 address */ + move.w %d0, MCFSIM_CSAR4(%a0) /* CS4 address */ + move.l #CS4_MASK, %d0 /* CS4 mask */ + move.l %d0, MCFSIM_CSMR4(%a0) /* CS4 mask */ + move.w #CS4_CTRL, %d0 /* CS4 control */ + move.w %d0, MCFSIM_CSCR4(%a0) /* CS4 control */ + + /* ----------------------- CS5 ----------------------- */ + move.w #CS5_ADDR, %d0 /* CS5 address */ + move.w %d0, MCFSIM_CSAR5(%a0) /* CS5 address */ + move.l #CS5_MASK, %d0 /* CS5 mask */ + move.l %d0, MCFSIM_CSMR5(%a0) /* CS5 mask */ + move.w #CS5_CTRL, %d0 /* CS5 control */ + move.w %d0, MCFSIM_CSCR5(%a0) /* CS5 control */ + + /* ----------------------- CS6 ----------------------- */ + move.w #CS6_ADDR, %d0 /* CS6 address */ + move.w %d0, MCFSIM_CSAR6(%a0) /* CS6 address */ + move.l #CS6_MASK, %d0 /* CS6 mask */ + move.l %d0, MCFSIM_CSMR6(%a0) /* CS6 mask */ + move.w #CS6_CTRL, %d0 /* CS6 control */ + move.w %d0, MCFSIM_CSCR6(%a0) /* CS6 control */ + + /* ----------------------- CS7 ----------------------- */ + move.w #CS7_ADDR, %d0 /* CS7 address */ + move.w %d0, MCFSIM_CSAR7(%a0) /* CS7 address */ + move.l #CS7_MASK, %d0 /* CS7 mask */ + move.l %d0, MCFSIM_CSMR7(%a0) /* CS7 mask */ + move.w #CS7_CTRL, %d0 /* CS7 control */ + move.w %d0, MCFSIM_CSCR7(%a0) /* CS7 control */ + + /* --------------------- Default --------------------- */ + move.w #DMC_CTRL, %d0 /* Default control */ + move.w %d0, MCFSIM_DMCR(%a0) /* Default control */ + + /* ----------------------- DRAM ------------------------ */ + move.w #DCRR, %d0 /* Refresh period */ + move.w %d0, MCFSIM_DCRR(%a0) /* Refresh period */ + move.w #DCTR, %d0 /* Timing address */ + move.w %d0, MCFSIM_DCTR(%a0) /* Timing address */ + move.w #DCAR0, %d0 /* DRAM0 base address */ + move.w %d0, MCFSIM_DCAR0(%a0) /* DRAM0 base address */ + move.l #DCMR0, %d0 /* DRAM0 mask */ + move.l %d0, MCFSIM_DCMR0(%a0) /* DRAM0 mask */ + move.b #DCCR0, %d0 /* DRAM0 control */ + move.b %d0, MCFSIM_DCCR0(%a0) /* DRAM0 control */ + move.w #DCAR1, %d0 /* DRAM1 base address */ + move.w %d0, MCFSIM_DCAR1(%a0) /* DRAM1 base address */ + move.l #DCMR1, %d0 /* DRAM1 mask */ + move.l %d0, MCFSIM_DCMR1(%a0) /* DRAM1 mask */ + move.b #DCCR1, %d0 /* DRAM1 control */ + move.b %d0, MCFSIM_DCCR1(%a0) /* DRAM1 control */ + + /* + * ChipSelect 0 - ROM cs + * + * ChipSelect 0 is the global chip select coming out of system reset. + * CS0 is asserted for every access until CSMR0 is written. Therefore, + * the entire ChipSelect must be properly set prior to asserting + * CSCR0_V. + */ + move.w #CS0_ADDR, %d0 /* CS0 address */ + move.w %d0, MCFSIM_CSAR0(%a0) /* CS0 address */ + move.l #CS0_MASK, %d0 /* CS0 mask */ + move.l %d0, MCFSIM_CSMR0(%a0) /* CS0 mask */ + move.w #CS0_CTRL, %d0 /* CS0 control */ + move.w %d0, MCFSIM_CSCR0(%a0) /* CS0 control */ + + + /* + * Setup VBR here, otherwise buserror remap will not work. + * if dBug was active before (on my SBC with dBug 1.1 of Dec 16 1996) + * + * bkr@cut.de 19990306 + * + * Note: this is because dBUG points VBR to ROM, making vectors read + * only, so the bus trap can't be changed. (RS) + */ + move.l #VBR_BASE, %a7 /* Note VBR can't be read */ + movec %a7, %VBR + move.l %a7, _ramvec /* Set up vector addr */ + move.l %a7, _rambase /* Set up base RAM addr */ + + + /* + * Determine size of RAM, then set up initial stack + * Done differently for different eval boards and cpus. + */ + +#if defined(CONFIG_SMALL) + /* + * Set to SRAM size when configuring a minimal system + */ + move.l #MEM_MAX, %a0 + +#else + /* + * On the Arnewsh 5206 board and the Motorola m5206eLITE board + * we can probe for the amount of DRAM present... + */ + move.l #MEM_MIN, %a0 /* Start at bottom */ + move.l #MEM_MAX, %a1 /* Set stop point */ + lea.l MEM_TMPSTACK, %sp /* Set up tmp stack ptr */ + + move.l #VBR_BASE+8, %a2 /* Address of bus trap */ + lea.l _ram_buserr, %a3 /* Get RAM trap address */ + move.l %a3, (%a2) /* Set trap to local ptr */ + +_find_ram: + move.l (%a0), %d0 /* Attempt read */ + add.l #MEM_LUMP, %a0 /* Try next bank */ + cmp.l %a1, %a0 /* Check more? */ + bne _find_ram + + /* + * BUS error trap handler - used for RAM probing. + */ +_ram_buserr: + bra _found_ram + +_found_ram: /* Vectored here on bus err */ +#endif + + move.l %a0, %d0 /* Mem end addr is in a0 */ + move.l %d0, %sp /* Set up initial stack ptr */ + move.l %d0, _ramend /* Set end ram addr */ + + + /* + * Enable CPU internal cache. + */ + move.l #0x01000000, %d0 /* Invalidate cache cmd */ + movec %d0, %CACR /* Invalidate cache */ + move.l #0x80000100, %d0 /* Setup cache mask */ + movec %d0, %CACR /* Enable cache */ + + + /* + * Move ROM filesystem above bss :-) + */ + lea.l _sbss, %a0 /* Get start of bss */ + lea.l _ebss, %a1 /* Set up destination */ + move.l %a0, %a2 /* Copy of bss start */ + + move.l 8(%a0), %d0 /* Get size of ROMFS */ + addq.l #8, %d0 /* Allow for rounding */ + and.l #0xfffffffc, %d0 /* Whole words */ + + add.l %d0, %a0 /* Copy from end */ + add.l %d0, %a1 /* Copy from end */ + move.l %a1, _ramstart /* Set start of ram */ + +_copy_romfs: + move.l -(%a0), %d0 /* Copy dword */ + move.l %d0, -(%a1) + cmp.l %a0, %a2 /* Check if at end */ + bne _copy_romfs + + /* + * Zero out the bss region. + */ + lea.l _sbss, %a0 /* Get start of bss */ + lea.l _ebss, %a1 /* Get end of bss */ + clr.l %d0 /* Set value */ +_clear_bss: + move.l %d0, (%a0)+ /* Clear each word */ + cmp.l %a0, %a1 /* Check if at end */ + bne _clear_bss + + /* + * Load the current task pointer and stack. + */ + lea init_thread_union, %a0 + lea 0x2000(%a0), %sp + + /* + * Assember start up done, start code proper. + */ + jsr start_kernel /* Start Linux kernel */ + +_exit: + jmp _exit /* Should never get here */ + +/*****************************************************************************/ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/5206e/eLITE/ram.ld linux.2.5.45-ac1/arch/m68knommu/platform/5206e/eLITE/ram.ld --- linux.2.5.45/arch/m68knommu/platform/5206e/eLITE/ram.ld 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/5206e/eLITE/ram.ld 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,72 @@ + +MEMORY { + ram : ORIGIN = 0x30020000, LENGTH = 0xe0000 +} + +jiffies = jiffies_64 + 4; + +SECTIONS { + + .text 0x30020000 : { + _stext = . ; + *(.text) + *(.exit.text) + *(.text.lock) + *(.exitcall.exit) + *(.rodata) + . = ALIGN(0x4) ; + *(.kstrtab) + . = ALIGN(16); /* Exception table */ + __start___ex_table = .; + *(__ex_table) + __stop___ex_table = .; + + __start___ksymtab = .; /* Kernel symbol table */ + *(__ksymtab) + __stop___ksymtab = .; + . = ALIGN(4) ; + _etext = . ; + } > ram + + .data BLOCK(0x4) : { + _sdata = . ; + __data_start = . ; + *(.data) + *(.data.exit) + . = ALIGN(0x2000) ; + *(.data.init_task) + . = ALIGN(0x2000) ; + _edata = . ; + } > ram + + .init BLOCK(4096) : { + __init_begin = .; + *(.init.text) + *(.init.data) + . = ALIGN(16); + __setup_start = .; + *(.init.setup) + __setup_end = .; + __initcall_start = .; + *(.initcall1.init) + *(.initcall2.init) + *(.initcall3.init) + *(.initcall4.init) + *(.initcall5.init) + *(.initcall6.init) + *(.initcall7.init) + __initcall_end = .; + . = ALIGN(4) ; + __init_end = .; + } > ram + + .bss BLOCK(0x4) : { + _sbss = . ; + *(.bss) + *(COMMON) + . = ALIGN(4) ; + _ebss = . ; + _end = . ; + } > ram +} + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/5206e/Makefile linux.2.5.45-ac1/arch/m68knommu/platform/5206e/Makefile --- linux.2.5.45/arch/m68knommu/platform/5206e/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/5206e/Makefile 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,24 @@ +# +# Makefile for the m68knommu linux kernel. +# + +# +# If you want to play with the HW breakpoints then you will +# need to add define this, which will give you a stack backtrace +# on the console port whenever a DBG interrupt occurs. You have to +# set up you HW breakpoints to trigger a DBG interrupt: +# +# EXTRA_CFLAGS += -DTRAP_DBG_INTERRUPT +# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT +# + +ifdef CONFIG_FULLDEBUG +AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1 +endif + +obj-y := config.o + +EXTRA_TARGETS := $(BOARD)/crt0_$(MODEL).o + +include $(TOPDIR)/Rules.make + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/5206e/MOTOROLA/crt0_ram.S linux.2.5.45-ac1/arch/m68knommu/platform/5206e/MOTOROLA/crt0_ram.S --- linux.2.5.45/arch/m68knommu/platform/5206e/MOTOROLA/crt0_ram.S 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/5206e/MOTOROLA/crt0_ram.S 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,145 @@ +/*****************************************************************************/ + +/* + * crt0_ram.S -- startup code for MCF5206e ColdFire based CADRE3 boards. + * + * (C) Copyright 1999-2002, Greg Ungerer (gerg@snapgear.com) + * + * 1999/02/24 Modified for the 5307 processor David W. Miller + */ + +/*****************************************************************************/ + +#include "linux/autoconf.h" +#include "asm/coldfire.h" +#include "asm/mcfsim.h" + +/*****************************************************************************/ + +/* + * Cadre-III M5206e ColdFire eval board, chip select and memory setup. + */ + +#define MEM_BASE 0x00000000 /* Memory base at address 0 */ +#define MEM_SIZE 0x00400000 /* Memory size 4Mb */ +#define VBR_BASE MEM_BASE /* Vector address */ + +/*****************************************************************************/ + +.global _start +.global _rambase +.global _ramvec +.global _ramstart +.global _ramend + +/*****************************************************************************/ + +.data + +/* + * Set up the usable of RAM stuff. Size of RAM is determined then + * an initial stack set up at the end. + */ +_rambase: +.long 0 +_ramvec: +.long 0 +_ramstart: +.long 0 +_ramend: +.long 0 + +/*****************************************************************************/ + +.text + +/* + * This is the codes first entry point. This is where it all + * begins... + */ + +_start: + nop /* Filler */ + move.w #0x2700, %sr /* No interrupts */ + + /* + * Setup VBR here, otherwise buserror remap will not work. + * if dBug was active before (on my SBC with dBug 1.1 of Dec 16 1996) + * + * bkr@cut.de 19990306 + * + * Note: this is because dBUG points VBR to ROM, making vectors read + * only, so the bus trap can't be changed. (RS) + */ + move.l #VBR_BASE, %a7 /* Note VBR can't be read */ + movec %a7, %VBR + move.l %a7, _ramvec /* Set up vector addr */ + move.l %a7, _rambase /* Set up base RAM addr */ + + + /* + * Set to 4 meg for the Cadre III board (m5206e). + */ + move.l #MEM_SIZE, %a0 + + move.l %a0, %d0 /* Mem end addr is in a0 */ + move.l %d0, %sp /* Set up initial stack ptr */ + move.l %d0, _ramend /* Set end ram addr */ + + + /* + * Enable CPU internal cache. + */ + move.l #0x01000000, %d0 /* Invalidate cache cmd */ + movec %d0, %CACR /* Invalidate cache */ + move.l #0x80000100, %d0 /* Setup cache mask */ + movec %d0, %CACR /* Enable cache */ + + + /* + * Move ROM filesystem above bss :-) + */ + lea.l _sbss, %a0 /* Get start of bss */ + lea.l _ebss, %a1 /* Set up destination */ + move.l %a0, %a2 /* Copy of bss start */ + + move.l 8(%a0), %d0 /* Get size of ROMFS */ + addq.l #8, %d0 /* Allow for rounding */ + and.l #0xfffffffc, %d0 /* Whole words */ + + add.l %d0, %a0 /* Copy from end */ + add.l %d0, %a1 /* Copy from end */ + move.l %a1, _ramstart /* Set start of ram */ + +_copy_romfs: + move.l -(%a0), %d0 /* Copy dword */ + move.l %d0, -(%a1) + cmp.l %a0, %a2 /* Check if at end */ + bne _copy_romfs + + /* + * Zero out the bss region. + */ + lea.l _sbss, %a0 /* Get start of bss */ + lea.l _ebss, %a1 /* Get end of bss */ + clr.l %d0 /* Set value */ +_clear_bss: + move.l %d0, (%a0)+ /* Clear each word */ + cmp.l %a0, %a1 /* Check if at end */ + bne _clear_bss + + /* + * Load the current task pointer and stack. + */ + lea init_thread_union, %a0 + lea 0x2000(%a0), %sp + + /* + * Assember start up done, start code proper. + */ + jsr start_kernel /* Start Linux kernel */ + +_exit: + jmp _exit /* Should never get here */ + +/*****************************************************************************/ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/5206e/MOTOROLA/ram.ld linux.2.5.45-ac1/arch/m68knommu/platform/5206e/MOTOROLA/ram.ld --- linux.2.5.45/arch/m68knommu/platform/5206e/MOTOROLA/ram.ld 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/5206e/MOTOROLA/ram.ld 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,72 @@ + +MEMORY { + ram : ORIGIN = 0x20000, LENGTH = 0x007E0000 +} + +jiffies = jiffies_64 + 4; + +SECTIONS { + + .text : { + _stext = . ; + *(.text) + *(.exit/text) + *(.text.lock) + *(.exitcall.exit) + *(.rodata) + . = ALIGN(0x4) ; + *(.kstrtab) + . = ALIGN(16); /* Exception table */ + __start___ex_table = .; + *(__ex_table) + __stop___ex_table = .; + + __start___ksymtab = .; /* Kernel symbol table */ + *(__ksymtab) + __stop___ksymtab = .; + . = ALIGN(4) ; + _etext = . ; + } > ram + + .data BLOCK(0x4) : { + _sdata = . ; + __data_start = . ; + *(.data) + *(.data.exit) + . = ALIGN(0x2000) ; + *(.data.init_task) + . = ALIGN(0x2000) ; + _edata = . ; + } > ram + + .init BLOCK(4096) : { + __init_begin = .; + *(.init.text) + *(.init.data) + . = ALIGN(16); + __setup_start = .; + *(.init.setup) + __setup_end = .; + __initcall_start = .; + *(.initcall1.init) + *(.initcall2.init) + *(.initcall3.init) + *(.initcall4.init) + *(.initcall5.init) + *(.initcall6.init) + *(.initcall7.init) + __initcall_end = .; + . = ALIGN(4) ; + __init_end = .; + } > ram + + .bss BLOCK(0x4) : { + _sbss = . ; + *(.bss) + *(COMMON) + . = ALIGN(4) ; + _ebss = . ; + _end = . ; + } > ram +} + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/5249/config.c linux.2.5.45-ac1/arch/m68knommu/platform/5249/config.c --- linux.2.5.45/arch/m68knommu/platform/5249/config.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/5249/config.c 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,229 @@ +/***************************************************************************/ + +/* + * linux/arch/m68knommu/platform/5249/config.c + * + * Copyright (C) 2002, Greg Ungerer (gerg@snapgear.com) + */ + +/***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/***************************************************************************/ + +void coldfire_profile_init(void); + +/***************************************************************************/ + +/* + * DMA channel base address table. + */ +unsigned int dma_base_addr[MAX_M68K_DMA_CHANNELS] = { + MCF_MBAR + MCFDMA_BASE0, + MCF_MBAR + MCFDMA_BASE1, + MCF_MBAR + MCFDMA_BASE2, + MCF_MBAR + MCFDMA_BASE3, +}; + +unsigned int dma_device_address[MAX_M68K_DMA_CHANNELS]; + +/***************************************************************************/ + +void coldfire_tick(void) +{ + volatile unsigned char *timerp; + + /* Reset the ColdFire timer */ + timerp = (volatile unsigned char *) (MCF_MBAR + MCFTIMER_BASE1); + timerp[MCFTIMER_TER] = MCFTIMER_TER_CAP | MCFTIMER_TER_REF; +} + +/***************************************************************************/ + +void coldfire_timer_init(void (*handler)(int, void *, struct pt_regs *)) +{ + volatile unsigned short *timerp; + volatile unsigned char *icrp; + + /* Set up TIMER 1 as poll clock */ + timerp = (volatile unsigned short *) (MCF_MBAR + MCFTIMER_BASE1); + timerp[MCFTIMER_TMR] = MCFTIMER_TMR_DISABLE; + + timerp[MCFTIMER_TRR] = (unsigned short) ((MCF_CLK / 16) / HZ); + timerp[MCFTIMER_TMR] = MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 | + MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE; + + icrp = (volatile unsigned char *) (MCF_MBAR + MCFSIM_TIMER1ICR); + *icrp = MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL5 | MCFSIM_ICR_PRI3; + request_irq(29, handler, SA_INTERRUPT, "ColdFire Timer", NULL); + +#ifdef CONFIG_HIGHPROFILE + coldfire_profile_init(); +#endif + mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_TIMER1); +} + +/***************************************************************************/ +#ifdef CONFIG_HIGHPROFILE +/***************************************************************************/ + +#define PROFILEHZ 1013 + +/* + * Use the other timer to provide high accuracy profiling info. + */ + +void coldfire_profile_tick(int irq, void *dummy, struct pt_regs *regs) +{ + volatile unsigned char *timerp; + + /* Reset the ColdFire timer2 */ + timerp = (volatile unsigned char *) (MCF_MBAR + MCFTIMER_BASE2); + timerp[MCFTIMER_TER] = MCFTIMER_TER_CAP | MCFTIMER_TER_REF; + + if (!user_mode(regs)) { + if (prof_buffer && current->pid) { + extern int _stext; + unsigned long ip = instruction_pointer(regs); + ip -= (unsigned long) &_stext; + ip >>= prof_shift; + if (ip < prof_len) + prof_buffer[ip]++; + } + } +} + +void coldfire_profile_init(void) +{ + volatile unsigned short *timerp; + volatile unsigned char *icrp; + + printk("PROFILE: lodging timer2=%d as profile timer\n", PROFILEHZ); + + /* Set up TIMER 2 as poll clock */ + timerp = (volatile unsigned short *) (MCF_MBAR + MCFTIMER_BASE2); + timerp[MCFTIMER_TMR] = MCFTIMER_TMR_DISABLE; + + timerp[MCFTIMER_TRR] = (unsigned short) ((MCF_CLK / 16) / PROFILEHZ); + timerp[MCFTIMER_TMR] = MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 | + MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE; + + icrp = (volatile unsigned char *) (MCF_MBAR + MCFSIM_TIMER2ICR); + + *icrp = MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL7 | MCFSIM_ICR_PRI3; + request_irq(31, coldfire_profile_tick, (SA_INTERRUPT | IRQ_FLG_FAST), + "Profile Timer", NULL); + mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_TIMER2); +} + +/***************************************************************************/ +#endif /* CONFIG_HIGHPROFILE */ +/***************************************************************************/ + +/* + * Program the vector to be an auto-vectored. + */ + +void mcf_autovector(unsigned int vec) +{ + volatile unsigned char *mbar; + + if ((vec >= 25) && (vec <= 31)) { + mbar = (volatile unsigned char *) MCF_MBAR; + vec = 0x1 << (vec - 24); + *(mbar + MCFSIM_AVR) |= vec; + mcf_setimr(mcf_getimr() & ~vec); + } +} + +/***************************************************************************/ + +extern e_vector *_ramvec; + +void set_evector(int vecnum, void (*handler)(void)) +{ + if (vecnum >= 0 && vecnum <= 255) + _ramvec[vecnum] = handler; +} + +/***************************************************************************/ + +/* assembler routines */ +asmlinkage void buserr(void); +asmlinkage void trap(void); +asmlinkage void system_call(void); +asmlinkage void inthandler(void); + +void __init coldfire_trap_init(void) +{ + int i; + +#ifndef ENABLE_dBUG + mcf_setimr(MCFSIM_IMR_MASKALL); +#endif + + /* + * There is a common trap handler and common interrupt + * handler that handle almost every vector. We treat + * the system call and bus error special, they get their + * own first level handlers. + */ +#ifndef ENABLE_dBUG + for (i = 3; (i <= 23); i++) + _ramvec[i] = trap; + for (i = 33; (i <= 63); i++) + _ramvec[i] = trap; +#endif + + for (i = 24; (i <= 30); i++) + _ramvec[i] = inthandler; +#ifndef ENABLE_dBUG + _ramvec[31] = inthandler; // Disables the IRQ7 button +#endif + + for (i = 64; (i < 255); i++) + _ramvec[i] = inthandler; + _ramvec[255] = 0; + + _ramvec[2] = buserr; + _ramvec[32] = system_call; +} + +/***************************************************************************/ + +void config_BSP(char *commandp, int size) +{ + memset(commandp, 0, size); + + mach_sched_init = coldfire_timer_init; + mach_tick = coldfire_tick; + mach_trap_init = coldfire_trap_init; +} + +/***************************************************************************/ +#ifdef TRAP_DBG_INTERRUPT + +asmlinkage void dbginterrupt_c(struct frame *fp) +{ + extern void dump(struct pt_regs *fp); + printk("%s(%d): BUS ERROR TRAP\n", __FILE__, __LINE__); + dump((struct pt_regs *) fp); + asm("halt"); +} + +#endif +/***************************************************************************/ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/5249/Makefile linux.2.5.45-ac1/arch/m68knommu/platform/5249/Makefile --- linux.2.5.45/arch/m68knommu/platform/5249/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/5249/Makefile 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,24 @@ +# +# Makefile for the m68knommu linux kernel. +# + +# +# If you want to play with the HW breakpoints then you will +# need to add define this, which will give you a stack backtrace +# on the console port whenever a DBG interrupt occurs. You have to +# set up you HW breakpoints to trigger a DBG interrupt: +# +# EXTRA_CFLAGS += -DTRAP_DBG_INTERRUPT +# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT +# + +ifdef CONFIG_FULLDEBUG +AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1 +endif + +obj-y := config.o + +EXTRA_TARGETS := $(BOARD)/crt0_$(MODEL).o + +include $(TOPDIR)/Rules.make + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/5249/MOTOROLA/crt0_ram.S linux.2.5.45-ac1/arch/m68knommu/platform/5249/MOTOROLA/crt0_ram.S --- linux.2.5.45/arch/m68knommu/platform/5249/MOTOROLA/crt0_ram.S 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/5249/MOTOROLA/crt0_ram.S 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,223 @@ +/*****************************************************************************/ + +/* + * crt0_ram.S -- startup code for Motorola M5249C3 eval board. + * + * (C) Copyright 1999-2002, Greg Ungerer (gerg@snapgear.com). + */ + +/*****************************************************************************/ + +#include "linux/autoconf.h" +#include "asm/coldfire.h" +#include "asm/mcfsim.h" + +/*****************************************************************************/ + +/* + * Motorola M5249C3 ColdFire eval board, chip select and memory setup. + */ +#define MEM_BASE 0x00000000 /* Memory base at address 0 */ +#define MEM_SIZE 0x00800000 /* Memory size 8MB */ +#define VBR_BASE MEM_BASE /* Vector address */ + +/*****************************************************************************/ + +.global _start +.global _rambase +.global _ramvec +.global _ramstart +.global _ramend + +/*****************************************************************************/ + +.data + +/* + * Set up the usable of RAM stuff. Size of RAM is determined then + * an initial stack set up at the end. + */ +_rambase: +.long 0 +_ramvec: +.long 0 +_ramstart: +.long 0 +_ramend: +.long 0 + +/*****************************************************************************/ + +.text + +/* + * This is the codes first entry point. This is where it all + * begins... + */ + +_start: + nop /* Filler */ + move.w #0x2700, %sr /* No interrupts */ + + /* + * Set MBAR1 and MBAR2, just incase they are not set. + */ + move.l #0x10000001, %a0 + movec %a0, %MBAR /* Map MBAR region */ + subq.l #1, %a0 /* Get MBAR address in a0 */ + + move.l #0x80000001, %a1 + movec %a1, #3086 /* Map MBAR2 region */ + subq.l #1, %a1 /* Get MBAR2 address in a1 */ + + /* + * Move secondary interrupts to base at 128. + */ + move.b #0x80, %d0 + move.b %d0, 0x16b(%a1) /* Interrupt base register */ + +#if 1 + /* + * Work around broken CSMR0/DRAM vector problem. + */ + move.l #0x001F0021, %d0 /* Disable C/I bit */ + move.l %d0, 0x84(%a0) /* Set CSMR0 */ +#endif + + /* + * Disable the PLL firstly. (Who knows what state it is + * in here!). + */ + move.l 0x180(%a1), %d0 /* Get current PLL value */ + and.l #0xfffffffe, %d0 /* PLL bypass first */ + move.l %d0, 0x180(%a1) /* Set PLL register */ + nop + +#if CONFIG_CLOCK_140MHz + /* + * Set initial clock frequency. This assumes M5249C3 board + * is fitted with 11.2896MHz crystal. It will program the + * PLL for 140MHz. Lets go fast :-) + */ + move.l #0x125a40f0, %d0 /* Set for 140MHz */ + move.l %d0, 0x180(%a1) /* Set PLL register */ + or.l #0x1, %d0 + move.l %d0, 0x180(%a1) /* Set PLL register */ +#endif + + /* + * Setup CS1 for ethernet controller. + * (Setup as per M5249C3 doco). + */ + move.l #0xe0000000, %d0 /* CS1 mapped at 0xe0000000 */ + move.l %d0, 0x8c(%a0) + move.l #0x001f0021, %d0 /* CS1 size of 1Mb */ + move.l %d0, 0x90(%a0) + move.w #0x0080, %d0 /* CS1 = 16bit port, AA */ + move.w %d0, 0x96(%a0) + + /* + * Setup CS2 for IDE interface. + */ + move.l #0x50000000, %d0 /* CS2 mapped at 0x50000000 */ + move.l %d0, 0x98(%a0) + move.l #0x001f0001, %d0 /* CS2 size of 1MB */ + move.l %d0, 0x9c(%a0) + move.w #0x0080, %d0 /* CS2 = 16bit, TA */ + move.w %d0, 0xa2(%a0) + + move.l #0x00107000, %d0 /* IDEconfig1 */ + move.l %d0, 0x18c(%a1) + move.l #0x000c0400, %d0 /* IDEconfig2 */ + move.l %d0, 0x190(%a1) + + move.l #0x00080000, %d0 /* GPIO19, IDE reset bit */ + or.l %d0, 0xc(%a1) /* Function GPIO19 */ + or.l %d0, 0x8(%a1) /* Enable GPIO19 as output */ + or.l %d0, 0x4(%a1) /* De-assert IDE reset */ + + + /* + * Setup VBR as per eval board (really dBUG does this). + * These settings must match it. + */ + move.l #VBR_BASE, %a0 /* Note VBR can't be read */ + movec %a0, %VBR + move.l %a0, _ramvec /* Set up vector addr */ + move.l %a0, _rambase /* Set up base RAM addr */ + + + /* + * Set the memory size, and then set a temporary stack. + */ + move.l #MEM_SIZE, %a0 + + move.l %a0, %d0 /* Mem end addr is in a0 */ + move.l %d0, %sp /* Set up initial stack ptr */ + move.l %d0, _ramend /* Set end ram addr */ + + + /* + * Enable CPU internal cache. + */ + move.l #0x01000000, %d0 /* Invalidate whole cache */ + movec %d0, %CACR + nop + + move.l #0x0000c000, %d0 /* Set SDRAM cached only */ + movec %d0, %ACR0 + move.l #0x00000000, %d0 /* No other regions cached */ + movec %d0, %ACR1 + + move.l #0xa0000200, %d0 /* Enable cache... */ + movec %d0, %CACR + nop + + + /* + * Move ROM filesystem above bss :-) + */ + lea.l _sbss, %a0 /* Get start of bss */ + lea.l _ebss, %a1 /* Set up destination */ + move.l %a0, %a2 /* Copy of bss start */ + + move.l 8(%a0), %d0 /* Get size of ROMFS */ + addq.l #8, %d0 /* Allow for rounding */ + and.l #0xfffffffc, %d0 /* Whole words */ + + add.l %d0, %a0 /* Copy from end */ + add.l %d0, %a1 /* Copy from end */ + move.l %a1, _ramstart /* Set start of ram */ + +_copy_romfs: + move.l -(%a0), %d0 /* Copy dword */ + move.l %d0, -(%a1) + cmp.l %a0, %a2 /* Check if at end */ + bne _copy_romfs + + /* + * Zero out the bss region. + */ + lea.l _sbss, %a0 /* Get start of bss */ + lea.l _ebss, %a1 /* Get end of bss */ + clr.l %d0 /* Set value */ +_clear_bss: + move.l %d0, (%a0)+ /* Clear each word */ + cmp.l %a0, %a1 /* Check if at end */ + bne _clear_bss + + /* + * Load the current thread pointer and stack. + */ + lea init_thread_union, %a0 + lea 0x2000(%a0), %sp + + /* + * Assember start up done, start code proper. + */ + jsr start_kernel /* Start Linux kernel */ + +_exit: + jmp _exit /* Should never get here */ + +/*****************************************************************************/ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/5249/MOTOROLA/ram.ld linux.2.5.45-ac1/arch/m68knommu/platform/5249/MOTOROLA/ram.ld --- linux.2.5.45/arch/m68knommu/platform/5249/MOTOROLA/ram.ld 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/5249/MOTOROLA/ram.ld 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,76 @@ + +MEMORY { + ram : ORIGIN = 0x20000, LENGTH = 0x3e0000 +} + +jiffies = jiffies_64 + 4; + +SECTIONS { + + .text : { + _stext = . ; + *(.text) + *(.exit.text) + *(.text.lock) + *(.exitcall.exit) + *(.rodata) + *(.modinfo) + . = ALIGN(0x4) ; + *(.kstrtab) + . = ALIGN(16); /* Exception table */ + __start___ex_table = .; + *(__ex_table) + __stop___ex_table = .; + + __start___ksymtab = .; /* Kernel symbol table */ + *(__ksymtab) + __stop___ksymtab = .; + . = ALIGN(4) ; + _etext = . ; + } > ram + + .data BLOCK(0x4) : { + . = ALIGN(4); + _sdata = . ; + __data_start = . ; + *(.data) + *(.data.exit) + . = ALIGN(8192) ; + *(.data.init_task) + . = ALIGN(8192) ; + _edata = . ; + } > ram + + .init BLOCK(4096) : { + . = ALIGN(4096); + __init_begin = .; + *(.init.text) + *(.init.data) + . = ALIGN(16); + __setup_start = .; + *(.init.setup) + __setup_end = .; + __initcall_start = .; + *(.initcall1.init) + *(.initcall2.init) + *(.initcall3.init) + *(.initcall4.init) + *(.initcall5.init) + *(.initcall6.init) + *(.initcall7.init) + __initcall_end = .; + . = ALIGN(4); + __init_end = .; + } > ram + + .bss BLOCK(0x4) : { + . = ALIGN(4); + _sbss = . ; + *(.bss) + *(COMMON) + . = ALIGN(4) ; + _ebss = . ; + _end = . ; + } > ram +} + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/5272/config.c linux.2.5.45-ac1/arch/m68knommu/platform/5272/config.c --- linux.2.5.45/arch/m68knommu/platform/5272/config.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/5272/config.c 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,247 @@ +/***************************************************************************/ + +/* + * linux/arch/m68knommu/platform/5272/config.c + * + * Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com) + * Copyright (C) 2001-2002, SnapGear Inc. (www.snapgear.com) + */ + +/***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/***************************************************************************/ + +void reset_setupbutton(void); + +/***************************************************************************/ + +/* + * DMA channel base address table. + */ +unsigned int dma_base_addr[MAX_M68K_DMA_CHANNELS] = { + MCF_MBAR + MCFDMA_BASE0, +}; + +unsigned int dma_device_address[MAX_M68K_DMA_CHANNELS]; + +/***************************************************************************/ + +void coldfire_tick(void) +{ + volatile unsigned char *timerp; + + /* Reset the ColdFire timer */ + timerp = (volatile unsigned char *) (MCF_MBAR + MCFTIMER_BASE4); + timerp[MCFTIMER_TER] = MCFTIMER_TER_CAP | MCFTIMER_TER_REF; +} + +/***************************************************************************/ + +void coldfire_timer_init(void (*handler)(int, void *, struct pt_regs *)) +{ + volatile unsigned short *timerp; + volatile unsigned long *icrp; + + /* Set up TIMER 4 as poll clock */ + timerp = (volatile unsigned short *) (MCF_MBAR + MCFTIMER_BASE4); + timerp[MCFTIMER_TMR] = MCFTIMER_TMR_DISABLE; + + timerp[MCFTIMER_TRR] = (unsigned short) ((MCF_CLK / 16) / HZ); + timerp[MCFTIMER_TMR] = MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 | + MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE; + + icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1); + *icrp = 0x0000000d; /* TMR4 with priority 5 */ + request_irq(72, handler, SA_INTERRUPT, "ColdFire Timer", NULL); + +#ifdef CONFIG_RESETSWITCH + /* This is not really the right place to do this... */ + reset_setupbutton(); +#endif +} + +/***************************************************************************/ + +/* + * Program the vector to be an auto-vectored. + */ + +void mcf_autovector(unsigned int vec) +{ + /* Everything is auto-vectored on the 5272 */ +} + +/***************************************************************************/ + +extern e_vector *_ramvec; + +void set_evector(int vecnum, void (*handler)(void)) +{ + if (vecnum >= 0 && vecnum <= 255) + _ramvec[vecnum] = handler; +} + +/***************************************************************************/ + +/* assembler routines */ +asmlinkage void buserr(void); +asmlinkage void trap(void); +asmlinkage void system_call(void); +asmlinkage void inthandler(void); + +void coldfire_trap_init(void) +{ + int i; + +#ifndef ENABLE_dBUG + volatile unsigned long *icrp; + + icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1); + icrp[0] = 0x88888888; + icrp[1] = 0x88888888; + icrp[2] = 0x88888888; + icrp[3] = 0x88888888; +#endif + + /* + * There is a common trap handler and common interrupt + * handler that handle almost every vector. We treat + * the system call and bus error special, they get their + * own first level handlers. + */ +#ifndef ENABLE_dBUG + for (i = 3; (i <= 23); i++) + _ramvec[i] = trap; + for (i = 33; (i <= 63); i++) + _ramvec[i] = trap; +#endif + + for (i = 24; (i <= 30); i++) + _ramvec[i] = inthandler; +#ifndef ENABLE_dBUG + _ramvec[31] = inthandler; // Disables the IRQ7 button +#endif + + for (i = 64; (i < 255); i++) + _ramvec[i] = inthandler; + _ramvec[255] = 0; + + _ramvec[2] = buserr; + _ramvec[32] = system_call; +} + +/***************************************************************************/ + +void coldfire_reset(void) +{ + HARD_RESET_NOW(); +} + +/***************************************************************************/ + +void config_BSP(char *commandp, int size) +{ +#if 0 + volatile unsigned long *pivrp; + + /* Set base of device vectors to be 64 */ + pivrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_PIVR); + *pivrp = 0x40; +#endif + +#if defined(CONFIG_NETtel) || defined(CONFIG_eLIA) || \ + defined(CONFIG_DISKtel) || defined(CONFIG_SECUREEDGEMP3) + /* Copy command line from FLASH to local buffer... */ + memcpy(commandp, (char *) 0xf0004000, size); + commandp[size-1] = 0; +#elif defined(CONFIG_MTD_KeyTechnology) + /* Copy command line from FLASH to local buffer... */ + memcpy(commandp, (char *) 0xffe06000, size); + commandp[size-1] = 0; +#else + memset(commandp, 0, size); +#endif + + mach_sched_init = coldfire_timer_init; + mach_tick = coldfire_tick; + mach_trap_init = coldfire_trap_init; + mach_reset = coldfire_reset; +} + +/***************************************************************************/ +#ifdef CONFIG_RESETSWITCH +/***************************************************************************/ + +/* + * Routines to support the NETtel software reset button. + */ +void reset_button(int irq, void *dev_id, struct pt_regs *regs) +{ + volatile unsigned long *icrp, *isrp; + extern void flash_eraseconfig(void); + static int inbutton = 0; + + /* + * IRQ7 is not maskable by the CPU core. It is possible + * that switch bounce mey get us back here before we have + * really serviced the interrupt. + */ + if (inbutton) + return; + inbutton = 1; + + /* Disable interrupt at SIM - best we can do... */ + icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1); + *icrp = (*icrp & 0x07777777) | 0x80000000; + + /* Try and de-bounce the switch a little... */ + udelay(10000); + + flash_eraseconfig(); + + /* Don't leave here 'till button is no longer pushed! */ + isrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ISR); + for (;;) { + if (*isrp & 0x80000000) + break; + } + + HARD_RESET_NOW(); + /* Should never get here... */ + + inbutton = 0; + /* Interrupt service done, acknowledge it */ + icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1); + *icrp = (*icrp & 0x07777777) | 0xf0000000; +} + +/***************************************************************************/ + +void reset_setupbutton(void) +{ + volatile unsigned long *icrp; + + icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1); + *icrp = (*icrp & 0x07777777) | 0xf0000000; + request_irq(65, reset_button, (SA_INTERRUPT | IRQ_FLG_FAST), + "Reset Button", NULL); +} + +/***************************************************************************/ +#endif /* CONFIG_RESETSWITCH */ +/***************************************************************************/ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/5272/Makefile linux.2.5.45-ac1/arch/m68knommu/platform/5272/Makefile --- linux.2.5.45/arch/m68knommu/platform/5272/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/5272/Makefile 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,24 @@ +# +# Makefile for the linux kernel. +# + +# +# If you want to play with the HW breakpoints then you will +# need to add define this, which will give you a stack backtrace +# on the console port whenever a DBG interrupt occurs. You have to +# set up you HW breakpoints to trigger a DBG interrupt: +# +# EXTRA_CFLAGS += -DTRAP_DBG_INTERRUPT +# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT +# + +ifdef CONFIG_FULLDEBUG +AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1 +endif + +obj-y := config.o + +EXTRA_TARGETS := $(BOARD)/crt0_$(MODEL).o + +include $(TOPDIR)/Rules.make + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/5272/MOTOROLA/crt0_ram.S linux.2.5.45-ac1/arch/m68knommu/platform/5272/MOTOROLA/crt0_ram.S --- linux.2.5.45/arch/m68knommu/platform/5272/MOTOROLA/crt0_ram.S 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/5272/MOTOROLA/crt0_ram.S 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,152 @@ +/*****************************************************************************/ + +/* + * crt0_ram.S -- startup code for MCF5272 ColdFire based MOTOROLA boards. + * + * (C) Copyright 1999-2002, Greg Ungerer (gerg@snapgear.com). + * (C) Copyright 2000, Lineo (www.lineo.com). + */ + +/*****************************************************************************/ + +#include +#include +#include +#include +#include +#include + +/*****************************************************************************/ + +/* + * Motorola M5272C3 ColdFire eval board, chip select and memory setup. + */ + +#define MEM_BASE 0x00000000 /* Memory base at address 0 */ +#define VBR_BASE MEM_BASE /* Vector address */ + +#if defined(CONFIG_RAM16MB) +#define MEM_SIZE 0x01000000 /* Memory size 16Mb */ +#elif defined(CONFIG_RAM8MB) +#define MEM_SIZE 0x00800000 /* Memory size 8Mb */ +#else +#define MEM_SIZE 0x00400000 /* Memory size 4Mb */ +#endif + +/*****************************************************************************/ + +.global _start +.global _rambase +.global _ramvec +.global _ramstart +.global _ramend + +/*****************************************************************************/ + +.data + +/* + * Set up the usable of RAM stuff. Size of RAM is determined then + * an initial stack set up at the end. + */ +_rambase: +.long 0 +_ramvec: +.long 0 +_ramstart: +.long 0 +_ramend: +.long 0 + +/*****************************************************************************/ + +.text + +/* + * This is the codes first entry point. This is where it all + * begins... + */ + +_start: + nop /* Filler */ + move.w #0x2700, %sr /* No interrupts */ + + /* + * Setup VBR here, otherwise buserror remap will not work. + * if dBug was active before (on my SBC with dBug 1.1 of Dec 16 1996) + * + * bkr@cut.de 19990306 + * + * Note: this is because dBUG points VBR to ROM, making vectors read + * only, so the bus trap can't be changed. (RS) + */ + move.l #VBR_BASE, %a7 /* Note VBR can't be read */ + movec %a7, %VBR + move.l %a7, _ramvec /* Set up vector addr */ + move.l %a7, _rambase /* Set up base RAM addr */ + + + /* + * Set memory size. + */ + move.l #MEM_SIZE, %a0 + + move.l %a0, %d0 /* Mem end addr is in a0 */ + move.l %d0, %sp /* Set up initial stack ptr */ + move.l %d0, _ramend /* Set end ram addr */ + + /* + * Enable CPU internal cache. + */ + move.l #0x01000000, %d0 /* Invalidate cache cmd */ + movec %d0, %CACR /* Invalidate cache */ + move.l #0x80000100, %d0 /* Setup cache mask */ + movec %d0, %CACR /* Enable cache */ + + /* + * Move ROM filesystem above bss :-) + */ + lea.l _sbss, %a0 /* Get start of bss */ + lea.l _ebss, %a1 /* Set up destination */ + move.l %a0, %a2 /* Copy of bss start */ + + move.l 8(%a0), %d0 /* Get size of ROMFS */ + addq.l #8, %d0 /* Allow for rounding */ + and.l #0xfffffffc, %d0 /* Whole words */ + + add.l %d0, %a0 /* Copy from end */ + add.l %d0, %a1 /* Copy from end */ + move.l %a1, _ramstart /* Set start of ram */ + +_copy_romfs: + move.l -(%a0), %d0 /* Copy dword */ + move.l %d0, -(%a1) + cmp.l %a0, %a2 /* Check if at end */ + bne _copy_romfs + + /* + * Zero out the bss region. + */ + lea.l _sbss, %a0 /* Get start of bss */ + lea.l _ebss, %a1 /* Get end of bss */ + clr.l %d0 /* Set value */ +_clear_bss: + move.l %d0, (%a0)+ /* Clear each word */ + cmp.l %a0, %a1 /* Check if at end */ + bne _clear_bss + + /* + * Load the current thread pointer and stack. + */ + lea init_thread_union, %a0 + lea 0x2000(%a0), %sp + + /* + * Assember start up done, start code proper. + */ + jsr start_kernel /* Start Linux kernel */ + +_exit: + jmp _exit /* Should never get here */ + +/*****************************************************************************/ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/5272/MOTOROLA/ram.ld linux.2.5.45-ac1/arch/m68knommu/platform/5272/MOTOROLA/ram.ld --- linux.2.5.45/arch/m68knommu/platform/5272/MOTOROLA/ram.ld 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/5272/MOTOROLA/ram.ld 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,76 @@ + +MEMORY { + ram : ORIGIN = 0x20000, LENGTH = 0x3e0000 +} + +jiffies = jiffies_64 + 4; + +SECTIONS { + + .text : { + _stext = . ; + *(.text) + *(.exit.text) + *(.text.lock) + *(.exitcall.exit) + *(.rodata) + *(.modinfo) + . = ALIGN(0x4) ; + *(.kstrtab) + . = ALIGN(16); /* Exception table */ + __start___ex_table = .; + *(__ex_table) + __stop___ex_table = .; + + __start___ksymtab = .; /* Kernel symbol table */ + *(__ksymtab) + __stop___ksymtab = .; + . = ALIGN(4) ; + _etext = . ; + } > ram + + .data BLOCK(0x4) : { + . = ALIGN(4); + _sdata = . ; + __data_start = . ; + *(.data) + *(.data.exit) + . = ALIGN(8192) ; + *(.data.init_task) + . = ALIGN(8192) ; + _edata = . ; + } > ram + + .init BLOCK(4096) : { + . = ALIGN(4096); + __init_begin = .; + *(.init.text) + *(.init.data) + . = ALIGN(16); + __setup_start = .; + *(.init.setup) + __setup_end = .; + __initcall_start = .; + *(.initcall1.init) + *(.initcall2.init) + *(.initcall3.init) + *(.initcall4.init) + *(.initcall5.init) + *(.initcall6.init) + *(.initcall7.init) + __initcall_end = .; + . = ALIGN(4); + __init_end = .; + } > ram + + .bss BLOCK(0x4) : { + . = ALIGN(4); + _sbss = . ; + *(.bss) + *(COMMON) + . = ALIGN(4) ; + _ebss = . ; + _end = . ; + } > ram +} + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/5272/NETtel/crt0_ram.S linux.2.5.45-ac1/arch/m68knommu/platform/5272/NETtel/crt0_ram.S --- linux.2.5.45/arch/m68knommu/platform/5272/NETtel/crt0_ram.S 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/5272/NETtel/crt0_ram.S 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,188 @@ +/*****************************************************************************/ + +/* + * crt0_ram.S -- startup code for MCF5307 ColdFire based NETtel. + * + * (C) Copyright 1999-2002, Greg Ungerer (gerg@snapgear.com). + * Copyright (C) 2000 Lineo Inc. (www.lineo.com) + * + * 1999/02/24 Modified for the 5307 processor David W. Miller + */ + +/*****************************************************************************/ + +#include "linux/autoconf.h" +#include "asm/coldfire.h" +#include "asm/mcfsim.h" +#include "asm/nettel.h" + +/*****************************************************************************/ + +/* + * Lineo NETtel board memory setup. + */ +#define MEM_BASE 0x00000000 /* Memory base at address 0 */ +#define VBR_BASE MEM_BASE /* Vector address */ + +#if defined(CONFIG_RAM16MB) +#define MEM_SIZE 0x01000000 /* Memory size 16Mb */ +#elif defined(CONFIG_RAM8MB) +#define MEM_SIZE 0x00800000 /* Memory size 8Mb */ +#else +#define MEM_SIZE 0x00400000 /* Memory size 4Mb */ +#endif + +/*****************************************************************************/ + +.global _start +.global _rambase +.global _ramvec +.global _ramstart +.global _ramend + +/*****************************************************************************/ + +.data + +/* + * Set up the usable of RAM stuff. Size of RAM is determined then + * an initial stack set up at the end. + */ +_rambase: +.long 0 +_ramvec: +.long 0 +_ramstart: +.long 0 +_ramend: +.long 0 + +/*****************************************************************************/ + +/* + * The NETtel platform has some funky LEDs! + */ +.global ppdata +ppdata: +.short 0x0000 + +.global ledbank +ledbank: +.byte 0xff + +/*****************************************************************************/ + +.text + +/* + * This is the codes first entry point. This is where it all + * begins... + */ + +_start: + nop /* Filler */ + move.w #0x2700, %sr /* No interrupts */ + + /* + * Setup VBR here, otherwise buserror remap will not work. + * if dBug was active before (on my SBC with dBug 1.1 of Dec 16 1996) + * + * bkr@cut.de 19990306 + * + * Note: this is because dBUG points VBR to ROM, making vectors read + * only, so the bus trap can't be changed. (RS) + */ + move.l #VBR_BASE, %a7 /* Note VBR can't be read */ + movec %a7, %VBR + move.l %a7, _ramvec /* Set up vector addr */ + move.l %a7, _rambase /* Set up base RAM addr */ + + + /* + * Determine size of RAM, then set up initial stack. + */ + move.l #MEM_SIZE, %a0 + + move.l %a0, %d0 /* Mem end addr is in a0 */ + move.l %d0, %sp /* Set up initial stack ptr */ + move.l %d0, _ramend /* Set end ram addr */ + + /* + * Enable CPU internal cache. + */ + move.l #0x01000000, %d0 /* Invalidate cache cmd */ + movec %d0, %CACR /* Invalidate cache */ + move.l #0x80000100, %d0 /* Setup cache mask */ + movec %d0, %CACR /* Enable cache */ + nop + +#ifdef CONFIG_ROMFS_FROM_ROM + /* + * check for an in RAM romfs + */ + lea.l _sbss, %a0 /* Get start of bss */ + mov.l (%a0), %d0 + cmp.l #0x2d726f6d, %d0 /* check for "-rom" */ + bne use_xip_romfs + add.l #4, %a0 + mov.l (%a0), %d0 + cmp.l #0x3166732d, %d0 /* check for "1fs-" */ + bne use_xip_romfs +#endif + + /* + * Move ROM filesystem above bss :-) + */ + lea.l _sbss, %a0 /* Get start of bss */ + lea.l _ebss, %a1 /* Set up destination */ + move.l %a0, %a2 /* Copy of bss start */ + + move.l 8(%a0), %d0 /* Get size of ROMFS */ + addq.l #8, %d0 /* Allow for rounding */ + and.l #0xfffffffc, %d0 /* Whole words */ + + add.l %d0, %a0 /* Copy from end */ + add.l %d0, %a1 /* Copy from end */ + move.l %a1, _ramstart /* Set start of ram */ + +_copy_romfs: + move.l -(%a0), %d0 /* Copy dword */ + move.l %d0, -(%a1) + cmp.l %a0, %a2 /* Check if at end */ + bne _copy_romfs + +#ifdef CONFIG_ROMFS_FROM_ROM + bra done_romfs + use_xip_romfs: + lea.l _ebss, %a1 /* Set up destination */ + mov.l #0, (%a1) /* make sure we don't use an old RAM version */ + move.l %a1, _ramstart /* Set start of ram */ + done_romfs: +#endif + + /* + * Zero out the bss region. + */ + lea.l _sbss, %a0 /* Get start of bss */ + lea.l _ebss, %a1 /* Get end of bss */ + clr.l %d0 /* Set value */ +_clear_bss: + move.l %d0, (%a0)+ /* Clear each word */ + cmp.l %a0, %a1 /* Check if at end */ + bne _clear_bss + + /* + * load the current task pointer and stack + */ + lea init_thread_union, %a0 + lea 0x2000(%a0), %sp + + /* + * Assember start up done, start code proper. + */ + jsr start_kernel /* Start Linux kernel */ + +_exit: + jmp _exit /* Should never get here */ + +/*****************************************************************************/ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/5272/NETtel/ram.ld linux.2.5.45-ac1/arch/m68knommu/platform/5272/NETtel/ram.ld --- linux.2.5.45/arch/m68knommu/platform/5272/NETtel/ram.ld 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/5272/NETtel/ram.ld 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,76 @@ + +MEMORY { + ram : ORIGIN = 0x400, LENGTH = 0x400000 +} + +jiffies = jiffies_64 + 4; + +SECTIONS { + + .text : { + _stext = . ; + *(.text) + *(.exit.text) + *(.text.lock) + *(.exitcall.exit) + *(.rodata) + *(.modinfo) + . = ALIGN(0x4) ; + *(.kstrtab) + . = ALIGN(16); /* Exception table */ + __start___ex_table = .; + *(__ex_table) + __stop___ex_table = .; + + __start___ksymtab = .; /* Kernel symbol table */ + *(__ksymtab) + __stop___ksymtab = .; + . = ALIGN(4) ; + _etext = . ; + } > ram + + .data BLOCK(0x4) : { + . = ALIGN(4); + _sdata = . ; + __data_start = . ; + *(.data) + *(.data.exit) + . = ALIGN(8192) ; + *(.data.init_task) + . = ALIGN(8192) ; + _edata = . ; + } > ram + + .init BLOCK(4096) : { + . = ALIGN(4096); + __init_begin = .; + *(.init.text) + *(.init.data) + . = ALIGN(16); + __setup_start = .; + *(.init.setup) + __setup_end = .; + __initcall_start = .; + *(.initcall1.init) + *(.initcall2.init) + *(.initcall3.init) + *(.initcall4.init) + *(.initcall5.init) + *(.initcall6.init) + *(.initcall7.init) + __initcall_end = .; + . = ALIGN(4); + __init_end = .; + } > ram + + .bss BLOCK(0x4) : { + . = ALIGN(4); + _sbss = . ; + *(.bss) + *(COMMON) + . = ALIGN(4) ; + _ebss = . ; + _end = . ; + } > ram +} + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/5307/ARNEWSH/crt0_ram.S linux.2.5.45-ac1/arch/m68knommu/platform/5307/ARNEWSH/crt0_ram.S --- linux.2.5.45/arch/m68knommu/platform/5307/ARNEWSH/crt0_ram.S 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/5307/ARNEWSH/crt0_ram.S 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,159 @@ +/*****************************************************************************/ + +/* + * crt0_ram.S -- startup code for MCF5307 ColdFire Arnewsh board. + * + * (C) Copyright 1999-2002, Greg Ungerer (gerg@snapgear.com). + * Copyright (C) 2000 Lineo Inc. (www.lineo.com) + * + * 1999/02/24 Modified for the 5307 processor David W. Miller + */ + +/*****************************************************************************/ + +#include "linux/autoconf.h" +#include "asm/coldfire.h" +#include "asm/mcfsim.h" +#include "asm/nettel.h" + +/*****************************************************************************/ + +/* + * SnapGear/NETtel board memory setup. + */ +#define MEM_BASE 0x00000000 /* Memory base at address 0 */ +#define MEM_SIZE 0x00800000 /* Memory size 8Mb */ +#define VBR_BASE MEM_BASE /* Vector address */ + +/*****************************************************************************/ + +.global _start +.global _rambase +.global _ramvec +.global _ramstart +.global _ramend + +/*****************************************************************************/ + +.data + +/* + * Set up the usable of RAM stuff. Size of RAM is determined then + * an initial stack set up at the end. + */ +_rambase: +.long 0 +_ramvec: +.long 0 +_ramstart: +.long 0 +_ramend: +.long 0 + +/*****************************************************************************/ + +.text + +/* + * This is the codes first entry point. This is where it all + * begins... + */ + +_start: + nop /* Filler */ + move.w #0x2700, %sr /* No interrupts */ + + /* + * Setup VBR here, otherwise buserror remap will not work. + * if dBug was active before (on my SBC with dBug 1.1 of Dec 16 1996) + * + * bkr@cut.de 19990306 + * + * Note: this is because dBUG points VBR to ROM, making vectors read + * only, so the bus trap can't be changed. (RS) + */ + move.l #VBR_BASE, %a7 /* Note VBR can't be read */ + movec %a7, %VBR + move.l %a7, _ramvec /* Set up vector addr */ + move.l %a7, _rambase /* Set up base RAM addr */ + + + /* + * Determine size of RAM, then set up initial stack. + */ + move.l #MEM_SIZE, %a0 + + move.l %a0, %d0 /* Mem end addr is in a0 */ + move.l %d0, %sp /* Set up initial stack ptr */ + move.l %d0, _ramend /* Set end ram addr */ + + /* make region ROM cachable (turn off for flash programming?) */ + /* 0xff000000 - 0xffffffff */ +#ifdef DEBUGGER_COMPATIBLE_CACHE + movl #(0xff< ram + + .data BLOCK(0x4) : { + _sdata = . ; + __data_start = . ; + *(.data) + *(.data.exit) + . = ALIGN(0x2000) ; + *(.data.init_task) + . = ALIGN(0x2000) ; + _edata = . ; + } > ram + + .init BLOCK(4096) : { + __init_begin = .; + *(.init.text) + *(.init.data) + . = ALIGN(16); + __setup_start = .; + *(.init.setup) + __setup_end = .; + __initcall_start = .; + *(.initcall1.init) + *(.initcall2.init) + *(.initcall3.init) + *(.initcall4.init) + *(.initcall5.init) + *(.initcall6.init) + *(.initcall7.init) + __initcall_end = .; + . = ALIGN(4) ; + __init_end = .; + } > ram + + .bss BLOCK(0x4) : { + _sbss = . ; + *(.bss) + *(COMMON) + . = ALIGN(4) ; + _ebss = . ; + _end = . ; + } > ram +} + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/5307/CLEOPATRA/crt0_ram.S linux.2.5.45-ac1/arch/m68knommu/platform/5307/CLEOPATRA/crt0_ram.S --- linux.2.5.45/arch/m68knommu/platform/5307/CLEOPATRA/crt0_ram.S 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/5307/CLEOPATRA/crt0_ram.S 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,176 @@ +/*****************************************************************************/ + +/* + * crt0_ram.S -- startup code for Feith CLEOPATRA board. + * + * (C) Copyright 2001, Roman Wagner. + * + * 1999/02/24 Modified for the 5307 processor David W. Miller + */ + +/*****************************************************************************/ + +#include "linux/autoconf.h" +#include "asm/coldfire.h" +#include "asm/mcfsim.h" + +/*****************************************************************************/ + +/* + * Feith CLEOPATRA board, chip select and memory setup. +*/ + +#define MEM_BASE 0x00000000 /* Memory base at address 0 */ +#define VBR_BASE MEM_BASE /* Vector address */ + +#if defined(CONFIG_RAM16MB) +#define MEM_SIZE 0x01000000 /* Memory size 16Mb */ +#else +#define MEM_SIZE 0x00800000 /* Memory size 8Mb */ +#endif + +/*****************************************************************************/ + +.global _start +.global _rambase +.global _ramvec +.global _ramstart +.global _ramend + +/*****************************************************************************/ + +.data + +/* + * Set up the usable of RAM stuff. Size of RAM is determined then + * an initial stack set up at the end. + */ +_rambase: +.long 0 +_ramvec: +.long 0 +_ramstart: +.long 0 +_ramend: +.long 0 + +/*****************************************************************************/ + +.text + +/* + * This is the codes first entry point. This is where it all + * begins... + */ + +_start: + nop /* Filler */ + move.w #0x2700, %sr /* No interrupts */ + + + /* + * Setup VBR here, otherwise buserror remap will not work. + * if dBug was active before (on my SBC with dBug 1.1 of Dec 16 1996) + * + * bkr@cut.de 19990306 + * + * Note: this is because dBUG points VBR to ROM, making vectors read + * only, so the bus trap can't be changed. (RS) + */ + move.l #VBR_BASE, %a7 /* Note VBR can't be read */ + movec %a7, %VBR + move.l %a7, _ramvec /* Set up vector addr */ + move.l %a7, _rambase /* Set up base RAM addr */ + + + /* + * Determine size of RAM, then set up initial stack. + */ +/* + * The current version of the 5307 processor + * SWT does not work. Probing invalid addresses + * will hang the system. + * + * For now, set the memory size to 8 meg + */ + move.l #MEM_SIZE, %a0 + + move.l %a0, %d0 /* Mem end addr is in a0 */ + move.l %d0, %sp /* Set up initial stack ptr */ + move.l %d0, _ramend /* Set end ram addr */ + + + /* now fire off the cache, remember to invalidate it first */ + movl #0,%d0 + movc %d0,%CACR + nop + movc %d0,%CACR /* cache is off */ + + movl #CACR_CINVA,%d0 /* invalidate whole cache */ + movc %d0,%CACR + nop + movc %d0,%CACR + nop + + /* make region ROM cachable (turn off for flash programming?) */ + /* 0xff000000 - 0xffffffff */ + movl #(0xff< ram + + .data BLOCK(0x4) : { + _sdata = . ; + __data_start = . ; + *(.data) + *(.data.exit) + . = ALIGN(0x2000) ; + *(.data.init_task) + . = ALIGN(0x2000) ; + _edata = . ; + } > ram + + .init BLOCK(4096) : { + __init_begin = .; + *(.init.text) + *(.init.data) + . = ALIGN(16); + __setup_start = .; + *(.init.setup) + __setup_end = .; + __initcall_start = .; + *(.initcall1.init) + *(.initcall2.init) + *(.initcall3.init) + *(.initcall4.init) + *(.initcall5.init) + *(.initcall6.init) + *(.initcall7.init) + __initcall_end = . ; + . = ALIGN(4); + __init_end = .; + } > ram + + .bss BLOCK(0x4) : { + _sbss = . ; + *(.bss) + *(COMMON) + . = ALIGN(4) ; + _ebss = . ; + _end = . ; + } > ram +} + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/5307/config.c linux.2.5.45-ac1/arch/m68knommu/platform/5307/config.c --- linux.2.5.45/arch/m68knommu/platform/5307/config.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/5307/config.c 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,337 @@ +/***************************************************************************/ + +/* + * linux/arch/m68knommu/platform/5307/config.c + * + * Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com) + * Copyright (C) 2000, Lineo (www.lineo.com) + */ + +/***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(CONFIG_eLIA) +#include +#endif + +#include + +/***************************************************************************/ + +void reset_setupbutton(void); +void coldfire_profile_init(void); + +/***************************************************************************/ + +/* + * DMA channel base address table. + */ +unsigned int dma_base_addr[MAX_M68K_DMA_CHANNELS] = { + MCF_MBAR + MCFDMA_BASE0, + MCF_MBAR + MCFDMA_BASE1, + MCF_MBAR + MCFDMA_BASE2, + MCF_MBAR + MCFDMA_BASE3, +}; + +unsigned int dma_device_address[MAX_M68K_DMA_CHANNELS]; + +/***************************************************************************/ + +void coldfire_tick(void) +{ + volatile unsigned char *timerp; + + /* Reset the ColdFire timer */ + timerp = (volatile unsigned char *) (MCF_MBAR + MCFTIMER_BASE1); + timerp[MCFTIMER_TER] = MCFTIMER_TER_CAP | MCFTIMER_TER_REF; +} + +/***************************************************************************/ + +void coldfire_timer_init(void (*handler)(int, void *, struct pt_regs *)) +{ + volatile unsigned short *timerp; + volatile unsigned char *icrp; + + /* Set up TIMER 1 as poll clock */ + timerp = (volatile unsigned short *) (MCF_MBAR + MCFTIMER_BASE1); + timerp[MCFTIMER_TMR] = MCFTIMER_TMR_DISABLE; + + timerp[MCFTIMER_TRR] = (unsigned short) ((MCF_CLK / 16) / HZ); + timerp[MCFTIMER_TMR] = MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 | + MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE; + + icrp = (volatile unsigned char *) (MCF_MBAR + MCFSIM_TIMER1ICR); + +#if defined(CONFIG_NETtel) || defined(CONFIG_eLIA) || \ + defined(CONFIG_DISKtel) || defined(CONFIG_SECUREEDGEMP3) || \ + defined(CONFIG_CLEOPATRA) + *icrp = MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI3; + request_irq(30, handler, SA_INTERRUPT, "ColdFire Timer", NULL); +#else + *icrp = MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL5 | MCFSIM_ICR_PRI3; + request_irq(29, handler, SA_INTERRUPT, "ColdFire Timer", NULL); +#endif + +#if defined(CONFIG_NETtel) || defined(CONFIG_eLIA) || \ + defined(CONFIG_DISKtel) || defined(CONFIG_SECUREEDGEMP3) + /* This is not really the right place to do this... */ + reset_setupbutton(); +#endif +#ifdef CONFIG_HIGHPROFILE + coldfire_profile_init(); +#endif + mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_TIMER1); +} + +/***************************************************************************/ +#ifdef CONFIG_HIGHPROFILE +/***************************************************************************/ + +#define PROFILEHZ 1013 + +/* + * Use the other timer to provide high accuracy profiling info. + */ + +void coldfire_profile_tick(int irq, void *dummy, struct pt_regs *regs) +{ + volatile unsigned char *timerp; + + /* Reset the ColdFire timer2 */ + timerp = (volatile unsigned char *) (MCF_MBAR + MCFTIMER_BASE2); + timerp[MCFTIMER_TER] = MCFTIMER_TER_CAP | MCFTIMER_TER_REF; + + if (!user_mode(regs)) { + if (prof_buffer && current->pid) { + extern int _stext; + unsigned long ip = instruction_pointer(regs); + ip -= (unsigned long) &_stext; + ip >>= prof_shift; + if (ip < prof_len) + prof_buffer[ip]++; + } + } +} + +void coldfire_profile_init(void) +{ + volatile unsigned short *timerp; + volatile unsigned char *icrp; + + printk("PROFILE: lodging timer2=%d as profile timer\n", PROFILEHZ); + + /* Set up TIMER 2 as poll clock */ + timerp = (volatile unsigned short *) (MCF_MBAR + MCFTIMER_BASE2); + timerp[MCFTIMER_TMR] = MCFTIMER_TMR_DISABLE; + + timerp[MCFTIMER_TRR] = (unsigned short) ((MCF_CLK / 16) / PROFILEHZ); + timerp[MCFTIMER_TMR] = MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 | + MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE; + + icrp = (volatile unsigned char *) (MCF_MBAR + MCFSIM_TIMER2ICR); + + *icrp = MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL7 | MCFSIM_ICR_PRI3; + request_irq(31, coldfire_profile_tick, (SA_INTERRUPT | IRQ_FLG_FAST), + "Profile Timer", NULL); + mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_TIMER2); +} + +/***************************************************************************/ +#endif /* CONFIG_HIGHPROFILE */ +/***************************************************************************/ + +/* + * Program the vector to be an auto-vectored. + */ + +void mcf_autovector(unsigned int vec) +{ + volatile unsigned char *mbar; + + if ((vec >= 25) && (vec <= 31)) { + mbar = (volatile unsigned char *) MCF_MBAR; + vec = 0x1 << (vec - 24); + *(mbar + MCFSIM_AVR) |= vec; + mcf_setimr(mcf_getimr() & ~vec); + } +} + +/***************************************************************************/ + +extern e_vector *_ramvec; + +void set_evector(int vecnum, void (*handler)(void)) +{ + if (vecnum >= 0 && vecnum <= 255) + _ramvec[vecnum] = handler; +} + +/***************************************************************************/ + +/* assembler routines */ +asmlinkage void buserr(void); +asmlinkage void trap(void); +asmlinkage void system_call(void); +asmlinkage void inthandler(void); + +#ifdef TRAP_DBG_INTERRUPT +asmlinkage void dbginterrupt(void); +#endif + +void __init coldfire_trap_init(void) +{ + int i; + +#ifndef ENABLE_dBUG + mcf_setimr(MCFSIM_IMR_MASKALL); +#endif + + /* + * There is a common trap handler and common interrupt + * handler that handle almost every vector. We treat + * the system call and bus error special, they get their + * own first level handlers. + */ +#ifndef ENABLE_dBUG + for (i = 3; (i <= 23); i++) + _ramvec[i] = trap; + for (i = 33; (i <= 63); i++) + _ramvec[i] = trap; +#endif +#ifdef TRAP_DBG_INTERRUPT + _ramvec[12] = dbginterrupt; +#endif + + for (i = 24; (i <= 30); i++) + _ramvec[i] = inthandler; +#ifndef ENABLE_dBUG + _ramvec[31] = inthandler; // Disables the IRQ7 button +#endif + + for (i = 64; (i < 255); i++) + _ramvec[i] = inthandler; + _ramvec[255] = 0; + + _ramvec[2] = buserr; + _ramvec[32] = system_call; +#ifdef MCF_BDM_DISABLE + /* Disable the BDM clocking. This also turns off most of the rest of + * the BDM device. This is good for EMC reasons. This option is not + * incompatible with the memory protection option. + */ + wdebug(MCFDEBUG_CSR, MCFDEBUG_CSR_PSTCLK); +#endif + +} + +/***************************************************************************/ + +#if defined(CONFIG_NETtel) || defined(CONFIG_eLIA) || \ + defined(CONFIG_DISKtel) || defined(CONFIG_SECUREEDGEMP3) + +/* + * Routines to support the NETtel software reset button. + */ +void reset_button(int irq, void *dev_id, struct pt_regs *regs) +{ + extern void flash_eraseconfig(void); + static int inbutton = 0; + + /* + * IRQ7 is not maskable by the CPU core. It is possible + * that switch bounce mey get us back here before we have + * really serviced the interrupt. + */ + if (inbutton) + return; + inbutton = 1; + /* Disable interrupt at SIM - best we can do... */ + mcf_setimr(mcf_getimr() | MCFSIM_IMR_EINT7); + /* Try and de-bounce the switch a little... */ + udelay(10000); + + flash_eraseconfig(); + + /* Don't leave here 'till button is no longer pushed! */ + for (;;) { + if ((mcf_getipr() & MCFSIM_IMR_EINT7) == 0) + break; + } + + HARD_RESET_NOW(); + /* Should never get here... */ + + inbutton = 0; + /* Interrupt service done, enable it again */ + mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_EINT7); +} + +/***************************************************************************/ + +void reset_setupbutton(void) +{ + volatile unsigned char *mbar; + + mbar = (volatile unsigned char *) MCF_MBAR; + *(mbar + MCFSIM_AVR) |= MCFSIM_IMR_EINT7; + mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_EINT7); + request_irq(31, reset_button, (SA_INTERRUPT | IRQ_FLG_FAST), + "Reset Button", NULL); +} + +#endif /* CONFIG_NETtel || CONFIG_eLIA || CONFIG_DISKtel || CONFIG_SECUREEDGEMP3 */ + +/***************************************************************************/ + +void coldfire_reset(void) +{ + HARD_RESET_NOW(); +} + +/***************************************************************************/ + +void config_BSP(char *commandp, int size) +{ +#if defined(CONFIG_NETtel) || defined(CONFIG_eLIA) || \ + defined(CONFIG_DISKtel) || defined(CONFIG_SECUREEDGEMP3) + /* Copy command line from FLASH to local buffer... */ + memcpy(commandp, (char *) 0xf0004000, size); + commandp[size-1] = 0; +#else + memset(commandp, 0, size); +#endif /* CONFIG_NETtel || CONFIG_eLIA || CONFIG_DISKtel || CONFIG_SECUREEDGEMP3 */ + + mach_sched_init = coldfire_timer_init; + mach_tick = coldfire_tick; + mach_trap_init = coldfire_trap_init; + mach_reset = coldfire_reset; +} + +/***************************************************************************/ +#ifdef TRAP_DBG_INTERRUPT + +asmlinkage void dbginterrupt_c(struct frame *fp) +{ + extern void dump(struct pt_regs *fp); + printk("%s(%d): BUS ERROR TRAP\n", __FILE__, __LINE__); + dump((struct pt_regs *) fp); + asm("halt"); +} + +#endif +/***************************************************************************/ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/5307/entry.S linux.2.5.45-ac1/arch/m68knommu/platform/5307/entry.S --- linux.2.5.45/arch/m68knommu/platform/5307/entry.S 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/5307/entry.S 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,557 @@ +/* -*- mode: asm -*- + * + * linux/arch/m68knommu/platform/5307/entry.S + * + * Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com) + * Copyright (C) 1998 D. Jeff Dionne , + * Kenneth Albanowski , + * Copyright (C) 2000 Lineo Inc. (www.lineo.com) + * + * Based on: + * + * linux/arch/m68k/kernel/entry.S + * + * Copyright (C) 1991, 1992 Linus Torvalds + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file README.legal in the main directory of this archive + * for more details. + * + * Linux/m68k support by Hamish Macdonald + * + * 68060 fixes by Jesper Skov + * ColdFire support by Greg Ungerer (gerg@snapgear.com) + * 5307 fixes by David W. Miller + * linux 2.4 support David McCullough + */ + +/* + * entry.S contains the system-call and fault low-level handling routines. + * This also contains the timer-interrupt handler, as well as all interrupts + * and faults that can result in a task-switch. + * + * NOTE: This code handles signal-recognition, which happens every time + * after a timer-interrupt and after each system call. + * + * Stack layout in 'ret_from_exception': + * + * This allows access to the syscall arguments in registers d1-d5 + * + * 0(sp) - d1 + * 4(sp) - d2 + * 8(sp) - d3 + * C(sp) - d4 + * 10(sp) - d5 + * 14(sp) - a0 + * 18(sp) - a1 + * 1C(sp) - a2 + * 20(sp) - d0 + * 24(sp) - orig_d0 + * 28(sp) - stack adjustment + * 2C(sp) - format & vector } + * 2E(sp) - sr } different to m68k + * 30(sp) - pc } + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +LENOSYS = 38 + +/* the following macro is used when enabling interrupts */ +#define ALLOWINT 0xf8ff +#define MAX_NOINT_IPL 0 + + +LD0 = 0x20 +LORIG_D0 = 0x24 +LFORMATVEC = 0x2c +LSR = 0x2e +LPC = 0x30 + +/* + * This defines the normal kernel pt-regs layout. + * + * regs are a2-a6 and d6-d7 preserved by C code + * the kernel doesn't mess with usp unless it needs to + * + * This is made a little more tricky on the ColdFire. There is no + * separate kernel and user stack pointers. Need to artificially + * construct a usp in software... When doing this we need to disable + * interrupts, otherwise bad things could happen. + */ +#define SAVE_ALL \ + move #0x2700,%sr; /* disable intrs */ \ + btst #5,%sp@(2); /* from user? */ \ + bnes 6f; /* no, skip */ \ + movel %sp,sw_usp; /* save user sp */ \ + addql #8,sw_usp; /* remove exception */ \ + movel sw_ksp,%sp; /* kernel sp */ \ + subql #8,%sp; /* room for exception */\ + clrl %sp@-; /* stk_adj */ \ + movel %d0,%sp@-; /* orig d0 */ \ + movel %d0,%sp@-; /* d0 */ \ + subl #32,%sp; /* space for 8 regs */ \ + moveml %d1-%d5/%a0-%a2,%sp@; \ + movel sw_usp,%a0; /* get usp */ \ + moveml %a0@(-8),%d1-%d2; /* get exception */ \ + moveml %d1-%d2,%sp@(LFORMATVEC); /* copy exception */ \ + bra 7f; \ + 6: \ + clrl %sp@-; /* stk_adj */ \ + movel %d0,%sp@-; /* orig d0 */ \ + movel %d0,%sp@-; /* d0 */ \ + subl #32,%sp; /* space for 7 regs */ \ + moveml %d1-%d5/%a0-%a2,%sp@; \ + 7: + +#define RESTORE_ALL \ + btst #5,%sp@(LSR); /* going user? */ \ + bnes 8f; /* no, skip */ \ + move #0x2700,%sr; /* disable intrs */ \ + movel sw_usp,%a0; /* get usp */ \ + moveml %sp@(LFORMATVEC),%d1-%d2; /* copy exception */ \ + moveml %d1-%d2,%a0@(-8); \ + moveml %sp@,%d1-%d5/%a0-%a2; \ + addl #32,%sp; /* space for 8 regs */ \ + movel %sp@+,%d0; \ + addql #4,%sp; /* orig d0 */ \ + addl %sp@+,%sp; /* stk adj */ \ + addql #8,%sp; /* remove exception */ \ + movel %sp,sw_ksp; /* save ksp */ \ + subql #8,sw_usp; /* set exception */ \ + movel sw_usp,%sp; /* restore usp */ \ + rte; \ + 8: \ + moveml %sp@,%d1-%d5/%a0-%a2; \ + addl #32,%sp; /* space for 8 regs */ \ + movel %sp@+,%d0; \ + addql #4,%sp; /* orig d0 */ \ + addl %sp@+,%sp; /* stk adj */ \ + rte + +/* + * Quick exception save, use current stack only. + */ +#define SAVE_LOCAL \ + move #0x2700,%sr; /* disable intrs */ \ + clrl %sp@-; /* stk_adj */ \ + movel %d0,%sp@-; /* orig d0 */ \ + movel %d0,%sp@-; /* d0 */ \ + subl #32,%sp; /* space for 8 regs */ \ + moveml %d1-%d5/%a0-%a2,%sp@; + +#define RESTORE_LOCAL \ + moveml %sp@,%d1-%d5/%a0-%a2; \ + addl #32,%sp; /* space for 8 regs */ \ + movel %sp@+,%d0; \ + addql #4,%sp; /* orig d0 */ \ + addl %sp@+,%sp; /* stk adj */ \ + rte + + +#define SWITCH_STACK_SIZE (6*4+4) /* includes return address */ + +#define SAVE_SWITCH_STACK \ + subl #24,%sp; /* 6 regs */ \ + moveml %a3-%a6/%d6-%d7,%sp@ + +#define RESTORE_SWITCH_STACK \ + moveml %sp@,%a3-%a6/%d6-%d7; \ + addl #24,%sp /* 6 regs */ + +/* + * Software copy of the user and kernel stack pointers... Ugh... + * Need these to get around ColdFire not having separate kernel + * and user stack pointers. + */ +.globl sw_usp +.globl sw_ksp + +.data + +sw_ksp: +.long 0 + +sw_usp: +.long 0 + +.text + + +.globl buserr +.globl trap +.globl system_call +.globl resume, ret_from_exception +.globl ret_from_signal +.globl sys_call_table +.globl sys_fork, sys_clone, sys_vfork +.globl ret_from_interrupt +.globl inthandler +.globl fasthandler + +#ifdef TRAP_DBG_INTERRUPT +.globl dbginterrupt +#endif + +/*--------------------------------------------------------------------------*/ + +.text + +ENTRY(buserr) + SAVE_ALL + moveq #-1,%d0 + movel %d0,%sp@(LORIG_D0) | a -1 in the ORIG_D0 field + | signifies that the stack frame + | is NOT for syscall + + movel %sp,%sp@- | stack frame pointer argument + jsr buserr_c + addql #4,%sp + jra ret_from_exception + + +#ifdef TRAP_DBG_INTERRUPT +ENTRY(dbginterrupt) + SAVE_ALL + moveq #-1,%d0 + movel %d0,%sp@(LORIG_D0) | a -1 in the ORIG_D0 field + | signifies that the stack frame + | is NOT for syscall + + movel %sp,%sp@- | stack frame pointer argument + jsr dbginterrupt_c + addql #4,%sp + jra ret_from_exception +#endif + + +ENTRY(reschedule) + | save top of frame + pea %sp@ + jbsr set_esp0 + addql #4,%sp + + pea ret_from_exception + jmp schedule + + | After a fork we jump here directly from resume, + | so that %d1 contains the previous task + | Theoretically only needed on SMP, but lets watch + | what happens in schedule_tail() in future... +ENTRY(ret_from_fork) +#ifdef CONFIG_SMP + movel %d1,%sp@- + jsr schedule_tail + addql #4,%sp +#endif + jra ret_from_exception + +ENTRY(system_call) + SAVE_ALL + move #0x2000,%sr; | enable intrs again + + movel #-LENOSYS,%d2 + movel %d2,LD0(%sp) | default return value in d0 + | original D0 is in orig_d0 + movel %d0,%d2 + + | save top of frame + pea %sp@ + jbsr set_esp0 + addql #4,%sp + + cmpl #NR_syscalls,%d2 + jcc ret_from_exception + lea sys_call_table,%a0 + lsll #2,%d2 | movel %a0@(%d2:l:4),%d3 + movel %a0@(%d2),%d3 + jeq ret_from_exception + lsrl #2,%d2 + + movel %sp,%d2 | get thread_info pointer + andl #0xffffe000,%d2 | at start of 8k kernel stack + movel %d2,%a0 + btst #TIF_SYSCALL_TRACE,%a0@(TI_FLAGS) + bnes 1f + + movel %d3,%a0 + jbsr %a0@ + movel %d0,%sp@(LD0) | save the return value + jra ret_from_exception +1: + subql #4,%sp + SAVE_SWITCH_STACK + jbsr syscall_trace + RESTORE_SWITCH_STACK + addql #4,%sp + movel %d3,%a0 + jbsr %a0@ + movel %d0,%sp@(LD0) | save the return value + subql #4,%sp | dummy return address + SAVE_SWITCH_STACK + jbsr syscall_trace + +ret_from_signal: + RESTORE_SWITCH_STACK + addql #4,%sp + +ret_from_exception: + btst #5,%sp@(LSR) | check if returning to kernel + jeq Luser_return | if so, skip resched, signals + +Lkernel_return: + moveml %sp@,%d1-%d5/%a0-%a2 + addl #32,%sp | space for 8 regs + movel %sp@+,%d0 + addql #4,%sp | orig d0 + addl %sp@+,%sp | stk adj + rte + +Luser_return: + movel %sp,%d1 | get thread_info pointer + andl #0xffffe000,%d1 | at base of 8k kernel stack + movel %d1,%a0 + movel %a0@(TI_FLAGS),%d1 | get thread_info->flags + andl #_TIF_WORK_MASK,%d1 + jne Lwork_to_do | still work to do + +Lreturn: + move #0x2700,%sr | disable intrs + movel sw_usp,%a0 | get usp + moveml %sp@(LFORMATVEC),%d1-%d2 | copy exception + moveml %d1-%d2,%a0@(-8) + bclr #5,%a0@(-8) | clear format byte, bit 5 to make + | stack appear modulo 4 which it WILL + | be when we do the rte because it was + | generated in setup_frame + bclr #4,%a0@(-8) | clear format byte, bit 4 to make + | stack appear modulo 4 which it WILL + | be when we do the rte because it was + | generated in setup_frame + moveml %sp@,%d1-%d5/%a0-%a2 + addl #32,%sp | space for 8 regs + movel %sp@+,%d0 + addql #4,%sp | orig d0 + addl %sp@+,%sp | stk adj + addql #8,%sp | remove exception + movel %sp,sw_ksp | save ksp + movel sw_usp,%sp | restore usp + subql #8,%sp | set exception + rte + +Lwork_to_do: + movel %a0@(TI_FLAGS),%d1 | get thread_info->flags + btst #TIF_NEED_RESCHED,%d1 + jne reschedule + + /* GERG: do we need something here for TRACEing?? */ + +Lsignal_return: + subql #4,%sp | dummy return address + SAVE_SWITCH_STACK + pea %sp@(SWITCH_STACK_SIZE) + clr %d1 + movel %d1,%sp@- + jsr do_signal + addql #8,%sp + RESTORE_SWITCH_STACK + addql #4,%sp + jmp Lreturn + +/*--------------------------------------------------------------------------*/ + +/* + * Common ColdFire trap handler. Most traps come through here first. + */ +ENTRY(trap) + SAVE_ALL + moveq #-1,%d0 + movel %d0,%sp@(LORIG_D0) | a -1 in the ORIG_D0 field + | signifies that the stack frame + | is NOT for syscall + movel %sp,%sp@- | stack frame pointer argument + jsr trap_c + addql #4,%sp + jra ret_from_exception + +/* + * This is the generic interrupt handler (for all hardware interrupt + * sources). It figures out the vector number and calls the appropriate + * interrupt service routine directly. + */ +ENTRY(inthandler) + SAVE_ALL + moveq #-1,%d0 + movel %d0,%sp@(LORIG_D0) | a -1 in the ORIG_D0 field + | signifies that the stack frame + | is NOT for syscall + addql #1,local_irq_count + | put exception # in d0 + movew %sp@(LFORMATVEC),%d0 + andl #0x03fc,%d0 | mask out vector only + + movel mach_kstat_irqs,%a0 + | get addr of kstat struct + addql #1,%a0@(%d0) | incr irq intr count + + lsrl #2,%d0 | calculate real vector # + movel %d0,%d1 | calculate array offset + lsll #4,%d1 + lea irq_list,%a0 + addl %d1,%a0 | pointer to array struct + + movel %sp,%sp@- | push regs arg onto stack + movel %a0@(8),%sp@- | push devid arg + movel %d0,%sp@- | push vector # on stack + + movel %a0@,%a0 | get function to call + jbsr %a0@ | call vector handler + addl #12,%sp | pop parameters off stack + + bra ret_from_interrupt | this was fallthrough + + +/* + * This is the fast interrupt handler (for certain hardware interrupt + * sources). Unlike the normal interrupt handler it just uses the + * current stack (doesn't care if it is user or kernel). It also + * doesn't bother doing the bottom half handlers. + */ +ENTRY(fasthandler) + SAVE_LOCAL + + movew %sp@(LFORMATVEC),%d0 + andl #0x03fc,%d0 | mask out vector only + + movel mach_kstat_irqs,%a0 + | get addr of kstat struct + addql #1,%a0@(%d0) | incr irq intr count + + movel %sp,%sp@- | push regs arg onto stack + clrl %d1 + movel %d1,%sp@- | push devid arg + lsrl #2,%d0 | calculate real vector # + movel %d0,%sp@- | push vector # on stack + + lsll #4,%d0 | adjust for array offset + lea irq_list,%a0 + movel %a0@(%d0),%a0 | get function to call + jbsr %a0@ | call vector handler + addl #12,%sp | pop parameters off stack + + RESTORE_LOCAL + +/*--------------------------------------------------------------------------*/ + +ENTRY(ret_from_interrupt) + subql #1,local_irq_count + jeq 2f +1: + RESTORE_ALL +2: + moveb %sp@(LSR),%d0 + andl #0x7,%d0 +#if MAX_NOINT_IPL > 0 + cmpiw #MAX_NOINT_IPL,%d0 +#endif + jhi 1b + + /* check if we need to do software interrupts */ + movel irq_stat+CPUSTAT_SOFTIRQ_PENDING,%d0 + jeq ret_from_exception + + pea ret_from_exception + jmp do_softirq + +ENTRY(sys_fork) + SAVE_SWITCH_STACK + pea %sp@(SWITCH_STACK_SIZE) + jbsr m68k_fork + addql #4,%sp + RESTORE_SWITCH_STACK + rts + +ENTRY(sys_vfork) + SAVE_SWITCH_STACK + pea %sp@(SWITCH_STACK_SIZE) + jbsr m68k_vfork + addql #4,%sp + RESTORE_SWITCH_STACK + rts + +ENTRY(sys_clone) + SAVE_SWITCH_STACK + pea %sp@(SWITCH_STACK_SIZE) + jbsr m68k_clone + addql #4,%sp + RESTORE_SWITCH_STACK + rts + +ENTRY(sys_sigsuspend) + SAVE_SWITCH_STACK + pea %sp@(SWITCH_STACK_SIZE) + jbsr do_sigsuspend + addql #4,%sp + RESTORE_SWITCH_STACK + rts + +ENTRY(sys_rt_sigsuspend) + SAVE_SWITCH_STACK + pea %sp@(SWITCH_STACK_SIZE) + jbsr do_rt_sigsuspend + addql #4,%sp + RESTORE_SWITCH_STACK + rts + +ENTRY(sys_sigreturn) + SAVE_SWITCH_STACK + jbsr do_sigreturn + RESTORE_SWITCH_STACK + rts + +ENTRY(sys_rt_sigreturn) + SAVE_SWITCH_STACK + jbsr do_rt_sigreturn + RESTORE_SWITCH_STACK + rts + +/*--------------------------------------------------------------------------*/ + +/* + * Beware - when entering resume, prev (the current task) is + * in a0, next (the new task) is in a1,so don't change these + * registers until their contents are no longer needed. + */ +ENTRY(resume) + + movel %a0, %d1 | get prev thread in d1 + + movew %sr,%d0 | save thread status reg + movew %d0,%a0@(TASK_THREAD+THREAD_SR) + + oril #0x700,%d0 | disable interrupts + move %d0,%sr + + movel sw_usp,%d0 | save usp + movel %d0,%a0@(TASK_THREAD+THREAD_USP) + + SAVE_SWITCH_STACK + movel %sp,%a0@(TASK_THREAD+THREAD_KSP) | save kernel stack pointer + movel %a1@(TASK_THREAD+THREAD_KSP),%sp | restore new thread stack + RESTORE_SWITCH_STACK + + movel %a1@(TASK_THREAD+THREAD_USP),%a0 | restore thread user stack + movel %a0, sw_usp + + movew %a1@(TASK_THREAD+THREAD_SR),%d0 | restore thread status reg + movew %d0, %sr + rts + +/*--------------------------------------------------------------------------*/ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/5307/Makefile linux.2.5.45-ac1/arch/m68knommu/platform/5307/Makefile --- linux.2.5.45/arch/m68knommu/platform/5307/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/5307/Makefile 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,27 @@ +# +# Makefile for the m68knommu kernel. +# + +# +# If you want to play with the HW breakpoints then you will +# need to add define this, which will give you a stack backtrace +# on the console port whenever a DBG interrupt occurs. You have to +# set up you HW breakpoints to trigger a DBG interrupt: +# +# EXTRA_CFLAGS += -DTRAP_DBG_INTERRUPT +# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT +# + +ifdef CONFIG_FULLDEBUG +AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1 +endif + +obj-$(CONFIG_COLDFIRE) += entry.o +obj-$(CONFIG_M5307) += config.o + +ifeq ($(CONFIG_M5307),y) +EXTRA_TARGETS := $(BOARD)/crt0_$(MODEL).o +endif + +include $(TOPDIR)/Rules.make + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/5307/MOTOROLA/crt0_ram.S linux.2.5.45-ac1/arch/m68knommu/platform/5307/MOTOROLA/crt0_ram.S --- linux.2.5.45/arch/m68knommu/platform/5307/MOTOROLA/crt0_ram.S 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/5307/MOTOROLA/crt0_ram.S 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,159 @@ +/*****************************************************************************/ + +/* + * crt0_ram.S -- startup code for MCF5307C3 Cadre-III ColdFire board. + * + * (C) Copyright 1999-2002, Greg Ungerer (gerg@snapgear.com). + * Copyright (C) 2000 Lineo Inc. (www.lineo.com) + * + * 1999/02/24 Modified for the 5307 processor David W. Miller + */ + +/*****************************************************************************/ + +#include "linux/autoconf.h" +#include "asm/coldfire.h" +#include "asm/mcfsim.h" +#include "asm/nettel.h" + +/*****************************************************************************/ + +/* + * SnapGear/NETtel board memory setup. + */ +#define MEM_BASE 0x00000000 /* Memory base at address 0 */ +#define MEM_SIZE 0x00800000 /* Memory size 8Mb */ +#define VBR_BASE MEM_BASE /* Vector address */ + +/*****************************************************************************/ + +.global _start +.global _rambase +.global _ramvec +.global _ramstart +.global _ramend + +/*****************************************************************************/ + +.data + +/* + * Set up the usable of RAM stuff. Size of RAM is determined then + * an initial stack set up at the end. + */ +_rambase: +.long 0 +_ramvec: +.long 0 +_ramstart: +.long 0 +_ramend: +.long 0 + +/*****************************************************************************/ + +.text + +/* + * This is the codes first entry point. This is where it all + * begins... + */ + +_start: + nop /* Filler */ + move.w #0x2700, %sr /* No interrupts */ + + /* + * Setup VBR here, otherwise buserror remap will not work. + * if dBug was active before (on my SBC with dBug 1.1 of Dec 16 1996) + * + * bkr@cut.de 19990306 + * + * Note: this is because dBUG points VBR to ROM, making vectors read + * only, so the bus trap can't be changed. (RS) + */ + move.l #VBR_BASE, %a7 /* Note VBR can't be read */ + movec %a7, %VBR + move.l %a7, _ramvec /* Set up vector addr */ + move.l %a7, _rambase /* Set up base RAM addr */ + + + /* + * Determine size of RAM, then set up initial stack. + */ + move.l #MEM_SIZE, %a0 + + move.l %a0, %d0 /* Mem end addr is in a0 */ + move.l %d0, %sp /* Set up initial stack ptr */ + move.l %d0, _ramend /* Set end ram addr */ + + /* make region ROM cachable (turn off for flash programming?) */ + /* 0xff000000 - 0xffffffff */ +#ifdef DEBUGGER_COMPATIBLE_CACHE + movl #(0xff< ram + + .data BLOCK(0x4) : { + _sdata = . ; + __data_start = . ; + *(.data) + *(.data.exit) + . = ALIGN(0x2000) ; + *(.data.init_task) + . = ALIGN(0x2000) ; + _edata = . ; + } > ram + + .init BLOCK(4096) : { + __init_begin = .; + *(.init.text) + *(.init.data) + . = ALIGN(16); + __setup_start = .; + *(.init.setup) + __setup_end = .; + __initcall_start = .; + *(.initcall1.init) + *(.initcall2.init) + *(.initcall3.init) + *(.initcall4.init) + *(.initcall5.init) + *(.initcall6.init) + *(.initcall7.init) + __initcall_end = .; + . = ALIGN(4) ; + __init_end = .; + } > ram + + .bss BLOCK(0x4) : { + _sbss = . ; + *(.bss) + *(COMMON) + . = ALIGN(4) ; + _ebss = . ; + _end = . ; + } > ram +} + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/5307/MP3/crt0_ram.S linux.2.5.45-ac1/arch/m68knommu/platform/5307/MP3/crt0_ram.S --- linux.2.5.45/arch/m68knommu/platform/5307/MP3/crt0_ram.S 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/5307/MP3/crt0_ram.S 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,173 @@ +/*****************************************************************************/ + +/* + * crt0_ram.S -- startup code for MCF5307 ColdFire based MP3. + * + * (C) Copyright 1999-2002, Greg Ungerer (gerg@snapgear.com). + * Copyright (C) 2000-2001 Lineo Inc. (www.lineo.com) + * + * 1999/02/24 Modified for the 5307 processor David W. Miller + */ + +/*****************************************************************************/ + +#include "linux/autoconf.h" +#include "asm/coldfire.h" +#include "asm/mcfsim.h" +#include "asm/nettel.h" + +/*****************************************************************************/ + +/* + * SnapGear/NETtel board memory setup. + */ +#define MEM_BASE 0x00000000 /* Memory base at address 0 */ +#define VBR_BASE MEM_BASE /* Vector address */ + +#if defined(CONFIG_RAM16MB) +#define MEM_SIZE 0x01000000 /* Memory size 16Mb */ +#else +#define MEM_SIZE 0x00800000 /* Memory size 8Mb */ +#endif + +/*****************************************************************************/ + +.global _start +.global _rambase +.global _ramvec +.global _ramstart +.global _ramend + +/*****************************************************************************/ + +.data + +/* + * Set up the usable of RAM stuff. Size of RAM is determined then + * an initial stack set up at the end. + */ +_rambase: +.long 0 +_ramvec: +.long 0 +_ramstart: +.long 0 +_ramend: +.long 0 + +/*****************************************************************************/ + +.text + +/* + * This is the codes first entry point. This is where it all + * begins... + */ + +_start: + nop /* Filler */ + move.w #0x2700, %sr /* No interrupts */ + + /* + * Disable watchdog timer. + */ + move.l #MCF_MBAR, %a0 /* Get MBAR address */ + clr.l %d0 /* Disable SWT */ + move.b %d0, MCFSIM_SYPCR(%a0) + move.b #0x55, %d0 /* Clear SWT as well */ + move.b %d0, MCFSIM_SWSR(%a0) + move.b #0xaa, %d0 + move.b %d0, MCFSIM_SWSR(%a0) + move.l #0xffffffff, %d0 /* Mask out all interrupts */ + move.l %d0, MCFSIM_IMR(%a0) + + /* + * Setup VBR here, otherwise buserror remap will not work. + * if dBug was active before (on my SBC with dBug 1.1 of Dec 16 1996) + * + * bkr@cut.de 19990306 + * + * Note: this is because dBUG points VBR to ROM, making vectors read + * only, so the bus trap can't be changed. (RS) + */ + move.l #VBR_BASE, %a7 /* Note VBR can't be read */ + movec %a7, %VBR + move.l %a7, _ramvec /* Set up vector addr */ + move.l %a7, _rambase /* Set up base RAM addr */ + + + /* + * Determine size of RAM, then set up initial stack. + */ + move.l #MEM_SIZE, %a0 + + move.l %a0, %d0 /* Mem end addr is in a0 */ + move.l %d0, %sp /* Set up initial stack ptr */ + move.l %d0, _ramend /* Set end ram addr */ + + /* + * Enable CPU internal cache. + */ + move.l #0x01000000, %d0 /* invalidate whole cache */ + movec %d0,%CACR + nop + + /* MUST be write-through for DMA to work... */ + /* This also makes this debugger safe */ + move.l #0x0000c000, %d0 /* Set SDRAM cached only */ + movec %d0, %ACR0 + move.l #0x00000000, %d0 /* No other regions cached */ + movec %d0, %ACR1 + + /* Enable cache */ + move.l #0xa0000200, %d0 + movec %d0,%CACR + nop + + /* + * Move ROM filesystem above bss :-) + */ + lea.l _sbss, %a0 /* Get start of bss */ + lea.l _ebss, %a1 /* Set up destination */ + move.l %a0, %a2 /* Copy of bss start */ + + move.l 8(%a0), %d0 /* Get size of ROMFS */ + addq.l #8, %d0 /* Allow for rounding */ + and.l #0xfffffffc, %d0 /* Whole words */ + + add.l %d0, %a0 /* Copy from end */ + add.l %d0, %a1 /* Copy from end */ + move.l %a1, _ramstart /* Set start of ram */ + +_copy_romfs: + move.l -(%a0), %d0 /* Copy dword */ + move.l %d0, -(%a1) + cmp.l %a0, %a2 /* Check if at end */ + bne _copy_romfs + + /* + * Zero out the bss region. + */ + lea.l _sbss, %a0 /* Get start of bss */ + lea.l _ebss, %a1 /* Get end of bss */ + clr.l %d0 /* Set value */ +_clear_bss: + move.l %d0, (%a0)+ /* Clear each word */ + cmp.l %a0, %a1 /* Check if at end */ + bne _clear_bss + + /* + * load the current task pointer and stack + */ + lea init_thread_union, %a0 + lea 0x2000(%a0), %sp + + /* + * Assember start up done, start code proper. + */ + jsr start_kernel /* Start Linux kernel */ + +_exit: + jmp _exit /* Should never get here */ + +/*****************************************************************************/ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/5307/MP3/ram.ld linux.2.5.45-ac1/arch/m68knommu/platform/5307/MP3/ram.ld --- linux.2.5.45/arch/m68knommu/platform/5307/MP3/ram.ld 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/5307/MP3/ram.ld 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,72 @@ + +MEMORY { + ram : ORIGIN = 0x400, LENGTH = 0x1000000 +} + +jiffies = jiffies_64 + 4; + +SECTIONS { + + .text : { + _stext = . ; + *(.text) + *(.exit.text) + *(.text.lock) + *(.exitcall.exit) + *(.rodata) + . = ALIGN(0x4) ; + *(.kstrtab) + . = ALIGN(16); /* Exception table */ + __start___ex_table = .; + *(__ex_table) + __stop___ex_table = .; + + __start___ksymtab = .; /* Kernel symbol table */ + *(__ksymtab) + __stop___ksymtab = .; + . = ALIGN(4) ; + _etext = . ; + } > ram + + .data BLOCK(0x4) : { + _sdata = . ; + __data_start = . ; + *(.data) + *(.data.exit) + . = ALIGN(0x2000) ; + *(.data.init_task) + . = ALIGN(0x2000) ; + _edata = . ; + } > ram + + .init BLOCK(4096) : { + __init_begin = .; + *(.init.text) + *(.init.data) + . = ALIGN(16); + __setup_start = .; + *(.init.setup) + __setup_end = .; + __initcall_start = .; + *(.initcall1.init) + *(.initcall2.init) + *(.initcall3.init) + *(.initcall4.init) + *(.initcall5.init) + *(.initcall6.init) + *(.initcall7.init) + __initcall_end = . ; + . = ALIGN(4); + __init_end = .; + } > ram + + .bss BLOCK(0x4) : { + _sbss = . ; + *(.bss) + *(COMMON) + . = ALIGN(4) ; + _ebss = . ; + _end = . ; + } > ram +} + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/5307/NETtel/crt0_ram.S linux.2.5.45-ac1/arch/m68knommu/platform/5307/NETtel/crt0_ram.S --- linux.2.5.45/arch/m68knommu/platform/5307/NETtel/crt0_ram.S 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/5307/NETtel/crt0_ram.S 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,196 @@ +/*****************************************************************************/ + +/* + * crt0_ram.S -- startup code for MCF5307 ColdFire based NETtel. + * + * (C) Copyright 1999-2002, Greg Ungerer (gerg@snapgear.com). + * Copyright (C) 2000 Lineo Inc. (www.lineo.com) + * + * 1999/02/24 Modified for the 5307 processor David W. Miller + */ + +/*****************************************************************************/ + +#include "linux/autoconf.h" +#include "asm/coldfire.h" +#include "asm/mcfsim.h" +#include "asm/nettel.h" + +/*****************************************************************************/ + +/* + * SnapGear/NETtel board memory setup. + */ +#define MEM_BASE 0x00000000 /* Memory base at address 0 */ +#define VBR_BASE MEM_BASE /* Vector address */ + +#if defined(CONFIG_RAM16MB) +#define MEM_SIZE 0x01000000 /* Memory size 16Mb */ +#elif defined(CONFIG_RAM8MB) +#define MEM_SIZE 0x00800000 /* Memory size 8Mb */ +#else +#define MEM_SIZE 0x00400000 /* Memory size 4Mb */ +#endif + +/*****************************************************************************/ + +.global _start +.global _rambase +.global _ramvec +.global _ramstart +.global _ramend + +/*****************************************************************************/ + +.data + +/* + * Set up the usable of RAM stuff. Size of RAM is determined then + * an initial stack set up at the end. + */ +_rambase: +.long 0 +_ramvec: +.long 0 +_ramstart: +.long 0 +_ramend: +.long 0 + +/*****************************************************************************/ + +/* + * The NETtel platform has some funky LEDs! + */ +.global ppdata +ppdata: +.short 0x0000 + +.global ledbank +ledbank: +.byte 0xff + +/*****************************************************************************/ + +.text + +/* + * This is the codes first entry point. This is where it all + * begins... + */ + +_start: + nop /* Filler */ + move.w #0x2700, %sr /* No interrupts */ + + /* + * Set LEDs to known startup state. + */ + move.l #NETtel_LEDADDR, %a5 /* Addr of LED bank */ + move.b #0xff, (%a5) /* Turn them all off */ + + + /* + * Disable watchdog timer. + */ + move.l #MCF_MBAR, %a0 /* Get MBAR address */ + clr.l %d0 /* Disable SWT */ + move.b %d0, MCFSIM_SYPCR(%a0) + move.b #0x55, %d0 /* Clear SWT as well */ + move.b %d0, MCFSIM_SWSR(%a0) + move.b #0xaa, %d0 + move.b %d0, MCFSIM_SWSR(%a0) + move.l #0xffffffff, %d0 /* Mask out all interrupts */ + move.l %d0, MCFSIM_IMR(%a0) + + /* + * Setup VBR here, otherwise buserror remap will not work. + * if dBug was active before (on my SBC with dBug 1.1 of Dec 16 1996) + * + * bkr@cut.de 19990306 + * + * Note: this is because dBUG points VBR to ROM, making vectors read + * only, so the bus trap can't be changed. (RS) + */ + move.l #VBR_BASE, %a7 /* Note VBR can't be read */ + movec %a7, %VBR + move.l %a7, _ramvec /* Set up vector addr */ + move.l %a7, _rambase /* Set up base RAM addr */ + + + /* + * Determine size of RAM, then set up initial stack. + */ + move.l #MEM_SIZE, %a0 + + move.l %a0, %d0 /* Mem end addr is in a0 */ + move.l %d0, %sp /* Set up initial stack ptr */ + move.l %d0, _ramend /* Set end ram addr */ + + /* + * Enable CPU internal cache. + */ + move.l #0x01000000, %d0 /* invalidate whole cache */ + movec %d0,%CACR + nop +#ifdef DEBUGGER_COMPATIBLE_CACHE + move.l #0x0000c000, %d0 /* Set SDRAM cached only */ +#else + move.l #0x0000c020, %d0 /* Set SDRAM cached only (copyback) */ +#endif + movec %d0, %ACR0 + move.l #0x00000000, %d0 /* No other regions cached */ + movec %d0, %ACR1 + + /* Enable cache */ + move.l #0xa0000200, %d0 + movec %d0,%CACR + nop + + /* + * Move ROM filesystem above bss :-) + */ + lea.l _sbss, %a0 /* Get start of bss */ + lea.l _ebss, %a1 /* Set up destination */ + move.l %a0, %a2 /* Copy of bss start */ + + move.l 8(%a0), %d0 /* Get size of ROMFS */ + addq.l #8, %d0 /* Allow for rounding */ + and.l #0xfffffffc, %d0 /* Whole words */ + + add.l %d0, %a0 /* Copy from end */ + add.l %d0, %a1 /* Copy from end */ + move.l %a1, _ramstart /* Set start of ram */ + +_copy_romfs: + move.l -(%a0), %d0 /* Copy dword */ + move.l %d0, -(%a1) + cmp.l %a0, %a2 /* Check if at end */ + bne _copy_romfs + + /* + * Zero out the bss region. + */ + lea.l _sbss, %a0 /* Get start of bss */ + lea.l _ebss, %a1 /* Get end of bss */ + clr.l %d0 /* Set value */ +_clear_bss: + move.l %d0, (%a0)+ /* Clear each word */ + cmp.l %a0, %a1 /* Check if at end */ + bne _clear_bss + + /* + * load the current task pointer and stack + */ + lea init_thread_union, %a0 + lea 0x2000(%a0), %sp + + /* + * Assember start up done, start code proper. + */ + jsr start_kernel /* Start Linux kernel */ + +_exit: + jmp _exit /* Should never get here */ + +/*****************************************************************************/ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/5307/NETtel/ram.ld linux.2.5.45-ac1/arch/m68knommu/platform/5307/NETtel/ram.ld --- linux.2.5.45/arch/m68knommu/platform/5307/NETtel/ram.ld 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/5307/NETtel/ram.ld 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,72 @@ + +MEMORY { + ram : ORIGIN = 0x400, LENGTH = 0x400000 +} + +jiffies = jiffies_64 + 4; + +SECTIONS { + + .text : { + _stext = . ; + *(.text) + *(.exit.text) + *(.text.lock) + *(.exitcall.exit) + *(.rodata) + . = ALIGN(0x4) ; + *(.kstrtab) + . = ALIGN(16); /* Exception table */ + __start___ex_table = .; + *(__ex_table) + __stop___ex_table = .; + + __start___ksymtab = .; /* Kernel symbol table */ + *(__ksymtab) + __stop___ksymtab = .; + . = ALIGN(4) ; + _etext = . ; + } > ram + + .data BLOCK(0x4) : { + _sdata = . ; + __data_start = . ; + *(.data) + *(.data.exit) + . = ALIGN(0x2000) ; + *(.data.init_task) + . = ALIGN(0x2000) ; + _edata = . ; + } > ram + + .init BLOCK(4096) : { + __init_begin = .; + *(.init.text) + *(.init.data) + . = ALIGN(16); + __setup_start = .; + *(.init.setup) + __setup_end = .; + __initcall_start = .; + *(.initcall1.init) + *(.initcall2.init) + *(.initcall3.init) + *(.initcall4.init) + *(.initcall5.init) + *(.initcall6.init) + *(.initcall7.init) + __initcall_end = .; + . = ALIGN(4) ; + __init_end = .; + } > ram + + .bss BLOCK(0x4) : { + _sbss = . ; + *(.bss) + *(COMMON) + . = ALIGN(4) ; + _ebss = . ; + _end = . ; + } > ram +} + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/5407/CLEOPATRA/crt0_ram.S linux.2.5.45-ac1/arch/m68knommu/platform/5407/CLEOPATRA/crt0_ram.S --- linux.2.5.45/arch/m68knommu/platform/5407/CLEOPATRA/crt0_ram.S 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/5407/CLEOPATRA/crt0_ram.S 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,173 @@ +/*****************************************************************************/ + +/* + * crt0_ram.S -- startup code for Feith Cleopatra 2 board. + * + * (C) Copyright 2001, Roman Wagner. + * + * 1999/02/24 Modified for the 5307 processor David W. Miller + */ + +/*****************************************************************************/ + +#include "linux/autoconf.h" +#include "asm/coldfire.h" +#include "asm/mcfsim.h" + +/*****************************************************************************/ + +/* + * Feith CLEOPATRA board, chip select and memory setup. +*/ + +#define MEM_BASE 0x00000000 /* Memory base at address 0 */ +#define VBR_BASE MEM_BASE /* Vector address */ + +#define MEM_SIZE 0x01000000 /* Memory size 16Mb */ + +/*****************************************************************************/ + +.global _start +.global _rambase +.global _ramvec +.global _ramstart +.global _ramend + +/*****************************************************************************/ + +.data + +/* + * Set up the usable of RAM stuff. Size of RAM is determined then + * an initial stack set up at the end. + */ +_rambase: +.long 0 +_ramvec: +.long 0 +_ramstart: +.long 0 +_ramend: +.long 0 + +/*****************************************************************************/ + +.text + +/* + * This is the codes first entry point. This is where it all + * begins... + */ + +_start: + nop /* Filler */ + move.w #0x2700, %sr /* No interrupts */ + + + /* + * Setup VBR here, otherwise buserror remap will not work. + * if dBug was active before (on my SBC with dBug 1.1 of Dec 16 1996) + * + * bkr@cut.de 19990306 + * + * Note: this is because dBUG points VBR to ROM, making vectors read + * only, so the bus trap can't be changed. (RS) + */ + move.l #VBR_BASE, %a7 /* Note VBR can't be read */ + movec %a7, %VBR + move.l %a7, _ramvec /* Set up vector addr */ + move.l %a7, _rambase /* Set up base RAM addr */ + + /* + * Determine size of RAM, then set up initial stack. + */ +/* + * The current version of the 5307 processor + * SWT does not work. Probing invalid addresses + * will hang the system. + * + * For now, set the memory size to 8 meg + */ + move.l #MEM_SIZE, %a0 + + move.l %a0, %d0 /* Mem end addr is in a0 */ + move.l %d0, %sp /* Set up initial stack ptr */ + move.l %d0, _ramend /* Set end ram addr */ + + + /* + * Enable CPU internal cache. + */ + move.l #0x01040100, %d0 /* Invalidate whole cache */ + movec %d0,%CACR + nop + + /* make region ROM cachable (turn off for flash programming?) */ + /* 0xff000000 - 0xffffffff */ + move.l #(0xff< ram + + .data BLOCK(0x4) : { + _sdata = . ; + __data_start = . ; + *(.data) + *(.data.exit) + . = ALIGN(0x2000) ; + *(.data.init_task) + . = ALIGN(0x2000) ; + _edata = . ; + } > ram + + .init BLOCK(4096) : { + __init_begin = .; + *(.init.text) + *(.init.data) + . = ALIGN(16); + __setup_start = .; + *(.init.setup) + __setup_end = .; + __initcall_start = .; + *(.initcall1.init) + *(.initcall2.init) + *(.initcall3.init) + *(.initcall4.init) + *(.initcall5.init) + *(.initcall6.init) + *(.initcall7.init) + __initcall_end = . ; + . = ALIGN(4); + __init_end = .; + } > ram + + .bss BLOCK(0x4) : { + _sbss = . ; + *(.bss) + *(COMMON) + . = ALIGN(4) ; + _ebss = . ; + _end = . ; + } > ram +} + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/5407/config.c linux.2.5.45-ac1/arch/m68knommu/platform/5407/config.c --- linux.2.5.45/arch/m68knommu/platform/5407/config.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/5407/config.c 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,236 @@ +/***************************************************************************/ + +/* + * linux/arch/m68knommu/platform/5407/config.c + * + * Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com) + * Copyright (C) 2000, Lineo (www.lineo.com) + */ + +/***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/***************************************************************************/ + +void coldfire_profile_init(void); + +/***************************************************************************/ + +/* + * DMA channel base address table. + */ +unsigned int dma_base_addr[MAX_M68K_DMA_CHANNELS] = { + MCF_MBAR + MCFDMA_BASE0, + MCF_MBAR + MCFDMA_BASE1, + MCF_MBAR + MCFDMA_BASE2, + MCF_MBAR + MCFDMA_BASE3, +}; + +unsigned int dma_device_address[MAX_M68K_DMA_CHANNELS]; + +/***************************************************************************/ + +void coldfire_tick(void) +{ + volatile unsigned char *timerp; + + /* Reset the ColdFire timer */ + timerp = (volatile unsigned char *) (MCF_MBAR + MCFTIMER_BASE1); + timerp[MCFTIMER_TER] = MCFTIMER_TER_CAP | MCFTIMER_TER_REF; +} + +/***************************************************************************/ + +void coldfire_timer_init(void (*handler)(int, void *, struct pt_regs *)) +{ + volatile unsigned short *timerp; + volatile unsigned char *icrp; + + /* Set up TIMER 1 as poll clock */ + timerp = (volatile unsigned short *) (MCF_MBAR + MCFTIMER_BASE1); + timerp[MCFTIMER_TMR] = MCFTIMER_TMR_DISABLE; + + timerp[MCFTIMER_TRR] = (unsigned short) ((MCF_CLK / 16) / HZ); + timerp[MCFTIMER_TMR] = MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 | + MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE; + + icrp = (volatile unsigned char *) (MCF_MBAR + MCFSIM_TIMER1ICR); + +#if defined(CONFIG_CLEOPATRA) + *icrp = MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI3; + request_irq(30, handler, SA_INTERRUPT, "ColdFire Timer", NULL); +#else + *icrp = MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL5 | MCFSIM_ICR_PRI3; + request_irq(29, handler, SA_INTERRUPT, "ColdFire Timer", NULL); +#endif + +#ifdef CONFIG_HIGHPROFILE + coldfire_profile_init(); +#endif + mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_TIMER1); +} + +/***************************************************************************/ +#ifdef CONFIG_HIGHPROFILE +/***************************************************************************/ + +#define PROFILEHZ 1013 + +/* + * Use the other timer to provide high accuracy profiling info. + */ + +void coldfire_profile_tick(int irq, void *dummy, struct pt_regs *regs) +{ + volatile unsigned char *timerp; + + /* Reset the ColdFire timer2 */ + timerp = (volatile unsigned char *) (MCF_MBAR + MCFTIMER_BASE2); + timerp[MCFTIMER_TER] = MCFTIMER_TER_CAP | MCFTIMER_TER_REF; + + if (!user_mode(regs)) { + if (prof_buffer && current->pid) { + extern int _stext; + unsigned long ip = instruction_pointer(regs); + ip -= (unsigned long) &_stext; + ip >>= prof_shift; + if (ip < prof_len) + prof_buffer[ip]++; + } + } +} + +void coldfire_profile_init(void) +{ + volatile unsigned short *timerp; + volatile unsigned char *icrp; + + printk("PROFILE: lodging timer2=%d as profile timer\n", PROFILEHZ); + + /* Set up TIMER 2 as poll clock */ + timerp = (volatile unsigned short *) (MCF_MBAR + MCFTIMER_BASE2); + timerp[MCFTIMER_TMR] = MCFTIMER_TMR_DISABLE; + + timerp[MCFTIMER_TRR] = (unsigned short) ((MCF_CLK / 16) / PROFILEHZ); + timerp[MCFTIMER_TMR] = MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 | + MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE; + + icrp = (volatile unsigned char *) (MCF_MBAR + MCFSIM_TIMER2ICR); + + *icrp = MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL7 | MCFSIM_ICR_PRI3; + request_irq(31, coldfire_profile_tick, (SA_INTERRUPT | IRQ_FLG_FAST), + "Profile Timer", NULL); + mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_TIMER2); +} + +/***************************************************************************/ +#endif /* CONFIG_HIGHPROFILE */ +/***************************************************************************/ + +/* + * Program the vector to be an auto-vectored. + */ + +void mcf_autovector(unsigned int vec) +{ + volatile unsigned char *mbar; + + if ((vec >= 25) && (vec <= 31)) { + mbar = (volatile unsigned char *) MCF_MBAR; + vec = 0x1 << (vec - 24); + *(mbar + MCFSIM_AVR) |= vec; + mcf_setimr(mcf_getimr() & ~vec); + } +} + +/***************************************************************************/ + +extern e_vector *_ramvec; + +void set_evector(int vecnum, void (*handler)(void)) +{ + if (vecnum >= 0 && vecnum <= 255) + _ramvec[vecnum] = handler; +} + +/***************************************************************************/ + +/* assembler routines */ +asmlinkage void buserr(void); +asmlinkage void trap(void); +asmlinkage void system_call(void); +asmlinkage void inthandler(void); + +void __init coldfire_trap_init(void) +{ + int i; + +#ifndef ENABLE_dBUG + mcf_setimr(MCFSIM_IMR_MASKALL); +#endif + + /* + * There is a common trap handler and common interrupt + * handler that handle almost every vector. We treat + * the system call and bus error special, they get their + * own first level handlers. + */ +#ifndef ENABLE_dBUG + for (i = 3; (i <= 23); i++) + _ramvec[i] = trap; + for (i = 33; (i <= 63); i++) + _ramvec[i] = trap; +#endif + + for (i = 24; (i <= 30); i++) + _ramvec[i] = inthandler; +#ifndef ENABLE_dBUG + _ramvec[31] = inthandler; // Disables the IRQ7 button +#endif + + for (i = 64; (i < 255); i++) + _ramvec[i] = inthandler; + _ramvec[255] = 0; + + _ramvec[2] = buserr; + _ramvec[32] = system_call; +} + +/***************************************************************************/ + +void config_BSP(char *commandp, int size) +{ + memset(commandp, 0, size); + + mach_sched_init = coldfire_timer_init; + mach_tick = coldfire_tick; + mach_trap_init = coldfire_trap_init; +} + +/***************************************************************************/ +#ifdef TRAP_DBG_INTERRUPT + +asmlinkage void dbginterrupt_c(struct frame *fp) +{ + extern void dump(struct pt_regs *fp); + printk("%s(%d): BUS ERROR TRAP\n", __FILE__, __LINE__); + dump((struct pt_regs *) fp); + asm("halt"); +} + +#endif +/***************************************************************************/ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/5407/Makefile linux.2.5.45-ac1/arch/m68knommu/platform/5407/Makefile --- linux.2.5.45/arch/m68knommu/platform/5407/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/5407/Makefile 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,24 @@ +# +# Makefile for the m68knommu linux kernel. +# + +# +# If you want to play with the HW breakpoints then you will +# need to add define this, which will give you a stack backtrace +# on the console port whenever a DBG interrupt occurs. You have to +# set up you HW breakpoints to trigger a DBG interrupt: +# +# EXTRA_CFLAGS += -DTRAP_DBG_INTERRUPT +# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT +# + +ifdef CONFIG_FULLDEBUG +AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1 +endif + +obj-y := config.o + +EXTRA_TARGETS := $(BOARD)/crt0_$(MODEL).o + +include $(TOPDIR)/Rules.make + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/5407/MOTOROLA/crt0_ram.S linux.2.5.45-ac1/arch/m68knommu/platform/5407/MOTOROLA/crt0_ram.S --- linux.2.5.45/arch/m68knommu/platform/5407/MOTOROLA/crt0_ram.S 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/5407/MOTOROLA/crt0_ram.S 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,152 @@ +/*****************************************************************************/ + +/* + * crt0_ram.S -- startup code for Motorola 5407 eval board. + * + * (C) Copyright 1999-2002, Greg Ungerer (gerg@snapgear.com). + * (C) Copyright 2000, Lineo (www.lineo.com). + * + * 1999/02/24 Modified for the 5307 processor David W. Miller + */ + +/*****************************************************************************/ + +#include "linux/autoconf.h" +#include "asm/coldfire.h" +#include "asm/mcfsim.h" + +/*****************************************************************************/ + +/* + * Board setup info. + */ +#define MEM_BASE 0x00000000 /* Memory base at address 0 */ +#define VBR_BASE MEM_BASE /* Vector address */ + +#define MEM_SIZE 0x02000000 /* Memory size 32 */ + +/*****************************************************************************/ + +.global _start +.global _rambase +.global _ramvec +.global _ramstart +.global _ramend + +/*****************************************************************************/ + +.data + +/* + * Set up the usable of RAM stuff. Size of RAM is determined then + * an initial stack set up at the end. + */ +_rambase: +.long 0 +_ramvec: +.long 0 +_ramstart: +.long 0 +_ramend: +.long 0 + +/*****************************************************************************/ + +.text + +/* + * This is the codes first entry point. This is where it all + * begins... + */ + +_start: + nop /* Filler */ + move.w #0x2700, %sr /* No interrupts */ + + /* + * Setup VBR as per eval board (really dBUG does this). + * These settings must match it. + */ + move.l #VBR_BASE, %a0 /* Note VBR can't be read */ + movec %a0, %VBR + move.l %a0, _ramvec /* Set up vector addr */ + move.l %a0, _rambase /* Set up base RAM addr */ + + + /* + * Determine size of RAM, then set up initial stack. + */ + move.l #MEM_SIZE, %a0 + + move.l %a0, %d0 /* Mem end addr is in a0 */ + move.l %d0, %sp /* Set up initial stack ptr */ + move.l %d0, _ramend /* Set end ram addr */ + + + /* + * Enable CPU internal cache. + */ + move.l #0x01040100, %d0 /* Invalidate whole cache */ + movec %d0,%CACR + nop + move.l #0x000fc000, %d0 /* Set SDRAM cached only */ + movec %d0, %ACR0 + move.l #0x00000000, %d0 /* No other regions cached */ + movec %d0, %ACR1 + move.l #0x000fc000, %d0 /* Set SDRAM cached only */ + movec %d0, %ACR2 + move.l #0x00000000, %d0 /* No other regions cached */ + movec %d0, %ACR3 + + /* Enable cache */ + move.l #0x86088400, %d0 + movec %d0,%CACR + nop + + /* + * Move ROM filesystem above bss :-) + */ + lea.l _sbss, %a0 /* Get start of bss */ + lea.l _ebss, %a1 /* Set up destination */ + move.l %a0, %a2 /* Copy of bss start */ + + move.l 8(%a0), %d0 /* Get size of ROMFS */ + addq.l #8, %d0 /* Allow for rounding */ + and.l #0xfffffffc, %d0 /* Whole words */ + + add.l %d0, %a0 /* Copy from end */ + add.l %d0, %a1 /* Copy from end */ + move.l %a1, _ramstart /* Set start of ram */ + +_copy_romfs: + move.l -(%a0), %d0 /* Copy dword */ + move.l %d0, -(%a1) + cmp.l %a0, %a2 /* Check if at end */ + bne _copy_romfs + + /* + * Zero out the bss region. + */ + lea.l _sbss, %a0 /* Get start of bss */ + lea.l _ebss, %a1 /* Get end of bss */ + clr.l %d0 /* Set value */ +_clear_bss: + move.l %d0, (%a0)+ /* Clear each word */ + cmp.l %a0, %a1 /* Check if at end */ + bne _clear_bss + + /* + * Load the current task pointer and stack. + */ + lea init_thread_union, %a0 + lea 0x2000(%a0), %sp + + /* + * Assember start up done, start code proper. + */ + jsr start_kernel /* Start Linux kernel */ + +_exit: + jmp _exit /* Should never get here */ + +/*****************************************************************************/ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/5407/MOTOROLA/ram.ld linux.2.5.45-ac1/arch/m68knommu/platform/5407/MOTOROLA/ram.ld --- linux.2.5.45/arch/m68knommu/platform/5407/MOTOROLA/ram.ld 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/5407/MOTOROLA/ram.ld 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,72 @@ + +MEMORY { + ram : ORIGIN = 0x20000, LENGTH = 0x007E0000 +} + +jiffies = jiffies_64 + 4; + +SECTIONS { + + .text : { + _stext = . ; + *(.text) + *(.exit.text) + *(.text.lock) + *(.exitcall.exit) + *(.rodata) + . = ALIGN(0x4) ; + *(.kstrtab) + . = ALIGN(16); /* Exception table */ + __start___ex_table = .; + *(__ex_table) + __stop___ex_table = .; + + __start___ksymtab = .; /* Kernel symbol table */ + *(__ksymtab) + __stop___ksymtab = .; + . = ALIGN(4) ; + _etext = . ; + } > ram + + .data BLOCK(0x4) : { + _sdata = . ; + __data_start = . ; + *(.data) + *(.data.exit) + . = ALIGN(0x2000) ; + *(.data.init_task) + . = ALIGN(0x2000) ; + _edata = . ; + } > ram + + .init BLOCK(4096) : { + __init_begin = .; + *(.init.text) + *(.init.data) + . = ALIGN(16); + __setup_start = .; + *(.init.setup) + __setup_end = .; + __initcall_start = .; + *(.initcall1.init) + *(.initcall2.init) + *(.initcall3.init) + *(.initcall4.init) + *(.initcall5.init) + *(.initcall6.init) + *(.initcall7.init) + __initcall_end = .; + . = ALIGN(4) ; + __init_end = .; + } > ram + + .bss BLOCK(0x4) : { + _sbss = . ; + *(.bss) + *(COMMON) + . = ALIGN(4) ; + _ebss = . ; + _end = . ; + } > ram +} + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/68328/bootlogo.h linux.2.5.45-ac1/arch/m68knommu/platform/68328/bootlogo.h --- linux.2.5.45/arch/m68knommu/platform/68328/bootlogo.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/68328/bootlogo.h 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,270 @@ +#define bootlogo_width 160 +#define bootlogo_height 160 +static unsigned char bootlogo_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x40, 0x55, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x55, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x20, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x08, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x08, 0x00, 0x00, + 0x00, 0xff, 0x80, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x20, 0x04, 0x00, 0x00, 0x00, 0xf8, 0x80, 0x0f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x50, 0x04, 0x00, 0x00, 0x00, 0x78, 0x80, 0x0f, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x03, 0x00, 0x00, + 0x00, 0x78, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x40, + 0xa8, 0x02, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x70, 0x28, 0x01, 0x00, 0x00, + 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x20, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x70, + 0x54, 0x01, 0x00, 0x00, 0x00, 0x3e, 0x80, 0x01, 0x3a, 0x78, 0x80, 0x0e, + 0x50, 0xc0, 0x03, 0x0e, 0x00, 0x20, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00, + 0x00, 0x3e, 0xf0, 0x83, 0x1f, 0xfc, 0xe0, 0x0f, 0x78, 0xf8, 0x87, 0x1f, + 0x00, 0x18, 0x00, 0x30, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x1e, 0xf8, 0xc3, + 0x1f, 0xfc, 0xe0, 0x0f, 0x78, 0xf8, 0x87, 0x0f, 0x00, 0x20, 0x00, 0x10, + 0x55, 0x00, 0x00, 0x00, 0x00, 0x1e, 0xc0, 0x03, 0x9f, 0xf3, 0x80, 0x0f, + 0x78, 0x80, 0xc7, 0x0e, 0x00, 0x18, 0x00, 0x20, 0xaa, 0x00, 0x00, 0x00, + 0x00, 0x1e, 0xe0, 0x03, 0x9f, 0xf1, 0x80, 0x07, 0x78, 0x80, 0x67, 0x00, + 0x00, 0x24, 0x00, 0x18, 0x55, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xe0, 0x01, + 0x5e, 0xf0, 0x80, 0x07, 0x3c, 0x00, 0x2f, 0x00, 0x00, 0x14, 0x00, 0x20, + 0xaa, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xe0, 0x01, 0x7f, 0xf0, 0x80, 0x07, + 0x3c, 0x00, 0x3f, 0x00, 0x00, 0x08, 0x00, 0x18, 0x55, 0x00, 0x00, 0x00, + 0x00, 0x0f, 0xe0, 0x00, 0x3f, 0xf0, 0xc0, 0x03, 0x1e, 0x00, 0x1f, 0x00, + 0x00, 0x14, 0x00, 0x28, 0xaa, 0x00, 0x00, 0x00, 0x80, 0x0f, 0xf0, 0x00, + 0x1f, 0xf0, 0xc0, 0x03, 0x1f, 0x00, 0x1f, 0x00, 0x00, 0x04, 0x00, 0x0c, + 0x54, 0x00, 0x00, 0x00, 0x80, 0x07, 0x78, 0x00, 0x1f, 0x78, 0xc0, 0x03, + 0x1f, 0x00, 0x1e, 0x00, 0x00, 0x0a, 0x00, 0x12, 0xa8, 0x00, 0x00, 0x00, + 0x80, 0x07, 0x78, 0x00, 0x1f, 0x78, 0xe0, 0x03, 0x1f, 0x00, 0x1f, 0x00, + 0x00, 0x04, 0x00, 0x0a, 0x54, 0x00, 0x00, 0x00, 0x80, 0x07, 0x78, 0x80, + 0x0f, 0x78, 0xe0, 0x03, 0x1f, 0x00, 0x1e, 0x00, 0x00, 0x0a, 0x00, 0x08, + 0x50, 0x01, 0x00, 0x00, 0x84, 0x03, 0x78, 0x80, 0x07, 0x3c, 0xe0, 0xc1, + 0x0f, 0x00, 0x1f, 0x00, 0x00, 0x04, 0x00, 0x06, 0xa8, 0x00, 0x00, 0x00, + 0xc0, 0x03, 0x78, 0xc0, 0x07, 0x3c, 0xe0, 0xc1, 0x0f, 0x00, 0x1f, 0x00, + 0x00, 0x0a, 0x00, 0x08, 0x50, 0x01, 0x00, 0x00, 0xc2, 0x01, 0x38, 0xc0, + 0x07, 0x3c, 0xe0, 0x60, 0x0f, 0x80, 0x1e, 0x00, 0x00, 0x05, 0x00, 0x07, + 0xa0, 0x00, 0x00, 0x80, 0xe0, 0x01, 0x3c, 0xc0, 0x07, 0x3c, 0xf0, 0xa0, + 0x07, 0xc0, 0x1c, 0x00, 0x00, 0x0a, 0x80, 0x08, 0xa0, 0x02, 0x00, 0xa0, + 0xe0, 0x21, 0x1c, 0xc0, 0x03, 0x1c, 0x71, 0x90, 0x47, 0x40, 0x3c, 0x04, + 0x00, 0x05, 0x80, 0x06, 0xa0, 0x02, 0x00, 0x20, 0xe0, 0x31, 0x1e, 0xc3, + 0x03, 0x1e, 0x79, 0x98, 0x47, 0x60, 0x38, 0x04, 0x00, 0x15, 0x40, 0x0a, + 0xa0, 0x0a, 0x00, 0x1a, 0xe0, 0x19, 0x9e, 0xe1, 0x01, 0x9e, 0x78, 0xcc, + 0xa7, 0x32, 0x78, 0x02, 0x80, 0x2a, 0x40, 0x05, 0x80, 0x2a, 0x00, 0x05, + 0xe0, 0x0d, 0x9e, 0xe0, 0x01, 0xde, 0x78, 0xc6, 0x97, 0x1b, 0x78, 0x03, + 0x80, 0x52, 0x30, 0x0a, 0x00, 0x95, 0xd2, 0x0a, 0xe0, 0x0f, 0xfe, 0xe0, + 0x00, 0x7e, 0xf8, 0x87, 0x9f, 0x0f, 0xf8, 0x01, 0x00, 0xa1, 0x0e, 0x15, + 0x80, 0x55, 0x55, 0x01, 0xe0, 0x01, 0x3c, 0xf0, 0x00, 0x3c, 0xf0, 0x80, + 0x8f, 0x0f, 0x70, 0x00, 0x00, 0x81, 0x02, 0x14, 0x00, 0x54, 0x55, 0x00, + 0xc0, 0x01, 0x3c, 0x00, 0x00, 0x0c, 0x60, 0x00, 0x07, 0x03, 0x70, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x40, 0x01, 0x00, 0x11, 0x09, 0x00, 0x04, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, + 0x00, 0x20, 0x01, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x49, 0x32, 0x49, 0x49, 0x91, + 0x24, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x20, 0x49, 0x0a, 0x09, 0xc9, 0x92, 0x14, 0x81, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x49, + 0x18, 0x01, 0x49, 0x92, 0x0c, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x49, 0x30, 0x01, 0x49, 0x92, + 0x14, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x08, 0x69, 0x22, 0x09, 0x49, 0xd2, 0x24, 0x24, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x51, + 0x1a, 0x09, 0x49, 0xa2, 0x44, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x87, 0x08, 0x00, 0x00, 0x00, + 0xf2, 0xf0, 0xf0, 0xf0, 0xf0, 0x00, 0xf0, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x40, 0x88, 0x00, 0x00, 0x00, 0x00, 0x09, 0x09, 0x09, 0x09, + 0x09, 0x01, 0x10, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x40, 0x24, 0x80, + 0x88, 0x86, 0x48, 0x04, 0x09, 0x08, 0x01, 0x01, 0x09, 0x01, 0x10, 0x71, + 0x88, 0x66, 0x00, 0x00, 0x00, 0x40, 0x24, 0x80, 0x88, 0x89, 0x48, 0x84, + 0x08, 0x08, 0x01, 0x01, 0x09, 0x01, 0x10, 0x89, 0x88, 0x99, 0x00, 0x00, + 0x00, 0x40, 0x24, 0x80, 0x88, 0x88, 0x88, 0x82, 0xf8, 0xf0, 0xe0, 0x80, + 0xf0, 0xf8, 0x13, 0x81, 0x88, 0x88, 0x00, 0x00, 0x00, 0x40, 0x24, 0x80, + 0x88, 0x88, 0x08, 0x81, 0x08, 0x09, 0x01, 0x41, 0x08, 0x01, 0xf0, 0xf0, + 0x88, 0x88, 0x00, 0x00, 0x00, 0x40, 0x24, 0x80, 0x88, 0x88, 0x88, 0x42, + 0x08, 0x09, 0x01, 0x21, 0x08, 0x01, 0x10, 0x88, 0x88, 0x88, 0x00, 0x00, + 0x00, 0x40, 0x46, 0x88, 0x88, 0x88, 0x4c, 0x44, 0x08, 0x09, 0x09, 0x11, + 0x08, 0x01, 0x10, 0x88, 0x88, 0x88, 0x00, 0x00, 0x00, 0x80, 0x85, 0x87, + 0x88, 0x08, 0x4b, 0x24, 0xf0, 0xf0, 0xf0, 0xf8, 0xf1, 0x00, 0x10, 0x70, + 0x89, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xf8, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, + 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x0f, 0x00, 0x00, + 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0x3f, 0x0f, 0x00, 0x00, 0x08, 0x02, 0x04, 0x00, + 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xff, 0x1f, 0x00, 0x00, 0x48, 0x62, 0xc4, 0x31, 0x4a, 0x18, 0x3c, 0x03, + 0x21, 0x45, 0x92, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x1f, 0x00, 0x00, + 0x48, 0x92, 0x24, 0x48, 0xb6, 0x24, 0x88, 0x04, 0x21, 0x4b, 0x92, 0x00, + 0x00, 0x00, 0x80, 0xff, 0xff, 0x3f, 0x00, 0x00, 0xa8, 0xf2, 0x24, 0x48, + 0x92, 0x3c, 0x88, 0x04, 0x21, 0x49, 0x62, 0x00, 0x00, 0x00, 0x80, 0xff, + 0xff, 0x3f, 0x00, 0x00, 0x10, 0x11, 0x24, 0x48, 0x92, 0x04, 0x88, 0x04, + 0x21, 0x49, 0x62, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x3f, 0x00, 0x00, + 0x10, 0x11, 0x24, 0x48, 0x92, 0x04, 0x88, 0x04, 0x21, 0x49, 0x93, 0x00, + 0x00, 0x00, 0x80, 0xff, 0xcf, 0x7e, 0x00, 0x00, 0x10, 0xe1, 0xc4, 0x31, + 0x92, 0x38, 0x30, 0x03, 0x2f, 0x89, 0x92, 0x00, 0x00, 0x00, 0x80, 0xe3, + 0x07, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc1, 0x03, 0x7e, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0xc9, 0x23, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x95, + 0x33, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xdd, 0xfb, 0x7e, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0x1d, 0xf8, 0x7e, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x40, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x9b, + 0x70, 0x7e, 0x00, 0x00, 0x08, 0x00, 0xe0, 0x00, 0x02, 0x00, 0x47, 0x80, + 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x80, 0x03, 0x00, 0x7e, 0x00, 0x00, + 0x3c, 0xa3, 0x20, 0x31, 0x52, 0x02, 0x49, 0xcc, 0x3f, 0xa3, 0x94, 0x08, + 0x00, 0x00, 0x00, 0x27, 0x02, 0x7e, 0x00, 0x00, 0x88, 0xe4, 0x20, 0x41, + 0xb2, 0x05, 0x49, 0x90, 0x88, 0xe4, 0x6c, 0x09, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x7e, 0x00, 0x00, 0x88, 0x24, 0xe0, 0x70, 0x92, 0x04, 0x47, 0x9c, + 0x88, 0x24, 0x24, 0x09, 0x00, 0x00, 0x00, 0x13, 0x48, 0x7e, 0x00, 0x00, + 0x88, 0x24, 0x20, 0x48, 0x92, 0x04, 0x41, 0x92, 0x88, 0x24, 0x24, 0x01, + 0x00, 0x00, 0x00, 0x43, 0x00, 0xfe, 0x00, 0x00, 0x88, 0x24, 0x20, 0x48, + 0x92, 0x04, 0x41, 0x92, 0x88, 0x24, 0x24, 0x09, 0x00, 0x00, 0x00, 0x07, + 0x94, 0xce, 0x00, 0x00, 0x08, 0x23, 0x20, 0xb0, 0x92, 0x04, 0x41, 0x2c, + 0x0b, 0x23, 0x24, 0x09, 0x00, 0x00, 0x00, 0x49, 0x02, 0xce, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x11, 0x08, 0xdc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, + 0x01, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0xf8, 0x07, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc0, 0x01, 0x00, 0xf8, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, + 0x00, 0xf0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0xf0, 0x1f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x70, 0x00, 0x00, 0xe0, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, + 0x00, 0xe0, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0xe0, 0x7f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x00, 0x00, 0xe0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, + 0x00, 0xc0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0xc0, 0xff, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1f, 0x00, 0x00, 0x80, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, + 0x00, 0x80, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0f, 0x00, 0x00, 0x00, 0xff, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x07, 0x00, 0x00, 0x00, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07, 0x00, + 0x00, 0x00, 0xfe, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x07, 0x00, 0x00, 0x00, 0xfe, 0x0f, + 0x00, 0x00, 0x80, 0x08, 0x00, 0x00, 0x05, 0x00, 0x00, 0x80, 0x08, 0x00, + 0x00, 0xc0, 0x03, 0x00, 0x78, 0x00, 0xfe, 0x0f, 0x00, 0x00, 0x40, 0x10, + 0x12, 0x10, 0x05, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, + 0x84, 0x00, 0xfe, 0x0f, 0x00, 0x00, 0x20, 0x26, 0x0a, 0x10, 0x9d, 0x39, + 0xa6, 0xb2, 0x0a, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x02, 0x00, 0xfe, 0x0f, + 0x00, 0x00, 0x20, 0x21, 0x06, 0x28, 0x25, 0x4a, 0xa9, 0x8a, 0x09, 0x00, + 0x00, 0xe0, 0x01, 0x22, 0x02, 0x00, 0xfc, 0x1f, 0x00, 0x00, 0x20, 0x21, + 0x0e, 0x38, 0xa5, 0x4b, 0xa9, 0xb2, 0x09, 0x00, 0x00, 0xf0, 0x01, 0x22, + 0x02, 0x00, 0xfc, 0x1f, 0x00, 0x00, 0x20, 0x21, 0x12, 0x44, 0xa5, 0x4a, + 0x49, 0xa1, 0x0a, 0x00, 0x00, 0xf8, 0x01, 0x22, 0x02, 0x00, 0xfc, 0x1f, + 0x00, 0x00, 0x20, 0x26, 0x52, 0x44, 0x9d, 0x4d, 0x46, 0x99, 0x0a, 0x00, + 0x00, 0xfc, 0x01, 0x22, 0x02, 0x00, 0xfc, 0x1f, 0x00, 0x00, 0x40, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x01, 0xb2, + 0x84, 0x00, 0xfc, 0x1f, 0x00, 0x00, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x01, 0x6e, 0x78, 0x00, 0xfc, 0x1f, + 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xfc, 0x01, 0x02, 0x00, 0x00, 0xfc, 0x1f, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x01, 0x02, + 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x06, 0x00, 0x00, 0xfc, 0x0f, + 0x00, 0x00, 0x80, 0x08, 0x00, 0x00, 0x20, 0x01, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x24, 0x06, 0x00, 0x00, 0x00, 0xfc, 0x07, 0x00, 0x00, 0x40, 0x10, + 0x1e, 0x20, 0x90, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, + 0x00, 0x80, 0xfc, 0x03, 0x00, 0x00, 0x20, 0x26, 0x22, 0x20, 0xf9, 0x89, + 0x32, 0xe7, 0x08, 0x00, 0x00, 0x92, 0x38, 0x00, 0x00, 0x00, 0xfc, 0x01, + 0x00, 0x00, 0x20, 0x21, 0x22, 0xa0, 0x92, 0x88, 0x4a, 0x29, 0x15, 0x00, + 0x00, 0x00, 0x78, 0x00, 0x00, 0x40, 0xfa, 0x04, 0x00, 0x00, 0x20, 0x21, + 0x22, 0xa0, 0x93, 0x88, 0x4a, 0x29, 0x1d, 0x00, 0x00, 0x11, 0xf2, 0x00, + 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x20, 0x21, 0x22, 0xa8, 0x90, 0x88, + 0x4a, 0x29, 0x05, 0x00, 0x48, 0x40, 0xf0, 0x01, 0x00, 0x80, 0x14, 0x04, + 0x00, 0x00, 0x20, 0x26, 0x9e, 0x10, 0x93, 0x78, 0x32, 0x29, 0x19, 0x00, + 0x00, 0x09, 0xe0, 0x03, 0x00, 0x00, 0x80, 0x10, 0x00, 0x00, 0x40, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0xc5, 0x03, + 0x00, 0x40, 0x22, 0x00, 0x00, 0x00, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x40, 0x04, 0xc0, 0x07, 0x00, 0x20, 0x08, 0x04, + 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x50, 0x90, 0x03, 0x00, 0xb0, 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, + 0x00, 0x38, 0x22, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x48, 0x04, 0x44, 0x00, 0x00, 0x3c, 0x08, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x20, 0x00, 0x00, 0x00, 0xbf, 0x40, 0x42, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x00, 0x00, 0x24, 0x80, 0x48, 0x02, + 0xc0, 0x1f, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4e, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x05, 0xf0, 0x3f, 0x09, 0x00, + 0x00, 0x10, 0x24, 0x48, 0x10, 0x12, 0x41, 0x52, 0x24, 0x09, 0x46, 0x71, + 0x90, 0x20, 0x02, 0xfc, 0xff, 0x1f, 0x80, 0x22, 0x00, 0x90, 0x24, 0x49, + 0x12, 0x92, 0x40, 0xb2, 0x24, 0x09, 0xc9, 0x49, 0x04, 0x80, 0x90, 0xfc, + 0xff, 0xbf, 0x24, 0x00, 0x00, 0x90, 0x24, 0x49, 0x12, 0x92, 0x40, 0x92, + 0x24, 0x06, 0x49, 0x48, 0x50, 0x0a, 0x02, 0xfe, 0xff, 0x3f, 0x00, 0x05, + 0x00, 0x50, 0xa5, 0x4a, 0x15, 0x92, 0x40, 0x92, 0x24, 0x06, 0x49, 0x48, + 0x80, 0x40, 0x48, 0xfe, 0xff, 0x3f, 0x49, 0x00, 0x00, 0x20, 0x42, 0x84, + 0x88, 0x1a, 0x41, 0x92, 0x34, 0x49, 0x49, 0x68, 0x00, 0x38, 0x10, 0x07, + 0x00, 0x60, 0x80, 0x00, 0x00, 0x20, 0x42, 0x84, 0x88, 0x14, 0x4e, 0x92, + 0x28, 0x49, 0x46, 0x50, 0x00, 0x80, 0x83, 0x01, 0x00, 0xa0, 0x6a, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0xfc, 0x00, 0x00, 0xc0, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, }; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/68328/bootlogo.pl linux.2.5.45-ac1/arch/m68knommu/platform/68328/bootlogo.pl --- linux.2.5.45/arch/m68knommu/platform/68328/bootlogo.pl 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/68328/bootlogo.pl 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,10 @@ + +$_ = join("", <>); + +s/(0x[0-9a-f]{2})/sprintf("0x%.2x",ord(pack("b8",unpack("B8",chr(hex($1))))))/gei; + +s/^ / .byte /gm; +s/[,};]+$//gm; +s/^static.*//gm; + +print $_; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/68328/config.c linux.2.5.45-ac1/arch/m68knommu/platform/68328/config.c --- linux.2.5.45/arch/m68knommu/platform/68328/config.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/68328/config.c 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,127 @@ +/* + * linux/arch/$(ARCH)/platform/$(PLATFORM)/config.c + * + * Copyright (C) 1993 Hamish Macdonald + * Copyright (C) 1999 D. Jeff Dionne + * + * 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. + * + * VZ Support/Fixes Evan Stawnyczy + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + +void BSP_sched_init(void (*timer_routine)(int, void *, struct pt_regs *)) +{ + +#ifdef CONFIG_XCOPILOT_BUGS + /* + * The only thing I know is that CLK32 is not available on Xcopilot + * I have little idea about what frequency SYSCLK has on Xcopilot. + * The values for prescaler and compare registers were simply + * taken from the original source + */ + + /* Restart mode, Enable int, SYSCLK, Enable timer */ + TCTL2 = TCTL_OM | TCTL_IRQEN | TCTL_CLKSOURCE_SYSCLK | TCTL_TEN; + /* Set prescaler */ + TPRER2 = 2; + /* Set compare register */ + TCMP2 = 0xd7e4; +#else + /* Restart mode, Enable int, 32KHz, Enable timer */ + TCTL2 = TCTL_OM | TCTL_IRQEN | TCTL_CLKSOURCE_32KHZ | TCTL_TEN; + /* Set prescaler (Divide 32KHz by 32)*/ + TPRER2 = 31; + /* Set compare register 32Khz / 32 / 10 = 100 */ + TCMP2 = 10; +#endif + + request_irq(TMR2_IRQ_NUM, timer_routine, IRQ_FLG_LOCK, "timer", NULL); +} + +void BSP_tick(void) +{ + /* Reset Timer2 */ + TSTAT2 &= 0; +} + +unsigned long BSP_gettimeoffset (void) +{ + return 0; +} + +void BSP_gettod (int *yearp, int *monp, int *dayp, + int *hourp, int *minp, int *secp) +{ +} + +int BSP_hwclk(int op, struct hwclk_time *t) +{ + if (!op) { + /* read */ + } else { + /* write */ + } + return 0; +} + +int BSP_set_clock_mmss (unsigned long nowtime) +{ +#if 0 + short real_seconds = nowtime % 60, real_minutes = (nowtime / 60) % 60; + + tod->second1 = real_seconds / 10; + tod->second2 = real_seconds % 10; + tod->minute1 = real_minutes / 10; + tod->minute2 = real_minutes % 10; +#endif + return 0; +} + +void BSP_reset (void) +{ + local_irq_disable(); + asm volatile (" + moveal #0x10c00000, %a0; + moveb #0, 0xFFFFF300; + moveal 0(%a0), %sp; + moveal 4(%a0), %a0; + jmp (%a0); + "); +} + +void config_BSP(char *command, int len) +{ + printk("\n68328 support D. Jeff Dionne \n"); + printk("68328 support Kenneth Albanowski \n"); + printk("68328/Pilot support Bernhard Kuhn \n"); + + mach_sched_init = BSP_sched_init; + mach_tick = BSP_tick; + mach_gettimeoffset = BSP_gettimeoffset; + mach_gettod = BSP_gettod; + mach_hwclk = NULL; + mach_set_clock_mmss = NULL; + mach_reset = BSP_reset; + + config_M68328_irq(); +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/68328/entry.S linux.2.5.45-ac1/arch/m68knommu/platform/68328/entry.S --- linux.2.5.45/arch/m68knommu/platform/68328/entry.S 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/68328/entry.S 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,483 @@ +/* -*- mode: asm -*- + * + * linux/arch/m68k/kernel/entry.S + * + * Copyright (C) 1991, 1992 Linus Torvalds + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file README.legal in the main directory of this archive + * for more details. + * + * Linux/m68k support by Hamish Macdonald + * + */ + +/* + * entry.S contains the system-call and fault low-level handling routines. + * This also contains the timer-interrupt handler, as well as all interrupts + * and faults that can result in a task-switch. + * + * NOTE: This code handles signal-recognition, which happens every time + * after a timer-interrupt and after each system call. + * + */ + +/* + * 12/03/96 Jes: Currently we only support m68k single-cpu systems, so + * all pointers that used to be 'current' are now entry + * number 0 in the 'current_set' list. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define IMMED # +#define DBG_PUTC(x) moveb IMMED x,0xfffff907; \ + moveb IMMED '\r',0xfffff907; \ + moveb IMMED '\n',0xfffff907 + +.globl system_call, buserr, trap +.globl resume, ret_from_exception +.globl ret_from_signal +.globl sys_call_table +.globl sys_fork, sys_clone, sys_vfork +.globl ret_from_interrupt, bad_interrupt +.globl inthandler1, inthandler2, inthandler3, inthandler4 +.globl inthandler5, inthandler6, inthandler7 + +.text +ENTRY(buserr) + SAVE_ALL_INT + GET_CURRENT(%d0) + movel %sp,%sp@- /* stack frame pointer argument*/ + bsrw buserr_c + addql #4,%sp + jra ret_from_exception + +ENTRY(trap) + SAVE_ALL_INT + GET_CURRENT(%d0) + movel %sp,%sp@- /* stack frame pointer argument*/ + bsrw trap_c + addql #4,%sp + jra ret_from_exception + +ENTRY(reschedule) + /* save top of frame*/ + pea %sp@ + jbsr set_esp0 + addql #4,%sp + + pea ret_from_exception + jmp schedule + + /* After a fork we jump here directly from resume,*/ + /* so that %d1 contains the previous task*/ + /* Theoretically only needed on SMP, but let's watch*/ + /* what happens in schedule_tail() in future...*/ +ENTRY(ret_from_fork) +#ifdef CONFIG_SMP + movel %d1,%sp@- + jsr schedule_tail + addql #4,%sp +#endif + jra ret_from_exception + +badsys: + movel #-ENOSYS,%sp@(PT_D0) + jra ret_from_exception + +do_trace: + movel #-ENOSYS,%sp@(PT_D0) /* needed for strace*/ + subql #4,%sp + SAVE_SWITCH_STACK + jbsr syscall_trace + RESTORE_SWITCH_STACK + addql #4,%sp + movel %sp@(PT_ORIG_D0),%d1 + movel #-ENOSYS,%d0 + cmpl #NR_syscalls,%d1 + jcc 1f + lsl #2,%d1 + lea sys_call_table, %a0 + jbsr %a0@(%d1) + +1: movel %d0,%sp@(PT_D0) /* save the return value*/ + subql #4,%sp /* dummy return address*/ + SAVE_SWITCH_STACK + jbsr syscall_trace + +ret_from_signal: + RESTORE_SWITCH_STACK + addql #4,%sp + jra ret_from_exception + +ENTRY(system_call) + SAVE_ALL_SYS + + GET_CURRENT(%d1) + /* save top of frame*/ + pea %sp@ + jbsr set_esp0 + addql #4,%sp + + btst #PF_TRACESYS_BIT,%a2@(TASK_FLAGS+PF_TRACESYS_OFF) + jne do_trace + cmpl #NR_syscalls,%d0 + jcc badsys + lsl #2,%d0 + lea sys_call_table,%a0 + movel %a0@(%d0), %a0 + jbsr %a0@ + movel %d0,%sp@(PT_D0) /* save the return value*/ + +ret_from_exception: + btst #5,%sp@(PT_SR) /* check if returning to kernel*/ + jeq Luser_return /* if so, skip resched, signals*/ + +Lkernel_return: + RESTORE_ALL + +Luser_return: + /* only allow interrupts when we are really the last one on the*/ + /* kernel stack, otherwise stack overflow can occur during*/ + /* heavy interupt load*/ + andw #ALLOWINT,%sr + + movel %sp,%d1 /* get thread_info pointer */ + andl #0xffffe000,%d1 + movel %d1,%a2 + move %a2@(TI_FLAGS),%d1 /* thread_info->flags */ + andl #_TIF_WORK_MASK,%d1 + jne Lwork_to_do + RESTORE_ALL + +Lwork_to_do: + movel %a2@(TI_FLAGS),%d1 /* thread_info->flags */ + btst #TIF_NEED_RESCHED,%d1 + jne reschedule + +Lsignal_return: + subql #4,%sp /* dummy return address*/ + SAVE_SWITCH_STACK + pea %sp@(SWITCH_STACK_SIZE) + clrl %sp@- + bsrw do_signal + addql #8,%sp + RESTORE_SWITCH_STACK + addql #4,%sp +Lreturn: + RESTORE_ALL + +/* +** This is the main interrupt handler, responsible for calling process_int() +*/ +inthandler1: + SAVE_ALL_INT + GET_CURRENT(%d0) + addql #1,local_irq_count /* put exception # in d0*/ +/* bfextu %sp@(PT_VECTOR){#4,#10},%d0 */ + movew %sp@(PT_VECTOR), %d0 + and #0x3ff, %d0 + + movel %sp,%sp@- + movel #65,%sp@- /* put vector # on stack*/ + jbsr process_int /* process the IRQ*/ +3: addql #8,%sp /* pop parameters off stack*/ + bra ret_from_interrupt + +inthandler2: + SAVE_ALL_INT + GET_CURRENT(%d0) + addql #1,local_irq_count /* put exception # in d0*/ +/* bfextu %sp@(PT_VECTOR){#4,#10},%d0 */ + movew %sp@(PT_VECTOR), %d0 + and #0x3ff, %d0 + + movel %sp,%sp@- + movel #66,%sp@- /* put vector # on stack*/ + jbsr process_int /* process the IRQ*/ +3: addql #8,%sp /* pop parameters off stack*/ + bra ret_from_interrupt + +inthandler3: + SAVE_ALL_INT + GET_CURRENT(%d0) + addql #1,local_irq_count /* put exception # in d0*/ +/* bfextu %sp@(PT_VECTOR){#4,#10},%d0 */ + movew %sp@(PT_VECTOR), %d0 + and #0x3ff, %d0 + + movel %sp,%sp@- + movel #67,%sp@- /* put vector # on stack*/ + jbsr process_int /* process the IRQ*/ +3: addql #8,%sp /* pop parameters off stack*/ + bra ret_from_interrupt + +inthandler4: + SAVE_ALL_INT + GET_CURRENT(%d0) + addql #1,local_irq_count /* put exception # in d0*/ +/* bfextu %sp@(PT_VECTOR){#4,#10},%d0 */ + movew %sp@(PT_VECTOR), %d0 + and #0x3ff, %d0 + + movel %sp,%sp@- + movel #68,%sp@- /* put vector # on stack*/ + jbsr process_int /* process the IRQ*/ +3: addql #8,%sp /* pop parameters off stack*/ + bra ret_from_interrupt + +inthandler5: + SAVE_ALL_INT + GET_CURRENT(%d0) + addql #1,local_irq_count /* put exception # in d0*/ +/* bfextu %sp@(PT_VECTOR){#4,#10},%d0 */ + movew %sp@(PT_VECTOR), %d0 + and #0x3ff, %d0 + + movel %sp,%sp@- + movel #69,%sp@- /* put vector # on stack*/ + jbsr process_int /* process the IRQ*/ +3: addql #8,%sp /* pop parameters off stack*/ + bra ret_from_interrupt + +inthandler6: + SAVE_ALL_INT + GET_CURRENT(%d0) + addql #1,local_irq_count /* put exception # in d0*/ +/* bfextu %sp@(PT_VECTOR){#4,#10},%d0 */ + movew %sp@(PT_VECTOR), %d0 + and #0x3ff, %d0 + + movel %sp,%sp@- + movel #70,%sp@- /* put vector # on stack*/ + jbsr process_int /* process the IRQ*/ +3: addql #8,%sp /* pop parameters off stack*/ + bra ret_from_interrupt + +inthandler7: + SAVE_ALL_INT + GET_CURRENT(%d0) + addql #1,local_irq_count /* put exception # in d0*/ +/* bfextu %sp@(PT_VECTOR){#4,#10},%d0 */ + movew %sp@(PT_VECTOR), %d0 + and #0x3ff, %d0 + + movel %sp,%sp@- + movel #71,%sp@- /* put vector # on stack*/ + jbsr process_int /* process the IRQ*/ +3: addql #8,%sp /* pop parameters off stack*/ + bra ret_from_interrupt + +inthandler8: + SAVE_ALL_INT + GET_CURRENT(%d0) + addql #1,local_irq_count /* put exception # in d0*/ +/* bfextu %sp@(PT_VECTOR){#4,#10},%d0 */ + movew %sp@(PT_VECTOR), %d0 + and #0x3ff, %d0 + + movel %sp,%sp@- + movel #72,%sp@- /* put vector # on stack*/ + jbsr process_int /* process the IRQ*/ +3: addql #8,%sp /* pop parameters off stack*/ + bra ret_from_interrupt + +timerhandler: + SAVE_ALL_INT + GET_CURRENT(%d0) + addql #1,local_irq_count /* put exception # in d0*/ +/* bfextu %sp@(PT_VECTOR){#4,#10},%d0 */ + movew %sp@(PT_VECTOR), %d0 + and #0x3ff, %d0 + + movel %sp,%sp@- + movel #0x40,%sp@- /* put vector # on stack*/ + jbsr process_int /* process the IRQ*/ +3: addql #8,%sp /* pop parameters off stack*/ + bra ret_from_interrupt + +serialhandler: + SAVE_ALL_INT + GET_CURRENT(%d0) + addql #1,local_irq_count /* put exception # in d0*/ +/* bfextu %sp@(PT_VECTOR){#4,#10},%d0 */ + movew %sp@(PT_VECTOR), %d0 + and #0x3ff, %d0 + + movel %sp,%sp@- + movel #0x42,%sp@- /* put vector # on stack*/ + jbsr process_int /* process the IRQ*/ +3: addql #8,%sp /* pop parameters off stack*/ + bra ret_from_interrupt + +inthandler_wrap: + SAVE_ALL_INT + GET_CURRENT(%d0) + addql #1,local_irq_count /* put exception # in d0*/ +/* bfextu %sp@(PT_VECTOR){#4,#10},%d0 */ + movew %sp@(PT_VECTOR), %d0 + and #0x3ff, %d0 + + movel %sp,%sp@- + movel %d0,%sp@- /* put vector # on stack*/ + jbsr process_int /* process the IRQ*/ +3: addql #8,%sp /* pop parameters off stack*/ + bra ret_from_interrupt + +inthandler: + SAVE_ALL_INT + GET_CURRENT(%d0) + addql #1,local_irq_count /* put exception # in d0*/ +/* bfextu %sp@(PT_VECTOR){#4,#10},%d0 */ + movew %sp@(PT_VECTOR), %d0 + and #0x3ff, %d0 + + movel %sp,%sp@- + movel %d0,%sp@- /* put vector # on stack*/ + jbsr process_int /* process the IRQ*/ +3: addql #8,%sp /* pop parameters off stack*/ + bra ret_from_interrupt + +ret_from_interrupt: + subql #1,local_irq_count + jeq 1f +2: + RESTORE_ALL +1: +#if 1 +/* bfextu %sp@(PT_SR){#5,#3},%d0 */ /* Check for nested interrupt.*/ + moveb %sp@(PT_SR), %d0 + and #7, %d0 + +#if MAX_NOINT_IPL > 0 + cmpiw #MAX_NOINT_IPL,%d0 +#endif + jhi 2b +#endif + /* check if we need to do software interrupts */ + + movel local_irq_count,%d0 + jeq ret_from_exception + + pea ret_from_exception + jra do_softirq + + +/* Handler for uninitialized and spurious interrupts */ + +bad_interrupt: + addql #1,num_spurious + rte + +ENTRY(sys_fork) + SAVE_SWITCH_STACK + pea %sp@(SWITCH_STACK_SIZE) + jbsr m68k_fork + addql #4,%sp + RESTORE_SWITCH_STACK + rts + +ENTRY(sys_clone) + SAVE_SWITCH_STACK + pea %sp@(SWITCH_STACK_SIZE) + jbsr m68k_clone + addql #4,%sp + RESTORE_SWITCH_STACK + rts + +ENTRY(sys_vfork) + SAVE_SWITCH_STACK + pea %sp@(SWITCH_STACK_SIZE) + jbsr m68k_vfork + addql #4,%sp + RESTORE_SWITCH_STACK + rts + +ENTRY(sys_sigsuspend) + SAVE_SWITCH_STACK + pea %sp@(SWITCH_STACK_SIZE) + jbsr do_sigsuspend + addql #4,%sp + RESTORE_SWITCH_STACK + rts + +ENTRY(sys_rt_sigsuspend) + SAVE_SWITCH_STACK + pea %sp@(SWITCH_STACK_SIZE) + jbsr do_rt_sigsuspend + addql #4,%sp + RESTORE_SWITCH_STACK + rts + +ENTRY(sys_sigreturn) + SAVE_SWITCH_STACK + jbsr do_sigreturn + RESTORE_SWITCH_STACK + rts + +ENTRY(sys_rt_sigreturn) + SAVE_SWITCH_STACK + jbsr do_rt_sigreturn + RESTORE_SWITCH_STACK + rts + +resume: + /* + * Beware - when entering resume, prev (the current task) is + * in a0, next (the new task) is in a1,so don't change these + * registers until their contents are no longer needed. + */ + + /* save prev thread in d1 */ + movel %a0,%d1 + + /* save sr */ + movew %sr,%a0@(TASK_THREAD+THREAD_SR) +#ifdef USE_SFC_DFC + /* save fs (sfc,%dfc) (may be pointing to kernel memory) */ + movec %sfc,%d0 + movew %d0,%a0@(TASK_THREAD+THREAD_FS) +#endif + + /* save non-scratch registers on stack */ + SAVE_SWITCH_STACK + + /* save usp */ + /* it is better to use a movel here instead of a movew 8*) */ + movel %usp,%a2 + movel %a2,%a0@(TASK_THREAD+THREAD_USP) + + /* save current kernel stack pointer */ + movel %sp,%a0@(TASK_THREAD+THREAD_KSP) + + /* restore the kernel stack pointer */ + movel %a1@(TASK_THREAD+THREAD_KSP),%sp + + /* restore non-scratch registers */ + RESTORE_SWITCH_STACK + + /* restore user stack pointer */ + movel %a1@(TASK_THREAD+THREAD_USP),%a0 + movel %a0,%usp + +#ifdef USE_SFC_DFC + /* restore fs (sfc,%dfc) */ + movew %a1@(TASK_THREAD+THREAD_FS),%a0 + movec %a0,%sfc + movec %a0,%dfc +#endif + /* restore status register */ + movew %a1@(TASK_THREAD+THREAD_SR),%sr + + rts + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/68328/ints.c linux.2.5.45-ac1/arch/m68knommu/platform/68328/ints.c --- linux.2.5.45/arch/m68knommu/platform/68328/ints.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/68328/ints.c 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,354 @@ +/* + * linux/arch/m68knommu/platform/68328/ints.c + * + * 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 1996 Roman Zippel + * Copyright 1999 D. Jeff Dionne + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#if defined(CONFIG_M68328) +#include +#elif defined(CONFIG_M68EZ328) +#include +#elif defined(CONFIG_M68VZ328) +#include +#endif + +#define INTERNAL_IRQS (32) + +/* assembler routines */ +asmlinkage void system_call(void); +asmlinkage void buserr(void); +asmlinkage void trap(void); +asmlinkage void trap3(void); +asmlinkage void trap4(void); +asmlinkage void trap5(void); +asmlinkage void trap6(void); +asmlinkage void trap7(void); +asmlinkage void trap8(void); +asmlinkage void trap9(void); +asmlinkage void trap10(void); +asmlinkage void trap11(void); +asmlinkage void trap12(void); +asmlinkage void trap13(void); +asmlinkage void trap14(void); +asmlinkage void trap15(void); +asmlinkage void trap33(void); +asmlinkage void trap34(void); +asmlinkage void trap35(void); +asmlinkage void trap36(void); +asmlinkage void trap37(void); +asmlinkage void trap38(void); +asmlinkage void trap39(void); +asmlinkage void trap40(void); +asmlinkage void trap41(void); +asmlinkage void trap42(void); +asmlinkage void trap43(void); +asmlinkage void trap44(void); +asmlinkage void trap45(void); +asmlinkage void trap46(void); +asmlinkage void trap47(void); +asmlinkage void bad_interrupt(void); +asmlinkage void inthandler(void); +asmlinkage void inthandler1(void); +asmlinkage void inthandler2(void); +asmlinkage void inthandler3(void); +asmlinkage void inthandler4(void); +asmlinkage void inthandler5(void); +asmlinkage void inthandler6(void); +asmlinkage void inthandler7(void); + +extern e_vector *_ramvec; + +/* irq node variables for the 32 (potential) on chip sources */ +static irq_node_t *int_irq_list[INTERNAL_IRQS]; + +static int int_irq_count[INTERNAL_IRQS]; +static short int_irq_ablecount[INTERNAL_IRQS]; + +static void int_badint(int irq, void *dev_id, struct pt_regs *fp) +{ + num_spurious += 1; +} + +/* + * This function should be called during kernel startup to initialize + * the amiga IRQ handling routines. + */ +void M68328_init_IRQ(void) +{ + int i; + + /* set up the vectors */ + +#ifdef CONFIG_DRAGON2 + for (i=2; i < 32; ++i) + _ramvec[i] = bad_interrupt; + + _ramvec[2] = buserr; + _ramvec[3] = trap3; + _ramvec[4] = trap4; + _ramvec[5] = trap5; + _ramvec[6] = trap6; + _ramvec[7] = trap7; + _ramvec[8] = trap8; + _ramvec[9] = trap9; + _ramvec[10] = trap10; + _ramvec[11] = trap11; + _ramvec[12] = trap12; + _ramvec[13] = trap13; + _ramvec[14] = trap14; + _ramvec[15] = trap15; +#endif + + _ramvec[32] = system_call; + + _ramvec[64] = bad_interrupt; + _ramvec[65] = inthandler1; + _ramvec[66] = inthandler2; + _ramvec[67] = inthandler3; + _ramvec[68] = inthandler4; + _ramvec[69] = inthandler5; + _ramvec[70] = inthandler6; + _ramvec[71] = inthandler7; + + IVR = 0x40; /* Set DragonBall IVR (interrupt base) to 64 */ + + /* initialize handlers */ + for (i = 0; i < INTERNAL_IRQS; i++) { + int_irq_list[i] = NULL; + + int_irq_ablecount[i] = 0; + int_irq_count[i] = 0; + } + + /* turn off all interrupts */ + IMR = ~0; +} + +void M68328_insert_irq(irq_node_t **list, irq_node_t *node) +{ + unsigned long flags; + irq_node_t *cur; + + if (!node->dev_id) + printk("%s: Warning: dev_id of %s is zero\n", + __FUNCTION__, node->devname); + + local_irq_save(flags); + + cur = *list; + while (cur) { + list = &cur->next; + cur = cur->next; + } + + node->next = cur; + *list = node; + + local_irq_restore(flags); +} + +void M68328_delete_irq(irq_node_t **list, void *dev_id) +{ + unsigned long flags; + irq_node_t *node; + + local_irq_save(flags); + + for (node = *list; node; list = &node->next, node = *list) { + if (node->dev_id == dev_id) { + *list = node->next; + /* Mark it as free. */ + node->handler = NULL; + local_irq_restore(flags); + return; + } + } + local_irq_restore(flags); + printk("%s: tried to remove invalid irq\n", __FUNCTION__); +} + +int M68328_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), + unsigned long flags, const char *devname, void *dev_id) +{ + if (irq >= INTERNAL_IRQS) { + printk ("%s: Unknown IRQ %d from %s\n", __FUNCTION__, irq, devname); + return -ENXIO; + } + + if (!int_irq_list[irq]) { + int_irq_list[irq] = new_irq_node(); + int_irq_list[irq]->flags = IRQ_FLG_STD; + } + + if (!(int_irq_list[irq]->flags & IRQ_FLG_STD)) { + if (int_irq_list[irq]->flags & IRQ_FLG_LOCK) { + printk("%s: IRQ %d from %s is not replaceable\n", + __FUNCTION__, irq, int_irq_list[irq]->devname); + return -EBUSY; + } + if (flags & IRQ_FLG_REPLACE) { + printk("%s: %s can't replace IRQ %d from %s\n", + __FUNCTION__, devname, irq, int_irq_list[irq]->devname); + return -EBUSY; + } + } + int_irq_list[irq]->handler = handler; + int_irq_list[irq]->flags = flags; + int_irq_list[irq]->dev_id = dev_id; + int_irq_list[irq]->devname = devname; + + /* enable in the IMR */ + if (!int_irq_ablecount[irq]) + IMR &= ~(1<= INTERNAL_IRQS) { + printk ("%s: Unknown IRQ %d\n", __FUNCTION__, irq); + return; + } + + if (int_irq_list[irq]->dev_id != dev_id) + printk("%s: removing probably wrong IRQ %d from %s\n", + __FUNCTION__, irq, int_irq_list[irq]->devname); + int_irq_list[irq]->handler = int_badint; + int_irq_list[irq]->flags = IRQ_FLG_STD; + int_irq_list[irq]->dev_id = NULL; + int_irq_list[irq]->devname = NULL; + + IMR |= 1<= INTERNAL_IRQS) { + printk("%s: Unknown IRQ %d\n", __FUNCTION__, irq); + return; + } + + if (--int_irq_ablecount[irq]) + return; + + /* enable the interrupt */ + IMR &= ~(1<= INTERNAL_IRQS) { + printk("%s: Unknown IRQ %d\n", __FUNCTION__, irq); + return; + } + + if (int_irq_ablecount[irq]++) + return; + + /* disable the interrupt */ + IMR |= 1<handler) { + int_irq_list[irq]->handler(irq, int_irq_list[irq]->dev_id, fp); + int_irq_count[irq]++; + } else { + printk("unregistered interrupt %d!\nTurning it off in the IMR...\n", irq); + IMR |= mask; + } + pend &= ~mask; + } +} + +void config_M68328_irq(void) +{ + mach_default_handler = NULL; + mach_init_IRQ = M68328_init_IRQ; + mach_request_irq = M68328_request_irq; + mach_free_irq = M68328_free_irq; + mach_enable_irq = M68328_enable_irq; + mach_disable_irq = M68328_disable_irq; + mach_process_int = M68328_do_irq; +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/68328/Makefile linux.2.5.45-ac1/arch/m68knommu/platform/68328/Makefile --- linux.2.5.45/arch/m68knommu/platform/68328/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/68328/Makefile 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,17 @@ +# +# Makefile for arch/m68knommu/platform/68328. +# + +obj-$(CONFIG_M68328) += entry.o ints.o config.o +obj-$(CONFIG_M68EZ328) += entry.o ints.o +obj-$(CONFIG_M68VZ328) += entry.o ints.o + +ifeq ($(CONFIG_M68328),y) +EXTRA_TARGETS := $(BOARD)/bootlogo.rh $(BOARD/crt0_$(MODEL).o +endif + +include $(TOPDIR)/Rules.make + +$(obj)/$(BOARD)/bootlogo.rh: $(src)/bootlogo.h + perl $(src)/bootlogo.pl < $(src)/bootlogo.h > $(obj)/$(BOARD)/bootlogo.rh + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/68328/pilot/crt0_rom.S linux.2.5.45-ac1/arch/m68knommu/platform/68328/pilot/crt0_rom.S --- linux.2.5.45/arch/m68knommu/platform/68328/pilot/crt0_rom.S 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/68328/pilot/crt0_rom.S 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,228 @@ +/* linux/arch/m68knommu/kernel/head.S: A startup file for the MC68332 + * + * Copyright (C) 1998 D. Jeff Dionne , + * Kenneth Albanowski , + * The Silver Hammer Group, Ltd. + * + * (c) 1995, Dionne & Associates + * (c) 1995, DKG Display Tech. + */ + +#define ASSEMBLY + +#define IMMED # +#define DBG_PUTC(x) moveb IMMED x, 0xfffff907 + +#include + +.global _stext +.global __bss_start + +.global _start + +.global _rambase +.global __ramvec +.global _ramvec +.global _ramstart +.global _ramend + +.global penguin_bits + +#ifdef CONFIG_PILOT + +#define IMR 0xFFFFF304 + + .data + .align 16 + +penguin_bits: +#include "bootlogo.rh" + +#endif + +/*****************************************************************************/ + +.data + +/* + * Set up the usable of RAM stuff. Size of RAM is determined then + * an initial stack set up at the end. + */ +.align 4 +_ramvec: +.long 0 +_rambase: +.long 0 +_ramstart: +.long 0 +_ramend: +.long 0 + +.text + +_start: +_stext: + + +#ifdef CONFIG_M68328 + +#ifdef CONFIG_PILOT + .byte 0x4e, 0xfa, 0x00, 0x0a /* Jmp +X bytes */ + .byte 'b', 'o', 'o', 't' + .word 10000 + + nop +#endif + + moveq #0, %d0 + movew %d0, 0xfffff618 /* Watchdog off */ + movel #0x00011f07, 0xfffff114 /* CS A1 Mask */ + + movew #0x0800, 0xfffff906 /* Ignore CTS */ + movew #0x010b, 0xfffff902 /* BAUD to 9600 */ + + movew #0x2410, 0xfffff200 /* PLLCR */ + movew #0x123, 0xfffff202 /* PLLFSR */ + +#ifdef CONFIG_PILOT + moveb #0, 0xfffffA27 /* LCKCON */ + movel #_start, 0xfffffA00 /* LSSA */ + moveb #0xa, 0xfffffA05 /* LVPW */ + movew #0x9f, 0xFFFFFa08 /* LXMAX */ + movew #0x9f, 0xFFFFFa0a /* LYMAX */ + moveb #9, 0xfffffa29 /* LBAR */ + moveb #0, 0xfffffa25 /* LPXCD */ + moveb #0x04, 0xFFFFFa20 /* LPICF */ + moveb #0x58, 0xfffffA27 /* LCKCON */ + moveb #0x85, 0xfffff429 /* PFDATA */ + moveb #0xd8, 0xfffffA27 /* LCKCON */ + moveb #0xc5, 0xfffff429 /* PFDATA */ + moveb #0xd5, 0xfffff429 /* PFDATA */ + + moveal #0x00100000, %a3 + moveal #0x100ffc00, %a4 + +#endif /* CONFIG_PILOT */ + + +#endif /* CONFIG_M68328 */ + + movew #0x2700, %sr + lea %a4@(-4), %sp + + DBG_PUTC('\r') + DBG_PUTC('\n') + DBG_PUTC('A') + + moveq #0,%d0 + movew #16384, %d0 /* PLL settle wait loop */ +L0: + subw #1, %d0 + bne L0 + + DBG_PUTC('B') + + /* Copy command line from beginning of RAM (+16) to end of bss */ + movel #__ramvec, %d7 + addl #16, %d7 + moveal %d7, %a0 + moveal #end, %a1 + lea %a1@(512), %a2 + + DBG_PUTC('C') + + /* Copy %a0 to %a1 until %a1 == %a2 */ +L2: + movel %a0@+, %d0 + movel %d0, %a1@+ + cmpal %a1, %a2 + bhi L2 + + /* Copy data segment from ROM to RAM */ + moveal #__data_rom_start, %a0 + moveal #__data_start, %a1 + moveal #__data_end, %a2 + + DBG_PUTC('D') + + /* Copy %a0 to %a1 until %a1 == %a2 */ +LD1: + movel %a0@+, %d0 + movel %d0, %a1@+ + cmpal %a1, %a2 + bhi LD1 + + DBG_PUTC('E') + + moveal #__bss_start, %a0 + moveal #end, %a1 + + /* Copy 0 to %a0 until %a0 == %a1 */ +L1: + movel #0, %a0@+ + cmpal %a0, %a1 + bhi L1 + + DBG_PUTC('F') + + /* Copy command line from end of bss to command line */ + moveal #end, %a0 + moveal #command_line, %a1 + lea %a1@(512), %a2 + + DBG_PUTC('G') + + /* Copy %a0 to %a1 until %a1 == %a2 */ +L3: + movel %a0@+, %d0 + movel %d0, %a1@+ + cmpal %a1, %a2 + bhi L3 + + movel #_sdata, %d0 + movel %d0, _rambase + movel #end, %d0 + movel %d0, _ramstart + + movel %a4, %d0 + subl #4096, %d0 /* Reserve 4K of stack */ + moveq #79, %d7 + movel %d0, _ramend + + movel %a3, %d0 + movel %d0, rom_length + + pea 0 + pea env + pea %sp@(4) + pea 0 + + DBG_PUTC('H') + +#ifdef CONFIG_PILOT + + movel #penguin_bits, 0xFFFFFA00 + moveb #10, 0xFFFFFA05 + movew #160, 0xFFFFFA08 + movew #160, 0xFFFFFA0A + +#endif /* CONFIG_PILOT */ + + DBG_PUTC('I') + + lea init_thread_union, %a0 + lea 0x2000(%a0), %sp + + DBG_PUTC('J') + DBG_PUTC('\r') + DBG_PUTC('\n') + + jsr start_kernel +_exit: + + jmp _exit + + + .data +env: + .long 0 diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/68328/pilot/rom.ld linux.2.5.45-ac1/arch/m68knommu/platform/68328/pilot/rom.ld --- linux.2.5.45/arch/m68knommu/platform/68328/pilot/rom.ld 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/68328/pilot/rom.ld 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,105 @@ +OUTPUT_ARCH(m68k) +ENTRY(_start) +MEMORY { + romvec : ORIGIN = 0x10c00000, LENGTH = 0x10400 + flash : ORIGIN = 0x10c10400, LENGTH = 0xfec00 + eflash : ORIGIN = 0x10d00000, LENGTH = 4 + ramvec : ORIGIN = 0x00000000, LENGTH = 0x400 + ram : ORIGIN = 0x10000400, LENGTH = 0x100000-0x400 + eram : ORIGIN = 0x10100000, LENGTH = 4 +} + +jiffies = jiffies_64 + 4; + +SECTIONS { + . = 0x10c00000 ; + .romvec : { + _flashstart = . ; + _romvec = . ; + } > romvec + + . = 0x10c10400 ; + .text : { + _text = .; /* Text and read-only data */ + text_start = . ; + *(.text) + *(.text.*) + *(.rodata) + *(.fixup) + *(__ex_table) + . = ALIGN(4) ; + _etext = . ; + __data_rom_start = . ; + } > flash + + . = 0x10d00000 ; + .eflash : + { + _flashend = . ; + } > eflash + + . = 0 ; + .ramvec : + { + __ramvec = . ; + } > ramvec + + /* . = 0x10000400 ; */ + .data 0x10000400 : + { + _sdata = . ; + __data_start = . ; + + . = ALIGN(0x2000) ; + *(.data.init_task) + . = ALIGN(0x2000) ; + + *(.data) + *(.data.*) + *(.setup.init) + *(.exitcall.exit) + + . = ALIGN(4096) ; + __init_begin = .; + *(.init.text) + *(.init.data) + . = ALIGN(16); + __setup_start = .; + *(.init.setup) + __setup_end = .; + __initcall_start = .; + *(.initcall1.init) + *(.initcall2.init) + *(.initcall3.init) + *(.initcall4.init) + *(.initcall5.init) + *(.initcall6.init) + *(.initcall7.init) + __initcall_end = .; + . = ALIGN(4) ; + __init_end = .; + + _edata = . ; + edata = . ; + } > ram + + .bss : + { + . = ALIGN(16) ; + _sbss = . ; + __bss_start = . ; + __data_end = . ; + *(.bss) + *(COMMON) + . = ALIGN(16) ; + end = . ; + _ebss = . ; + _end = . ; + } > ram + + . = 0x10100000 ; + .eram : + { + __ramend = . ; + } > eram +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/68360/commproc.c linux.2.5.45-ac1/arch/m68knommu/platform/68360/commproc.c --- linux.2.5.45/arch/m68knommu/platform/68360/commproc.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/68360/commproc.c 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,308 @@ +/* + * General Purpose functions for the global management of the + * Communication Processor Module. + * + * Copyright (c) 2000 Michael Leslie + * Copyright (c) 1997 Dan Malek (dmalek@jlc.net) + * + * In addition to the individual control of the communication + * channels, there are a few functions that globally affect the + * communication processor. + * + * Buffer descriptors must be allocated from the dual ported memory + * space. The allocator for that is here. When the communication + * process is reset, we reclaim the memory available. There is + * currently no deallocator for this memory. + * The amount of space available is platform dependent. On the + * MBX, the EPPC software loads additional microcode into the + * communication processor, and uses some of the DP ram for this + * purpose. Current, the first 512 bytes and the last 256 bytes of + * memory are used. Right now I am conservative and only use the + * memory that can never be used for microcode. If there are + * applications that require more DP ram, we can expand the boundaries + * but then we have to be careful of any downloaded microcode. + * + */ + +/* + * Michael Leslie + * adapted Dan Malek's ppc8xx drivers to M68360 + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* #include */ +/* #include */ +extern void *_quicc_base; +extern unsigned int system_clock; + + +static uint dp_alloc_base; /* Starting offset in DP ram */ +static uint dp_alloc_top; /* Max offset + 1 */ + +#if 0 +static void *host_buffer; /* One page of host buffer */ +static void *host_end; /* end + 1 */ +#endif + +/* struct cpm360_t *cpmp; */ /* Pointer to comm processor space */ + +QUICC *pquicc; +/* QUICC *quicc_dpram; */ /* mleslie - temporary; use extern pquicc elsewhere instead */ + + +/* CPM interrupt vector functions. */ +struct cpm_action { + void (*handler)(void *); + void *dev_id; +}; +static struct cpm_action cpm_vecs[CPMVEC_NR]; +static void cpm_interrupt(int irq, void * dev, struct pt_regs * regs); +static void cpm_error_interrupt(void *); + +/* prototypes: */ +void cpm_install_handler(int vec, void (*handler)(void *), void *dev_id); +void m360_cpm_reset(void); + + + + +void m360_cpm_reset() +{ +/* pte_t *pte; */ + + pquicc = (struct quicc *)(_quicc_base); /* initialized in crt0_rXm.S */ + + /* Perform a CPM reset. */ + pquicc->cp_cr = (SOFTWARE_RESET | CMD_FLAG); + + /* Wait for CPM to become ready (should be 2 clocks). */ + while (pquicc->cp_cr & CMD_FLAG); + + /* On the recommendation of the 68360 manual, p. 7-60 + * - Set sdma interupt service mask to 7 + * - Set sdma arbitration ID to 4 + */ + pquicc->sdma_sdcr = 0x0740; + + + /* Claim the DP memory for our use. + */ + dp_alloc_base = CPM_DATAONLY_BASE; + dp_alloc_top = dp_alloc_base + CPM_DATAONLY_SIZE; + + + /* Set the host page for allocation. + */ + /* host_buffer = host_page_addr; */ + /* host_end = host_page_addr + PAGE_SIZE; */ + + /* pte = find_pte(&init_mm, host_page_addr); */ + /* pte_val(*pte) |= _PAGE_NO_CACHE; */ + /* flush_tlb_page(current->mm->mmap, host_buffer); */ + + /* Tell everyone where the comm processor resides. + */ +/* cpmp = (cpm360_t *)commproc; */ +} + + +/* This is called during init_IRQ. We used to do it above, but this + * was too early since init_IRQ was not yet called. + */ +void +cpm_interrupt_init(void) +{ + /* Initialize the CPM interrupt controller. + * NOTE THAT pquicc had better have been initialized! + * reference: MC68360UM p. 7-377 + */ + pquicc->intr_cicr = + (CICR_SCD_SCC4 | CICR_SCC_SCC3 | CICR_SCB_SCC2 | CICR_SCA_SCC1) | + (CPM_INTERRUPT << 13) | + CICR_HP_MASK | + (CPM_VECTOR_BASE << 5) | + CICR_SPS; + + /* mask all CPM interrupts from reaching the cpu32 core: */ + pquicc->intr_cimr = 0; + + + /* mles - If I understand correctly, the 360 just pops over to the CPM + * specific vector, obviating the necessity to vector through the IRQ + * whose priority the CPM is set to. This needs a closer look, though. + */ + + /* Set our interrupt handler with the core CPU. */ +/* if (request_irq(CPM_INTERRUPT, cpm_interrupt, 0, "cpm", NULL) != 0) */ +/* panic("Could not allocate CPM IRQ!"); */ + + /* Install our own error handler. + */ + /* I think we want to hold off on this one for the moment - mles */ + /* cpm_install_handler(CPMVEC_ERROR, cpm_error_interrupt, NULL); */ + + /* master CPM interrupt enable */ + /* pquicc->intr_cicr |= CICR_IEN; */ /* no such animal for 360 */ +} + + + +/* CPM interrupt controller interrupt. +*/ +static void +cpm_interrupt(int irq, void * dev, struct pt_regs * regs) +{ + /* uint vec; */ + + /* mles: Note that this stuff is currently being performed by + * M68360_do_irq(int vec, struct pt_regs *fp), in ../ints.c */ + + /* figure out the vector */ + /* call that vector's handler */ + /* clear the irq's bit in the service register */ + +#if 0 /* old 860 stuff: */ + /* Get the vector by setting the ACK bit and then reading + * the register. + */ + ((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_civr = 1; + vec = ((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_civr; + vec >>= 11; + + + if (cpm_vecs[vec].handler != 0) + (*cpm_vecs[vec].handler)(cpm_vecs[vec].dev_id); + else + ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr &= ~(1 << vec); + + /* After servicing the interrupt, we have to remove the status + * indicator. + */ + ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cisr |= (1 << vec); +#endif + +} + +/* The CPM can generate the error interrupt when there is a race condition + * between generating and masking interrupts. All we have to do is ACK it + * and return. This is a no-op function so we don't need any special + * tests in the interrupt handler. + */ +static void +cpm_error_interrupt(void *dev) +{ +} + +/* Install a CPM interrupt handler. +*/ +void +cpm_install_handler(int vec, void (*handler)(void *), void *dev_id) +{ + + request_irq(vec, handler, IRQ_FLG_LOCK, "timer", dev_id); + +/* if (cpm_vecs[vec].handler != 0) */ +/* printk("CPM interrupt %x replacing %x\n", */ +/* (uint)handler, (uint)cpm_vecs[vec].handler); */ +/* cpm_vecs[vec].handler = handler; */ +/* cpm_vecs[vec].dev_id = dev_id; */ + + /* ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr |= (1 << vec); */ +/* pquicc->intr_cimr |= (1 << vec); */ + +} + +/* Free a CPM interrupt handler. +*/ +void +cpm_free_handler(int vec) +{ + cpm_vecs[vec].handler = NULL; + cpm_vecs[vec].dev_id = NULL; + /* ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr &= ~(1 << vec); */ + pquicc->intr_cimr &= ~(1 << vec); +} + + + + +/* Allocate some memory from the dual ported ram. We may want to + * enforce alignment restrictions, but right now everyone is a good + * citizen. + */ +uint +m360_cpm_dpalloc(uint size) +{ + uint retloc; + + if ((dp_alloc_base + size) >= dp_alloc_top) + return(CPM_DP_NOSPACE); + + retloc = dp_alloc_base; + dp_alloc_base += size; + + return(retloc); +} + + +#if 0 /* mleslie - for now these are simply kmalloc'd */ +/* We also own one page of host buffer space for the allocation of + * UART "fifos" and the like. + */ +uint +m360_cpm_hostalloc(uint size) +{ + uint retloc; + + if ((host_buffer + size) >= host_end) + return(0); + + retloc = host_buffer; + host_buffer += size; + + return(retloc); +} +#endif + + +/* Set a baud rate generator. This needs lots of work. There are + * four BRGs, any of which can be wired to any channel. + * The internal baud rate clock is the system clock divided by 16. + * This assumes the baudrate is 16x oversampled by the uart. + */ +/* #define BRG_INT_CLK (((bd_t *)__res)->bi_intfreq * 1000000) */ +#define BRG_INT_CLK system_clock +#define BRG_UART_CLK (BRG_INT_CLK/16) + +void +m360_cpm_setbrg(uint brg, uint rate) +{ + volatile uint *bp; + + /* This is good enough to get SMCs running..... + */ + /* bp = (uint *)&cpmp->cp_brgc1; */ + bp = (volatile uint *)(&pquicc->brgc[0].l); + bp += brg; + *bp = ((BRG_UART_CLK / rate - 1) << 1) | CPM_BRG_EN; +} + + +/* + * Local variables: + * c-indent-level: 4 + * c-basic-offset: 4 + * tab-width: 4 + * End: + */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/68360/config.c linux.2.5.45-ac1/arch/m68knommu/platform/68360/config.c --- linux.2.5.45/arch/m68knommu/platform/68360/config.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/68360/config.c 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,213 @@ +/* + * linux/arch/m68knommu/platform/68360/config.c + * + * Copyright (c) 2000 Michael Leslie + * Copyright (C) 1993 Hamish Macdonald + * Copyright (C) 1999 D. Jeff Dionne + * + * 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 + +#ifdef CONFIG_UCQUICC +#include +#endif + +extern void m360_cpm_reset(void); + +// Mask to select if the PLL prescaler is enabled. +#define MCU_PREEN ((unsigned short)(0x0001 << 13)) + +#if defined(CONFIG_UCQUICC) +#define OSCILLATOR (unsigned long int)33000000 +#endif + +unsigned long int system_clock; + +void M68360_init_IRQ(void); + +extern QUICC *pquicc; + +/* TODO DON"T Hard Code this */ +/* calculate properly using the right PLL and prescaller */ +// unsigned int system_clock = 33000000l; +extern unsigned long int system_clock; //In kernel setup.c + +extern void config_M68360_irq(void); + +void BSP_sched_init(void (*timer_routine)(int, void *, struct pt_regs *)) +{ + unsigned char prescaler; + unsigned short tgcr_save; + int return_value; + +#if 0 + /* Restart mode, Enable int, 32KHz, Enable timer */ + TCTL = TCTL_OM | TCTL_IRQEN | TCTL_CLKSOURCE_32KHZ | TCTL_TEN; + /* Set prescaler (Divide 32KHz by 32)*/ + TPRER = 31; + /* Set compare register 32Khz / 32 / 10 = 100 */ + TCMP = 10; + + request_irq(IRQ_MACHSPEC | 1, timer_routine, IRQ_FLG_LOCK, "timer", NULL); +#endif + + /* General purpose quicc timers: MC68360UM p7-20 */ + + /* Set up timer 1 (in [1..4]) to do 100Hz */ + tgcr_save = pquicc->timer_tgcr & 0xfff0; + pquicc->timer_tgcr = tgcr_save; /* stop and reset timer 1 */ + /* pquicc->timer_tgcr |= 0x4444; */ /* halt timers when FREEZE (ie bdm freeze) */ + + prescaler = 8; + pquicc->timer_tmr1 = 0x001a | /* or=1, frr=1, iclk=01b */ + (unsigned short)((prescaler - 1) << 8); + + pquicc->timer_tcn1 = 0x0000; /* initial count */ + /* calculate interval for 100Hz based on the _system_clock: */ + pquicc->timer_trr1 = (system_clock/ prescaler) / HZ; /* reference count */ + + pquicc->timer_ter1 = 0x0003; /* clear timer events */ + + /* enable timer 1 interrupt in CIMR */ +// request_irq(IRQ_MACHSPEC | CPMVEC_TIMER1, timer_routine, IRQ_FLG_LOCK, "timer", NULL); + //return_value = request_irq( CPMVEC_TIMER1, timer_routine, IRQ_FLG_LOCK, "timer", NULL); + return_value = request_irq(CPMVEC_TIMER1 , timer_routine, IRQ_FLG_LOCK, + "Timer", NULL); + + /* Start timer 1: */ + tgcr_save = (pquicc->timer_tgcr & 0xfff0) | 0x0001; + pquicc->timer_tgcr = tgcr_save; +} + + +void BSP_tick(void) +{ + /* Reset Timer1 */ + /* TSTAT &= 0; */ + + pquicc->timer_ter1 = 0x0002; /* clear timer event */ +} + +unsigned long BSP_gettimeoffset (void) +{ + return 0; +} + +void BSP_gettod (int *yearp, int *monp, int *dayp, + int *hourp, int *minp, int *secp) +{ +} + +int BSP_hwclk(int op, struct hwclk_time *t) +{ + if (!op) { + /* read */ + } else { + /* write */ + } + return 0; +} + +int BSP_set_clock_mmss (unsigned long nowtime) +{ +#if 0 + short real_seconds = nowtime % 60, real_minutes = (nowtime / 60) % 60; + + tod->second1 = real_seconds / 10; + tod->second2 = real_seconds % 10; + tod->minute1 = real_minutes / 10; + tod->minute2 = real_minutes % 10; +#endif + return 0; +} + +void BSP_reset (void) +{ + local_irq_disable(); + asm volatile (" + moveal #_start, %a0; + moveb #0, 0xFFFFF300; + moveal 0(%a0), %sp; + moveal 4(%a0), %a0; + jmp (%a0); + "); +} + +unsigned char *scc1_hwaddr; +static int errno; + +#if defined (CONFIG_UCQUICC) +_bsc0(char *, getserialnum) +_bsc1(unsigned char *, gethwaddr, int, a) +_bsc1(char *, getbenv, char *, a) +#endif + + +void config_BSP(char *command, int len) +{ + unsigned char *p; + + m360_cpm_reset(); + + /* Calculate the real system clock value. */ + { + unsigned int local_pllcr = (unsigned int)(pquicc->sim_pllcr); + if( local_pllcr & MCU_PREEN ) // If the prescaler is dividing by 128 + { + int mf = (int)(pquicc->sim_pllcr & 0x0fff); + system_clock = (OSCILLATOR / 128) * (mf + 1); + } + else + { + int mf = (int)(pquicc->sim_pllcr & 0x0fff); + system_clock = (OSCILLATOR) * (mf + 1); + } + } + + printk("\n68360 QUICC support (C) 2000 Lineo Inc.\n"); + +#if defined(CONFIG_UCQUICC) && 0 + printk("uCquicc serial string [%s]\n",getserialnum()); + p = scc1_hwaddr = gethwaddr(0); + printk("uCquicc hwaddr %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n", + p[0], p[1], p[2], p[3], p[4], p[5]); + + p = getbenv("APPEND"); + if (p) + strcpy(p,command); + else + command[0] = 0; +#else + scc1_hwaddr = "\00\01\02\03\04\05"; +#endif + + mach_sched_init = BSP_sched_init; + mach_tick = BSP_tick; + mach_gettimeoffset = BSP_gettimeoffset; + mach_gettod = BSP_gettod; + mach_hwclk = NULL; + mach_set_clock_mmss = NULL; + mach_reset = BSP_reset; + + //Kendrick's Change + mach_trap_init = M68360_init_IRQ; + + config_M68360_irq(); +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/68360/entry.S linux.2.5.45-ac1/arch/m68knommu/platform/68360/entry.S --- linux.2.5.45/arch/m68knommu/platform/68360/entry.S 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/68360/entry.S 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,344 @@ +/* -*- mode: asm -*- + * + * linux/arch/m68knommu/platform/68360/entry.S + * + * Copyright (C) 1991, 1992 Linus Torvalds + * Copyright (C) 2001 SED Systems, a Division of Calian Ltd. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file README.legal in the main directory of this archive + * for more details. + * + * Linux/m68k support by Hamish Macdonald + * M68360 Port by SED Systems, and Lineo. + * + */ + +/* + * entry.S contains the system-call and fault low-level handling routines. + * This also contains the timer-interrupt handler, as well as all interrupts + * and faults that can result in a task-switch. + * + * NOTE: This code handles signal-recognition, which happens every time + * after a timer-interrupt and after each system call. + * + */ + +/* + * 12/03/96 Jes: Currently we only support m68k single-cpu systems, so + * all pointers that used to be 'current' are now entry + * number 0 in the 'current_set' list. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define IMMED # +#define DBG_PUTC(x) moveb IMMED x,0xfffff907; \ + moveb IMMED '\r',0xfffff907; \ + moveb IMMED '\n',0xfffff907 +LD0 = 0x20 +LORIG_D0 = 0x24 + +.globl system_call +.globl buserr +.globl trap +.globl resume +.globl ret_from_exception +.globl ret_from_signal +.globl sys_call_table +.globl sys_fork +.globl sys_clone +.globl sys_vfork +.globl ret_from_interrupt +.globl bad_interrupt +.globl inthandler + +.text +ENTRY(buserr) + SAVE_ALL_INT + /* GET_CURRENT(%d0) */ + movel %sp,%sp@- /* stack frame pointer argument*/ + bsrw buserr_c + addql #4,%sp + jra ret_from_exception + +ENTRY(trap) + SAVE_ALL_INT + GET_CURRENT(%d0) + moveq.l #-1,%d0 + move.l %d0,%sp@(LORIG_D0) +/* may have to test for LFORMATVEC here as was done in teh 2.0 module */ + movel %sp,%sp@- /* stack frame pointer argument*/ + bsrw trap_c + addql #4,%sp + jra ret_from_exception + + +ENTRY(reschedule) + /* save top of frame*/ + pea %sp@ + jbsr set_esp0 + addql #4,%sp + + pea ret_from_exception + jmp schedule + + /* After a fork we jump here directly from resume,*/ + /* so that %d1 contains the previous task*/ + /* Theoretically only needed on SMP, but let's watch*/ + /* what happens in schedule_tail() in future...*/ +ENTRY(ret_from_fork) +#ifdef CONFIG_SMP + movel %d1,%sp@- + jsr schedule_tail + addql #4,%sp +#endif + jra ret_from_exception + +badsys: + movel #-ENOSYS,%sp@(PT_D0) + jra ret_from_exception + +do_trace: + movel #-ENOSYS,%sp@(PT_D0) /* needed for strace*/ + subql #4,%sp + SAVE_SWITCH_STACK + jbsr syscall_trace + RESTORE_SWITCH_STACK + addql #4,%sp + movel %sp@(PT_ORIG_D0),%d1 + movel #-ENOSYS,%d0 + cmpl #NR_syscalls,%d1 + jcc 1f + lsl #2,%d1 + lea sys_call_table, %a0 + jbsr %a0@(%d1) + +1: movel %d0,%sp@(PT_D0) /* save the return value*/ + subql #4,%sp /* dummy return address*/ + SAVE_SWITCH_STACK + jbsr syscall_trace + +ret_from_signal: + RESTORE_SWITCH_STACK + addql #4,%sp + jra ret_from_exception + +ENTRY(system_call) + SAVE_ALL_SYS + + GET_CURRENT(%d1) + /* save top of frame*/ + pea %sp@ + jbsr set_esp0 + addql #4,%sp + + btst #PF_TRACESYS_BIT,%a2@(TASK_FLAGS+PF_TRACESYS_OFF) + jne do_trace + cmpl #NR_syscalls,%d0 + jcc badsys + lsl #2,%d0 + lea sys_call_table,%a0 + movel %a0@(%d0), %a0 + jbsr %a0@ + movel %d0,%sp@(PT_D0) /* save the return value*/ + +ret_from_exception: + btst #5,%sp@(PT_SR) /* check if returning to kernel*/ + jeq Luser_return /* if so, skip resched, signals*/ + +Lkernel_return: + RESTORE_ALL + +Luser_return: + /* only allow interrupts when we are really the last one on the*/ + /* kernel stack, otherwise stack overflow can occur during*/ + /* heavy interupt load*/ + andw #ALLOWINT,%sr + + movel %sp,%d1 /* get thread_info pointer */ + andl #0xffffe000,%d1 + movel %d1,%a2 + move %a2@(TI_FLAGS),%d1 /* thread_info->flags */ + andl #_TIF_WORK_MASK,%d1 + jne Lwork_to_do + RESTORE_ALL + +Lwork_to_do: + movel %a2@(TI_FLAGS),%d1 /* thread_info->flags */ + btst #TIF_NEED_RESCHED,%d1 + jne reschedule + +Lsignal_return: + subql #4,%sp /* dummy return address*/ + SAVE_SWITCH_STACK + pea %sp@(SWITCH_STACK_SIZE) + clrl %sp@- + bsrw do_signal + addql #8,%sp + RESTORE_SWITCH_STACK + addql #4,%sp +Lreturn: + RESTORE_ALL + +/* +** This is the main interrupt handler, responsible for calling process_int() +*/ + +inthandler: + SAVE_ALL_INT + GET_CURRENT(%d0) + addql #1,local_irq_count /* put exception # in d0*/ +/* bfextu %sp@(PT_VECTOR){#4,#10},%d0 */ + movew %sp@(PT_VECTOR), %d0 + and.l #0x3ff, %d0 + lsr.l #0x02, %d0 + + movel %sp,%sp@- + movel %d0,%sp@- /* put vector # on stack*/ + jbsr process_int /* process the IRQ*/ +3: addql #8,%sp /* pop parameters off stack*/ + bra ret_from_interrupt + +ret_from_interrupt: + subql #1,local_irq_count + jeq 1f +2: + RESTORE_ALL +1: +#if 1 +/* bfextu %sp@(PT_SR){#5,#3},%d0 */ /* Check for nested interrupt.*/ + moveb %sp@(PT_SR), %d0 + and #7, %d0 + +#if MAX_NOINT_IPL > 0 + cmpiw #MAX_NOINT_IPL,%d0 +#endif + jhi 2b +#endif + /* check if we need to do software interrupts */ + + movel irq_stat+CPUSTAT_SOFTIRQ_PENDING,%d0 + jeq ret_from_exception + + pea ret_from_exception + jra do_softirq + + +/* Handler for uninitialized and spurious interrupts */ + +bad_interrupt: + addql #1,num_spurious + rte + +ENTRY(sys_fork) + SAVE_SWITCH_STACK + pea %sp@(SWITCH_STACK_SIZE) + jbsr m68k_fork + addql #4,%sp + RESTORE_SWITCH_STACK + rts + +ENTRY(sys_clone) + SAVE_SWITCH_STACK + pea %sp@(SWITCH_STACK_SIZE) + jbsr m68k_clone + addql #4,%sp + RESTORE_SWITCH_STACK + rts + +ENTRY(sys_vfork) + SAVE_SWITCH_STACK + pea %sp@(SWITCH_STACK_SIZE) + jbsr m68k_vfork + addql #4,%sp + RESTORE_SWITCH_STACK + rts + +ENTRY(sys_sigsuspend) + SAVE_SWITCH_STACK + pea %sp@(SWITCH_STACK_SIZE) + jbsr do_sigsuspend + addql #4,%sp + RESTORE_SWITCH_STACK + rts + +ENTRY(sys_rt_sigsuspend) + SAVE_SWITCH_STACK + pea %sp@(SWITCH_STACK_SIZE) + jbsr do_rt_sigsuspend + addql #4,%sp + RESTORE_SWITCH_STACK + rts + +ENTRY(sys_sigreturn) + SAVE_SWITCH_STACK + jbsr do_sigreturn + RESTORE_SWITCH_STACK + rts + +ENTRY(sys_rt_sigreturn) + SAVE_SWITCH_STACK + jbsr do_rt_sigreturn + RESTORE_SWITCH_STACK + rts + +resume: + /* + * Beware - when entering resume, prev (the current task) is + * in a0, next (the new task) is in a1,so don't change these + * registers until their contents are no longer needed. + */ + + /* save prev thread in d1 */ + movel %a0,%d1 + + /* save sr */ + movew %sr,%a0@(TASK_THREAD+THREAD_SR) +#ifdef USE_SFC_DFC + /* save fs (sfc,%dfc) (may be pointing to kernel memory) */ + movec %sfc,%d0 + movew %d0,%a0@(TASK_THREAD+THREAD_FS) +#endif + + /* save non-scratch registers on stack */ + SAVE_SWITCH_STACK + + /* save usp */ + /* it is better to use a movel here instead of a movew 8*) */ + movel %usp,%a2 + movel %a2,%a0@(TASK_THREAD+THREAD_USP) + + /* save current kernel stack pointer */ + movel %sp,%a0@(TASK_THREAD+THREAD_KSP) + + /* restore the kernel stack pointer */ + movel %a1@(TASK_THREAD+THREAD_KSP),%sp + + /* restore non-scratch registers */ + RESTORE_SWITCH_STACK + + /* restore user stack pointer */ + movel %a1@(TASK_THREAD+THREAD_USP),%a0 + movel %a0,%usp + +#ifdef USE_SFC_DFC + /* restore fs (sfc,%dfc) */ + movew %a1@(TASK_THREAD+THREAD_FS),%a0 + movec %a0,%sfc + movec %a0,%dfc +#endif + /* restore status register */ + movew %a1@(TASK_THREAD+THREAD_SR),%sr + + rts + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/68360/ints.c linux.2.5.45-ac1/arch/m68knommu/platform/68360/ints.c --- linux.2.5.45/arch/m68knommu/platform/68360/ints.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/68360/ints.c 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,318 @@ +/* + * linux/arch/$(ARCH)/platform/$(PLATFORM)/ints.c + * + * 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) 2000 Michael Leslie + * Copyright (c) 1996 Roman Zippel + * Copyright (c) 1999 D. Jeff Dionne + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +/* from quicc/commproc.c: */ +extern QUICC *pquicc; +extern void cpm_interrupt_init(void); + +#define INTERNAL_IRQS (96) + +/* assembler routines */ +asmlinkage void system_call(void); +asmlinkage void buserr(void); +asmlinkage void trap(void); +asmlinkage void bad_interrupt(void); +asmlinkage void inthandler(void); + +extern void *_ramvec[]; + +/* irq node variables for the 32 (potential) on chip sources */ +static irq_node_t *int_irq_list[INTERNAL_IRQS]; + +static int int_irq_count[INTERNAL_IRQS]; +static short int_irq_ablecount[INTERNAL_IRQS]; + +static void int_badint(int irq, void *dev_id, struct pt_regs *fp) +{ + num_spurious += 1; +} + +/* + * This function should be called during kernel startup to initialize + * IRQ handling routines. + */ + +void M68360_init_IRQ(void) +{ + int i; + int vba = (CPM_VECTOR_BASE<<4); + + /* set up the vectors */ + _ramvec[2] = buserr; + _ramvec[3] = trap; + _ramvec[4] = trap; + _ramvec[5] = trap; + _ramvec[6] = trap; + _ramvec[7] = trap; + _ramvec[8] = trap; + _ramvec[9] = trap; + _ramvec[10] = trap; + _ramvec[11] = trap; + _ramvec[12] = trap; + _ramvec[13] = trap; + _ramvec[14] = trap; + _ramvec[15] = trap; + + _ramvec[32] = system_call; + _ramvec[33] = trap; + + + cpm_interrupt_init(); + + /* set up CICR for vector base address and irq level */ + /* irl = 4, hp = 1f - see MC68360UM p 7-377 */ + pquicc->intr_cicr = 0x00e49f00 | vba; + + /* CPM interrupt vectors: (p 7-376) */ + _ramvec[vba+CPMVEC_ERROR] = bad_interrupt; /* Error */ + _ramvec[vba+CPMVEC_PIO_PC11] = inthandler; /* pio - pc11 */ + _ramvec[vba+CPMVEC_PIO_PC10] = inthandler; /* pio - pc10 */ + _ramvec[vba+CPMVEC_SMC2] = inthandler; /* smc2/pip */ + _ramvec[vba+CPMVEC_SMC1] = inthandler; /* smc1 */ + _ramvec[vba+CPMVEC_SPI] = inthandler; /* spi */ + _ramvec[vba+CPMVEC_PIO_PC9] = inthandler; /* pio - pc9 */ + _ramvec[vba+CPMVEC_TIMER4] = inthandler; /* timer 4 */ + _ramvec[vba+CPMVEC_RESERVED1] = inthandler; /* reserved */ + _ramvec[vba+CPMVEC_PIO_PC8] = inthandler; /* pio - pc8 */ + _ramvec[vba+CPMVEC_PIO_PC7] = inthandler; /* pio - pc7 */ + _ramvec[vba+CPMVEC_PIO_PC6] = inthandler; /* pio - pc6 */ + _ramvec[vba+CPMVEC_TIMER3] = inthandler; /* timer 3 */ + _ramvec[vba+CPMVEC_RISCTIMER] = inthandler; /* reserved */ + _ramvec[vba+CPMVEC_PIO_PC5] = inthandler; /* pio - pc5 */ + _ramvec[vba+CPMVEC_PIO_PC4] = inthandler; /* pio - pc4 */ + _ramvec[vba+CPMVEC_RESERVED2] = inthandler; /* reserved */ + _ramvec[vba+CPMVEC_RISCTIMER] = inthandler; /* timer table */ + _ramvec[vba+CPMVEC_TIMER2] = inthandler; /* timer 2 */ + _ramvec[vba+CPMVEC_RESERVED3] = inthandler; /* reserved */ + _ramvec[vba+CPMVEC_IDMA2] = inthandler; /* idma 2 */ + _ramvec[vba+CPMVEC_IDMA1] = inthandler; /* idma 1 */ + _ramvec[vba+CPMVEC_SDMA_CB_ERR] = inthandler; /* sdma channel bus error */ + _ramvec[vba+CPMVEC_PIO_PC3] = inthandler; /* pio - pc3 */ + _ramvec[vba+CPMVEC_PIO_PC2] = inthandler; /* pio - pc2 */ + /* _ramvec[vba+CPMVEC_TIMER1] = cpm_isr_timer1; */ /* timer 1 */ + _ramvec[vba+CPMVEC_TIMER1] = inthandler; /* timer 1 */ + _ramvec[vba+CPMVEC_PIO_PC1] = inthandler; /* pio - pc1 */ + _ramvec[vba+CPMVEC_SCC4] = inthandler; /* scc 4 */ + _ramvec[vba+CPMVEC_SCC3] = inthandler; /* scc 3 */ + _ramvec[vba+CPMVEC_SCC2] = inthandler; /* scc 2 */ + _ramvec[vba+CPMVEC_SCC1] = inthandler; /* scc 1 */ + _ramvec[vba+CPMVEC_PIO_PC0] = inthandler; /* pio - pc0 */ + + + /* turn off all CPM interrupts */ + pquicc->intr_cimr = 0x00000000; + + /* initialize handlers */ + for (i = 0; i < INTERNAL_IRQS; i++) { + int_irq_list[i] = NULL; + + int_irq_ablecount[i] = 0; + int_irq_count[i] = 0; + } +} + +void M68360_insert_irq(irq_node_t **list, irq_node_t *node) +{ + unsigned long flags; + irq_node_t *cur; + + if (!node->dev_id) + printk("%s: Warning: dev_id of %s is zero\n", + __FUNCTION__, node->devname); + + local_irq_save(flags); + + cur = *list; + + while (cur) { + list = &cur->next; + cur = cur->next; + } + + node->next = cur; + *list = node; + + local_irq_restore(flags); +} + +void M68360_delete_irq(irq_node_t **list, void *dev_id) +{ + unsigned long flags; + irq_node_t *node; + + local_irq_save(flags); + + for (node = *list; node; list = &node->next, node = *list) { + if (node->dev_id == dev_id) { + *list = node->next; + /* Mark it as free. */ + node->handler = NULL; + local_irq_restore(flags); + return; + } + } + local_irq_restore(flags); + printk ("%s: tried to remove invalid irq\n", __FUNCTION__); +} + +int M68360_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), + unsigned long flags, const char *devname, void *dev_id) +{ + int mask = (1<= INTERNAL_IRQS) { + printk ("%s: Unknown IRQ %d from %s\n", __FUNCTION__, irq, devname); + return -ENXIO; + } + + if (!int_irq_list[irq]) { + int_irq_list[irq] = new_irq_node(); + int_irq_list[irq]->flags = IRQ_FLG_STD; + } + + if (!(int_irq_list[irq]->flags & IRQ_FLG_STD)) { + if (int_irq_list[irq]->flags & IRQ_FLG_LOCK) { + printk("%s: IRQ %d from %s is not replaceable\n", + __FUNCTION__, irq, int_irq_list[irq]->devname); + return -EBUSY; + } + if (flags & IRQ_FLG_REPLACE) { + printk("%s: %s can't replace IRQ %d from %s\n", + __FUNCTION__, devname, irq, int_irq_list[irq]->devname); + return -EBUSY; + } + } + int_irq_list[irq]->handler = handler; + int_irq_list[irq]->flags = flags; + int_irq_list[irq]->dev_id = dev_id; + int_irq_list[irq]->devname = devname; + + /* enable in the CIMR */ + if (!int_irq_ablecount[irq]) + pquicc->intr_cimr |= mask; + /* *(volatile unsigned long *)0xfffff304 &= ~(1<= INTERNAL_IRQS) { + printk ("%s: Unknown IRQ %d\n", __FUNCTION__, irq); + return; + } + + if (int_irq_list[irq]->dev_id != dev_id) + printk("%s: removing probably wrong IRQ %d from %s\n", + __FUNCTION__, irq, int_irq_list[irq]->devname); + int_irq_list[irq]->handler = int_badint; + int_irq_list[irq]->flags = IRQ_FLG_STD; + int_irq_list[irq]->dev_id = NULL; + int_irq_list[irq]->devname = NULL; + + *(volatile unsigned long *)0xfffff304 |= 1<= INTERNAL_IRQS) { + printk("%s: Unknown IRQ %d\n", __FUNCTION__, irq); + return; + } + + if (--int_irq_ablecount[irq]) + return; + + /* enable the interrupt */ + *(volatile unsigned long *)0xfffff304 &= ~(1<= INTERNAL_IRQS) { + printk("%s: Unknown IRQ %d\n", __FUNCTION__, irq); + return; + } + + if (int_irq_ablecount[irq]++) + return; + + /* disable the interrupt */ + *(volatile unsigned long *)0xfffff304 |= 1<intr_cipr; */ + + /* Bugger all that wierdness. For the moment, I seem to know where I came from; + * vec is passed from a specific ISR, so I'll use it. */ + + if (int_irq_list[irq] && int_irq_list[irq]->handler) { + int_irq_list[irq]->handler(irq , int_irq_list[irq]->dev_id, fp); + int_irq_count[irq]++; + pquicc->intr_cisr = (1 << vec); /* indicate that irq has been serviced */ + } else { + printk("unregistered interrupt %d!\nTurning it off in the CIMR...\n", irq); + /* *(volatile unsigned long *)0xfffff304 |= mask; */ + pquicc->intr_cimr &= ~(1 << vec); + } +} + +void config_M68360_irq(void) +{ + mach_default_handler = NULL; + mach_init_IRQ = M68360_init_IRQ; + mach_request_irq = M68360_request_irq; + mach_free_irq = M68360_free_irq; + mach_enable_irq = M68360_enable_irq; + mach_disable_irq = M68360_disable_irq; + mach_process_int = M68360_do_irq; +} + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/68360/Makefile linux.2.5.45-ac1/arch/m68knommu/platform/68360/Makefile --- linux.2.5.45/arch/m68knommu/platform/68360/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/68360/Makefile 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,10 @@ +# +# Makefile for arch/m68knommu/platform/68360. +# + +obj-y := config.o commproc.o entry.o ints.o + +EXTRA_TARGETS := $(BOARD)/crt0_$(MODEL).o + +include $(TOPDIR)/Rules.make + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/68360/uCquicc/crt0_ram.S linux.2.5.45-ac1/arch/m68knommu/platform/68360/uCquicc/crt0_ram.S --- linux.2.5.45/arch/m68knommu/platform/68360/uCquicc/crt0_ram.S 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/68360/uCquicc/crt0_ram.S 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,415 @@ +/* arch/m68knommu/platform/68360/uCquicc/crt0_rom.S + * + * Startup code for Motorola 68360 + * + * Copyright 2001 (C) SED Systems, a Division of Calian Ltd. + * Based on: arch/m68knommu/platform/68328/pilot/crt0_rom.S + * Based on: arch/m68knommu/platform/68360/uCquicc/crt0_rom.S, 2.0.38.1.pre7 + * uClinux Kernel + * Copyright (C) Michael Leslie + * Based on: arch/m68knommu/platform/68EZ328/ucsimm/crt0_rom.S + * Copyright (C) 1998 D. Jeff Dionne , + * + */ +#define ASSEMBLY +#include + +.global _stext +.global __bss_start +.global _start + +.global _rambase +.global __ramvec +.global _ramvec +.global _ramstart +.global _ramend + +.global _quicc_base +.global _periph_base +.global _dprbase + +#define REGB 0x1000 +#define PEPAR (_dprbase + REGB + 0x0016) +#define GMR (_dprbase + REGB + 0x0040) +#define OR0 (_dprbase + REGB + 0x0054) +#define BR0 (_dprbase + REGB + 0x0050) +#define OR1 (_dprbase + REGB + 0x0064) +#define BR1 (_dprbase + REGB + 0x0060) +#define OR4 (_dprbase + REGB + 0x0094) +#define BR4 (_dprbase + REGB + 0x0090) +#define OR6 (_dprbase + REGB + 0x00b4) +#define BR6 (_dprbase + REGB + 0x00b0) +#define OR7 (_dprbase + REGB + 0x00c4) +#define BR7 (_dprbase + REGB + 0x00c0) + +#define MCR (_dprbase + REGB + 0x0000) +#define AVR (_dprbase + REGB + 0x0008) + +#define SYPCR (_dprbase + REGB + 0x0022) + +#define PLLCR (_dprbase + REGB + 0x0010) +#define CLKOCR (_dprbase + REGB + 0x000C) +#define CDVCR (_dprbase + REGB + 0x0014) + +#define BKAR (_dprbase + REGB + 0x0030) +#define BKCR (_dprbase + REGB + 0x0034) +#define SWIV (_dprbase + REGB + 0x0023) +#define PICR (_dprbase + REGB + 0x0026) +#define PITR (_dprbase + REGB + 0x002A) + +/* Define for all memory configuration */ +#define MCU_SIM_GMR 0x00000000 +#define SIM_OR_MASK 0x0fffffff + +/* Defines for chip select zero - the flash */ +#define SIM_OR0_MASK 0x20000002 +#define SIM_BR0_MASK 0x00000001 + + +/* Defines for chip select one - the RAM */ +#define SIM_OR1_MASK 0x10000000 +#define SIM_BR1_MASK 0x00000001 + +#define MCU_SIM_MBAR_ADRS 0x0003ff00 +#define MCU_SIM_MBAR_BA_MASK 0xfffff000 +#define MCU_SIM_MBAR_AS_MASK 0x00000001 + +#define MCU_SIM_PEPAR 0x00B4 + +#define MCU_DISABLE_INTRPTS 0x2700 +#define MCU_SIM_AVR 0x00 + +#define MCU_SIM_MCR 0x00005cff + +#define MCU_SIM_CLKOCR 0x00 +#define MCU_SIM_PLLCR 0x8000 +#define MCU_SIM_CDVCR 0x0000 + +#define MCU_SIM_SYPCR 0x0000 +#define MCU_SIM_SWIV 0x00 +#define MCU_SIM_PICR 0x0000 +#define MCU_SIM_PITR 0x0000 + + +#include + + +/* By the time this RAM specific code begins to execute, DPRAM + * and DRAM should already be mapped and accessible. */ + + .text +_start: +_stext: + nop + ori.w #MCU_DISABLE_INTRPTS, %sr /* disable interrupts: */ + /* We should not need to setup the boot stack the reset should do it. */ + movea.l #_boot_stack, %sp /*set up stack at the end of DRAM:*/ + + +set_mbar_register: + moveq.l #0x07, %d1 /* Setup MBAR */ + movec %d1, %dfc + + lea.l MCU_SIM_MBAR_ADRS, %a0 + move.l #_dprbase, %d0 + andi.l #MCU_SIM_MBAR_BA_MASK, %d0 + ori.l #MCU_SIM_MBAR_AS_MASK, %d0 + moves.l %d0, %a0@ + + moveq.l #0x05, %d1 + movec.l %d1, %dfc + +/* Now we can begin to access registers in DPRAM */ + +set_sim_mcr: + /* Set Module Configuration Register */ + move.l #MCU_SIM_MCR, MCR + +/* to do: Determine cause of reset */ + + + /* + * configure system clock MC68360 p. 6-40 + * (value +1)*osc/128 = system clock + */ +set_sim_clock: + move.w #MCU_SIM_PLLCR, PLLCR + move.b #MCU_SIM_CLKOCR, CLKOCR + move.w #MCU_SIM_CDVCR, CDVCR + + // Wait for the PLL to settle + move.w #16384, %d0 +pll_settle_wait: + subi.w #1, %d0 + bne pll_settle_wait + + /* Setup the system protection register, and watchdog timer register */ + + move.b #MCU_SIM_SWIV, SWIV + move.w #MCU_SIM_PICR, PICR + move.w #MCU_SIM_PITR, PITR + move.w #MCU_SIM_SYPCR, SYPCR + +/* Clear DPRAM - system + parameter */ + movea.l #_dprbase, %a0 + movea.l #_dprbase+0x2000, %a1 + + /* Copy 0 to %a0 until %a0 == %a1 */ +clear_dpram: + movel #0, %a0@+ + cmpal %a0, %a1 + bhi clear_dpram + +configure_memory_controller: + /* + * Set up Global Memory Register (GMR) + */ + move.l #MCU_SIM_GMR, %d0 + move.l %d0, GMR + +configure_chip_select_0: + move.l #__ramend, %d0 + subi.l #__ramstart, %d0 + subq.l #0x01, %d0 + eori.l #SIM_OR_MASK, %d0 + ori.l #SIM_OR0_MASK, %d0 + move.l %d0, OR0 + + move.l #__ramstart, %d0 + ori.l #SIM_BR0_MASK, %d0 + move.l %d0, BR0 + + +configure_chip_select_1: + move.l #__flashend, %d0 + subi.l #__flashstart, %d0 + subq.l #0x01, %d0 + eori.l #SIM_OR_MASK, %d0 + ori.l #SIM_OR1_MASK, %d0 + move.l %d0, OR1 + + move.l #__flashstart, %d0 + ori.l #SIM_BR1_MASK, %d0 + move.l %d0, BR1 + + + move.w #MCU_SIM_PEPAR, PEPAR + +/* point to vector table: */ + move.l #_romvec, %a0 + move.l #_ramvec, %a1 +copy_vectors: + move.l %a0@, %d0 + move.l %d0, %a1@ + move.l %a0@, %a1@ + addq.l #0x04, %a0 + addq.l #0x04, %a1 + cmp.l #_start, %a0 + blt copy_vectors + + move.l #_ramvec, %a1 + movec %a1, %vbr + + + /* Copy data segment from ROM to RAM */ + moveal #__data_rom_start, %a0 + moveal #__data_start, %a1 + moveal #__data_end, %a2 + + /* Copy %a0 to %a1 until %a1 == %a2 */ +LD1: + move.l %a0@, %d0 + addq.l #0x04, %a0 + move.l %d0, %a1@ + addq.l #0x04, %a1 + cmp.l #__data_end, %a1 + blt LD1 + + moveal #__bss_start, %a0 + moveal #end, %a1 + + /* Copy 0 to %a0 until %a0 == %a1 */ +L1: + movel #0, %a0@+ + cmpal %a0, %a1 + bhi L1 + +load_quicc: + move.l #_dprbase, _quicc_base + +store_ram_size: + /* Set ram size information */ + move.l #_sdata, _rambase + move.l #end, _ramstart + move.l #__ramend, %d0 + sub.l #0x1000, %d0 /* Reserve 4K for stack space.*/ + move.l %d0, _ramend /* Different from __ramend.*/ + +store_flash_size: + /* Set rom size information */ + move.l #__flashend, %d0 + sub.l #__flashstart, %d0 + move.l %d0, rom_length + + pea 0 + pea env + pea %sp@(4) + pea 0 + + lea init_thread_union, %a2 + lea 0x2000(%a2), %sp + +lp: + jsr start_kernel + /* jmp lp */ + +_exit: + + jmp _exit + + + + .data + .align 4 +env: + .long 0 +_quicc_base: + .long 0 +_periph_base: + .long 0 +_ramvec: + .long 0 +_rambase: + .long 0 +_ramstart: + .long 0 +_ramend: + .long 0 + .text + + /* + * These are the exception vectors at boot up, they are copied into RAM + * and then overwritten as needed. + */ + +.section ".data.initvect","awx" + .long _boot_stack /* Reset: Initial Stack Pointer - 0. */ + .long _start /* Reset: Initial Program Counter - 1. */ + .long buserr /* Bus Error - 2. */ + .long trap /* Address Error - 3. */ + .long trap /* Illegal Instruction - 4. */ + .long trap /* Divide by zero - 5. */ + .long trap /* CHK, CHK2 Instructions - 6. */ + .long trap /* TRAPcc, TRAPV Instructions - 7. */ + .long trap /* Privilege Violation - 8. */ + .long trap /* Trace - 9. */ + .long trap /* Line 1010 Emulator - 10. */ + .long trap /* Line 1111 Emualtor - 11. */ + .long trap /* Harware Breakpoint - 12. */ + .long trap /* (Reserved for Coprocessor Protocol Violation)- 13. */ + .long trap /* Format Error - 14. */ + .long trap /* Uninitialized Interrupt - 15. */ + .long trap /* (Unassigned, Reserver) - 16. */ + .long trap /* (Unassigned, Reserver) - 17. */ + .long trap /* (Unassigned, Reserver) - 18. */ + .long trap /* (Unassigned, Reserver) - 19. */ + .long trap /* (Unassigned, Reserver) - 20. */ + .long trap /* (Unassigned, Reserver) - 21. */ + .long trap /* (Unassigned, Reserver) - 22. */ + .long trap /* (Unassigned, Reserver) - 23. */ + .long trap /* Spurious Interrupt - 24. */ + .long trap /* Level 1 Interrupt Autovector - 25. */ + .long trap /* Level 2 Interrupt Autovector - 26. */ + .long trap /* Level 3 Interrupt Autovector - 27. */ + .long trap /* Level 4 Interrupt Autovector - 28. */ + .long trap /* Level 5 Interrupt Autovector - 29. */ + .long trap /* Level 6 Interrupt Autovector - 30. */ + .long trap /* Level 7 Interrupt Autovector - 31. */ + .long system_call /* Trap Instruction Vectors 0 - 32. */ + .long trap /* Trap Instruction Vectors 1 - 33. */ + .long trap /* Trap Instruction Vectors 2 - 34. */ + .long trap /* Trap Instruction Vectors 3 - 35. */ + .long trap /* Trap Instruction Vectors 4 - 36. */ + .long trap /* Trap Instruction Vectors 5 - 37. */ + .long trap /* Trap Instruction Vectors 6 - 38. */ + .long trap /* Trap Instruction Vectors 7 - 39. */ + .long trap /* Trap Instruction Vectors 8 - 40. */ + .long trap /* Trap Instruction Vectors 9 - 41. */ + .long trap /* Trap Instruction Vectors 10 - 42. */ + .long trap /* Trap Instruction Vectors 11 - 43. */ + .long trap /* Trap Instruction Vectors 12 - 44. */ + .long trap /* Trap Instruction Vectors 13 - 45. */ + .long trap /* Trap Instruction Vectors 14 - 46. */ + .long trap /* Trap Instruction Vectors 15 - 47. */ + .long 0 /* (Reserved for Coprocessor) - 48. */ + .long 0 /* (Reserved for Coprocessor) - 49. */ + .long 0 /* (Reserved for Coprocessor) - 50. */ + .long 0 /* (Reserved for Coprocessor) - 51. */ + .long 0 /* (Reserved for Coprocessor) - 52. */ + .long 0 /* (Reserved for Coprocessor) - 53. */ + .long 0 /* (Reserved for Coprocessor) - 54. */ + .long 0 /* (Reserved for Coprocessor) - 55. */ + .long 0 /* (Reserved for Coprocessor) - 56. */ + .long 0 /* (Reserved for Coprocessor) - 57. */ + .long 0 /* (Reserved for Coprocessor) - 58. */ + .long 0 /* (Unassigned, Reserved) - 59. */ + .long 0 /* (Unassigned, Reserved) - 60. */ + .long 0 /* (Unassigned, Reserved) - 61. */ + .long 0 /* (Unassigned, Reserved) - 62. */ + .long 0 /* (Unassigned, Reserved) - 63. */ + /* The assignment of these vectors to the CPM is */ + /* dependant on the configuration of the CPM vba */ + /* fields. */ + .long 0 /* (User-Defined Vectors 1) CPM Error - 64. */ + .long 0 /* (User-Defined Vectors 2) CPM Parallel IO PC11- 65. */ + .long 0 /* (User-Defined Vectors 3) CPM Parallel IO PC10- 66. */ + .long 0 /* (User-Defined Vectors 4) CPM SMC2 / PIP - 67. */ + .long 0 /* (User-Defined Vectors 5) CPM SMC1 - 68. */ + .long 0 /* (User-Defined Vectors 6) CPM SPI - 69. */ + .long 0 /* (User-Defined Vectors 7) CPM Parallel IO PC9 - 70. */ + .long 0 /* (User-Defined Vectors 8) CPM Timer 4 - 71. */ + .long 0 /* (User-Defined Vectors 9) CPM Reserved - 72. */ + .long 0 /* (User-Defined Vectors 10) CPM Parallel IO PC8- 73. */ + .long 0 /* (User-Defined Vectors 11) CPM Parallel IO PC7- 74. */ + .long 0 /* (User-Defined Vectors 12) CPM Parallel IO PC6- 75. */ + .long 0 /* (User-Defined Vectors 13) CPM Timer 3 - 76. */ + .long 0 /* (User-Defined Vectors 14) CPM Reserved - 77. */ + .long 0 /* (User-Defined Vectors 15) CPM Parallel IO PC5- 78. */ + .long 0 /* (User-Defined Vectors 16) CPM Parallel IO PC4- 79. */ + .long 0 /* (User-Defined Vectors 17) CPM Reserved - 80. */ + .long 0 /* (User-Defined Vectors 18) CPM RISC Timer Tbl - 81. */ + .long 0 /* (User-Defined Vectors 19) CPM Timer 2 - 82. */ + .long 0 /* (User-Defined Vectors 21) CPM Reserved - 83. */ + .long 0 /* (User-Defined Vectors 22) CPM IDMA2 - 84. */ + .long 0 /* (User-Defined Vectors 23) CPM IDMA1 - 85. */ + .long 0 /* (User-Defined Vectors 24) CPM SDMA Bus Err - 86. */ + .long 0 /* (User-Defined Vectors 25) CPM Parallel IO PC3- 87. */ + .long 0 /* (User-Defined Vectors 26) CPM Parallel IO PC2- 88. */ + .long 0 /* (User-Defined Vectors 27) CPM Timer 1 - 89. */ + .long 0 /* (User-Defined Vectors 28) CPM Parallel IO PC1- 90. */ + .long 0 /* (User-Defined Vectors 29) CPM SCC 4 - 91. */ + .long 0 /* (User-Defined Vectors 30) CPM SCC 3 - 92. */ + .long 0 /* (User-Defined Vectors 31) CPM SCC 2 - 93. */ + .long 0 /* (User-Defined Vectors 32) CPM SCC 1 - 94. */ + .long 0 /* (User-Defined Vectors 33) CPM Parallel IO PC0- 95. */ + /* I don't think anything uses the vectors after here. */ + .long 0 /* (User-Defined Vectors 34) - 96. */ + .long 0,0,0,0,0 /* (User-Defined Vectors 35 - 39). */ + .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 40 - 49). */ + .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 50 - 59). */ + .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 60 - 69). */ + .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 70 - 79). */ + .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 80 - 89). */ + .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 90 - 99). */ + .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 100 - 109). */ + .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 110 - 119). */ + .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 120 - 129). */ + .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 130 - 139). */ + .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 140 - 149). */ + .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 150 - 159). */ + .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 160 - 169). */ + .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 170 - 179). */ + .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 180 - 189). */ + .long 0,0,0 /* (User-Defined Vectors 190 - 192). */ +.text +ignore: rte diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/68360/uCquicc/crt0_rom.S linux.2.5.45-ac1/arch/m68knommu/platform/68360/uCquicc/crt0_rom.S --- linux.2.5.45/arch/m68knommu/platform/68360/uCquicc/crt0_rom.S 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/68360/uCquicc/crt0_rom.S 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,424 @@ +/* arch/m68knommu/platform/68360/uCquicc/crt0_rom.S + * + * Startup code for Motorola 68360 + * + * Copyright (C) SED Systems, a Division of Calian Ltd. + * Based on: arch/m68knommu/platform/68328/pilot/crt0_rom.S + * Based on: arch/m68knommu/platform/68360/uCquicc/crt0_rom.S, 2.0.38.1.pre7 + * uClinux Kernel + * Copyright (C) Michael Leslie + * Based on: arch/m68knommu/platform/68EZ328/ucsimm/crt0_rom.S + * Copyright (C) 1998 D. Jeff Dionne , + * + */ +#define ASSEMBLY +#include + +.global _stext +.global __bss_start +.global _start + +.global _rambase +.global __ramvec +.global _ramvec +.global _ramstart +.global _ramend + +.global _quicc_base +.global _periph_base +.global _dprbase + +#define REGB 0x1000 +#define PEPAR (_dprbase + REGB + 0x0016) +#define GMR (_dprbase + REGB + 0x0040) +#define OR0 (_dprbase + REGB + 0x0054) +#define BR0 (_dprbase + REGB + 0x0050) + +#define OR1 (_dprbase + REGB + 0x0064) +#define BR1 (_dprbase + REGB + 0x0060) + +#define OR2 (_dprbase + REGB + 0x0074) +#define BR2 (_dprbase + REGB + 0x0070) + +#define OR3 (_dprbase + REGB + 0x0084) +#define BR3 (_dprbase + REGB + 0x0080) + +#define OR4 (_dprbase + REGB + 0x0094) +#define BR4 (_dprbase + REGB + 0x0090) + +#define OR5 (_dprbase + REGB + 0x00A4) +#define BR5 (_dprbase + REGB + 0x00A0) + +#define OR6 (_dprbase + REGB + 0x00b4) +#define BR6 (_dprbase + REGB + 0x00b0) + +#define OR7 (_dprbase + REGB + 0x00c4) +#define BR7 (_dprbase + REGB + 0x00c0) + +#define MCR (_dprbase + REGB + 0x0000) +#define AVR (_dprbase + REGB + 0x0008) + +#define SYPCR (_dprbase + REGB + 0x0022) + +#define PLLCR (_dprbase + REGB + 0x0010) +#define CLKOCR (_dprbase + REGB + 0x000C) +#define CDVCR (_dprbase + REGB + 0x0014) + +#define BKAR (_dprbase + REGB + 0x0030) +#define BKCR (_dprbase + REGB + 0x0034) +#define SWIV (_dprbase + REGB + 0x0023) +#define PICR (_dprbase + REGB + 0x0026) +#define PITR (_dprbase + REGB + 0x002A) + +/* Define for all memory configuration */ +#define MCU_SIM_GMR 0x00000000 +#define SIM_OR_MASK 0x0fffffff + +/* Defines for chip select zero - the flash */ +#define SIM_OR0_MASK 0x20000000 +#define SIM_BR0_MASK 0x00000001 + + +/* Defines for chip select one - the RAM */ +#define SIM_OR1_MASK 0x10000000 +#define SIM_BR1_MASK 0x00000001 + +#define MCU_SIM_MBAR_ADRS 0x0003ff00 +#define MCU_SIM_MBAR_BA_MASK 0xfffff000 +#define MCU_SIM_MBAR_AS_MASK 0x00000001 + +#define MCU_SIM_PEPAR 0x00B4 + +#define MCU_DISABLE_INTRPTS 0x2700 +#define MCU_SIM_AVR 0x00 + +#define MCU_SIM_MCR 0x00005cff + +#define MCU_SIM_CLKOCR 0x00 +#define MCU_SIM_PLLCR 0x8000 +#define MCU_SIM_CDVCR 0x0000 + +#define MCU_SIM_SYPCR 0x0000 +#define MCU_SIM_SWIV 0x00 +#define MCU_SIM_PICR 0x0000 +#define MCU_SIM_PITR 0x0000 + + +#include + + +/* By the time this RAM specific code begins to execute, DPRAM + * and DRAM should already be mapped and accessible. */ + + .text +_start: +_stext: + nop + ori.w #MCU_DISABLE_INTRPTS, %sr /* disable interrupts: */ + /* We should not need to setup the boot stack the reset should do it. */ + movea.l #_boot_stack, %sp /*set up stack at the end of DRAM:*/ + + +set_mbar_register: + moveq.l #0x07, %d1 /* Setup MBAR */ + movec %d1, %dfc + + lea.l MCU_SIM_MBAR_ADRS, %a0 + move.l #_dprbase, %d0 + andi.l #MCU_SIM_MBAR_BA_MASK, %d0 + ori.l #MCU_SIM_MBAR_AS_MASK, %d0 + moves.l %d0, %a0@ + + moveq.l #0x05, %d1 + movec.l %d1, %dfc + +/* Now we can begin to access registers in DPRAM */ + +set_sim_mcr: + /* Set Module Configuration Register */ + move.l #MCU_SIM_MCR, MCR + +/* to do: Determine cause of reset */ + + + /* + * configure system clock MC68360 p. 6-40 + * (value +1)*osc/128 = system clock + * or + * (value + 1)*osc = system clock + * You do not need to divide the oscillator by 128 unless you want to. + */ +set_sim_clock: + move.w #MCU_SIM_PLLCR, PLLCR + move.b #MCU_SIM_CLKOCR, CLKOCR + move.w #MCU_SIM_CDVCR, CDVCR + + // Wait for the PLL to settle + move.w #16384, %d0 +pll_settle_wait: + subi.w #1, %d0 + bne pll_settle_wait + + /* Setup the system protection register, and watchdog timer register */ + + move.b #MCU_SIM_SWIV, SWIV + move.w #MCU_SIM_PICR, PICR + move.w #MCU_SIM_PITR, PITR + move.w #MCU_SIM_SYPCR, SYPCR + +/* Clear DPRAM - system + parameter */ + movea.l #_dprbase, %a0 + movea.l #_dprbase+0x2000, %a1 + + /* Copy 0 to %a0 until %a0 == %a1 */ +clear_dpram: + movel #0, %a0@+ + cmpal %a0, %a1 + bhi clear_dpram + +configure_memory_controller: + /* + * Set up Global Memory Register (GMR) + */ + move.l #MCU_SIM_GMR, %d0 + move.l %d0, GMR + +configure_chip_select_0: + move.l #0x00400000, %d0 + subq.l #0x01, %d0 + eori.l #SIM_OR_MASK, %d0 + ori.l #SIM_OR0_MASK, %d0 + move.l %d0, OR0 + + move.l #__flashstart, %d0 + ori.l #SIM_BR0_MASK, %d0 + move.l %d0, BR0 + + move.l #0x0, BR1 + move.l #0x0, BR2 + move.l #0x0, BR3 + move.l #0x0, BR4 + move.l #0x0, BR5 + move.l #0x0, BR6 + move.l #0x0, BR7 + + move.w #MCU_SIM_PEPAR, PEPAR + +/* point to vector table: */ + move.l #_romvec, %a0 + move.l #_ramvec, %a1 +copy_vectors: + move.l %a0@, %d0 + move.l %d0, %a1@ + move.l %a0@, %a1@ + addq.l #0x04, %a0 + addq.l #0x04, %a1 + cmp.l #_start, %a0 + blt copy_vectors + + move.l #_ramvec, %a1 + movec %a1, %vbr + + + /* Copy data segment from ROM to RAM */ + moveal #__data_rom_start, %a0 + moveal #__data_start, %a1 + moveal #__data_end, %a2 + + /* Copy %a0 to %a1 until %a1 == %a2 */ +LD1: + move.l %a0@, %d0 + addq.l #0x04, %a0 + move.l %d0, %a1@ + addq.l #0x04, %a1 + cmp.l #__data_end, %a1 + blt LD1 + + moveal #__bss_start, %a0 + moveal #end, %a1 + + /* Copy 0 to %a0 until %a0 == %a1 */ +L1: + movel #0, %a0@+ + cmpal %a0, %a1 + bhi L1 + +load_quicc: + move.l #_dprbase, _quicc_base + +store_ram_size: + /* Set ram size information */ + move.l #_sdata, _rambase + move.l #end, _ramstart + move.l #__ramend, %d0 + sub.l #0x1000, %d0 /* Reserve 4K for stack space.*/ + move.l %d0, _ramend /* Different from __ramend.*/ + +store_flash_size: + /* Set rom size information */ + move.l #__flashend, %d0 + sub.l #__flashstart, %d0 + move.l %d0, rom_length + + pea 0 + pea env + pea %sp@(4) + pea 0 + + lea init_thread_union, %a2 + lea 0x2000(%a2), %sp + +lp: + jsr start_kernel + /* jmp lp */ + +_exit: + + jmp _exit + + + + .data + .align 4 +env: + .long 0 +_quicc_base: + .long 0 +_periph_base: + .long 0 +_ramvec: + .long 0 +_rambase: + .long 0 +_ramstart: + .long 0 +_ramend: + .long 0 + .text + + /* + * These are the exception vectors at boot up, they are copied into RAM + * and then overwritten as needed. + */ + +.section ".data.initvect","awx" + .long _boot_stack /* Reset: Initial Stack Pointer - 0. */ + .long _start /* Reset: Initial Program Counter - 1. */ + .long buserr /* Bus Error - 2. */ + .long trap /* Address Error - 3. */ + .long trap /* Illegal Instruction - 4. */ + .long trap /* Divide by zero - 5. */ + .long trap /* CHK, CHK2 Instructions - 6. */ + .long trap /* TRAPcc, TRAPV Instructions - 7. */ + .long trap /* Privilege Violation - 8. */ + .long trap /* Trace - 9. */ + .long trap /* Line 1010 Emulator - 10. */ + .long trap /* Line 1111 Emualtor - 11. */ + .long trap /* Harware Breakpoint - 12. */ + .long trap /* (Reserved for Coprocessor Protocol Violation)- 13. */ + .long trap /* Format Error - 14. */ + .long trap /* Uninitialized Interrupt - 15. */ + .long trap /* (Unassigned, Reserver) - 16. */ + .long trap /* (Unassigned, Reserver) - 17. */ + .long trap /* (Unassigned, Reserver) - 18. */ + .long trap /* (Unassigned, Reserver) - 19. */ + .long trap /* (Unassigned, Reserver) - 20. */ + .long trap /* (Unassigned, Reserver) - 21. */ + .long trap /* (Unassigned, Reserver) - 22. */ + .long trap /* (Unassigned, Reserver) - 23. */ + .long trap /* Spurious Interrupt - 24. */ + .long trap /* Level 1 Interrupt Autovector - 25. */ + .long trap /* Level 2 Interrupt Autovector - 26. */ + .long trap /* Level 3 Interrupt Autovector - 27. */ + .long trap /* Level 4 Interrupt Autovector - 28. */ + .long trap /* Level 5 Interrupt Autovector - 29. */ + .long trap /* Level 6 Interrupt Autovector - 30. */ + .long trap /* Level 7 Interrupt Autovector - 31. */ + .long system_call /* Trap Instruction Vectors 0 - 32. */ + .long trap /* Trap Instruction Vectors 1 - 33. */ + .long trap /* Trap Instruction Vectors 2 - 34. */ + .long trap /* Trap Instruction Vectors 3 - 35. */ + .long trap /* Trap Instruction Vectors 4 - 36. */ + .long trap /* Trap Instruction Vectors 5 - 37. */ + .long trap /* Trap Instruction Vectors 6 - 38. */ + .long trap /* Trap Instruction Vectors 7 - 39. */ + .long trap /* Trap Instruction Vectors 8 - 40. */ + .long trap /* Trap Instruction Vectors 9 - 41. */ + .long trap /* Trap Instruction Vectors 10 - 42. */ + .long trap /* Trap Instruction Vectors 11 - 43. */ + .long trap /* Trap Instruction Vectors 12 - 44. */ + .long trap /* Trap Instruction Vectors 13 - 45. */ + .long trap /* Trap Instruction Vectors 14 - 46. */ + .long trap /* Trap Instruction Vectors 15 - 47. */ + .long 0 /* (Reserved for Coprocessor) - 48. */ + .long 0 /* (Reserved for Coprocessor) - 49. */ + .long 0 /* (Reserved for Coprocessor) - 50. */ + .long 0 /* (Reserved for Coprocessor) - 51. */ + .long 0 /* (Reserved for Coprocessor) - 52. */ + .long 0 /* (Reserved for Coprocessor) - 53. */ + .long 0 /* (Reserved for Coprocessor) - 54. */ + .long 0 /* (Reserved for Coprocessor) - 55. */ + .long 0 /* (Reserved for Coprocessor) - 56. */ + .long 0 /* (Reserved for Coprocessor) - 57. */ + .long 0 /* (Reserved for Coprocessor) - 58. */ + .long 0 /* (Unassigned, Reserved) - 59. */ + .long 0 /* (Unassigned, Reserved) - 60. */ + .long 0 /* (Unassigned, Reserved) - 61. */ + .long 0 /* (Unassigned, Reserved) - 62. */ + .long 0 /* (Unassigned, Reserved) - 63. */ + /* The assignment of these vectors to the CPM is */ + /* dependant on the configuration of the CPM vba */ + /* fields. */ + .long 0 /* (User-Defined Vectors 1) CPM Error - 64. */ + .long 0 /* (User-Defined Vectors 2) CPM Parallel IO PC11- 65. */ + .long 0 /* (User-Defined Vectors 3) CPM Parallel IO PC10- 66. */ + .long 0 /* (User-Defined Vectors 4) CPM SMC2 / PIP - 67. */ + .long 0 /* (User-Defined Vectors 5) CPM SMC1 - 68. */ + .long 0 /* (User-Defined Vectors 6) CPM SPI - 69. */ + .long 0 /* (User-Defined Vectors 7) CPM Parallel IO PC9 - 70. */ + .long 0 /* (User-Defined Vectors 8) CPM Timer 4 - 71. */ + .long 0 /* (User-Defined Vectors 9) CPM Reserved - 72. */ + .long 0 /* (User-Defined Vectors 10) CPM Parallel IO PC8- 73. */ + .long 0 /* (User-Defined Vectors 11) CPM Parallel IO PC7- 74. */ + .long 0 /* (User-Defined Vectors 12) CPM Parallel IO PC6- 75. */ + .long 0 /* (User-Defined Vectors 13) CPM Timer 3 - 76. */ + .long 0 /* (User-Defined Vectors 14) CPM Reserved - 77. */ + .long 0 /* (User-Defined Vectors 15) CPM Parallel IO PC5- 78. */ + .long 0 /* (User-Defined Vectors 16) CPM Parallel IO PC4- 79. */ + .long 0 /* (User-Defined Vectors 17) CPM Reserved - 80. */ + .long 0 /* (User-Defined Vectors 18) CPM RISC Timer Tbl - 81. */ + .long 0 /* (User-Defined Vectors 19) CPM Timer 2 - 82. */ + .long 0 /* (User-Defined Vectors 21) CPM Reserved - 83. */ + .long 0 /* (User-Defined Vectors 22) CPM IDMA2 - 84. */ + .long 0 /* (User-Defined Vectors 23) CPM IDMA1 - 85. */ + .long 0 /* (User-Defined Vectors 24) CPM SDMA Bus Err - 86. */ + .long 0 /* (User-Defined Vectors 25) CPM Parallel IO PC3- 87. */ + .long 0 /* (User-Defined Vectors 26) CPM Parallel IO PC2- 88. */ + .long 0 /* (User-Defined Vectors 27) CPM Timer 1 - 89. */ + .long 0 /* (User-Defined Vectors 28) CPM Parallel IO PC1- 90. */ + .long 0 /* (User-Defined Vectors 29) CPM SCC 4 - 91. */ + .long 0 /* (User-Defined Vectors 30) CPM SCC 3 - 92. */ + .long 0 /* (User-Defined Vectors 31) CPM SCC 2 - 93. */ + .long 0 /* (User-Defined Vectors 32) CPM SCC 1 - 94. */ + .long 0 /* (User-Defined Vectors 33) CPM Parallel IO PC0- 95. */ + /* I don't think anything uses the vectors after here. */ + .long 0 /* (User-Defined Vectors 34) - 96. */ + .long 0,0,0,0,0 /* (User-Defined Vectors 35 - 39). */ + .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 40 - 49). */ + .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 50 - 59). */ + .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 60 - 69). */ + .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 70 - 79). */ + .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 80 - 89). */ + .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 90 - 99). */ + .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 100 - 109). */ + .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 110 - 119). */ + .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 120 - 129). */ + .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 130 - 139). */ + .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 140 - 149). */ + .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 150 - 159). */ + .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 160 - 169). */ + .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 170 - 179). */ + .long 0,0,0,0,0,0,0,0,0,0 /* (User-Defined Vectors 180 - 189). */ + .long 0,0,0 /* (User-Defined Vectors 190 - 192). */ +.text +ignore: rte diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/68360/uCquicc/ram.ld linux.2.5.45-ac1/arch/m68knommu/platform/68360/uCquicc/ram.ld --- linux.2.5.45/arch/m68knommu/platform/68360/uCquicc/ram.ld 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/68360/uCquicc/ram.ld 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,113 @@ +MEMORY +{ + romvec : ORIGIN = 0x00000000, LENGTH = 1028 + flash : ORIGIN = 1028, LENGTH = 0x00080000 - 1028 + eflash : ORIGIN = 0x00000000 + 0x00100000, LENGTH = 1 + ramvec : ORIGIN = 0x00200000, LENGTH = 1028 + ram : ORIGIN = 0x00200000 + 1028, LENGTH = 0x00080000 - 1028 + eram : ORIGIN = 0x00200000 + 0x00080000, LENGTH = 1 + dpram : ORIGIN = 0xffffe000, LENGTH = 0x00002000 +} + +jiffies = jiffies_64 + 4; + +SECTIONS +{ + .dpram : + { + _dprbase = . ; + } > dpram + + .romvec : + { + _romvec = . ; + __flashstart = . ; + *(.data.initvect) + . = ALIGN(4); + } > romvec + + .text : + { + text_start = . ; + *(.text) + *(.exit.text) + *(.text.*) + *(.rodata) + *(.fixup) + *(.kstrtab) + __start___ksymtab = . ; + *(__ksymtab) + __stop___ksymtab = . ; + __start___ex_table = . ; + *(___ex_table) + __stop___ex_table = . ; + . = ALIGN(4) ;_etext = . ; + __data_rom_start = ALIGN ( 4 ) ; + } > flash + + .eflash : + { + __flashend = . ; + } > eflash + + + .ramvec : + { + __ramstart = . ; + _ramvec = . ; + } > ramvec + + .data : + { + _sdata = . ; + __data_start = . ; + . = ALIGN(0x2000) ; + *(.data.init_task) + . = ALIGN(0x2000) ; + *(.data) + *(.data.*) + *(.setup.init) + *(.exitcall.exit) + . = ALIGN(4096) ; + __init_begin = .; + *(.init.text) + *(.init.data) + . = ALIGN(16); + __setup_start = .; + *(.init.setup) + __setup_end = .; + __initcall_start = .; + *(.initcall1.init) + *(.initcall2.init) + *(.initcall3.init) + *(.initcall4.init) + *(.initcall5.init) + *(.initcall6.init) + *(.initcall7.init) + __initcall_end = .; + . = ALIGN(4) ; + __init_end = .; + _edata = . ; + edata = .; + } > ram + + .bss : + { + _sbss = ALIGN( 0x10 ) ; + __bss_start = ALIGN( 0x10 ) ; + __data_end = ALIGN( 0x10 ) ; + *(.bss) + *(COMMON) + _ebss = . ; + __bss_end = . ; + end = ALIGN( 0x10 ) ; + _end = ALIGN( 0x10 ) ; + } > ram + + .eram : + { + _boot_stack = . - 4; + __ramend = . ; + + } > eram +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/68360/uCquicc/rom.ld linux.2.5.45-ac1/arch/m68knommu/platform/68360/uCquicc/rom.ld --- linux.2.5.45/arch/m68knommu/platform/68360/uCquicc/rom.ld 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/68360/uCquicc/rom.ld 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,113 @@ +MEMORY +{ + romvec : ORIGIN = 0x00000000, LENGTH = 1028 + flash : ORIGIN = 1028, LENGTH = 0x00200000 - 1028 + eflash : ORIGIN = 0x00000000 + 0x00200000, LENGTH = 1 + ramvec : ORIGIN = 0x00200000, LENGTH = 1028 + ram : ORIGIN = 0x00200000 + 1028, LENGTH = 0x00200000 - 1028 + eram : ORIGIN = 0x00200000 + 0x00200000, LENGTH = 1 + dpram : ORIGIN = 0xffffe000, LENGTH = 0x00002000 +} + +jiffies = jiffies_64 + 4; + +SECTIONS +{ + .dpram : + { + _dprbase = . ; + } > dpram + + .romvec : + { + _romvec = . ; + __flashstart = . ; + *(.data.initvect) + . = ALIGN(4); + } > romvec + + .text : + { + text_start = . ; + *(.text) + *(.exit.text) + *(.text.*) + *(.rodata) + *(.fixup) + *(.kstrtab) + __start___ksymtab = . ; + *(__ksymtab) + __stop___ksymtab = . ; + __start___ex_table = . ; + *(___ex_table) + __stop___ex_table = . ; + . = ALIGN(4) ;_etext = . ; + __data_rom_start = ALIGN ( 4 ) ; + } > flash + + .eflash : + { + __flashend = . ; + } > eflash + + + .ramvec : + { + __ramstart = . ; + _ramvec = . ; + } > ramvec + + .data : + { + _sdata = . ; + __data_start = . ; + . = ALIGN(0x2000) ; + *(.data.init_task) + . = ALIGN(0x2000) ; + *(.data) + *(.data.*) + *(.setup.init) + *(.exitcall.exit) + . = ALIGN(4096) ; + __init_begin = .; + *(.init.text) + *(.init.data) + . = ALIGN(16); + __setup_start = .; + *(.init.setup) + __setup_end = .; + __initcall_start = .; + *(.initcall1.init) + *(.initcall2.init) + *(.initcall3.init) + *(.initcall4.init) + *(.initcall5.init) + *(.initcall6.init) + *(.initcall7.init) + __initcall_end = .; + . = ALIGN(4) ; + __init_end = .; + _edata = . ; + edata = .; + } > ram + + .bss : + { + _sbss = ALIGN( 0x10 ) ; + __bss_start = ALIGN( 0x10 ) ; + __data_end = ALIGN( 0x10 ) ; + *(.bss) + *(COMMON) + _ebss = . ; + __bss_end = . ; + end = ALIGN( 0x10 ) ; + _end = ALIGN( 0x10 ) ; + } > ram + + .eram : + { + _boot_stack = . - 4; + __ramend = . ; + + } > eram +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/68EZ328/bootlogo.h linux.2.5.45-ac1/arch/m68knommu/platform/68EZ328/bootlogo.h --- linux.2.5.45/arch/m68knommu/platform/68EZ328/bootlogo.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/68EZ328/bootlogo.h 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,3204 @@ +#define splash_width 640 +#define splash_height 480 +static unsigned char splash_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, + 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xf8, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xe0, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, + 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0x7f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, + 0x03, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0xfe, 0xff, 0x1f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x7c, 0x00, 0xe0, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, + 0x00, 0x00, 0xf8, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0xe0, 0x7f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x7f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xfc, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, + 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x3f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3e, 0xf8, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, + 0x00, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0xfe, 0xff, 0x1f, + 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfc, 0x7f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7f, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x7f, 0xe0, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xe0, 0xff, + 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xe0, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x7f, 0xe0, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x1f, + 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, + 0xf0, 0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xe0, 0xff, + 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xf0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x7f, 0xe0, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xe0, 0xff, 0x07, 0xfe, 0xff, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, + 0x03, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xe0, 0xff, 0x01, 0xf8, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, + 0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, + 0x00, 0xf0, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x7f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7f, 0x00, 0xe0, 0xff, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0x03, + 0x3f, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xe0, 0x3f, 0x00, 0xc0, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x0f, 0xfc, 0x00, 0x00, 0x00, + 0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x1f, + 0x00, 0x80, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, + 0xff, 0xff, 0xff, 0x3f, 0xf0, 0x01, 0x00, 0x00, 0xf8, 0xff, 0x7f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x1f, 0x00, 0x80, 0xff, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x3f, 0x00, 0xc0, 0xff, + 0xc1, 0x03, 0x00, 0x00, 0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xfe, 0x0f, 0x00, 0x00, 0xfc, 0x07, 0x07, 0x00, 0x00, + 0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x0f, + 0x00, 0x00, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, + 0x07, 0x00, 0x00, 0xe0, 0x07, 0x0e, 0x00, 0x00, 0xf8, 0xff, 0x7f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0xff, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x01, 0x00, 0x00, 0x00, + 0x3f, 0x1c, 0x00, 0x00, 0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x38, 0x00, 0x00, + 0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x0f, + 0x00, 0x00, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, + 0x00, 0x00, 0x00, 0x00, 0x78, 0x70, 0x00, 0x00, 0xf8, 0xff, 0x7f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0xff, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0xf0, 0xe0, 0x00, 0x00, 0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc3, 0x01, 0x00, + 0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x1f, + 0x00, 0x80, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, + 0x00, 0x00, 0x00, 0x00, 0x80, 0xc7, 0x03, 0x00, 0xf8, 0xff, 0x7f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x1f, 0x00, 0x80, 0xff, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x87, 0x03, 0x00, 0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xe0, 0x3f, 0x00, 0xc0, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x07, 0x00, + 0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7f, + 0x00, 0xe0, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x1f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0e, 0x00, 0xf0, 0xff, 0x7f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x00, 0xf0, 0xff, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x1f, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x0c, 0x00, 0xf0, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xe0, 0xff, 0x01, 0xf8, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x1c, 0x00, + 0xf0, 0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x07, 0xfe, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x38, 0x00, 0xf0, 0xff, 0x7f, 0xe0, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x38, 0x00, 0xf0, 0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x71, 0x00, + 0xe0, 0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0x00, 0xe0, 0xff, 0x7f, 0xe0, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xe2, 0x00, 0xe0, 0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, + 0xe0, 0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0xc0, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xe0, 0x01, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01, + 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x03, 0x80, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc0, 0x03, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x03, + 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x07, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc0, 0x07, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07, + 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x07, 0x00, 0xfe, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc0, 0x07, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x07, + 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x07, 0x00, 0xf8, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc0, 0x07, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x07, + 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07, 0x00, 0xf0, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x07, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, + 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x9f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xfe, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, + 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x0f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1c, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, + 0xf8, 0xff, 0x1f, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x80, 0xff, 0xff, 0x00, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x38, 0x00, 0xfe, 0xff, 0x0f, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, + 0x00, 0xf8, 0xff, 0xff, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0xc0, 0xff, 0xff, + 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0xfc, 0xff, 0x7f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0xe0, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, + 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, + 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xfe, 0x3f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, + 0xff, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfc, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x1f, 0xc0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, + 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, + 0xfe, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0xf0, 0xff, 0xff, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x38, 0x00, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, + 0x00, 0xf8, 0xff, 0x01, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0xc0, 0xff, 0x01, + 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0xfc, 0x01, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x41, 0x08, 0x04, 0xb3, 0x07, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0xe0, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x41, 0x08, 0x04, 0xb3, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x18, 0x8e, 0x31, 0x7b, 0x30, + 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x18, 0x8e, 0x31, 0x7b, 0x30, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0xf8, + 0x41, 0xc6, 0x84, 0x0c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x0f, 0x00, 0x00, 0xf8, 0x41, 0xc6, 0x84, 0x0c, + 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x0f, 0x00, 0x00, 0x18, 0x0c, 0x08, 0x00, 0x40, 0xc0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x00, 0xe4, + 0xb1, 0xc1, 0x98, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0x09, 0x00, 0x00, 0xe4, 0xb1, 0xc1, 0x98, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xfc, 0x3f, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, + 0x08, 0x00, 0x00, 0x1c, 0x02, 0x08, 0x04, 0x4c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, + 0xff, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x1c, + 0x02, 0x08, 0x04, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x1f, 0xc0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x10, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x64, 0x4c, 0x00, 0x00, 0x00, + 0x36, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0xf0, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x09, 0x00, 0x00, 0x64, 0x4c, 0x00, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xff, 0x03, 0xf0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x9c, + 0x01, 0x08, 0x83, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x03, 0xf0, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x0f, 0x00, 0x00, 0x64, 0x8c, 0x01, 0x18, 0x40, + 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0xff, 0x03, 0xf0, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, + 0x0f, 0x00, 0x00, 0x64, 0x8c, 0x01, 0x18, 0x40, 0x30, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xff, 0x03, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x00, 0x9b, + 0x01, 0xc0, 0x00, 0x00, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbc, 0xff, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0x09, 0x00, 0x00, 0x9b, 0x01, 0xc0, 0x00, 0x00, + 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xc0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xf8, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, + 0x00, 0x00, 0x00, 0x07, 0x32, 0x06, 0x18, 0x43, 0x00, 0x06, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xf0, 0xc1, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x02, 0x02, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x07, + 0x32, 0x06, 0x18, 0x43, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x02, 0x10, 0xe0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x70, 0x08, 0x00, 0x00, 0x7b, 0x00, 0x30, 0x03, 0x0c, + 0x08, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xf0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xe0, 0x07, 0x03, 0xf0, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x09, 0x00, 0xc0, 0x84, 0x8d, 0x01, 0x80, 0x00, 0xc0, 0x06, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, + 0xfd, 0x03, 0xf0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0xc0, 0x84, + 0x8d, 0x01, 0x80, 0x00, 0xc0, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfd, 0x03, 0xf0, 0x7f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xc0, 0x1b, 0x00, 0x30, 0x00, 0x40, + 0x08, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0xfc, 0x01, 0xf0, 0x3f, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x00, 0xc0, 0x1b, 0x00, 0x30, 0x00, 0x40, 0x08, 0x18, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, + 0x07, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, + 0xf8, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xc0, 0x64, + 0x42, 0x06, 0x1b, 0x03, 0x00, 0x61, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x7f, 0x00, 0xc0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0xc0, 0x64, 0x42, 0x06, 0x1b, 0x03, + 0x00, 0x61, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xf0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xfe, 0xff, 0x03, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x0f, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x80, 0x30, 0x08, 0x86, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, + 0xff, 0x3f, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0x1b, + 0x00, 0x00, 0x80, 0x30, 0x08, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xc3, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0xe0, 0x84, 0x31, 0x30, 0x04, 0x80, + 0xc1, 0x18, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xf0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1c, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0x09, 0x00, 0xc0, 0x63, 0x02, 0x06, 0x00, 0x00, 0x00, 0x60, 0x6c, 0xfc, + 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0xe0, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x08, 0x00, 0xc0, 0x63, + 0x02, 0x06, 0x00, 0x00, 0x00, 0x60, 0x6c, 0xfc, 0xff, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0xff, 0xff, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xe0, 0x1c, 0x40, 0x00, 0x1b, 0x4c, + 0x06, 0x81, 0x80, 0xfd, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x70, 0x00, 0xf0, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0xe0, 0x1c, 0x40, 0x00, 0x1b, 0x4c, 0x06, 0x81, 0x80, 0xfd, + 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x00, 0x80, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x09, 0x00, 0x20, 0x63, + 0x0c, 0x08, 0x80, 0x00, 0x30, 0x06, 0x0c, 0xfc, 0xff, 0x7f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x20, 0x63, 0x0c, 0x08, 0x80, 0x00, + 0x30, 0x06, 0x0c, 0xfc, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x3f, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x0f, 0x00, 0xd8, 0x84, 0x01, 0xc0, 0x00, 0x00, 0x06, 0x00, 0x80, 0xf1, + 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xe0, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0x00, 0xf8, 0x1b, + 0x40, 0x08, 0x84, 0x0c, 0xc0, 0x18, 0x13, 0xcc, 0xff, 0xff, 0x0f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0x0f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0xe0, 0x7f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0xf8, 0x1b, 0x40, 0x08, 0x84, 0x0c, + 0xc0, 0x18, 0x13, 0xcc, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xe0, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0xf0, 0xe4, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0x09, 0x00, 0x38, 0x80, 0x01, 0x00, 0x18, 0x30, 0x06, 0x01, 0x00, 0xc0, + 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, + 0x07, 0x00, 0x30, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x38, 0x80, + 0x01, 0x00, 0x18, 0x30, 0x06, 0x01, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x07, 0x00, 0x10, 0x84, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xd8, 0x1f, 0x30, 0x36, 0x80, 0x00, + 0x00, 0x00, 0x03, 0xf2, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xfc, 0x3f, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x4f, 0x0e, 0x00, 0x10, 0x84, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, + 0x08, 0x00, 0xd8, 0x1f, 0x30, 0x36, 0x80, 0x00, 0x00, 0x00, 0x03, 0xf2, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, + 0xff, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, + 0x08, 0x00, 0x10, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x09, 0x00, 0x3e, 0x00, + 0x82, 0x01, 0x03, 0x40, 0x30, 0x98, 0x10, 0xf0, 0xe7, 0xff, 0xff, 0xff, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x20, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x1f, 0xc0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x08, 0x00, 0x10, 0xe4, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0xe6, 0x1b, 0x00, 0x00, 0x18, 0x0c, + 0x00, 0x00, 0x00, 0xfc, 0xff, 0xfb, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x41, 0x08, 0x00, 0x30, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x00, 0xe6, 0x1b, 0x00, 0x00, 0x18, 0x0c, 0x00, 0x00, 0x00, 0xfc, + 0xff, 0xfb, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9e, + 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, + 0x08, 0x00, 0x20, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x1e, 0x64, + 0x30, 0xc6, 0x80, 0x80, 0x09, 0x06, 0x63, 0xfe, 0xf9, 0xff, 0xff, 0xff, + 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0xf8, 0xff, 0xff, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x0e, 0x00, 0xc0, 0x3c, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x1e, 0x64, 0x30, 0xc6, 0x80, 0x80, + 0x09, 0x06, 0x63, 0xfe, 0xf9, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x20, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1c, 0x80, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xc3, 0x07, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0e, 0x00, 0x39, 0x03, 0x00, 0x00, 0x04, 0x0c, 0xc0, 0x60, 0x80, 0x3f, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, + 0x00, 0xfc, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc2, + 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0f, 0x00, 0x39, 0x03, + 0x00, 0x00, 0x04, 0x0c, 0xc0, 0x60, 0x80, 0x3f, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x3e, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x80, 0xff, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0xe7, 0x04, 0x42, 0xc6, 0x00, 0x00, + 0x00, 0x00, 0xec, 0xcf, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0x0f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0xfc, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, + 0x0f, 0xc0, 0x1f, 0x80, 0x01, 0x00, 0x98, 0x4c, 0x06, 0x06, 0xf0, 0x01, + 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x01, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x09, 0xc0, 0x1f, 0x80, + 0x01, 0x00, 0x98, 0x4c, 0x06, 0x06, 0xf0, 0x01, 0x00, 0xe0, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x20, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3f, 0x08, 0xc0, 0xe6, 0x04, 0x0c, 0x08, 0x00, 0x00, + 0xc0, 0x60, 0x7c, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xf0, 0x1f, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, + 0x00, 0xc0, 0xe6, 0x04, 0x0c, 0x08, 0x00, 0x00, 0xc0, 0x60, 0x7c, 0x00, + 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, + 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0xc0, 0x19, 0x60, + 0x40, 0x00, 0x63, 0x30, 0x08, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0xf8, + 0xff, 0xf3, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x3f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xc0, 0x09, 0xc0, 0x19, 0x60, 0x40, 0x00, 0x63, 0x30, + 0x08, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xf3, 0xff, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xf0, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x78, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0f, 0xc0, 0x27, 0x03, 0x00, 0x30, 0x00, 0x03, 0x00, 0xe6, 0x1f, 0x00, + 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0xe0, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, + 0xcf, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xe0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0f, 0xc0, 0x27, 0x03, + 0x00, 0x30, 0x00, 0x03, 0x00, 0xe6, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x0f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xf0, 0x0f, 0xc0, 0xde, 0x04, 0x0c, 0x06, 0x03, 0x80, + 0xc1, 0xf8, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x7f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xfe, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0f, 0x03, 0x00, 0xf8, 0xff, 0x07, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, + 0x0f, 0xc0, 0x19, 0x00, 0x32, 0x00, 0x60, 0x30, 0x08, 0xff, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x9f, + 0x07, 0x00, 0xf8, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x09, 0xc0, 0x19, 0x00, + 0x32, 0x00, 0x60, 0x30, 0x08, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0x07, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x9f, 0x07, 0x00, 0x18, 0x40, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3f, 0x00, 0xc0, 0x27, 0x63, 0x80, 0x31, 0x04, 0x03, + 0xf0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xf8, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1c, 0xfe, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0x1f, 0x07, 0x00, 0x18, 0x40, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, + 0x00, 0xc0, 0x27, 0x63, 0x80, 0x31, 0x04, 0x03, 0xf0, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, + 0x7f, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, + 0xe0, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x31, + 0x04, 0x00, 0x10, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x08, 0x00, 0xd9, 0x04, + 0x00, 0x08, 0x00, 0x80, 0xf9, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xf0, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x7f, 0x1e, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0xfe, 0xff, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x20, 0x04, 0x00, 0x60, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xc0, 0x09, 0x00, 0xd9, 0x04, 0x00, 0x08, 0x00, 0x80, + 0xf9, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, + 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xf8, 0x7f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x78, 0x00, 0xf0, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0f, 0xc0, 0x27, 0x00, 0x30, 0xc0, 0x60, 0xb0, 0xff, 0x7f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x60, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xc0, 0xde, 0x9b, + 0x8d, 0x01, 0x04, 0xc3, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0xf1, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbc, 0x03, 0x00, 0xf0, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x07, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0xc0, 0xde, 0x9b, 0x8d, 0x01, 0x04, 0xc3, + 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xf1, 0xff, + 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3e, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xc0, 0x39, 0x04, 0x00, 0xc8, 0x00, 0xfc, 0xff, 0x07, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xf8, 0xff, 0x3f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0xc0, 0x39, 0x04, + 0x00, 0xc8, 0x00, 0xfc, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0xf8, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1f, 0x00, 0xc0, 0xc7, 0x60, 0x42, 0x00, 0x60, 0xff, + 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xf8, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, + 0x00, 0xc0, 0xc7, 0x60, 0x42, 0x00, 0x60, 0xff, 0xff, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, + 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0xc0, 0xff, 0x07, + 0xb0, 0x09, 0xe4, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x30, 0x00, 0xfc, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x7f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0e, 0x00, 0xc0, 0xde, 0x78, 0x02, 0x00, 0xfb, 0xff, + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0xff, 0x1f, 0xf8, 0xff, 0xff, 0x1f, 0xf0, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xf8, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xc0, 0xde, 0x78, 0x02, 0x00, 0xfb, 0xff, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0x1f, 0xf8, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x08, + 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xc0, 0x3f, 0x07, + 0xb0, 0xc9, 0xf8, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0xc0, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0xc0, 0x3f, 0x07, 0xb0, 0xc9, 0xf8, 0xff, + 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, + 0x0f, 0x00, 0xe7, 0xfb, 0x43, 0x30, 0xf8, 0xff, 0x0f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x0f, 0x00, 0xe7, 0xfb, + 0x43, 0x30, 0xf8, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x08, 0x70, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0xe0, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0xfe, 0x1c, 0xb2, 0x0f, 0xe0, 0xff, + 0x07, 0x00, 0xe0, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xc0, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xf8, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0x0f, 0x00, 0xf8, 0xe7, 0xfd, 0x01, 0xe0, 0xff, 0x07, 0x00, 0xe0, 0xff, + 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc1, 0xe0, + 0xb1, 0x3f, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0xf8, + 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xf0, 0xc0, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0xf8, 0xe7, + 0xfd, 0x01, 0xe0, 0xff, 0x07, 0x00, 0xe0, 0xff, 0xff, 0xff, 0x0f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc1, 0xe0, 0xb1, 0x3f, 0x00, 0x00, + 0xf8, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0xf8, 0x7f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0xf8, 0xff, 0x7f, 0x00, 0x80, 0xff, + 0x01, 0x00, 0xe0, 0x03, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x98, 0x4f, 0x0e, 0x18, 0x00, 0xf8, 0xff, 0xff, 0xff, + 0x07, 0x00, 0x00, 0xf8, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0xf8, 0xff, 0x7f, 0x00, 0x80, 0xff, 0x01, 0x00, 0xe0, 0x03, + 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, + 0x4f, 0x0e, 0xf8, 0x1f, 0xf6, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0xf8, 0xff, + 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xb1, 0x01, 0xff, 0x1f, + 0xf6, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x1f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x07, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x08, 0x00, 0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xf8, 0xb1, 0x01, 0xff, 0x7f, 0xc0, 0xff, 0xff, 0xff, + 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0x0f, 0x00, 0xe0, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, + 0x00, 0xce, 0xff, 0x7f, 0xc0, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, + 0xff, 0xe3, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0xe0, 0xff, + 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xce, 0xff, 0x7f, + 0x00, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x07, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0xc0, 0xff, 0x3f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x20, 0x1b, 0xb2, 0x31, 0xff, 0x7f, 0x00, 0xff, 0xff, 0xff, + 0x3f, 0x00, 0x00, 0xe0, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xfe, 0x03, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0x01, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0x0f, 0x00, 0xc0, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x1c, + 0x00, 0xc0, 0xff, 0x73, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xf0, + 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, + 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xc0, 0xff, + 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x07, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x1c, 0x00, 0xc0, 0x7f, 0x1c, + 0x30, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xf8, 0x7f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x78, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xc0, 0xff, 0x0f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x87, 0x31, 0x06, 0x7c, 0x1c, 0x30, 0xff, 0xff, 0xff, + 0xff, 0x00, 0x00, 0xf8, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc0, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x87, + 0x31, 0x06, 0xfc, 0x0f, 0xc8, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x38, + 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, + 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0xc0, 0xff, + 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x0f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xe6, 0x04, 0x00, 0x30, 0xe3, 0x0f, + 0xc8, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0xe0, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0xc0, 0xff, 0x0f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x30, 0xe6, 0x04, 0x00, 0x30, 0x03, 0x00, 0xf0, 0xff, 0xff, 0xff, + 0xff, 0x03, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0xe0, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, + 0x07, 0x00, 0xc0, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x1b, + 0x4c, 0x00, 0x04, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0xf0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x07, 0x00, 0xc0, 0xff, + 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x07, 0x04, 0x00, 0x06, 0x18, 0x80, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0f, 0x0e, 0x00, 0xc0, 0xff, 0x0f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x07, 0x04, 0x00, 0x06, 0x78, 0xf3, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x07, 0x00, 0xf8, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x08, 0x00, 0xc0, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x3e, 0x04, + 0x02, 0x30, 0x60, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0xf8, + 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0xc0, 0xff, + 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x3e, 0x04, 0x02, 0x30, 0xe0, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0xf8, 0x7f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0x04, 0x40, 0x00, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x07, 0x00, 0xf8, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x08, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x04, + 0x40, 0x00, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x08, + 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0e, 0x00, 0x00, 0xff, + 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x39, 0x67, 0x00, 0x06, 0xe0, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0x0f, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x06, 0x04, 0x30, 0x00, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x3f, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x0f, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x04, + 0x30, 0x00, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x08, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x06, 0x00, 0x00, 0xff, + 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x1f, 0x00, 0x7e, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x3e, 0x9b, 0x01, 0x30, 0xe0, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x08, 0x60, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xc0, 0x1f, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x3e, 0x9b, 0x01, 0x30, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x3f, 0x00, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1c, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x02, 0x00, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, + 0x01, 0x00, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x1c, + 0x0c, 0x06, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x38, + 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xe0, + 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0xff, + 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x01, 0x00, 0xf0, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x1c, 0x0c, 0x06, 0xfb, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x68, 0x7c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xf8, 0x07, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0xff, 0x03, 0x00, 0xff, 0x3f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x18, 0x00, 0x00, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x3f, 0x00, 0xc0, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0xfe, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xff, 0x03, 0x00, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, + 0x00, 0x00, 0xc0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc6, 0x9b, + 0x81, 0x01, 0x60, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x80, + 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x7f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x03, 0x00, 0xff, + 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0xc0, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc6, 0x9b, 0x81, 0x01, 0x00, 0x00, + 0xf6, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0xc0, 0x0f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x1f, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0xff, 0x03, 0x00, 0xff, 0x3f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x78, 0x0c, 0x30, 0x04, 0x00, 0xf6, 0xff, 0xff, 0xff, + 0xff, 0x3f, 0x00, 0xe8, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, + 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x78, + 0x0c, 0x30, 0x04, 0x00, 0xc8, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0xf8, + 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, + 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x80, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x64, 0x40, 0x00, 0x1c, 0x00, + 0xc8, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0xf8, 0x58, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x3f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc0, 0x64, 0x40, 0x00, 0xfc, 0x03, 0xc0, 0xff, 0xff, 0xff, + 0xff, 0x3f, 0x00, 0x78, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x08, 0x00, 0x00, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, + 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xe0, + 0x01, 0x36, 0xfc, 0x03, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x38, + 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0xff, + 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x80, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xe0, 0x01, 0x36, 0xfc, 0x1f, + 0x30, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x18, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0x8f, 0x01, 0x00, 0xff, 0x3f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc6, 0x87, 0x0f, 0x00, 0xff, 0x1f, 0x30, 0xff, 0xff, 0xff, + 0xff, 0x07, 0x00, 0x08, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xcf, 0x03, 0x00, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, + 0x00, 0x00, 0xc0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x40, 0xc0, 0xff, 0x7f, 0xc0, 0xfe, 0xff, 0xff, 0xff, 0x07, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x0f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xcf, 0x03, 0x00, 0xff, + 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0xc0, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x40, 0xc0, 0xff, 0x7f, + 0x00, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0x8f, 0x01, 0x00, 0xff, 0x7f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0x0e, 0xc6, 0xff, 0x7f, 0x00, 0xff, 0xff, 0xff, + 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, + 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x0e, 0xc6, 0xff, 0x7f, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0c, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, + 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x01, 0x00, 0xf0, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x9c, 0x01, 0x30, 0xff, 0x7f, + 0x00, 0xfe, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xf0, 0x01, 0x00, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x20, 0x9c, 0x01, 0x30, 0xff, 0x63, 0x30, 0xff, 0xff, 0xff, + 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x08, 0x00, 0x00, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x07, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, + 0x4c, 0x00, 0xff, 0x63, 0x30, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0xff, + 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x3e, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb2, 0x31, 0xfc, 0x1f, + 0x00, 0xff, 0xff, 0xfd, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0xff, 0xff, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xb2, 0x31, 0xfc, 0x0f, 0x00, 0xff, 0xff, 0x03, + 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0e, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0x0f, 0x00, 0x00, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, + 0x41, 0x00, 0xe0, 0x0f, 0x00, 0xff, 0xff, 0x03, 0xff, 0x03, 0x00, 0x38, + 0x80, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0xff, + 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x41, 0x00, 0x00, 0x80, + 0xc9, 0xf9, 0xff, 0x3d, 0xff, 0x03, 0x00, 0x78, 0xc0, 0x0f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0xff, 0xff, 0x07, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x60, 0x32, 0x08, 0x00, 0x80, 0xc9, 0xf9, 0xff, 0x3d, + 0xff, 0x03, 0x00, 0xf8, 0xc0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xf8, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x02, 0x00, 0x00, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, + 0x32, 0x08, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xcf, 0xff, 0x00, 0x00, 0xf8, + 0x81, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0xff, + 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xe0, 0x01, 0xf8, 0x00, 0x00, + 0xf0, 0xff, 0xff, 0xcf, 0xff, 0x00, 0x00, 0x38, 0x03, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x60, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xff, 0xff, 0x3f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x03, 0x80, 0xff, 0xff, 0xff, 0xff, + 0x3f, 0x00, 0x00, 0x38, 0x06, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, + 0xff, 0xff, 0x03, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x38, + 0x1e, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x18, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0e, 0x00, 0x00, 0xff, + 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x03, 0xfc, + 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x38, 0xfc, 0x1f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x70, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0xff, 0xff, 0x3f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x1f, 0x00, 0x00, 0x38, 0xf8, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, + 0x80, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0x0f, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x78, + 0xf0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xe0, 0x1f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x07, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0xf8, 0xc1, 0x07, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x60, 0xf8, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0x03, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xc0, 0xff, + 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x1f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x01, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x67, + 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xf8, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x13, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xc0, 0xff, + 0xff, 0xff, 0x1f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0x67, 0xfe, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x1f, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xf0, 0xff, 0xff, 0x98, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, + 0x0f, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x98, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0xf8, 0xff, + 0xff, 0xff, 0x7f, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x3f, 0xe7, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0xff, 0xfc, 0xff, 0xff, 0xff, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, + 0xff, 0xff, 0x3f, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, + 0x00, 0xc0, 0xff, 0x67, 0x8c, 0xf9, 0xfb, 0x73, 0x00, 0x67, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xf8, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x80, + 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0xc0, 0xff, 0x67, + 0x8c, 0xf9, 0xfb, 0x73, 0x00, 0x67, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x1f, 0xe7, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x07, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0x00, 0xc0, 0x27, 0xfc, 0x73, 0xc6, 0x1c, 0x8c, + 0x37, 0x80, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, + 0xff, 0xff, 0x1f, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, + 0x00, 0x00, 0x00, 0xf0, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0xc0, 0x27, 0xfc, 0x73, 0xc6, 0x1c, 0x8c, 0x37, 0x80, 0x0c, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xfc, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, + 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x08, 0xc0, 0xfe, 0x03, + 0x8c, 0x09, 0xe3, 0x73, 0xc8, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0x0f, 0xc0, 0xfe, 0x03, 0x8c, 0x09, 0xe3, 0x73, + 0xc8, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0x0f, 0xc0, 0x27, 0xe7, 0x31, 0x36, 0x04, 0x8c, 0x01, 0x60, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0f, 0xc0, 0xde, 0x18, + 0x42, 0xc0, 0x98, 0x30, 0x08, 0x01, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0x0f, 0xc0, 0xde, 0x18, 0x42, 0xc0, 0x98, 0x30, + 0x08, 0x01, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xf0, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0xc0, 0x27, 0x63, 0x00, 0x08, 0x63, 0x03, 0x06, 0x60, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, + 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x07, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xc0, 0x27, 0x63, + 0x00, 0x08, 0x63, 0x03, 0x06, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x07, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0xc0, 0xd9, 0x04, 0xb2, 0x01, 0x00, 0xb0, + 0x31, 0x19, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xf9, 0xff, + 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x08, 0xc0, 0xd9, 0x04, 0xb2, 0x01, 0x00, 0xb0, 0x31, 0x19, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xff, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x07, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0c, 0xc0, 0x1e, 0x63, + 0x00, 0x30, 0x04, 0x03, 0xc8, 0x60, 0x00, 0x0e, 0x00, 0x00, 0xfc, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0x0e, 0xc0, 0xe1, 0x18, 0x80, 0x01, 0x60, 0xb0, + 0x01, 0xe7, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, + 0x0f, 0xc0, 0xe1, 0x18, 0x80, 0x01, 0x60, 0xb0, 0x01, 0xe7, 0xf3, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8d, 0x0f, 0xc0, 0x1e, 0x03, + 0x02, 0x08, 0x04, 0x00, 0xc8, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xd8, 0x0f, 0xc0, 0x1e, 0x03, 0x02, 0x08, 0x04, 0x00, + 0xc8, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0x0f, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, + 0x0b, 0x00, 0x21, 0x64, 0x40, 0xc0, 0x00, 0xb3, 0xf1, 0xfe, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xfb, 0x07, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x21, 0x64, + 0x40, 0xc0, 0x00, 0xb3, 0xf1, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xfb, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfb, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xfd, 0x00, 0xc0, 0xdf, 0x00, 0x00, 0x06, 0x60, 0x00, + 0x0e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0xf9, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, + 0x01, 0xc0, 0xdf, 0x00, 0x00, 0x06, 0x60, 0x00, 0x0e, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xf0, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x0b, 0xc0, 0xc0, 0x84, + 0x31, 0xc0, 0x00, 0x4c, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x83, 0x07, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1e, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0f, 0x0e, 0xc0, 0x3f, 0x18, 0x00, 0x06, 0x84, 0x80, + 0x09, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xf0, 0xc3, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, + 0x0c, 0xc0, 0x3f, 0x18, 0x00, 0x06, 0x84, 0x80, 0x09, 0xff, 0xff, 0x3f, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, + 0xc1, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x08, 0xc0, 0xc1, 0x03, + 0x4c, 0x00, 0x00, 0x30, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x90, 0x13, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x08, 0xc0, 0xc1, 0x03, 0x4c, 0x00, 0x00, 0x30, + 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0xc0, 0x3f, 0x98, 0x01, 0x08, 0x1b, 0x43, 0xc8, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x3f, 0x98, + 0x01, 0x08, 0x1b, 0x43, 0xc8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x18, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0e, 0x00, 0xc0, 0xc6, 0x03, 0x40, 0x00, 0x00, 0x80, + 0x31, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xf8, 0xef, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, + 0x00, 0x00, 0x3f, 0x18, 0x0c, 0x30, 0x60, 0x0c, 0xce, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, + 0xef, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x3f, 0x18, + 0x0c, 0x30, 0x60, 0x0c, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xc7, 0x0f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0xde, 0x63, 0x40, 0x06, 0x03, 0x30, + 0x30, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xc0, 0x83, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, + 0x00, 0x00, 0xde, 0x63, 0x40, 0x06, 0x03, 0x30, 0x30, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x04, + 0x02, 0x00, 0x00, 0x83, 0xc9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x38, 0x04, 0x02, 0x00, 0x00, 0x83, + 0xc9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xc0, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, + 0x03, 0x00, 0xe0, 0x1b, 0x0c, 0x08, 0x18, 0x40, 0x30, 0xfe, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, + 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x07, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x07, 0x00, 0xc0, 0x84, + 0x81, 0x01, 0x03, 0x0c, 0xc6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x0f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xfe, 0x07, 0x00, 0xc0, 0x84, 0x81, 0x01, 0x03, 0x0c, + 0xc6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xf8, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, + 0x0e, 0x00, 0x00, 0x1b, 0x0c, 0x30, 0x80, 0x00, 0x30, 0xf8, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x10, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x1b, + 0x0c, 0x30, 0x80, 0x00, 0x30, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x20, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x67, 0xc0, 0x01, 0x04, 0x40, + 0x00, 0xe1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x08, 0x00, 0x00, 0x67, 0xc0, 0x01, 0x04, 0x40, 0x00, 0xe1, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x30, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x9c, + 0x01, 0x08, 0x60, 0x0c, 0x06, 0x86, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xbf, 0x1f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x07, 0x0e, 0x00, 0x00, 0x18, 0x0c, 0xc0, 0x00, 0x00, + 0xc0, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xf0, 0x9f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, + 0x07, 0x00, 0x00, 0x18, 0x0c, 0xc0, 0x00, 0x00, 0xc0, 0x00, 0xfc, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, + 0x1f, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x07, 0x00, 0x00, 0xe0, + 0x01, 0x06, 0x00, 0x30, 0x06, 0x86, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x07, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0xe0, 0x01, 0x06, 0x00, 0x30, + 0x06, 0x86, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, + 0x00, 0x00, 0x00, 0x60, 0x30, 0x00, 0x63, 0x03, 0x30, 0x00, 0xe0, 0xff, + 0xff, 0xff, 0xff, 0x8f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, + 0x30, 0x00, 0x63, 0x03, 0x30, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x80, 0x83, 0x09, 0x18, 0x00, + 0x00, 0x06, 0x83, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x08, 0x00, 0x00, 0x80, 0x83, 0x09, 0x18, 0x00, 0x00, 0x06, 0x83, 0xff, + 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0x00, + 0x00, 0xc0, 0x00, 0x8c, 0xc9, 0x60, 0x00, 0xfe, 0xff, 0xff, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x8e, 0x01, 0x84, 0x40, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0x0f, 0x00, 0x00, 0x00, 0x8e, 0x01, 0x84, 0x40, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x04, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x60, 0x83, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, + 0x00, 0xc8, 0x60, 0x83, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x30, 0x06, 0x00, 0x0c, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0f, 0x00, 0x00, 0x00, 0x80, 0xc1, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x1f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x80, 0xc1, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x08, 0x60, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xf8, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xc6, + 0x03, 0x00, 0x00, 0x00, 0x40, 0x08, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xef, 0x07, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xd8, 0xef, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1c, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0xf3, + 0x0f, 0x00, 0x00, 0x00, 0x80, 0x09, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x33, 0x0c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x88, 0x13, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x13, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x33, 0x0c, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x88, 0xf3, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0xe3, + 0x0f, 0x00, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x06, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0xe1, 0x1f, 0x00, 0x00, 0x00, + 0x00, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xf0, 0xc1, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xc0, 0x07, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x60, 0xf0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xf8, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfc, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0e, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x1c, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfc, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x07, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xf8, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfc, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xf8, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0e, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0e, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfc, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xf8, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x07, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x07, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/68EZ328/config.c linux.2.5.45-ac1/arch/m68knommu/platform/68EZ328/config.c --- linux.2.5.45/arch/m68knommu/platform/68EZ328/config.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/68EZ328/config.c 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,131 @@ +/* + * linux/arch/$(ARCH)/platform/$(PLATFORM)/config.c + * + * Copyright (C) 1993 Hamish Macdonald + * Copyright (C) 1999 D. Jeff Dionne + * + * 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 +#ifdef CONFIG_UCSIMM +#include +#endif +#ifdef CONFIG_PILOT +#include "PalmV/romfs.h" +#endif + +void BSP_sched_init(void (*timer_routine)(int, void *, struct pt_regs *)) +{ + /* Restart mode, Enable int, 32KHz, Enable timer */ + TCTL = TCTL_OM | TCTL_IRQEN | TCTL_CLKSOURCE_32KHZ | TCTL_TEN; + /* Set prescaler (Divide 32KHz by 32)*/ + TPRER = 31; + /* Set compare register 32Khz / 32 / 10 = 100 */ + TCMP = 10; + + request_irq(TMR_IRQ_NUM, timer_routine, IRQ_FLG_LOCK, "timer", NULL); +} + +void BSP_tick(void) +{ + /* Reset Timer1 */ + TSTAT &= 0; +} + +unsigned long BSP_gettimeoffset (void) +{ + return 0; +} + +void BSP_gettod (int *yearp, int *monp, int *dayp, + int *hourp, int *minp, int *secp) +{ +} + +int BSP_hwclk(int op, struct hwclk_time *t) +{ + if (!op) { + /* read */ + } else { + /* write */ + } + return 0; +} + +int BSP_set_clock_mmss (unsigned long nowtime) +{ +#if 0 + short real_seconds = nowtime % 60, real_minutes = (nowtime / 60) % 60; + + tod->second1 = real_seconds / 10; + tod->second2 = real_seconds % 10; + tod->minute1 = real_minutes / 10; + tod->minute2 = real_minutes % 10; +#endif + return 0; +} + +void BSP_reset (void) +{ + local_irq_disable(); + asm volatile (" + moveal #0x10c00000, %a0; + moveb #0, 0xFFFFF300; + moveal 0(%a0), %sp; + moveal 4(%a0), %a0; + jmp (%a0); + "); +} + +unsigned char *cs8900a_hwaddr; +static int errno; + +#ifdef CONFIG_UCSIMM +_bsc0(char *, getserialnum) +_bsc1(unsigned char *, gethwaddr, int, a) +_bsc1(char *, getbenv, char *, a) +#endif + +void config_BSP(char *command, int len) +{ + unsigned char *p; + + printk("\n68EZ328 DragonBallEZ support (C) 1999 Rt-Control, Inc\n"); + +#ifdef CONFIG_UCSIMM + printk("uCsimm serial string [%s]\n",getserialnum()); + p = cs8900a_hwaddr = gethwaddr(0); + printk("uCsimm hwaddr %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n", + p[0], p[1], p[2], p[3], p[4], p[5]); + + p = getbenv("APPEND"); + if (p) strcpy(p,command); + else command[0] = 0; +#endif + + mach_sched_init = BSP_sched_init; + mach_tick = BSP_tick; + mach_gettimeoffset = BSP_gettimeoffset; + mach_gettod = BSP_gettod; + mach_hwclk = NULL; + mach_set_clock_mmss = NULL; + mach_reset = BSP_reset; + + config_M68328_irq(); +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/68EZ328/Makefile linux.2.5.45-ac1/arch/m68knommu/platform/68EZ328/Makefile --- linux.2.5.45/arch/m68knommu/platform/68EZ328/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/68EZ328/Makefile 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,14 @@ +# +# Makefile for arch/m68knommu/platform/68EZ328. +# + +obj-y := config.o + +EXTRA_TARGETS := $(BOARD)/bootlogo.rh $(BOARD)/crt0_$(MODEL).o + +include $(TOPDIR)/Rules.make + +$(obj)/$(BOARD)/bootlogo.rh: $(src)/bootlogo.h + perl $(src)/../68328/bootlogo.pl < $(src)/bootlogo.h \ + > $(obj)/$(BOARD)/bootlogo.rh + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/68EZ328/ucsimm/crt0_fixed.S linux.2.5.45-ac1/arch/m68knommu/platform/68EZ328/ucsimm/crt0_fixed.S --- linux.2.5.45/arch/m68knommu/platform/68EZ328/ucsimm/crt0_fixed.S 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/68EZ328/ucsimm/crt0_fixed.S 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,109 @@ +#include + + .global _start + .global _stext + + .global _rambase + .global _ramvec + .global _ramstart + .global _ramend + +#ifdef CONFIG_INIT_LCD + .global splash_bits +#endif + + .data + +/* + * Set up the usable of RAM stuff. Size of RAM is determined then + * an initial stack set up at the end. + */ +.align 4 +_ramvec: +.long 0 +_rambase: +.long 0 +_ramstart: +.long 0 +_ramend: +.long 0 + +#ifdef CONFIG_INIT_LCD +splash_bits: +#include "bootlogo.rh" +#endif + + .text +_start: +_stext: movew #0x2700,%sr +#ifdef CONFIG_INIT_LCD + movel #splash_bits, 0xfffffA00 /* LSSA */ + moveb #0x28, 0xfffffA05 /* LVPW */ + movew #0x280, 0xFFFFFa08 /* LXMAX */ + movew #0x1df, 0xFFFFFa0a /* LYMAX */ + moveb #0, 0xfffffa29 /* LBAR */ + moveb #0, 0xfffffa25 /* LPXCD */ + moveb #0x08, 0xFFFFFa20 /* LPICF */ + moveb #0x01, 0xFFFFFA21 /* -ve pol */ + moveb #0x81, 0xfffffA27 /* LCKCON */ + movew #0xff00, 0xfffff412 /* LCD pins */ +#endif + moveal #__ramend-CONFIG_MEMORY_RESERVE*0x100000 - 0x10, %sp + movew #32767, %d0 /* PLL settle wait loop */ +1: subq #1, %d0 + bne 1b + + /* Copy data segment from ROM to RAM */ + moveal #__data_rom_start, %a0 + moveal #_sdata, %a1 + moveal #_edata, %a2 + + /* Copy %a0 to %a1 until %a1 == %a2 */ +1: movel %a0@+, %a1@+ + cmpal %a1, %a2 + bhi 1b + + moveal #_sbss, %a0 + moveal #_ebss, %a1 + /* Copy 0 to %a0 until %a0 == %a1 */ + +1: + clrl %a0@+ + cmpal %a0, %a1 + bhi 1b + + movel #_sdata, %d0 + movel %d0, _rambase + movel #_ebss, %d0 + movel %d0, _ramstart + movel #__ramend-CONFIG_MEMORY_RESERVE*0x100000, %d0 + movel %d0, _ramend + movel #__ramvec, %d0 + movel %d0, _ramvec + +/* + * load the current task pointer and stack + */ + lea init_thread_union, %a0 + lea 0x2000(%a0), %sp + +1: jsr start_kernel + bra 1b +_exit: + + jmp _exit + + +putc: + moveb %d7,0xfffff907 +1: + movew 0xfffff906, %d7 + andw #0x2000, %d7 + beq 1b + rts + + .data +env: + .long 0 + .text + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/68EZ328/ucsimm/crt0_himem.S linux.2.5.45-ac1/arch/m68knommu/platform/68EZ328/ucsimm/crt0_himem.S --- linux.2.5.45/arch/m68knommu/platform/68EZ328/ucsimm/crt0_himem.S 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/68EZ328/ucsimm/crt0_himem.S 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1 @@ +#include "crt0_fixed.S" diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/68EZ328/ucsimm/crt0_ram.S linux.2.5.45-ac1/arch/m68knommu/platform/68EZ328/ucsimm/crt0_ram.S --- linux.2.5.45/arch/m68knommu/platform/68EZ328/ucsimm/crt0_ram.S 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/68EZ328/ucsimm/crt0_ram.S 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,172 @@ + .global __text_start + .global __main + .global __bss_start + .global __bss_end + .global __ram_start + .global __ram_end + .global __rom_start + .global __rom_end + .global __data_start + .global __data_end + + .global _rambase + .global _ramstart + + .global splash_bits + .global _start + .global _stext + +#define DEBUG +#define ROM_OFFSET 0x10C00000 +#define STACK_GAURD 0x10 + + .text + +_start: +_stext: + movew #0x2700, %sr /* Exceptions off! */ + + /* Init chip registers. uCsimm specific */ + moveb #0x00, 0xfffffb0b /* Watchdog off */ + moveb #0x10, 0xfffff000 /* SCR */ + + movew #0x2400, 0xfffff200 /* PLLCR */ + movew #0x0123, 0xfffff202 /* PLLFSR */ + + moveb #0x00, 0xfffff40b /* enable chip select */ + moveb #0x00, 0xfffff423 /* enable /DWE */ + moveb #0x08, 0xfffffd0d /* disable hardmap */ + moveb #0x07, 0xfffffd0e /* level 7 interrupt clear */ + + movew #0x8600, 0xfffff100 /* FLASH at 0x10c00000 */ + movew #0x018b, 0xfffff110 /* 2Meg, enable, 0ws */ + + movew #0x8f00, 0xfffffc00 /* DRAM configuration */ + movew #0x9667, 0xfffffc02 /* DRAM control */ + movew #0x0000, 0xfffff106 /* DRAM at 0x00000000 */ + movew #0x068f, 0xfffff116 /* 8Meg, enable, 0ws */ + + moveb #0x40, 0xfffff300 /* IVR */ + movel #0x007FFFFF, %d0 /* IMR */ + movel %d0, 0xfffff304 + + moveb 0xfffff42b, %d0 + andb #0xe0, %d0 + moveb %d0, 0xfffff42b + + moveb #0x08, 0xfffff907 /* Ignore CTS */ + movew #0x010b, 0xfffff902 /* BAUD to 9600 */ + movew #0xe100, 0xfffff900 /* enable */ + + movew #16384, %d0 /* PLL settle wait loop */ +L0: + subw #1, %d0 + bne L0 +#ifdef DEBUG + moveq #70, %d7 /* 'F' */ + moveb %d7,0xfffff907 /* No absolute addresses */ +pclp1: + movew 0xfffff906, %d7 + andw #0x2000, %d7 + beq pclp1 +#endif /* DEBUG */ + +#ifdef CONFIG_RELOCATE + /* Copy me to RAM */ + moveal #__rom_start, %a0 + moveal #__ram_start, %a1 + moveal #__data_end, %a2 + + /* Copy %a0 to %a1 until %a1 == %a2 */ +LD1: + movel %a0@+, %d0 + movel %d0, %a1@+ + cmpal %a1, %a2 + bhi LD1 + +#ifdef DEBUG + moveq #74, %d7 /* 'J' */ + moveb %d7,0xfffff907 /* No absolute addresses */ +pclp2: + movew 0xfffff906, %d7 + andw #0x2000, %d7 + beq pclp2 +#endif /* DEBUG */ + /* jump into the RAM copy */ + jmp ram_jump +ram_jump: + +#endif /* CONFIG_RELOCATE */ + +#ifdef DEBUG + moveq #82, %d7 /* 'R' */ + moveb %d7,0xfffff907 /* No absolute addresses */ +pclp3: + movew 0xfffff906, %d7 + andw #0x2000, %d7 + beq pclp3 +#endif /* DEBUG */ + moveal #0x007ffff0, %ssp + moveal #__bss_start, %a0 + moveal #__bss_end, %a1 + + /* Copy 0 to %a0 until %a0 >= %a1 */ +L1: + movel #0, %a0@+ + cmpal %a0, %a1 + bhi L1 + +#ifdef DEBUG + moveq #67, %d7 /* 'C' */ + jsr putc +#endif /* DEBUG */ + + pea 0 + pea env + pea %sp@(4) + pea 0 + +#ifdef DEBUG + moveq #70, %d7 /* 'F' */ + jsr putc +#endif /* DEBUG */ + +lp: + jsr start_kernel + jmp lp +_exit: + + jmp _exit + +__main: + /* nothing */ + rts + +#ifdef DEBUG +putc: + moveb %d7,0xfffff907 +pclp: + movew 0xfffff906, %d7 + andw #0x2000, %d7 + beq pclp + rts +#endif /* DEBUG */ + + .data + +/* + * Set up the usable of RAM stuff. Size of RAM is determined then + * an initial stack set up at the end. + */ +.align 4 +_ramvec: +.long 0 +_rambase: +.long 0 +_ramstart: +.long 0 +_ramend: +.long 0 + +env: + .long 0 diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/68EZ328/ucsimm/crt0_rom.S linux.2.5.45-ac1/arch/m68knommu/platform/68EZ328/ucsimm/crt0_rom.S --- linux.2.5.45/arch/m68knommu/platform/68EZ328/ucsimm/crt0_rom.S 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/68EZ328/ucsimm/crt0_rom.S 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1 @@ +#include "crt0_fixed.S" diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/68EZ328/ucsimm/fixed.ld linux.2.5.45-ac1/arch/m68knommu/platform/68EZ328/ucsimm/fixed.ld --- linux.2.5.45/arch/m68knommu/platform/68EZ328/ucsimm/fixed.ld 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/68EZ328/ucsimm/fixed.ld 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,108 @@ + +jiffies = jiffies_64 + 4; + +SECTIONS +{ + .romvec : + { + _flashstart = . ; + _romvec = . ; + __rom_start = . ; + } > romvec + + .text : + { + _stext = . ; + *(.text) + *(.exit.text) + . = ALIGN(0x4) ; + *(.text.*) + . = ALIGN(0x4) ; + *(.exitcall.exit) + . = ALIGN(0x4) ; + *(.kstrtab) + . = ALIGN(16); /* Exception table */ + __start___ex_table = .; + *(__ex_table) + __stop___ex_table = .; + + __start___ksymtab = .; /* Kernel symbol table */ + *(__ksymtab) + __stop___ksymtab = .; + + . = ALIGN(0x4) ; + _etext = . ; + __data_rom_start = . ; + } > flash + + .eflash : + { + _flashend = . ; + } > eflash + + .ramvec : + { + __ram_start = . ; + __ramvec = . ; + } > ramvec + + .data : + { + . = ALIGN(0x4) ; + _sdata = . ; + __data_start = . ; + + . = ALIGN(0x4) ; + *(.rodata) + . = ALIGN(0x4) ; + *(.data) + . = ALIGN(0x4) ; + *(.data.*) + + . = ALIGN(0x4) ; + __init_begin = .; + *(.init.text) + *(.init.data) + + . = ALIGN(0x4) ; + __setup_start = .; + *(.init.setup) + . = ALIGN(0x4) ; + __setup_end = .; + + . = ALIGN(0x4) ; + __initcall_start = .; + *(.initcall1.init) + *(.initcall2.init) + *(.initcall3.init) + *(.initcall4.init) + *(.initcall5.init) + *(.initcall6.init) + *(.initcall7.init) + __initcall_end = .; + . = ALIGN(0x4) ; + + . = ALIGN(0x2000) ; + *(.data.init_task) + . = ALIGN(0x2000) ; + + _edata = . ; + } > ram + + .bss : + { + . = ALIGN(0x4) ; + _sbss = . ; + *(.bss) + . = ALIGN(0x4) ; + *(COMMON) + . = ALIGN(0x4) ; + _ebss = . ; + _end = . ; + } > ram + + .eram : + { + __ramend = . ; + } > eram +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/68EZ328/ucsimm/himem.ld linux.2.5.45-ac1/arch/m68knommu/platform/68EZ328/ucsimm/himem.ld --- linux.2.5.45/arch/m68knommu/platform/68EZ328/ucsimm/himem.ld 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/68EZ328/ucsimm/himem.ld 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,11 @@ +MEMORY + { + romvec : ORIGIN = 0x00600000, LENGTH = 0x00000400 + flash : ORIGIN = 0x00600400, LENGTH = 0x00200000 - 0x00010400 + eflash : ORIGIN = 0x007f0000, LENGTH = 0 + ramvec : ORIGIN = 0x00000000, LENGTH = 0x00000400 + ram : ORIGIN = 0x00020000, LENGTH = 0x00600000 - 0x00020000 + eram : ORIGIN = 0x00600000, LENGTH = 0 + } + +INCLUDE arch/m68knommu/platform/68EZ328/ucsimm/fixed.ld diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/68EZ328/ucsimm/ram.ld linux.2.5.45-ac1/arch/m68knommu/platform/68EZ328/ucsimm/ram.ld --- linux.2.5.45/arch/m68knommu/platform/68EZ328/ucsimm/ram.ld 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/68EZ328/ucsimm/ram.ld 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,110 @@ +MEMORY + { + romvec : ORIGIN = 0x10c10000, LENGTH = 0x00000400 + flash : ORIGIN = 0x10c10400, LENGTH = 0x00200000 - 0x00010400 + eflash : ORIGIN = 0x10e00000, LENGTH = 0 + ramvec : ORIGIN = 0x00000000, LENGTH = 0x00000400 + bvec : ORIGIN = 0x00020000, LENGTH = 0x00000400 + ram : ORIGIN = 0x00020400, LENGTH = 0x00800000 - 0x00020400 + eram : ORIGIN = 0x00800000, LENGTH = 0 + } + +jiffies = jiffies_64 + 4; + +SECTIONS +{ + .fakevec : + { + } > romvec + .rom : + { + __rom_start = . ; + } > flash + .eflash : + { + _flashend = . ; + } > eflash + .realvec : + { + _ramvec = . ; + } > ramvec + .romvec : + { + _romvec = . ; + } > bvec + .text : + { + __ram_start = . ; + text_start = . ; + *(.text) + *(.exit.text) + *(.text.*) + *(.rodata) + . = ALIGN(0x4) ; + *(.kstrtab) + . = ALIGN(16); /* Exception table */ + __start___ex_table = .; + *(__ex_table) + __stop___ex_table = .; + + __start___ksymtab = .; /* Kernel symbol table */ + *(__ksymtab) + __stop___ksymtab = .; + + _etext = . ; + __data_rom_start = ALIGN ( 4 ) ; + } > ram + .data : + { + _sdata = . ; + __data_start = . ; + + . = ALIGN(0x2000) ; + *(.data.init_task) + . = ALIGN(0x2000) ; + + *(.data) + *(.data.*) + *(.exitcall.exit) + + . = ALIGN(4096) ; + __init_begin = .; + *(.init.text) + *(.init.data) + . = ALIGN(16); + __setup_start = .; + *(.init.setup) + __setup_end = .; + __initcall_start = .; + *(.initcall1.init) + *(.initcall2.init) + *(.initcall3.init) + *(.initcall4.init) + *(.initcall5.init) + *(.initcall6.init) + *(.initcall7.init) + __initcall_end = .; + . = ALIGN(4) ; + __init_end = .; + + _edata = . ; + edata = ALIGN( 0x10 ) ; + } > ram + .bss : + { + _sbss = ALIGN( 0x10 ) ; + __bss_start = ALIGN( 0x10 ) ; + __data_end = ALIGN( 0x10 ) ; + *(.bss) + *(COMMON) + _ebss = . ; + __bss_end = . ; + end = ALIGN( 0x10 ) ; + _end = ALIGN( 0x10 ) ; + } > ram + .eram : + { + __ramend = . ; + _ramend = . ; + } > eram +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/68EZ328/ucsimm/rom.ld linux.2.5.45-ac1/arch/m68knommu/platform/68EZ328/ucsimm/rom.ld --- linux.2.5.45/arch/m68knommu/platform/68EZ328/ucsimm/rom.ld 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/68EZ328/ucsimm/rom.ld 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,11 @@ +MEMORY + { + romvec : ORIGIN = 0x10c10000, LENGTH = 0x00000400 + flash : ORIGIN = 0x10c10400, LENGTH = 0x001fec00 + eflash : ORIGIN = 0x10d00000, LENGTH = 0 + ramvec : ORIGIN = 0x00000000, LENGTH = 1024 + ram : ORIGIN = 0x00020000, LENGTH = 0x00800000 - 0x00020000 + eram : ORIGIN = 0x00800000, LENGTH = 0 + } + +INCLUDE arch/m68knommu/platform/68EZ328/ucsimm/fixed.ld diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/68VZ328/de2/config.c linux.2.5.45-ac1/arch/m68knommu/platform/68VZ328/de2/config.c --- linux.2.5.45/arch/m68knommu/platform/68VZ328/de2/config.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/68VZ328/de2/config.c 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,151 @@ +/* + * linux/arch/m68knommu/platform/MC68VZ328/de2/config.c + * + * Copyright (C) 1993 Hamish Macdonald + * Copyright (C) 1999 D. Jeff Dionne + * Copyright (C) 2001 Georges Menie, Ken Desmet + * + * 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 + +#define CLOCK_COMPARE (32768/HZ) + +static void dragen2_sched_init(void (*timer_routine)(int, void *, struct pt_regs *)) +{ + /* disable timer 1 */ + TCTL = 0; + + /* set ISR */ + request_irq(TMR_IRQ_NUM, timer_routine, IRQ_FLG_LOCK, "timer", NULL); + + /* Restart mode, Enable int, 32KHz */ + TCTL = TCTL_OM | TCTL_IRQEN | TCTL_CLKSOURCE_32KHZ; + TPRER = 0; + TCMP = CLOCK_COMPARE-1; + + /* Enable timer 1 */ + TCTL |= TCTL_TEN; +} + +static void dragen2_tick(void) +{ + /* Reset Timer1 */ + TSTAT &= 0; +} + +static unsigned long dragen2_gettimeoffset(void) +{ + unsigned long ticks, offset = 0; + + ticks = TCN; + + if (ticks > (CLOCK_COMPARE>>1)) { + /* check for pending interrupt */ + if (ISR & (1<>24)%24; + *min = (now>>16)%60; + *sec = now%60; +} + +static void dragen2_reset(void) +{ + local_irq_disable(); + asm volatile (" + movel #-1, 0xFFFFF304; + moveb #0, 0xFFFFF300; + moveal #0x04000000, %a0; + moveal 0(%a0), %sp; + moveal 4(%a0), %a0; + jmp (%a0); + "); +} + +int dragen2_cs8900_setup(struct net_device *dev) +{ + /* Set the ETH hardware address from its flash monitor location */ + memcpy(dev->dev_addr, (void *)0x400fffa, 6); + dev->irq = INT1_IRQ_NUM; + return dev->base_addr = 0x08000041; +} + +static void init_hardware(void) +{ + /* CSGB Init */ + CSGBB = 0x4000; + CSB = 0x1a1; + + /* CS8900 init */ + /* PK3: hardware sleep function pin, active low */ + PKSEL |= PK(3); /* select pin as I/O */ + PKDIR |= PK(3); /* select pin as output */ + PKDATA |= PK(3); /* set pin high */ + + /* PF5: hardware reset function pin, active high */ + PFSEL |= PF(5); /* select pin as I/O */ + PFDIR |= PF(5); /* select pin as output */ + PFDATA &= ~PF(5); /* set pin low */ + + /* cs8900 hardware reset */ + PFDATA |= PF(5); + { volatile int i; for (i = 0; i < 32000; ++i); } + PFDATA &= ~PF(5); + + /* INT1 enable (cs8900 IRQ) */ + PDPOL &= ~PD(1); /* active high signal */ + PDIQEG &= ~PD(1); + PDIRQEN |= PD(1); /* IRQ enabled */ + +#ifdef CONFIG_68328_SERIAL_UART2 + /* Enable RXD TXD port bits to enable UART2 */ + PJSEL &= ~(PJ(5)|PJ(4)); +#endif +} + +void config_BSP(char *command, int len) +{ + printk("68VZ328 DragonBallVZ support (c) 2001 Lineo, Inc.\n"); + command[0] = '\0'; /* no specific boot option */ + + init_hardware(); + + mach_sched_init = dragen2_sched_init; + mach_tick = dragen2_tick; + mach_gettimeoffset = dragen2_gettimeoffset; + mach_reset = dragen2_reset; + mach_gettod = dragen2_gettod; + + config_M68VZ328_irq(); +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/68VZ328/de2/crt0_fixed.S linux.2.5.45-ac1/arch/m68knommu/platform/68VZ328/de2/crt0_fixed.S --- linux.2.5.45/arch/m68knommu/platform/68VZ328/de2/crt0_fixed.S 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/68VZ328/de2/crt0_fixed.S 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,159 @@ +#include + + .global _start + .global _stext + + .global _rambase + .global _ramvec + .global _ramstart + .global _ramend + +#ifdef CONFIG_INIT_LCD + .global splash_bits +#endif + + .data + +/* + * Set up the usable of RAM stuff. Size of RAM is determined then + * an initial stack set up at the end. + */ +.align 4 +_ramvec: +.long 0 +_rambase: +.long 0 +_ramstart: +.long 0 +_ramend: +.long 0 + +#ifdef CONFIG_INIT_LCD +splash_bits: +#include "bootlogo.rh" +#endif + + .text +_start: +_stext: + movew #0x2700,%sr + moveal #__ramend-CONFIG_MEMORY_RESERVE*0x100000 - 0x10, %sp + movel #0xffffffff, 0xfffff304 /* disable all interrupts */ + +#ifdef CONFIG_RAMKERNEL + /* Copy me from ROM to RAM */ + moveal #__rom_start, %a0 + moveal #__ram_start, %a1 + moveal #__data_end, %a2 + + /* Copy %a0 to %a1 until %a1 == %a2 */ +2: cmpal %a1, %a2 + beq 1f + movel %a0@+, %a1@+ + bra 2b +1: + /* jump into the RAM copy */ + jmp ram_jump +ram_jump: +#endif + +#ifdef CONFIG_INIT_LCD + movel #splash_bits, 0xfffffA00 /* LSSA */ + moveb #0x28, 0xfffffA05 /* LVPW */ + movew #0x280, 0xFFFFFa08 /* LXMAX */ + movew #0x1df, 0xFFFFFa0a /* LYMAX */ + moveb #0, 0xfffffa29 /* LBAR */ + moveb #0, 0xfffffa25 /* LPXCD */ + moveb #0x08, 0xFFFFFa20 /* LPICF */ + moveb #0x01, 0xFFFFFA21 /* -ve pol */ + moveb #0x81, 0xfffffA27 /* LCKCON */ + movew #0xff00, 0xfffff412 /* LCD pins */ +#endif + + moveq #13, %d7 /* '\r' */ + jsr putc + moveq #10, %d7 /* '\n' */ + jsr putc + moveq #65, %d7 /* 'A' */ + jsr putc + + movew #32767, %d0 /* PLL settle wait loop */ +1: subq #1, %d0 + bne 1b + + moveq #66, %d7 /* 'B' */ + jsr putc + +#ifndef CONFIG_RAMKERNEL + /* Copy data segment from ROM to RAM */ + moveal #__data_rom_start, %a0 + moveal #_sdata, %a1 + moveal #_edata, %a2 + + /* Copy %a0 to %a1 until %a1 == %a2 */ +2: cmpal %a1, %a2 + beq 1f + movel %a0@+, %a1@+ + bra 2b +1: +#endif + moveq #67, %d7 /* 'C' */ + jsr putc + + /* Initialize BSS segment to 0 */ + moveal #_sbss, %a0 + moveal #_ebss, %a1 + + /* Copy 0 to %a0 until %a0 == %a1 */ +2: cmpal %a0, %a1 + beq 1f + clrl %a0@+ + bra 2b +1: + moveq #68, %d7 /* 'D' */ + jsr putc + + movel #_sdata, %d0 + movel %d0, _rambase + movel #_ebss, %d0 + movel %d0, _ramstart + movel #__ramend-CONFIG_MEMORY_RESERVE*0x100000, %d0 + movel %d0, _ramend + movel #__ramvec, %d0 + movel %d0, _ramvec + + moveq #69, %d7 /* 'E' */ + jsr putc + +/* + * load the current task pointer and stack + */ + lea init_thread_union, %a0 + lea 0x2000(%a0), %sp + + moveq #70, %d7 /* 'F' */ + jsr putc + moveq #13, %d7 /* '\r' */ + jsr putc + moveq #10, %d7 /* '\n' */ + jsr putc + +1: jsr start_kernel + bra 1b + +_exit: + bra _exit + +putc: + moveb %d7,0xfffff907 +1: + movew 0xfffff906, %d7 + andw #0x2000, %d7 + beq 1b + rts + + .data +env: + .long 0 + .text + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/68VZ328/de2/crt0_himem.S linux.2.5.45-ac1/arch/m68knommu/platform/68VZ328/de2/crt0_himem.S --- linux.2.5.45/arch/m68knommu/platform/68VZ328/de2/crt0_himem.S 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/68VZ328/de2/crt0_himem.S 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1 @@ +#include "crt0_fixed.S" diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/68VZ328/de2/crt0_ram.S linux.2.5.45-ac1/arch/m68knommu/platform/68VZ328/de2/crt0_ram.S --- linux.2.5.45/arch/m68knommu/platform/68VZ328/de2/crt0_ram.S 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/68VZ328/de2/crt0_ram.S 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1 @@ +#include "crt0_fixed.S" diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/68VZ328/de2/crt0_rom.S linux.2.5.45-ac1/arch/m68knommu/platform/68VZ328/de2/crt0_rom.S --- linux.2.5.45/arch/m68knommu/platform/68VZ328/de2/crt0_rom.S 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/68VZ328/de2/crt0_rom.S 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1 @@ +#include "crt0_fixed.S" diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/68VZ328/de2/fixed.ld linux.2.5.45-ac1/arch/m68knommu/platform/68VZ328/de2/fixed.ld --- linux.2.5.45/arch/m68knommu/platform/68VZ328/de2/fixed.ld 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/68VZ328/de2/fixed.ld 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,102 @@ + +jiffies = jiffies_64 + 4; + +SECTIONS +{ + .romvec : + { + _flashstart = . ; + _romvec = . ; + __rom_start = . ; + } > romvec + + .text : + { + _stext = . ; + *(.text) + . = ALIGN(0x4) ; + *(.text.*) + . = ALIGN(0x4) ; + *(.exitcall.exit) + . = ALIGN(0x4) ; + *(.kstrtab) + . = ALIGN(16); /* Exception table */ + __start___ex_table = .; + *(__ex_table) + __stop___ex_table = .; + + __start___ksymtab = .; /* Kernel symbol table */ + *(__ksymtab) + __stop___ksymtab = .; + + . = ALIGN(0x4) ; + _etext = . ; + __data_rom_start = . ; + } > flash + + .eflash : + { + _flashend = . ; + } > eflash + + .ramvec : + { + __ram_start = . ; + __ramvec = . ; + } > ramvec + + .data : + { + . = ALIGN(0x4) ; + _sdata = . ; + __data_start = . ; + + . = ALIGN(0x4) ; + *(.rodata) + . = ALIGN(0x4) ; + *(.data) + . = ALIGN(0x4) ; + *(.data.*) + + . = ALIGN(0x4) ; + __setup_start = .; + *(.init.setup) + . = ALIGN(0x4) ; + __setup_end = .; + + . = ALIGN(0x4) ; + __initcall_start = .; + *(.initcall1.init) + *(.initcall2.init) + *(.initcall3.init) + *(.initcall4.init) + *(.initcall5.init) + *(.initcall6.init) + *(.initcall7.init) + __initcall_end = .; + . = ALIGN(0x4) ; + + . = ALIGN(0x2000) ; + *(.data.init_task) + . = ALIGN(0x2000) ; + + _edata = . ; + } > ram + + .bss : + { + . = ALIGN(0x4) ; + _sbss = . ; + *(.bss) + . = ALIGN(0x4) ; + *(COMMON) + . = ALIGN(0x4) ; + _ebss = . ; + _end = . ; + } > ram + + .eram : + { + __ramend = . ; + } > eram +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/68VZ328/de2/himem.ld linux.2.5.45-ac1/arch/m68knommu/platform/68VZ328/de2/himem.ld --- linux.2.5.45/arch/m68knommu/platform/68VZ328/de2/himem.ld 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/68VZ328/de2/himem.ld 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,11 @@ +MEMORY + { + romvec : ORIGIN = 0x01e00000, LENGTH = 1k + flash : ORIGIN = 0x01e00400, LENGTH = 2M - 1k + eflash : ORIGIN = 0x02000000, LENGTH = 0 + ramvec : ORIGIN = 0x00000000, LENGTH = 1k + ram : ORIGIN = 0x00010000, LENGTH = 30M - 64k + eram : ORIGIN = 0x01e00000, LENGTH = 0 + } + +INCLUDE arch/m68knommu/platform/68VZ328/de2/fixed.ld diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/68VZ328/de2/ram.ld linux.2.5.45-ac1/arch/m68knommu/platform/68VZ328/de2/ram.ld --- linux.2.5.45/arch/m68knommu/platform/68VZ328/de2/ram.ld 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/68VZ328/de2/ram.ld 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,109 @@ +MEMORY + { + romvec : ORIGIN = 0x04030000, LENGTH = 1k + flash : ORIGIN = 0x04030400, LENGTH = 2M - 197k + eflash : ORIGIN = 0x04200000, LENGTH = 0 + ramvec : ORIGIN = 0x00000000, LENGTH = 1k + bvec : ORIGIN = 0x00010000, LENGTH = 1k + ram : ORIGIN = 0x00010400, LENGTH = 32M - 65k + eram : ORIGIN = 0x02000000, LENGTH = 0 + } + +jiffies = jiffies_64 + 4; + +SECTIONS +{ + .fakevec : + { + } > romvec + .rom : + { + __rom_start = . ; + } > flash + .eflash : + { + _flashend = . ; + } > eflash + .realvec : + { + __ramvec = . ; + } > ramvec + .romvec : + { + _romvec = . ; + } > bvec + .text : + { + __ram_start = . ; + text_start = . ; + *(.text) + *(.text.*) + *(.rodata) + . = ALIGN(0x4) ; + *(.kstrtab) + . = ALIGN(16); /* Exception table */ + __start___ex_table = .; + *(__ex_table) + __stop___ex_table = .; + + __start___ksymtab = .; /* Kernel symbol table */ + *(__ksymtab) + __stop___ksymtab = .; + + _etext = . ; + __data_rom_start = ALIGN ( 4 ) ; + } > ram + .data : + { + _sdata = . ; + __data_start = . ; + + . = ALIGN(0x2000) ; + *(.data.init_task) + . = ALIGN(0x2000) ; + + *(.data) + *(.data.*) + *(.exitcall.exit) + + . = ALIGN(4096) ; + __init_begin = .; + *(.init.text) + *(.init.data) + . = ALIGN(16); + __setup_start = .; + *(.init.setup) + __setup_end = .; + __initcall_start = .; + *(.initcall1.init) + *(.initcall2.init) + *(.initcall3.init) + *(.initcall4.init) + *(.initcall5.init) + *(.initcall6.init) + *(.initcall7.init) + __initcall_end = .; + . = ALIGN(4) ; + __init_end = .; + + _edata = . ; + edata = ALIGN( 0x10 ) ; + } > ram + .bss : + { + _sbss = ALIGN( 0x10 ) ; + __bss_start = ALIGN( 0x10 ) ; + __data_end = ALIGN( 0x10 ) ; + *(.bss) + *(COMMON) + _ebss = . ; + __bss_end = . ; + end = ALIGN( 0x10 ) ; + _end = ALIGN( 0x10 ) ; + } > ram + .eram : + { + __ramend = . ; + _ramend = . ; + } > eram +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/68VZ328/de2/rom.ld linux.2.5.45-ac1/arch/m68knommu/platform/68VZ328/de2/rom.ld --- linux.2.5.45/arch/m68knommu/platform/68VZ328/de2/rom.ld 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/68VZ328/de2/rom.ld 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,11 @@ +MEMORY + { + romvec : ORIGIN = 0x04030000, LENGTH = 1k + flash : ORIGIN = 0x04030400, LENGTH = 2M - 197k + eflash : ORIGIN = 0x04200000, LENGTH = 0 + ramvec : ORIGIN = 0x00000000, LENGTH = 1k + ram : ORIGIN = 0x00010000, LENGTH = 32M - 64k + eram : ORIGIN = 0x02000000, LENGTH = 0 + } + +INCLUDE arch/m68knommu/platform/68VZ328/de2/fixed.ld diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/68VZ328/Makefile linux.2.5.45-ac1/arch/m68knommu/platform/68VZ328/Makefile --- linux.2.5.45/arch/m68knommu/platform/68VZ328/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/68VZ328/Makefile 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,14 @@ +# +# Makefile for arch/m68knommu/platform/68VZ328. +# + +obj-y := $(BOARD)/config.o + +EXTRA_TARGETS := $(BOARD)/bootlogo.rh $(BOARD)/crt0_$(MODEL).o + +include $(TOPDIR)/Rules.make + +$(obj)/$(BOARD)/bootlogo.rh: $(src)/../68EZ328/bootlogo.h + perl $(src)/../68328/bootlogo.pl < $(src)/../68EZ328/bootlogo.h \ + > $(obj)/$(BOARD)/bootlogo.rh + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/68VZ328/ucdimm/crt0_fixed.S linux.2.5.45-ac1/arch/m68knommu/platform/68VZ328/ucdimm/crt0_fixed.S --- linux.2.5.45/arch/m68knommu/platform/68VZ328/ucdimm/crt0_fixed.S 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/68VZ328/ucdimm/crt0_fixed.S 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,109 @@ +#include + + .global _start + .global _stext + + .global _rambase + .global _ramvec + .global _ramstart + .global _ramend + +#ifdef CONFIG_INIT_LCD + .global splash_bits +#endif + + .data + +/* + * Set up the usable of RAM stuff. Size of RAM is determined then + * an initial stack set up at the end. + */ +.align 4 +_ramvec: +.long 0 +_rambase: +.long 0 +_ramstart: +.long 0 +_ramend: +.long 0 + +#ifdef CONFIG_INIT_LCD +splash_bits: +#include "bootlogo.rh" +#endif + + .text +_start: +_stext: movew #0x2700,%sr +#ifdef CONFIG_INIT_LCD + movel #splash_bits, 0xfffffA00 /* LSSA */ + moveb #0x28, 0xfffffA05 /* LVPW */ + movew #0x280, 0xFFFFFa08 /* LXMAX */ + movew #0x1df, 0xFFFFFa0a /* LYMAX */ + moveb #0, 0xfffffa29 /* LBAR */ + moveb #0, 0xfffffa25 /* LPXCD */ + moveb #0x08, 0xFFFFFa20 /* LPICF */ + moveb #0x01, 0xFFFFFA21 /* -ve pol */ + moveb #0x81, 0xfffffA27 /* LCKCON */ + movew #0xff00, 0xfffff412 /* LCD pins */ +#endif + moveal #__ramend-CONFIG_MEMORY_RESERVE*0x100000 - 0x10, %sp + movew #32767, %d0 /* PLL settle wait loop */ +1: subq #1, %d0 + bne 1b + + /* Copy data segment from ROM to RAM */ + moveal #__data_rom_start, %a0 + moveal #_sdata, %a1 + moveal #_edata, %a2 + + /* Copy %a0 to %a1 until %a1 == %a2 */ +1: movel %a0@+, %a1@+ + cmpal %a1, %a2 + bhi 1b + + moveal #_sbss, %a0 + moveal #_ebss, %a1 + /* Copy 0 to %a0 until %a0 == %a1 */ + +1: + clrl %a0@+ + cmpal %a0, %a1 + bhi 1b + + movel #_sdata, %d0 + movel %d0, _rambase + movel #_ebss, %d0 + movel %d0, _ramstart + movel #__ramend-CONFIG_MEMORY_RESERVE*0x100000, %d0 + movel %d0, _ramend + movel #__ramvec, %d0 + movel %d0, _ramvec + +/* + * load the current task pointer and stack + */ + lea init_thread_union, %a0 + lea 0x2000(%a0), %sp + +1: jsr start_kernel + bra 1b +_exit: + + jmp _exit + + +putc: + moveb %d7,0xfffff907 +1: + movew 0xfffff906, %d7 + andw #0x2000, %d7 + beq 1b + rts + + .data +env: + .long 0 + .text + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/68VZ328/ucdimm/crt0_himem.S linux.2.5.45-ac1/arch/m68knommu/platform/68VZ328/ucdimm/crt0_himem.S --- linux.2.5.45/arch/m68knommu/platform/68VZ328/ucdimm/crt0_himem.S 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/68VZ328/ucdimm/crt0_himem.S 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1 @@ +#include "crt0_fixed.S" diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/68VZ328/ucdimm/crt0_ram.S linux.2.5.45-ac1/arch/m68knommu/platform/68VZ328/ucdimm/crt0_ram.S --- linux.2.5.45/arch/m68knommu/platform/68VZ328/ucdimm/crt0_ram.S 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/68VZ328/ucdimm/crt0_ram.S 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,176 @@ +#include + + .global __text_start + .global __main + .global __bss_start + .global __bss_end + .global __ram_start + .global __ram_end + .global __rom_start + .global __rom_end + .global __data_start + .global __data_end + + .global _rambase + .global _ramstart + + .global splash_bits + .global _start + .global _stext + +#define DEBUG +#define ROM_OFFSET 0x10C00000 +#define STACK_GAURD 0x10 + + .text + +_start: +_stext: + movew #0x2700, %sr /* Exceptions off! */ + +#if 0 + /* Init chip registers. uCsimm specific */ + moveb #0x00, 0xfffffb0b /* Watchdog off */ + moveb #0x10, 0xfffff000 /* SCR */ + + movew #0x2400, 0xfffff200 /* PLLCR */ + movew #0x0123, 0xfffff202 /* PLLFSR */ + + moveb #0x00, 0xfffff40b /* enable chip select */ + moveb #0x00, 0xfffff423 /* enable /DWE */ + moveb #0x08, 0xfffffd0d /* disable hardmap */ + moveb #0x07, 0xfffffd0e /* level 7 interrupt clear */ + + movew #0x8600, 0xfffff100 /* FLASH at 0x10c00000 */ + movew #0x018b, 0xfffff110 /* 2Meg, enable, 0ws */ + + movew #0x8f00, 0xfffffc00 /* DRAM configuration */ + movew #0x9667, 0xfffffc02 /* DRAM control */ + movew #0x0000, 0xfffff106 /* DRAM at 0x00000000 */ + movew #0x068f, 0xfffff116 /* 8Meg, enable, 0ws */ + + moveb #0x40, 0xfffff300 /* IVR */ + movel #0x007FFFFF, %d0 /* IMR */ + movel %d0, 0xfffff304 + + moveb 0xfffff42b, %d0 + andb #0xe0, %d0 + moveb %d0, 0xfffff42b + + moveb #0x08, 0xfffff907 /* Ignore CTS */ + movew #0x010b, 0xfffff902 /* BAUD to 9600 */ + movew #0xe100, 0xfffff900 /* enable */ +#endif + + movew #16384, %d0 /* PLL settle wait loop */ +L0: + subw #1, %d0 + bne L0 +#ifdef DEBUG + moveq #70, %d7 /* 'F' */ + moveb %d7,0xfffff907 /* No absolute addresses */ +pclp1: + movew 0xfffff906, %d7 + andw #0x2000, %d7 + beq pclp1 +#endif /* DEBUG */ + +#ifdef CONFIG_RELOCATE + /* Copy me to RAM */ + moveal #__rom_start, %a0 + moveal #__ram_start, %a1 + moveal #__data_end, %a2 + + /* Copy %a0 to %a1 until %a1 == %a2 */ +LD1: + movel %a0@+, %d0 + movel %d0, %a1@+ + cmpal %a1, %a2 + bhi LD1 + +#ifdef DEBUG + moveq #74, %d7 /* 'J' */ + moveb %d7,0xfffff907 /* No absolute addresses */ +pclp2: + movew 0xfffff906, %d7 + andw #0x2000, %d7 + beq pclp2 +#endif /* DEBUG */ + /* jump into the RAM copy */ + jmp ram_jump +ram_jump: + +#endif /* CONFIG_RELOCATE */ + +#ifdef DEBUG + moveq #82, %d7 /* 'R' */ + moveb %d7,0xfffff907 /* No absolute addresses */ +pclp3: + movew 0xfffff906, %d7 + andw #0x2000, %d7 + beq pclp3 +#endif /* DEBUG */ + moveal #0x007ffff0, %ssp + moveal #__bss_start, %a0 + moveal #__bss_end, %a1 + + /* Copy 0 to %a0 until %a0 >= %a1 */ +L1: + movel #0, %a0@+ + cmpal %a0, %a1 + bhi L1 + +#ifdef DEBUG + moveq #67, %d7 /* 'C' */ + jsr putc +#endif /* DEBUG */ + + pea 0 + pea env + pea %sp@(4) + pea 0 + +#ifdef DEBUG + moveq #70, %d7 /* 'F' */ + jsr putc +#endif /* DEBUG */ + +lp: + jsr start_kernel + jmp lp +_exit: + + jmp _exit + +__main: + /* nothing */ + rts + +#ifdef DEBUG +putc: + moveb %d7,0xfffff907 +pclp: + movew 0xfffff906, %d7 + andw #0x2000, %d7 + beq pclp + rts +#endif /* DEBUG */ + + .data + +/* + * Set up the usable of RAM stuff. Size of RAM is determined then + * an initial stack set up at the end. + */ +.align 4 +_ramvec: +.long 0 +_rambase: +.long 0 +_ramstart: +.long 0 +_ramend: +.long 0 + +env: + .long 0 diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/68VZ328/ucdimm/crt0_rom.S linux.2.5.45-ac1/arch/m68knommu/platform/68VZ328/ucdimm/crt0_rom.S --- linux.2.5.45/arch/m68knommu/platform/68VZ328/ucdimm/crt0_rom.S 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/68VZ328/ucdimm/crt0_rom.S 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1 @@ +#include "crt0_fixed.S" diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/68VZ328/ucdimm/fixed.ld linux.2.5.45-ac1/arch/m68knommu/platform/68VZ328/ucdimm/fixed.ld --- linux.2.5.45/arch/m68knommu/platform/68VZ328/ucdimm/fixed.ld 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/68VZ328/ucdimm/fixed.ld 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,102 @@ + +jiffies = jiffies_64 + 4; + +SECTIONS +{ + .romvec : + { + _flashstart = . ; + _romvec = . ; + __rom_start = . ; + } > romvec + + .text : + { + _stext = . ; + *(.text) + . = ALIGN(0x4) ; + *(.text.*) + . = ALIGN(0x4) ; + *(.exitcall.exit) + . = ALIGN(0x4) ; + *(.kstrtab) + . = ALIGN(16); /* Exception table */ + __start___ex_table = .; + *(__ex_table) + __stop___ex_table = .; + + __start___ksymtab = .; /* Kernel symbol table */ + *(__ksymtab) + __stop___ksymtab = .; + + . = ALIGN(0x4) ; + _etext = . ; + __data_rom_start = . ; + } > flash + + .eflash : + { + _flashend = . ; + } > eflash + + .ramvec : + { + __ram_start = . ; + __ramvec = . ; + } > ramvec + + .data : + { + . = ALIGN(0x4) ; + _sdata = . ; + __data_start = . ; + + . = ALIGN(0x4) ; + *(.rodata) + . = ALIGN(0x4) ; + *(.data) + . = ALIGN(0x4) ; + *(.data.*) + + . = ALIGN(0x4) ; + __setup_start = .; + *(.init.setup) + . = ALIGN(0x4) ; + __setup_end = .; + + . = ALIGN(0x4) ; + __initcall_start = .; + *(.initcall1.init) + *(.initcall2.init) + *(.initcall3.init) + *(.initcall4.init) + *(.initcall5.init) + *(.initcall6.init) + *(.initcall7.init) + __initcall_end = .; + . = ALIGN(0x4) ; + + . = ALIGN(0x2000) ; + *(.data.init_task) + . = ALIGN(0x2000) ; + + _edata = . ; + } > ram + + .bss : + { + . = ALIGN(0x4) ; + _sbss = . ; + *(.bss) + . = ALIGN(0x4) ; + *(COMMON) + . = ALIGN(0x4) ; + _ebss = . ; + _end = . ; + } > ram + + .eram : + { + __ramend = . ; + } > eram +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/68VZ328/ucdimm/himem.ld linux.2.5.45-ac1/arch/m68knommu/platform/68VZ328/ucdimm/himem.ld --- linux.2.5.45/arch/m68knommu/platform/68VZ328/ucdimm/himem.ld 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/68VZ328/ucdimm/himem.ld 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,11 @@ +MEMORY + { + romvec : ORIGIN = 0x00600000, LENGTH = 0x00000400 + flash : ORIGIN = 0x00600400, LENGTH = 0x00200000 - 0x00010400 + eflash : ORIGIN = 0x007f0000, LENGTH = 0 + ramvec : ORIGIN = 0x00000000, LENGTH = 0x00000400 + ram : ORIGIN = 0x00020000, LENGTH = 0x00600000 - 0x00020000 + eram : ORIGIN = 0x00600000, LENGTH = 0 + } + +INCLUDE arch/m68knommu/platform/68VZ328/ucdimm/fixed.ld diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/68VZ328/ucdimm/ram.ld linux.2.5.45-ac1/arch/m68knommu/platform/68VZ328/ucdimm/ram.ld --- linux.2.5.45/arch/m68knommu/platform/68VZ328/ucdimm/ram.ld 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/68VZ328/ucdimm/ram.ld 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,109 @@ +MEMORY + { + romvec : ORIGIN = 0x10c10000, LENGTH = 0x00000400 + flash : ORIGIN = 0x10c10400, LENGTH = 0x00200000 - 0x00010400 + eflash : ORIGIN = 0x10e00000, LENGTH = 0 + ramvec : ORIGIN = 0x00000000, LENGTH = 0x00000400 + bvec : ORIGIN = 0x00020000, LENGTH = 0x00000400 + ram : ORIGIN = 0x00020400, LENGTH = 0x00800000 - 0x00020400 + eram : ORIGIN = 0x00800000, LENGTH = 0 + } + +jiffies = jiffies_64 + 4; + +SECTIONS +{ + .fakevec : + { + } > romvec + .rom : + { + __rom_start = . ; + } > flash + .eflash : + { + _flashend = . ; + } > eflash + .realvec : + { + _ramvec = . ; + } > ramvec + .romvec : + { + _romvec = . ; + } > bvec + .text : + { + __ram_start = . ; + text_start = . ; + *(.text) + *(.text.*) + *(.rodata) + . = ALIGN(0x4) ; + *(.kstrtab) + . = ALIGN(16); /* Exception table */ + __start___ex_table = .; + *(__ex_table) + __stop___ex_table = .; + + __start___ksymtab = .; /* Kernel symbol table */ + *(__ksymtab) + __stop___ksymtab = .; + + _etext = . ; + __data_rom_start = ALIGN ( 4 ) ; + } > ram + .data : + { + _sdata = . ; + __data_start = . ; + + . = ALIGN(0x2000) ; + *(.data.init_task) + . = ALIGN(0x2000) ; + + *(.data) + *(.data.*) + *(.exitcall.exit) + + . = ALIGN(4096) ; + __init_begin = .; + *(.init.text) + *(.init.data) + . = ALIGN(16); + __setup_start = .; + *(.init.setup) + __setup_end = .; + __initcall_start = .; + *(.initcall1.init) + *(.initcall2.init) + *(.initcall3.init) + *(.initcall4.init) + *(.initcall5.init) + *(.initcall6.init) + *(.initcall7.init) + __initcall_end = .; + . = ALIGN(4) ; + __init_end = .; + + _edata = . ; + edata = ALIGN( 0x10 ) ; + } > ram + .bss : + { + _sbss = ALIGN( 0x10 ) ; + __bss_start = ALIGN( 0x10 ) ; + __data_end = ALIGN( 0x10 ) ; + *(.bss) + *(COMMON) + _ebss = . ; + __bss_end = . ; + end = ALIGN( 0x10 ) ; + _end = ALIGN( 0x10 ) ; + } > ram + .eram : + { + __ramend = . ; + _ramend = . ; + } > eram +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/68VZ328/ucdimm/rom.ld linux.2.5.45-ac1/arch/m68knommu/platform/68VZ328/ucdimm/rom.ld --- linux.2.5.45/arch/m68knommu/platform/68VZ328/ucdimm/rom.ld 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/68VZ328/ucdimm/rom.ld 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,11 @@ +MEMORY + { + romvec : ORIGIN = 0x10c10000, LENGTH = 0x00000400 + flash : ORIGIN = 0x10c10400, LENGTH = 0x001fec00 + eflash : ORIGIN = 0x10d00000, LENGTH = 0 + ramvec : ORIGIN = 0x00000000, LENGTH = 1024 + ram : ORIGIN = 0x00020000, LENGTH = 0x00800000 - 0x00020000 + eram : ORIGIN = 0x00800000, LENGTH = 0 + } + +INCLUDE arch/m68knommu/platform/68VZ328/ucdimm/fixed.ld diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/platform/Makefile linux.2.5.45-ac1/arch/m68knommu/platform/Makefile --- linux.2.5.45/arch/m68knommu/platform/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/platform/Makefile 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,6 @@ +# +# Makefile for the arch/m68knommu/platform. +# + +include $(TOPDIR)/Rules.make + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/m68knommu/vmlinux.lds.S linux.2.5.45-ac1/arch/m68knommu/vmlinux.lds.S --- linux.2.5.45/arch/m68knommu/vmlinux.lds.S 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/m68knommu/vmlinux.lds.S 2002-11-01 15:19:55.000000000 +0000 @@ -0,0 +1,115 @@ + +#include + +#ifdef CONFIG_PILOT3 +#ifdef CONFIG_ROMKERNEL +#include "platform/68328/pilot/rom.ld" +#endif +#ifdef CONFIG_RAMKERNEL +#include "platform/68328/pilot/ram.ld" +#endif +#endif + +#ifdef CONFIG_UCSIMM +#ifdef CONFIG_RAMKERNEL +#include "platform/68EZ328/ucsimm/ram.ld" +#endif +#ifdef CONFIG_ROMKERNEL +#include "platform/68EZ328/ucsimm/rom.ld" +#endif +#ifdef CONFIG_HIMEMKERNEL +#include "platform/68EZ328/ucsimm/himem.ld" +#endif +#endif + +#ifdef CONFIG_UCDIMM +#ifdef CONFIG_RAMKERNEL +#include "platform/68VZ328/ucdimm/ram.ld" +#endif +#ifdef CONFIG_ROMKERNEL +#include "platform/68VZ328/ucdimm/rom.ld" +#endif +#ifdef CONFIG_HIMEMKERNEL +#include "platform/68VZ328/ucdimm/himem.ld" +#endif +#endif +#ifdef CONFIG_DRAGEN2 +#ifdef CONFIG_RAMKERNEL +#include "platform/68VZ328/de2/ram.ld" +#endif +#ifdef CONFIG_ROMKERNEL +#include "platform/68VZ328/de2/rom.ld" +#endif +#ifdef CONFIG_HIMEMKERNEL +#include "platform/68VZ328/de2/himem.ld" +#endif +#endif + +#ifdef CONFIG_UCQUICC +#ifdef CONFIG_RAMKERNEL +#include "platform/68360/uCquicc/ram.ld" +#endif +#ifdef CONFIG_ROMKERNEL +#include "platform/68360/uCquicc/rom.ld" +#endif +#endif + +#ifdef CONFIG_ARN5206 +#include "platform/5206/ARNEWSH/ram.ld" +#endif + +#ifdef CONFIG_M5206eC3 +#include "platform/5206e/MOTOROLA/ram.ld" +#endif +#ifdef CONFIG_ELITE +#include "platform/5206e/eLITE/ram.ld" +#endif + +#ifdef CONFIG_M5249C3 +#include "platform/5249/MOTOROLA/ram.ld" +#endif + +#ifdef CONFIG_M5272C3 +#include "platform/5272/MOTOROLA/ram.ld" +#endif + +#ifdef CONFIG_ARN5307 +#include "platform/5307/ARNEWSH/ram.ld" +#endif +#ifdef CONFIG_M5307C3 +#include "platform/5307/MOTOROLA/ram.ld" +#endif +#ifdef CONFIG_eLIA +#include "platform/5307/eLIA/ram.ld" +#endif +#ifdef CONFIG_DISKtel +#include "platform/5307/DISKtel/ram.ld" +#endif +#ifdef CONFIG_SECUREEDGEMP3 +#include "platform/5307/MP3/ram.ld" +#endif + +#ifdef CONFIG_M5407 +#include "platform/5407/MOTOROLA/ram.ld" +#endif + +#ifdef CONFIG_CLEOPATRA +#ifdef CONFIG_M5307 +#include "platform/5307/CLEOPATRA/ram.ld" +#endif +#ifdef CONFIG_M5407 +#include "platform/5407/CLEOPATRA/ram.ld" +#endif +#endif + +#ifdef CONFIG_NETtel +#ifdef CONFIG_M5206e +#include "platform/5206e/NETtel/ram.ld" +#endif +#ifdef CONFIG_M5272 +#include "platform/5272/NETtel/ram.ld" +#endif +#ifdef CONFIG_M5307 +#include "platform/5307/NETtel/ram.ld" +#endif +#endif diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/mips/Kconfig linux.2.5.45-ac1/arch/mips/Kconfig --- linux.2.5.45/arch/mips/Kconfig 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.45-ac1/arch/mips/Kconfig 2002-11-01 11:34:38.000000000 +0000 @@ -6,6 +6,14 @@ bool default y +config MMU + bool + default y + +config SWAP + bool + default y + config SMP bool ---help--- diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/mips64/Kconfig linux.2.5.45-ac1/arch/mips64/Kconfig --- linux.2.5.45/arch/mips64/Kconfig 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.45-ac1/arch/mips64/Kconfig 2002-11-01 11:34:44.000000000 +0000 @@ -5,6 +5,14 @@ mainmenu "Linux Kernel Configuration" +config MMU + bool + default y + +config SWAP + bool + default y + source "init/Kconfig" diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/mips64/kernel/ioctl32.c linux.2.5.45-ac1/arch/mips64/kernel/ioctl32.c --- linux.2.5.45/arch/mips64/kernel/ioctl32.c 2002-10-31 14:57:34.000000000 +0000 +++ linux.2.5.45-ac1/arch/mips64/kernel/ioctl32.c 2002-10-31 15:05:56.000000000 +0000 @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -791,6 +792,20 @@ IOCTL32_DEFAULT(RESTART_ARRAY_RW), #endif /* CONFIG_MD */ +#if defined(CONFIG_BLK_DEV_DM) || defined(CONFIG_BLK_DEV_DM_MODULE) + IOCTL32_DEFAULT(DM_VERSION), + IOCTL32_DEFAULT(DM_REMOVE_ALL), + IOCTL32_DEFAULT(DM_DEV_CREATE), + IOCTL32_DEFAULT(DM_DEV_REMOVE), + IOCTL32_DEFAULT(DM_DEV_RELOAD), + IOCTL32_DEFAULT(DM_DEV_SUSPEND), + IOCTL32_DEFAULT(DM_DEV_RENAME), + IOCTL32_DEFAULT(DM_DEV_DEPS), + IOCTL32_DEFAULT(DM_DEV_STATUS), + IOCTL32_DEFAULT(DM_TARGET_STATUS), + IOCTL32_DEFAULT(DM_TARGET_WAIT), +#endif /* CONFIG_BLK_DEV_DM */ + IOCTL32_DEFAULT(MTIOCTOP), /* mtio.h ioctls */ IOCTL32_HANDLER(MTIOCGET32, mt_ioctl_trans), IOCTL32_HANDLER(MTIOCPOS32, mt_ioctl_trans), diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/parisc/Kconfig linux.2.5.45-ac1/arch/parisc/Kconfig --- linux.2.5.45/arch/parisc/Kconfig 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.45-ac1/arch/parisc/Kconfig 2002-11-01 11:30:04.000000000 +0000 @@ -20,6 +20,14 @@ bool default y +coonfig MMU + bool + default y + +config SWAP + bool + default y + config RWSEM_XCHGADD_ALGORITHM bool diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/ppc/Kconfig linux.2.5.45-ac1/arch/ppc/Kconfig --- linux.2.5.45/arch/ppc/Kconfig 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.45-ac1/arch/ppc/Kconfig 2002-11-01 11:34:04.000000000 +0000 @@ -15,6 +15,13 @@ bool default y +config MMU + bool + default y + +config SWAP + bool + default y mainmenu "Linux/PowerPC Kernel Configuration" diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/ppc/platforms/mcpn765_setup.c linux.2.5.45-ac1/arch/ppc/platforms/mcpn765_setup.c --- linux.2.5.45/arch/ppc/platforms/mcpn765_setup.c 2002-10-31 14:57:21.000000000 +0000 +++ linux.2.5.45-ac1/arch/ppc/platforms/mcpn765_setup.c 2002-10-31 15:05:47.000000000 +0000 @@ -154,9 +154,9 @@ * PPCBug doesn't set the enable bits for the IDE device. * Turn them on now. */ - pcibios_read_config_byte(dev->bus->number, dev->devfn, 0x40, &c); + pci_read_config_byte(dev, 0x40, &c); c |= 0x03; - pcibios_write_config_byte(dev->bus->number, dev->devfn, 0x40, c); + pci_write_config_byte(dev, 0x40, c); return; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/ppc/platforms/prep_pci.c linux.2.5.45-ac1/arch/ppc/platforms/prep_pci.c --- linux.2.5.45/arch/ppc/platforms/prep_pci.c 2002-10-31 14:57:22.000000000 +0000 +++ linux.2.5.45-ac1/arch/ppc/platforms/prep_pci.c 2002-10-31 15:05:47.000000000 +0000 @@ -1089,8 +1089,7 @@ devnum = PCI_SLOT(tdev->devfn); /* Read the interrupt pin of the device and adjust for indexing */ - pcibios_read_config_byte(dev->bus->number, dev->devfn, - PCI_INTERRUPT_PIN, &intpin); + pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &intpin); /* If device doesn't request an interrupt, return */ if ( (intpin < 1) || (intpin > 4) ) @@ -1162,7 +1161,7 @@ pci_for_each_dev(dev) { if (dev->bus->number == 0) { dev->irq = openpic_to_irq(Motherboard_map[PCI_SLOT(dev->devfn)]); - pcibios_write_config_byte(dev->bus->number, dev->devfn, PCI_INTERRUPT_LINE, dev->irq); + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); } else { if (Motherboard_non0 != NULL) Motherboard_non0(dev); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/ppc64/Kconfig linux.2.5.45-ac1/arch/ppc64/Kconfig --- linux.2.5.45/arch/ppc64/Kconfig 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.45-ac1/arch/ppc64/Kconfig 2002-11-01 11:34:10.000000000 +0000 @@ -24,6 +24,14 @@ bool default y +config MMU + bool + default y + +config SWAP + bool + default y + source "init/Kconfig" diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/ppc64/kernel/ioctl32.c linux.2.5.45-ac1/arch/ppc64/kernel/ioctl32.c --- linux.2.5.45/arch/ppc64/kernel/ioctl32.c 2002-10-31 14:57:31.000000000 +0000 +++ linux.2.5.45-ac1/arch/ppc64/kernel/ioctl32.c 2002-10-31 15:05:55.000000000 +0000 @@ -66,6 +66,7 @@ #if defined(CONFIG_BLK_DEV_LVM) || defined(CONFIG_BLK_DEV_LVM_MODULE) #include #endif /* LVM */ +#include #include /* Ugly hack. */ @@ -4402,6 +4403,18 @@ COMPATIBLE_IOCTL(NBD_PRINT_DEBUG), COMPATIBLE_IOCTL(NBD_SET_SIZE_BLOCKS), COMPATIBLE_IOCTL(NBD_DISCONNECT), +/* device-mapper */ +COMPATIBLE_IOCTL(DM_VERSION), +COMPATIBLE_IOCTL(DM_REMOVE_ALL), +COMPATIBLE_IOCTL(DM_DEV_CREATE), +COMPATIBLE_IOCTL(DM_DEV_REMOVE), +COMPATIBLE_IOCTL(DM_DEV_RELOAD), +COMPATIBLE_IOCTL(DM_DEV_SUSPEND), +COMPATIBLE_IOCTL(DM_DEV_RENAME), +COMPATIBLE_IOCTL(DM_DEV_DEPS), +COMPATIBLE_IOCTL(DM_DEV_STATUS), +COMPATIBLE_IOCTL(DM_TARGET_STATUS), +COMPATIBLE_IOCTL(DM_TARGET_WAIT), /* And these ioctls need translation */ HANDLE_IOCTL(MEMREADOOB32, mtd_rw_oob), HANDLE_IOCTL(MEMWRITEOOB32, mtd_rw_oob), diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/s390/boot/Makefile linux.2.5.45-ac1/arch/s390/boot/Makefile --- linux.2.5.45/arch/s390/boot/Makefile 2002-10-31 14:57:34.000000000 +0000 +++ linux.2.5.45-ac1/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.45/arch/s390/defconfig linux.2.5.45-ac1/arch/s390/defconfig --- linux.2.5.45/arch/s390/defconfig 2002-10-31 14:57:35.000000000 +0000 +++ linux.2.5.45-ac1/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.45/arch/s390/Kconfig linux.2.5.45-ac1/arch/s390/Kconfig --- linux.2.5.45/arch/s390/Kconfig 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.45-ac1/arch/s390/Kconfig 2002-11-01 14:29:12.000000000 +0000 @@ -34,6 +34,14 @@ (and especially the web page given there) before attempting to build an MCA bus kernel. +config MMU + bool + default y + +config SWAP + bool + default y + config UID16 bool default y @@ -106,6 +114,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" @@ -144,6 +158,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.45/arch/s390/lib/uaccess.S linux.2.5.45-ac1/arch/s390/lib/uaccess.S --- linux.2.5.45/arch/s390/lib/uaccess.S 2002-10-31 14:57:35.000000000 +0000 +++ linux.2.5.45-ac1/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.45/arch/s390/Makefile linux.2.5.45-ac1/arch/s390/Makefile --- linux.2.5.45/arch/s390/Makefile 2002-10-31 14:57:35.000000000 +0000 +++ linux.2.5.45-ac1/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.45/arch/s390x/boot/Makefile linux.2.5.45-ac1/arch/s390x/boot/Makefile --- linux.2.5.45/arch/s390x/boot/Makefile 2002-10-31 14:57:34.000000000 +0000 +++ linux.2.5.45-ac1/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.45/arch/s390x/defconfig linux.2.5.45-ac1/arch/s390x/defconfig --- linux.2.5.45/arch/s390x/defconfig 2002-10-31 14:57:34.000000000 +0000 +++ linux.2.5.45-ac1/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.45/arch/s390x/Kconfig linux.2.5.45-ac1/arch/s390x/Kconfig --- linux.2.5.45/arch/s390x/Kconfig 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.45-ac1/arch/s390x/Kconfig 2002-11-01 14:30:52.000000000 +0000 @@ -44,6 +44,14 @@ config GENERIC_BUST_SPINLOCK bool +config MMU + bool + default y + +config SWAP + bool + default y + mainmenu "Linux Kernel Configuration" @@ -99,6 +107,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" @@ -152,6 +166,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.45/arch/s390x/kernel/ioctl32.c linux.2.5.45-ac1/arch/s390x/kernel/ioctl32.c --- linux.2.5.45/arch/s390x/kernel/ioctl32.c 2002-10-31 14:57:34.000000000 +0000 +++ linux.2.5.45-ac1/arch/s390x/kernel/ioctl32.c 2002-11-02 21:32:49.000000000 +0000 @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -897,6 +898,18 @@ IOCTL32_DEFAULT(SIOCGSTAMP), + IOCTL32_DEFAULT(DM_VERSION), + IOCTL32_DEFAULT(DM_REMOVE_ALL), + IOCTL32_DEFAULT(DM_DEV_CREATE), + IOCTL32_DEFAULT(DM_DEV_REMOVE), + IOCTL32_DEFAULT(DM_DEV_RELOAD), + IOCTL32_DEFAULT(DM_DEV_SUSPEND), + IOCTL32_DEFAULT(DM_DEV_RENAME), + IOCTL32_DEFAULT(DM_DEV_DEPS), + IOCTL32_DEFAULT(DM_DEV_STATUS), + IOCTL32_DEFAULT(DM_TARGET_STATUS), + IOCTL32_DEFAULT(DM_TARGET_WAIT), + IOCTL32_DEFAULT(LOOP_SET_FD), IOCTL32_DEFAULT(LOOP_CLR_FD), diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/s390x/kernel/linux32.c linux.2.5.45-ac1/arch/s390x/kernel/linux32.c --- linux.2.5.45/arch/s390x/kernel/linux32.c 2002-10-31 14:57:34.000000000 +0000 +++ linux.2.5.45-ac1/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.45/arch/s390x/lib/uaccess.S linux.2.5.45-ac1/arch/s390x/lib/uaccess.S --- linux.2.5.45/arch/s390x/lib/uaccess.S 2002-10-31 14:57:34.000000000 +0000 +++ linux.2.5.45-ac1/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.45/arch/s390x/Makefile linux.2.5.45-ac1/arch/s390x/Makefile --- linux.2.5.45/arch/s390x/Makefile 2002-10-31 14:57:34.000000000 +0000 +++ linux.2.5.45-ac1/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.45/arch/sh/Kconfig linux.2.5.45-ac1/arch/sh/Kconfig --- linux.2.5.45/arch/sh/Kconfig 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.45-ac1/arch/sh/Kconfig 2002-11-01 11:36:26.000000000 +0000 @@ -29,6 +29,14 @@ bool default y +config MMU + bool + default y + +config SWAP + bool + default y + source "init/Kconfig" diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/sparc/Kconfig linux.2.5.45-ac1/arch/sparc/Kconfig --- linux.2.5.45/arch/sparc/Kconfig 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.45-ac1/arch/sparc/Kconfig 2002-11-01 11:36:18.000000000 +0000 @@ -5,6 +5,14 @@ mainmenu "Linux/SPARC Kernel Configuration" +config MMU + bool + default y + +config SWAP + bool + default y + config UID16 bool default y diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/sparc64/Kconfig linux.2.5.45-ac1/arch/sparc64/Kconfig --- linux.2.5.45/arch/sparc64/Kconfig 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.45-ac1/arch/sparc64/Kconfig 2002-11-01 11:36:09.000000000 +0000 @@ -5,6 +5,14 @@ mainmenu "Linux/UltraSPARC Kernel Configuration" +config MMU + bool + default y + +config SWAP + bool + default y + source "init/Kconfig" diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/sparc64/kernel/ioctl32.c linux.2.5.45-ac1/arch/sparc64/kernel/ioctl32.c --- linux.2.5.45/arch/sparc64/kernel/ioctl32.c 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.45-ac1/arch/sparc64/kernel/ioctl32.c 2002-10-31 15:28:02.000000000 +0000 @@ -55,6 +55,7 @@ #if defined(CONFIG_BLK_DEV_LVM) || defined(CONFIG_BLK_DEV_LVM_MODULE) #include #endif /* LVM */ +#include #include /* Ugly hack. */ @@ -5012,6 +5013,19 @@ COMPATIBLE_IOCTL(NBD_PRINT_DEBUG) COMPATIBLE_IOCTL(NBD_SET_SIZE_BLOCKS) COMPATIBLE_IOCTL(NBD_DISCONNECT) +/* device-mapper */ +COMPATIBLE_IOCTL(DM_VERSION) +COMPATIBLE_IOCTL(DM_REMOVE_ALL) +COMPATIBLE_IOCTL(DM_DEV_CREATE) +COMPATIBLE_IOCTL(DM_DEV_REMOVE) +COMPATIBLE_IOCTL(DM_DEV_RELOAD) +COMPATIBLE_IOCTL(DM_DEV_SUSPEND) +COMPATIBLE_IOCTL(DM_DEV_RENAME) +COMPATIBLE_IOCTL(DM_DEV_DEPS) +COMPATIBLE_IOCTL(DM_DEV_STATUS) +COMPATIBLE_IOCTL(DM_TARGET_STATUS) +COMPATIBLE_IOCTL(DM_TARGET_WAIT) + /* And these ioctls need translation */ HANDLE_IOCTL(MEMREADOOB32, mtd_rw_oob) HANDLE_IOCTL(MEMWRITEOOB32, mtd_rw_oob) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/um/defconfig linux.2.5.45-ac1/arch/um/defconfig --- linux.2.5.45/arch/um/defconfig 2002-10-31 14:57:35.000000000 +0000 +++ linux.2.5.45-ac1/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.45/arch/um/drivers/Makefile linux.2.5.45-ac1/arch/um/drivers/Makefile --- linux.2.5.45/arch/um/drivers/Makefile 2002-10-31 14:57:35.000000000 +0000 +++ linux.2.5.45-ac1/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.45/arch/um/drivers/mconsole_kern.c linux.2.5.45-ac1/arch/um/drivers/mconsole_kern.c --- linux.2.5.45/arch/um/drivers/mconsole_kern.c 2002-10-31 14:57:35.000000000 +0000 +++ linux.2.5.45-ac1/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.45/arch/um/drivers/port_kern.c linux.2.5.45-ac1/arch/um/drivers/port_kern.c --- linux.2.5.45/arch/um/drivers/port_kern.c 2002-10-31 14:57:35.000000000 +0000 +++ linux.2.5.45-ac1/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.45/arch/um/drivers/ssl.c linux.2.5.45-ac1/arch/um/drivers/ssl.c --- linux.2.5.45/arch/um/drivers/ssl.c 2002-10-31 14:57:35.000000000 +0000 +++ linux.2.5.45-ac1/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.45/arch/um/drivers/stdio_console.c linux.2.5.45-ac1/arch/um/drivers/stdio_console.c --- linux.2.5.45/arch/um/drivers/stdio_console.c 2002-10-31 14:57:35.000000000 +0000 +++ linux.2.5.45-ac1/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.45/arch/um/drivers/ubd_kern.c linux.2.5.45-ac1/arch/um/drivers/ubd_kern.c --- linux.2.5.45/arch/um/drivers/ubd_kern.c 2002-10-31 14:57:35.000000000 +0000 +++ linux.2.5.45-ac1/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.45/arch/um/drivers/xterm.c linux.2.5.45-ac1/arch/um/drivers/xterm.c --- linux.2.5.45/arch/um/drivers/xterm.c 2002-10-31 14:57:35.000000000 +0000 +++ linux.2.5.45-ac1/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.45/arch/um/drivers/xterm.h linux.2.5.45-ac1/arch/um/drivers/xterm.h --- linux.2.5.45/arch/um/drivers/xterm.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/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.45/arch/um/drivers/xterm_kern.c linux.2.5.45-ac1/arch/um/drivers/xterm_kern.c --- linux.2.5.45/arch/um/drivers/xterm_kern.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/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.45/arch/um/include/chan_user.h linux.2.5.45-ac1/arch/um/include/chan_user.h --- linux.2.5.45/arch/um/include/chan_user.h 2002-10-31 14:57:35.000000000 +0000 +++ linux.2.5.45-ac1/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.45/arch/um/include/kern_util.h linux.2.5.45-ac1/arch/um/include/kern_util.h --- linux.2.5.45/arch/um/include/kern_util.h 2002-10-31 14:57:35.000000000 +0000 +++ linux.2.5.45-ac1/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.45/arch/um/Kconfig linux.2.5.45-ac1/arch/um/Kconfig --- linux.2.5.45/arch/um/Kconfig 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.45-ac1/arch/um/Kconfig 2002-11-01 11:36:41.000000000 +0000 @@ -22,6 +22,14 @@ bool default y +config MMU + bool + default y + +config SWAP + bool + default y + menu "Code maturity level options" diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/um/kernel/irq_user.c linux.2.5.45-ac1/arch/um/kernel/irq_user.c --- linux.2.5.45/arch/um/kernel/irq_user.c 2002-10-31 14:57:35.000000000 +0000 +++ linux.2.5.45-ac1/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.45/arch/um/kernel/ksyms.c linux.2.5.45-ac1/arch/um/kernel/ksyms.c --- linux.2.5.45/arch/um/kernel/ksyms.c 2002-10-31 14:57:35.000000000 +0000 +++ linux.2.5.45-ac1/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.45/arch/um/kernel/Makefile linux.2.5.45-ac1/arch/um/kernel/Makefile --- linux.2.5.45/arch/um/kernel/Makefile 2002-10-31 14:57:35.000000000 +0000 +++ linux.2.5.45-ac1/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.45/arch/um/kernel/process_kern.c linux.2.5.45-ac1/arch/um/kernel/process_kern.c --- linux.2.5.45/arch/um/kernel/process_kern.c 2002-10-31 14:57:35.000000000 +0000 +++ linux.2.5.45-ac1/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.45/arch/um/kernel/reboot.c linux.2.5.45-ac1/arch/um/kernel/reboot.c --- linux.2.5.45/arch/um/kernel/reboot.c 2002-10-31 14:57:35.000000000 +0000 +++ linux.2.5.45-ac1/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.45/arch/um/kernel/signal_user.c linux.2.5.45-ac1/arch/um/kernel/signal_user.c --- linux.2.5.45/arch/um/kernel/signal_user.c 2002-10-31 14:57:35.000000000 +0000 +++ linux.2.5.45-ac1/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.45/arch/um/kernel/smp.c linux.2.5.45-ac1/arch/um/kernel/smp.c --- linux.2.5.45/arch/um/kernel/smp.c 2002-10-31 14:57:35.000000000 +0000 +++ linux.2.5.45-ac1/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.45/arch/um/kernel/sys_call_table.c linux.2.5.45-ac1/arch/um/kernel/sys_call_table.c --- linux.2.5.45/arch/um/kernel/sys_call_table.c 2002-10-31 14:57:35.000000000 +0000 +++ linux.2.5.45-ac1/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.45/arch/um/kernel/sysrq.c linux.2.5.45-ac1/arch/um/kernel/sysrq.c --- linux.2.5.45/arch/um/kernel/sysrq.c 2002-10-31 14:57:35.000000000 +0000 +++ linux.2.5.45-ac1/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.45/arch/um/kernel/trap_kern.c linux.2.5.45-ac1/arch/um/kernel/trap_kern.c --- linux.2.5.45/arch/um/kernel/trap_kern.c 2002-10-31 14:57:35.000000000 +0000 +++ linux.2.5.45-ac1/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.45/arch/um/kernel/um_arch.c linux.2.5.45-ac1/arch/um/kernel/um_arch.c --- linux.2.5.45/arch/um/kernel/um_arch.c 2002-10-31 14:57:35.000000000 +0000 +++ linux.2.5.45-ac1/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.45/arch/um/Makefile linux.2.5.45-ac1/arch/um/Makefile --- linux.2.5.45/arch/um/Makefile 2002-10-31 14:57:35.000000000 +0000 +++ linux.2.5.45-ac1/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.45/arch/um/Makefile-i386 linux.2.5.45-ac1/arch/um/Makefile-i386 --- linux.2.5.45/arch/um/Makefile-i386 2002-10-31 14:57:35.000000000 +0000 +++ linux.2.5.45-ac1/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.45/arch/um/os-Linux/file.c linux.2.5.45-ac1/arch/um/os-Linux/file.c --- linux.2.5.45/arch/um/os-Linux/file.c 2002-10-31 14:57:36.000000000 +0000 +++ linux.2.5.45-ac1/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.45/arch/um/sys-i386/Makefile linux.2.5.45-ac1/arch/um/sys-i386/Makefile --- linux.2.5.45/arch/um/sys-i386/Makefile 2002-10-31 14:57:36.000000000 +0000 +++ linux.2.5.45-ac1/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.45/arch/um/uml.lds.S linux.2.5.45-ac1/arch/um/uml.lds.S --- linux.2.5.45/arch/um/uml.lds.S 2002-10-31 14:57:35.000000000 +0000 +++ linux.2.5.45-ac1/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.45/arch/v850/anna.ld linux.2.5.45-ac1/arch/v850/anna.ld --- linux.2.5.45/arch/v850/anna.ld 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/v850/anna.ld 2002-11-01 15:20:35.000000000 +0000 @@ -0,0 +1,122 @@ +/* Linker script for the Midas labs Anna V850E2 evaluation board + (CONFIG_V850E2_ANNA). */ + +/* Note, all symbols are prefixed with an extra `_' for compatibility with + the existing linux sources. */ + +_jiffies = _jiffies_64 ; + +MEMORY { + /* 256KB of internal memory (followed by one mirror). */ + iMEM0 : ORIGIN = 0, LENGTH = 0x00040000 + /* 256KB of internal memory (followed by one mirror). */ + iMEM1 : ORIGIN = 0x00040000, LENGTH = 0x00040000 + + /* 1MB of static RAM. This memory is mirrored 64 times. */ + SRAM : ORIGIN = 0x04000000, LENGTH = 0x00100000 + /* 64MB of DRAM. */ + SDRAM : ORIGIN = 0x08000000, LENGTH = 0x04000000 +} + +SECTIONS { + .intv : { + __intv_start = . ; + *(.intv.reset) /* Reset vector */ + *(.intv.common) /* Vectors common to all v850e proc. */ + *(.intv.mach) /* Machine-specific int. vectors. */ + __intv_end = . ; + } > iMEM0 + + .text : { + __kram_start = . ; + + __stext = . ; + *(.text) + *(.exit.text) /* 2.5 convention */ + *(.text.exit) /* 2.4 convention */ + *(.text.lock) + *(.exitcall.exit) + __real_etext = . ; /* There may be data after here. */ + *(.rodata) + + . = ALIGN (0x4) ; + *(.kstrtab) + + . = ALIGN (4) ; + *(.call_table_data) + *(.call_table_text) + + . = ALIGN (16) ; /* Exception table. */ + ___start___ex_table = . ; + *(__ex_table) + ___stop___ex_table = . ; + + ___start___ksymtab = . ;/* Kernel symbol table. */ + *(__ksymtab) + ___stop___ksymtab = . ; + . = ALIGN (4) ; + __etext = . ; + } > SRAM + + .data ALIGN (0x4) : { + __sdata = . ; + ___data_start = . ; + *(.data) + *(.exit.data) /* 2.5 convention */ + *(.data.exit) /* 2.4 convention */ + . = ALIGN (16) ; + *(.data.cacheline_aligned) + . = ALIGN (0x2000) ; + *(.data.init_task) + . = ALIGN (0x2000) ; + __edata = . ; + } > SRAM + + .bss ALIGN (0x4) : { + __sbss = . ; + *(.bss) + *(COMMON) + . = ALIGN (4) ; + __init_stack_end = . ; + __ebss = . ; + } > SRAM + + .init ALIGN (4096) : { + __init_start = . ; + *(.init.text) /* 2.5 convention */ + *(.init.data) + *(.text.init) /* 2.4 convention */ + *(.data.init) + . = ALIGN (16) ; + ___setup_start = . ; + *(.init.setup) /* 2.5 convention */ + *(.setup.init) /* 2.4 convention */ + ___setup_end = . ; + ___initcall_start = . ; + *(.initcall.init) + *(.initcall1.init) + *(.initcall2.init) + *(.initcall3.init) + *(.initcall4.init) + *(.initcall5.init) + *(.initcall6.init) + *(.initcall7.init) + . = ALIGN (4) ; + ___initcall_end = . ; + __init_end = . ; + + __kram_end = . ; + } > SRAM + + .bootmap ALIGN (4096) : { + __bootmap = . ; + . = . + 4096 ; /* enough for 128MB. */ + } > SRAM + + /* Device contents for the root filesystem. */ + .root : { + __root_fs_image_start = . ; + *(.root) + __root_fs_image_end = . ; + } > SDRAM +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/v850/anna-rom.ld linux.2.5.45-ac1/arch/v850/anna-rom.ld --- linux.2.5.45/arch/v850/anna-rom.ld 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/v850/anna-rom.ld 2002-11-01 15:20:35.000000000 +0000 @@ -0,0 +1,127 @@ +/* Linker script for the Midas labs Anna V850E2 evaluation board + (CONFIG_V850E2_ANNA), with kernel in ROM (CONFIG_ROM_KERNEL). */ + +/* Note, all symbols are prefixed with an extra `_' for compatibility with + the existing linux sources. */ + +_jiffies = _jiffies_64 ; + +MEMORY { + /* 8MB of flash ROM. */ + ROM : ORIGIN = 0, LENGTH = 0x00800000 + + /* 1MB of static RAM. This memory is mirrored 64 times. */ + SRAM : ORIGIN = 0x04000000, LENGTH = 0x00100000 + /* 64MB of DRAM. */ + SDRAM : ORIGIN = 0x08000000, LENGTH = 0x04000000 +} + +SECTIONS { + .intv : { + __intv_start = . ; + *(.intv.reset) /* Reset vector */ + *(.intv.common) /* Vectors common to all v850e proc. */ + *(.intv.mach) /* Machine-specific int. vectors. */ + __intv_end = . ; + } > ROM + + .text ALIGN (0x10) : { + __stext = . ; + *(.text) + *(.exit.text) /* 2.5 convention */ + *(.text.exit) /* 2.4 convention */ + *(.text.lock) + *(.exitcall.exit) + __real_etext = . ; /* There may be data after here. */ + *(.rodata) + + . = ALIGN (0x4) ; + *(.kstrtab) + + . = ALIGN (4) ; + *(.call_table_data) + *(.call_table_text) + + . = ALIGN (16) ; /* Exception table. */ + ___start___ex_table = . ; + *(__ex_table) + ___stop___ex_table = . ; + + ___start___ksymtab = . ;/* Kernel symbol table. */ + *(__ksymtab) + ___stop___ksymtab = . ; + . = ALIGN (4) ; + __etext = . ; + } > ROM + + .init_text ALIGN (4096) : { + *(.init.text) /* 2.5 convention */ + *(.text.init) /* 2.4 convention */ + . = ALIGN (16) ; + ___setup_start = . ; + *(.init.setup) /* 2.5 convention */ + *(.setup.init) /* 2.4 convention */ + ___setup_end = . ; + ___initcall_start = . ; + *(.initcall.init) + *(.initcall1.init) + *(.initcall2.init) + *(.initcall3.init) + *(.initcall4.init) + *(.initcall5.init) + *(.initcall6.init) + *(.initcall7.init) + . = ALIGN (4) ; + ___initcall_end = . ; + } > ROM + + /* Device contents for the root filesystem. */ + .root ALIGN (4096) : { + __root_fs_image_start = . ; + *(.root) + __root_fs_image_end = . ; + } > ROM + + __rom_copy_src_start = . ; + + .data : { + __kram_start = . ; + __rom_copy_dst_start = . ; + + __sdata = . ; + ___data_start = . ; + *(.data) + *(.exit.data) /* 2.5 convention */ + *(.data.exit) /* 2.4 convention */ + . = ALIGN (16) ; + *(.data.cacheline_aligned) + . = ALIGN (0x2000) ; + *(.data.init_task) + . = ALIGN (0x2000) ; + __edata = . ; + } > SRAM AT> ROM + + .init_data ALIGN (4096) : { + __init_start = . ; + *(.init.data) /* 2.5 convention */ + *(.data.init) /* 2.4 convention */ + __init_end = . ; + __rom_copy_dst_end = . ; + } > SRAM AT> ROM + + .bss ALIGN (4096) : { + __sbss = . ; + *(.bss) + *(COMMON) + . = ALIGN (4) ; + __init_stack_end = . ; + __ebss = . ; + + __kram_end = . ; + } > SRAM + + .bootmap ALIGN (4096) : { + __bootmap = . ; + . = . + 4096 ; /* enough for 128MB. */ + } > SRAM +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/v850/fpga85e2c.ld linux.2.5.45-ac1/arch/v850/fpga85e2c.ld --- linux.2.5.45/arch/v850/fpga85e2c.ld 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/v850/fpga85e2c.ld 2002-11-01 15:20:35.000000000 +0000 @@ -0,0 +1,144 @@ +/* Linker script for the FPGA implementation of the V850E2 NA85E2C cpu core + (CONFIG_V850E2_FPGA85E2C). */ + +/* Note, all symbols are prefixed with an extra `_' for compatibility with + the existing linux sources. */ + +_jiffies = _jiffies_64 ; + +MEMORY { + /* Reset vector. */ + RESET : ORIGIN = 0, LENGTH = 0x10 + /* Interrupt vectors. */ + INTV : ORIGIN = 0x10, LENGTH = 0x470 + /* The `window' in RAM were we're allowed to load stuff. */ + RAM_LOW : ORIGIN = 0x480, LENGTH = 0x0005FB80 + /* Some more ram above the window were we can put bss &c. */ + RAM_HIGH : ORIGIN = 0x00060000, LENGTH = 0x000A0000 + /* This is the area visible from the outside world (we can use + this only for uninitialized data). */ + VISIBLE : ORIGIN = 0x00200000, LENGTH = 0x00060000 +} + +SECTIONS { + .reset : { + __kram_start = . ; + __intv_start = . ; + *(.intv.reset) /* Reset vector */ + } > RESET + + .r0_ram : { + __r0_ram = . ; + . = . + 32 ; + } > RAM_LOW + + .text : { + __stext = . ; + *(.text) + *(.exit.text) /* 2.5 convention */ + *(.text.exit) /* 2.4 convention */ + *(.text.lock) + *(.exitcall.exit) + __real_etext = . ; /* There may be data after here. */ + *(.rodata) + . = ALIGN (0x4) ; + *(.kstrtab) + + . = ALIGN (4) ; + *(.call_table_data) + *(.call_table_text) + + . = ALIGN (16) ; /* Exception table. */ + ___start___ex_table = . ; + *(__ex_table) + ___stop___ex_table = . ; + + ___start___ksymtab = . ;/* Kernel symbol table. */ + *(__ksymtab) + ___stop___ksymtab = . ; + . = ALIGN (4) ; + __etext = . ; + } > RAM_LOW + + .data : { + __sdata = . ; + *(.data) + *(.exit.data) /* 2.5 convention */ + *(.data.exit) /* 2.4 convention */ + . = ALIGN (16) ; + *(.data.cacheline_aligned) + . = ALIGN (0x2000) ; + *(.data.init_task) + . = ALIGN (0x2000) ; + __edata = . ; + } > RAM_LOW + + /* Device contents for the root filesystem. */ + .root : { + . = ALIGN (4096) ; + __root_fs_image_start = . ; + *(.root) + __root_fs_image_end = . ; + } > RAM_LOW + + .init ALIGN (4096) : { + __init_start = . ; + *(.init.text) /* 2.5 convention */ + *(.init.data) + *(.text.init) /* 2.4 convention */ + *(.data.init) + . = ALIGN (16) ; + ___setup_start = . ; + *(.init.setup) /* 2.5 convention */ + *(.setup.init) /* 2.4 convention */ + ___setup_end = . ; + ___initcall_start = . ; + *(.initcall.init) + *(.initcall1.init) + *(.initcall2.init) + *(.initcall3.init) + *(.initcall4.init) + *(.initcall5.init) + *(.initcall6.init) + *(.initcall7.init) + . = ALIGN (4) ; + ___initcall_end = . ; + } > RAM_LOW + + /* Where the interrupt vectors are initially loaded. */ + __intv_load_start = . ; + + .intv : { + *(.intv.common) /* Vectors common to all v850e proc. */ + *(.intv.mach) /* Machine-specific int. vectors. */ + __intv_end = . ; + } > INTV AT> RAM_LOW + + .bss : { + /* This is here so that when we free init memory the + load-time copy of the interrupt vectors and any empty + space at the end of the `RAM_LOW' area is freed too. */ + . = ALIGN (4096); + __init_end = . ; + + __sbss = . ; + *(.bss) + *(COMMON) + . = ALIGN (4) ; + __init_stack_end = . ; + __ebss = . ; + + __kram_end = . ; + } > RAM_HIGH + + .bootmap ALIGN (4096) : { + __bootmap = . ; + . = . + 4096 ; /* enough for 128MB. */ + } > RAM_HIGH + + .visible : { + _memcons_output = . ; + . = . + 0x8000 ; + _memcons_output_end = . ; + } > VISIBLE +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/v850/Kconfig linux.2.5.45-ac1/arch/v850/Kconfig --- linux.2.5.45/arch/v850/Kconfig 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/v850/Kconfig 2002-11-01 16:39:54.000000000 +0000 @@ -0,0 +1,488 @@ +############################################################################# +# +# For a description of the syntax of this configuration file, +# see Documentation/kbuild/config-language.txt. +# +############################################################################# + +mainmenu "uClinux/v850 (w/o MMU) Kernel Configuration" + +config MMU + bool + default n +config SWAP + bool + default n +config UID16 + bool + default n +config RWSEM_GENERIC_SPINLOCK + bool + default y +config RWSEM_XCHGADD_ALGORITHM + bool + default n + +# Turn off some random 386 crap that can affect device config +config ISA + bool + default n +config ISAPNP + bool + default n +config EISA + bool + default n +config MCA + bool + default n + + +############################################################################# +#### v850-specific config + +# Define the architecture +config V850 + bool + default y + +menu "Processor type and features" + + choice + prompt "Platform" + default GDB + config RTE_CB_MA1 + bool "RTE-V850E/MA1-CB" + config RTE_CB_NB85E + bool "RTE-V850E/NB85E-CB" + config V850E_SIM + bool "GDB" + config V850E2_SIM85E2C + bool "sim85e2c" + config V850E2_FPGA85E2C + bool "NA85E2C-FPGA" + config V850E2_ANNA + bool "Anna" + endchoice + + + #### V850E processor-specific config + + # All CPUs currently supported use the v850e architecture + config V850E + bool + default y + + # The RTE-V850E/MA1-CB is the only type of V850E/MA1 platform we + # currently support + config V850E_MA1 + bool + depends RTE_CB_MA1 + default y + # Similarly for the RTE-V850E/MA1-CB - V850E/TEG + config V850E_TEG + bool + depends RTE_CB_NB85E + default y + + # NB85E processor core + config V850E_NB85E + bool + depends V850E_MA1 || V850E_TEG + default y + + config V850E_MA1_HIGHRES_TIMER + bool "High resolution timer support" + depends V850E_MA1 + + + #### V850E2 processor-specific config + + # V850E2 processors + config V850E2 + bool + depends V850E2_SIM85E2C || V850E2_FPGA85E2C || V850E2_ANNA + default y + + # Processors based on the NA85E2A core + config V850E2_NA85E2A + bool + depends V850E2_ANNA + default y + + # Processors based on the NA85E2C core + config V850E2_NA85E2C + bool + depends V850E2_SIM85E2C || V850E2_FPGA85E2C + default y + + + #### RTE-CB platform-specific config + + # Boards in the RTE-x-CB series + config RTE_CB + bool + depends RTE_CB_MA1 || RTE_CB_NB85E + default y + + # Currently, we only support RTE-CB boards using the Multi debugger + config RTE_CB_MULTI + bool + depends RTE_CB + default y + + config RTE_CB_MA1_KSRAM + bool "Kernel in SRAM (limits size of kernel)" + depends RTE_CB_MA1 && RTE_CB_MULTI + default n + + config RTE_MB_A_PCI + bool "Mother-A PCI support" + depends RTE_CB + default y + + # The GBUS is used to talk to the RTE-MOTHER-A board + config RTE_GBUS_INT + bool + depends RTE_MB_A_PCI + default y + + # The only PCI bus we support is on the RTE-MOTHER-A board + config PCI + bool + default y if RTE_MB_A_PCI + + + #### Misc config + + config ROM_KERNEL + bool "Kernel in ROM" + depends V850E2_ANNA || (RTE_CB && !RTE_CB_MULTI) + + # Some platforms pre-zero memory, in which case the kernel doesn't need to + config ZERO_BSS + bool + depends !V850E2_SIM85E2C + default y + + # The crappy-ass zone allocator requires that the start of allocatable + # memory be aligned to the largest possible allocation. + config FORCE_MAX_ZONEORDER + int + default 8 if V850E2_SIM85E2C || V850E2_FPGA85E2C + + config TIME_BOOTUP + bool "Time bootup" + depends V850E_MA1_HIGHRES_TIMER + + config RESET_GUARD + bool "Reset Guard" + + config LARGE_ALLOCS + bool "Allow allocating large blocks (> 1MB) of memory" + help + Allow the slab memory allocator to keep chains for very large + memory sizes - upto 32MB. You may need this if your system has + a lot of RAM, and you need to able to allocate very large + contiguous chunks. If unsure, say N. + +endmenu + + +############################################################################# + +source init/Kconfig + +############################################################################# + +menu "Bus options (PCI, PCMCIA, EISA, MCA, ISA)" + +# config PCI +# bool "PCI support" +# help +# Support for PCI bus. + +source "drivers/pci/Kconfig" + +config HOTPLUG + bool "Support for hot-pluggable device" + ---help--- + Say Y here if you want to plug devices into your computer while + the system is running, and be able to use them quickly. In many + cases, the devices can likewise be unplugged at any time too. + + One well known example of this is PCMCIA- or PC-cards, credit-card + size devices such as network cards, modems or hard drives which are + plugged into slots found on all modern laptop computers. Another + example, used on modern desktops as well as laptops, is USB. + + Enable HOTPLUG and KMOD, and build a modular kernel. Get agent + software (at ) and install it. + Then your kernel will automatically call out to a user mode "policy + agent" (/sbin/hotplug) to load modules and set up software needed + to use devices as you hotplug them. + +source "drivers/pcmcia/Kconfig" + +source "drivers/hotplug/Kconfig" + +endmenu + +menu "Executable file formats" + +config KCORE_AOUT + bool + default y + +config KCORE_ELF + default y + +config BINFMT_FLAT + tristate "Kernel support for flat binaries" + help + Support uClinux FLAT format binaries. + +config BINFMT_ZFLAT + bool " Enable ZFLAT support" + depends on BINFMT_FLAT + help + Support FLAT format compressed binaries + +endmenu + +############################################################################# + +source drivers/mtd/Kconfig + +source drivers/parport/Kconfig + +#source drivers/pnp/Kconfig + +source drivers/block/Kconfig + +############################################################################# + +menu "Disk device support" + +config IDE + tristate "ATA/ATAPI/MFM/RLL device support" + ---help--- + If you say Y here, your kernel will be able to manage low cost mass + storage units such as ATA/(E)IDE and ATAPI units. The most common + cases are IDE hard drives and ATAPI CD-ROM drives. + + It only makes sense to choose this option if your board actually + has an IDE interface. If unsure, say N. + +source "drivers/ide/Kconfig" + +config SCSI + tristate "SCSI device support" + help + If you want to use a SCSI hard disk, SCSI tape drive, SCSI CD-ROM or + any other SCSI device under Linux, say Y and make sure that you know + the name of your SCSI host adapter (the card inside your computer + that "speaks" the SCSI protocol, also called SCSI controller), + because you will be asked for it. + +source "drivers/scsi/Kconfig" + +endmenu + +############################################################################# + + +source "drivers/md/Kconfig" + +source "drivers/message/fusion/Kconfig" + +source "drivers/ieee1394/Kconfig" + +source "drivers/message/i2o/Kconfig" + +source "net/Kconfig" + + +menu "Network device support" + depends on NET + +config NETDEVICES + bool "Network device support" + ---help--- + You can say N here if you don't intend to connect your Linux box to + any other computer at all or if all your connections will be over a + telephone line with a modem either via UUCP (UUCP is a protocol to + forward mail and news between unix hosts over telephone lines; read + the UUCP-HOWTO, available from + ) or dialing up a shell + account or a BBS, even using term (term is a program which gives you + almost full Internet connectivity if you have a regular dial up + shell account on some Internet connected Unix computer. Read + ). + + You'll have to say Y if your computer contains a network card that + you want to use under Linux (make sure you know its name because you + will be asked for it and read the Ethernet-HOWTO (especially if you + plan to use more than one network card under Linux)) or if you want + to use SLIP (Serial Line Internet Protocol is the protocol used to + send Internet traffic over telephone lines or null modem cables) or + CSLIP (compressed SLIP) or PPP (Point to Point Protocol, a better + and newer replacement for SLIP) or PLIP (Parallel Line Internet + Protocol is mainly used to create a mini network by connecting the + parallel ports of two local machines) or AX.25/KISS (protocol for + sending Internet traffic over amateur radio links). + + Make sure to read the NET-3-HOWTO. Eventually, you will have to read + Olaf Kirch's excellent and free book "Network Administrator's + Guide", to be found in . If + unsure, say Y. + +source "drivers/net/Kconfig" + +source "drivers/atm/Kconfig" + +endmenu + +source "net/ax25/Kconfig" + +source "net/irda/Kconfig" + +source "drivers/isdn/Kconfig" + +#source "drivers/telephony/Kconfig" + +# +# input before char - char/joystick depends on it. As does USB. +# +source "drivers/input/Kconfig" + +source "drivers/char/Kconfig" + +#source drivers/misc/Config.in +source "drivers/media/Kconfig" + +source "fs/Kconfig" + + +menu "Console drivers" + depends on VT + +config VGA_CONSOLE + bool "VGA text console" + help + Saying Y here will allow you to use Linux in text mode through a + display that complies with the generic VGA standard. Virtually + everyone wants that. + + The program SVGATextMode can be used to utilize SVGA video cards to + their full potential in text mode. Download it from + . + + If unsure, say N. + +config VIDEO_SELECT + bool "Video mode selection support" + ---help--- + This enables support for text mode selection on kernel startup. If + you want to take advantage of some high-resolution text mode your + card's BIOS offers, but the traditional Linux utilities like + SVGATextMode don't, you can say Y here and set the mode using the + "vga=" option from your boot loader (lilo or loadlin) or set + "vga=ask" which brings up a video mode menu on kernel startup. (Try + "man bootparam" or see the documentation of your boot loader about + how to pass options to the kernel.) + + Read the file for more information + about the Video mode selection support. If unsure, say N. + +source "drivers/video/Kconfig" + +endmenu + + +menu "Sound" + +config SOUND + tristate "Sound card support" + ---help--- + If you have a sound card in your computer, i.e. if it can say more + than an occasional beep, say Y. Be sure to have all the information + about your sound card and its configuration down (I/O port, + interrupt and DMA channel), because you will be asked for it. + + You want to read the Sound-HOWTO, available from + . General information about + the modular sound system is contained in the files + . The file + contains some slightly + outdated but still useful information as well. + + If you have a PnP sound card and you want to configure it at boot + time using the ISA PnP tools (read + ), then you need to + compile the sound card support as a module ( = code which can be + inserted in and removed from the running kernel whenever you want) + and load that module after the PnP configuration is finished. To do + this, say M here and read as well + as ; the module will be + called soundcore.o. + + I'm told that even without a sound card, you can make your computer + say more than an occasional beep, by programming the PC speaker. + Kernel patches and supporting utilities to do that are in the pcsp + package, available at . + +source "sound/Kconfig" + +endmenu + +source "drivers/usb/Kconfig" + +source "net/bluetooth/Kconfig" + + +menu "Kernel hacking" + +config FULLDEBUG + bool "Full Symbolic/Source Debugging support" + help + Enable debuging symbols on kernel build. + +config MAGIC_SYSRQ + bool "Magic SysRq key" + help + Enables console device to interprent special characters as + commands to dump state information. + +config HIGHPROFILE + bool "Use fast second timer for profiling" + help + Use a fast secondary clock to produce profiling information. + +config DUMPTOFLASH + bool "Panic/Dump to FLASH" + depends on COLDFIRE + help + Dump any panic of trap output into a flash memory segment + for later analysis. + +config NO_KERNEL_MSG + bool "Suppress Kernel BUG Messages" + help + Do not output any debug BUG messages within the kernel. + +config BDM_DISABLE + bool "Disable BDM signals" + depends on (EXPERIMENTAL && COLDFIRE) + help + Disable the CPU's BDM signals. + +endmenu + +source "security/Kconfig" + +source "crypto/Kconfig" + +source "lib/Kconfig" + +############################################################################# diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/v850/kernel/anna.c linux.2.5.45-ac1/arch/v850/kernel/anna.c --- linux.2.5.45/arch/v850/kernel/anna.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/v850/kernel/anna.c 2002-11-01 16:39:54.000000000 +0000 @@ -0,0 +1,202 @@ +/* + * arch/v850/kernel/anna.c -- Anna V850E2 evaluation chip/board + * + * Copyright (C) 2002 NEC Corporation + * Copyright (C) 2002 Miles Bader + * + * 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. + * + * Written by Miles Bader + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "mach.h" + + +/* SRAM and SDRAM are vaguely contiguous (with a hole in between; see + mach_reserve_bootmem for details), so just use both as one big area. */ +#define RAM_START SRAM_ADDR +#define RAM_END (SDRAM_ADDR + SDRAM_SIZE) + + +static void anna_led_tick (void); + + +void __init mach_early_init (void) +{ + ANNA_ILBEN = 0; + ANNA_CSC(0) = 0x402F; + ANNA_CSC(1) = 0x4000; + ANNA_BPC = 0; + ANNA_BSC = 0xAAAA; + ANNA_BEC = 0; + ANNA_BHC = 0x00FF; /* icache all memory, dcache none */ + ANNA_BCT(0) = 0xB088; + ANNA_BCT(1) = 0x0008; + ANNA_DWC(0) = 0x0027; + ANNA_DWC(1) = 0; + ANNA_BCC = 0x0006; + ANNA_ASC = 0; + ANNA_LBS = 0x0089; + ANNA_SCR3 = 0x21A9; + ANNA_RFS3 = 0x8121; + + nb85e_intc_disable_irqs (); +} + +void __init mach_setup (char **cmdline) +{ + printk (KERN_INFO + "CPU: %s\n" + "Platform: %s\n", + CPU_MODEL_LONG, + PLATFORM_LONG); + +#ifdef CONFIG_V850E_NB85E_UART_CONSOLE + nb85e_uart_cons_init (1); +#endif + + ANNA_PORT_PM (0) = 0; /* Make all LED pins output pins. */ + mach_tick = anna_led_tick; +} + +void __init mach_get_physical_ram (unsigned long *ram_start, + unsigned long *ram_len) +{ + *ram_start = RAM_START; + *ram_len = RAM_END - RAM_START; +} + +void __init mach_reserve_bootmem () +{ + /* The space between SRAM and SDRAM is filled with duplicate + images of SRAM. Prevent the kernel from using them. */ + reserve_bootmem (SRAM_ADDR + SRAM_SIZE, + SDRAM_ADDR - (SRAM_ADDR + SRAM_SIZE)); +} + +void mach_gettimeofday (struct timespec *tv) +{ + tv->tv_sec = 0; + tv->tv_nsec = 0; +} + +void __init mach_sched_init (struct irqaction *timer_action) +{ + /* Start hardware timer. */ + nb85e_timer_d_configure (0, HZ); + /* Install timer interrupt handler. */ + setup_irq (IRQ_INTCMD(0), timer_action); +} + +static struct nb85e_intc_irq_init irq_inits[] = { + { "IRQ", 0, NUM_MACH_IRQS, 1, 7 }, + { "PIN", IRQ_INTP(0), IRQ_INTP_NUM, 1, 4 }, + { "CCC", IRQ_INTCCC(0), IRQ_INTCCC_NUM, 1, 5 }, + { "CMD", IRQ_INTCMD(0), IRQ_INTCMD_NUM, 1, 5 }, + { "DMA", IRQ_INTDMA(0), IRQ_INTDMA_NUM, 1, 2 }, + { "DMXER", IRQ_INTDMXER,1, 1, 2 }, + { "SRE", IRQ_INTSRE(0), IRQ_INTSRE_NUM, 3, 3 }, + { "SR", IRQ_INTSR(0), IRQ_INTSR_NUM, 3, 4 }, + { "ST", IRQ_INTST(0), IRQ_INTST_NUM, 3, 5 }, + { 0 } +}; +#define NUM_IRQ_INITS ((sizeof irq_inits / sizeof irq_inits[0]) - 1) + +static struct hw_interrupt_type hw_itypes[NUM_IRQ_INITS]; + +void __init mach_init_irqs (void) +{ + nb85e_intc_init_irq_types (irq_inits, hw_itypes); +} + +void machine_restart (char *__unused) +{ +#ifdef CONFIG_RESET_GUARD + disable_reset_guard (); +#endif + asm ("jmp r0"); /* Jump to the reset vector. */ +} + +void machine_halt (void) +{ +#ifdef CONFIG_RESET_GUARD + disable_reset_guard (); +#endif + local_irq_disable (); /* Ignore all interrupts. */ + ANNA_PORT_IO(0) = 0xAA; /* Note that we halted. */ + for (;;) + asm ("halt; nop; nop; nop; nop; nop"); +} + +void machine_power_off (void) +{ + machine_halt (); +} + +/* Called before configuring an on-chip UART. */ +void anna_uart_pre_configure (unsigned chan, unsigned cflags, unsigned baud) +{ + /* The Anna connects some general-purpose I/O pins on the CPU to + the RTS/CTS lines of UART 1's serial connection. I/O pins P07 + and P37 are RTS and CTS respectively. */ + if (chan == 1) { + ANNA_PORT_PM(0) &= ~0x80; /* P07 in output mode */ + ANNA_PORT_PM(3) |= 0x80; /* P37 in input mode */ + } +} + +/* Minimum and maximum bounds for the moving upper LED boundary in the + clock tick display. We can't use the last bit because it's used for + UART0's CTS output. */ +#define MIN_MAX_POS 0 +#define MAX_MAX_POS 6 + +/* There are MAX_MAX_POS^2 - MIN_MAX_POS^2 cycles in the animation, so if + we pick 6 and 0 as above, we get 49 cycles, which is when divided into + the standard 100 value for HZ, gives us an almost 1s total time. */ +#define TICKS_PER_FRAME \ + (HZ / (MAX_MAX_POS * MAX_MAX_POS - MIN_MAX_POS * MIN_MAX_POS)) + +static void anna_led_tick () +{ + static unsigned counter = 0; + + if (++counter == TICKS_PER_FRAME) { + static int pos = 0, max_pos = MAX_MAX_POS, dir = 1; + + if (dir > 0 && pos == max_pos) { + dir = -1; + if (max_pos == MIN_MAX_POS) + max_pos = MAX_MAX_POS; + else + max_pos--; + } else { + if (dir < 0 && pos == 0) + dir = 1; + + if (pos + dir <= max_pos) { + /* Each bit of port 0 has a LED. */ + clear_bit (pos, &ANNA_PORT_IO(0)); + pos += dir; + set_bit (pos, &ANNA_PORT_IO(0)); + } + } + + counter = 0; + } +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/v850/kernel/asm-consts.c linux.2.5.45-ac1/arch/v850/kernel/asm-consts.c --- linux.2.5.45/arch/v850/kernel/asm-consts.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/v850/kernel/asm-consts.c 2002-11-01 15:20:35.000000000 +0000 @@ -0,0 +1,60 @@ +/* + * This program is used to generate definitions needed by + * assembly language modules. + * + * We use the technique used in the OSF Mach kernel code: + * generate asm statements containing #defines, + * compile this file to assembler, and then extract the + * #defines from the assembly-language output. + */ + +#include +#include +#include +#include +#include +#include + +#define DEFINE(sym, val) \ + asm volatile("\n->" #sym " %0 " #val : : "i" (val)) + +#define BLANK() asm volatile("\n->" : : ) + +int main (void) +{ + /* offsets into the task struct */ + DEFINE (TASK_STATE, offsetof (struct task_struct, state)); + DEFINE (TASK_FLAGS, offsetof (struct task_struct, flags)); + DEFINE (TASK_PTRACE, offsetof (struct task_struct, ptrace)); + DEFINE (TASK_BLOCKED, offsetof (struct task_struct, blocked)); + DEFINE (TASK_THREAD, offsetof (struct task_struct, thread)); + DEFINE (TASK_THREAD_INFO, offsetof (struct task_struct, thread_info)); + DEFINE (TASK_MM, offsetof (struct task_struct, mm)); + DEFINE (TASK_ACTIVE_MM, offsetof (struct task_struct, active_mm)); + DEFINE (TASK_PID, offsetof (struct task_struct, pid)); + + /* offsets into the kernel_stat struct */ + DEFINE (STAT_IRQ, offsetof (struct kernel_stat, irqs)); + + + /* signal defines */ + DEFINE (SIGSEGV, SIGSEGV); + DEFINE (SEGV_MAPERR, SEGV_MAPERR); + DEFINE (SIGTRAP, SIGTRAP); + DEFINE (SIGCHLD, SIGCHLD); + DEFINE (SIGILL, SIGILL); + DEFINE (TRAP_TRACE, TRAP_TRACE); + + /* ptrace flag bits */ + DEFINE (PT_PTRACED, PT_PTRACED); + DEFINE (PT_DTRACE, PT_DTRACE); + + /* error values */ + DEFINE (ENOSYS, ENOSYS); + + /* clone flag bits */ + DEFINE (CLONE_VFORK, CLONE_VFORK); + DEFINE (CLONE_VM, CLONE_VM); + + return 0; +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/v850/kernel/bug.c linux.2.5.45-ac1/arch/v850/kernel/bug.c --- linux.2.5.45/arch/v850/kernel/bug.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/v850/kernel/bug.c 2002-11-01 15:20:35.000000000 +0000 @@ -0,0 +1,62 @@ +/* + * arch/v850/kernel/bug.c -- Bug reporting functions + * + * Copyright (C) 2001,02 NEC Corporation + * Copyright (C) 2001,02 Miles Bader + * + * 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. + * + * Written by Miles Bader + */ + +#include +#include +#include + +#include +#include +#include + +/* We should use __builtin_return_address, but it doesn't work in gcc-2.90 + (which is currently our standard compiler on the v850). */ +#define ret_addr() ({ register u32 lp asm ("lp"); lp; }) +#define stack_addr() ({ register u32 sp asm ("sp"); sp; }) + +void __bug () +{ + printk (KERN_CRIT "kernel BUG at PC 0x%x (SP ~0x%x)!\n", + ret_addr() - 4, /* - 4 for `jarl' */ + stack_addr()); + machine_halt (); +} + +int bad_trap (int trap_num, struct pt_regs *regs) +{ + printk (KERN_CRIT + "unimplemented trap %d called at 0x%08lx, pid %d!\n", + trap_num, regs->pc, current->pid); + return -ENOSYS; +} + +int debug_trap (struct pt_regs *regs) +{ + printk (KERN_CRIT "debug trap at 0x%08lx!\n", regs->pc); + return -ENOSYS; +} + +#ifdef CONFIG_RESET_GUARD +void unexpected_reset (unsigned long ret_addr, unsigned long kmode, + struct task_struct *task, unsigned long sp) +{ + printk (KERN_CRIT + "unexpected reset in %s mode, pid %d" + " (ret_addr = 0x%lx, sp = 0x%lx)\n", + kmode ? "kernel" : "user", + task ? task->pid : -1, + ret_addr, sp); + + machine_halt (); +} +#endif /* CONFIG_RESET_GUARD */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/v850/kernel/entry.S linux.2.5.45-ac1/arch/v850/kernel/entry.S --- linux.2.5.45/arch/v850/kernel/entry.S 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/v850/kernel/entry.S 2002-11-01 15:20:35.000000000 +0000 @@ -0,0 +1,1005 @@ +/* + * arch/v850/kernel/entry.S -- Low-level system-call handling, trap handlers, + * and context-switching + * + * Copyright (C) 2001,02 NEC Corporation + * Copyright (C) 2001,02 Miles Bader + * + * 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. + * + * Written by Miles Bader + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + + +/* Make a slightly more convenient alias for C_SYMBOL_NAME. */ +#define CSYM C_SYMBOL_NAME + + +/* The offset of the struct pt_regs in a `state save frame' on the stack. */ +#define PTO STATE_SAVE_PT_OFFSET + + +/* Save argument registers to the struct pt_regs pointed to by EP. */ +#define SAVE_ARG_REGS \ + sst.w r6, PTO+PT_GPR(6)[ep]; \ + sst.w r7, PTO+PT_GPR(7)[ep]; \ + sst.w r8, PTO+PT_GPR(8)[ep]; \ + sst.w r9, PTO+PT_GPR(9)[ep]; +/* Restore argument registers from the struct pt_regs pointed to by EP. */ +#define RESTORE_ARG_REGS \ + sld.w PTO+PT_GPR(6)[ep], r6; \ + sld.w PTO+PT_GPR(7)[ep], r7; \ + sld.w PTO+PT_GPR(8)[ep], r8; \ + sld.w PTO+PT_GPR(9)[ep], r9; + +/* Save value return registers to the struct pt_regs pointed to by EP. */ +#define SAVE_RVAL_REGS \ + sst.w r10, PTO+PT_GPR(10)[ep]; \ + sst.w r11, PTO+PT_GPR(11)[ep]; +/* Restore value return registers from the struct pt_regs pointed to by EP. */ +#define RESTORE_RVAL_REGS \ + sld.w PTO+PT_GPR(10)[ep], r10; \ + sld.w PTO+PT_GPR(11)[ep], r11; + + +#define SAVE_CALL_CLOBBERED_REGS_BEFORE_ARGS \ + sst.w r1, PTO+PT_GPR(1)[ep]; \ + sst.w r5, PTO+PT_GPR(5)[ep]; +#define SAVE_CALL_CLOBBERED_REGS_AFTER_RVAL \ + sst.w r12, PTO+PT_GPR(12)[ep]; \ + sst.w r13, PTO+PT_GPR(13)[ep]; \ + sst.w r14, PTO+PT_GPR(14)[ep]; \ + sst.w r15, PTO+PT_GPR(15)[ep]; \ + sst.w r16, PTO+PT_GPR(16)[ep]; \ + sst.w r17, PTO+PT_GPR(17)[ep]; \ + sst.w r18, PTO+PT_GPR(18)[ep]; \ + sst.w r19, PTO+PT_GPR(19)[ep]; +#define RESTORE_CALL_CLOBBERED_REGS_BEFORE_ARGS \ + sld.w PTO+PT_GPR(1)[ep], r1; \ + sld.w PTO+PT_GPR(5)[ep], r5; +#define RESTORE_CALL_CLOBBERED_REGS_AFTER_RVAL \ + sld.w PTO+PT_GPR(12)[ep], r12; \ + sld.w PTO+PT_GPR(13)[ep], r13; \ + sld.w PTO+PT_GPR(14)[ep], r14; \ + sld.w PTO+PT_GPR(15)[ep], r15; \ + sld.w PTO+PT_GPR(16)[ep], r16; \ + sld.w PTO+PT_GPR(17)[ep], r17; \ + sld.w PTO+PT_GPR(18)[ep], r18; \ + sld.w PTO+PT_GPR(19)[ep], r19; + +/* Save `call clobbered' registers to the struct pt_regs pointed to by EP. */ +#define SAVE_CALL_CLOBBERED_REGS \ + SAVE_CALL_CLOBBERED_REGS_BEFORE_ARGS; \ + SAVE_ARG_REGS; \ + SAVE_RVAL_REGS; \ + SAVE_CALL_CLOBBERED_REGS_AFTER_RVAL; +/* Restore `call clobbered' registers from the struct pt_regs pointed to + by EP. */ +#define RESTORE_CALL_CLOBBERED_REGS \ + RESTORE_CALL_CLOBBERED_REGS_BEFORE_ARGS; \ + RESTORE_ARG_REGS; \ + RESTORE_RVAL_REGS; \ + RESTORE_CALL_CLOBBERED_REGS_AFTER_RVAL; + +/* Save `call clobbered' registers except for the return-value registers + to the struct pt_regs pointed to by EP. */ +#define SAVE_CALL_CLOBBERED_REGS_NO_RVAL \ + SAVE_CALL_CLOBBERED_REGS_BEFORE_ARGS; \ + SAVE_ARG_REGS; \ + SAVE_CALL_CLOBBERED_REGS_AFTER_RVAL; +/* Restore `call clobbered' registers except for the return-value registers + from the struct pt_regs pointed to by EP. */ +#define RESTORE_CALL_CLOBBERED_REGS_NO_RVAL \ + RESTORE_CALL_CLOBBERED_REGS_BEFORE_ARGS; \ + RESTORE_ARG_REGS; \ + RESTORE_CALL_CLOBBERED_REGS_AFTER_RVAL; + +/* Zero `call clobbered' registers except for the return-value registers. */ +#define ZERO_CALL_CLOBBERED_REGS_NO_RVAL \ + mov r0, r1; mov r0, r5; \ + mov r0, r12; mov r0, r13; mov r0, r14; mov r0, r15; \ + mov r0, r16; mov r0, r17; mov r0, r18; mov r0, r19; + +/* Save `call saved' registers to the struct pt_regs pointed to by EP. */ +#define SAVE_CALL_SAVED_REGS \ + sst.w r2, PTO+PT_GPR(2)[ep]; \ + sst.w r20, PTO+PT_GPR(20)[ep]; \ + sst.w r21, PTO+PT_GPR(21)[ep]; \ + sst.w r22, PTO+PT_GPR(22)[ep]; \ + sst.w r23, PTO+PT_GPR(23)[ep]; \ + sst.w r24, PTO+PT_GPR(24)[ep]; \ + sst.w r25, PTO+PT_GPR(25)[ep]; \ + sst.w r26, PTO+PT_GPR(26)[ep]; \ + sst.w r27, PTO+PT_GPR(27)[ep]; \ + sst.w r28, PTO+PT_GPR(28)[ep]; \ + sst.w r29, PTO+PT_GPR(29)[ep]; +/* Restore `call saved' registers from the struct pt_regs pointed to by EP. */ +#define RESTORE_CALL_SAVED_REGS \ + sld.w PTO+PT_GPR(2)[ep], r2; \ + sld.w PTO+PT_GPR(20)[ep], r20; \ + sld.w PTO+PT_GPR(21)[ep], r21; \ + sld.w PTO+PT_GPR(22)[ep], r22; \ + sld.w PTO+PT_GPR(23)[ep], r23; \ + sld.w PTO+PT_GPR(24)[ep], r24; \ + sld.w PTO+PT_GPR(25)[ep], r25; \ + sld.w PTO+PT_GPR(26)[ep], r26; \ + sld.w PTO+PT_GPR(27)[ep], r27; \ + sld.w PTO+PT_GPR(28)[ep], r28; \ + sld.w PTO+PT_GPR(29)[ep], r29; + + +/* Save system registers to the struct pt_regs pointed to by REG. + r19 is clobbered. */ +#define SAVE_SYS_REGS \ + stsr SR_EIPC, r19; /* user's PC, before interrupt */ \ + sst.w r19, PTO+PT_PC[ep]; \ + stsr SR_EIPSW, r19; /* & PSW (XXX save this?) */ \ + sst.w r19, PTO+PT_PSW[ep]; \ + stsr SR_CTPC, r19; /* (XXX maybe not used in kernel?) */ \ + sst.w r19, PTO+PT_CTPC[ep]; \ + stsr SR_CTPSW, r19; /* " */ \ + sst.w r19, PTO+PT_CTPSW[ep]; \ + stsr SR_CTBP, r19; /* " */ \ + sst.w r19, PTO+PT_CTBP[ep]; +/* Restore system registers from the struct pt_regs pointed to by EP. + LP is clobbered (it is used as a scratch register because the POP_STATE + macro restores it, and this macro is usually used inside POP_STATE). */ +#define RESTORE_SYS_REGS \ + sld.w PTO+PT_PC[ep], lp; \ + ldsr lp, SR_EIPC; /* user's PC, before interrupt */ \ + sld.w PTO+PT_PSW[ep], lp; \ + ldsr lp, SR_EIPSW; /* & PSW (XXX save this?) */ \ + sld.w PTO+PT_CTPC[ep], lp; \ + ldsr lp, SR_CTPC; /* (XXX maybe not used in kernel?) */ \ + sld.w PTO+PT_CTPSW[ep], lp; \ + ldsr lp, SR_CTPSW; /* " */ \ + sld.w PTO+PT_CTBP[ep], lp; \ + ldsr lp, SR_CTBP; /* " */ + + +/* Save system registers to the struct pt_regs pointed to by REG. This is a + NMI-specific version, because NMIs save the PC/PSW in a different place + than other interrupt requests. r19 is clobbered. */ +#define SAVE_SYS_REGS_FOR_NMI \ + stsr SR_FEPC, r19; /* user's PC, before NMI */ \ + sst.w r19, PTO+PT_PC[ep]; \ + stsr SR_FEPSW, r19; /* & PSW (XXX save this?) */ \ + sst.w r19, PTO+PT_PSW[ep]; \ + stsr SR_CTPC, r19; /* (XXX maybe not used in kernel?) */ \ + sst.w r19, PTO+PT_CTPC[ep]; \ + stsr SR_CTPSW, r19; /* " */ \ + sst.w r19, PTO+PT_CTPSW[ep]; \ + stsr SR_CTBP, r19; /* " */ \ + sst.w r19, PTO+PT_CTBP[ep]; +/* Restore system registers from the struct pt_regs pointed to by EP. This is + a NMI-specific version, because NMIs save the PC/PSW in a different place + than other interrupt requests. LP is clobbered (it is used as a scratch + register because the POP_STATE macro restores it, and this macro is usually + used inside POP_STATE). */ +#define RESTORE_SYS_REGS_FOR_NMI \ + ldsr lp, SR_FEPC; /* user's PC, before NMI */ \ + sld.w PTO+PT_PC[ep], lp; \ + ldsr lp, SR_FEPSW; /* & PSW (XXX save this?) */ \ + sld.w PTO+PT_PSW[ep], lp; \ + ldsr lp, SR_CTPC; /* (XXX maybe not used in kernel?) */ \ + sld.w PTO+PT_CTPC[ep], lp; \ + ldsr lp, SR_CTPSW; /* " */ \ + sld.w PTO+PT_CTPSW[ep], lp; \ + ldsr lp, SR_CTBP; /* " */ \ + sld.w PTO+PT_CTBP[ep], lp; + + +/* Push register state, except for the stack pointer, on the stack in the form + of a struct pt_regs, in preparation for a system call. This macro makes + sure that `special' registers, system registers; TYPE identifies the set of + extra registers to be saved as well. EP is clobbered. */ +#define PUSH_STATE(type) \ + addi -STATE_SAVE_SIZE, sp, sp; /* Make room on the stack. */ \ + st.w ep, PTO+PT_GPR(GPR_EP)[sp]; \ + mov sp, ep; \ + sst.w gp, PTO+PT_GPR(GPR_GP)[ep]; \ + sst.w lp, PTO+PT_GPR(GPR_LP)[ep]; \ + type ## _STATE_SAVER; +/* Pop a register state, except for the stack pointer, from the struct pt_regs + on the stack. */ +#define POP_STATE(type) \ + mov sp, ep; \ + type ## _STATE_RESTORER; \ + sld.w PTO+PT_GPR(GPR_GP)[ep], gp; \ + sld.w PTO+PT_GPR(GPR_LP)[ep], lp; \ + sld.w PTO+PT_GPR(GPR_EP)[ep], ep; \ + addi STATE_SAVE_SIZE, sp, sp; /* Clean up our stack space. */ + + +/* Switch to the kernel stack if necessary, and push register state on + the stack in the form of a struct pt_regs. Also load the current + task pointer if switching from user mode. The stack-pointer (r3) + should have already been saved to the memory location SP_SAVE_LOC + (the reason for this is that the interrupt vectors may be beyond a + 22-bit signed offset jump from the actual interrupt handler, and this + allows them to save the stack-pointer and use that register to do an + indirect jump). This macro makes sure that `special' registers, + system registers, and the stack pointer are saved; TYPE identifies + the set of extra registers to be saved as well. SYSCALL_NUM is the + register in which the system-call number this state is for is stored + (r0 if this isn't a system call). Interrupts should already be + disabled when calling this. */ +#define SAVE_STATE(type, syscall_num, sp_save_loc) \ + tst1 0, KM; /* See if already in kernel mode. */ \ + bz 1f; \ + /* Kernel-mode state save. */ \ + ld.w sp_save_loc, sp; /* Reload kernel stack-pointer. */ \ + st.w sp, (PT_GPR(GPR_SP)-PT_SIZE)[sp]; /* Save original SP. */ \ + PUSH_STATE(type); \ + mov 1, r19; /* Was in kernel-mode. */ \ + sst.w r19, PTO+PT_KERNEL_MODE[ep]; /* [ep is set by PUSH_STATE] */ \ + br 2f; \ +1: /* User-mode state save. */ \ + ld.w KSP, sp; /* Switch to kernel stack. */ \ + PUSH_STATE(type); \ + sst.w r0, PTO+PT_KERNEL_MODE[ep]; /* Was in user-mode. */ \ + ld.w sp_save_loc, r19; \ + sst.w r19, PTO+PT_GPR(GPR_SP)[ep]; /* Store user SP. */ \ + mov 1, r19; \ + st.b r19, KM; /* Now we're in kernel-mode. */ \ + GET_CURRENT_TASK(CURRENT_TASK); /* Fetch the current task pointer. */ \ +2: /* Save away the syscall number. */ \ + sst.w syscall_num, PTO+PT_SYSCALL[ep] + + +/* Save register state not normally saved by PUSH_STATE for TYPE. */ +#define SAVE_EXTRA_STATE(type) \ + mov sp, ep; \ + type ## _EXTRA_STATE_SAVER; +/* Restore register state not normally restored by POP_STATE for TYPE. */ +#define RESTORE_EXTRA_STATE(type) \ + mov sp, ep; \ + type ## _EXTRA_STATE_RESTORER; + +/* Save any call-clobbered registers not normally saved by PUSH_STATE + for TYPE. */ +#define SAVE_EXTRA_STATE_FOR_FUNCALL(type) \ + mov sp, ep; \ + type ## _FUNCALL_EXTRA_STATE_SAVER; +/* Restore any call-clobbered registers not normally restored by POP_STATE for + TYPE. */ +#define RESTORE_EXTRA_STATE_FOR_FUNCALL(type) \ + mov sp, ep; \ + type ## _FUNCALL_EXTRA_STATE_RESTORER; + + +/* These are extra_state_saver/restorer values for a user trap. Note that we + save the argument registers so that restarted syscalls will function + properly (otherwise it wouldn't be necessary), and we must _not_ restore + the return-value registers (so that traps can return a value!), but there + are various options for what happens to other call-clobbered registers, + selected by preprocessor conditionals. */ + +#if TRAPS_PRESERVE_CALL_CLOBBERED_REGS + +/* Traps save/restore all call-clobbered registers (except for rval regs). */ +#define TRAP_STATE_SAVER \ + SAVE_CALL_CLOBBERED_REGS_NO_RVAL; \ + SAVE_SYS_REGS +#define TRAP_STATE_RESTORER \ + RESTORE_CALL_CLOBBERED_REGS_NO_RVAL; \ + RESTORE_SYS_REGS + +#else /* !TRAPS_PRESERVE_CALL_CLOBBERED_REGS */ + +/* Traps don't save call-clobbered registers (but do still save arg regs). */ +#define TRAP_STATE_SAVER \ + SAVE_ARG_REGS; \ + SAVE_SYS_REGS + +#if TRAPS_ZERO_CALL_CLOBBERED_REGS + +/* Traps zero call-clobbered registers (except for arg/rval regs) before + returning from a system call, to avoid any internal values from leaking out + of the kernel. */ +#define TRAP_STATE_RESTORER \ + ZERO_CALL_CLOBBERED_REGS_NO_ARGS_NO_RVAL; \ + RESTORE_ARG_REGS; \ + RESTORE_SYS_REGS + +#else /* !TRAPS_ZERO_CALL_CLOBBERED_REGS */ + +/* When traps return, they just leave call-clobbered registers (except for arg + regs) with whatever value they have from the kernel. */ +#define TRAP_STATE_RESTORER \ + RESTORE_ARG_REGS; \ + RESTORE_SYS_REGS + +#endif /* TRAPS_ZERO_CALL_CLOBBERED_REGS */ +#endif /* TRAPS_PRESERVE_CALL_CLOBBERED_REGS */ + +/* Save registers not normally saved by traps. */ +#define TRAP_EXTRA_STATE_SAVER \ + SAVE_RVAL_REGS; \ + SAVE_CALL_SAVED_REGS +#define TRAP_EXTRA_STATE_RESTORER \ + RESTORE_RVAL_REGS; \ + RESTORE_CALL_SAVED_REGS +#define TRAP_FUNCALL_EXTRA_STATE_SAVER \ + SAVE_RVAL_REGS +#define TRAP_FUNCALL_EXTRA_STATE_RESTORER \ + RESTORE_RVAL_REGS + + +/* Register saving/restoring for maskable interrupts. */ +#define IRQ_STATE_SAVER \ + SAVE_CALL_CLOBBERED_REGS; \ + SAVE_SYS_REGS +#define IRQ_STATE_RESTORER \ + RESTORE_CALL_CLOBBERED_REGS; \ + RESTORE_SYS_REGS +#define IRQ_EXTRA_STATE_SAVER \ + SAVE_CALL_SAVED_REGS +#define IRQ_EXTRA_STATE_RESTORER \ + RESTORE_CALL_SAVED_REGS +#define IRQ_FUNCALL_EXTRA_STATE_SAVER /* nothing */ +#define IRQ_FUNCALL_EXTRA_STATE_RESTORER /* nothing */ + +/* Register saving/restoring for non-maskable interrupts. */ +#define NMI_STATE_SAVER \ + SAVE_CALL_CLOBBERED_REGS; \ + SAVE_SYS_REGS_FOR_NMI +#define NMI_STATE_RESTORER \ + RESTORE_CALL_CLOBBERED_REGS; \ + RESTORE_SYS_REGS_FOR_NMI +#define NMI_EXTRA_STATE_SAVER \ + SAVE_CALL_SAVED_REGS +#define NMI_EXTRA_STATE_RESTORER \ + RESTORE_CALL_SAVED_REGS +#define NMI_FUNCALL_EXTRA_STATE_SAVER /* nothing */ +#define NMI_FUNCALL_EXTRA_STATE_RESTORER /* nothing */ + +/* Register saving/restoring for a context switch. We don't need to save too + many registers, because context-switching looks like a function call (via + the function `switch_thread'), so callers will save any call-clobbered + registers themselves. The stack pointer and return value are handled by + switch_thread itself. */ +#define SWITCH_STATE_SAVER \ + SAVE_CALL_SAVED_REGS +#define SWITCH_STATE_RESTORER \ + RESTORE_CALL_SAVED_REGS + + +/* Restore register state from the struct pt_regs on the stack, switch back + to the user stack if necessary, and return from the trap/interrupt. + EXTRA_STATE_RESTORER is a sequence of assembly language statements to + restore anything not restored by this macro. Only registers not saved by + the C compiler are restored (that is, R3(sp), R4(gp), R31(lp), and + anything restored by EXTRA_STATE_RESTORER). */ +#define RETURN(type) \ + ld.b PTO+PT_KERNEL_MODE[sp], r19; \ + di; /* Disable interrupts */ \ + cmp r19, r0; /* See if returning to kernel mode, */\ + bne 2f; /* ... if so, skip resched &c. */ \ + \ + /* We're returning to user mode, so check for various conditions that \ + trigger rescheduling. */ \ + GET_CURRENT_THREAD(r18); \ + ld.w TI_FLAGS[r18], r19; \ + andi _TIF_NEED_RESCHED, r19, r0; \ + bnz 3f; /* Call the scheduler. */ \ + andi _TIF_SIGPENDING, r19, r0; \ + bnz 4f; /* Signals to handle, handle them */ \ + \ +/* Finally, return to user state. */ \ +1: st.b r0, KM; /* Now officially in user state. */ \ + POP_STATE(type); \ + st.w sp, KSP; /* Save the kernel stack pointer. */ \ + ld.w PT_GPR(GPR_SP)-PT_SIZE[sp], sp; \ + /* Restore user stack pointer. */ \ + reti; \ + \ +/* Return to kernel state. */ \ +2: POP_STATE(type); \ + reti; \ + \ +/* Call the scheduler before returning from a syscall/trap. */ \ +3: SAVE_EXTRA_STATE_FOR_FUNCALL(type); /* Prepare for funcall. */ \ + jarl CSYM(schedule), lp; /* Call scheduler */ \ + di; /* The scheduler enables interrupts */\ + RESTORE_EXTRA_STATE_FOR_FUNCALL(type); \ + br 1b; \ + \ +/* Handle a signal return. */ \ +4: /* Not all registers are saved by the normal trap/interrupt entry \ + points (for instance, call-saved registers (because the normal \ + C-compiler calling sequence in the kernel makes sure they're \ + preserved), and call-clobbered registers in the case of \ + traps), but signal handlers may want to examine or change the \ + complete register state. Here we save anything not saved by \ + the normal entry sequence, so that it may be safely restored \ + (in a possibly modified form) after do_signal returns. */ \ + SAVE_EXTRA_STATE(type) /* Save state not saved by entry. */ \ + movea PTO, sp, r6; /* Arg 1: struct pt_regs *regs */ \ + mov r0, r7; /* Arg 2: sigset_t *oldset */ \ + jarl CSYM(do_signal), lp; /* Handle any signals */ \ + di; /* sig handling enables interrupts */ \ + RESTORE_EXTRA_STATE(type); /* Restore extra regs. */ \ + br 1b; + + +/* Jump to the appropriate function for the system call number in r12 + (r12 is not preserved), or return an error if r12 is not valid. The + LP register should point to the location where the called function + should return. [note that MAKE_SYS_CALL uses label 1] */ +#define MAKE_SYS_CALL \ + /* See if the system call number is valid. */ \ + addi -NR_syscalls, r12, r0; \ + bnh 1f; \ + /* Figure out which function to use for this system call. */ \ + shl 2, r12; \ + mov hilo(CSYM(sys_call_table)), r19; \ + add r19, r12; \ + ld.w 0[r12], r12; \ + /* Make the system call. */ \ + jmp [r12]; \ + /* The syscall number is invalid, return an error. */ \ +1: addi -ENOSYS, r0, r10; \ + jmp [lp]; + + + .text + +/* + * User trap. + * + * Trap 0 system calls are also handled here. + * + * The stack-pointer (r3) should have already been saved to the memory + * location ENTRY_SP (the reason for this is that the interrupt vectors may be + * beyond a 22-bit signed offset jump from the actual interrupt handler, and + * this allows them to save the stack-pointer and use that register to do an + * indirect jump). + * + * Syscall protocol: + * Syscall number in r12, args in r6-r9 + * Return value in r10 + */ +G_ENTRY(trap): + SAVE_STATE (TRAP, r12, ENTRY_SP) // Save registers. + stsr SR_ECR, r19 // Find out which trap it was. + ei // Enable interrupts. + mov hilo(ret_from_trap), lp // where the trap should return + + // The following two shifts (1) clear out extraneous NMI data in the + // upper 16-bits, (2) convert the 0x40 - 0x5f range of trap ECR + // numbers into the (0-31) << 2 range we want, (3) set the flags. + shl 27, r19 // chop off all high bits + shr 25, r19 // scale back down and then << 2 + bnz 2f // See if not trap 0. + + // Trap 0 is a `short' system call, skip general trap table. + MAKE_SYS_CALL // Jump to the syscall function. + +2: // For other traps, use a table lookup. + mov hilo(CSYM(trap_table)), r18 + add r19, r18 + ld.w 0[r18], r18 + jmp [r18] // Jump to the trap handler. +END(trap) + +/* This is just like ret_from_trap, but first restores extra registers + saved by some wrappers. */ +L_ENTRY(restore_extra_regs_and_ret_from_trap): + RESTORE_EXTRA_STATE(TRAP) + // fall through +END(restore_extra_regs_and_ret_from_trap) + +/* Entry point used to return from a syscall/trap. */ +L_ENTRY(ret_from_trap): + RETURN(TRAP) +END(ret_from_trap) + +/* This the initial entry point for a new child thread, with an appropriate + stack in place that makes it look the the child is in the middle of an + syscall. This function is actually `returned to' from switch_thread + (copy_thread makes ret_from_fork the return address in each new thread's + saved context). */ +C_ENTRY(ret_from_fork): +#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT) + mov r10, r6 // switch_thread returns the prev task. + jarl CSYM(schedule_tail), lp // ...which is schedule_tail's arg +#endif + mov r0, r10 // Child's fork call should return 0. + br ret_from_trap // Do normal trap return. +C_END(ret_from_fork) + + +/* + * Trap 1: `long' system calls + * `Long' syscall protocol: + * Syscall number in r12, args in r6-r9, r13-r14 + * Return value in r10 + */ +L_ENTRY(syscall_long): + // Push extra arguments on the stack. Note that by default, the trap + // handler reserves enough stack space for 6 arguments, so we don't + // have to make any additional room. + st.w r13, 16[sp] // arg 5 + st.w r14, 20[sp] // arg 6 + +#if !TRAPS_PRESERVE_CALL_CLOBBERED_REGS + // Make sure r13 and r14 are preserved, in case we have to restart a + // system call because of a signal (ep has already been set by caller). + st.w r13, PTO+PT_GPR(13)[sp] + st.w r14, PTO+PT_GPR(13)[sp] + mov hilo(ret_from_long_syscall), lp +#endif /* !TRAPS_PRESERVE_CALL_CLOBBERED_REGS */ + + MAKE_SYS_CALL // Jump to the syscall function. +END(syscall_long) + +#if !TRAPS_PRESERVE_CALL_CLOBBERED_REGS +/* Entry point used to return from a long syscall. Only needed to restore + r13/r14 if the general trap mechanism doesnt' do so. */ +L_ENTRY(ret_from_long_syscall): + ld.w PTO+PT_GPR(13)[sp], r13 // Restore the extra registers + ld.w PTO+PT_GPR(13)[sp], r14 + br ret_from_trap // The rest is the same as other traps +END(ret_from_long_syscall) +#endif /* !TRAPS_PRESERVE_CALL_CLOBBERED_REGS */ + + +/* These syscalls need access to the struct pt_regs on the stack, so we + implement them in assembly (they're basically all wrappers anyway). */ + +L_ENTRY(sys_fork_wrapper): +#ifdef CONFIG_MMU + // Save state not saved by entry. This is actually slight overkill; + // it's actually only necessary to save any state restored by + // switch_thread that's not saved by the trap entry. + SAVE_EXTRA_STATE(TRAP) // Save state not saved by entry. + addi SIGCHLD, r0, r6 // Arg 0: flags + ld.w PTO+PT_GPR(GPR_SP)[sp], r7 // Arg 1: child SP (use parent's) + movea PTO, sp, r8 // Arg 2: parent context + jr CSYM(fork_common) // Do real work (tail-call). +#else + // fork almost works, enough to trick you into looking elsewhere :-( + addi -EINVAL, r0, r10 + jmp [lp] +#endif +END(sys_fork_wrapper) + +L_ENTRY(sys_vfork_wrapper): + // Save state not saved by entry. This is actually slight overkill; + // it's actually only necessary to save any state restored by + // switch_thread that's not saved by the trap entry. + SAVE_EXTRA_STATE(TRAP) // Save state not saved by entry. + addi CLONE_VFORK | CLONE_VM | SIGCHLD, r0, r6 // Arg 0: flags + ld.w PTO+PT_GPR(GPR_SP)[sp], r7 // Arg 1: child SP (use parent's) + movea PTO, sp, r8 // Arg 2: parent context + jr CSYM(fork_common) // Do real work (tail-call). +END(sys_vfork_wrapper) + +L_ENTRY(sys_clone_wrapper): + // Save state not saved by entry. This is actually slight overkill; + // it's actually only necessary to save any state restored by + // switch_thread that's not saved by the trap entry. + SAVE_EXTRA_STATE(TRAP) // Save state not saved by entry. + ld.w PTO+PT_GPR(GPR_SP)[sp], r19 // parent's stack pointer + cmp r7, r0 // See if child SP arg (arg 1) is 0. + cmov z, r19, r7, r7 // ... and use the parent's if so. + movea PTO, sp, r8 // Arg 2: parent context + jr CSYM(fork_common) // Do real work (tail-call). +END(sys_clone_wrapper) + +L_ENTRY(sys_execve_wrapper): + movea PTO, sp, r9 // add user context as 4th arg + jr CSYM(sys_execve) // Do real work (tail-call). +END(sys_execve_wrapper) + +L_ENTRY(sys_sigsuspend_wrapper): + SAVE_EXTRA_STATE(TRAP) // Save state not saved by entry. + movea PTO, sp, r7 // add user context as 2nd arg + jarl CSYM(sys_sigsuspend), lp// Do real work. + br restore_extra_regs_and_ret_from_trap +END(sys_sigsuspend_wrapper) +L_ENTRY(sys_rt_sigsuspend_wrapper): + SAVE_EXTRA_STATE(TRAP) // Save state not saved by entry. + movea PTO, sp, r8 // add user context as 3rd arg + jarl CSYM(sys_rt_sigsuspend), lp // Do real work. + br restore_extra_regs_and_ret_from_trap +END(sys_rt_sigsuspend_wrapper) + +L_ENTRY(sys_sigreturn_wrapper): + SAVE_EXTRA_STATE(TRAP) // Save state not saved by entry. + movea PTO, sp, r6 // add user context as 1st arg + jarl CSYM(sys_sigreturn), lp // Do real work. + br restore_extra_regs_and_ret_from_trap +END(sys_sigreturn_wrapper) +L_ENTRY(sys_rt_sigreturn_wrapper): + SAVE_EXTRA_STATE(TRAP) // Save state not saved by entry. + movea PTO, sp, r6 // add user context as 1st arg + jarl CSYM(sys_rt_sigreturn), lp // Do real work. + br restore_extra_regs_and_ret_from_trap +END(sys_rt_sigreturn_wrapper) + + +/* + * Hardware maskable interrupts. + * + * The stack-pointer (r3) should have already been saved to the memory + * location ENTRY_SP (the reason for this is that the interrupt vectors may be + * beyond a 22-bit signed offset jump from the actual interrupt handler, and + * this allows them to save the stack-pointer and use that register to do an + * indirect jump). + */ +G_ENTRY(irq): + SAVE_STATE (IRQ, r0, ENTRY_SP) // Save registers. + + stsr SR_ECR, r6 // Find out which interrupt it was. + movea PTO, sp, r7 // User regs are arg2 + + // All v850 implementations I know about encode their interrupts as + // multiples of 0x10, starting at 0x80 (after NMIs and software + // interrupts). Convert this number into a simple IRQ index for the + // rest of the kernel. We also clear the upper 16 bits, which hold + // NMI info, and don't appear to be cleared when a NMI returns. + shl 16, r6 // clear upper 16 bits + shr 20, r6 // shift back, and remove lower nibble + add -8, r6 // remove bias for irqs + // Call the high-level interrupt handling code. + jarl CSYM(handle_irq), lp + // fall through + +/* Entry point used to return from an interrupt (also used by exception + handlers, below). */ +ret_from_irq: + RETURN(IRQ) +END(irq) + + +/* + * Hardware non-maskable interrupts. + * + * The stack-pointer (r3) should have already been saved to the memory + * location ENTRY_SP (the reason for this is that the interrupt vectors may be + * beyond a 22-bit signed offset jump from the actual interrupt handler, and + * this allows them to save the stack-pointer and use that register to do an + * indirect jump). + */ +G_ENTRY(nmi): + SAVE_STATE (NMI, r0, NMI_ENTRY_SP); /* Save registers. */ + + stsr SR_ECR, r6; /* Find out which nmi it was. */ + shr 20, r6; /* Extract NMI code in bits 20-24. */ + movea PTO, sp, r7; /* User regs are arg2. */ + + /* Non-maskable interrupts always lie right after maskable interrupts. + Call the generic IRQ handler, with two arguments, the IRQ number, + and a pointer to the user registers, to handle the specifics. + (we subtract one because the first NMI has code 1). */ + addi FIRST_NMI - 1, r6, r6; + jarl CSYM(handle_irq), lp + + RETURN(NMI) +END(nmi0) + + +/* + * Illegal instruction trap. + * + * The stack-pointer (r3) should have already been saved to the memory + * location ENTRY_SP (the reason for this is that the interrupt vectors may be + * beyond a 22-bit signed offset jump from the actual interrupt handler, and + * this allows them to save the stack-pointer and use that register to do an + * indirect jump). + */ +G_ENTRY(illegal_instruction): + SAVE_STATE (IRQ, r0, ENTRY_SP) // Save registers. + ei + addi SIGILL, r0, r6 // Arg 0: signal number + mov CURRENT_TASK, r7 // Arg 1: task + mov hilo(ret_from_irq), lp // where the handler should return + jr CSYM(force_sig) +END(illegal_instruction) + + +/* + * `Debug' trap + * + * The stack-pointer (r3) should have already been saved to the memory + * location ENTRY_SP (the reason for this is that the interrupt vectors may be + * beyond a 22-bit signed offset jump from the actual interrupt handler, and + * this allows them to save the stack-pointer and use that register to do an + * indirect jump). + */ +G_ENTRY(dbtrap): + SAVE_STATE (IRQ, r0, ENTRY_SP) // Save registers. + ei + movea PTO, sp, r6 // Arg 0: user regs + mov hilo(ret_from_irq), lp // where the handler should return + jr CSYM(debug_trap) +END(dbtrap) + + +/* + * Trap with no handler + */ +L_ENTRY(bad_trap_wrapper): + mov r19, r6 // Arg 0: trap number + movea PTO, sp, r7 // Arg 1: user regs + jr CSYM(bad_trap) // tail call handler +END(bad_trap_wrapper) + + +/* + * This is where we switch between two threads. The arguments are: + * r6 -- pointer to the struct thread for the `current' process + * r7 -- pointer to the struct thread for the `new' process. + * when this function returns, it will return to the new thread. + */ +C_ENTRY(switch_thread): + // Return the previous task (r10 is not clobbered by restore below) + mov CURRENT_TASK, r10 + // First, push the current processor state on the stack + PUSH_STATE(SWITCH) + // Now save the location of the kernel stack pointer for this thread; + // since we've pushed all other state on the stack, this is enough to + // restore it all later. + st.w sp, THREAD_KSP[r6] + // Now restore the stack pointer from the new process + ld.w THREAD_KSP[r7], sp + // ... and restore all state from that + POP_STATE(SWITCH) + // Update the current task pointer + GET_CURRENT_TASK(CURRENT_TASK) + // Now return into the new thread + jmp [lp] +C_END(switch_thread) + + + .data + + .align 4 + .globl CSYM(trap_table) +CSYM(trap_table): + .long bad_trap_wrapper // trap 0, doesn't use trap table. + .long syscall_long // trap 1, `long' syscall. + .long bad_trap_wrapper + .long bad_trap_wrapper + .long bad_trap_wrapper + .long bad_trap_wrapper + .long bad_trap_wrapper + .long bad_trap_wrapper + .long bad_trap_wrapper + .long bad_trap_wrapper + .long bad_trap_wrapper + .long bad_trap_wrapper + .long bad_trap_wrapper + .long bad_trap_wrapper + .long bad_trap_wrapper + .long bad_trap_wrapper + + + .section .rodata + + .align 4 + .globl CSYM(sys_call_table) +CSYM(sys_call_table): + .long CSYM(sys_ni_syscall) // 0 - old "setup()" system call + .long CSYM(sys_exit) + .long sys_fork_wrapper + .long CSYM(sys_read) + .long CSYM(sys_write) + .long CSYM(sys_open) // 5 + .long CSYM(sys_close) + .long CSYM(sys_waitpid) + .long CSYM(sys_creat) + .long CSYM(sys_link) + .long CSYM(sys_unlink) // 10 + .long sys_execve_wrapper + .long CSYM(sys_chdir) + .long CSYM(sys_time) + .long CSYM(sys_mknod) + .long CSYM(sys_chmod) // 15 + .long CSYM(sys_chown) + .long CSYM(sys_ni_syscall) // was: break + .long CSYM(sys_ni_syscall) // was: oldstat (aka stat) + .long CSYM(sys_lseek) + .long CSYM(sys_getpid) // 20 + .long CSYM(sys_mount) + .long CSYM(sys_oldumount) + .long CSYM(sys_setuid) + .long CSYM(sys_getuid) + .long CSYM(sys_stime) // 25 + .long CSYM(sys_ptrace) + .long CSYM(sys_alarm) + .long CSYM(sys_ni_syscall) // was: oldfstat (aka fstat) + .long CSYM(sys_pause) + .long CSYM(sys_utime) // 30 + .long CSYM(sys_ni_syscall) // was: stty + .long CSYM(sys_ni_syscall) // was: gtty + .long CSYM(sys_access) + .long CSYM(sys_nice) + .long CSYM(sys_ni_syscall) // 35, was: ftime + .long CSYM(sys_sync) + .long CSYM(sys_kill) + .long CSYM(sys_rename) + .long CSYM(sys_mkdir) + .long CSYM(sys_rmdir) // 40 + .long CSYM(sys_dup) + .long CSYM(sys_pipe) + .long CSYM(sys_times) + .long CSYM(sys_ni_syscall) // was: prof + .long CSYM(sys_brk) // 45 + .long CSYM(sys_setgid) + .long CSYM(sys_getgid) + .long CSYM(sys_signal) + .long CSYM(sys_geteuid) + .long CSYM(sys_getegid) // 50 + .long CSYM(sys_acct) + .long CSYM(sys_umount) // recycled never used phys() + .long CSYM(sys_ni_syscall) // was: lock + .long CSYM(sys_ioctl) + .long CSYM(sys_fcntl) // 55 + .long CSYM(sys_ni_syscall) // was: mpx + .long CSYM(sys_setpgid) + .long CSYM(sys_ni_syscall) // was: ulimit + .long CSYM(sys_ni_syscall) + .long CSYM(sys_umask) // 60 + .long CSYM(sys_chroot) + .long CSYM(sys_ustat) + .long CSYM(sys_dup2) + .long CSYM(sys_getppid) + .long CSYM(sys_getpgrp) // 65 + .long CSYM(sys_setsid) + .long CSYM(sys_sigaction) + .long CSYM(sys_sgetmask) + .long CSYM(sys_ssetmask) + .long CSYM(sys_setreuid) // 70 + .long CSYM(sys_setregid) + .long sys_sigsuspend_wrapper + .long CSYM(sys_sigpending) + .long CSYM(sys_sethostname) + .long CSYM(sys_setrlimit) // 75 + .long CSYM(sys_getrlimit) + .long CSYM(sys_getrusage) + .long CSYM(sys_gettimeofday) + .long CSYM(sys_settimeofday) + .long CSYM(sys_getgroups) // 80 + .long CSYM(sys_setgroups) + .long CSYM(sys_select) + .long CSYM(sys_symlink) + .long CSYM(sys_ni_syscall) // was: oldlstat (aka lstat) + .long CSYM(sys_readlink) // 85 + .long CSYM(sys_uselib) + .long CSYM(sys_swapon) + .long CSYM(sys_reboot) + .long CSYM(old_readdir) + .long CSYM(sys_mmap) // 90 + .long CSYM(sys_munmap) + .long CSYM(sys_truncate) + .long CSYM(sys_ftruncate) + .long CSYM(sys_fchmod) + .long CSYM(sys_fchown) // 95 + .long CSYM(sys_getpriority) + .long CSYM(sys_setpriority) + .long CSYM(sys_ni_syscall) // was: profil + .long CSYM(sys_statfs) + .long CSYM(sys_fstatfs) // 100 + .long CSYM(sys_ni_syscall) // i386: ioperm + .long CSYM(sys_socketcall) + .long CSYM(sys_syslog) + .long CSYM(sys_setitimer) + .long CSYM(sys_getitimer) // 105 + .long CSYM(sys_newstat) + .long CSYM(sys_newlstat) + .long CSYM(sys_newfstat) + .long CSYM(sys_ni_syscall) // was: olduname (aka uname) + .long CSYM(sys_ni_syscall) // 110, i386: iopl + .long CSYM(sys_vhangup) + .long CSYM(sys_ni_syscall) // was: idle + .long CSYM(sys_ni_syscall) // i386: vm86old + .long CSYM(sys_wait4) + .long CSYM(sys_swapoff) // 115 + .long CSYM(sys_sysinfo) + .long CSYM(sys_ipc) + .long CSYM(sys_fsync) + .long sys_sigreturn_wrapper + .long sys_clone_wrapper // 120 + .long CSYM(sys_setdomainname) + .long CSYM(sys_newuname) + .long CSYM(sys_ni_syscall) // i386: modify_ldt, m68k: cacheflush + .long CSYM(sys_adjtimex) + .long CSYM(sys_ni_syscall) // 125 - sys_mprotect + .long CSYM(sys_sigprocmask) + .long CSYM(sys_create_module) + .long CSYM(sys_init_module) + .long CSYM(sys_delete_module) + .long CSYM(sys_get_kernel_syms) // 130 + .long CSYM(sys_quotactl) + .long CSYM(sys_getpgid) + .long CSYM(sys_fchdir) + .long CSYM(sys_bdflush) + .long CSYM(sys_sysfs) // 135 + .long CSYM(sys_personality) + .long CSYM(sys_ni_syscall) // for afs_syscall + .long CSYM(sys_setfsuid) + .long CSYM(sys_setfsgid) + .long CSYM(sys_llseek) // 140 + .long CSYM(sys_getdents) + .long CSYM(sys_select) // for backward compat; remove someday + .long CSYM(sys_flock) + .long CSYM(sys_ni_syscall) // sys_msync + .long CSYM(sys_readv) // 145 + .long CSYM(sys_writev) + .long CSYM(sys_getsid) + .long CSYM(sys_fdatasync) + .long CSYM(sys_sysctl) + .long CSYM(sys_ni_syscall) // 150 - sys_mlock + .long CSYM(sys_ni_syscall) // sys_munlock + .long CSYM(sys_ni_syscall) // sys_mlockall + .long CSYM(sys_ni_syscall) // sys_munlockall + .long CSYM(sys_sched_setparam) + .long CSYM(sys_sched_getparam) // 155 + .long CSYM(sys_sched_setscheduler) + .long CSYM(sys_sched_getscheduler) + .long CSYM(sys_sched_yield) + .long CSYM(sys_sched_get_priority_max) + .long CSYM(sys_sched_get_priority_min) // 160 + .long CSYM(sys_sched_rr_get_interval) + .long CSYM(sys_nanosleep) + .long CSYM(sys_ni_syscall) // sys_mremap + .long CSYM(sys_setresuid) + .long CSYM(sys_getresuid) // 165 + .long CSYM(sys_ni_syscall) // for vm86 + .long CSYM(sys_query_module) + .long CSYM(sys_poll) + .long CSYM(sys_nfsservctl) + .long CSYM(sys_setresgid) // 170 + .long CSYM(sys_getresgid) + .long CSYM(sys_prctl) + .long sys_rt_sigreturn_wrapper + .long CSYM(sys_rt_sigaction) + .long CSYM(sys_rt_sigprocmask) // 175 + .long CSYM(sys_rt_sigpending) + .long CSYM(sys_rt_sigtimedwait) + .long CSYM(sys_rt_sigqueueinfo) + .long sys_rt_sigsuspend_wrapper + .long CSYM(sys_pread64) // 180 + .long CSYM(sys_pwrite64) + .long CSYM(sys_lchown) + .long CSYM(sys_getcwd) + .long CSYM(sys_capget) + .long CSYM(sys_capset) // 185 + .long CSYM(sys_sigaltstack) + .long CSYM(sys_sendfile) + .long CSYM(sys_ni_syscall) // streams1 + .long CSYM(sys_ni_syscall) // streams2 + .long sys_vfork_wrapper // 190 + .long CSYM(sys_ni_syscall) + .long CSYM(sys_mmap2) + .long CSYM(sys_truncate64) + .long CSYM(sys_ftruncate64) + .long CSYM(sys_stat64) // 195 + .long CSYM(sys_lstat64) + .long CSYM(sys_fstat64) + .long CSYM(sys_fcntl64) + .long CSYM(sys_getdents64) + .long CSYM(sys_pivot_root) // 200 + .long CSYM(sys_gettid) + .long CSYM(sys_tkill) + .long CSYM(sys_ni_syscall) // sys_mincore + .long CSYM(sys_ni_syscall) // sys_madvise + + .space (NR_syscalls-205)*4 diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/v850/kernel/fpga85e2c.c linux.2.5.45-ac1/arch/v850/kernel/fpga85e2c.c --- linux.2.5.45/arch/v850/kernel/fpga85e2c.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/v850/kernel/fpga85e2c.c 2002-11-01 15:20:35.000000000 +0000 @@ -0,0 +1,167 @@ +/* + * arch/v850/kernel/fpga85e2c.h -- Machine-dependent defs for + * FPGA implementation of V850E2/NA85E2C + * + * Copyright (C) 2002 NEC Corporation + * Copyright (C) 2002 Miles Bader + * + * 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. + * + * Written by Miles Bader + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "mach.h" + +extern void memcons_setup (void); + + +#define REG_DUMP_ADDR 0x220000 + + +extern struct irqaction reg_snap_action; /* fwd decl */ + + +void __init mach_early_init (void) +{ + int i; + const u32 *src; + register u32 *dst asm ("ep"); + extern int panic_timeout; + extern u32 _intv_end, _intv_load_start; + + /* Set bus sizes: CS0 32-bit, CS1 16-bit, CS7 8-bit, + everything else 32-bit. */ + BSC = 0x2AA6; + for (i = 2; i <= 6; i++) + CSDEV(i) = 0; /* 32 bit */ + + /* Ensure that the simulator halts on a panic, instead of going + into an infinite loop inside the panic function. */ + panic_timeout = -1; + + /* Move the interrupt vectors into their real location. Note that + any relocations there are relative to the real location, so we + don't have to fix anything up. We use a loop instead of calling + memcpy to keep this a leaf function (to avoid a function + prologue being generated). */ + dst = 0x10; /* &_intv_start + 0x10. */ + src = &_intv_load_start; + do { + u32 t0 = src[0], t1 = src[1], t2 = src[2], t3 = src[3]; + u32 t4 = src[4], t5 = src[5], t6 = src[6], t7 = src[7]; + dst[0] = t0; dst[1] = t1; dst[2] = t2; dst[3] = t3; + dst[4] = t4; dst[5] = t5; dst[6] = t6; dst[7] = t7; + dst += 8; + src += 8; + } while (dst < &_intv_end); +} + +void __init mach_setup (char **cmdline) +{ + printk (KERN_INFO "CPU: NEC V850E2 (NA85E2C FPGA implementation)\n"); + + memcons_setup (); + + /* Setup up NMI0 to copy the registers to a known memory location. + The FGPA board has a button that produces NMI0 when pressed, so + this allows us to push the button, and then look at memory to see + what's in the registers (there's no other way to easily do so). + We have to use `setup_irq' instead of `request_irq' because it's + still too early to do memory allocation. */ + setup_irq (IRQ_NMI (0), ®_snap_action); +} + +void mach_get_physical_ram (unsigned long *ram_start, unsigned long *ram_len) +{ + *ram_start = ERAM_ADDR; + *ram_len = ERAM_SIZE; +} + +void __init mach_sched_init (struct irqaction *timer_action) +{ + /* Setup up the timer interrupt. The FPGA peripheral control + registers _only_ work with single-bit writes (set1/clr1)! */ + __clear_bit (RPU_GTMC_CE_BIT, &RPU_GTMC); + __clear_bit (RPU_GTMC_CLK_BIT, &RPU_GTMC); + __set_bit (RPU_GTMC_CE_BIT, &RPU_GTMC); + + /* We use the first RPU interrupt, which occurs every 8.192ms. */ + setup_irq (IRQ_RPU (0), timer_action); +} + + +void mach_gettimeofday (struct timespec *tv) +{ + tv->tv_sec = 0; + tv->tv_nsec = 0; +} + +void machine_halt (void) __attribute__ ((noreturn)); +void machine_halt (void) +{ + for (;;) { + DWC(0) = 0x7777; + DWC(1) = 0x7777; + ASC = 0xffff; + FLGREG(0) = 1; /* Halt immediately. */ + asm ("di; halt; nop; nop; nop; nop; nop"); + } +} + +void machine_restart (char *__unused) +{ + machine_halt (); +} + +void machine_power_off (void) +{ + machine_halt (); +} + + +/* Interrupts */ + +struct nb85e_intc_irq_init irq_inits[] = { + { "IRQ", 0, NUM_MACH_IRQS, 1, 7 }, + { "RPU", IRQ_RPU(0), IRQ_RPU_NUM, 1, 6 }, + { 0 } +}; +#define NUM_IRQ_INITS ((sizeof irq_inits / sizeof irq_inits[0]) - 1) + +struct hw_interrupt_type hw_itypes[NUM_IRQ_INITS]; + +/* Initialize interrupts. */ +void __init mach_init_irqs (void) +{ + nb85e_intc_init_irq_types (irq_inits, hw_itypes); +} + + +/* An interrupt handler that copies the registers to a known memory location, + for debugging purposes. */ + +static void make_reg_snap (int irq, void *dummy, struct pt_regs *regs) +{ + (*(unsigned *)REG_DUMP_ADDR)++; + (*(struct pt_regs *)(REG_DUMP_ADDR + sizeof (unsigned))) = *regs; +} + +static int reg_snap_dev_id; +static struct irqaction reg_snap_action = { + make_reg_snap, 0, 0, "reg_snap", ®_snap_dev_id, 0 +}; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/v850/kernel/gbus_int.c linux.2.5.45-ac1/arch/v850/kernel/gbus_int.c --- linux.2.5.45/arch/v850/kernel/gbus_int.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/v850/kernel/gbus_int.c 2002-11-01 15:20:35.000000000 +0000 @@ -0,0 +1,267 @@ +/* + * arch/v850/kernel/gbus_int.c -- Midas labs GBUS interrupt support + * + * Copyright (C) 2001,02 NEC Corporation + * Copyright (C) 2001,02 Miles Bader + * + * 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. + * + * Written by Miles Bader + */ + +#include +#include +#include +#include /* For some unfathomable reason, + request_irq/free_irq are declared here. */ + +#include +#include + + +/* The number of shared GINT interrupts. */ +#define NUM_GINTS 4 + +/* For each GINT interrupt, how many GBUS interrupts are using it. */ +static unsigned gint_num_active_irqs[NUM_GINTS] = { 0 }; + +/* A table of GINTn interrupts we actually use. */ +struct used_gint { + unsigned gint; + unsigned priority; +} used_gint[] = { + { 1, GBUS_INT_PRIORITY_HIGH }, + { 3, GBUS_INT_PRIORITY_LOW } +}; +#define NUM_USED_GINTS (sizeof used_gint / sizeof used_gint[0]) + +/* A table of which GINT is used by each GBUS interrupts (they are + assigned based on priority). */ +static unsigned char gbus_int_gint[IRQ_GBUS_INT_NUM]; + + +/* Interrupt enabling/disabling. */ + +/* Enable interrupt handling for interrupt IRQ. */ +void gbus_int_enable_irq (unsigned irq) +{ + unsigned gint = gbus_int_gint[irq - GBUS_INT_BASE_IRQ]; + GBUS_INT_ENABLE (GBUS_INT_IRQ_WORD(irq), gint) + |= GBUS_INT_IRQ_MASK (irq); +} + +/* Disable interrupt handling for interrupt IRQ. Note that any + interrupts received while disabled will be delivered once the + interrupt is enabled again, unless they are explicitly cleared using + `gbus_int_clear_pending_irq'. */ +void gbus_int_disable_irq (unsigned irq) +{ + unsigned gint = gbus_int_gint[irq - GBUS_INT_BASE_IRQ]; + GBUS_INT_ENABLE (GBUS_INT_IRQ_WORD(irq), gint) + &= ~GBUS_INT_IRQ_MASK (irq); +} + +/* Return true if interrupt handling for interrupt IRQ is enabled. */ +int gbus_int_irq_enabled (unsigned irq) +{ + unsigned gint = gbus_int_gint[irq - GBUS_INT_BASE_IRQ]; + return (GBUS_INT_ENABLE (GBUS_INT_IRQ_WORD(irq), gint) + & GBUS_INT_IRQ_MASK(irq)); +} + +/* Disable all GBUS irqs. */ +int gbus_int_disable_irqs () +{ + unsigned w, n; + for (w = 0; w < GBUS_INT_NUM_WORDS; w++) + for (n = 0; n < IRQ_GINT_NUM; n++) + GBUS_INT_ENABLE (w, n) = 0; +} + +/* Clear any pending interrupts for IRQ. */ +void gbus_int_clear_pending_irq (unsigned irq) +{ + GBUS_INT_CLEAR (GBUS_INT_IRQ_WORD(irq)) = GBUS_INT_IRQ_MASK (irq); +} + +/* Return true if interrupt IRQ is pending (but disabled). */ +int gbus_int_irq_pending (unsigned irq) +{ + return (GBUS_INT_STATUS (GBUS_INT_IRQ_WORD(irq)) + & GBUS_INT_IRQ_MASK(irq)); +} + + +/* Delegating interrupts. */ + +/* Handle a shared GINT interrupt by passing to the appropriate GBUS + interrupt handler. */ +static void gbus_int_handle_irq (int irq, void *dev_id, struct pt_regs *regs) +{ + unsigned w; + unsigned gint = irq - IRQ_GINT (0); + + for (w = 0; w < GBUS_INT_NUM_WORDS; w++) { + unsigned status = GBUS_INT_STATUS (w); + unsigned enable = GBUS_INT_ENABLE (w, gint); + + /* Only pay attention to enabled interrupts. */ + status &= enable; + if (status) { + unsigned base_irq + = IRQ_GBUS_INT (w * GBUS_INT_BITS_PER_WORD); + irq = base_irq; + do { + /* There's an active interrupt in word + W, find out which one, and call its + handler. */ + + while (! (status & 0x1)) { + irq++; + status >>= 1; + } + status &= ~0x1; + + /* Recursively call handle_irq to handle it. */ + handle_irq (irq, regs); + } while (status); + } + } + + /* Toggle the `all enable' bit back and forth, which should cause + another edge transition if there are any other interrupts + still pending, and so result in another CPU interrupt. */ + GBUS_INT_ENABLE (0, gint) &= ~0x1; + GBUS_INT_ENABLE (0, gint) |= 0x1; +} + + +/* Initialize GBUS interrupt sources. */ + +static void irq_nop (unsigned irq) { } + +static unsigned gbus_int_startup_irq (unsigned irq) +{ + unsigned gint = gbus_int_gint[irq - GBUS_INT_BASE_IRQ]; + + if (gint_num_active_irqs[gint] == 0) { + /* First enable the CPU interrupt. */ + int rval = + request_irq (IRQ_GINT(gint), gbus_int_handle_irq, + SA_INTERRUPT, + "gbus_int_handler", + &gint_num_active_irqs[gint]); + if (rval != 0) + return rval; + } + + gint_num_active_irqs[gint]++; + + gbus_int_clear_pending_irq (irq); + gbus_int_enable_irq (irq); + + return 0; +} + +static void gbus_int_shutdown_irq (unsigned irq) +{ + unsigned gint = gbus_int_gint[irq - GBUS_INT_BASE_IRQ]; + + gbus_int_disable_irq (irq); + + if (--gint_num_active_irqs[gint] == 0) + /* Disable the CPU interrupt. */ + free_irq (IRQ_GINT(gint), &gint_num_active_irqs[gint]); +} + +/* Initialize HW_IRQ_TYPES for INTC-controlled irqs described in array + INITS (which is terminated by an entry with the name field == 0). */ +void __init gbus_int_init_irq_types (struct gbus_int_irq_init *inits, + struct hw_interrupt_type *hw_irq_types) +{ + struct gbus_int_irq_init *init; + for (init = inits; init->name; init++) { + int i; + struct hw_interrupt_type *hwit = hw_irq_types++; + + hwit->typename = init->name; + + hwit->startup = gbus_int_startup_irq; + hwit->shutdown = gbus_int_shutdown_irq; + hwit->enable = gbus_int_enable_irq; + hwit->disable = gbus_int_disable_irq; + hwit->ack = irq_nop; + hwit->end = irq_nop; + + /* Initialize kernel IRQ infrastructure for this interrupt. */ + init_irq_handlers(init->base, init->num, init->interval, hwit); + + /* Set the interrupt priorities. */ + for (i = 0; i < init->num; i++) { + int j; + for (j = 0; j < NUM_USED_GINTS; j++) + if (used_gint[j].priority > init->priority) + break; + /* Wherever we stopped looking is one past the + GINT we want. */ + gbus_int_gint[init->base + i * init->interval + - GBUS_INT_BASE_IRQ] + = used_gint[j > 0 ? j - 1 : 0].gint; + } + } +} + + +/* Initialize IRQS. */ + +/* Chip interrupts (GINTn) shared among GBUS interrupts. */ +static struct hw_interrupt_type gint_hw_itypes[NUM_USED_GINTS]; + + +/* GBUS interrupts themselves. */ + +__init struct gbus_int_irq_init gbus_irq_inits[] = { + /* First set defaults. */ + { "GBUS_INT", IRQ_GBUS_INT(0), IRQ_GBUS_INT_NUM, 1, 6}, + { 0 } +}; +#define NUM_GBUS_IRQ_INITS \ + ((sizeof gbus_irq_inits / sizeof gbus_irq_inits[0]) - 1) + +static struct hw_interrupt_type gbus_hw_itypes[NUM_GBUS_IRQ_INITS]; + + +/* Initialize GBUS interrupts. */ +void __init gbus_int_init_irqs (void) +{ + int i; + + /* First initialize the shared gint interrupts. */ + for (i = 0; i < NUM_USED_GINTS; i++) { + unsigned gint = used_gint[i].gint; + struct nb85e_intc_irq_init gint_irq_init[2]; + + /* We initialize one GINT interrupt at a time. */ + gint_irq_init[0].name = "GINT"; + gint_irq_init[0].base = IRQ_GINT (gint); + gint_irq_init[0].num = 1; + gint_irq_init[0].interval = 1; + gint_irq_init[0].priority = used_gint[i].priority; + + gint_irq_init[1].name = 0; /* Terminate the vector. */ + + nb85e_intc_init_irq_types (gint_irq_init, gint_hw_itypes); + } + + /* Then the GBUS interrupts. */ + gbus_int_disable_irqs (); + gbus_int_init_irq_types (gbus_irq_inits, gbus_hw_itypes); + /* Turn on the `all enable' bits, which are ANDed with + individual interrupt enable bits; we only want to bother with + the latter. They are the first bit in the first word of each + interrupt-enable area. */ + for (i = 0; i < NUM_USED_GINTS; i++) + GBUS_INT_ENABLE (0, used_gint[i].gint) = 0x1; +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/v850/kernel/head.S linux.2.5.45-ac1/arch/v850/kernel/head.S --- linux.2.5.45/arch/v850/kernel/head.S 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/v850/kernel/head.S 2002-11-01 15:20:35.000000000 +0000 @@ -0,0 +1,121 @@ +/* + * arch/v850/kernel/head.S -- Lowest-level startup code + * + * Copyright (C) 2001,02 NEC Corporation + * Copyright (C) 2001,02 Miles Bader + * + * 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. + * + * Written by Miles Bader + */ + +#include +#include +#include +#include +#include + + +/* Make a slightly more convenient alias for C_SYMBOL_NAME. */ +#define CSYM C_SYMBOL_NAME + + + .text + + // Define `mach_early_init' as a weak symbol + .global CSYM(mach_early_init) + .weak CSYM(mach_early_init) + +C_ENTRY(start): + // Make sure interrupts are turned off, just in case + di + +#ifdef CONFIG_RESET_GUARD + // See if we got here via an unexpected reset + ld.w RESET_GUARD, r19 // Check current value of reset guard + mov RESET_GUARD_ACTIVE, r20 + cmp r19, r20 + bne 1f // Guard was not active + + // If we get here, the reset guard was active. Load up some + // interesting values as arguments, and jump to the handler. + st.w r0, RESET_GUARD // Allow further resets to succeed + mov lp, r6 // Arg 0: return address + ld.b KM, r7 // Arg 1: kernel mode + mov sp, r9 // Arg 3: stack pointer + ld.w KSP, r19 // maybe switch to kernel stack + cmp r7, r0 // see if already in kernel mode + cmov z, r19, sp, sp // and switch to kernel stack if not + GET_CURRENT_TASK(r8) // Arg 2: task pointer + jr CSYM(unexpected_reset) + +1: st.w r20, RESET_GUARD // Turn on reset guard +#endif /* CONFIG_RESET_GUARD */ + + // Setup a temporary stack for doing pre-initialization function calls. + // + // We can't use the initial kernel stack, because (1) it may be + // located in memory we're not allowed to touch, and (2) since + // it's in the data segment, calling memcpy to initialize that + // area from ROM will overwrite memcpy's return address. + mov hilo(CSYM(_init_stack_end) - 4), sp + + // See if there's a platform-specific early-initialization routine + // defined; it's a weak symbol, so it will have an address of zero if + // there's not. + mov hilo(CSYM(mach_early_init)), r6 + cmp r6, r0 + bz 3f + + // There is one, so call it. If this function is written in C, it + // should be very careful -- the stack pointer is valid, but very + // little else is (e.g., bss is not zeroed yet, and initialized data + // hasn't been). + jarl 2f, lp // first figure out return address +2: add 3f - ., lp + jmp [r6] // do call +3: + +#ifdef CONFIG_ROM_KERNEL + // Copy the data area from ROM to RAM + mov hilo(CSYM(_rom_copy_dst_start)), r6 + mov hilo(CSYM(_rom_copy_src_start)), r7 + mov hilo(CSYM(_rom_copy_dst_end)), r8 + sub r6, r8 + jarl CSYM(memcpy), lp +#endif + + // Load the initial thread's stack, and current task pointer (in r16) + mov hilo(CSYM(init_thread_union)), r19 + movea THREAD_SIZE, r19, sp + ld.w TI_TASK[r19], CURRENT_TASK + +#ifdef CONFIG_TIME_BOOTUP + /* This stuff must come after mach_early_init, because interrupts may + not work until after its been called. */ + jarl CSYM(highres_timer_reset), lp + jarl CSYM(highres_timer_start), lp +#endif + + // Kernel stack pointer save location + st.w sp, KSP + + // Assert that we're in `kernel mode' + mov 1, r19 + st.w r19, KM + +#ifdef CONFIG_ZERO_BSS + // Zero bss area, since we can't rely upon any loader to do so + mov hilo(CSYM(_sbss)), r6 + mov r0, r7 + mov hilo(CSYM(_ebss)), r8 + sub r6, r8 + jarl CSYM(memset), lp +#endif + + // Start Linux kernel. + mov hilo(CSYM(machine_halt)), lp + jr CSYM(start_kernel) +END(start) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/v850/kernel/highres_timer.c linux.2.5.45-ac1/arch/v850/kernel/highres_timer.c --- linux.2.5.45/arch/v850/kernel/highres_timer.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/v850/kernel/highres_timer.c 2002-11-01 15:20:35.000000000 +0000 @@ -0,0 +1,132 @@ +/* + * arch/v850/kernel/highres_timer.c -- High resolution timing routines + * + * Copyright (C) 2001,02 NEC Corporation + * Copyright (C) 2001,02 Miles Bader + * + * 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. + * + * Written by Miles Bader + */ + +#include +#include +#include + +#define HIGHRES_TIMER_USEC_SHIFT 12 + +/* Pre-calculated constant used for converting ticks to real time + units. We initialize it to prevent it being put into BSS. */ +static u32 highres_timer_usec_prescale = 1; + +void highres_timer_slow_tick_irq (void) __attribute__ ((noreturn)); +void highres_timer_slow_tick_irq (void) +{ + /* This is an interrupt handler, so it must be very careful to + not to trash any registers. At this point, the stack-pointer + (r3) has been saved in the chip ram location ENTRY_SP by the + interrupt vector, so we can use it as a scratch register; we + must also restore it before returning. */ + asm ("ld.w %0[r0], sp;" + "add 1, sp;" + "st.w sp, %0[r0];" + "ld.w %1[r0], sp;" /* restore pre-irq stack-pointer */ + "reti" + :: + "i" (HIGHRES_TIMER_SLOW_TICKS_ADDR), + "i" (ENTRY_SP_ADDR) + : "memory"); +} + +void highres_timer_reset (void) +{ + NB85E_TIMER_D_TMD (HIGHRES_TIMER_TIMER_D_UNIT) = 0; + HIGHRES_TIMER_SLOW_TICKS = 0; +} + +void highres_timer_start (void) +{ + u32 fast_tick_rate; + + /* Start hardware timer. */ + nb85e_timer_d_configure (HIGHRES_TIMER_TIMER_D_UNIT, + HIGHRES_TIMER_SLOW_TICK_RATE); + + fast_tick_rate = + (NB85E_TIMER_D_BASE_FREQ + >> NB85E_TIMER_D_DIVLOG2 (HIGHRES_TIMER_TIMER_D_UNIT)); + + /* The obvious way of calculating microseconds from fast ticks + is to do: + + usec = fast_ticks * 10^6 / fast_tick_rate + + However, divisions are much slower than multiplications, and + the above calculation can overflow, so we do this instead: + + usec = fast_ticks * (10^6 * 2^12 / fast_tick_rate) / 2^12 + + since we can pre-calculate (10^6 * (2^12 / fast_tick_rate)) + and use a shift for dividing by 2^12, this avoids division, + and is almost as accurate (it differs by about 2 microseconds + at the extreme value of the fast-tick counter's ranger). */ + highres_timer_usec_prescale = ((1000000 << HIGHRES_TIMER_USEC_SHIFT) + / fast_tick_rate); + + /* Enable the interrupt (which is hardwired to this use), and + give it the highest priority. */ + NB85E_INTC_IC (IRQ_INTCMD (HIGHRES_TIMER_TIMER_D_UNIT)) = 0; +} + +void highres_timer_stop (void) +{ + /* Stop the timer. */ + NB85E_TIMER_D_TMCD (HIGHRES_TIMER_TIMER_D_UNIT) = + NB85E_TIMER_D_TMCD_CAE; + /* Disable its interrupt, just in case. */ + nb85e_intc_disable_irq (IRQ_INTCMD (HIGHRES_TIMER_TIMER_D_UNIT)); +} + +inline void highres_timer_read_ticks (u32 *slow_ticks, u32 *fast_ticks) +{ + int flags; + u32 fast_ticks_1, fast_ticks_2, _slow_ticks; + + local_irq_save (flags); + fast_ticks_1 = NB85E_TIMER_D_TMD (HIGHRES_TIMER_TIMER_D_UNIT); + _slow_ticks = HIGHRES_TIMER_SLOW_TICKS; + fast_ticks_2 = NB85E_TIMER_D_TMD (HIGHRES_TIMER_TIMER_D_UNIT); + local_irq_restore (flags); + + if (fast_ticks_2 < fast_ticks_1) + _slow_ticks++; + + *slow_ticks = _slow_ticks; + *fast_ticks = fast_ticks_2; +} + +inline void highres_timer_ticks_to_timeval (u32 slow_ticks, u32 fast_ticks, + struct timeval *tv) +{ + unsigned long sec, sec_rem, usec; + + usec = ((fast_ticks * highres_timer_usec_prescale) + >> HIGHRES_TIMER_USEC_SHIFT); + + sec = slow_ticks / HIGHRES_TIMER_SLOW_TICK_RATE; + sec_rem = slow_ticks % HIGHRES_TIMER_SLOW_TICK_RATE; + + usec += sec_rem * (1000000 / HIGHRES_TIMER_SLOW_TICK_RATE); + + tv->tv_sec = sec; + tv->tv_usec = usec; +} + +void highres_timer_read (struct timeval *tv) +{ + u32 fast_ticks, slow_ticks; + highres_timer_read_ticks (&slow_ticks, &fast_ticks); + highres_timer_ticks_to_timeval (slow_ticks, fast_ticks, tv); +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/v850/kernel/init_task.c linux.2.5.45-ac1/arch/v850/kernel/init_task.c --- linux.2.5.45/arch/v850/kernel/init_task.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/v850/kernel/init_task.c 2002-11-01 15:20:35.000000000 +0000 @@ -0,0 +1,42 @@ +/* + * arch/v850/kernel/init_task.c -- Initial task/thread structures + * + * Copyright (C) 2002 NEC Corporation + * Copyright (C) 2002 Miles Bader + * + * 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 + +static struct fs_struct init_fs = INIT_FS; +static struct files_struct init_files = INIT_FILES; +static struct signal_struct init_signals = INIT_SIGNALS (init_signals); +struct mm_struct init_mm = INIT_MM (init_mm); + +/* + * Initial task structure. + * + * All other task structs will be allocated on slabs in fork.c + */ +struct task_struct init_task = INIT_TASK (init_task); + +/* + * Initial thread structure. + * + * We need to make sure that this is 8192-byte aligned due to the + * way process stacks are handled. This is done by having a special + * "init_task" linker map entry. + */ +union thread_union init_thread_union + __attribute__((__section__(".data.init_task"))) = + { INIT_THREAD_INFO(init_task) }; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/v850/kernel/intv.S linux.2.5.45-ac1/arch/v850/kernel/intv.S --- linux.2.5.45/arch/v850/kernel/intv.S 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/v850/kernel/intv.S 2002-11-01 15:20:35.000000000 +0000 @@ -0,0 +1,90 @@ +/* + * arch/v850/kernel/intv.S -- Interrupt vectors + * + * Copyright (C) 2001,02 NEC Corporation + * Copyright (C) 2001,02 Miles Bader + * + * 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. + * + * Written by Miles Bader + */ + +#include +#include +#include +#include + +#ifdef CONFIG_V850E_MA1_HIGHRES_TIMER +#include +#endif + +/* Jump to an interrupt/trap handler. These handlers (defined in entry.S) + expect the stack-pointer to be saved in ENTRY_SP, so we use sp to do an + indirect jump (which avoids problems when the handler is more than a signed + 22-bit offset away). */ +#define JUMP_TO_HANDLER(name, sp_save_loc) \ + st.w sp, sp_save_loc; \ + mov hilo(name), sp; \ + jmp [sp] + + + /* Reset vector. */ + .section .intv.reset, "ax" + .org 0x0 + mov hilo(C_SYMBOL_NAME(start)), r1; + jmp [r1] + + + /* Generic interrupt vectors. */ + .section .intv.common, "ax" + .balign 0x10 + JUMP_TO_HANDLER (nmi, NMI_ENTRY_SP) // NMI0 + .balign 0x10 + JUMP_TO_HANDLER (nmi, NMI_ENTRY_SP) // NMI1 + .balign 0x10 + JUMP_TO_HANDLER (nmi, NMI_ENTRY_SP) // NMI2 + + .balign 0x10 + JUMP_TO_HANDLER (trap, ENTRY_SP) // TRAP0n + .balign 0x10 + JUMP_TO_HANDLER (trap, ENTRY_SP) // TRAP1n + + .balign 0x10 + JUMP_TO_HANDLER (illegal_instruction, ENTRY_SP) // illegal insn trap + + .balign 0x10 + JUMP_TO_HANDLER (dbtrap, ENTRY_SP) // DBTRAP insn + + + /* Hardware interrupt vectors. */ + .section .intv.mach, "ax" + .org 0x0 + +#if defined (CONFIG_V850E_MA1_HIGHRES_TIMER) && defined (IRQ_INTCMD) + + /* Interrupts before the highres timer interrupt. */ + .rept IRQ_INTCMD (HIGHRES_TIMER_TIMER_D_UNIT) + .balign 0x10 + JUMP_TO_HANDLER (irq, ENTRY_SP) + .endr + + /* The highres timer interrupt. */ + .balign 0x10 + JUMP_TO_HANDLER (C_SYMBOL_NAME (highres_timer_slow_tick_irq), ENTRY_SP) + + /* Interrupts after the highres timer interrupt. */ + .rept NUM_CPU_IRQS - IRQ_INTCMD (HIGHRES_TIMER_TIMER_D_UNIT) - 1 + .balign 0x10 + JUMP_TO_HANDLER (irq, ENTRY_SP) + .endr + +#else /* No highres timer */ + + .rept NUM_CPU_IRQS + .balign 0x10 + JUMP_TO_HANDLER (irq, ENTRY_SP) + .endr + +#endif /* Highres timer */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/v850/kernel/irq.c linux.2.5.45-ac1/arch/v850/kernel/irq.c --- linux.2.5.45/arch/v850/kernel/irq.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/v850/kernel/irq.c 2002-11-01 15:20:35.000000000 +0000 @@ -0,0 +1,716 @@ +/* + * arch/v850/kernel/irq.c -- High-level interrupt handling + * + * Copyright (C) 2001,02 NEC Corporation + * Copyright (C) 2001,02 Miles Bader + * Copyright (C) 1994-2000 Ralf Baechle + * Copyright (C) 1992 Linus Torvalds + * + * 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. + * + * This file was was derived from the mips version, arch/mips/kernel/irq.c + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* + * Controller mappings for all interrupt sources: + */ +irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = + { [0 ... NR_IRQS-1] = { 0, &no_irq_type, NULL, 0, SPIN_LOCK_UNLOCKED}}; + +/* + * Special irq handlers. + */ + +void no_action(int cpl, void *dev_id, struct pt_regs *regs) { } + +/* + * Generic no controller code + */ + +static void enable_none(unsigned int irq) { } +static unsigned int startup_none(unsigned int irq) { return 0; } +static void disable_none(unsigned int irq) { } +static void ack_none(unsigned int irq) +{ + /* + * 'what should we do if we get a hw irq event on an illegal vector'. + * each architecture has to answer this themselves, it doesnt deserve + * a generic callback i think. + */ + printk("received IRQ %d with unknown interrupt type\n", irq); +} + +/* startup is the same as "enable", shutdown is same as "disable" */ +#define shutdown_none disable_none +#define end_none enable_none + +struct hw_interrupt_type no_irq_type = { + "none", + startup_none, + shutdown_none, + enable_none, + disable_none, + ack_none, + end_none +}; + +volatile unsigned long irq_err_count, spurious_count; + +/* + * Generic, controller-independent functions: + */ + +int show_interrupts(struct seq_file *p, void *v) +{ + int i; + struct irqaction * action; + + seq_puts(p, " "); + for (i=0; i < 1 /*smp_num_cpus*/; i++) + seq_printf(p, "CPU%d ", i); + seq_putc(p, '\n'); + + for (i = 0 ; i < NR_IRQS ; i++) { + int j, count, num; + const char *type_name = irq_desc[i].handler->typename; + + action = irq_desc[i].action; + if (!action) + continue; + + count = 0; + num = -1; + for (j = 0; j < NR_IRQS; j++) + if (irq_desc[j].handler->typename == type_name) { + if (i == j) + num = count; + count++; + } + + seq_printf(p, "%3d: ",i); + seq_printf(p, "%10u ", kstat_irqs(i)); + if (count > 1) { + int prec = (num >= 100 ? 3 : num >= 10 ? 2 : 1); + seq_printf(p, " %*s%d", 14 - prec, type_name, num); + } else + seq_printf(p, " %14s", type_name); + seq_printf(p, " %s", action->name); + + for (action=action->next; action; action = action->next) + seq_printf(p, ", %s", action->name); + seq_putc(p, '\n'); + } + seq_printf(p, "ERR: %10lu\n", irq_err_count); + return 0; +} + +/* + * This should really return information about whether + * we should do bottom half handling etc. Right now we + * end up _always_ checking the bottom half, which is a + * waste of time and is not what some drivers would + * prefer. + */ +int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqaction * action) +{ + int status = 1; /* Force the "do bottom halves" bit */ + + if (!(action->flags & SA_INTERRUPT)) + local_irq_enable(); + + do { + status |= action->flags; + action->handler(irq, action->dev_id, regs); + action = action->next; + } while (action); + if (status & SA_SAMPLE_RANDOM) + add_interrupt_randomness(irq); + local_irq_disable(); + + return status; +} + +/* + * Generic enable/disable code: this just calls + * down into the PIC-specific version for the actual + * hardware disable after having gotten the irq + * controller lock. + */ + +/** + * disable_irq_nosync - disable an irq without waiting + * @irq: Interrupt to disable + * + * Disable the selected interrupt line. Disables of an interrupt + * stack. Unlike disable_irq(), this function does not ensure existing + * instances of the IRQ handler have completed before returning. + * + * This function may be called from IRQ context. + */ + +void inline disable_irq_nosync(unsigned int irq) +{ + irq_desc_t *desc = irq_desc + irq; + unsigned long flags; + + spin_lock_irqsave(&desc->lock, flags); + if (!desc->depth++) { + desc->status |= IRQ_DISABLED; + desc->handler->disable(irq); + } + spin_unlock_irqrestore(&desc->lock, flags); +} + +/** + * disable_irq - disable an irq and wait for completion + * @irq: Interrupt to disable + * + * Disable the selected interrupt line. Disables of an interrupt + * stack. That is for two disables you need two enables. This + * function waits for any pending IRQ handlers for this interrupt + * to complete before returning. If you use this function while + * holding a resource the IRQ handler may need you will deadlock. + * + * This function may be called - with care - from IRQ context. + */ + +void disable_irq(unsigned int irq) +{ + disable_irq_nosync(irq); + synchronize_irq(irq); +} + +/** + * enable_irq - enable interrupt handling on an irq + * @irq: Interrupt to enable + * + * Re-enables the processing of interrupts on this IRQ line + * providing no disable_irq calls are now in effect. + * + * This function may be called from IRQ context. + */ + +void enable_irq(unsigned int irq) +{ + irq_desc_t *desc = irq_desc + irq; + unsigned long flags; + + spin_lock_irqsave(&desc->lock, flags); + switch (desc->depth) { + case 1: { + unsigned int status = desc->status & ~IRQ_DISABLED; + desc->status = status; + if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) { + desc->status = status | IRQ_REPLAY; + hw_resend_irq(desc->handler,irq); + } + desc->handler->enable(irq); + /* fall-through */ + } + default: + desc->depth--; + break; + case 0: + printk("enable_irq(%u) unbalanced from %p\n", irq, + __builtin_return_address(0)); + } + spin_unlock_irqrestore(&desc->lock, flags); +} + +/* Handle interrupt IRQ. REGS are the registers at the time of ther + interrupt. */ +unsigned int handle_irq (int irq, struct pt_regs *regs) +{ + /* + * We ack quickly, we don't want the irq controller + * thinking we're snobs just because some other CPU has + * disabled global interrupts (we have already done the + * INT_ACK cycles, it's too late to try to pretend to the + * controller that we aren't taking the interrupt). + * + * 0 return value means that this irq is already being + * handled by some other CPU. (or is disabled) + */ + int cpu = smp_processor_id(); + irq_desc_t *desc = irq_desc + irq; + struct irqaction * action; + unsigned int status; + + irq_enter(); + kstat.irqs[cpu][irq]++; + spin_lock(&desc->lock); + desc->handler->ack(irq); + /* + REPLAY is when Linux resends an IRQ that was dropped earlier + WAITING is used by probe to mark irqs that are being tested + */ + status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING); + status |= IRQ_PENDING; /* we _want_ to handle it */ + + /* + * If the IRQ is disabled for whatever reason, we cannot + * use the action we have. + */ + action = NULL; + if (likely(!(status & (IRQ_DISABLED | IRQ_INPROGRESS)))) { + action = desc->action; + status &= ~IRQ_PENDING; /* we commit to handling */ + status |= IRQ_INPROGRESS; /* we are handling it */ + } + desc->status = status; + + /* + * If there is no IRQ handler or it was disabled, exit early. + Since we set PENDING, if another processor is handling + a different instance of this same irq, the other processor + will take care of it. + */ + if (unlikely(!action)) + goto out; + + /* + * Edge triggered interrupts need to remember + * pending events. + * This applies to any hw interrupts that allow a second + * instance of the same irq to arrive while we are in handle_irq + * or in the handler. But the code here only handles the _second_ + * instance of the irq, not the third or fourth. So it is mostly + * useful for irq hardware that does not mask cleanly in an + * SMP environment. + */ + for (;;) { + spin_unlock(&desc->lock); + handle_IRQ_event(irq, regs, action); + spin_lock(&desc->lock); + + if (likely(!(desc->status & IRQ_PENDING))) + break; + desc->status &= ~IRQ_PENDING; + } + desc->status &= ~IRQ_INPROGRESS; + +out: + /* + * The ->end() handler has to deal with interrupts which got + * disabled while the handler was running. + */ + desc->handler->end(irq); + spin_unlock(&desc->lock); + + irq_exit(); + + return 1; +} + +/** + * request_irq - allocate an interrupt line + * @irq: Interrupt line to allocate + * @handler: Function to be called when the IRQ occurs + * @irqflags: Interrupt type flags + * @devname: An ascii name for the claiming device + * @dev_id: A cookie passed back to the handler function + * + * This call allocates interrupt resources and enables the + * interrupt line and IRQ handling. From the point this + * call is made your handler function may be invoked. Since + * your handler function must clear any interrupt the board + * raises, you must take care both to initialise your hardware + * and to set up the interrupt handler in the right order. + * + * Dev_id must be globally unique. Normally the address of the + * device data structure is used as the cookie. Since the handler + * receives this value it makes sense to use it. + * + * If your interrupt is shared you must pass a non NULL dev_id + * as this is required when freeing the interrupt. + * + * Flags: + * + * SA_SHIRQ Interrupt is shared + * + * SA_INTERRUPT Disable local interrupts while processing + * + * SA_SAMPLE_RANDOM The interrupt can be used for entropy + * + */ + +int request_irq(unsigned int irq, + void (*handler)(int, void *, struct pt_regs *), + unsigned long irqflags, + const char * devname, + void *dev_id) +{ + int retval; + struct irqaction * action; + +#if 1 + /* + * Sanity-check: shared interrupts should REALLY pass in + * a real dev-ID, otherwise we'll have trouble later trying + * to figure out which interrupt is which (messes up the + * interrupt freeing logic etc). + */ + if (irqflags & SA_SHIRQ) { + if (!dev_id) + printk("Bad boy: %s (at 0x%x) called us without a dev_id!\n", devname, (&irq)[-1]); + } +#endif + + if (irq >= NR_IRQS) + return -EINVAL; + if (!handler) + return -EINVAL; + + action = (struct irqaction *) + kmalloc(sizeof(struct irqaction), GFP_KERNEL); + if (!action) + return -ENOMEM; + + action->handler = handler; + action->flags = irqflags; + action->mask = 0; + action->name = devname; + action->next = NULL; + action->dev_id = dev_id; + + retval = setup_irq(irq, action); + if (retval) + kfree(action); + return retval; +} + +/** + * free_irq - free an interrupt + * @irq: Interrupt line to free + * @dev_id: Device identity to free + * + * Remove an interrupt handler. The handler is removed and if the + * interrupt line is no longer in use by any driver it is disabled. + * On a shared IRQ the caller must ensure the interrupt is disabled + * on the card it drives before calling this function. The function + * does not return until any executing interrupts for this IRQ + * have completed. + * + * This function may be called from interrupt context. + * + * Bugs: Attempting to free an irq in a handler for the same irq hangs + * the machine. + */ + +void free_irq(unsigned int irq, void *dev_id) +{ + irq_desc_t *desc; + struct irqaction **p; + unsigned long flags; + + if (irq >= NR_IRQS) + return; + + desc = irq_desc + irq; + spin_lock_irqsave(&desc->lock,flags); + p = &desc->action; + for (;;) { + struct irqaction * action = *p; + if (action) { + struct irqaction **pp = p; + p = &action->next; + if (action->dev_id != dev_id) + continue; + + /* Found it - now remove it from the list of entries */ + *pp = action->next; + if (!desc->action) { + desc->status |= IRQ_DISABLED; + desc->handler->shutdown(irq); + } + spin_unlock_irqrestore(&desc->lock,flags); + + synchronize_irq(irq); + kfree(action); + return; + } + printk("Trying to free free IRQ%d\n",irq); + spin_unlock_irqrestore(&desc->lock,flags); + return; + } +} + +/* + * IRQ autodetection code.. + * + * This depends on the fact that any interrupt that + * comes in on to an unassigned handler will get stuck + * with "IRQ_WAITING" cleared and the interrupt + * disabled. + */ + +static DECLARE_MUTEX(probe_sem); + +/** + * probe_irq_on - begin an interrupt autodetect + * + * Commence probing for an interrupt. The interrupts are scanned + * and a mask of potential interrupt lines is returned. + * + */ + +unsigned long probe_irq_on(void) +{ + unsigned int i; + irq_desc_t *desc; + unsigned long val; + unsigned long delay; + + down(&probe_sem); + /* + * something may have generated an irq long ago and we want to + * flush such a longstanding irq before considering it as spurious. + */ + for (i = NR_IRQS-1; i > 0; i--) { + desc = irq_desc + i; + + spin_lock_irq(&desc->lock); + if (!irq_desc[i].action) + irq_desc[i].handler->startup(i); + spin_unlock_irq(&desc->lock); + } + + /* Wait for longstanding interrupts to trigger. */ + for (delay = jiffies + HZ/50; time_after(delay, jiffies); ) + /* about 20ms delay */ barrier(); + + /* + * enable any unassigned irqs + * (we must startup again here because if a longstanding irq + * happened in the previous stage, it may have masked itself) + */ + for (i = NR_IRQS-1; i > 0; i--) { + desc = irq_desc + i; + + spin_lock_irq(&desc->lock); + if (!desc->action) { + desc->status |= IRQ_AUTODETECT | IRQ_WAITING; + if (desc->handler->startup(i)) + desc->status |= IRQ_PENDING; + } + spin_unlock_irq(&desc->lock); + } + + /* + * Wait for spurious interrupts to trigger + */ + for (delay = jiffies + HZ/10; time_after(delay, jiffies); ) + /* about 100ms delay */ barrier(); + + /* + * Now filter out any obviously spurious interrupts + */ + val = 0; + for (i = 0; i < NR_IRQS; i++) { + irq_desc_t *desc = irq_desc + i; + unsigned int status; + + spin_lock_irq(&desc->lock); + status = desc->status; + + if (status & IRQ_AUTODETECT) { + /* It triggered already - consider it spurious. */ + if (!(status & IRQ_WAITING)) { + desc->status = status & ~IRQ_AUTODETECT; + desc->handler->shutdown(i); + } else + if (i < 32) + val |= 1 << i; + } + spin_unlock_irq(&desc->lock); + } + + return val; +} + +/* + * Return a mask of triggered interrupts (this + * can handle only legacy ISA interrupts). + */ + +/** + * probe_irq_mask - scan a bitmap of interrupt lines + * @val: mask of interrupts to consider + * + * Scan the ISA bus interrupt lines and return a bitmap of + * active interrupts. The interrupt probe logic state is then + * returned to its previous value. + * + * Note: we need to scan all the irq's even though we will + * only return ISA irq numbers - just so that we reset them + * all to a known state. + */ +unsigned int probe_irq_mask(unsigned long val) +{ + int i; + unsigned int mask; + + mask = 0; + for (i = 0; i < NR_IRQS; i++) { + irq_desc_t *desc = irq_desc + i; + unsigned int status; + + spin_lock_irq(&desc->lock); + status = desc->status; + + if (status & IRQ_AUTODETECT) { + if (i < 16 && !(status & IRQ_WAITING)) + mask |= 1 << i; + + desc->status = status & ~IRQ_AUTODETECT; + desc->handler->shutdown(i); + } + spin_unlock_irq(&desc->lock); + } + up(&probe_sem); + + return mask & val; +} + +/* + * Return the one interrupt that triggered (this can + * handle any interrupt source). + */ + +/** + * probe_irq_off - end an interrupt autodetect + * @val: mask of potential interrupts (unused) + * + * Scans the unused interrupt lines and returns the line which + * appears to have triggered the interrupt. If no interrupt was + * found then zero is returned. If more than one interrupt is + * found then minus the first candidate is returned to indicate + * their is doubt. + * + * The interrupt probe logic state is returned to its previous + * value. + * + * BUGS: When used in a module (which arguably shouldnt happen) + * nothing prevents two IRQ probe callers from overlapping. The + * results of this are non-optimal. + */ + +int probe_irq_off(unsigned long val) +{ + int i, irq_found, nr_irqs; + + nr_irqs = 0; + irq_found = 0; + for (i = 0; i < NR_IRQS; i++) { + irq_desc_t *desc = irq_desc + i; + unsigned int status; + + spin_lock_irq(&desc->lock); + status = desc->status; + + if (status & IRQ_AUTODETECT) { + if (!(status & IRQ_WAITING)) { + if (!nr_irqs) + irq_found = i; + nr_irqs++; + } + desc->status = status & ~IRQ_AUTODETECT; + desc->handler->shutdown(i); + } + spin_unlock_irq(&desc->lock); + } + up(&probe_sem); + + if (nr_irqs > 1) + irq_found = -irq_found; + return irq_found; +} + +/* this was setup_x86_irq but it seems pretty generic */ +int setup_irq(unsigned int irq, struct irqaction * new) +{ + int shared = 0; + unsigned long flags; + struct irqaction *old, **p; + irq_desc_t *desc = irq_desc + irq; + + /* + * Some drivers like serial.c use request_irq() heavily, + * so we have to be careful not to interfere with a + * running system. + */ + if (new->flags & SA_SAMPLE_RANDOM) { + /* + * This function might sleep, we want to call it first, + * outside of the atomic block. + * Yes, this might clear the entropy pool if the wrong + * driver is attempted to be loaded, without actually + * installing a new handler, but is this really a problem, + * only the sysadmin is able to do this. + */ + rand_initialize_irq(irq); + } + + /* + * The following block of code has to be executed atomically + */ + spin_lock_irqsave(&desc->lock,flags); + p = &desc->action; + if ((old = *p) != NULL) { + /* Can't share interrupts unless both agree to */ + if (!(old->flags & new->flags & SA_SHIRQ)) { + spin_unlock_irqrestore(&desc->lock,flags); + return -EBUSY; + } + + /* add new interrupt at end of irq queue */ + do { + p = &old->next; + old = *p; + } while (old); + shared = 1; + } + + *p = new; + + if (!shared) { + desc->depth = 0; + desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING | IRQ_INPROGRESS); + desc->handler->startup(irq); + } + spin_unlock_irqrestore(&desc->lock,flags); + + /* register_irq_proc(irq); */ + return 0; +} + +/* Initialize irq handling for IRQs. + BASE_IRQ, BASE_IRQ+INTERVAL, ..., BASE_IRQ+NUM*INTERVAL + to IRQ_TYPE. An IRQ_TYPE of 0 means to use a generic interrupt type. */ +void __init +init_irq_handlers (int base_irq, int num, int interval, + struct hw_interrupt_type *irq_type) +{ + while (num-- > 0) { + irq_desc[base_irq].status = IRQ_DISABLED; + irq_desc[base_irq].action = NULL; + irq_desc[base_irq].depth = 1; + irq_desc[base_irq].handler = irq_type; + base_irq += interval; + } +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/v850/kernel/ma.c linux.2.5.45-ac1/arch/v850/kernel/ma.c --- linux.2.5.45/arch/v850/kernel/ma.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/v850/kernel/ma.c 2002-11-01 15:20:35.000000000 +0000 @@ -0,0 +1,70 @@ +/* + * arch/v850/kernel/ma.c -- V850E/MA series of cpu chips + * + * Copyright (C) 2001,02 NEC Corporation + * Copyright (C) 2001,02 Miles Bader + * + * 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. + * + * Written by Miles Bader + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "mach.h" + +void __init mach_sched_init (struct irqaction *timer_action) +{ + /* Start hardware timer. */ + nb85e_timer_d_configure (0, HZ); + /* Install timer interrupt handler. */ + setup_irq (IRQ_INTCMD(0), timer_action); +} + +static struct nb85e_intc_irq_init irq_inits[] = { + { "IRQ", 0, NUM_MACH_IRQS, 1, 7 }, + { "CMD", IRQ_INTCMD(0), IRQ_INTCMD_NUM, 1, 5 }, + { "DMA", IRQ_INTDMA(0), IRQ_INTDMA_NUM, 1, 2 }, + { "CSI", IRQ_INTCSI(0), IRQ_INTCSI_NUM, 4, 4 }, + { "SER", IRQ_INTSER(0), IRQ_INTSER_NUM, 4, 3 }, + { "SR", IRQ_INTSR(0), IRQ_INTSR_NUM, 4, 4 }, + { "ST", IRQ_INTST(0), IRQ_INTST_NUM, 4, 5 }, + { 0 } +}; +#define NUM_IRQ_INITS ((sizeof irq_inits / sizeof irq_inits[0]) - 1) + +static struct hw_interrupt_type hw_itypes[NUM_IRQ_INITS]; + +/* Initialize MA chip interrupts. */ +void __init ma_init_irqs (void) +{ + nb85e_intc_init_irq_types (irq_inits, hw_itypes); +} + +/* Called before configuring an on-chip UART. */ +void ma_uart_pre_configure (unsigned chan, unsigned cflags, unsigned baud) +{ + /* We only know about the first two UART channels (though + specific chips may have more). */ + if (chan < 2) { + unsigned bits = 0x3 << (chan * 3); + /* Specify that the relevent pins on the chip should do + serial I/O, not direct I/O. */ + MA_PORT4_PMC |= bits; + /* Specify that we're using the UART, not the CSI device. */ + MA_PORT4_PFC |= bits; + } +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/v850/kernel/mach.c linux.2.5.45-ac1/arch/v850/kernel/mach.c --- linux.2.5.45/arch/v850/kernel/mach.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/v850/kernel/mach.c 2002-11-01 15:20:35.000000000 +0000 @@ -0,0 +1,17 @@ +/* + * arch/v850/kernel/mach.c -- Defaults for some things defined by "mach.h" + * + * Copyright (C) 2001 NEC Corporation + * Copyright (C) 2001 Miles Bader + * + * 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. + * + * Written by Miles Bader + */ + +#include "mach.h" + +/* Called with each timer tick, if non-zero. */ +void (*mach_tick)(void) = 0; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/v850/kernel/mach.h linux.2.5.45-ac1/arch/v850/kernel/mach.h --- linux.2.5.45/arch/v850/kernel/mach.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/v850/kernel/mach.h 2002-11-01 15:20:35.000000000 +0000 @@ -0,0 +1,56 @@ +/* + * arch/v850/kernel/mach.h -- Machine-dependent functions used by v850 port + * + * Copyright (C) 2001,02 NEC Corporation + * Copyright (C) 2001,02 Miles Bader + * + * 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. + * + * Written by Miles Bader + */ + +#ifndef __V850_MACH_H__ +#define __V850_MACH_H__ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +void mach_setup (char **cmdline); +void mach_gettimeofday (struct timespec *tv); +void mach_sched_init (struct irqaction *timer_action); +void mach_get_physical_ram (unsigned long *ram_start, unsigned long *ram_len); +void mach_init_irqs (void); + +/* If defined, is called very early in the kernel initialization. The + stack pointer is valid, but very little has been initialized (e.g., + bss is not zeroed yet) when this is called, so care must taken. */ +void mach_early_init (void); + +/* If defined, called after the bootmem allocator has been initialized, + to allow the platform-dependent code to reserve any areas of RAM that + the kernel shouldn't touch. */ +void mach_reserve_bootmem (void) __attribute__ ((__weak__)); + +/* Called with each timer tick, if non-zero. */ +extern void (*mach_tick) (void); + +/* The following establishes aliases for various mach_ functions to the + name by which the rest of the kernal calls them. These statements + should only have an effect in the file that defines the actual functions. */ +#define MACH_ALIAS(to, from) \ + asm (".global " macrology_stringify (C_SYMBOL_NAME (to)) ";" \ + macrology_stringify (C_SYMBOL_NAME (to)) \ + " = " macrology_stringify (C_SYMBOL_NAME (from))) +/* e.g.: MACH_ALIAS (kernel_name, arch_spec_name); */ + +#endif /* __V850_MACH_H__ */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/v850/kernel/Makefile linux.2.5.45-ac1/arch/v850/kernel/Makefile --- linux.2.5.45/arch/v850/kernel/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/v850/kernel/Makefile 2002-11-01 15:20:35.000000000 +0000 @@ -0,0 +1,38 @@ +# +# arch/v850/kernel/Makefile +# +# Copyright (C) 2001,02 NEC Corporation +# Copyright (C) 2001,02 Miles Bader +# +# 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. +# + +EXTRA_TARGETS := head.o init_task.o + +obj-y += intv.o entry.o process.o syscalls.o time.o semaphore.o setup.o \ + signal.o irq.o mach.o ptrace.o bug.o +export-objs += v850_ksyms.o rte_mb_a_pci.o + +obj-$(CONFIG_MODULES) += v850_ksyms.o +# chip-specific code +obj-$(CONFIG_V850E_MA1) += ma.o nb85e_utils.o nb85e_timer_d.o +obj-$(CONFIG_V850E_NB85E) += nb85e_intc.o +obj-$(CONFIG_V850E2_ANNA) += anna.o nb85e_intc.o nb85e_utils.o nb85e_timer_d.o +# platform-specific code +obj-$(CONFIG_V850E_SIM) += sim.o simcons.o +obj-$(CONFIG_V850E2_SIM85E2C) += sim85e2c.o nb85e_intc.o memcons.o +obj-$(CONFIG_V850E2_FPGA85E2C) += fpga85e2c.o nb85e_intc.o memcons.o +obj-$(CONFIG_RTE_CB) += rte_cb.o rte_cb_leds.o +obj-$(CONFIG_RTE_CB_MA1) += rte_ma1_cb.o +obj-$(CONFIG_RTE_CB_NB85E) += rte_nb85e_cb.o +obj-$(CONFIG_RTE_CB_MULTI) += rte_cb_multi.o +obj-$(CONFIG_RTE_MB_A_PCI) += rte_mb_a_pci.o +obj-$(CONFIG_RTE_GBUS_INT) += gbus_int.o +# feature-specific code +obj-$(CONFIG_V850E_MA1_HIGHRES_TIMER) += highres_timer.o +obj-$(CONFIG_PROC_FS) += procfs.o + + +include $(TOPDIR)/Rules.make diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/v850/kernel/memcons.c linux.2.5.45-ac1/arch/v850/kernel/memcons.c --- linux.2.5.45/arch/v850/kernel/memcons.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/v850/kernel/memcons.c 2002-11-01 15:20:35.000000000 +0000 @@ -0,0 +1,134 @@ +/* + * arch/v850/kernel/memcons.c -- Console I/O to a memory buffer + * + * Copyright (C) 2001,02 NEC Corporation + * Copyright (C) 2001,02 Miles Bader + * + * 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. + * + * Written by Miles Bader + */ + +#include +#include +#include +#include +#include + +/* If this device is enabled, the linker map should define start and + end points for its buffer. */ +extern char memcons_output[], memcons_output_end; + +/* Current offset into the buffer. */ +static unsigned long memcons_offs = 0; + +/* Spinlock protecting memcons_offs. */ +static spinlock_t memcons_lock = SPIN_LOCK_UNLOCKED; + + +static size_t write (const char *buf, size_t len) +{ + int flags; + char *point; + + spin_lock_irqsave (memcons_lock, flags); + + point = memcons_output + memcons_offs; + if (point + len >= &memcons_output_end) { + len = &memcons_output_end - point; + memcons_offs = 0; + } else + memcons_offs += len; + + spin_unlock_irqrestore (memcons_lock, flags); + + memcpy (point, buf, len); + + return len; +} + + +/* Low-level console. */ + +static void memcons_write (struct console *co, const char *buf, unsigned len) +{ + while (len > 0) + len -= write (buf, len); +} + +static kdev_t memcons_device (struct console *co) +{ + return MKDEV (TTY_MAJOR, 64 + co->index); +} + +static struct console memcons = +{ + name: "memcons", + write: memcons_write, + device: memcons_device, + flags: CON_PRINTBUFFER, + index: -1, +}; + +void memcons_setup (void) +{ + register_console (&memcons); + printk (KERN_INFO "Console: static memory buffer (memcons)\n"); +} + +/* Higher level TTY interface. */ + +static struct tty_struct *tty_table[1] = { 0 }; +static struct termios *tty_termios[1] = { 0 }; +static struct termios *tty_termios_locked[1] = { 0 }; +static struct tty_driver tty_driver = { 0 }; +static int tty_ref_count = 0; + +int memcons_tty_open (struct tty_struct *tty, struct file *filp) +{ + return 0; +} + +int memcons_tty_write (struct tty_struct *tty, int from_user, + const unsigned char *buf, int len) +{ + return write (buf, len); +} + +int memcons_tty_write_room (struct tty_struct *tty) +{ + return &memcons_output_end - (memcons_output + memcons_offs); +} + +int memcons_tty_chars_in_buffer (struct tty_struct *tty) +{ + /* We have no buffer. */ + return 0; +} + +int __init memcons_tty_init (void) +{ + tty_driver.name = "memcons"; + tty_driver.major = TTY_MAJOR; + tty_driver.minor_start = 64; + tty_driver.num = 1; + tty_driver.type = TTY_DRIVER_TYPE_SYSCONS; + + tty_driver.refcount = &tty_ref_count; + + tty_driver.table = tty_table; + tty_driver.termios = tty_termios; + tty_driver.termios_locked = tty_termios_locked; + + tty_driver.init_termios = tty_std_termios; + + tty_driver.open = memcons_tty_open; + tty_driver.write = memcons_tty_write; + tty_driver.write_room = memcons_tty_write_room; + tty_driver.chars_in_buffer = memcons_tty_chars_in_buffer; + + tty_register_driver (&tty_driver); +} +__initcall (memcons_tty_init); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/v850/kernel/nb85e_intc.c linux.2.5.45-ac1/arch/v850/kernel/nb85e_intc.c --- linux.2.5.45/arch/v850/kernel/nb85e_intc.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/v850/kernel/nb85e_intc.c 2002-11-01 15:20:35.000000000 +0000 @@ -0,0 +1,68 @@ +/* + * arch/v850/kernel/nb85e_intc.c -- NB85E cpu core interrupt controller (INTC) + * + * Copyright (C) 2001,02 NEC Corporation + * Copyright (C) 2001,02 Miles Bader + * + * 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. + * + * Written by Miles Bader + */ + +#include +#include +#include + +#include + +static void irq_nop (unsigned irq) { } + +static unsigned nb85e_intc_irq_startup (unsigned irq) +{ + nb85e_intc_clear_pending_irq (irq); + nb85e_intc_enable_irq (irq); + return 0; +} + +/* Initialize HW_IRQ_TYPES for INTC-controlled irqs described in array + INITS (which is terminated by an entry with the name field == 0). */ +void __init nb85e_intc_init_irq_types (struct nb85e_intc_irq_init *inits, + struct hw_interrupt_type *hw_irq_types) +{ + struct nb85e_intc_irq_init *init; + for (init = inits; init->name; init++) { + int i; + struct hw_interrupt_type *hwit = hw_irq_types++; + + hwit->typename = init->name; + + hwit->startup = nb85e_intc_irq_startup; + hwit->shutdown = nb85e_intc_disable_irq; + hwit->enable = nb85e_intc_enable_irq; + hwit->disable = nb85e_intc_disable_irq; + hwit->ack = irq_nop; + hwit->end = irq_nop; + + /* Initialize kernel IRQ infrastructure for this interrupt. */ + init_irq_handlers(init->base, init->num, init->interval, hwit); + + /* Set the interrupt priorities. */ + for (i = 0; i < init->num; i++) { + unsigned irq = init->base + i * init->interval; + + /* If the interrupt is currently enabled (all + interrupts are initially disabled), then + assume whoever enabled it has set things up + properly, and avoid messing with it. */ + if (! nb85e_intc_irq_enabled (irq)) + /* This write also (1) disables the + interrupt, and (2) clears any pending + interrupts. */ + NB85E_INTC_IC (irq) + = (NB85E_INTC_IC_PR (init->priority) + | NB85E_INTC_IC_MK); + } + } +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/v850/kernel/nb85e_timer_d.c linux.2.5.45-ac1/arch/v850/kernel/nb85e_timer_d.c --- linux.2.5.45/arch/v850/kernel/nb85e_timer_d.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/v850/kernel/nb85e_timer_d.c 2002-11-01 15:20:35.000000000 +0000 @@ -0,0 +1,54 @@ +/* + * include/asm-v850/nb85e_timer_d.c -- `Timer D' component often used + * with the NB85E cpu core + * + * Copyright (C) 2001,02 NEC Corporation + * Copyright (C) 2001,02 Miles Bader + * + * 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. + * + * Written by Miles Bader + */ + +#include + +#include +#include + +/* Start interval timer TIMER (0-3). The timer will issue the + corresponding INTCMD interrupt RATE times per second. + This function does not enable the interrupt. */ +void nb85e_timer_d_configure (unsigned timer, unsigned rate) +{ + unsigned divlog2, count; + + /* Calculate params for timer. */ + if (! calc_counter_params ( + NB85E_TIMER_D_BASE_FREQ, rate, + NB85E_TIMER_D_TMCD_CS_MIN, NB85E_TIMER_D_TMCD_CS_MAX, 16, + &divlog2, &count)) + printk (KERN_WARNING + "Cannot find interval timer %d setting suitable" + " for rate of %dHz.\n" + "Using rate of %dHz instead.\n", + timer, rate, + (NB85E_TIMER_D_BASE_FREQ >> divlog2) >> 16); + + /* Do the actual hardware timer initialization: */ + + /* Enable timer. */ + NB85E_TIMER_D_TMCD(timer) = NB85E_TIMER_D_TMCD_CAE; + /* Set clock divider. */ + NB85E_TIMER_D_TMCD(timer) + = NB85E_TIMER_D_TMCD_CAE + | NB85E_TIMER_D_TMCD_CS(divlog2); + /* Set timer compare register. */ + NB85E_TIMER_D_CMD(timer) = count; + /* Start counting. */ + NB85E_TIMER_D_TMCD(timer) + = NB85E_TIMER_D_TMCD_CAE + | NB85E_TIMER_D_TMCD_CS(divlog2) + | NB85E_TIMER_D_TMCD_CE; +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/v850/kernel/nb85e_utils.c linux.2.5.45-ac1/arch/v850/kernel/nb85e_utils.c --- linux.2.5.45/arch/v850/kernel/nb85e_utils.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/v850/kernel/nb85e_utils.c 2002-11-01 15:20:35.000000000 +0000 @@ -0,0 +1,65 @@ +/* + * include/asm-v850/nb85e_utils.h -- Utility functions associated with + * the NB85E cpu core + * + * Copyright (C) 2001 NEC Corporation + * Copyright (C) 2001 Miles Bader + * + * 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. + * + * Written by Miles Bader + */ + +/* Note: these functions are often associated with the N85E cpu core, + but not always, which is why they're not in `nb85e.c'. */ + +#include + +/* Calculate counter clock-divider and count values to attain the + desired frequency RATE from the base frequency BASE_FREQ. The + counter is expected to have a clock-divider, which can divide the + system cpu clock by a power of two value from MIN_DIVLOG2 to + MAX_DIV_LOG2, and a word-size of COUNTER_SIZE bits (the counter + counts up and resets whenever it's equal to the compare register, + generating an interrupt or whatever when it does so). The returned + values are: *DIVLOG2 -- log2 of the desired clock divider and *COUNT + -- the counter compare value to use. Returns true if it was possible + to find a reasonable value, otherwise false (and the other return + values will be set to be as good as possible). */ +int calc_counter_params (unsigned long base_freq, + unsigned long rate, + unsigned min_divlog2, unsigned max_divlog2, + unsigned counter_size, + unsigned *divlog2, unsigned *count) +{ + unsigned _divlog2; + int ok = 0; + + /* Find the lowest clock divider setting that can represent RATE. */ + for (_divlog2 = min_divlog2; _divlog2 <= max_divlog2; _divlog2++) { + /* Minimum interrupt rate possible using this divider. */ + int min_int_rate + = (base_freq >> _divlog2) >> counter_size; + + if (min_int_rate <= rate) { + /* This setting is the highest resolution + setting that's slow enough enough to attain + RATE interrupts per second, so use it. */ + ok = 1; + break; + } + } + + if (_divlog2 > max_divlog2) + /* Can't find correct setting. */ + _divlog2 = max_divlog2; + + if (divlog2) + *divlog2 = _divlog2; + if (count) + *count = ((base_freq >> _divlog2) + rate/2) / rate; + + return ok; +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/v850/kernel/process.c linux.2.5.45-ac1/arch/v850/kernel/process.c --- linux.2.5.45/arch/v850/kernel/process.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/v850/kernel/process.c 2002-11-01 15:20:35.000000000 +0000 @@ -0,0 +1,282 @@ +/* + * arch/v850/kernel/process.c -- Arch-dependent process handling + * + * Copyright (C) 2001,02 NEC Corporation + * Copyright (C) 2001,02 Miles Bader + * + * 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. + * + * Written by Miles Bader + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +extern void ret_from_fork (void); + + +/* The idle loop. */ +void default_idle (void) +{ + while (1) { + while (! need_resched ()) + asm ("halt; nop; nop; nop; nop; nop" ::: "cc"); + schedule (); + } +} + +void (*idle)(void) = default_idle; + +/* + * The idle thread. There's no useful work to be + * done, so just try to conserve power and have a + * low exit latency (ie sit in a loop waiting for + * somebody to say that they'd like to reschedule) + */ +void cpu_idle (void) +{ + /* endless idle loop with no priority at all */ + (*idle) (); +} + +struct spec_reg_name { + const char *name; + int gpr; +}; + +struct spec_reg_name spec_reg_names[] = { + { "sp", GPR_SP }, + { "gp", GPR_GP }, + { "tp", GPR_TP }, + { "ep", GPR_EP }, + { "lp", GPR_LP }, + { 0, 0 } +}; + +void show_regs (struct pt_regs *regs) +{ + int gpr_base, gpr_offs; + + printk (" pc 0x%08lx psw 0x%08lx kernel_mode %d\n", + regs->pc, regs->psw, regs->kernel_mode); + printk (" ctpc 0x%08lx ctpsw 0x%08lx ctbp 0x%08lx\n", + regs->ctpc, regs->ctpsw, regs->ctbp); + + for (gpr_base = 0; gpr_base < NUM_GPRS; gpr_base += 4) { + for (gpr_offs = 0; gpr_offs < 4; gpr_offs++) { + int gpr = gpr_base + gpr_offs; + long val = regs->gpr[gpr]; + struct spec_reg_name *srn; + + for (srn = spec_reg_names; srn->name; srn++) + if (srn->gpr == gpr) + break; + + if (srn->name) + printk ("%7s 0x%08lx", srn->name, val); + else + printk (" r%02d 0x%08lx", gpr, val); + } + + printk ("\n"); + } +} + +/* + * This is the mechanism for creating a new kernel thread. + * + * NOTE! Only a kernel-only process (ie the swapper or direct descendants who + * haven't done an "execve()") should use this: it will work within a system + * call from a "real" process, but the process memory space will not be free'd + * until both the parent and the child have exited. + */ +int kernel_thread (int (*fn)(void *), void *arg, unsigned long flags) +{ + register mm_segment_t fs = get_fs (); + register unsigned long syscall asm (SYSCALL_NUM); + register unsigned long arg0 asm (SYSCALL_ARG0); + register unsigned long ret asm (SYSCALL_RET); + + set_fs (KERNEL_DS); + + /* Clone this thread. */ + arg0 = flags | CLONE_VM; + syscall = __NR_clone; + asm volatile ("trap " SYSCALL_SHORT_TRAP + : "=r" (ret), "=r" (syscall) + : "1" (syscall), "r" (arg0) + : SYSCALL_SHORT_CLOBBERS); + + if (ret == 0) { + /* In child thread, call FN and exit. */ + arg0 = (*fn) (arg); + syscall = __NR_exit; + asm volatile ("trap " SYSCALL_SHORT_TRAP + : "=r" (ret), "=r" (syscall) + : "1" (syscall), "r" (arg0) + : SYSCALL_SHORT_CLOBBERS); + } + + /* In parent. */ + set_fs (fs); + + return ret; +} + +void flush_thread (void) +{ + set_fs (USER_DS); +} + +int copy_thread (int nr, unsigned long clone_flags, + unsigned long stack_start, unsigned long stack_size, + struct task_struct *p, struct pt_regs *regs) +{ + /* Start pushing stuff from the top of the child's kernel stack. */ + unsigned long ksp = (unsigned long)p->thread_info + THREAD_SIZE; + /* We push two `state save' stack fames (see entry.S) on the new + kernel stack: + 1) The innermost one is what switch_thread would have + pushed, and is used when we context switch to the child + thread for the first time. It's set up to return to + ret_from_fork in entry.S. + 2) The outermost one (nearest the top) is what a syscall + trap would have pushed, and is set up to return to the + same location as the parent thread, but with a return + value of 0. */ + struct pt_regs *child_switch_regs, *child_trap_regs; + + /* Trap frame. */ + ksp -= STATE_SAVE_SIZE; + child_trap_regs = (struct pt_regs *)(ksp + STATE_SAVE_PT_OFFSET); + /* Switch frame. */ + ksp -= STATE_SAVE_SIZE; + child_switch_regs = (struct pt_regs *)(ksp + STATE_SAVE_PT_OFFSET); + + /* First copy parent's register state to child. */ + *child_switch_regs = *regs; + *child_trap_regs = *regs; + + /* switch_thread returns to the restored value of the lp + register (r31), so we make that the place where we want to + jump when the child thread begins running. */ + child_switch_regs->gpr[GPR_LP] = (v850_reg_t)ret_from_fork; + + /* Thread state for the child (everything else is on the stack). */ + p->thread.ksp = ksp; + + return 0; +} + +/* + * fill in the user structure for a core dump.. + */ +void dump_thread (struct pt_regs *regs, struct user *dump) +{ +#if 0 /* Later. XXX */ + dump->magic = CMAGIC; + dump->start_code = 0; + dump->start_stack = regs->gpr[GPR_SP]; + dump->u_tsize = ((unsigned long) current->mm->end_code) >> PAGE_SHIFT; + dump->u_dsize = ((unsigned long) (current->mm->brk + + (PAGE_SIZE-1))) >> PAGE_SHIFT; + dump->u_dsize -= dump->u_tsize; + dump->u_ssize = 0; + + if (dump->start_stack < TASK_SIZE) + dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> PAGE_SHIFT; + + dump->u_ar0 = (struct user_regs_struct *)((int)&dump->regs - (int)dump); + dump->regs = *regs; + dump->u_fpvalid = 0; +#endif +} + +/* + * sys_execve() executes a new program. + */ +int sys_execve (char *name, char **argv, char **envp, struct pt_regs *regs) +{ + char *filename = getname (name); + int error = PTR_ERR (filename); + + if (! IS_ERR (filename)) { + error = do_execve (filename, argv, envp, regs); + putname (filename); + } + + return error; +} + +/* This is the common part of the various fork-like system calls (which + are in entry.S). */ +int fork_common (int flags, unsigned long new_sp, struct pt_regs *regs) +{ + struct task_struct *p = do_fork (flags, new_sp, regs, 0, 0); + return IS_ERR (p) ? PTR_ERR (p) : p->pid; +} + + +/* + * These bracket the sleeping functions.. + */ +extern void scheduling_functions_start_here (void); +extern void scheduling_functions_end_here (void); +#define first_sched ((unsigned long) scheduling_functions_start_here) +#define last_sched ((unsigned long) scheduling_functions_end_here) + +unsigned long get_wchan (struct task_struct *p) +{ +#if 0 /* Barf. Figure out the stack-layout later. XXX */ + unsigned long fp, pc; + int count = 0; + + if (!p || p == current || p->state == TASK_RUNNING) + return 0; + + pc = thread_saved_pc (&p->thread); + + /* This quite disgusting function walks up the stack, following + saved return address, until it something that's out of bounds + (as defined by `first_sched' and `last_sched'). It then + returns the last PC that was in-bounds. */ + do { + if (fp < stack_page + sizeof (struct task_struct) || + fp >= 8184+stack_page) + return 0; + pc = ((unsigned long *)fp)[1]; + /* FIXME: This depends on the order of these functions. */ + if (pc < first_sched || pc >= last_sched) + return pc; + fp = *(unsigned long *) fp; + } while (count++ < 16); +#endif + + return 0; +} + +void show_trace_task (struct task_struct *t) +{ + /* blarg XXX */ + printk ("show_trace_task: KSP = 0x%lx, USP = 0x%lx, UPC = 0x%lx\n", + t->thread.ksp, KSTK_ESP (t), KSTK_EIP (t)); +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/v850/kernel/procfs.c linux.2.5.45-ac1/arch/v850/kernel/procfs.c --- linux.2.5.45/arch/v850/kernel/procfs.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/v850/kernel/procfs.c 2002-11-01 15:20:35.000000000 +0000 @@ -0,0 +1,67 @@ +/* + * arch/v850/kernel/procfs.c -- Introspection functions for /proc filesystem + * + * Copyright (C) 2001,02 NEC Corporation + * Copyright (C) 2001,02 Miles Bader + * + * 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. + * + * Written by Miles Bader + */ + +#include "mach.h" + +static int cpuinfo_print (struct seq_file *m, void *v) +{ + extern unsigned long loops_per_jiffy; + + seq_printf (m, "CPU-Family: v850\nCPU-Arch: %s\n", CPU_ARCH); + +#ifdef CPU_MODEL_LONG + seq_printf (m, "CPU-Model: %s (%s)\n", CPU_MODEL, CPU_MODEL_LONG); +#else + seq_printf (m, "CPU-Model: %s\n", CPU_MODEL); +#endif + +#ifdef CPU_CLOCK_FREQ + seq_printf (m, "CPU-Clock: %ld (%ld MHz)\n", + (long)CPU_CLOCK_FREQ, + (long)CPU_CLOCK_FREQ / 1000000); +#endif + + seq_printf (m, "BogoMips: %lu.%02lu\n", + loops_per_jiffy/(500000/HZ), + (loops_per_jiffy/(5000/HZ)) % 100); + +#ifdef PLATFORM_LONG + seq_printf (m, "Platform: %s (%s)\n", PLATFORM, PLATFORM_LONG); +#elif defined (PLATFORM) + seq_printf (m, "Platform: %s\n", PLATFORM); +#endif + + return 0; +} + +static void *cpuinfo_start (struct seq_file *m, loff_t *pos) +{ + return *pos < NR_CPUS ? ((void *) 0x12345678) : NULL; +} + +static void *cpuinfo_next (struct seq_file *m, void *v, loff_t *pos) +{ + ++*pos; + return cpuinfo_start (m, pos); +} + +static void cpuinfo_stop (struct seq_file *m, void *v) +{ +} + +struct seq_operations cpuinfo_op = { + start: cpuinfo_start, + next: cpuinfo_next, + stop: cpuinfo_stop, + show: cpuinfo_print +}; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/v850/kernel/ptrace.c linux.2.5.45-ac1/arch/v850/kernel/ptrace.c --- linux.2.5.45/arch/v850/kernel/ptrace.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/v850/kernel/ptrace.c 2002-11-01 15:20:35.000000000 +0000 @@ -0,0 +1,202 @@ +/* + * arch/v850/kernel/ptrace.c -- `ptrace' system call + * + * Copyright (C) 2002 NEC Corporation + * Copyright (C) 2002 Miles Bader + * + * Derived from arch/mips/kernel/ptrace.c: + * + * Copyright (C) 1992 Ross Biro + * Copyright (C) Linus Torvalds + * Copyright (C) 1994, 95, 96, 97, 98, 2000 Ralf Baechle + * Copyright (C) 1996 David S. Miller + * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com + * Copyright (C) 1999 MIPS Technologies, Inc. + * + * 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 + +int sys_ptrace(long request, long pid, long addr, long data) +{ + struct task_struct *child; + int rval; + + lock_kernel(); + +#if 0 + printk("ptrace(r=%d,pid=%d,addr=%08lx,data=%08lx)\n", + (int) request, (int) pid, (unsigned long) addr, + (unsigned long) data); +#endif + + if (request == PTRACE_TRACEME) { + /* are we already being traced? */ + if (current->ptrace & PT_PTRACED) { + rval = -EPERM; + goto out; + } + /* set the ptrace bit in the process flags. */ + current->ptrace |= PT_PTRACED; + rval = 0; + goto out; + } + rval = -ESRCH; + read_lock(&tasklist_lock); + child = find_task_by_pid(pid); + if (child) + get_task_struct(child); + read_unlock(&tasklist_lock); + if (!child) + goto out; + + rval = -EPERM; + if (pid == 1) /* you may not mess with init */ + goto out; + + if (request == PTRACE_ATTACH) { + rval = ptrace_attach(child); + goto out_tsk; + } + rval = -ESRCH; + if (!(child->ptrace & PT_PTRACED)) + goto out_tsk; + if (child->state != TASK_STOPPED) { + if (request != PTRACE_KILL) + goto out_tsk; + } + if (child->parent != current) + goto out_tsk; + + switch (request) { + case PTRACE_PEEKTEXT: /* read word at location addr. */ + case PTRACE_PEEKDATA:{ + unsigned long tmp; + int copied; + + copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); + rval = -EIO; + if (copied != sizeof(tmp)) + break; + rval = put_user(tmp,(unsigned long *) data); + + goto out; + } + + /* Read the word at location addr in the USER area. */ + case PTRACE_PEEKUSR: + if (addr >= 0 && addr < PT_SIZE && (addr & 0x3) == 0) { + struct pt_regs *regs = task_regs (child); + unsigned long val = + *(unsigned long *)((char *)regs + addr); + rval = put_user (val, (unsigned long *)data); + } else { + rval = 0; + rval = -EIO; + } + goto out; + + case PTRACE_POKETEXT: /* write the word at location addr. */ + case PTRACE_POKEDATA: + rval = 0; + if (access_process_vm(child, addr, &data, sizeof(data), 1) + == sizeof(data)) + break; + rval = -EIO; + goto out; + + case PTRACE_POKEUSR: + if (addr >= 0 && addr < PT_SIZE && (addr & 0x3) == 0) { + struct pt_regs *regs = task_regs (child); + unsigned long *loc = + (unsigned long *)((char *)regs + addr); + *loc = data; + } else { + rval = 0; + rval = -EIO; + } + goto out; + + case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ + case PTRACE_CONT: /* rvaltart after signal. */ + rval = -EIO; + if ((unsigned long) data > _NSIG) + break; + if (request == PTRACE_SYSCALL) + set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); + else + clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); + child->exit_code = data; + wake_up_process(child); + rval = 0; + break; + + /* + * make the child exit. Best I can do is send it a sigkill. + * perhaps it should be put in the status that it wants to + * exit. + */ + case PTRACE_KILL: + rval = 0; + if (child->state == TASK_ZOMBIE) /* already dead */ + break; + child->exit_code = SIGKILL; + wake_up_process(child); + break; + + case PTRACE_DETACH: /* detach a process that was attached. */ + rval = ptrace_detach(child, data); + break; + + default: + rval = -EIO; + goto out; + } + +out_tsk: + put_task_struct(child); +out: + unlock_kernel(); + return rval; +} + +asmlinkage void syscall_trace(void) +{ + if (!test_thread_flag(TIF_SYSCALL_TRACE)) + return; + if (!(current->ptrace & PT_PTRACED)) + return; + /* The 0x80 provides a way for the tracing parent to distinguish + between a syscall stop and SIGTRAP delivery */ + current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) + ? 0x80 : 0); + current->state = TASK_STOPPED; + notify_parent(current, SIGCHLD); + schedule(); + /* + * this isn't the same as continuing with a signal, but it will do + * for normal use. strace only continues with a signal if the + * stopping signal is not SIGTRAP. -brl + */ + if (current->exit_code) { + send_sig(current->exit_code, current, 1); + current->exit_code = 0; + } +} + +void ptrace_disable (struct task_struct *child) +{ + /* nothing to do */ +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/v850/kernel/rte_cb.c linux.2.5.45-ac1/arch/v850/kernel/rte_cb.c --- linux.2.5.45/arch/v850/kernel/rte_cb.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/v850/kernel/rte_cb.c 2002-11-01 16:39:54.000000000 +0000 @@ -0,0 +1,234 @@ +/* + * include/asm-v850/rte_cb.c -- Midas lab RTE-CB series of evaluation boards + * + * Copyright (C) 2001,02 NEC Corporation + * Copyright (C) 2001,02 Miles Bader + * + * 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. + * + * Written by Miles Bader + */ + +#include +#include +#include +#include + +#include +#include + +#include "mach.h" + +static void led_tick (void); + +/* LED access routines. */ +extern unsigned read_leds (int pos, char *buf, int len); +extern unsigned write_leds (int pos, const char *buf, int len); + +#ifdef CONFIG_RTE_CB_MULTI +extern void multi_init (void); +#endif + + +#ifdef CONFIG_ROM_KERNEL +/* Initialization for kernel in ROM. */ +static inline rom_kernel_init (void) +{ + /* If the kernel is in ROM, we have to copy any initialized data + from ROM into RAM. */ + extern unsigned long _data_load_start, _sdata, _edata; + register unsigned long *src = &_data_load_start; + register unsigned long *dst = &_sdata, *end = &_edata; + + while (dst != end) + *dst++ = *src++; +} +#endif /* CONFIG_ROM_KERNEL */ + +void __init mach_early_init (void) +{ + nb85e_intc_disable_irqs (); + +#if defined (CONFIG_ROM_KERNEL) + rom_kernel_init (); +#elif defined (CONFIG_RTE_CB_MULTI) + multi_init (); +#endif +} + +void __init mach_setup (char **cmdline) +{ + printk (KERN_INFO + "CPU: %s\n" + "Platform: %s%s\n", + CPU_MODEL_LONG, + PLATFORM_LONG, +#ifdef CONFIG_ROM_KERNEL + "" +#elif defined (CONFIG_RTE_CB_MULTI) + " (with Multi ROM monitor)" +#else + " (with ROM monitor)" +#endif + ); + + /* Probe for Mother-A, and print a message if we find it. */ + *(volatile long *)MB_A_SRAM_ADDR = 0xDEADBEEF; + if (*(volatile long *)MB_A_SRAM_ADDR == 0xDEADBEEF) { + *(volatile long *)MB_A_SRAM_ADDR = 0x12345678; + if (*(volatile long *)MB_A_SRAM_ADDR == 0x12345678) + printk (KERN_INFO + " NEC SolutionGear/Midas lab" + " RTE-MOTHER-A motherboard\n"); + } + +#if defined (CONFIG_V850E_NB85E_UART_CONSOLE) && !defined (CONFIG_TIME_BOOTUP) + nb85e_uart_cons_init (0); +#endif + + mach_tick = led_tick; +} + +#ifdef CONFIG_TIME_BOOTUP +void initial_boot_done (void) +{ +#ifdef CONFIG_V850E_NB85E_UART_CONSOLE + nb85e_uart_cons_init (0); +#endif +} +#endif + +void machine_restart (char *__unused) +{ +#ifdef CONFIG_RESET_GUARD + disable_reset_guard (); +#endif + asm ("jmp r0"); /* Jump to the reset vector. */ +} + +/* This says `HALt.' in LEDese. */ +static unsigned char halt_leds_msg[] = { 0x76, 0x77, 0x38, 0xF8 }; + +void machine_halt (void) +{ +#ifdef CONFIG_RESET_GUARD + disable_reset_guard (); +#endif + + /* Ignore all interrupts. */ + local_irq_disable (); + + /* Write a little message. */ + write_leds (0, halt_leds_msg, sizeof halt_leds_msg); + + /* Really halt. */ + for (;;) + asm ("halt; nop; nop; nop; nop; nop"); +} + +void machine_power_off (void) +{ + machine_halt (); +} + + +/* Animated LED display for timer tick. */ + +#define TICK_UPD_FREQ 6 +static int tick_frames[][10] = { + { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, -1 }, + { 0x63, 0x5c, -1 }, + { 0x5c, 0x00, -1 }, + { 0x63, 0x00, -1 }, + { -1 } +}; + +static void led_tick () +{ + static unsigned counter = 0; + + if (++counter == (HZ / TICK_UPD_FREQ)) { + /* Which frame we're currently displaying for each digit. */ + static unsigned frame_nums[LED_NUM_DIGITS] = { 0 }; + /* Display image. */ + static unsigned char image[LED_NUM_DIGITS] = { 0 }; + unsigned char prev_image[LED_NUM_DIGITS]; + int write_to_leds = 1; /* true if we should actually display */ + int digit; + + /* We check to see if the physical LEDs contains what we last + wrote to them; if not, we suppress display (this is so that + users can write to the LEDs, and not have their output + overwritten). As a special case, we start writing again if + all the LEDs are blank, or our display image is all zeros + (indicating that this is the initial update, when the actual + LEDs might contain random data). */ + read_leds (0, prev_image, LED_NUM_DIGITS); + for (digit = 0; digit < LED_NUM_DIGITS; digit++) + if (image[digit] != prev_image[digit] + && image[digit] && prev_image[digit]) + { + write_to_leds = 0; + break; + } + + /* Update display image. */ + for (digit = 0; + digit < LED_NUM_DIGITS && tick_frames[digit][0] >= 0; + digit++) + { + int frame = tick_frames[digit][frame_nums[digit]]; + if (frame < 0) { + image[digit] = tick_frames[digit][0]; + frame_nums[digit] = 1; + } else { + image[digit] = frame; + frame_nums[digit]++; + break; + } + } + + if (write_to_leds) + /* Write the display image to the physical LEDs. */ + write_leds (0, image, LED_NUM_DIGITS); + + counter = 0; + } +} + + +/* Mother-A interrupts. */ + +#ifdef CONFIG_RTE_GBUS_INT + +#define L GBUS_INT_PRIORITY_LOW +#define M GBUS_INT_PRIORITY_MEDIUM +#define H GBUS_INT_PRIORITY_HIGH + +static struct gbus_int_irq_init gbus_irq_inits[] = { +#ifdef CONFIG_RTE_MB_A_PCI + { "MB_A_LAN", IRQ_MB_A_LAN, 1, 1, L }, + { "MB_A_PCI1", IRQ_MB_A_PCI1(0), IRQ_MB_A_PCI1_NUM, 1, L }, + { "MB_A_PCI2", IRQ_MB_A_PCI2(0), IRQ_MB_A_PCI2_NUM, 1, L }, + { "MB_A_EXT", IRQ_MB_A_EXT(0), IRQ_MB_A_EXT_NUM, 1, L }, + { "MB_A_USB_OC",IRQ_MB_A_USB_OC(0), IRQ_MB_A_USB_OC_NUM, 1, L }, + { "MB_A_PCMCIA_OC",IRQ_MB_A_PCMCIA_OC, 1, 1, L }, +#endif + { 0 } +}; +#define NUM_GBUS_IRQ_INITS \ + ((sizeof gbus_irq_inits / sizeof gbus_irq_inits[0]) - 1) + +static struct hw_interrupt_type gbus_hw_itypes[NUM_GBUS_IRQ_INITS]; + +#endif /* CONFIG_RTE_GBUS_INT */ + +void __init rte_cb_init_irqs (void) +{ +#ifdef CONFIG_RTE_GBUS_INT + gbus_int_init_irqs (); + gbus_int_init_irq_types (gbus_irq_inits, gbus_hw_itypes); +#endif /* CONFIG_RTE_GBUS_INT */ +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/v850/kernel/rte_cb_leds.c linux.2.5.45-ac1/arch/v850/kernel/rte_cb_leds.c --- linux.2.5.45/arch/v850/kernel/rte_cb_leds.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/v850/kernel/rte_cb_leds.c 2002-11-01 15:20:35.000000000 +0000 @@ -0,0 +1,135 @@ +/* + * include/asm-v850/rte_cb_leds.c -- Midas lab RTE-CB board LED device support + * + * Copyright (C) 2002 NEC Corporation + * Copyright (C) 2002 Miles Bader + * + * 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. + * + * Written by Miles Bader + */ + +#include +#include +#include +#include + +#include + +#define LEDS_MINOR 169 /* Minor device number, using misc major. */ + +/* The actual LED hardware is write-only, so we hold the contents here too. */ +static unsigned char leds_image[LED_NUM_DIGITS] = { 0 }; + +/* Spinlock protecting the above leds. */ +static spinlock_t leds_lock = SPIN_LOCK_UNLOCKED; + +/* Common body of LED read/write functions, checks POS and LEN for + correctness, declares a variable using IMG_DECL, initialized pointing at + the POS position in the LED image buffer, and and iterates COPY_EXPR + until BUF is equal to the last buffer position; finally, sets LEN to be + the amount actually copied. IMG should be a variable declaration + (without an initializer or a terminating semicolon); POS, BUF, and LEN + should all be simple variables. */ +#define DO_LED_COPY(img_decl, pos, buf, len, copy_expr) \ +do { \ + if (pos > LED_NUM_DIGITS) \ + len = 0; \ + else { \ + if (pos + len > LED_NUM_DIGITS) \ + len = LED_NUM_DIGITS - pos; \ + \ + if (len > 0) { \ + int _flags; \ + const char *_end = buf + len; \ + img_decl = &leds_image[pos]; \ + \ + spin_lock_irqsave (leds_lock, _flags); \ + do \ + (copy_expr); \ + while (buf != _end); \ + spin_unlock_irqrestore (leds_lock, _flags); \ + } \ + } \ +} while (0) + +/* Read LEN bytes from LEDs at position POS, into BUF. + Returns actual amount read. */ +unsigned read_leds (unsigned pos, char *buf, unsigned len) +{ + DO_LED_COPY (const char *img, pos, buf, len, *buf++ = *img++); + return len; +} + +/* Write LEN bytes to LEDs at position POS, from BUF. + Returns actual amount written. */ +unsigned write_leds (unsigned pos, const char *buf, unsigned len) +{ + /* We write the actual LED values backwards, because + increasing memory addresses reflect LEDs right-to-left. */ + volatile char *led = &LED (LED_NUM_DIGITS - pos - 1); + /* We invert the value written to the hardware, because 1 = off, + and 0 = on. */ + DO_LED_COPY (char *img, pos, buf, len, + *led-- = 0xFF ^ (*img++ = *buf++)); + return len; +} + + +/* Device functions. */ + +static ssize_t leds_dev_read (struct file *file, char *buf, size_t len, + loff_t *pos) +{ + char temp_buf[LED_NUM_DIGITS]; + len = read_leds (*pos, temp_buf, len); + if (copy_to_user (buf, temp_buf, len)) + return -EFAULT; + *pos += len; + return len; +} + +static ssize_t leds_dev_write (struct file *file, const char *buf, size_t len, + loff_t *pos) +{ + char temp_buf[LED_NUM_DIGITS]; + if (copy_from_user (temp_buf, buf, min_t(size_t, len, LED_NUM_DIGITS))) + return -EFAULT; + len = write_leds (*pos, temp_buf, len); + *pos += len; + return len; +} + +static loff_t leds_dev_lseek (struct file *file, loff_t offs, int whence) +{ + if (whence == 1) + offs += file->f_pos; /* relative */ + else if (whence == 2) + offs += LED_NUM_DIGITS; /* end-relative */ + + if (offs >= 0 && offs <= LED_NUM_DIGITS) + file->f_pos = offs; + else + return -EINVAL; +} + +static struct file_operations leds_fops = { + read: leds_dev_read, + write: leds_dev_write, + llseek: leds_dev_lseek +}; + +static struct miscdevice leds_miscdev = { + name: "leds", + minor: LEDS_MINOR, + fops: &leds_fops +}; + +int __init leds_dev_init (void) +{ + return misc_register (&leds_miscdev); +} + +__initcall (leds_dev_init); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/v850/kernel/rte_cb_multi.c linux.2.5.45-ac1/arch/v850/kernel/rte_cb_multi.c --- linux.2.5.45/arch/v850/kernel/rte_cb_multi.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/v850/kernel/rte_cb_multi.c 2002-11-01 15:20:35.000000000 +0000 @@ -0,0 +1,85 @@ +/* + * include/asm-v850/rte_multi.c -- Support for Multi debugger monitor ROM + * on Midas lab RTE-CB series of evaluation boards + * + * Copyright (C) 2001,02 NEC Corporation + * Copyright (C) 2001,02 Miles Bader + * + * 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. + * + * Written by Miles Bader + */ + +#include + +#include + +/* A table of which interrupt vectors to install, since blindly + installing all of them makes the debugger stop working. This is a + list of offsets in the interrupt vector area; each entry means to + copy that particular 16-byte vector. An entry less than zero ends + the table. */ +static long multi_intv_install_table[] = { + 0x40, 0x50, /* trap vectors */ + /* Note -- illegal insn trap is used by the debugger. */ + 0xD0, 0xE0, 0xF0, /* GINT1 - GINT3 */ + 0x240, 0x250, 0x260, 0x270, /* timer D interrupts */ + 0x2D0, 0x2E0, 0x2F0, /* UART channel 0 */ + 0x310, 0x320, 0x330, /* UART channel 1 */ + 0x350, 0x360, 0x370, /* UART channel 2 */ + -1 +}; + +/* Early initialization for kernel using Multi debugger ROM monitor. */ +void __init multi_init (void) +{ + /* We're using the Multi debugger monitor, so we have to install + the interrupt vectors. The monitor doesn't allow them to be + initially downloaded into their final destination because + it's in the monitor's scratch-RAM area. Unfortunately, Multi + also doesn't deal correctly with ELF sections where the LMA + and VMA differ -- it just ignores the LMA -- so we can't use + that feature to work around the problem. What we do instead + is just put the interrupt vectors into a normal section, and + do the necessary copying and relocation here. Since the + interrupt vector basically only contains `jr' instructions + and no-ops, it's not that hard. */ + extern unsigned long _intv_load_start, _intv_start; + register unsigned long *src = &_intv_load_start; + register unsigned long *dst = (unsigned long *)INTV_BASE; + register unsigned long jr_fixup = (char *)&_intv_start - (char *)dst; + register long *ii; + + /* Copy interupt vectors as instructed by multi_intv_install_table. */ + for (ii = multi_intv_install_table; *ii >= 0; ii++) { + /* Copy 16-byte interrupt vector at offset *ii. */ + int boffs; + for (boffs = 0; boffs < 0x10; boffs += sizeof *src) { + /* Copy a single word, fixing up the jump offs + if it's a `jr' instruction. */ + int woffs = (*ii + boffs) / sizeof *src; + unsigned long word = src[woffs]; + + if ((word & 0xFC0) == 0x780) { + /* A `jr' insn, fix up its offset (and yes, the + wierd half-word swapping is intentional). */ + unsigned short hi = word & 0xFFFF; + unsigned short lo = word >> 16; + unsigned long udisp22 + = lo + ((hi & 0x3F) << 16); + long disp22 = (long)(udisp22 << 10) >> 10; + + disp22 += jr_fixup; + + hi = ((disp22 >> 16) & 0x3F) | 0x780; + lo = disp22 & 0xFFFF; + + word = hi + (lo << 16); + } + + dst[woffs] = word; + } + } +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/v850/kernel/rte_ma1_cb.c linux.2.5.45-ac1/arch/v850/kernel/rte_ma1_cb.c --- linux.2.5.45/arch/v850/kernel/rte_ma1_cb.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/v850/kernel/rte_ma1_cb.c 2002-11-01 15:20:35.000000000 +0000 @@ -0,0 +1,101 @@ +/* + * arch/v850/kernel/rte_ma1_cb.c -- Midas labs RTE-V850E/MA1-CB board + * + * Copyright (C) 2001,02 NEC Corporation + * Copyright (C) 2001,02 Miles Bader + * + * 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. + * + * Written by Miles Bader + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "mach.h" + + +/* SRAM and SDRAM are almost contiguous (with a small hole in between; + see mach_reserve_bootmem for details), so just use both as one big area. */ +#define RAM_START SRAM_ADDR +#define RAM_END (SDRAM_ADDR + SDRAM_SIZE) + + +void __init mach_get_physical_ram (unsigned long *ram_start, + unsigned long *ram_len) +{ + *ram_start = RAM_START; + *ram_len = RAM_END - RAM_START; +} + +void __init mach_reserve_bootmem () +{ +#ifdef CONFIG_RTE_CB_MULTI + /* Prevent the kernel from touching the monitor's scratch RAM. */ + reserve_bootmem (MON_SCRATCH_ADDR, MON_SCRATCH_SIZE); +#endif + + /* The space between SRAM and SDRAM is filled with duplicate + images of SRAM. Prevent the kernel from using them. */ + reserve_bootmem (SRAM_ADDR + SRAM_SIZE, + SDRAM_ADDR - (SRAM_ADDR + SRAM_SIZE)); +} + +void mach_gettimeofday (struct timespec *tv) +{ + tv->tv_sec = 0; + tv->tv_nsec = 0; +} + +/* Called before configuring an on-chip UART. */ +void rte_ma1_cb_uart_pre_configure (unsigned chan, + unsigned cflags, unsigned baud) +{ + /* The RTE-MA1-CB connects some general-purpose I/O pins on the + CPU to the RTS/CTS lines of UART 0's serial connection. + I/O pins P42 and P43 are RTS and CTS respectively. */ + if (chan == 0) { + /* Put P42 & P43 in I/O port mode. */ + MA_PORT4_PMC &= ~0xC; + /* Make P42 and output, and P43 an input. */ + MA_PORT4_PM = (MA_PORT4_PM & ~0xC) | 0x8; + } + + /* Do pre-configuration for the actual UART. */ + ma_uart_pre_configure (chan, cflags, baud); +} + +void __init mach_init_irqs (void) +{ + unsigned tc; + + /* Initialize interrupts. */ + ma_init_irqs (); + rte_cb_init_irqs (); + + /* Use falling-edge-sensitivity for interrupts . */ + NB85E_TIMER_C_SESC (0) &= ~0xC; + NB85E_TIMER_C_SESC (1) &= ~0xF; + + /* INTP000-INTP011 are shared with `Timer C', so we have to set + up Timer C to pass them through as raw interrupts. */ + for (tc = 0; tc < 2; tc++) + /* Turn on the timer. */ + NB85E_TIMER_C_TMCC0 (tc) |= NB85E_TIMER_C_TMCC0_CAE; + + /* Make sure the relevent port0/port1 pins are assigned + interrupt duty. We used INTP001-INTP011 (don't screw with + INTP000 because the monitor uses it). */ + MA_PORT0_PMC |= 0x4; /* P02 (INTP001) in IRQ mode. */ + MA_PORT1_PMC |= 0x6; /* P11 (INTP010) & P12 (INTP011) in IRQ mode.*/ +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/v850/kernel/rte_mb_a_pci.c linux.2.5.45-ac1/arch/v850/kernel/rte_mb_a_pci.c --- linux.2.5.45/arch/v850/kernel/rte_mb_a_pci.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/v850/kernel/rte_mb_a_pci.c 2002-11-01 15:20:35.000000000 +0000 @@ -0,0 +1,781 @@ +/* + * arch/v850/kernel/mb_a_pci.c -- PCI support for Midas lab RTE-MOTHER-A board + * + * Copyright (C) 2001,02 NEC Corporation + * Copyright (C) 2001,02 Miles Bader + * + * 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. + * + * Written by Miles Bader + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +/* __nomods_init is like __devinit, but is a no-op when modules are enabled. + This is used by some routines that can be called either during boot + or by a module. */ +#ifdef CONFIG_MODULES +#define __nomods_init /*nothing*/ +#else +#define __nomods_init __devinit +#endif + +/* PCI devices on the Mother-A board can only do DMA to/from the MB SRAM + (the RTE-V850E/MA1-CB cpu board doesn't support PCI access to + CPU-board memory), and since linux DMA buffers are allocated in + normal kernel memory, we basically have to copy DMA blocks around + (this is like a `bounce buffer'). When a DMA block is `mapped', we + allocate an identically sized block in MB SRAM, and if we're doing + output to the device, copy the CPU-memory block to the MB-SRAM block. + When an active block is `unmapped', we will copy the block back to + CPU memory if necessary, and then deallocate the MB SRAM block. + Ack. */ + +/* Where the motherboard SRAM is in the PCI-bus address space (the + first 512K of it is also mapped at PCI address 0). */ +#define PCI_MB_SRAM_ADDR 0x800000 + +/* Convert CPU-view MB SRAM address to/from PCI-view addresses of the + same memory. */ +#define MB_SRAM_TO_PCI(mb_sram_addr) \ + ((dma_addr_t)mb_sram_addr - MB_A_SRAM_ADDR + PCI_MB_SRAM_ADDR) +#define PCI_TO_MB_SRAM(pci_addr) \ + (void *)(pci_addr - PCI_MB_SRAM_ADDR + MB_A_SRAM_ADDR) + +static void pcibios_assign_resources (void); + +struct mb_pci_dev_irq { + unsigned dev; /* PCI device number */ + unsigned irq_base; /* First IRQ */ + unsigned query_pin; /* True if we should read the device's + Interrupt Pin info, and allocate + interrupt IRQ_BASE + PIN. */ +}; + +/* PCI interrupts are mapped statically to GBUS interrupts. */ +static struct mb_pci_dev_irq mb_pci_dev_irqs[] = { + /* Motherboard SB82558 ethernet controller */ + { 10, IRQ_MB_A_LAN, 0 }, + /* PCI slot 1 */ + { 8, IRQ_MB_A_PCI1(0), 1 }, + /* PCI slot 2 */ + { 9, IRQ_MB_A_PCI2(0), 1 } +}; +#define NUM_MB_PCI_DEV_IRQS \ + (sizeof mb_pci_dev_irqs / sizeof mb_pci_dev_irqs[0]) + + +/* PCI configuration primitives. */ + +#define CONFIG_DMCFGA(bus, devfn, offs) \ + (0x80000000 \ + | ((offs) & ~0x3) \ + | ((devfn) << 8) \ + | ((bus)->number << 16)) + +static int +mb_pci_read (struct pci_bus *bus, unsigned devfn, int offs, int size, u32 *rval) +{ + u32 addr; + int flags; + + local_irq_save (flags); + + MB_A_PCI_PCICR = 0x7; + MB_A_PCI_DMCFGA = CONFIG_DMCFGA (bus, devfn, offs); + + addr = MB_A_PCI_IO_ADDR + (offs & 0x3); + + switch (size) { + case 1: *rval = *(volatile u8 *)addr; break; + case 2: *rval = *(volatile u16 *)addr; break; + case 4: *rval = *(volatile u32 *)addr; break; + } + + if (MB_A_PCI_PCISR & 0x2000) { + MB_A_PCI_PCISR = 0x2000; + *rval = ~0; + } + + MB_A_PCI_DMCFGA = 0; + + local_irq_restore (flags); + + return PCIBIOS_SUCCESSFUL; +} + +static int +mb_pci_write (struct pci_bus *bus, unsigned devfn, int offs, int size, u32 val) +{ + u32 addr; + int flags; + + local_irq_save (flags); + + MB_A_PCI_PCICR = 0x7; + MB_A_PCI_DMCFGA = CONFIG_DMCFGA (bus, devfn, offs); + + addr = MB_A_PCI_IO_ADDR + (offs & 0x3); + + switch (size) { + case 1: *(volatile u8 *)addr = val; break; + case 2: *(volatile u16 *)addr = val; break; + case 4: *(volatile u32 *)addr = val; break; + } + + if (MB_A_PCI_PCISR & 0x2000) + MB_A_PCI_PCISR = 0x2000; + + MB_A_PCI_DMCFGA = 0; + + local_irq_restore (flags); + + return PCIBIOS_SUCCESSFUL; +} + +static struct pci_ops mb_pci_config_ops = { + .read = mb_pci_read, + .write = mb_pci_write, +}; + + +/* PCI Initialization. */ + +static struct pci_bus *mb_pci_bus = 0; + +/* Do initial PCI setup. */ +static int __devinit pcibios_init (void) +{ + u32 id = MB_A_PCI_PCIHIDR; + u16 vendor = id & 0xFFFF; + u16 device = (id >> 16) & 0xFFFF; + + if (vendor == PCI_VENDOR_ID_PLX && device == PCI_DEVICE_ID_PLX_9080) { + printk (KERN_INFO + "PCI: PLX Technology PCI9080 HOST/PCI bridge\n"); + + MB_A_PCI_PCICR = 0x147; + MB_A_PCI_DMLBAM = 0x0; + + MB_A_PCI_PCIBAR0 = 0x007FFF00; + MB_A_PCI_PCIBAR1 = 0x0000FF00; + MB_A_PCI_PCIBAR2 = 0x00800000; + + MB_A_PCI_PCILTR = 0x20; + + MB_A_PCI_PCIPBAM |= 0x3; + + MB_A_PCI_PCISR = ~0; /* Clear errors. */ + + /* Reprogram the motherboard's IO/config address space, + as we don't support the GCS7 address space that the + default uses. Note that we have to give the address + from the motherboard's point of view, which is + different than the CPU's. */ + MB_A_PCI_DMLBAI = MB_A_PCI_IO_ADDR - GCS5_ADDR; + MB_A_PCI_DMRR = ~(MB_A_PCI_MEM_SIZE - 1); + + mb_pci_bus = pci_scan_bus (0, &mb_pci_config_ops, 0); + + pcibios_assign_resources (); + } else + printk (KERN_ERR "PCI: HOST/PCI bridge not found\n"); + + return 0; +} + +subsys_initcall (pcibios_init); + +char __devinit *pcibios_setup (char *option) +{ + /* Don't handle any options. */ + return option; +} + + +int __nomods_init pcibios_enable_device (struct pci_dev *dev, int mask) +{ + u16 cmd, old_cmd; + int idx; + struct resource *r; + + pci_read_config_word(dev, PCI_COMMAND, &cmd); + old_cmd = cmd; + for (idx = 0; idx < 6; idx++) { + r = &dev->resource[idx]; + if (!r->start && r->end) { + printk(KERN_ERR "PCI: Device %s not available because " + "of resource collisions\n", dev->slot_name); + return -EINVAL; + } + if (r->flags & IORESOURCE_IO) + cmd |= PCI_COMMAND_IO; + if (r->flags & IORESOURCE_MEM) + cmd |= PCI_COMMAND_MEMORY; + } + if (cmd != old_cmd) { + printk("PCI: Enabling device %s (%04x -> %04x)\n", + dev->slot_name, old_cmd, cmd); + pci_write_config_word(dev, PCI_COMMAND, cmd); + } + return 0; +} + + +/* Resource allocation. */ +static void __devinit pcibios_assign_resources (void) +{ + struct pci_dev *dev; + struct resource *r; + + pci_for_each_dev (dev) { + int di_num; + unsigned class = dev->class >> 8; + + if (class && class != PCI_CLASS_BRIDGE_HOST) { + unsigned r_num; + for(r_num = 0; r_num < 6; r_num++) { + r = &dev->resource[r_num]; + if (!r->start && r->end) + pci_assign_resource (dev, r_num); + } + } + + /* Assign interrupts. */ + for (di_num = 0; di_num < NUM_MB_PCI_DEV_IRQS; di_num++) { + struct mb_pci_dev_irq *di = &mb_pci_dev_irqs[di_num]; + + if (di->dev == PCI_SLOT (dev->devfn)) { + unsigned irq = di->irq_base; + + if (di->query_pin) { + /* Find out which interrupt pin + this device uses (each PCI + slot has 4). */ + u8 irq_pin; + + pci_read_config_byte (dev, + PCI_INTERRUPT_PIN, + &irq_pin); + + if (irq_pin == 0) + /* Doesn't use interrupts. */ + continue; + else + irq += irq_pin - 1; + } + + pcibios_update_irq (dev, irq); + } + } + } +} + +void __devinit pcibios_update_irq (struct pci_dev *dev, int irq) +{ + dev->irq = irq; + pci_write_config_byte (dev, PCI_INTERRUPT_LINE, irq); +} + +void __nomods_init +pcibios_update_resource (struct pci_dev *dev, struct resource *root, + struct resource *r, int resource) +{ + u32 new, check; + int reg; + + if (r->flags & IORESOURCE_IO) + new = (((r->start - MB_A_PCI_IO_ADDR) + & PCI_BASE_ADDRESS_IO_MASK) + | PCI_BASE_ADDRESS_SPACE_IO); + else if (r->flags & IORESOURCE_MEM) + new = (((r->start - MB_A_PCI_MEM_ADDR) + & PCI_BASE_ADDRESS_MEM_MASK) + | PCI_BASE_ADDRESS_MEM_TYPE_32 + | ((r->flags & IORESOURCE_PREFETCH) + ? PCI_BASE_ADDRESS_MEM_PREFETCH + : 0) + | PCI_BASE_ADDRESS_SPACE_MEMORY); + else + panic ("pcibios_update_resource: unknown resource type"); + + if (resource < 6) + reg = PCI_BASE_ADDRESS_0 + 4*resource; + else if (resource == PCI_ROM_RESOURCE) { + r->flags |= PCI_ROM_ADDRESS_ENABLE; + new |= PCI_ROM_ADDRESS_ENABLE; + reg = dev->rom_base_reg; + } else + return; + + pci_write_config_dword(dev, reg, new); + pci_read_config_dword(dev, reg, &check); + if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) { + printk (KERN_ERR "PCI: Error while updating region " + "%s/%d (%08x != %08x)\n", dev->slot_name, resource, + new, check); + } +} + + +/* Stubs for things we don't use. */ + +struct pci_fixup pcibios_fixups[] = { { 0 } }; + +/* Called after each bus is probed, but before its children are examined. */ +void pcibios_fixup_bus(struct pci_bus *b) +{ +} + +void +pcibios_align_resource (void *data, struct resource *res, + unsigned long size, unsigned long align) +{ +} + +void pcibios_set_master (struct pci_dev *dev) +{ +} + + +/* Mother-A SRAM memory allocation. This is a simple first-fit allocator. */ + +/* A memory free-list node. */ +struct mb_sram_free_area { + void *mem; + unsigned long size; + struct mb_sram_free_area *next; +}; + +/* The tail of the free-list, which starts out containing all the SRAM. */ +static struct mb_sram_free_area mb_sram_free_tail = { + (void *)MB_A_SRAM_ADDR, MB_A_SRAM_SIZE, 0 +}; + +/* The free-list. */ +static struct mb_sram_free_area *mb_sram_free_areas = &mb_sram_free_tail; + +/* The free-list of free free-list nodes. (:-) */ +static struct mb_sram_free_area *mb_sram_free_free_areas = 0; + +/* Spinlock protecting the above globals. */ +static spinlock_t mb_sram_lock = SPIN_LOCK_UNLOCKED; + +/* Allocate a memory block at least SIZE bytes long in the Mother-A SRAM + space. */ +static void *alloc_mb_sram (size_t size) +{ + struct mb_sram_free_area *prev, *fa; + int flags; + void *mem = 0; + + spin_lock_irqsave (mb_sram_lock, flags); + + /* Look for a free area that can contain SIZE bytes. */ + for (prev = 0, fa = mb_sram_free_areas; fa; prev = fa, fa = fa->next) + if (fa->size >= size) { + /* Found one! */ + mem = fa->mem; + + if (fa->size == size) { + /* In fact, it fits exactly, so remove + this node from the free-list. */ + if (prev) + prev->next = fa->next; + else + mb_sram_free_areas = fa->next; + /* Put it on the free-list-entry-free-list. */ + fa->next = mb_sram_free_free_areas; + mb_sram_free_free_areas = fa; + } else { + /* FA is bigger than SIZE, so just + reduce its size to account for this + allocation. */ + fa->mem += size; + fa->size -= size; + } + + break; + } + + spin_unlock_irqrestore (mb_sram_lock, flags); + + return mem; +} + +/* Return the memory area MEM of size SIZE to the MB SRAM free pool. */ +static void free_mb_sram (void *mem, size_t size) +{ + struct mb_sram_free_area *prev, *fa, *new_fa; + int flags; + void *end = mem + size; + + spin_lock_irqsave (mb_sram_lock, flags); + + retry: + /* Find an adjacent free-list entry. */ + for (prev = 0, fa = mb_sram_free_areas; fa; prev = fa, fa = fa->next) + if (fa->mem == end) { + /* FA is just after MEM, grow down to encompass it. */ + fa->mem = mem; + fa->size += size; + goto done; + } else if (fa->mem + fa->size == mem) { + struct mb_sram_free_area *next_fa = fa->next; + + /* FA is just before MEM, expand to encompass it. */ + fa->size += size; + + /* See if FA can now be merged with its successor. */ + if (next_fa && fa->mem + fa->size == next_fa->mem) { + /* Yup; merge NEXT_FA's info into FA. */ + fa->size += next_fa->size; + fa->next = next_fa->next; + /* Free NEXT_FA. */ + next_fa->next = mb_sram_free_free_areas; + mb_sram_free_free_areas = next_fa; + } + goto done; + } else if (fa->mem > mem) + /* We've reached the right spot in the free-list + without finding an adjacent free-area, so add + a new free area to hold mem. */ + break; + + /* Make a new free-list entry. */ + + /* First, get a free-list entry. */ + if (! mb_sram_free_free_areas) { + /* There are none, so make some. */ + void *block; + size_t block_size = sizeof (struct mb_sram_free_area) * 8; + + /* Don't hold the lock while calling kmalloc (I'm not + sure whether it would be a problem, since we use + GFP_ATOMIC, but it makes me nervous). */ + spin_unlock_irqrestore (mb_sram_lock, flags); + + block = kmalloc (block_size, GFP_ATOMIC); + if (! block) + panic ("free_mb_sram: can't allocate free-list entry"); + + /* Now get the lock back. */ + spin_lock_irqsave (mb_sram_lock, flags); + + /* Add the new free free-list entries. */ + while (block_size > 0) { + struct mb_sram_free_area *nfa = block; + nfa->next = mb_sram_free_free_areas; + mb_sram_free_free_areas = nfa; + block += sizeof *nfa; + block_size -= sizeof *nfa; + } + + /* Since we dropped the lock to call kmalloc, the + free-list could have changed, so retry from the + beginning. */ + goto retry; + } + + /* Remove NEW_FA from the free-list of free-list entries. */ + new_fa = mb_sram_free_free_areas; + mb_sram_free_free_areas = new_fa->next; + + /* NEW_FA initially holds only MEM. */ + new_fa->mem = mem; + new_fa->size = size; + + /* Insert NEW_FA in the free-list between PREV and FA. */ + new_fa->next = fa; + if (prev) + prev->next = new_fa; + else + mb_sram_free_areas = new_fa; + + done: + spin_unlock_irqrestore (mb_sram_lock, flags); +} + + +/* Maintainence of CPU -> Mother-A DMA mappings. */ + +struct dma_mapping { + void *cpu_addr; + void *mb_sram_addr; + size_t size; + struct dma_mapping *next; +}; + +/* A list of mappings from CPU addresses to MB SRAM addresses for active + DMA blocks (that have been `granted' to the PCI device). */ +static struct dma_mapping *active_dma_mappings = 0; + +/* A list of free mapping objects. */ +static struct dma_mapping *free_dma_mappings = 0; + +/* Spinlock protecting the above globals. */ +static spinlock_t dma_mappings_lock = SPIN_LOCK_UNLOCKED; + +static struct dma_mapping *new_dma_mapping (size_t size) +{ + int flags; + struct dma_mapping *mapping; + void *mb_sram_block = alloc_mb_sram (size); + + if (! mb_sram_block) + return 0; + + spin_lock_irqsave (dma_mappings_lock, flags); + + if (! free_dma_mappings) { + /* We're out of mapping structures, make more. */ + void *mblock; + size_t mblock_size = sizeof (struct dma_mapping) * 8; + + /* Don't hold the lock while calling kmalloc (I'm not + sure whether it would be a problem, since we use + GFP_ATOMIC, but it makes me nervous). */ + spin_unlock_irqrestore (dma_mappings_lock, flags); + + mblock = kmalloc (mblock_size, GFP_ATOMIC); + if (! mblock) { + free_mb_sram (mb_sram_block, size); + return 0; + } + + /* Get the lock back. */ + spin_lock_irqsave (dma_mappings_lock, flags); + + /* Add the new mapping structures to the free-list. */ + while (mblock_size > 0) { + struct dma_mapping *fm = mblock; + fm->next = free_dma_mappings; + free_dma_mappings = fm; + mblock += sizeof *fm; + mblock_size -= sizeof *fm; + } + } + + /* Get a mapping struct from the freelist. */ + mapping = free_dma_mappings; + free_dma_mappings = mapping->next; + + /* Initialize the mapping. Other fields should be filled in by + caller. */ + mapping->mb_sram_addr = mb_sram_block; + mapping->size = size; + + /* Add it to the list of active mappings. */ + mapping->next = active_dma_mappings; + active_dma_mappings = mapping; + + spin_unlock_irqrestore (dma_mappings_lock, flags); + + return mapping; +} + +static struct dma_mapping *find_dma_mapping (void *mb_sram_addr) +{ + int flags; + struct dma_mapping *mapping; + + spin_lock_irqsave (dma_mappings_lock, flags); + + for (mapping = active_dma_mappings; mapping; mapping = mapping->next) + if (mapping->mb_sram_addr == mb_sram_addr) { + spin_unlock_irqrestore (dma_mappings_lock, flags); + return mapping; + } + + panic ("find_dma_mapping: unmapped PCI DMA addr 0x%x", + MB_SRAM_TO_PCI (mb_sram_addr)); +} + +static struct dma_mapping *deactivate_dma_mapping (void *mb_sram_addr) +{ + int flags; + struct dma_mapping *mapping, *prev; + + spin_lock_irqsave (dma_mappings_lock, flags); + + for (prev = 0, mapping = active_dma_mappings; + mapping; + prev = mapping, mapping = mapping->next) + { + if (mapping->mb_sram_addr == mb_sram_addr) { + /* This is the MAPPING; deactivate it. */ + if (prev) + prev->next = mapping->next; + else + active_dma_mappings = mapping->next; + + spin_unlock_irqrestore (dma_mappings_lock, flags); + + return mapping; + } + } + + panic ("deactivate_dma_mapping: unmapped PCI DMA addr 0x%x", + MB_SRAM_TO_PCI (mb_sram_addr)); +} + +/* Return MAPPING to the freelist. */ +static inline void +free_dma_mapping (struct dma_mapping *mapping) +{ + int flags; + + free_mb_sram (mapping->mb_sram_addr, mapping->size); + + spin_lock_irqsave (dma_mappings_lock, flags); + + mapping->next = free_dma_mappings; + free_dma_mappings = mapping; + + spin_unlock_irqrestore (dma_mappings_lock, flags); +} + + +/* Single PCI DMA mappings. */ + +/* `Grant' to PDEV the memory block at CPU_ADDR, for doing DMA. The + 32-bit PCI bus mastering address to use is returned. the device owns + this memory until either pci_unmap_single or pci_dma_sync_single is + performed. */ +dma_addr_t +pci_map_single (struct pci_dev *pdev, void *cpu_addr, size_t size, int dir) +{ + struct dma_mapping *mapping = new_dma_mapping (size); + + if (! mapping) + return 0; + + mapping->cpu_addr = cpu_addr; + + if (dir == PCI_DMA_BIDIRECTIONAL || dir == PCI_DMA_TODEVICE) + memcpy (mapping->mb_sram_addr, cpu_addr, size); + + return MB_SRAM_TO_PCI (mapping->mb_sram_addr); +} + +/* Return to the CPU the PCI DMA memory block previously `granted' to + PDEV, at DMA_ADDR. */ +void pci_unmap_single (struct pci_dev *pdev, dma_addr_t dma_addr, size_t size, + int dir) +{ + void *mb_sram_addr = PCI_TO_MB_SRAM (dma_addr); + struct dma_mapping *mapping = deactivate_dma_mapping (mb_sram_addr); + + if (size != mapping->size) + panic ("pci_unmap_single: size (%d) doesn't match" + " size of mapping at PCI DMA addr 0x%x (%d)\n", + size, dma_addr, mapping->size); + + /* Copy back the DMA'd contents if necessary. */ + if (dir == PCI_DMA_BIDIRECTIONAL || dir == PCI_DMA_FROMDEVICE) + memcpy (mapping->cpu_addr, mb_sram_addr, size); + + /* Return mapping to the freelist. */ + free_dma_mapping (mapping); +} + +/* Make physical memory consistant for a single streaming mode DMA + translation after a transfer. + + If you perform a pci_map_single() but wish to interrogate the + buffer using the cpu, yet do not wish to teardown the PCI dma + mapping, you must call this function before doing so. At the next + point you give the PCI dma address back to the card, the device + again owns the buffer. */ +void +pci_dma_sync_single (struct pci_dev *pdev, dma_addr_t dma_addr, size_t size, + int dir) +{ + void *mb_sram_addr = PCI_TO_MB_SRAM (dma_addr); + struct dma_mapping *mapping = find_dma_mapping (mb_sram_addr); + + /* Synchronize the DMA buffer with the CPU buffer if necessary. */ + if (dir == PCI_DMA_FROMDEVICE) + memcpy (mapping->cpu_addr, mb_sram_addr, size); + else if (dir == PCI_DMA_TODEVICE) + memcpy (mb_sram_addr, mapping->cpu_addr, size); + else + panic("pci_dma_sync_single: unsupported sync dir: %d", dir); +} + + +/* Scatter-gather PCI DMA mappings. */ + +/* Do multiple DMA mappings at once. */ +int +pci_map_sg (struct pci_dev *pdev, struct scatterlist *sg, int sg_len, int dir) +{ + BUG (); + return 0; +} + +/* Unmap multiple DMA mappings at once. */ +void +pci_unmap_sg (struct pci_dev *pdev, struct scatterlist *sg, int sg_len,int dir) +{ + BUG (); +} + +/* Make physical memory consistant for a set of streaming mode DMA + translations after a transfer. The same as pci_dma_sync_single but + for a scatter-gather list, same rules and usage. */ + +void +pci_dma_sync_sg (struct pci_dev *dev, struct scatterlist *sg, int sg_len, + int dir) +{ + BUG (); +} + + +/* PCI mem mapping. */ + +/* Allocate and map kernel buffer using consistent mode DMA for PCI + device. Returns non-NULL cpu-view pointer to the buffer if + successful and sets *DMA_ADDR to the pci side dma address as well, + else DMA_ADDR is undefined. */ +void * +pci_alloc_consistent (struct pci_dev *pdev, size_t size, dma_addr_t *dma_addr) +{ + void *mb_sram_mem = alloc_mb_sram (size); + if (mb_sram_mem) + *dma_addr = MB_SRAM_TO_PCI (mb_sram_mem); + return mb_sram_mem; +} + +/* Free and unmap a consistent DMA buffer. CPU_ADDR and DMA_ADDR must + be values that were returned from pci_alloc_consistent. SIZE must be + the same as what as passed into pci_alloc_consistent. References to + the memory and mappings assosciated with CPU_ADDR or DMA_ADDR past + this call are illegal. */ +void +pci_free_consistent (struct pci_dev *pdev, size_t size, void *cpu_addr, + dma_addr_t dma_addr) +{ + void *mb_sram_mem = PCI_TO_MB_SRAM (dma_addr); + free_mb_sram (mb_sram_mem, size); +} + + +/* symbol exports (for modules) */ + +EXPORT_SYMBOL (pci_map_single); +EXPORT_SYMBOL (pci_unmap_single); +EXPORT_SYMBOL (pci_alloc_consistent); +EXPORT_SYMBOL (pci_free_consistent); +EXPORT_SYMBOL (pci_dma_sync_single); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/v850/kernel/rte_nb85e_cb.c linux.2.5.45-ac1/arch/v850/kernel/rte_nb85e_cb.c --- linux.2.5.45/arch/v850/kernel/rte_nb85e_cb.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/v850/kernel/rte_nb85e_cb.c 2002-11-01 15:20:35.000000000 +0000 @@ -0,0 +1,54 @@ +/* + * arch/v850/kernel/rte_nb85e_cb.c -- Midas labs RTE-V850E/NB85E-CB board + * + * Copyright (C) 2001,02 NEC Corporation + * Copyright (C) 2001,02 Miles Bader + * + * 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. + * + * Written by Miles Bader + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "mach.h" + +void __init mach_get_physical_ram (unsigned long *ram_start, + unsigned long *ram_len) +{ + /* We just use SDRAM here; the kernel itself is in SRAM. */ + *ram_start = SDRAM_ADDR; + *ram_len = SDRAM_SIZE; +} + +void __init mach_reserve_bootmem () +{ + extern char _root_fs_image_start, _root_fs_image_end; + u32 root_fs_image_start = (u32)&_root_fs_image_start; + u32 root_fs_image_end = (u32)&_root_fs_image_end; + + /* Reserve the memory used by the root filesystem image if it's + in RAM. */ + if (root_fs_image_start >= RAM_START && root_fs_image_start < RAM_END) + reserve_bootmem (root_fs_image_start, + root_fs_image_end - root_fs_image_start); +} + +void mach_gettimeofday (struct timespec *tv) +{ + tv->tv_sec = 0; + tv->tv_nsec = 0; +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/v850/kernel/semaphore.c linux.2.5.45-ac1/arch/v850/kernel/semaphore.c --- linux.2.5.45/arch/v850/kernel/semaphore.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/v850/kernel/semaphore.c 2002-11-01 15:20:35.000000000 +0000 @@ -0,0 +1,164 @@ +/* + * arch/v850/kernel/semaphore.c -- Semaphore support + * + * Copyright (C) 1998-2000 IBM Corporation + * Copyright (C) 1999 Linus Torvalds + * + * 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. + * + * This file is a copy of the s390 version, arch/s390/kernel/semaphore.c + * Author(s): Martin Schwidefsky + * which was derived from the i386 version, linux/arch/i386/kernel/semaphore.c + */ + +#include + +#include + +/* + * Semaphores are implemented using a two-way counter: + * The "count" variable is decremented for each process + * that tries to acquire the semaphore, while the "sleeping" + * variable is a count of such acquires. + * + * Notably, the inline "up()" and "down()" functions can + * efficiently test if they need to do any extra work (up + * needs to do something only if count was negative before + * the increment operation. + * + * "sleeping" and the contention routine ordering is + * protected by the semaphore spinlock. + * + * Note that these functions are only called when there is + * contention on the lock, and as such all this is the + * "non-critical" part of the whole semaphore business. The + * critical part is the inline stuff in + * where we want to avoid any extra jumps and calls. + */ + +/* + * Logic: + * - only on a boundary condition do we need to care. When we go + * from a negative count to a non-negative, we wake people up. + * - when we go from a non-negative count to a negative do we + * (a) synchronize with the "sleeper" count and (b) make sure + * that we're on the wakeup list before we synchronize so that + * we cannot lose wakeup events. + */ + +void __up(struct semaphore *sem) +{ + wake_up(&sem->wait); +} + +static spinlock_t semaphore_lock = SPIN_LOCK_UNLOCKED; + +void __down(struct semaphore * sem) +{ + struct task_struct *tsk = current; + DECLARE_WAITQUEUE(wait, tsk); + tsk->state = TASK_UNINTERRUPTIBLE; + add_wait_queue_exclusive(&sem->wait, &wait); + + spin_lock_irq(&semaphore_lock); + sem->sleepers++; + for (;;) { + int sleepers = sem->sleepers; + + /* + * Add "everybody else" into it. They aren't + * playing, because we own the spinlock. + */ + if (!atomic_add_negative(sleepers - 1, &sem->count)) { + sem->sleepers = 0; + break; + } + sem->sleepers = 1; /* us - see -1 above */ + spin_unlock_irq(&semaphore_lock); + + schedule(); + tsk->state = TASK_UNINTERRUPTIBLE; + spin_lock_irq(&semaphore_lock); + } + spin_unlock_irq(&semaphore_lock); + remove_wait_queue(&sem->wait, &wait); + tsk->state = TASK_RUNNING; + wake_up(&sem->wait); +} + +int __down_interruptible(struct semaphore * sem) +{ + int retval = 0; + struct task_struct *tsk = current; + DECLARE_WAITQUEUE(wait, tsk); + tsk->state = TASK_INTERRUPTIBLE; + add_wait_queue_exclusive(&sem->wait, &wait); + + spin_lock_irq(&semaphore_lock); + sem->sleepers ++; + for (;;) { + int sleepers = sem->sleepers; + + /* + * With signals pending, this turns into + * the trylock failure case - we won't be + * sleeping, and we* can't get the lock as + * it has contention. Just correct the count + * and exit. + */ + if (signal_pending(current)) { + retval = -EINTR; + sem->sleepers = 0; + atomic_add(sleepers, &sem->count); + break; + } + + /* + * Add "everybody else" into it. They aren't + * playing, because we own the spinlock. The + * "-1" is because we're still hoping to get + * the lock. + */ + if (!atomic_add_negative(sleepers - 1, &sem->count)) { + sem->sleepers = 0; + break; + } + sem->sleepers = 1; /* us - see -1 above */ + spin_unlock_irq(&semaphore_lock); + + schedule(); + tsk->state = TASK_INTERRUPTIBLE; + spin_lock_irq(&semaphore_lock); + } + spin_unlock_irq(&semaphore_lock); + tsk->state = TASK_RUNNING; + remove_wait_queue(&sem->wait, &wait); + wake_up(&sem->wait); + return retval; +} + +/* + * Trylock failed - make sure we correct for + * having decremented the count. + */ +int __down_trylock(struct semaphore * sem) +{ + unsigned long flags; + int sleepers; + + spin_lock_irqsave(&semaphore_lock, flags); + sleepers = sem->sleepers + 1; + sem->sleepers = 0; + + /* + * Add "everybody else" and us into it. They aren't + * playing, because we own the spinlock. + */ + if (!atomic_add_negative(sleepers, &sem->count)) + wake_up(&sem->wait); + + spin_unlock_irqrestore(&semaphore_lock, flags); + return 1; +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/v850/kernel/setup.c linux.2.5.45-ac1/arch/v850/kernel/setup.c --- linux.2.5.45/arch/v850/kernel/setup.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/v850/kernel/setup.c 2002-11-01 15:20:35.000000000 +0000 @@ -0,0 +1,273 @@ +/* + * arch/v850/kernel/setup.c -- Arch-dependent initialization functions + * + * Copyright (C) 2001,02 NEC Corporation + * Copyright (C) 2001,02 Miles Bader + * + * 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. + * + * Written by Miles Bader + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "mach.h" + +/* These symbols are all defined in the linker map to delineate various + statically allocated regions of memory. */ + +extern char _intv_start, _intv_end; +/* `kram' is only used if the kernel uses part of normal user RAM. */ +extern char _kram_start __attribute__ ((__weak__)); +extern char _kram_end __attribute__ ((__weak__)); +extern char _init_start, _init_end; +extern char _bootmap; +extern char _stext, _etext, _sdata, _edata, _sbss, _ebss; +/* Many platforms use an embedded root image. */ +extern char _root_fs_image_start __attribute__ ((__weak__)); +extern char _root_fs_image_end __attribute__ ((__weak__)); + + +char command_line[512]; +char saved_command_line[512]; + +/* Memory not used by the kernel. */ +static unsigned long total_ram_pages; + +/* System RAM. */ +static unsigned long ram_start = 0, ram_len = 0; + + +#define ADDR_TO_PAGE_UP(x) ((((unsigned long)x) + PAGE_SIZE-1) >> PAGE_SHIFT) +#define ADDR_TO_PAGE(x) (((unsigned long)x) >> PAGE_SHIFT) +#define PAGE_TO_ADDR(x) (((unsigned long)x) << PAGE_SHIFT) + +static void init_mem_alloc (unsigned long ram_start, unsigned long ram_len); + +void set_mem_root (void *addr, size_t len, char *cmd_line); + + +void __init setup_arch (char **cmdline) +{ + /* Keep a copy of command line */ + *cmdline = command_line; + memcpy (saved_command_line, command_line, sizeof saved_command_line); + saved_command_line[sizeof saved_command_line - 1] = '\0'; + + console_verbose (); + + init_mm.start_code = (unsigned long) &_stext; + init_mm.end_code = (unsigned long) &_etext; + init_mm.end_data = (unsigned long) &_edata; + init_mm.brk = (unsigned long) &_kram_end; + + /* Find out what mem this machine has. */ + mach_get_physical_ram (&ram_start, &ram_len); + /* ... and tell the kernel about it. */ + init_mem_alloc (ram_start, ram_len); + + /* do machine-specific setups. */ + mach_setup (cmdline); + +#ifdef CONFIG_MTD + if (!ROOT_DEV && &_root_fs_image_end > &_root_fs_image_start) + set_mem_root (&_root_fs_image_start, + &_root_fs_image_end - &_root_fs_image_start, + *cmdline); +#endif +} + +void __init trap_init (void) +{ +} + +#ifdef CONFIG_MTD +/* Set the root filesystem to be the given memory region. + Some parameter may be appended to CMD_LINE. */ +void set_mem_root (void *addr, size_t len, char *cmd_line) +{ + /* The only way to pass info to the MTD slram driver is via + the command line. */ + if (*cmd_line) { + cmd_line += strlen (cmd_line); + *cmd_line++ = ' '; + } + sprintf (cmd_line, "slram=root,0x%x,+0x%x", (u32)addr, (u32)len); + + ROOT_DEV = MKDEV (MTD_BLOCK_MAJOR, 0); +} +#endif + + +static void irq_nop (unsigned irq) { } +static unsigned irq_zero (unsigned irq) { return 0; } + +static void nmi_end (unsigned irq) +{ + if (irq != IRQ_NMI (0)) { + printk (KERN_CRIT "NMI %d is unrecoverable; restarting...", + irq - IRQ_NMI (0)); + machine_restart (0); + } +} + +static struct hw_interrupt_type nmi_irq_type = { + "NMI", + irq_zero, /* startup */ + irq_nop, /* shutdown */ + irq_nop, /* enable */ + irq_nop, /* disable */ + irq_nop, /* ack */ + nmi_end, /* end */ +}; + +void __init init_IRQ (void) +{ + init_irq_handlers (0, NUM_MACH_IRQS, 1, 0); + init_irq_handlers (IRQ_NMI (0), NUM_NMIS, 1, &nmi_irq_type); + mach_init_irqs (); +} + + +void __init mem_init (void) +{ + max_mapnr = MAP_NR (ram_start + ram_len); + + num_physpages = ADDR_TO_PAGE (ram_len); + + total_ram_pages = free_all_bootmem (); + + printk (KERN_INFO + "Memory: %luK/%luK available" + " (%luK kernel code, %luK data)\n", + PAGE_TO_ADDR (nr_free_pages()) / 1024, + ram_len / 1024, + ((unsigned long)&_etext - (unsigned long)&_stext) / 1024, + ((unsigned long)&_ebss - (unsigned long)&_sdata) / 1024); +} + +void free_initmem (void) +{ + unsigned long ram_end = ram_start + ram_len; + unsigned long start = PAGE_ALIGN ((unsigned long)(&_init_start)); + + if (start >= ram_start && start < ram_end) { + unsigned long addr; + unsigned long end = PAGE_ALIGN ((unsigned long)(&_init_end)); + + if (end > ram_end) + end = ram_end; + + printk("Freeing unused kernel memory: %ldK freed\n", + (end - start) / 1024); + + for (addr = start; addr < end; addr += PAGE_SIZE) { + struct page *page = virt_to_page (addr); + ClearPageReserved (page); + set_page_count (page, 1); + __free_page (page); + total_ram_pages++; + } + } +} + + +/* Initialize the `bootmem allocator'. RAM_START and RAM_LEN identify + what RAM may be used. */ +static void __init +init_bootmem_alloc (unsigned long ram_start, unsigned long ram_len) +{ + /* The part of the kernel that's in the same managed RAM space + used for general allocation. */ + unsigned long kram_start = (unsigned long)&_kram_start; + unsigned long kram_end = (unsigned long)&_kram_end; + /* End of the managed RAM space. */ + unsigned long ram_end = ram_start + ram_len; + /* Address range of the interrupt vector table. */ + unsigned long intv_start = (unsigned long)&_intv_start; + unsigned long intv_end = (unsigned long)&_intv_end; + /* True if the interrupt vectors are in the managed RAM area. */ + int intv_in_ram = (intv_end > ram_start && intv_start < ram_end); + /* True if the interrupt vectors are inside the kernel's RAM. */ + int intv_in_kram = (intv_end > kram_start && intv_start < kram_end); + /* A pointer to an optional function that reserves platform-specific + memory regions. We declare the pointer `volatile' to avoid gcc + turning the call into a static call (the problem is that since + it's a weak symbol, a static call may end up trying to reference + the location 0x0, which is not always reachable). */ + void (*volatile mrb) (void) = mach_reserve_bootmem; + /* The bootmem allocator's allocation bitmap. */ + unsigned long bootmap = (unsigned long)&_bootmap; + unsigned long bootmap_len; + + /* Round bootmap location up to next page. */ + bootmap = PAGE_TO_ADDR (ADDR_TO_PAGE_UP (bootmap)); + + /* Initialize bootmem allocator. */ + bootmap_len = init_bootmem_node (NODE_DATA (0), + ADDR_TO_PAGE (bootmap), + ADDR_TO_PAGE (PAGE_OFFSET), + ADDR_TO_PAGE (ram_end)); + + /* Now make the RAM actually allocatable (it starts out `reserved'). */ + free_bootmem (ram_start, ram_len); + + if (kram_end > kram_start) + /* Reserve the RAM part of the kernel's address space, so it + doesn't get allocated. */ + reserve_bootmem (kram_start, kram_end - kram_start); + + if (intv_in_ram && !intv_in_kram) + /* Reserve the interrupt vector space. */ + reserve_bootmem (intv_start, intv_end - intv_start); + + if (bootmap >= ram_start && bootmap < ram_end) + /* Reserve the bootmap space. */ + reserve_bootmem (bootmap, bootmap_len); + + /* Reserve the memory used by the root filesystem image if it's + in RAM. */ + if (&_root_fs_image_end > &_root_fs_image_start + && (unsigned long)&_root_fs_image_start >= ram_start + && (unsigned long)&_root_fs_image_start < ram_end) + reserve_bootmem ((unsigned long)&_root_fs_image_start, + &_root_fs_image_end - &_root_fs_image_start); + + /* Let the platform-dependent code reserve some too. */ + if (mrb) + (*mrb) (); +} + +/* Tell the kernel about what RAM it may use for memory allocation. */ +static void __init +init_mem_alloc (unsigned long ram_start, unsigned long ram_len) +{ + unsigned i; + unsigned long zones_size[MAX_NR_ZONES]; + + init_bootmem_alloc (ram_start, ram_len); + + for (i = 0; i < MAX_NR_ZONES; i++) + zones_size[i] = 0; + + /* We stuff all the memory into one area, which includes the + initial gap from PAGE_OFFSET to ram_start. */ + zones_size[ZONE_DMA] + = ADDR_TO_PAGE (ram_len + (ram_start - PAGE_OFFSET)); + + free_area_init_node (0, NODE_DATA(0), 0, zones_size, + ADDR_TO_PAGE (PAGE_OFFSET), 0); + mem_map = NODE_DATA(0)->node_mem_map; +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/v850/kernel/signal.c linux.2.5.45-ac1/arch/v850/kernel/signal.c --- linux.2.5.45/arch/v850/kernel/signal.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/v850/kernel/signal.c 2002-11-01 15:20:35.000000000 +0000 @@ -0,0 +1,523 @@ +/* + * arch/v850/kernel/signal.c -- Signal handling + * + * Copyright (C) 2001,02 NEC Corporation + * Copyright (C) 2001,02 Miles Bader + * Copyright (C) 1999,2000,2002 Niibe Yutaka & Kaz Kojima + * Copyright (C) 1991,1992 Linus Torvalds + * + * 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. + * + * 1997-11-28 Modified for POSIX.1b signals by Richard Henderson + * + * This file was derived from the sh version, arch/sh/kernel/signal.c + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#define DEBUG_SIG 0 + +#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) + +asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset); + +/* + * Atomically swap in the new signal mask, and wait for a signal. + */ +asmlinkage int +sys_sigsuspend(old_sigset_t mask, struct pt_regs *regs) +{ + sigset_t saveset; + + mask &= _BLOCKABLE; + spin_lock_irq(¤t->sig->siglock); + saveset = current->blocked; + siginitset(¤t->blocked, mask); + recalc_sigpending(); + spin_unlock_irq(¤t->sig->siglock); + + regs->gpr[GPR_RVAL] = -EINTR; + while (1) { + current->state = TASK_INTERRUPTIBLE; + schedule(); + if (do_signal(regs, &saveset)) + return -EINTR; + } +} + +asmlinkage int +sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize, + struct pt_regs *regs) +{ + sigset_t saveset, newset; + + /* XXX: Don't preclude handling different sized sigset_t's. */ + if (sigsetsize != sizeof(sigset_t)) + return -EINVAL; + + if (copy_from_user(&newset, unewset, sizeof(newset))) + return -EFAULT; + sigdelsetmask(&newset, ~_BLOCKABLE); + spin_lock_irq(¤t->sig->siglock); + saveset = current->blocked; + current->blocked = newset; + recalc_sigpending(); + spin_unlock_irq(¤t->sig->siglock); + + regs->gpr[GPR_RVAL] = -EINTR; + while (1) { + current->state = TASK_INTERRUPTIBLE; + schedule(); + if (do_signal(regs, &saveset)) + return -EINTR; + } +} + +asmlinkage int +sys_sigaction(int sig, const struct old_sigaction *act, + struct old_sigaction *oact) +{ + struct k_sigaction new_ka, old_ka; + int ret; + + if (act) { + old_sigset_t mask; + if (verify_area(VERIFY_READ, act, sizeof(*act)) || + __get_user(new_ka.sa.sa_handler, &act->sa_handler) || + __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) + return -EFAULT; + __get_user(new_ka.sa.sa_flags, &act->sa_flags); + __get_user(mask, &act->sa_mask); + siginitset(&new_ka.sa.sa_mask, mask); + } + + ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); + + if (!ret && oact) { + if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) || + __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || + __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) + return -EFAULT; + __put_user(old_ka.sa.sa_flags, &oact->sa_flags); + __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); + } + + return ret; +} + +asmlinkage int +sys_sigaltstack(const stack_t *uss, stack_t *uoss, + struct pt_regs *regs) +{ + return do_sigaltstack(uss, uoss, regs->gpr[GPR_SP]); +} + + +/* + * Do a signal return; undo the signal stack. + */ + +struct sigframe +{ + struct sigcontext sc; + unsigned long extramask[_NSIG_WORDS-1]; + unsigned long tramp[2]; /* signal trampoline */ +}; + +struct rt_sigframe +{ + struct siginfo *pinfo; + void *puc; + struct siginfo info; + struct ucontext uc; + unsigned long tramp[2]; /* signal trampoline */ +}; + +static int +restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc, int *rval_p) +{ + unsigned int err = 0; + +#define COPY(x) err |= __get_user(regs->x, &sc->regs.x) + COPY(gpr[0]); COPY(gpr[1]); COPY(gpr[2]); COPY(gpr[3]); + COPY(gpr[4]); COPY(gpr[5]); COPY(gpr[6]); COPY(gpr[7]); + COPY(gpr[8]); COPY(gpr[9]); COPY(gpr[10]); COPY(gpr[11]); + COPY(gpr[12]); COPY(gpr[13]); COPY(gpr[14]); COPY(gpr[15]); + COPY(gpr[16]); COPY(gpr[17]); COPY(gpr[18]); COPY(gpr[19]); + COPY(gpr[20]); COPY(gpr[21]); COPY(gpr[22]); COPY(gpr[23]); + COPY(gpr[24]); COPY(gpr[25]); COPY(gpr[26]); COPY(gpr[27]); + COPY(gpr[28]); COPY(gpr[29]); COPY(gpr[30]); COPY(gpr[31]); + COPY(pc); COPY(psw); + COPY(ctpc); COPY(ctpsw); COPY(ctbp); +#undef COPY + + return err; +} + +asmlinkage int sys_sigreturn(struct pt_regs *regs) +{ + struct sigframe *frame = (struct sigframe *)regs->gpr[GPR_SP]; + sigset_t set; + int rval; + + if (verify_area(VERIFY_READ, frame, sizeof(*frame))) + goto badframe; + + if (__get_user(set.sig[0], &frame->sc.oldmask) + || (_NSIG_WORDS > 1 + && __copy_from_user(&set.sig[1], &frame->extramask, + sizeof(frame->extramask)))) + goto badframe; + + sigdelsetmask(&set, ~_BLOCKABLE); + spin_lock_irq(¤t->sig->siglock); + current->blocked = set; + recalc_sigpending(); + spin_unlock_irq(¤t->sig->siglock); + + if (restore_sigcontext(regs, &frame->sc, &rval)) + goto badframe; + return rval; + +badframe: + force_sig(SIGSEGV, current); + return 0; +} + +asmlinkage int sys_rt_sigreturn(struct pt_regs *regs) +{ + struct rt_sigframe *frame = (struct rt_sigframe *)regs->gpr[GPR_SP]; + sigset_t set; + stack_t st; + int rval; + + if (verify_area(VERIFY_READ, frame, sizeof(*frame))) + goto badframe; + + if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) + goto badframe; + + sigdelsetmask(&set, ~_BLOCKABLE); + spin_lock_irq(¤t->sig->siglock); + current->blocked = set; + recalc_sigpending(); + spin_unlock_irq(¤t->sig->siglock); + + if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &rval)) + goto badframe; + + if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st))) + goto badframe; + /* It is more difficult to avoid calling this function than to + call it and ignore errors. */ + do_sigaltstack(&st, NULL, regs->gpr[GPR_SP]); + + return rval; + +badframe: + force_sig(SIGSEGV, current); + return 0; +} + +/* + * Set up a signal frame. + */ + +static int +setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs, + unsigned long mask) +{ + int err = 0; + +#define COPY(x) err |= __put_user(regs->x, &sc->regs.x) + COPY(gpr[0]); COPY(gpr[1]); COPY(gpr[2]); COPY(gpr[3]); + COPY(gpr[4]); COPY(gpr[5]); COPY(gpr[6]); COPY(gpr[7]); + COPY(gpr[8]); COPY(gpr[9]); COPY(gpr[10]); COPY(gpr[11]); + COPY(gpr[12]); COPY(gpr[13]); COPY(gpr[14]); COPY(gpr[15]); + COPY(gpr[16]); COPY(gpr[17]); COPY(gpr[18]); COPY(gpr[19]); + COPY(gpr[20]); COPY(gpr[21]); COPY(gpr[22]); COPY(gpr[23]); + COPY(gpr[24]); COPY(gpr[25]); COPY(gpr[26]); COPY(gpr[27]); + COPY(gpr[28]); COPY(gpr[29]); COPY(gpr[30]); COPY(gpr[31]); + COPY(pc); COPY(psw); + COPY(ctpc); COPY(ctpsw); COPY(ctbp); +#undef COPY + + err |= __put_user(mask, &sc->oldmask); + + return err; +} + +/* + * Determine which stack to use.. + */ +static inline void * +get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) +{ + /* Default to using normal stack */ + unsigned long sp = regs->gpr[GPR_SP]; + + if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! on_sig_stack(sp)) + sp = current->sas_ss_sp + current->sas_ss_size; + + return (void *)((sp - frame_size) & -8UL); +} + +static void setup_frame(int sig, struct k_sigaction *ka, + sigset_t *set, struct pt_regs *regs) +{ + struct sigframe *frame; + int err = 0; + int signal; + + frame = get_sigframe(ka, regs, sizeof(*frame)); + + if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) + goto give_sigsegv; + + signal = current_thread_info()->exec_domain + && current_thread_info()->exec_domain->signal_invmap + && sig < 32 + ? current_thread_info()->exec_domain->signal_invmap[sig] + : sig; + + err |= setup_sigcontext(&frame->sc, regs, set->sig[0]); + + if (_NSIG_WORDS > 1) { + err |= __copy_to_user(frame->extramask, &set->sig[1], + sizeof(frame->extramask)); + } + + /* Set up to return from userspace. If provided, use a stub + already in userspace. */ + if (ka->sa.sa_flags & SA_RESTORER) { + regs->gpr[GPR_LP] = (unsigned long) ka->sa.sa_restorer; + } else { + /* Note, these encodings are _little endian_! */ + + /* addi __NR_sigreturn, r0, r12 */ + err |= __put_user(0x6600 | (__NR_sigreturn << 16), + frame->tramp + 0); + /* trap 0 */ + err |= __put_user(0x010007e0, + frame->tramp + 1); + + regs->gpr[GPR_LP] = (unsigned long)frame->tramp; + + flush_cache_sigtramp (regs->gpr[GPR_LP]); + } + + if (err) + goto give_sigsegv; + + /* Set up registers for signal handler */ + regs->gpr[GPR_SP] = (unsigned long) frame; + regs->gpr[GPR_ARG0] = signal; /* Arg for signal handler */ + regs->pc = (unsigned long) ka->sa.sa_handler; + + set_fs(USER_DS); + +#if DEBUG_SIG + printk("SIG deliver (%s:%d): sp=%p pc=%08lx ra=%08lx\n", + current->comm, current->pid, frame, regs->pc, ); +#endif + + return; + +give_sigsegv: + if (sig == SIGSEGV) + ka->sa.sa_handler = SIG_DFL; + force_sig(SIGSEGV, current); +} + +static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, + sigset_t *set, struct pt_regs *regs) +{ + struct rt_sigframe *frame; + int err = 0; + int signal; + + frame = get_sigframe(ka, regs, sizeof(*frame)); + + if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) + goto give_sigsegv; + + signal = current_thread_info()->exec_domain + && current_thread_info()->exec_domain->signal_invmap + && sig < 32 + ? current_thread_info()->exec_domain->signal_invmap[sig] + : sig; + + err |= __put_user(&frame->info, &frame->pinfo); + err |= __put_user(&frame->uc, &frame->puc); + err |= copy_siginfo_to_user(&frame->info, info); + + /* Create the ucontext. */ + err |= __put_user(0, &frame->uc.uc_flags); + err |= __put_user(0, &frame->uc.uc_link); + err |= __put_user((void *)current->sas_ss_sp, + &frame->uc.uc_stack.ss_sp); + err |= __put_user(sas_ss_flags(regs->gpr[GPR_SP]), + &frame->uc.uc_stack.ss_flags); + err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); + err |= setup_sigcontext(&frame->uc.uc_mcontext, + regs, set->sig[0]); + err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); + + /* Set up to return from userspace. If provided, use a stub + already in userspace. */ + if (ka->sa.sa_flags & SA_RESTORER) { + regs->gpr[GPR_LP] = (unsigned long) ka->sa.sa_restorer; + } else { + /* Note, these encodings are _little endian_! */ + + /* addi __NR_sigreturn, r0, r12 */ + err |= __put_user(0x6600 | (__NR_sigreturn << 16), + frame->tramp + 0); + /* trap 0 */ + err |= __put_user(0x010007e0, + frame->tramp + 1); + + regs->gpr[GPR_LP] = (unsigned long)frame->tramp; + + flush_cache_sigtramp (regs->gpr[GPR_LP]); + } + + if (err) + goto give_sigsegv; + + /* Set up registers for signal handler */ + regs->gpr[GPR_SP] = (unsigned long) frame; + regs->gpr[GPR_ARG0] = signal; /* Arg for signal handler */ + regs->pc = (unsigned long) ka->sa.sa_handler; + + set_fs(USER_DS); + +#if DEBUG_SIG + printk("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n", + current->comm, current->pid, frame, regs->pc, regs->pr); +#endif + + return; + +give_sigsegv: + if (sig == SIGSEGV) + ka->sa.sa_handler = SIG_DFL; + force_sig(SIGSEGV, current); +} + +/* + * OK, we're invoking a handler + */ + +static void +handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset, + struct pt_regs * regs) +{ + struct k_sigaction *ka = ¤t->sig->action[sig-1]; + + /* Are we from a system call? */ + if (PT_REGS_SYSCALL (regs)) { + /* If so, check system call restarting.. */ + switch (regs->gpr[GPR_RVAL]) { + case -ERESTARTNOHAND: + regs->gpr[GPR_RVAL] = -EINTR; + break; + + case -ERESTARTSYS: + if (!(ka->sa.sa_flags & SA_RESTART)) { + regs->gpr[GPR_RVAL] = -EINTR; + break; + } + /* fallthrough */ + case -ERESTARTNOINTR: + regs->gpr[12] = PT_REGS_SYSCALL (regs); + regs->pc -= 4; /* Size of `trap 0' insn. */ + } + + PT_REGS_SET_SYSCALL (regs, 0); + } + + /* Set up the stack frame */ + if (ka->sa.sa_flags & SA_SIGINFO) + setup_rt_frame(sig, ka, info, oldset, regs); + else + setup_frame(sig, ka, oldset, regs); + + if (ka->sa.sa_flags & SA_ONESHOT) + ka->sa.sa_handler = SIG_DFL; + + if (!(ka->sa.sa_flags & SA_NODEFER)) { + spin_lock_irq(¤t->sig->siglock); + sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); + sigaddset(¤t->blocked,sig); + recalc_sigpending(); + spin_unlock_irq(¤t->sig->siglock); + } +} + +/* + * Note that 'init' is a special process: it doesn't get signals it doesn't + * want to handle. Thus you cannot kill init even with a SIGKILL even by + * mistake. + * + * Note that we go through the signals twice: once to check the signals that + * the kernel can handle, and then we build all the user-level signal handling + * stack-frames in one go after that. + */ +int do_signal(struct pt_regs *regs, sigset_t *oldset) +{ + siginfo_t info; + int signr; + + /* + * We want the common case to go fast, which + * is why we may in certain cases get here from + * kernel mode. Just return without doing anything + * if so. + */ + if (!user_mode(regs)) + return 1; + + if (!oldset) + oldset = ¤t->blocked; + + signr = get_signal_to_deliver(&info, regs); + if (signr > 0) { + /* Whee! Actually deliver the signal. */ + handle_signal(signr, &info, oldset, regs); + return 1; + } + + /* Did we come from a system call? */ + if (PT_REGS_SYSCALL (regs)) { + /* Restart the system call - no handlers present */ + if (regs->gpr[GPR_RVAL] == -ERESTARTNOHAND || + regs->gpr[GPR_RVAL] == -ERESTARTSYS || + regs->gpr[GPR_RVAL] == -ERESTARTNOINTR) { + regs->gpr[12] = PT_REGS_SYSCALL (regs); + regs->pc -= 4; /* Size of `trap 0' insn. */ + } + } + return 0; +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/v850/kernel/sim85e2c.c linux.2.5.45-ac1/arch/v850/kernel/sim85e2c.c --- linux.2.5.45/arch/v850/kernel/sim85e2c.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/v850/kernel/sim85e2c.c 2002-11-01 15:20:35.000000000 +0000 @@ -0,0 +1,147 @@ +/* + * arch/v850/kernel/sim85e2c.c -- Machine-specific stuff for + * V850E2 RTL simulator + * + * Copyright (C) 2002 NEC Corporation + * Copyright (C) 2002 Miles Bader + * + * 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. + * + * Written by Miles Bader + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "mach.h" + +extern void memcons_setup (void); + + +void __init mach_early_init (void) +{ + extern int panic_timeout; + + /* Don't stop the simulator at `halt' instructions. */ + NOTHAL = 1; + + /* The sim85e2c simulator tracks `undefined' values, so to make + debugging easier, we begin by zeroing out all otherwise + undefined registers. This is not strictly necessary. + + The registers we zero are: + Every GPR except: + stack-pointer (r3) + task-pointer (r16) + our return addr (r31) + Every system register (SPR) that we know about except for + the PSW (SPR 5), which we zero except for the + disable-interrupts bit. + */ + + /* GPRs */ + asm volatile (" mov r0, r1 ; mov r0, r2 "); + asm volatile ("mov r0, r4 ; mov r0, r5 ; mov r0, r6 ; mov r0, r7 "); + asm volatile ("mov r0, r8 ; mov r0, r9 ; mov r0, r10; mov r0, r11"); + asm volatile ("mov r0, r12; mov r0, r13; mov r0, r14; mov r0, r15"); + asm volatile (" mov r0, r17; mov r0, r18; mov r0, r19"); + asm volatile ("mov r0, r20; mov r0, r21; mov r0, r22; mov r0, r23"); + asm volatile ("mov r0, r24; mov r0, r25; mov r0, r26; mov r0, r27"); + asm volatile ("mov r0, r28; mov r0, r29; mov r0, r30"); + + /* SPRs */ + asm volatile ("ldsr r0, 0; ldsr r0, 1; ldsr r0, 2; ldsr r0, 3"); + asm volatile ("ldsr r0, 4"); + asm volatile ("addi 0x20, r0, r1; ldsr r1, 5"); /* PSW */ + asm volatile ("ldsr r0, 16; ldsr r0, 17; ldsr r0, 18; ldsr r0, 19"); + asm volatile ("ldsr r0, 20"); + + /* Turn on the caches. */ + NA85E2C_CACHE_BTSC + |= (NA85E2C_CACHE_BTSC_ICM | NA85E2C_CACHE_BTSC_DCM0); + NA85E2C_BUSM_BHC = 0xFFFF; + + /* Ensure that the simulator halts on a panic, instead of going + into an infinite loop inside the panic function. */ + panic_timeout = -1; +} + +void __init mach_setup (char **cmdline) +{ + printk (KERN_INFO "CPU: NEC V850E2 (sim85e2c simulator)\n"); + + memcons_setup (); +} + +void mach_get_physical_ram (unsigned long *ram_start, unsigned long *ram_len) +{ + /* There are 3 possible areas we can use: + IRAM (1MB) is fast for instruction fetches, but slow for data + DRAM (1020KB) is fast for data, but slow for instructions + ERAM is cached, so should be fast for both insns and data, + _but_ currently only supports write-through caching, so + writes are slow. + Since there's really no area that's good for general kernel + use, we use DRAM -- it won't be good for user programs + (which will be loaded into kernel allocated memory), but + currently we're more concerned with testing the kernel. */ + *ram_start = DRAM_ADDR; + *ram_len = R0_RAM_ADDR - DRAM_ADDR; +} + +void __init mach_sched_init (struct irqaction *timer_action) +{ + /* The simulator actually cycles through all interrupts + periodically. We just pay attention to IRQ0, which gives us + 1/64 the rate of the periodic interrupts. */ + setup_irq (0, timer_action); +} + +void mach_gettimeofday (struct timespec *tv) +{ + tv->tv_sec = 0; + tv->tv_nsec = 0; +} + +/* Interrupts */ + +struct nb85e_intc_irq_init irq_inits[] = { + { "IRQ", 0, NUM_MACH_IRQS, 1, 7 }, + { 0 } +}; +struct hw_interrupt_type hw_itypes[1]; + +/* Initialize interrupts. */ +void __init mach_init_irqs (void) +{ + nb85e_intc_init_irq_types (irq_inits, hw_itypes); +} + + +void machine_halt (void) __attribute__ ((noreturn)); +void machine_halt (void) +{ + SIMFIN = 0; /* Halt immediately. */ + for (;;) {} +} + +void machine_restart (char *__unused) +{ + machine_halt (); +} + +void machine_power_off (void) +{ + machine_halt (); +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/v850/kernel/sim.c linux.2.5.45-ac1/arch/v850/kernel/sim.c --- linux.2.5.45/arch/v850/kernel/sim.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/v850/kernel/sim.c 2002-11-01 15:20:35.000000000 +0000 @@ -0,0 +1,174 @@ +/* + * arch/v850/kernel/sim.c -- Machine-specific stuff for GDB v850e simulator + * + * Copyright (C) 2001,02 NEC Corporation + * Copyright (C) 2001,02 Miles Bader + * + * 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. + * + * Written by Miles Bader + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "mach.h" + +/* The name of a file containing the root filesystem. */ +#define ROOT_FS "rootfs.image" + +extern void simcons_setup (void); +extern void simcons_poll_ttys (void); +extern void set_mem_root (void *addr, size_t len, char *cmd_line); + +static int read_file (const char *name, + unsigned long *addr, unsigned long *len, + const char **err); + +void __init mach_setup (char **cmdline) +{ + const char *err; + unsigned long root_dev_addr, root_dev_len; + + printk (KERN_INFO "CPU: NEC V850E (GDB simulator)\n"); + + simcons_setup (); + + printk (KERN_INFO "Reading root filesystem: %s", ROOT_FS); + + if (read_file (ROOT_FS, &root_dev_addr, &root_dev_len, &err)) { + printk (" (size %luK)\n", root_dev_len / 1024); + set_mem_root ((void *)root_dev_addr, (size_t)root_dev_len, + *cmdline); + } else + printk ("...%s failed!\n", err); +} + +void mach_get_physical_ram (unsigned long *ram_start, unsigned long *ram_len) +{ + *ram_start = RAM_ADDR; + *ram_len = RAM_SIZE; +} + +void __init mach_sched_init (struct irqaction *timer_action) +{ + /* ...do magic timer initialization?... */ + mach_tick = simcons_poll_ttys; + setup_irq (0, timer_action); +} + + +static void irq_nop (unsigned irq) { } +static unsigned irq_zero (unsigned irq) { return 0; } + +static struct hw_interrupt_type sim_irq_type = { + "IRQ", + irq_zero, /* startup */ + irq_nop, /* shutdown */ + irq_nop, /* enable */ + irq_nop, /* disable */ + irq_nop, /* ack */ + irq_nop, /* end */ +}; + +void __init mach_init_irqs (void) +{ + init_irq_handlers (0, NUM_MACH_IRQS, 1, &sim_irq_type); +} + + +void mach_gettimeofday (struct timespec *tv) +{ + long timeval[2], timezone[2]; + int rval = V850_SIM_SYSCALL (gettimeofday, timeval, timezone); + if (rval == 0) { + tv->tv_sec = timeval[0]; + tv->tv_nsec = timeval[1] * 1000; + } +} + +void machine_restart (char *__unused) +{ + V850_SIM_SYSCALL (write, 1, "RESTART\n", 8); + V850_SIM_SYSCALL (exit, 0); +} + +void machine_halt (void) +{ + V850_SIM_SYSCALL (write, 1, "HALT\n", 5); + V850_SIM_SYSCALL (exit, 0); +} + +void machine_power_off (void) +{ + V850_SIM_SYSCALL (write, 1, "POWER OFF\n", 10); + V850_SIM_SYSCALL (exit, 0); +} + + +/* Load data from a file called NAME into ram. The address and length + of the data image are returned in ADDR and LEN. */ +static int __init +read_file (const char *name, + unsigned long *addr, unsigned long *len, + const char **err) +{ + int rval, fd; + unsigned long cur, left; + /* Note this is not a normal stat buffer, it's an ad-hoc + structure defined by the simulator. */ + unsigned long stat_buf[10]; + + /* Stat the file to find out the length. */ + rval = V850_SIM_SYSCALL (stat, name, stat_buf); + if (rval < 0) { + if (err) *err = "stat"; + return 0; + } + *len = stat_buf[4]; + + /* Open the file; `0' is O_RDONLY. */ + fd = V850_SIM_SYSCALL (open, name, 0); + if (fd < 0) { + if (err) *err = "open"; + return 0; + } + + *addr = (unsigned long)alloc_bootmem(*len); + if (! *addr) { + V850_SIM_SYSCALL (close, fd); + if (err) *err = "alloc_bootmem"; + return 0; + } + + cur = *addr; + left = *len; + while (left > 0) { + int chunk = V850_SIM_SYSCALL (read, fd, cur, left); + if (chunk <= 0) + break; + cur += chunk; + left -= chunk; + } + V850_SIM_SYSCALL (close, fd); + if (left > 0) { + /* Some read failed. */ + free_bootmem (*addr, *len); + if (err) *err = "read"; + return 0; + } + + return 1; +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/v850/kernel/simcons.c linux.2.5.45-ac1/arch/v850/kernel/simcons.c --- linux.2.5.45/arch/v850/kernel/simcons.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/v850/kernel/simcons.c 2002-11-01 15:20:35.000000000 +0000 @@ -0,0 +1,158 @@ +/* + * arch/v850/kernel/simcons.c -- Console I/O for GDB v850e simulator + * + * Copyright (C) 2001,02 NEC Corporation + * Copyright (C) 2001,02 Miles Bader + * + * 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. + * + * Written by Miles Bader + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + + +/* Low-level console. */ + +static void simcons_write (struct console *co, const char *buf, unsigned len) +{ + V850_SIM_SYSCALL (write, 1, buf, len); +} + +static int simcons_read (struct console *co, const char *buf, unsigned len) +{ + return V850_SIM_SYSCALL (read, 0, buf, len); +} + +static kdev_t simcons_device (struct console *c) +{ + return mk_kdev (TTY_MAJOR, 64 + c->index); +} + +static struct console simcons = +{ + .name = "simcons", + .write = simcons_write, + .read = simcons_read, + .device = simcons_device, + .flags = CON_PRINTBUFFER, + .index = -1, +}; + +/* Higher level TTY interface. */ + +static struct tty_struct *tty_table[1] = { 0 }; +static struct termios *tty_termios[1] = { 0 }; +static struct termios *tty_termios_locked[1] = { 0 }; +static struct tty_driver tty_driver = { 0 }; +static int tty_refcount = 0; + +int simcons_tty_open (struct tty_struct *tty, struct file *filp) +{ + return 0; +} + +int simcons_tty_write (struct tty_struct *tty, int from_user, + const unsigned char *buf, int count) +{ + return V850_SIM_SYSCALL (write, 1, buf, count); +} + +int simcons_tty_write_room (struct tty_struct *tty) +{ + /* Completely arbitrary. */ + return 0x100000; +} + +int simcons_tty_chars_in_buffer (struct tty_struct *tty) +{ + /* We have no buffer. */ + return 0; +} + +int __init simcons_tty_init (void) +{ + tty_driver.name = "simcons"; + tty_driver.major = TTY_MAJOR; + tty_driver.minor_start = 64; + tty_driver.num = 1; + tty_driver.type = TTY_DRIVER_TYPE_SYSCONS; + + tty_driver.refcount = &tty_refcount; + + tty_driver.table = tty_table; + tty_driver.termios = tty_termios; + tty_driver.termios_locked = tty_termios_locked; + + tty_driver.init_termios = tty_std_termios; + + tty_driver.open = simcons_tty_open; + tty_driver.write = simcons_tty_write; + tty_driver.write_room = simcons_tty_write_room; + tty_driver.chars_in_buffer = simcons_tty_chars_in_buffer; + + tty_register_driver (&tty_driver); +} +__initcall (simcons_tty_init); + +/* Poll for input on the console, and if there's any, deliver it to the + tty driver. */ +void simcons_poll_tty (struct tty_struct *tty) +{ + int flip = 0, send_break = 0; + struct pollfd pfd; + pfd.fd = 0; + pfd.events = POLLIN; + + if (V850_SIM_SYSCALL (poll, &pfd, 1, 0) > 0) { + if (pfd.revents & POLLIN) { + int left = TTY_FLIPBUF_SIZE - tty->flip.count; + + if (left > 0) { + unsigned char *buf = tty->flip.char_buf_ptr; + int rd = V850_SIM_SYSCALL (read, 0, buf, left); + + if (rd > 0) { + tty->flip.count += rd; + tty->flip.char_buf_ptr += rd; + memset (tty->flip.flag_buf_ptr, 0, rd); + tty->flip.flag_buf_ptr += rd; + flip = 1; + } else + send_break = 1; + } + } else if (pfd.revents & POLLERR) + send_break = 1; + } + + if (send_break) { + tty_insert_flip_char (tty, 0, TTY_BREAK); + flip = 1; + } + + if (flip) + tty_schedule_flip (tty); +} + +void simcons_poll_ttys (void) +{ + if (tty_table[0]) + simcons_poll_tty (tty_table[0]); +} + +void simcons_setup (void) +{ + V850_SIM_SYSCALL (make_raw, 0); + register_console (&simcons); + printk (KERN_INFO "Console: GDB/v850e simulator stdio\n"); +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/v850/kernel/syscalls.c linux.2.5.45-ac1/arch/v850/kernel/syscalls.c --- linux.2.5.45/arch/v850/kernel/syscalls.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/v850/kernel/syscalls.c 2002-11-01 15:20:35.000000000 +0000 @@ -0,0 +1,197 @@ +/* + * arch/v850/kernel/syscalls.c -- Various system-call definitions not + * defined in machine-independent code + * + * Copyright (C) 2001,02 NEC Corporation + * Copyright (C) 2001,02 Miles Bader + * + * 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. + * + * This file was derived the ppc version, arch/ppc/kernel/syscalls.c + * ... which was derived from "arch/i386/kernel/sys_i386.c" by Gary Thomas; + * modified by Cort Dougan (cort@cs.nmt.edu) + * and Paul Mackerras (paulus@cs.anu.edu.au). + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* + * sys_ipc() is the de-multiplexer for the SysV IPC calls.. + * + * This is really horribly ugly. + */ +int +sys_ipc (uint call, int first, int second, int third, void *ptr, long fifth) +{ + int version, ret; + + version = call >> 16; /* hack for backward compatibility */ + call &= 0xffff; + + ret = -EINVAL; + switch (call) { + case SEMOP: + ret = sys_semop (first, (struct sembuf *)ptr, second); + break; + case SEMGET: + ret = sys_semget (first, second, third); + break; + case SEMCTL: + { + union semun fourth; + + if (!ptr) + break; + if ((ret = verify_area (VERIFY_READ, ptr, sizeof(long))) + || (ret = get_user(fourth.__pad, (void **)ptr))) + break; + ret = sys_semctl (first, second, third, fourth); + break; + } + case MSGSND: + ret = sys_msgsnd (first, (struct msgbuf *) ptr, second, third); + break; + case MSGRCV: + switch (version) { + case 0: { + struct ipc_kludge tmp; + + if (!ptr) + break; + if ((ret = verify_area (VERIFY_READ, ptr, sizeof(tmp))) + || (ret = copy_from_user(&tmp, + (struct ipc_kludge *) ptr, + sizeof (tmp)))) + break; + ret = sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp, + third); + break; + } + default: + ret = sys_msgrcv (first, (struct msgbuf *) ptr, + second, fifth, third); + break; + } + break; + case MSGGET: + ret = sys_msgget ((key_t) first, second); + break; + case MSGCTL: + ret = sys_msgctl (first, second, (struct msqid_ds *) ptr); + break; + case SHMAT: + switch (version) { + default: { + ulong raddr; + + if ((ret = verify_area(VERIFY_WRITE, (ulong*) third, + sizeof(ulong)))) + break; + ret = sys_shmat (first, (char *) ptr, second, &raddr); + if (ret) + break; + ret = put_user (raddr, (ulong *) third); + break; + } + case 1: /* iBCS2 emulator entry point */ + if (!segment_eq(get_fs(), get_ds())) + break; + ret = sys_shmat (first, (char *) ptr, second, + (ulong *) third); + break; + } + break; + case SHMDT: + ret = sys_shmdt ((char *)ptr); + break; + case SHMGET: + ret = sys_shmget (first, second, third); + break; + case SHMCTL: + ret = sys_shmctl (first, second, (struct shmid_ds *) ptr); + break; + } + + return ret; +} + +/* + * sys_pipe() is the normal C calling standard for creating + * a pipe. It's not the way unix traditionally does this, though. + */ +int sys_pipe (int *fildes) +{ + int fd[2]; + int error; + + error = do_pipe (fd); + if (!error) { + if (copy_to_user (fildes, fd, 2*sizeof (int))) + error = -EFAULT; + } + return error; +} + +static inline unsigned long +do_mmap2 (unsigned long addr, size_t len, + unsigned long prot, unsigned long flags, + unsigned long fd, unsigned long pgoff) +{ + struct file * file = NULL; + int ret = -EBADF; + + flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); + if (! (flags & MAP_ANONYMOUS)) { + if (!(file = fget (fd))) + goto out; + } + + down_write (¤t->mm->mmap_sem); + ret = do_mmap_pgoff (file, addr, len, prot, flags, pgoff); + up_write (¤t->mm->mmap_sem); + if (file) + fput (file); +out: + return ret; +} + +unsigned long sys_mmap2 (unsigned long addr, size_t len, + unsigned long prot, unsigned long flags, + unsigned long fd, unsigned long pgoff) +{ + return do_mmap2 (addr, len, prot, flags, fd, pgoff); +} + +unsigned long sys_mmap (unsigned long addr, size_t len, + unsigned long prot, unsigned long flags, + unsigned long fd, off_t offset) +{ + int err = -EINVAL; + + if (offset & ~PAGE_MASK) + goto out; + + err = do_mmap2 (addr, len, prot, flags, fd, offset >> PAGE_SHIFT); +out: + return err; +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/v850/kernel/time.c linux.2.5.45-ac1/arch/v850/kernel/time.c --- linux.2.5.45/arch/v850/kernel/time.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/v850/kernel/time.c 2002-11-01 15:20:35.000000000 +0000 @@ -0,0 +1,193 @@ +/* + * linux/arch/v850/kernel/time.c -- Arch-dependent timer functions + * + * Copyright (C) 1991, 1992, 1995, 2001, 2002 Linus Torvalds + * + * This file contains the v850-specific time handling details. + * Most of the stuff is located in the machine specific files. + * + * 1997-09-10 Updated NTP code according to technical memorandum Jan '96 + * "A Kernel Model for Precision Timekeeping" by Dave Mills + */ + +#include /* CONFIG_HEARTBEAT */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "mach.h" + +u64 jiffies_64; + +#define TICK_SIZE (tick_nsec / 1000) + +static inline void do_profile (unsigned long pc) +{ + if (prof_buffer && current->pid) { + extern int _stext; + pc -= (unsigned long) &_stext; + pc >>= prof_shift; + if (pc < prof_len) + ++prof_buffer[pc]; + else + /* + * Don't ignore out-of-bounds PC values silently, + * put them into the last histogram slot, so if + * present, they will show up as a sharp peak. + */ + ++prof_buffer[prof_len-1]; + } +} + +/* + * timer_interrupt() needs to keep up the real-time clock, + * as well as call the "do_timer()" routine every clocktick + */ +static void timer_interrupt (int irq, void *dummy, struct pt_regs *regs) +{ +#if 0 + /* last time the cmos clock got updated */ + static long last_rtc_update=0; +#endif + + /* may need to kick the hardware timer */ + if (mach_tick) + mach_tick (); + + do_timer (regs); + + if (! user_mode (regs)) + do_profile (regs->pc); + +#if 0 + /* + * If we have an externally synchronized Linux clock, then update + * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be + * called as close as possible to 500 ms before the new second starts. + */ + if ((time_status & STA_UNSYNC) == 0 && + xtime.tv_sec > last_rtc_update + 660 && + (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 && + (xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) { + if (set_rtc_mmss (xtime.tv_sec) == 0) + last_rtc_update = xtime.tv_sec; + else + last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */ + } +#ifdef CONFIG_HEARTBEAT + /* use power LED as a heartbeat instead -- much more useful + for debugging -- based on the version for PReP by Cort */ + /* acts like an actual heart beat -- ie thump-thump-pause... */ + if (mach_heartbeat) { + static unsigned cnt = 0, period = 0, dist = 0; + + if (cnt == 0 || cnt == dist) + mach_heartbeat ( 1 ); + else if (cnt == 7 || cnt == dist+7) + mach_heartbeat ( 0 ); + + if (++cnt > period) { + cnt = 0; + /* The hyperbolic function below modifies the heartbeat period + * length in dependency of the current (5min) load. It goes + * through the points f(0)=126, f(1)=86, f(5)=51, + * f(inf)->30. */ + period = ((672<= 1000000) { + usec -= 1000000; + sec++; + } + + tv->tv_sec = sec; + tv->tv_usec = usec; +} + +void do_settimeofday (struct timeval *tv) +{ + write_lock_irq (&xtime_lock); + + /* This is revolting. We need to set the xtime.tv_nsec + * correctly. However, the value in this location is + * is value at the last tick. + * Discover what correction gettimeofday + * would have done, and then undo it! + */ +#if 0 + tv->tv_usec -= mach_gettimeoffset (); +#endif + + while (tv->tv_usec < 0) { + tv->tv_usec += 1000000; + tv->tv_sec--; + } + + xtime.tv_sec = tv->tv_sec; + xtime.tv_nsec = tv->tv_usec * 1000; + + time_adjust = 0; /* stop active adjtime () */ + time_status |= STA_UNSYNC; + time_maxerror = NTP_PHASE_LIMIT; + time_esterror = NTP_PHASE_LIMIT; + + write_unlock_irq (&xtime_lock); +} + +static int timer_dev_id; +static struct irqaction timer_irqaction = { + timer_interrupt, + SA_INTERRUPT, + 0, + "timer", + &timer_dev_id, + NULL +}; + +void time_init (void) +{ + mach_gettimeofday (&xtime); + mach_sched_init (&timer_irqaction); +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/v850/kernel/v850_ksyms.c linux.2.5.45-ac1/arch/v850/kernel/v850_ksyms.c --- linux.2.5.45/arch/v850/kernel/v850_ksyms.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/v850/kernel/v850_ksyms.c 2002-11-01 15:20:35.000000000 +0000 @@ -0,0 +1,79 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +extern void *trap_table; +EXPORT_SYMBOL (trap_table); + +/* platform dependent support */ +extern void dump_thread (struct pt_regs *, struct user *); +EXPORT_SYMBOL (dump_thread); +EXPORT_SYMBOL (kernel_thread); +EXPORT_SYMBOL (__bug); + +/* Networking helper routines. */ +EXPORT_SYMBOL (csum_partial_copy); +EXPORT_SYMBOL (csum_partial_copy_from_user); +EXPORT_SYMBOL (ip_compute_csum); +EXPORT_SYMBOL (ip_fast_csum); + +/* string / mem functions */ +EXPORT_SYMBOL_NOVERS (strcpy); +EXPORT_SYMBOL_NOVERS (strncpy); +EXPORT_SYMBOL_NOVERS (strcat); +EXPORT_SYMBOL_NOVERS (strncat); +EXPORT_SYMBOL_NOVERS (strcmp); +EXPORT_SYMBOL_NOVERS (strncmp); +EXPORT_SYMBOL_NOVERS (strchr); +EXPORT_SYMBOL_NOVERS (strlen); +EXPORT_SYMBOL_NOVERS (strnlen); +EXPORT_SYMBOL_NOVERS (strpbrk); +EXPORT_SYMBOL_NOVERS (strtok); +EXPORT_SYMBOL_NOVERS (strrchr); +EXPORT_SYMBOL_NOVERS (strstr); +EXPORT_SYMBOL_NOVERS (memset); +EXPORT_SYMBOL_NOVERS (memcpy); +EXPORT_SYMBOL_NOVERS (memmove); +EXPORT_SYMBOL_NOVERS (memcmp); +EXPORT_SYMBOL_NOVERS (memscan); + +/* semaphores */ +EXPORT_SYMBOL_NOVERS (__down); +EXPORT_SYMBOL_NOVERS (__down_interruptible); +EXPORT_SYMBOL_NOVERS (__down_trylock); +EXPORT_SYMBOL_NOVERS (__up); + +/* + * libgcc functions - functions that are used internally by the + * compiler... (prototypes are not correct though, but that + * doesn't really matter since they're not versioned). + */ +extern void __ashldi3 (void); +extern void __ashrdi3 (void); +extern void __lshrdi3 (void); +extern void __muldi3 (void); +extern void __negdi2 (void); + +EXPORT_SYMBOL_NOVERS (__ashldi3); +EXPORT_SYMBOL_NOVERS (__ashrdi3); +EXPORT_SYMBOL_NOVERS (__lshrdi3); +EXPORT_SYMBOL_NOVERS (__muldi3); +EXPORT_SYMBOL_NOVERS (__negdi2); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/v850/lib/ashldi3.c linux.2.5.45-ac1/arch/v850/lib/ashldi3.c --- linux.2.5.45/arch/v850/lib/ashldi3.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/v850/lib/ashldi3.c 2002-11-01 15:20:35.000000000 +0000 @@ -0,0 +1,62 @@ +/* ashldi3.c extracted from gcc-2.95.2/libgcc2.c which is: */ +/* Copyright (C) 1989, 92-98, 1999 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC 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. + +GNU CC 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 GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#define BITS_PER_UNIT 8 + +typedef int SItype __attribute__ ((mode (SI))); +typedef unsigned int USItype __attribute__ ((mode (SI))); +typedef int DItype __attribute__ ((mode (DI))); +typedef int word_type __attribute__ ((mode (__word__))); + +struct DIstruct {SItype high, low;}; + +typedef union +{ + struct DIstruct s; + DItype ll; +} DIunion; + +DItype +__ashldi3 (DItype u, word_type b) +{ + DIunion w; + word_type bm; + DIunion uu; + + if (b == 0) + return u; + + uu.ll = u; + + bm = (sizeof (SItype) * BITS_PER_UNIT) - b; + if (bm <= 0) + { + w.s.low = 0; + w.s.high = (USItype)uu.s.low << -bm; + } + else + { + USItype carries = (USItype)uu.s.low >> bm; + w.s.low = (USItype)uu.s.low << b; + w.s.high = ((USItype)uu.s.high << b) | carries; + } + + return w.ll; +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/v850/lib/ashrdi3.c linux.2.5.45-ac1/arch/v850/lib/ashrdi3.c --- linux.2.5.45/arch/v850/lib/ashrdi3.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/v850/lib/ashrdi3.c 2002-11-01 15:20:35.000000000 +0000 @@ -0,0 +1,63 @@ +/* ashrdi3.c extracted from gcc-2.7.2/libgcc2.c which is: */ +/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC 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. + +GNU CC 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 GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#define BITS_PER_UNIT 8 + +typedef int SItype __attribute__ ((mode (SI))); +typedef unsigned int USItype __attribute__ ((mode (SI))); +typedef int DItype __attribute__ ((mode (DI))); +typedef int word_type __attribute__ ((mode (__word__))); + +struct DIstruct {SItype high, low;}; + +typedef union +{ + struct DIstruct s; + DItype ll; +} DIunion; + +DItype +__ashrdi3 (DItype u, word_type b) +{ + DIunion w; + word_type bm; + DIunion uu; + + if (b == 0) + return u; + + uu.ll = u; + + bm = (sizeof (SItype) * BITS_PER_UNIT) - b; + if (bm <= 0) + { + /* w.s.high = 1..1 or 0..0 */ + w.s.high = uu.s.high >> (sizeof (SItype) * BITS_PER_UNIT - 1); + w.s.low = uu.s.high >> -bm; + } + else + { + USItype carries = (USItype)uu.s.high << bm; + w.s.high = uu.s.high >> b; + w.s.low = ((USItype)uu.s.low >> b) | carries; + } + + return w.ll; +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/v850/lib/checksum.c linux.2.5.45-ac1/arch/v850/lib/checksum.c --- linux.2.5.45/arch/v850/lib/checksum.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/v850/lib/checksum.c 2002-11-01 15:20:35.000000000 +0000 @@ -0,0 +1,151 @@ +/* + * INET An implementation of the TCP/IP protocol suite for the LINUX + * operating system. INET is implemented using the BSD Socket + * interface as the means of communication with the user level. + * + * MIPS specific IP/TCP/UDP checksumming routines + * + * Authors: Ralf Baechle, + * Lots of code moved from tcp.c and ip.c; see those files + * for more names. + * + * 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. + * + * $Id: checksum.c,v 1.1 2002/09/28 14:58:40 gerg Exp $ + */ +#include +#include +#include +#include +#include + +static inline unsigned short from32to16 (unsigned long sum) +{ + unsigned int result; + /* + %0 %1 + hsw %1, %0 H L L H + add %1, %0 H L H+L+C H+L + */ + asm ("hsw %1, %0; add %1, %0" : "=&r" (result) : "r" (sum)); + return result >> 16; +} + +static inline unsigned int do_csum(const unsigned char * buff, int len) +{ + int odd, count; + unsigned int result = 0; + + if (len <= 0) + goto out; + odd = 1 & (unsigned long) buff; + if (odd) { + result = be16_to_cpu(*buff); + len--; + buff++; + } + count = len >> 1; /* nr of 16-bit words.. */ + if (count) { + if (2 & (unsigned long) buff) { + result += *(unsigned short *) buff; + count--; + len -= 2; + buff += 2; + } + count >>= 1; /* nr of 32-bit words.. */ + if (count) { + unsigned int carry = 0; + do { + unsigned int w = *(unsigned int *) buff; + count--; + buff += 4; + result += carry; + result += w; + carry = (w > result); + } while (count); + result += carry; + result = (result & 0xffff) + (result >> 16); + } + if (len & 2) { + result += *(unsigned short *) buff; + buff += 2; + } + } + if (len & 1) + result += le16_to_cpu(*buff); + result = from32to16(result); + if (odd) + result = ((result >> 8) & 0xff) | ((result & 0xff) << 8); +out: + return result; +} + +/* + * This is a version of ip_compute_csum() optimized for IP headers, + * which always checksum on 4 octet boundaries. + */ +unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl) +{ + return ~do_csum(iph,ihl*4); +} + +/* + * this routine is used for miscellaneous IP-like checksums, mainly + * in icmp.c + */ +unsigned short ip_compute_csum(const unsigned char * buff, int len) +{ + return ~do_csum(buff,len); +} + +/* + * computes a partial checksum, e.g. for TCP/UDP fragments + */ +unsigned int csum_partial(const unsigned char *buff, int len, unsigned int sum) +{ + unsigned int result = do_csum(buff, len); + + /* add in old sum, and carry.. */ + result += sum; + if(sum > result) + result += 1; + return result; +} + +/* + * copy while checksumming, otherwise like csum_partial + */ +unsigned int csum_partial_copy(const char *src, char *dst, + int len, unsigned int sum) +{ + /* + * It's 2:30 am and I don't feel like doing it real ... + * This is lots slower than the real thing (tm) + */ + sum = csum_partial(src, len, sum); + memcpy(dst, src, len); + + return sum; +} + +/* + * Copy from userspace and compute checksum. If we catch an exception + * then zero the rest of the buffer. + */ +unsigned int csum_partial_copy_from_user (const char *src, char *dst, + int len, unsigned int sum, + int *err_ptr) +{ + int missing; + + missing = copy_from_user(dst, src, len); + if (missing) { + memset(dst + len - missing, 0, missing); + *err_ptr = -EFAULT; + } + + return csum_partial(dst, len, sum); +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/v850/lib/lshrdi3.c linux.2.5.45-ac1/arch/v850/lib/lshrdi3.c --- linux.2.5.45/arch/v850/lib/lshrdi3.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/v850/lib/lshrdi3.c 2002-11-01 15:20:35.000000000 +0000 @@ -0,0 +1,62 @@ +/* lshrdi3.c extracted from gcc-2.7.2/libgcc2.c which is: */ +/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC 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. + +GNU CC 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 GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#define BITS_PER_UNIT 8 + +typedef int SItype __attribute__ ((mode (SI))); +typedef unsigned int USItype __attribute__ ((mode (SI))); +typedef int DItype __attribute__ ((mode (DI))); +typedef int word_type __attribute__ ((mode (__word__))); + +struct DIstruct {SItype high, low;}; + +typedef union +{ + struct DIstruct s; + DItype ll; +} DIunion; + +DItype +__lshrdi3 (DItype u, word_type b) +{ + DIunion w; + word_type bm; + DIunion uu; + + if (b == 0) + return u; + + uu.ll = u; + + bm = (sizeof (SItype) * BITS_PER_UNIT) - b; + if (bm <= 0) + { + w.s.high = 0; + w.s.low = (USItype)uu.s.high >> -bm; + } + else + { + USItype carries = (USItype)uu.s.high << bm; + w.s.high = (USItype)uu.s.high >> b; + w.s.low = ((USItype)uu.s.low >> b) | carries; + } + + return w.ll; +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/v850/lib/Makefile linux.2.5.45-ac1/arch/v850/lib/Makefile --- linux.2.5.45/arch/v850/lib/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/v850/lib/Makefile 2002-11-01 15:20:35.000000000 +0000 @@ -0,0 +1,9 @@ +# +# arch/v850/lib/Makefile +# + +L_TARGET = lib.a +obj-y = ashrdi3.o ashldi3.o lshrdi3.o muldi3.o negdi2.o \ + checksum.o memcpy.o memset.o + +include $(TOPDIR)/Rules.make diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/v850/lib/memcpy.c linux.2.5.45-ac1/arch/v850/lib/memcpy.c --- linux.2.5.45/arch/v850/lib/memcpy.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/v850/lib/memcpy.c 2002-11-01 15:20:35.000000000 +0000 @@ -0,0 +1,97 @@ +/* + * arch/v850/lib/memcpy.c -- Memory copying + * + * Copyright (C) 2001,02 NEC Corporation + * Copyright (C) 2001,02 Miles Bader + * + * 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. + * + * Written by Miles Bader + */ + +#include +#include + +#define CHUNK_SIZE 32 /* bytes */ +#define CHUNK_ALIGNED(addr) (((unsigned long)addr & 0x3) == 0) + +/* Note that this macro uses 8 call-clobbered registers (not including + R1), which are few enough so that the following functions don't need + to spill anything to memory. It also uses R1, which is nominally + reserved for the assembler, but here it should be OK. */ +#define COPY_CHUNK(src, dst) \ + asm ("mov %0, ep;" \ + "sld.w 0[ep], r1; sld.w 4[ep], r12;" \ + "sld.w 8[ep], r13; sld.w 12[ep], r14;" \ + "sld.w 16[ep], r15; sld.w 20[ep], r17;" \ + "sld.w 24[ep], r18; sld.w 28[ep], r19;" \ + "mov %1, ep;" \ + "sst.w r1, 0[ep]; sst.w r12, 4[ep];" \ + "sst.w r13, 8[ep]; sst.w r14, 12[ep];" \ + "sst.w r15, 16[ep]; sst.w r17, 20[ep];" \ + "sst.w r18, 24[ep]; sst.w r19, 28[ep]" \ + :: "r" (src), "r" (dst) \ + : "r1", "r12", "r13", "r14", "r15", \ + "r17", "r18", "r19", "ep", "memory"); + +void *memcpy (void *dst, const void *src, __kernel_size_t size) +{ + char *_dst = dst; + const char *_src = src; + + if (size >= CHUNK_SIZE && CHUNK_ALIGNED(_src) && CHUNK_ALIGNED(_dst)) { + /* Copy large blocks efficiently. */ + unsigned count; + for (count = size / CHUNK_SIZE; count; count--) { + COPY_CHUNK (_src, _dst); + _src += CHUNK_SIZE; + _dst += CHUNK_SIZE; + } + size %= CHUNK_SIZE; + } + + if (size > 0) + do + *_dst++ = *_src++; + while (--size); + + return dst; +} + +void bcopy (const char *src, char *dst, int size) +{ + memcpy (dst, src, size); +} + +void *memmove (void *dst, const void *src, __kernel_size_t size) +{ + if ((unsigned long)dst < (unsigned long)src + || (unsigned long)src + size < (unsigned long)dst) + return memcpy (dst, src, size); + else { + char *_dst = dst + size; + const char *_src = src + size; + + if (size >= CHUNK_SIZE + && CHUNK_ALIGNED (_src) && CHUNK_ALIGNED (_dst)) + { + /* Copy large blocks efficiently. */ + unsigned count; + for (count = size / CHUNK_SIZE; count; count--) { + _src -= CHUNK_SIZE; + _dst -= CHUNK_SIZE; + COPY_CHUNK (_src, _dst); + } + size %= CHUNK_SIZE; + } + + if (size > 0) + do + *--_dst = *--_src; + while (--size); + + return _dst; + } +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/v850/lib/memset.c linux.2.5.45-ac1/arch/v850/lib/memset.c --- linux.2.5.45/arch/v850/lib/memset.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/v850/lib/memset.c 2002-11-01 15:20:35.000000000 +0000 @@ -0,0 +1,61 @@ +/* + * arch/v850/lib/memset.c -- Memory initialization + * + * Copyright (C) 2001,02 NEC Corporation + * Copyright (C) 2001,02 Miles Bader + * + * 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. + * + * Written by Miles Bader + */ + +#include + +void *memset (void *dst, int val, __kernel_size_t count) +{ + if (count) { + register unsigned loop; + register void *ptr asm ("ep") = dst; + + /* replicate VAL into a long. */ + val &= 0xff; + val |= val << 8; + val |= val << 16; + + /* copy initial unaligned bytes. */ + if ((long)ptr & 1) { + *((char *)ptr)++ = val; + count--; + } + if (count > 2 && ((long)ptr & 2)) { + *((short *)ptr)++ = val; + count -= 2; + } + + /* 32-byte copying loop. */ + for (loop = count / 32; loop; loop--) { + asm ("sst.w %0, 0[ep]; sst.w %0, 4[ep];" + "sst.w %0, 8[ep]; sst.w %0, 12[ep];" + "sst.w %0, 16[ep]; sst.w %0, 20[ep];" + "sst.w %0, 24[ep]; sst.w %0, 28[ep]" + :: "r" (val) : "memory"); + ptr += 32; + } + count %= 32; + + /* long copying loop. */ + for (loop = count / 4; loop; loop--) + *((long *)ptr)++ = val; + count %= 4; + + /* finish up with any trailing bytes. */ + if (count & 2) + *((short *)ptr)++ = val; + if (count & 1) + *(char *)ptr = val; + } + + return dst; +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/v850/lib/muldi3.c linux.2.5.45-ac1/arch/v850/lib/muldi3.c --- linux.2.5.45/arch/v850/lib/muldi3.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/v850/lib/muldi3.c 2002-11-01 15:20:35.000000000 +0000 @@ -0,0 +1,61 @@ +/* muldi3.c extracted from gcc-2.7.2.3/libgcc2.c and + gcc-2.7.2.3/longlong.h which is: */ +/* Copyright (C) 1989, 1992, 1993, 1994, 1995, 2001 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC 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. + +GNU CC 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 GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("mulu %3, %0, %1" \ + : "=r" ((USItype)(w0)), \ + "=r" ((USItype)(w1)) \ + : "%0" ((USItype)(u)), \ + "r" ((USItype)(v))) + +#define __umulsidi3(u, v) \ + ({DIunion __w; \ + umul_ppmm (__w.s.high, __w.s.low, u, v); \ + __w.ll; }) + +typedef int SItype __attribute__ ((mode (SI))); +typedef unsigned int USItype __attribute__ ((mode (SI))); +typedef int DItype __attribute__ ((mode (DI))); +typedef int word_type __attribute__ ((mode (__word__))); + +struct DIstruct {SItype high, low;}; + +typedef union +{ + struct DIstruct s; + DItype ll; +} DIunion; + +DItype +__muldi3 (DItype u, DItype v) +{ + DIunion w; + DIunion uu, vv; + + uu.ll = u, + vv.ll = v; + + w.ll = __umulsidi3 (uu.s.low, vv.s.low); + w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high + + (USItype) uu.s.high * (USItype) vv.s.low); + + return w.ll; +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/v850/lib/negdi2.c linux.2.5.45-ac1/arch/v850/lib/negdi2.c --- linux.2.5.45/arch/v850/lib/negdi2.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/v850/lib/negdi2.c 2002-11-01 15:20:35.000000000 +0000 @@ -0,0 +1,25 @@ +/* + * arch/v850/lib/negdi2.c -- 64-bit negation + * + * Copyright (C) 2001 NEC Corporation + * Copyright (C) 2001 Miles Bader + * + * 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. + * + * Written by Miles Bader + */ + +typedef int DItype __attribute__ ((mode (DI))); + +DItype __negdi2 (DItype x) +{ + __asm__ __volatile__ + ("not r6, r10;" + "add 1, r10;" + "setf c, r6;" + "not r7, r11;" + "add r6, r11" + ::: "r6", "r7", "r10", "r11"); +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/v850/Makefile linux.2.5.45-ac1/arch/v850/Makefile --- linux.2.5.45/arch/v850/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/v850/Makefile 2002-11-01 15:20:35.000000000 +0000 @@ -0,0 +1,65 @@ +# +# arch/v850/Makefile +# +# Copyright (C) 2001,02 NEC Corporation +# Copyright (C) 2001,02 Miles Bader +# +# This file is included by the global makefile so that you can add your own +# architecture-specific flags and dependencies. Remember to do have actions +# for "archclean" and "archdep" for cleaning up and making dependencies for +# this architecture +# +# 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. +# + +arch_dir = arch/v850 + +CFLAGS += -mv850e +# r16 is a fixed pointer to the current task +CFLAGS += -ffixed-r16 -mno-prolog-function +CFLAGS += -fno-builtin +CFLAGS += -D__linux__ -DUTS_SYSNAME=\"uClinux\" + + +HEAD := $(arch_dir)/kernel/head.o $(arch_dir)/kernel/init_task.o +core-y += $(arch_dir)/kernel/ +libs-y += $(arch_dir)/lib/ + + +include $(TOPDIR)/Rules.make + + +# Deal with the initial contents of the root device +ifdef ROOT_FS_IMAGE +core-y += root_fs_image.o + +# Because the kernel build-system erases all explicit .o build rules, we +# have to use an intermediate target to fool it into building for us. +# This results in it being built anew each time, but that's alright. +root_fs_image.o: root_fs_image_force + +# Note that we use the build-system's objcopy, as the v850 tools are fairly +# old, and don't have the --rename-section option. +root_fs_image_force: $(ROOT_FS_IMAGE) + objcopy -I binary -O elf32-little -B i386 --rename-section .data=.root,alloc,load,readonly,data,contents $< root_fs_image.o +endif + + +prepare: include/asm-$(ARCH)/asm-consts.h + +# Generate constants from C code for use by asm files +arch/$(ARCH)/kernel/asm-consts.s: include/asm include/linux/version.h \ + include/config/MARKER +include/asm-$(ARCH)/asm-consts.h.tmp: arch/$(ARCH)/kernel/asm-consts.s + @$(generate-asm-offsets.h) < $< > $@ +include/asm-$(ARCH)/asm-consts.h: include/asm-$(ARCH)/asm-consts.h.tmp + @echo -n ' Generating $@' + @$(update-if-changed) + + +CLEAN_FILES += include/asm-$(ARCH)/asm-consts.h.tmp \ + include/asm-$(ARCH)/asm-consts.h \ + arch/$(ARCH)/kernel/asm-consts.s \ + root_fs_image.o diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/v850/README linux.2.5.45-ac1/arch/v850/README --- linux.2.5.45/arch/v850/README 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/v850/README 2002-11-01 16:39:54.000000000 +0000 @@ -0,0 +1,23 @@ +This port to the NEC V850E processor supports the following platforms: + + + The gdb v850e simulator (CONFIG_V850E_SIM); see the subdirectory `sim' + for some more support files for this. + + + The Midas labs RTE-V850E/MA1-CB evaluation board (CONFIG_RTE_CB_MA1), + with untested support for the RTE-V850E/NB85E-CB board + (CONFIG_RTE_CB_NB85E). This support has only been tested when running + with the Multi-debugger monitor ROM (for the Green Hills Multi debugger). + The optional NEC Solution Gear RTE-MOTHER-A motherboard is also + supported, which allows PCI boards to be used (CONFIG_RTE_MB_A_PCI). + + + The sim85e2c simulator, which is a verilog simulation of the V850E2 + NA85E2C cpu core (CONFIG_V850E2_SIM85E2C). + + + A FPGA implementation of the V850E2 NA85E2C cpu core + (CONFIG_V850E2_FPGA85E2C). + + + The `Anna' (board/chip) implementation of the V850E2 processor. + +Porting to anything with a V850E/MA1 or MA2 processor should be simple. +See the file and the files it includes for an example of +how to add platform/chip-specific support. diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/v850/rte_ma1_cb-ksram.ld linux.2.5.45-ac1/arch/v850/rte_ma1_cb-ksram.ld --- linux.2.5.45/arch/v850/rte_ma1_cb-ksram.ld 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/v850/rte_ma1_cb-ksram.ld 2002-11-01 15:20:35.000000000 +0000 @@ -0,0 +1,152 @@ +/* Linker script for the Midas labs RTE-V850E/MA1-CB evaluation board + (CONFIG_RTE_CB_MA1), with kernel in SRAM, under Multi debugger. */ + +/* Note, all symbols are prefixed with an extra `_' for compatibility with + the existing linux sources. */ + +_jiffies = _jiffies_64 ; + +MEMORY { + /* 1MB of SRAM; we can't use the last 32KB, because it's used by + the monitor scratch-RAM. This memory is mirrored 4 times. */ + SRAM : ORIGIN = 0x00400000, LENGTH = 0x000F8000 + /* Monitor scratch RAM; only the interrupt vectors should go here. */ + MRAM : ORIGIN = 0x004F8000, LENGTH = 0x00008000 + /* 32MB of SDRAM. */ + SDRAM : ORIGIN = 0x00800000, LENGTH = 0x02000000 +} + +SECTIONS { + .text : { + __kram_start = . ; + + __stext = . ; + *(.text) + *(.exit.text) /* 2.5 convention */ + *(.text.exit) /* 2.4 convention */ + *(.text.lock) + *(.exitcall.exit) + __real_etext = . ; /* There may be data after here. */ + *(.rodata) + + . = ALIGN (0x4) ; + *(.kstrtab) + + . = ALIGN (4) ; + *(.call_table_data) + *(.call_table_text) + + . = ALIGN (16) ; /* Exception table. */ + ___start___ex_table = . ; + *(__ex_table) + ___stop___ex_table = . ; + + ___start___ksymtab = . ;/* Kernel symbol table. */ + *(__ksymtab) + ___stop___ksymtab = . ; + . = ALIGN (4) ; + __etext = . ; + } > SRAM + + .data ALIGN (0x4) : { + __sdata = . ; + ___data_start = . ; + *(.data) + *(.exit.data) /* 2.5 convention */ + *(.data.exit) /* 2.4 convention */ + . = ALIGN (16) ; + *(.data.cacheline_aligned) + . = ALIGN (0x2000) ; + *(.data.init_task) + . = ALIGN (0x2000) ; + __edata = . ; + } > SRAM + + .bss ALIGN (0x4) : { + __sbss = . ; + *(.bss) + *(COMMON) + . = ALIGN (4) ; + __init_stack_end = . ; + __ebss = . ; + } > SRAM + + .init ALIGN (4096) : { + __init_start = . ; + *(.init.text) /* 2.5 convention */ + *(.init.data) + *(.text.init) /* 2.4 convention */ + *(.data.init) + . = ALIGN (16) ; + ___setup_start = . ; + *(.init.setup) /* 2.5 convention */ + *(.setup.init) /* 2.4 convention */ + ___setup_end = . ; + ___initcall_start = . ; + *(.initcall.init) + *(.initcall1.init) + *(.initcall2.init) + *(.initcall3.init) + *(.initcall4.init) + *(.initcall5.init) + *(.initcall6.init) + *(.initcall7.init) + . = ALIGN (4) ; + ___initcall_end = . ; + } > SRAM + + /* This provides address at which the interrupt vectors are + initially loaded by the loader. */ + __intv_load_start = ALIGN (0x10) ; + + /* Interrupt vector space. Because we're using the monitor + ROM, Instead of the native interrupt vector, we must use the + `alternate interrupt vector' area. Note that this is in + `SRAM' space, which is not currently used by the kernel (the + kernel uses `SDRAM' space). */ + + /* We can't load the interrupt vectors directly into their + target location, because the monitor ROM for the GHS Multi + debugger barfs if we try. Unfortunately, Multi also doesn't + deal correctly with ELF sections where the LMA and VMA differ + (it just ignores the LMA), so we can't use that feature to + work around the problem! What we do instead is just put the + interrupt vectors into a normal section, and have the + `mach_early_init' function for Midas boards do the necessary + copying and relocation at runtime (this section basically + only contains `jr' instructions, so it's not that hard). + + This the section structure I initially tried to use (which more + accurately expresses the intent): + + .intv 0x007F8000 : AT (ADDR (.init) + SIZEOF (.init)) { + ... + } > MRAM + */ + + .intv ALIGN (0x10) : { + __intv_start = . ; + *(.intv.reset) /* Reset vector */ + *(.intv.common) /* Vectors common to all v850e proc. */ + *(.intv.mach) /* Machine-specific int. vectors. */ + __intv_end = . ; + + /* This is here so that when we free init memory, the initial + load-area of the interrupt vectors is freed too. */ + __init_end = __intv_end; + + __kram_end = __init_end ; + } > SRAM + + .bootmap ALIGN (4096) : { + __bootmap = . ; + . = . + 4096 ; /* enough for 128MB. */ + } > SRAM + + /* Device contents for the root filesystem. */ + .root : { + __root_fs_image_start = . ; + *(.root) + __root_fs_image_end = . ; + } > SDRAM +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/v850/rte_ma1_cb.ld linux.2.5.45-ac1/arch/v850/rte_ma1_cb.ld --- linux.2.5.45/arch/v850/rte_ma1_cb.ld 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/v850/rte_ma1_cb.ld 2002-11-01 15:20:35.000000000 +0000 @@ -0,0 +1,152 @@ +/* Linker script for the Midas labs RTE-V850E/MA1-CB evaluation board + (CONFIG_RTE_CB_MA1), with kernel in SDRAM, under Multi debugger. */ + +/* Note, all symbols are prefixed with an extra `_' for compatibility with + the existing linux sources. */ + +_jiffies = _jiffies_64 ; + +MEMORY { + /* 1MB of SRAM; we can't use the last 32KB, because it's used by + the monitor scratch-RAM. This memory is mirrored 4 times. */ + SRAM : ORIGIN = 0x00400000, LENGTH = 0x000F8000 + /* Monitor scratch RAM; only the interrupt vectors should go here. */ + MRAM : ORIGIN = 0x004F8000, LENGTH = 0x00008000 + /* 32MB of SDRAM. */ + SDRAM : ORIGIN = 0x00800000, LENGTH = 0x02000000 +} + +SECTIONS { + .bootmap : { + __bootmap = . ; + . = . + 4096 ; /* enough for 128MB. */ + } > SRAM + + .text : { + __kram_start = . ; + + __stext = . ; + *(.text) + *(.exit.text) /* 2.5 convention */ + *(.text.exit) /* 2.4 convention */ + *(.text.lock) + *(.exitcall.exit) + __real_etext = . ; /* There may be data after here. */ + *(.rodata) + + . = ALIGN (0x4) ; + *(.kstrtab) + + . = ALIGN (4) ; + *(.call_table_data) + *(.call_table_text) + + . = ALIGN (16) ; /* Exception table. */ + ___start___ex_table = . ; + *(__ex_table) + ___stop___ex_table = . ; + + ___start___ksymtab = . ;/* Kernel symbol table. */ + *(__ksymtab) + ___stop___ksymtab = . ; + . = ALIGN (4) ; + __etext = . ; + } > SDRAM + + .data ALIGN (0x4) : { + __sdata = . ; + ___data_start = . ; + *(.data) + *(.exit.data) /* 2.5 convention */ + *(.data.exit) /* 2.4 convention */ + . = ALIGN (16) ; + *(.data.cacheline_aligned) + . = ALIGN (0x2000) ; + *(.data.init_task) + . = ALIGN (0x2000) ; + __edata = . ; + } > SDRAM + + .bss ALIGN (0x4) : { + __sbss = . ; + *(.bss) + *(COMMON) + . = ALIGN (4) ; + __init_stack_end = . ; + __ebss = . ; + } > SDRAM + + .init ALIGN (4096) : { + __init_start = . ; + *(.init.text) /* 2.5 convention */ + *(.init.data) + *(.text.init) /* 2.4 convention */ + *(.data.init) + . = ALIGN (16) ; + ___setup_start = . ; + *(.init.setup) /* 2.5 convention */ + *(.setup.init) /* 2.4 convention */ + ___setup_end = . ; + ___initcall_start = . ; + *(.initcall.init) + *(.initcall1.init) + *(.initcall2.init) + *(.initcall3.init) + *(.initcall4.init) + *(.initcall5.init) + *(.initcall6.init) + *(.initcall7.init) + . = ALIGN (4) ; + ___initcall_end = . ; + } > SDRAM + + /* This provides address at which the interrupt vectors are + initially loaded by the loader. */ + __intv_load_start = ALIGN (0x10) ; + + /* Interrupt vector space. Because we're using the monitor + ROM, Instead of the native interrupt vector, we must use the + `alternate interrupt vector' area. Note that this is in + `SRAM' space, which is not currently used by the kernel (the + kernel uses `SDRAM' space). */ + + /* We can't load the interrupt vectors directly into their + target location, because the monitor ROM for the GHS Multi + debugger barfs if we try. Unfortunately, Multi also doesn't + deal correctly with ELF sections where the LMA and VMA differ + (it just ignores the LMA), so we can't use that feature to + work around the problem! What we do instead is just put the + interrupt vectors into a normal section, and have the + `mach_early_init' function for Midas boards do the necessary + copying and relocation at runtime (this section basically + only contains `jr' instructions, so it's not that hard). + + This the section structure I initially tried to use (which more + accurately expresses the intent): + + .intv 0x007F8000 : AT (ADDR (.init) + SIZEOF (.init)) { + ... + } > MRAM + */ + + .intv ALIGN (0x10) : { + __intv_start = . ; + *(.intv.reset) /* Reset vector */ + *(.intv.common) /* Vectors common to all v850e proc. */ + *(.intv.mach) /* Machine-specific int. vectors. */ + __intv_end = . ; + + /* This is here so that when we free init memory, the initial + load-area of the interrupt vectors is freed too. */ + __init_end = __intv_end; + + __kram_end = . ; + } > SDRAM + + /* Device contents for the root filesystem. */ + .root ALIGN (4096) : { + __root_fs_image_start = . ; + *(.root) + __root_fs_image_end = . ; + } > SDRAM +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/v850/rte_ma1_cb-rom.ld linux.2.5.45-ac1/arch/v850/rte_ma1_cb-rom.ld --- linux.2.5.45/arch/v850/rte_ma1_cb-rom.ld 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/v850/rte_ma1_cb-rom.ld 2002-11-01 15:20:35.000000000 +0000 @@ -0,0 +1,115 @@ +/* Linker script for the Midas labs RTE-V850E/MA1-CB evaluation board + (CONFIG_RTE_CB_MA1), with kernel in ROM. */ + +/* Note, all symbols are prefixed with an extra `_' for compatibility with + the existing linux sources. */ + +_jiffies = _jiffies_64 ; + +MEMORY { + ROM : ORIGIN = 0x00000000, LENGTH = 0x00100000 + /* 1MB of SRAM. This memory is mirrored 4 times. */ + SRAM : ORIGIN = 0x00400000, LENGTH = 0x00100000 + /* 32MB of SDRAM. */ + SDRAM : ORIGIN = 0x00800000, LENGTH = 0x02000000 +} + +SECTIONS { + /* Interrupt vector space. */ + .intv { + __intv_start = . ; + *(.intv.reset) /* Reset vector */ + *(.intv.common) /* Vectors common to all v850e proc. */ + *(.intv.mach) /* Machine-specific int. vectors. */ + __intv_end = . ; + } > ROM + + .text : { + __stext = . ; + *(.text) + *(.exit.text) /* 2.5 convention */ + *(.text.exit) /* 2.4 convention */ + *(.text.lock) + *(.exitcall.exit) + __real_etext = . ; /* There may be data after here. */ + *(.rodata) + . = ALIGN (0x4) ; + *(.kstrtab) + . = ALIGN (16) ; /* Exception table. */ + ___start___ex_table = . ; + *(__ex_table) + ___stop___ex_table = . ; + + ___start___ksymtab = . ;/* Kernel symbol table. */ + *(__ksymtab) + ___stop___ksymtab = . ; + . = ALIGN (4) ; + __etext = . ; + } > ROM + + __data_load_start = . ; + + .data : { + __kram_start = . ; + + __sdata = . ; + ___data_start = . ; + *(.data) + *(.exit.data) /* 2.5 convention */ + *(.data.exit) /* 2.4 convention */ + . = ALIGN (16) ; + *(.data.cacheline_aligned) + . = ALIGN (0x2000) ; + *(.data.init_task) + . = ALIGN (0x2000) ; + __edata = . ; + } > SRAM AT> ROM + + .bss ALIGN (0x4) : { + __sbss = . ; + *(.bss) + *(COMMON) + . = ALIGN (4) ; + __init_stack_end = . ; + __ebss = . ; + } > SRAM + + .init ALIGN (4096) : { + __init_start = . ; + *(.init.text) /* 2.5 convention */ + *(.init.data) + *(.text.init) /* 2.4 convention */ + *(.data.init) + . = ALIGN (16) ; + ___setup_start = . ; + *(.init.setup) /* 2.5 convention */ + *(.setup.init) /* 2.4 convention */ + ___setup_end = . ; + ___initcall_start = . ; + *(.initcall.init) + *(.initcall1.init) + *(.initcall2.init) + *(.initcall3.init) + *(.initcall4.init) + *(.initcall5.init) + *(.initcall6.init) + *(.initcall7.init) + . = ALIGN (4) ; + ___initcall_end = . ; + __init_end = . ; + + __kram_end = . ; + } > SRAM + + .bootmap ALIGN (4096) : { + __bootmap = . ; + . = . + 4096 ; /* enough for 128MB. */ + } > SRAM + + /* device contents for the root filesystem. */ + .root ALIGN (4096) { + __root_fs_image_start = . ; + *(.root) + __root_fs_image_end = . ; + } > SDRAM +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/v850/sim85e2c.ld linux.2.5.45-ac1/arch/v850/sim85e2c.ld --- linux.2.5.45/arch/v850/sim85e2c.ld 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/v850/sim85e2c.ld 2002-11-01 15:20:35.000000000 +0000 @@ -0,0 +1,135 @@ +/* Linker script for the sim85e2c simulator, which is a verilog simulation of + the V850E2 NA85E2C cpu core (CONFIG_V850E2_SIM85E2C). */ + +/* Note, all symbols are prefixed with an extra `_' for compatibility with + the existing linux sources. */ + +_jiffies = _jiffies_64 ; + +MEMORY { + /* 1MB of `instruction RAM', starting at 0. + Instruction fetches are much faster from IRAM than from DRAM. + This should match IRAM_ADDR in "include/asm-v580/sim85e2c.h". */ + IRAM : ORIGIN = 0x00000000, LENGTH = 0x00100000 + + /* 1MB of `data RAM', below and contiguous with the I/O space. + Data fetches are much faster from DRAM than from IRAM. + This should match DRAM_ADDR in "include/asm-v580/sim85e2c.h". */ + DRAM : ORIGIN = 0xfff00000, LENGTH = 0x000ff000 + /* We have to load DRAM at a mirror-address of 0x1ff00000, + because the simulator's preprocessing script isn't smart + enough to deal with the above LMA. */ + DRAM_LOAD : ORIGIN = 0x1ff00000, LENGTH = 0x000ff000 + + /* `external ram' (CS1 area), comes after IRAM. + This should match ERAM_ADDR in "include/asm-v580/sim85e2c.h". */ + ERAM : ORIGIN = 0x00100000, LENGTH = 0x07f00000 +} + +SECTIONS { + .intv : { + __intv_start = . ; + *(.intv) /* Interrupt vectors. */ + *(.intv.reset) /* Reset vector */ + *(.intv.common) /* Vectors common to all v850e proc. */ + *(.intv.mach) /* Machine-specific int. vectors. */ + __intv_end = . ; + } > IRAM + + .text : { + __stext = . ; + *(.text) + *(.exit.text) /* 2.5 convention */ + *(.text.exit) /* 2.4 convention */ + *(.text.lock) + *(.exitcall.exit) + __real_etext = . ; /* There may be data after here. */ + *(.rodata) + . = ALIGN (0x4) ; + *(.kstrtab) + + . = ALIGN (4) ; + *(.call_table_data) + *(.call_table_text) + + . = ALIGN (16) ; /* Exception table. */ + ___start___ex_table = . ; + *(__ex_table) + ___stop___ex_table = . ; + + ___start___ksymtab = . ;/* Kernel symbol table. */ + *(__ksymtab) + ___stop___ksymtab = . ; + . = ALIGN (4) ; + __etext = . ; + } > IRAM + + .init ALIGN (4096) : { + __init_start = . ; + *(.init.text) /* 2.5 convention */ + *(.init.data) + *(.text.init) /* 2.4 convention */ + *(.data.init) + . = ALIGN (16) ; + ___setup_start = . ; + *(.init.setup) /* 2.5 convention */ + *(.setup.init) /* 2.4 convention */ + ___setup_end = . ; + ___initcall_start = . ; + *(.initcall.init) + *(.initcall1.init) + *(.initcall2.init) + *(.initcall3.init) + *(.initcall4.init) + *(.initcall5.init) + *(.initcall6.init) + *(.initcall7.init) + . = ALIGN (4) ; + ___initcall_end = . ; + __init_end = . ; + } > IRAM + + .data : { + __kram_start = . ; + + __sdata = . ; + *(.data) + *(.exit.data) /* 2.5 convention */ + *(.data.exit) /* 2.4 convention */ + . = ALIGN (16) ; + *(.data.cacheline_aligned) + . = ALIGN (0x2000) ; + *(.data.init_task) + . = ALIGN (0x2000) ; + __edata = . ; + } > DRAM AT> DRAM_LOAD + + .bss ALIGN (0x4) : { + __sbss = . ; + *(.bss) + *(COMMON) + . = ALIGN (4) ; + __init_stack_end = . ; + __ebss = . ; + } > DRAM AT> DRAM_LOAD + + /* Device contents for the root filesystem. */ + .root ALIGN (4096) : { + __root_fs_image_start = . ; + *(.root) + __root_fs_image_end = . ; + } > DRAM AT> DRAM_LOAD + + .memcons : { + _memcons_output = . ; + . = . + 0x8000 ; + _memcons_output_end = . ; + + __kram_end = . ; + } > DRAM AT> DRAM_LOAD + + .bootmap ALIGN (4096) : { + __bootmap = . ; + . = . + 4096 ; /* enough for 128MB. */ + } > DRAM AT> DRAM_LOAD +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/v850/sim.ld linux.2.5.45-ac1/arch/v850/sim.ld --- linux.2.5.45/arch/v850/sim.ld 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/v850/sim.ld 2002-11-01 15:20:35.000000000 +0000 @@ -0,0 +1,108 @@ +/* Linker script for the gdb v850e simulator (CONFIG_V850E_SIM). */ + +/* Note, all symbols are prefixed with an extra `_' for compatibility with + the existing linux sources. */ + +_jiffies = _jiffies_64 ; + +MEMORY { + /* Interrupt vectors. */ + INTV : ORIGIN = 0x0, LENGTH = 0xe0 + /* 16MB of RAM. + This must match RAM_ADDR and RAM_SIZE in include/asm-v580/sim.h */ + RAM : ORIGIN = 0x8F000000, LENGTH = 0x01000000 +} + +SECTIONS { + .intv : { + __intv_start = . ; + *(.intv.reset) /* Reset vector */ + *(.intv.common) /* Vectors common to all v850e proc. */ + *(.intv.mach) /* Machine-specific int. vectors. */ + __intv_end = . ; + } > INTV + + .text : { + __kram_start = . ; + + __stext = . ; + *(.text) + *(.exit.text) /* 2.5 convention */ + *(.text.exit) /* 2.4 convention */ + *(.text.lock) + *(.exitcall.exit) + __real_etext = . ; /* There may be data after here. */ + *(.rodata) + . = ALIGN (0x4) ; + *(.kstrtab) + + . = ALIGN (4) ; + *(.call_table_data) + *(.call_table_text) + + . = ALIGN (16) ; /* Exception table. */ + ___start___ex_table = . ; + *(__ex_table) + ___stop___ex_table = . ; + + ___start___ksymtab = . ;/* Kernel symbol table. */ + *(__ksymtab) + ___stop___ksymtab = . ; + . = ALIGN (4) ; + __etext = . ; + } > RAM + + .data ALIGN (0x4) : { + __sdata = . ; + *(.data) + *(.exit.data) /* 2.5 convention */ + *(.data.exit) /* 2.4 convention */ + . = ALIGN (16) ; + *(.data.cacheline_aligned) + . = ALIGN (0x2000) ; + *(.data.init_task) + . = ALIGN (0x2000) ; + __edata = . ; + } > RAM + + .bss ALIGN (0x4) : { + __sbss = . ; + *(.bss) + *(COMMON) + . = ALIGN (4) ; + __init_stack_end = . ; + __ebss = . ; + } > RAM + + .init ALIGN (4096) : { + __init_start = . ; + *(.init.text) /* 2.5 convention */ + *(.init.data) + *(.text.init) /* 2.4 convention */ + *(.data.init) + . = ALIGN (16) ; + ___setup_start = . ; + *(.init.setup) /* 2.5 convention */ + *(.setup.init) /* 2.4 convention */ + ___setup_end = . ; + ___initcall_start = . ; + *(.initcall.init) + *(.initcall1.init) + *(.initcall2.init) + *(.initcall3.init) + *(.initcall4.init) + *(.initcall5.init) + *(.initcall6.init) + *(.initcall7.init) + . = ALIGN (4) ; + ___initcall_end = . ; + __init_end = . ; + + __kram_end = . ; + } > RAM + + .bootmap ALIGN (4096) : { + __bootmap = . ; + . = . + 4096 ; /* enough for 128MB. */ + } > RAM +} diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/v850/vmlinux.lds.S linux.2.5.45-ac1/arch/v850/vmlinux.lds.S --- linux.2.5.45/arch/v850/vmlinux.lds.S 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/arch/v850/vmlinux.lds.S 2002-11-01 15:20:35.000000000 +0000 @@ -0,0 +1,31 @@ +#include + +#ifdef CONFIG_V850E_SIM +# include "sim.ld" +#endif + +#ifdef CONFIG_V850E2_SIM85E2C +# include "sim85e2c.ld" +#endif + +#ifdef CONFIG_V850E2_FPGA85E2C +# include "fpga85e2c.ld" +#endif + +#ifdef CONFIG_V850E2_ANNA +# ifdef CONFIG_ROM_KERNEL +# include "anna-rom.ld" +# else +# include "anna.ld" +# endif +#endif + +#ifdef CONFIG_RTE_CB_MA1 +# ifdef CONFIG_ROM_KERNEL +# include "rte_ma1_cb-rom.ld" +# elif CONFIG_RTE_CB_MA1_KSRAM +# include "rte_ma1_cb-ksram.ld" +# else /* !CONFIG_ROM_KERNEL && !CONFIG_RTE_CB_MA1_KSRAM */ +# include "rte_ma1_cb.ld" +# endif /* CONFIG_ROM_KERNEL */ +#endif /* CONFIG_RTE_CB_MA1 */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/arch/x86_64/Kconfig linux.2.5.45-ac1/arch/x86_64/Kconfig --- linux.2.5.45/arch/x86_64/Kconfig 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.45-ac1/arch/x86_64/Kconfig 2002-11-01 11:37:30.000000000 +0000 @@ -37,6 +37,14 @@ config SBUS bool +config MMU + bool + default y + +config SWAP + bool + default y + config UID16 bool default y diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/CREDITS linux.2.5.45-ac1/CREDITS --- linux.2.5.45/CREDITS 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.45-ac1/CREDITS 2002-11-01 15:19:11.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 @@ -3047,8 +3055,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.45/Documentation/README.nsp_cs.eng linux.2.5.45-ac1/Documentation/README.nsp_cs.eng --- linux.2.5.45/Documentation/README.nsp_cs.eng 2002-10-31 14:57:48.000000000 +0000 +++ linux.2.5.45-ac1/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.45/Documentation/sysctl/kernel.txt linux.2.5.45-ac1/Documentation/sysctl/kernel.txt --- linux.2.5.45/Documentation/sysctl/kernel.txt 2002-10-31 14:57:47.000000000 +0000 +++ linux.2.5.45-ac1/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.45/drivers/atm/zatm.c linux.2.5.45-ac1/drivers/atm/zatm.c --- linux.2.5.45/drivers/atm/zatm.c 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.45-ac1/drivers/atm/zatm.c 2002-10-31 16:47:09.000000000 +0000 @@ -1260,13 +1260,13 @@ /* don't handle RD */ if (reason & uPD98401_INT_SPE) printk(KERN_ALERT DEV_LABEL "(itf %d): system parity " - "error at 0x%08lx\n",dev->number,zin(ADDR)); + "error at 0x%08x\n",dev->number,zin(ADDR)); if (reason & uPD98401_INT_CPE) printk(KERN_ALERT DEV_LABEL "(itf %d): control memory " - "parity error at 0x%08lx\n",dev->number,zin(ADDR)); + "parity error at 0x%08x\n",dev->number,zin(ADDR)); if (reason & uPD98401_INT_SBE) { printk(KERN_ALERT DEV_LABEL "(itf %d): system bus " - "error at 0x%08lx\n",dev->number,zin(ADDR)); + "error at 0x%08x\n",dev->number,zin(ADDR)); event_dump(); } /* don't handle IND */ @@ -1448,7 +1448,7 @@ } while (t0 > t1 || t1 > t2); /* loop if wrapping ... */ zatm_dev->khz = t2-2*t1+t0; - printk(KERN_NOTICE DEV_LABEL "(itf %d): uPD98401 %ld.%ld at %d.%03d " + printk(KERN_NOTICE DEV_LABEL "(itf %d): uPD98401 %d.%d at %d.%03d " "MHz\n",dev->number, (zin(VER) & uPD98401_MAJOR) >> uPD98401_MAJOR_SHIFT, zin(VER) & uPD98401_MINOR,zatm_dev->khz/1000,zatm_dev->khz % 1000); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/block/cciss.c linux.2.5.45-ac1/drivers/block/cciss.c --- linux.2.5.45/drivers/block/cciss.c 2002-10-31 14:57:17.000000000 +0000 +++ linux.2.5.45-ac1/drivers/block/cciss.c 2002-10-31 15:05:41.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.45/drivers/block/cciss_cmd.h linux.2.5.45-ac1/drivers/block/cciss_cmd.h --- linux.2.5.45/drivers/block/cciss_cmd.h 2002-10-31 14:57:17.000000000 +0000 +++ linux.2.5.45-ac1/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.45/drivers/block/cciss_scsi.c linux.2.5.45-ac1/drivers/block/cciss_scsi.c --- linux.2.5.45/drivers/block/cciss_scsi.c 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.45-ac1/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.45/drivers/block/floppy98.c linux.2.5.45-ac1/drivers/block/floppy98.c --- linux.2.5.45/drivers/block/floppy98.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/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.45/drivers/block/genhd.c linux.2.5.45-ac1/drivers/block/genhd.c --- linux.2.5.45/drivers/block/genhd.c 2002-10-31 15:05:00.000000000 +0000 +++ linux.2.5.45-ac1/drivers/block/genhd.c 2002-10-31 16:48:50.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.45/drivers/block/Makefile linux.2.5.45-ac1/drivers/block/Makefile --- linux.2.5.45/drivers/block/Makefile 2002-10-31 14:57:17.000000000 +0000 +++ linux.2.5.45-ac1/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.45/drivers/block/rd.c linux.2.5.45-ac1/drivers/block/rd.c --- linux.2.5.45/drivers/block/rd.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.45-ac1/drivers/block/rd.c 2002-10-31 16:49:46.000000000 +0000 @@ -204,7 +204,7 @@ kunmap(vec->bv_page); if (rw == READ) { - flush_dcache_page(sbh->b_page); + flush_dcache_page(vec->bv_page); } else { SetPageDirty(page); } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/char/agp/agp.h linux.2.5.45-ac1/drivers/char/agp/agp.h --- linux.2.5.45/drivers/char/agp/agp.h 2002-10-31 14:57:09.000000000 +0000 +++ linux.2.5.45-ac1/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.45/drivers/char/defkeymap.c linux.2.5.45-ac1/drivers/char/defkeymap.c --- linux.2.5.45/drivers/char/defkeymap.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/drivers/char/defkeymap.c 2002-10-31 15:05:31.000000000 +0000 @@ -0,0 +1,262 @@ +/* Do not edit this file! It was automatically generated by */ +/* loadkeys --mktable defkeymap.map > defkeymap.c */ + +#include +#include +#include + +u_short plain_map[NR_KEYS] = { + 0xf200, 0xf01b, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036, + 0xf037, 0xf038, 0xf039, 0xf030, 0xf02d, 0xf03d, 0xf07f, 0xf009, + 0xfb71, 0xfb77, 0xfb65, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69, + 0xfb6f, 0xfb70, 0xf05b, 0xf05d, 0xf201, 0xf702, 0xfb61, 0xfb73, + 0xfb64, 0xfb66, 0xfb67, 0xfb68, 0xfb6a, 0xfb6b, 0xfb6c, 0xf03b, + 0xf027, 0xf060, 0xf700, 0xf05c, 0xfb7a, 0xfb78, 0xfb63, 0xfb76, + 0xfb62, 0xfb6e, 0xfb6d, 0xf02c, 0xf02e, 0xf02f, 0xf700, 0xf30c, + 0xf703, 0xf020, 0xf207, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104, + 0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf208, 0xf209, 0xf307, + 0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301, + 0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf03c, 0xf10a, + 0xf10b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf30e, 0xf702, 0xf30d, 0xf01c, 0xf701, 0xf205, 0xf114, 0xf603, + 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116, + 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short shift_map[NR_KEYS] = { + 0xf200, 0xf01b, 0xf021, 0xf040, 0xf023, 0xf024, 0xf025, 0xf05e, + 0xf026, 0xf02a, 0xf028, 0xf029, 0xf05f, 0xf02b, 0xf07f, 0xf009, + 0xfb51, 0xfb57, 0xfb45, 0xfb52, 0xfb54, 0xfb59, 0xfb55, 0xfb49, + 0xfb4f, 0xfb50, 0xf07b, 0xf07d, 0xf201, 0xf702, 0xfb41, 0xfb53, + 0xfb44, 0xfb46, 0xfb47, 0xfb48, 0xfb4a, 0xfb4b, 0xfb4c, 0xf03a, + 0xf022, 0xf07e, 0xf700, 0xf07c, 0xfb5a, 0xfb58, 0xfb43, 0xfb56, + 0xfb42, 0xfb4e, 0xfb4d, 0xf03c, 0xf03e, 0xf03f, 0xf700, 0xf30c, + 0xf703, 0xf020, 0xf207, 0xf10a, 0xf10b, 0xf10c, 0xf10d, 0xf10e, + 0xf10f, 0xf110, 0xf111, 0xf112, 0xf113, 0xf213, 0xf203, 0xf307, + 0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301, + 0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf03e, 0xf10a, + 0xf10b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603, + 0xf20b, 0xf601, 0xf602, 0xf117, 0xf600, 0xf20a, 0xf115, 0xf116, + 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short altgr_map[NR_KEYS] = { + 0xf200, 0xf200, 0xf200, 0xf040, 0xf200, 0xf024, 0xf200, 0xf200, + 0xf07b, 0xf05b, 0xf05d, 0xf07d, 0xf05c, 0xf200, 0xf200, 0xf200, + 0xfb71, 0xfb77, 0xf918, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69, + 0xfb6f, 0xfb70, 0xf200, 0xf07e, 0xf201, 0xf702, 0xf914, 0xfb73, + 0xf917, 0xf919, 0xfb67, 0xfb68, 0xfb6a, 0xfb6b, 0xfb6c, 0xf200, + 0xf200, 0xf200, 0xf700, 0xf200, 0xfb7a, 0xfb78, 0xf916, 0xfb76, + 0xf915, 0xfb6e, 0xfb6d, 0xf200, 0xf200, 0xf200, 0xf700, 0xf30c, + 0xf703, 0xf200, 0xf207, 0xf50c, 0xf50d, 0xf50e, 0xf50f, 0xf510, + 0xf511, 0xf512, 0xf513, 0xf514, 0xf515, 0xf208, 0xf202, 0xf911, + 0xf912, 0xf913, 0xf30b, 0xf90e, 0xf90f, 0xf910, 0xf30a, 0xf90b, + 0xf90c, 0xf90d, 0xf90a, 0xf310, 0xf206, 0xf200, 0xf07c, 0xf516, + 0xf517, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603, + 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116, + 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short ctrl_map[NR_KEYS] = { + 0xf200, 0xf200, 0xf200, 0xf000, 0xf01b, 0xf01c, 0xf01d, 0xf01e, + 0xf01f, 0xf07f, 0xf200, 0xf200, 0xf01f, 0xf200, 0xf008, 0xf200, + 0xf011, 0xf017, 0xf005, 0xf012, 0xf014, 0xf019, 0xf015, 0xf009, + 0xf00f, 0xf010, 0xf01b, 0xf01d, 0xf201, 0xf702, 0xf001, 0xf013, + 0xf004, 0xf006, 0xf007, 0xf008, 0xf00a, 0xf00b, 0xf00c, 0xf200, + 0xf007, 0xf000, 0xf700, 0xf01c, 0xf01a, 0xf018, 0xf003, 0xf016, + 0xf002, 0xf00e, 0xf00d, 0xf200, 0xf20e, 0xf07f, 0xf700, 0xf30c, + 0xf703, 0xf000, 0xf207, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104, + 0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf208, 0xf204, 0xf307, + 0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301, + 0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf200, 0xf10a, + 0xf10b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf30e, 0xf702, 0xf30d, 0xf01c, 0xf701, 0xf205, 0xf114, 0xf603, + 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116, + 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short shift_ctrl_map[NR_KEYS] = { + 0xf200, 0xf200, 0xf200, 0xf000, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf01f, 0xf200, 0xf200, 0xf200, + 0xf011, 0xf017, 0xf005, 0xf012, 0xf014, 0xf019, 0xf015, 0xf009, + 0xf00f, 0xf010, 0xf200, 0xf200, 0xf201, 0xf702, 0xf001, 0xf013, + 0xf004, 0xf006, 0xf007, 0xf008, 0xf00a, 0xf00b, 0xf00c, 0xf200, + 0xf200, 0xf200, 0xf700, 0xf200, 0xf01a, 0xf018, 0xf003, 0xf016, + 0xf002, 0xf00e, 0xf00d, 0xf200, 0xf200, 0xf200, 0xf700, 0xf30c, + 0xf703, 0xf200, 0xf207, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf208, 0xf200, 0xf307, + 0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301, + 0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603, + 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116, + 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short alt_map[NR_KEYS] = { + 0xf200, 0xf81b, 0xf831, 0xf832, 0xf833, 0xf834, 0xf835, 0xf836, + 0xf837, 0xf838, 0xf839, 0xf830, 0xf82d, 0xf83d, 0xf87f, 0xf809, + 0xf871, 0xf877, 0xf865, 0xf872, 0xf874, 0xf879, 0xf875, 0xf869, + 0xf86f, 0xf870, 0xf85b, 0xf85d, 0xf80d, 0xf702, 0xf861, 0xf873, + 0xf864, 0xf866, 0xf867, 0xf868, 0xf86a, 0xf86b, 0xf86c, 0xf83b, + 0xf827, 0xf860, 0xf700, 0xf85c, 0xf87a, 0xf878, 0xf863, 0xf876, + 0xf862, 0xf86e, 0xf86d, 0xf82c, 0xf82e, 0xf82f, 0xf700, 0xf30c, + 0xf703, 0xf820, 0xf207, 0xf500, 0xf501, 0xf502, 0xf503, 0xf504, + 0xf505, 0xf506, 0xf507, 0xf508, 0xf509, 0xf208, 0xf209, 0xf907, + 0xf908, 0xf909, 0xf30b, 0xf904, 0xf905, 0xf906, 0xf30a, 0xf901, + 0xf902, 0xf903, 0xf900, 0xf310, 0xf206, 0xf200, 0xf83c, 0xf50a, + 0xf50b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf30e, 0xf702, 0xf30d, 0xf01c, 0xf701, 0xf205, 0xf114, 0xf603, + 0xf118, 0xf210, 0xf211, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116, + 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +u_short ctrl_alt_map[NR_KEYS] = { + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf811, 0xf817, 0xf805, 0xf812, 0xf814, 0xf819, 0xf815, 0xf809, + 0xf80f, 0xf810, 0xf200, 0xf200, 0xf201, 0xf702, 0xf801, 0xf813, + 0xf804, 0xf806, 0xf807, 0xf808, 0xf80a, 0xf80b, 0xf80c, 0xf200, + 0xf200, 0xf200, 0xf700, 0xf200, 0xf81a, 0xf818, 0xf803, 0xf816, + 0xf802, 0xf80e, 0xf80d, 0xf200, 0xf200, 0xf200, 0xf700, 0xf30c, + 0xf703, 0xf200, 0xf207, 0xf500, 0xf501, 0xf502, 0xf503, 0xf504, + 0xf505, 0xf506, 0xf507, 0xf508, 0xf509, 0xf208, 0xf200, 0xf307, + 0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301, + 0xf302, 0xf303, 0xf300, 0xf20c, 0xf206, 0xf200, 0xf200, 0xf50a, + 0xf50b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, + 0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603, + 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf20c, + 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d, + 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, +}; + +ushort *key_maps[MAX_NR_KEYMAPS] = { + plain_map, shift_map, altgr_map, 0, + ctrl_map, shift_ctrl_map, 0, 0, + alt_map, 0, 0, 0, + ctrl_alt_map, 0 +}; + +unsigned int keymap_count = 7; + +/* + * Philosophy: most people do not define more strings, but they who do + * often want quite a lot of string space. So, we statically allocate + * the default and allocate dynamically in chunks of 512 bytes. + */ + +char func_buf[] = { + '\033', '[', '[', 'A', 0, + '\033', '[', '[', 'B', 0, + '\033', '[', '[', 'C', 0, + '\033', '[', '[', 'D', 0, + '\033', '[', '[', 'E', 0, + '\033', '[', '1', '7', '~', 0, + '\033', '[', '1', '8', '~', 0, + '\033', '[', '1', '9', '~', 0, + '\033', '[', '2', '0', '~', 0, + '\033', '[', '2', '1', '~', 0, + '\033', '[', '2', '3', '~', 0, + '\033', '[', '2', '4', '~', 0, + '\033', '[', '2', '5', '~', 0, + '\033', '[', '2', '6', '~', 0, + '\033', '[', '2', '8', '~', 0, + '\033', '[', '2', '9', '~', 0, + '\033', '[', '3', '1', '~', 0, + '\033', '[', '3', '2', '~', 0, + '\033', '[', '3', '3', '~', 0, + '\033', '[', '3', '4', '~', 0, + '\033', '[', '1', '~', 0, + '\033', '[', '2', '~', 0, + '\033', '[', '3', '~', 0, + '\033', '[', '4', '~', 0, + '\033', '[', '5', '~', 0, + '\033', '[', '6', '~', 0, + '\033', '[', 'M', 0, + '\033', '[', 'P', 0, +}; + +char *funcbufptr = func_buf; +int funcbufsize = sizeof(func_buf); +int funcbufleft = 0; /* space left */ + +char *func_table[MAX_NR_FUNC] = { + func_buf + 0, + func_buf + 5, + func_buf + 10, + func_buf + 15, + func_buf + 20, + func_buf + 25, + func_buf + 31, + func_buf + 37, + func_buf + 43, + func_buf + 49, + func_buf + 55, + func_buf + 61, + func_buf + 67, + func_buf + 73, + func_buf + 79, + func_buf + 85, + func_buf + 91, + func_buf + 97, + func_buf + 103, + func_buf + 109, + func_buf + 115, + func_buf + 120, + func_buf + 125, + func_buf + 130, + func_buf + 135, + func_buf + 140, + func_buf + 145, + 0, + 0, + func_buf + 149, + 0, +}; + +struct kbdiacr accent_table[MAX_DIACR] = { + {'`', 'A', '\300'}, {'`', 'a', '\340'}, + {'\'', 'A', '\301'}, {'\'', 'a', '\341'}, + {'^', 'A', '\302'}, {'^', 'a', '\342'}, + {'~', 'A', '\303'}, {'~', 'a', '\343'}, + {'"', 'A', '\304'}, {'"', 'a', '\344'}, + {'O', 'A', '\305'}, {'o', 'a', '\345'}, + {'0', 'A', '\305'}, {'0', 'a', '\345'}, + {'A', 'A', '\305'}, {'a', 'a', '\345'}, + {'A', 'E', '\306'}, {'a', 'e', '\346'}, + {',', 'C', '\307'}, {',', 'c', '\347'}, + {'`', 'E', '\310'}, {'`', 'e', '\350'}, + {'\'', 'E', '\311'}, {'\'', 'e', '\351'}, + {'^', 'E', '\312'}, {'^', 'e', '\352'}, + {'"', 'E', '\313'}, {'"', 'e', '\353'}, + {'`', 'I', '\314'}, {'`', 'i', '\354'}, + {'\'', 'I', '\315'}, {'\'', 'i', '\355'}, + {'^', 'I', '\316'}, {'^', 'i', '\356'}, + {'"', 'I', '\317'}, {'"', 'i', '\357'}, + {'-', 'D', '\320'}, {'-', 'd', '\360'}, + {'~', 'N', '\321'}, {'~', 'n', '\361'}, + {'`', 'O', '\322'}, {'`', 'o', '\362'}, + {'\'', 'O', '\323'}, {'\'', 'o', '\363'}, + {'^', 'O', '\324'}, {'^', 'o', '\364'}, + {'~', 'O', '\325'}, {'~', 'o', '\365'}, + {'"', 'O', '\326'}, {'"', 'o', '\366'}, + {'/', 'O', '\330'}, {'/', 'o', '\370'}, + {'`', 'U', '\331'}, {'`', 'u', '\371'}, + {'\'', 'U', '\332'}, {'\'', 'u', '\372'}, + {'^', 'U', '\333'}, {'^', 'u', '\373'}, + {'"', 'U', '\334'}, {'"', 'u', '\374'}, + {'\'', 'Y', '\335'}, {'\'', 'y', '\375'}, + {'T', 'H', '\336'}, {'t', 'h', '\376'}, + {'s', 's', '\337'}, {'"', 'y', '\377'}, + {'s', 'z', '\337'}, {'i', 'j', '\377'}, +}; + +unsigned int accent_table_size = 68; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/char/keyboard.c linux.2.5.45-ac1/drivers/char/keyboard.c --- linux.2.5.45/drivers/char/keyboard.c 2002-10-31 14:57:09.000000000 +0000 +++ linux.2.5.45-ac1/drivers/char/keyboard.c 2002-10-31 15:05:31.000000000 +0000 @@ -680,8 +680,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.45/drivers/char/mem.c linux.2.5.45-ac1/drivers/char/mem.c --- linux.2.5.45/drivers/char/mem.c 2002-10-31 14:57:09.000000000 +0000 +++ linux.2.5.45-ac1/drivers/char/mem.c 2002-10-31 15:05:31.000000000 +0000 @@ -6,6 +6,8 @@ * Added devfs support. * Jan-11-1998, C. Scott Ananian * Shared /dev/zero mmaping support, Feb 2000, Kanoj Sarcar + * CONFIG_MMU changes Dec 2000, David McCullough + * based on work by Kenneth Albanowski . */ #include @@ -49,7 +51,7 @@ ssize_t written; written = 0; -#if defined(__sparc__) || defined(__mc68000__) +#if defined(__sparc__) || defined(__mc68000__) && defined(CONFIG_MMU) /* we don't have page 0 mapped on sparc and m68k.. */ if (realp < PAGE_SIZE) { unsigned long sz = PAGE_SIZE-realp; @@ -86,7 +88,7 @@ if (count > end_mem - p) count = end_mem - p; read = 0; -#if defined(__sparc__) || defined(__mc68000__) +#if defined(__sparc__) || defined(__mc68000__) && defined(CONFIG_MMU) /* we don't have page 0 mapped on sparc and m68k.. */ if (p < PAGE_SIZE) { unsigned long sz = PAGE_SIZE-p; @@ -140,7 +142,7 @@ prot |= _PAGE_PCD | _PAGE_PWT; #elif defined(__powerpc__) prot |= _PAGE_NO_CACHE | _PAGE_GUARDED; -#elif defined(__mc68000__) +#elif defined(__mc68000__) && defined(CONFIG_MMU) #ifdef SUN3_PAGE_NOCACHE if (MMU_IS_SUN3) prot |= SUN3_PAGE_NOCACHE; @@ -185,6 +187,7 @@ static int mmap_mem(struct file * file, struct vm_area_struct * vma) { +#ifdef CONFIG_MMU unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; /* @@ -208,6 +211,15 @@ vma->vm_page_prot)) return -EAGAIN; return 0; +#else + /* + * Return the physical address unmodified if it's possible to do + * so given the arguments. + */ + if (vma->vm_start == (file->f_pos + (vma->vm_pgoff << PAGE_SHIFT))) + return 0; + return -EINVAL; +#endif /* CONFIG_MMU */ } extern long vread(char *buf, char *addr, unsigned long count); @@ -229,7 +241,7 @@ if (count > (unsigned long) high_memory - p) read = (unsigned long) high_memory - p; -#if defined(__sparc__) || defined(__mc68000__) +#if defined(__sparc__) || defined(__mc68000__) && defined(CONFIG_MMU) /* we don't have page 0 mapped on sparc and m68k.. */ if (p < PAGE_SIZE && read > 0) { size_t tmp = PAGE_SIZE - p; @@ -377,6 +389,7 @@ return count; } +#ifdef CONFIG_MMU /* * For fun, we are using the MMU for this. */ @@ -430,10 +443,12 @@ return size; } +#endif /* CONFIG_MMU */ + static ssize_t read_zero(struct file * file, char * buf, size_t count, loff_t *ppos) { - unsigned long left, unwritten, written = 0; + unsigned long left; if (!count) return 0; @@ -443,6 +458,9 @@ left = count; +#ifdef CONFIG_MMU +{ + unsigned long unwritten, written = 0; /* do we want to be clever? Arbitrary cut-off */ if (count >= PAGE_SIZE*4) { unsigned long partial; @@ -467,14 +485,28 @@ out: return written ? written : -EFAULT; } +#else + for (left = count; left > 0; left--) { + put_user(0,buf); + buf++; + if (need_resched) + schedule(); + } + return(count); +#endif /* CONFIG_MMU */ +} static int mmap_zero(struct file * file, struct vm_area_struct * vma) { +#ifdef CONFIG_MMU if (vma->vm_flags & VM_SHARED) return shmem_zero_setup(vma); if (zeromap_page_range(vma, vma->vm_start, vma->vm_end - vma->vm_start, vma->vm_page_prot)) return -EAGAIN; return 0; +#else + return -ENOSYS; +#endif } static ssize_t write_full(struct file * file, const char * buf, diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/char/sysrq.c linux.2.5.45-ac1/drivers/char/sysrq.c --- linux.2.5.45/drivers/char/sysrq.c 2002-10-31 14:57:09.000000000 +0000 +++ linux.2.5.45-ac1/drivers/char/sysrq.c 2002-10-31 15:05:31.000000000 +0000 @@ -35,6 +35,10 @@ #include +#ifdef CONFIG_VOYAGER +#include +#endif + extern void reset_vc(unsigned int); extern struct list_head super_blocks; @@ -319,6 +323,14 @@ action_msg: "Terminate All Tasks", }; +#ifdef CONFIG_VOYAGER +static struct sysrq_key_op sysrq_voyager_dump_op = { + handler: voyager_dump, + help_msg: "voyager", + action_msg: "Dump Voyager Status\n", +}; +#endif + static void sysrq_handle_kill(int key, struct pt_regs *pt_regs, struct tty_struct *tty) { @@ -352,7 +364,11 @@ it is handled specially on the sparc and will never arrive */ /* b */ &sysrq_reboot_op, +#ifdef CONFIG_VOYAGER +/* c */ &sysrq_voyager_dump_op, +#else /* c */ NULL, +#endif /* d */ NULL, /* e */ &sysrq_term_op, /* f */ NULL, diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/char/tty_io.c linux.2.5.45-ac1/drivers/char/tty_io.c --- linux.2.5.45/drivers/char/tty_io.c 2002-10-31 14:57:09.000000000 +0000 +++ linux.2.5.45-ac1/drivers/char/tty_io.c 2002-10-31 15:05:31.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.45/drivers/char/upd4990a.c linux.2.5.45-ac1/drivers/char/upd4990a.c --- linux.2.5.45/drivers/char/upd4990a.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/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.45/drivers/hotplug/cpqphp_nvram.c linux.2.5.45-ac1/drivers/hotplug/cpqphp_nvram.c --- linux.2.5.45/drivers/hotplug/cpqphp_nvram.c 2002-10-31 14:57:01.000000000 +0000 +++ linux.2.5.45-ac1/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.45/drivers/ieee1394/sbp2.c linux.2.5.45-ac1/drivers/ieee1394/sbp2.c --- linux.2.5.45/drivers/ieee1394/sbp2.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.45-ac1/drivers/ieee1394/sbp2.c 2002-11-02 22:13:52.000000000 +0000 @@ -3137,15 +3137,9 @@ /* * Called by scsi stack to get bios parameters (used by fdisk, and at boot). */ -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,44) static int sbp2scsi_biosparam (struct scsi_device *sdev, - struct block_device *dev, sector_t capacy, int geom[]) + struct block_device *dev, sector_t capacity, int geom[]) { -#else -static int sbp2scsi_biosparam (Scsi_Disk *disk, kdev_t dev, int geom[]) -{ - sector_t capacy = disk->capacity; -#endif int heads, sectors, cylinders; SBP2_DEBUG("Request for bios parameters"); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/ieee1394/sbp2.h linux.2.5.45-ac1/drivers/ieee1394/sbp2.h --- linux.2.5.45/drivers/ieee1394/sbp2.h 2002-10-31 14:57:19.000000000 +0000 +++ linux.2.5.45-ac1/drivers/ieee1394/sbp2.h 2002-11-02 22:13:23.000000000 +0000 @@ -549,11 +549,7 @@ static int sbp2scsi_detect (Scsi_Host_Template *tpnt); static const char *sbp2scsi_info (struct Scsi_Host *host); void sbp2scsi_setup(char *str, int *ints); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,28) -static int sbp2scsi_biosparam (Scsi_Disk *disk, kdev_t dev, int geom[]); -#else -static int sbp2scsi_biosparam (Scsi_Disk *disk, struct block_device *dev, int geom[]); -#endif +static int sbp2scsi_biosparam (struct scsi_device *sdev, struct block_device *dev, sector_t capacity, int geom[]); static int sbp2scsi_abort (Scsi_Cmnd *SCpnt); static int sbp2scsi_reset (Scsi_Cmnd *SCpnt); static int sbp2scsi_queuecommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/input/mouse/psmouse.c linux.2.5.45-ac1/drivers/input/mouse/psmouse.c --- linux.2.5.45/drivers/input/mouse/psmouse.c 2002-10-31 14:57:18.000000000 +0000 +++ linux.2.5.45-ac1/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.45/drivers/isdn/hisax/bkm_a8.c linux.2.5.45-ac1/drivers/isdn/hisax/bkm_a8.c --- linux.2.5.45/drivers/isdn/hisax/bkm_a8.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.45-ac1/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.45/drivers/md/dm-ioctl.c linux.2.5.45-ac1/drivers/md/dm-ioctl.c --- linux.2.5.45/drivers/md/dm-ioctl.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.45-ac1/drivers/md/dm-ioctl.c 2002-11-02 22:47:37.000000000 +0000 @@ -554,6 +554,21 @@ return 0; } +/* Really the mapped device ought to hold the bdev anyway... this is + a -ac fixit hack not a nice fix */ + +static void dm_set_device_ro(struct mapped_device *md, int flag) +{ + struct block_device *bdev; + dev_t dev = kdev_t_to_nr(dm_kdev(md)); + bdev = bdget(dev); + if (!bdev) + return; + set_device_ro(bdev, flag); + bdput(bdev); + +} + static int create(struct dm_ioctl *param, struct dm_ioctl *user) { int r; @@ -585,7 +600,7 @@ } dm_table_put(t); /* md will have grabbed its own reference */ - set_device_ro(dm_kdev(md), (param->flags & DM_READONLY_FLAG)); + dm_set_device_ro(md, (param->flags & DM_READONLY_FLAG)); r = dm_hash_insert(param->name, *param->uuid ? param->uuid : NULL, md); dm_put(md); @@ -871,7 +886,7 @@ return r; } - set_device_ro(dm_kdev(md), (param->flags & DM_READONLY_FLAG)); + dm_set_device_ro(md, (param->flags & DM_READONLY_FLAG)); dm_put(md); r = info(param, user); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/media/video/bttv-driver.c linux.2.5.45-ac1/drivers/media/video/bttv-driver.c --- linux.2.5.45/drivers/media/video/bttv-driver.c 2002-10-31 14:57:08.000000000 +0000 +++ linux.2.5.45-ac1/drivers/media/video/bttv-driver.c 2002-10-31 15:05:24.000000000 +0000 @@ -813,7 +813,7 @@ i2c_mux = mux = (btv->audio & AUDIO_MUTE) ? AUDIO_OFF : btv->audio; if (btv->opt_automute && !signal && !btv->radio_user) mux = AUDIO_OFF; - 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"); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/message/fusion/mptscsih.h linux.2.5.45-ac1/drivers/message/fusion/mptscsih.h --- linux.2.5.45/drivers/message/fusion/mptscsih.h 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.45-ac1/drivers/message/fusion/mptscsih.h 2002-11-02 22:49:51.000000000 +0000 @@ -231,7 +231,8 @@ extern int x_scsi_old_reset(Scsi_Cmnd *, unsigned int); #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,28) -extern int x_scsi_bios_param(Disk *, struct block_device *, int *); +extern int mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev, + sector_t capacity, int *ip); #else extern int x_scsi_bios_param(Disk *, kdev_t, int *); #endif diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/message/i2o/i2o_block.c linux.2.5.45-ac1/drivers/message/i2o/i2o_block.c --- linux.2.5.45/drivers/message/i2o/i2o_block.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.45-ac1/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.45/drivers/message/i2o/i2o_scsi.c linux.2.5.45-ac1/drivers/message/i2o/i2o_scsi.c --- linux.2.5.45/drivers/message/i2o/i2o_scsi.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.45-ac1/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.45/drivers/mtd/maps/Kconfig linux.2.5.45-ac1/drivers/mtd/maps/Kconfig --- linux.2.5.45/drivers/mtd/maps/Kconfig 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.45-ac1/drivers/mtd/maps/Kconfig 2002-11-01 15:21:05.000000000 +0000 @@ -346,5 +346,11 @@ cards are usually around 4-16MiB in size. This does not include Compact Flash cards which are treated as IDE devices. +config MTD_UCLINUX + tristate "Generic uClinux RAM/ROM filesystem support" + depends on MTD_PARTITIONS + help + Map driver to support image based filesystems for uClinux. + endmenu diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/mtd/maps/Makefile linux.2.5.45-ac1/drivers/mtd/maps/Makefile --- linux.2.5.45/drivers/mtd/maps/Makefile 2002-10-31 14:57:13.000000000 +0000 +++ linux.2.5.45-ac1/drivers/mtd/maps/Makefile 2002-10-31 15:05:38.000000000 +0000 @@ -30,6 +30,7 @@ obj-$(CONFIG_MTD_SCx200_DOCFLASH)+= scx200_docflash.o obj-$(CONFIG_MTD_DBOX2) += dbox2-flash.o obj-$(CONFIG_MTD_OCELOT) += ocelot.o +obj-$(CONFIG_MTD_UCLINUX) += uclinux.o obj-$(CONFIG_MTD_SOLUTIONENGINE)+= solutionengine.o obj-$(CONFIG_MTD_PCI) += pci.o obj-$(CONFIG_MTD_AUTCPU12) += autcpu12-nvram.o diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/mtd/maps/uclinux.c linux.2.5.45-ac1/drivers/mtd/maps/uclinux.c --- linux.2.5.45/drivers/mtd/maps/uclinux.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/drivers/mtd/maps/uclinux.c 2002-10-31 15:05:38.000000000 +0000 @@ -0,0 +1,171 @@ +/****************************************************************************/ + +/* + * uclinux.c -- generic memory mapped MTD driver for uclinux + * + * (C) Copyright 2002, Greg Ungerer (gerg@snapgear.com) + */ + +/****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/****************************************************************************/ + +__u8 uclinux_read8(struct map_info *map, unsigned long ofs) +{ + return(*((__u8 *) (map->map_priv_1 + ofs))); +} + +__u16 uclinux_read16(struct map_info *map, unsigned long ofs) +{ + return(*((__u16 *) (map->map_priv_1 + ofs))); +} + +__u32 uclinux_read32(struct map_info *map, unsigned long ofs) +{ + return(*((__u32 *) (map->map_priv_1 + ofs))); +} + +void uclinux_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) +{ + memcpy(to, (void *)(map->map_priv_1 + from), len); +} + +void uclinux_write8(struct map_info *map, __u8 d, unsigned long adr) +{ + *((__u8 *) (map->map_priv_1 + adr)) = d; +} + +void uclinux_write16(struct map_info *map, __u16 d, unsigned long adr) +{ + *((__u16 *) (map->map_priv_1 + adr)) = d; +} + +void uclinux_write32(struct map_info *map, __u32 d, unsigned long adr) +{ + *((__u32 *) (map->map_priv_1 + adr)) = d; +} + +void uclinux_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) +{ + memcpy((void *) (map->map_priv_1 + to), from, len); +} + +/****************************************************************************/ + +struct map_info uclinux_ram_map = { + name: "RAM", + read8: uclinux_read8, + read16: uclinux_read16, + read32: uclinux_read32, + copy_from: uclinux_copy_from, + write8: uclinux_write8, + write16: uclinux_write16, + write32: uclinux_write32, + copy_to: uclinux_copy_to, +}; + +struct mtd_info *uclinux_ram_mtdinfo; + +/****************************************************************************/ + +struct mtd_partition uclinux_romfs[] = { + { name: "ROMfs", offset: 0 } +}; + +#define NUM_PARTITIONS (sizeof(uclinux_romfs) / sizeof(uclinux_romfs[0])) + +/****************************************************************************/ + +int uclinux_point(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char **mtdbuf) +{ + struct map_info *map = (struct map_info *) mtd->priv; + *mtdbuf = (u_char *) (map->map_priv_1 + ((int) from)); + *retlen = len; + return(0); +} + +/****************************************************************************/ + +int __init uclinux_mtd_init(void) +{ + struct mtd_info *mtd; + struct map_info *mapp; + extern char _ebss; + + mapp = &uclinux_ram_map; + mapp->map_priv_2 = (unsigned long) &_ebss; + mapp->size = PAGE_ALIGN(*((unsigned long *)((&_ebss) + 8))); + mapp->buswidth = 4; + + printk("uclinux[mtd]: RAM probe address=0x%x size=0x%x\n", + (int) mapp->map_priv_2, (int) mapp->size); + + mapp->map_priv_1 = (unsigned long) + ioremap_nocache(mapp->map_priv_2, mapp->size); + + if (mapp->map_priv_1 == 0) { + printk("uclinux[mtd]: ioremap_nocache() failed\n"); + return(-EIO); + } + + mtd = do_map_probe("map_ram", mapp); + if (!mtd) { + printk("uclinux[mtd]: failed to find a mapping?\n"); + iounmap((void *) mapp->map_priv_1); + return(-ENXIO); + } + + mtd->module = THIS_MODULE; + mtd->point = uclinux_point; + mtd->priv = mapp; + + uclinux_ram_mtdinfo = mtd; + add_mtd_partitions(mtd, uclinux_romfs, NUM_PARTITIONS); + + printk("uclinux[mtd]: set %s to be root filesystem\n", + uclinux_romfs[0].name); + ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, 0); + put_mtd_device(mtd); + + return(0); +} + +/****************************************************************************/ + +void __exit uclinux_mtd_cleanup(void) +{ + if (uclinux_ram_mtdinfo) { + del_mtd_partitions(uclinux_ram_mtdinfo); + map_destroy(uclinux_ram_mtdinfo); + uclinux_ram_mtdinfo = NULL; + } + if (uclinux_ram_map.map_priv_1) { + iounmap((void *) uclinux_ram_map.map_priv_1); + uclinux_ram_map.map_priv_1 = 0; + } +} + +/****************************************************************************/ + +module_init(uclinux_mtd_init); +module_exit(uclinux_mtd_cleanup); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Greg Ungerer "); +MODULE_DESCRIPTION("Generic RAM based MTD for uClinux"); + +/****************************************************************************/ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/net/3c509.c linux.2.5.45-ac1/drivers/net/3c509.c --- linux.2.5.45/drivers/net/3c509.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.45-ac1/drivers/net/3c509.c 2002-10-31 17:15:43.000000000 +0000 @@ -51,11 +51,13 @@ - Full duplex support v1.19 16Oct2002 Zwane Mwaikambo - Additional ethtool features + v1.19a 28Oct2002 Davud Ruggiero + - Increase *read_eeprom udelay to workaround oops with 2 cards. */ #define DRV_NAME "3c509" -#define DRV_VERSION "1.19" -#define DRV_RELDATE "16Oct2002" +#define DRV_VERSION "1.19a" +#define DRV_RELDATE "28Oct2002" /* A few values that may be tweaked. */ @@ -570,8 +572,9 @@ static ushort read_eeprom(int ioaddr, int index) { outw(EEPROM_READ + index, ioaddr + 10); - /* Pause for at least 162 us. for the read to take place. */ - udelay (500); + /* Pause for at least 162 us. for the read to take place. + Some chips seem to require much longer */ + mdelay(2); return inw(ioaddr + 12); } @@ -585,7 +588,8 @@ outb(EEPROM_READ + index, id_port); /* Pause for at least 162 us. for the read to take place. */ - udelay (500); + /* Some chips seem to require much longer */ + mdelay(4); for (bit = 15; bit >= 0; bit--) word = (word << 1) + (inb(id_port) & 0x01); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/net/68360enet.c linux.2.5.45-ac1/drivers/net/68360enet.c --- linux.2.5.45/drivers/net/68360enet.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/drivers/net/68360enet.c 2002-10-31 15:05:21.000000000 +0000 @@ -0,0 +1,953 @@ +/* + * Ethernet driver for Motorola MPC8xx. + * Copyright (c) 2000 Michael Leslie + * Copyright (c) 1997 Dan Malek (dmalek@jlc.net) + * + * I copied the basic skeleton from the lance driver, because I did not + * know how to write the Linux driver, but I did know how the LANCE worked. + * + * This version of the driver is somewhat selectable for the different + * processor/board combinations. It works for the boards I know about + * now, and should be easily modified to include others. Some of the + * configuration information is contained in "commproc.h" and the + * remainder is here. + * + * Buffer descriptors are kept in the CPM dual port RAM, and the frame + * buffers are in the host memory. + * + * Right now, I am very watseful with the buffers. I allocate memory + * pages and then divide them into 2K frame buffers. This way I know I + * have buffers large enough to hold one frame within one buffer descriptor. + * Once I get this working, I will use 64 or 128 byte CPM buffers, which + * will be much more memory efficient and will easily handle lots of + * small packets. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +/* #include */ +/* #include */ +/* #include */ +#include +/* #include */ +#include + + +/* + * Theory of Operation + * + * The MPC8xx CPM performs the Ethernet processing on SCC1. It can use + * an aribtrary number of buffers on byte boundaries, but must have at + * least two receive buffers to prevent constant overrun conditions. + * + * The buffer descriptors are allocated from the CPM dual port memory + * with the data buffers allocated from host memory, just like all other + * serial communication protocols. The host memory buffers are allocated + * from the free page pool, and then divided into smaller receive and + * transmit buffers. The size of the buffers should be a power of two, + * since that nicely divides the page. This creates a ring buffer + * structure similar to the LANCE and other controllers. + * + * Like the LANCE driver: + * The driver runs as two independent, single-threaded flows of control. One + * is the send-packet routine, which enforces single-threaded use by the + * cep->tx_busy flag. The other thread is the interrupt handler, which is + * single threaded by the hardware and other software. + * + * The send packet thread has partial control over the Tx ring and the + * 'cep->tx_busy' flag. It sets the tx_busy flag whenever it's queuing a Tx + * packet. If the next queue slot is empty, it clears the tx_busy flag when + * finished otherwise it sets the 'lp->tx_full' flag. + * + * The MBX has a control register external to the MPC8xx that has some + * control of the Ethernet interface. Information is in the manual for + * your board. + * + * The RPX boards have an external control/status register. Consult the + * programming documents for details unique to your board. + * + * For the TQM8xx(L) modules, there is no control register interface. + * All functions are directly controlled using I/O pins. See commproc.h. + */ + + +/* The transmitter timeout + */ +#define TX_TIMEOUT (2*HZ) + +/* The number of Tx and Rx buffers. These are allocated statically here. + * We don't need to allocate pages for the transmitter. We just use + * the skbuffer directly. + */ +#ifdef CONFIG_ENET_BIG_BUFFERS +#define RX_RING_SIZE 64 +#define TX_RING_SIZE 64 /* Must be power of two */ +#define TX_RING_MOD_MASK 63 /* for this to work */ +#else +#define RX_RING_SIZE 8 +#define TX_RING_SIZE 8 /* Must be power of two */ +#define TX_RING_MOD_MASK 7 /* for this to work */ +#endif + +#define CPM_ENET_RX_FRSIZE 2048 /* overkill left over from ppc page-based allocation */ +static char rx_buf_pool[RX_RING_SIZE * CPM_ENET_RX_FRSIZE]; + + +/* The CPM stores dest/src/type, data, and checksum for receive packets. + */ +#define PKT_MAXBUF_SIZE 1518 +#define PKT_MINBUF_SIZE 64 +#define PKT_MAXBLR_SIZE 1520 + +/* The CPM buffer descriptors track the ring buffers. The rx_bd_base and + * tx_bd_base always point to the base of the buffer descriptors. The + * cur_rx and cur_tx point to the currently available buffer. + * The dirty_tx tracks the current buffer that is being sent by the + * controller. The cur_tx and dirty_tx are equal under both completely + * empty and completely full conditions. The empty/ready indicator in + * the buffer descriptor determines the actual condition. + */ +struct scc_enet_private { + /* The saved address of a sent-in-place packet/buffer, for skfree(). */ + struct sk_buff* tx_skbuff[TX_RING_SIZE]; + ushort skb_cur; + ushort skb_dirty; + + /* CPM dual port RAM relative addresses. + */ + QUICC_BD *rx_bd_base; /* Address of Rx and Tx buffers. */ + QUICC_BD *tx_bd_base; + QUICC_BD *cur_rx, *cur_tx; /* The next free ring entry */ + QUICC_BD *dirty_tx; /* The ring entries to be free()ed. */ + volatile struct scc_regs *sccp; + /* struct net_device_stats stats; */ + struct net_device_stats stats; + uint tx_full; + /* spinlock_t lock; */ + volatile unsigned int lock; +}; + + + +static int scc_enet_open(struct net_device *dev); +static int scc_enet_start_xmit(struct sk_buff *skb, struct net_device *dev); +static int scc_enet_rx(struct net_device *dev); +/* static void scc_enet_interrupt(void *dev_id); */ +static void scc_enet_interrupt(int vec, void *dev_id, struct pt_regs *fp); +static int scc_enet_close(struct net_device *dev); +/* static struct net_device_stats *scc_enet_get_stats(struct net_device *dev); */ +static struct net_device_stats *scc_enet_get_stats(struct net_device *dev); +static void set_multicast_list(struct net_device *dev); + +/* Get this from various configuration locations (depends on board). +*/ +/*static ushort my_enet_addr[] = { 0x0800, 0x3e26, 0x1559 };*/ + +/* Typically, 860(T) boards use SCC1 for Ethernet, and other 8xx boards + * use SCC2. This is easily extended if necessary. + */ + +#define CONFIG_SCC1_ENET /* by default */ + +#ifdef CONFIG_SCC1_ENET +#define CPM_CR_ENET CPM_CR_CH_SCC1 +#define PROFF_ENET PROFF_SCC1 +#define SCC_ENET 0 +#define CPMVEC_ENET CPMVEC_SCC1 +#endif + +#ifdef CONFIG_SCC2_ENET +#define CPM_CR_ENET CPM_CR_CH_SCC2 +#define PROFF_ENET PROFF_SCC2 +#define SCC_ENET 1 /* Index, not number! */ +#define CPMVEC_ENET CPMVEC_SCC2 +#endif + +static int +scc_enet_open(struct net_device *dev) +{ + + /* I should reset the ring buffers here, but I don't yet know + * a simple way to do that. + * mleslie: That's no biggie. Worth doing, too. + */ + + /* netif_start_queue(dev); */ + return 0; /* Always succeed */ +} + + +static int +scc_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct scc_enet_private *cep = (struct scc_enet_private *)dev->priv; + volatile QUICC_BD *bdp; + + /* Fill in a Tx ring entry */ + bdp = cep->cur_tx; + +#ifndef final_version + if (bdp->status & BD_ENET_TX_READY) { + /* Ooops. All transmit buffers are full. Bail out. + * This should not happen, since cep->tx_busy should be set. + */ + printk("%s: tx queue full!.\n", dev->name); + return 1; + } +#endif + + /* Clear all of the status flags. + */ + bdp->status &= ~BD_ENET_TX_STATS; + + /* If the frame is short, tell CPM to pad it. + */ + if (skb->len <= ETH_ZLEN) + bdp->status |= BD_ENET_TX_PAD; + else + bdp->status &= ~BD_ENET_TX_PAD; + + /* Set buffer length and buffer pointer. + */ + bdp->length = skb->len; + /* bdp->buf = __pa(skb->data); */ + bdp->buf = skb->data; + + /* Save skb pointer. + */ + cep->tx_skbuff[cep->skb_cur] = skb; + + /* cep->stats.tx_bytes += skb->len; */ /* TODO: It would really be nice... */ + + cep->skb_cur = (cep->skb_cur+1) & TX_RING_MOD_MASK; + + + /* Push the data cache so the CPM does not get stale memory + * data. + */ +/* flush_dcache_range((unsigned long)(skb->data), */ +/* (unsigned long)(skb->data + skb->len)); */ + + /* spin_lock_irq(&cep->lock); */ /* TODO: SPINLOCK */ + local_irq_disable(); + if (cep->lock > 0) { + printk ("scc_enet_start_xmit() lock == %d\n", cep->lock); + } else { + cep->lock++; + } + + /* Send it on its way. Tell CPM its ready, interrupt when done, + * its the last BD of the frame, and to put the CRC on the end. + */ + bdp->status |= (BD_ENET_TX_READY | BD_ENET_TX_INTR | BD_ENET_TX_LAST | BD_ENET_TX_TC); + + dev->trans_start = jiffies; + + /* If this was the last BD in the ring, start at the beginning again. + */ + if (bdp->status & BD_ENET_TX_WRAP) + bdp = cep->tx_bd_base; + else + bdp++; + + if (bdp->status & BD_ENET_TX_READY) { + /* netif_stop_queue(dev); */ + cep->tx_full = 1; + } + + cep->cur_tx = (QUICC_BD *)bdp; + + /* spin_unlock_irq(&cep->lock); */ /* TODO: SPINLOCK */ + cep->lock--; + sti(); + + return 0; +} + +#if 0 +static void +scc_enet_timeout(struct net_device *dev) +{ + struct scc_enet_private *cep = (struct scc_enet_private *)dev->priv; + + printk("%s: transmit timed out.\n", dev->name); + cep->stats.tx_errors++; +#ifndef final_version + { + int i; + QUICC_BD *bdp; + printk(" Ring data dump: cur_tx %p%s cur_rx %p.\n", + cep->cur_tx, cep->tx_full ? " (full)" : "", + cep->cur_rx); + bdp = cep->tx_bd_base; + for (i = 0 ; i < TX_RING_SIZE; i++, bdp++) + printk("%04x %04x %08x\n", + bdp->status, + bdp->length, + (int)(bdp->buf)); + bdp = cep->rx_bd_base; + for (i = 0 ; i < RX_RING_SIZE; i++, bdp++) + printk("%04x %04x %08x\n", + bdp->status, + bdp->length, + (int)(bdp->buf)); + } +#endif +/* if (!cep->tx_full) */ +/* netif_wake_queue(dev); */ +} +#endif + +/* The interrupt handler. + * This is called from the CPM handler, not the MPC core interrupt. + */ +/* static void scc_enet_interrupt(void *dev_id) */ +static void scc_enet_interrupt(int vec, void *dev_id, struct pt_regs *fp) +{ + struct net_device *dev = (struct net_device *)dev_id; + volatile struct scc_enet_private *cep; + volatile QUICC_BD *bdp; + ushort int_events; + int must_restart; + + cep = (struct scc_enet_private *)dev->priv; + + /* Get the interrupt events that caused us to be here. + */ + int_events = cep->sccp->scc_scce; + cep->sccp->scc_scce = int_events; + must_restart = 0; + + /* Handle receive event in its own function. + */ + if (int_events & SCCE_ENET_RXF) + scc_enet_rx(dev_id); + + /* Check for a transmit error. The manual is a little unclear + * about this, so the debug code until I get it figured out. It + * appears that if TXE is set, then TXB is not set. However, + * if carrier sense is lost during frame transmission, the TXE + * bit is set, "and continues the buffer transmission normally." + * I don't know if "normally" implies TXB is set when the buffer + * descriptor is closed.....trial and error :-). + */ + + /* Transmit OK, or non-fatal error. Update the buffer descriptors. + */ + if (int_events & (SCCE_ENET_TXE | SCCE_ENET_TXB)) { + /* spin_lock(&cep->lock); */ /* TODO: SPINLOCK */ + /* local_irq_disable(); */ + if (cep->lock > 0) { + printk ("scc_enet_interrupt() lock == %d\n", cep->lock); + } else { + cep->lock++; + } + + bdp = cep->dirty_tx; + while ((bdp->status&BD_ENET_TX_READY)==0) { + if ((bdp==cep->cur_tx) && (cep->tx_full == 0)) + break; + + if (bdp->status & BD_ENET_TX_HB) /* No heartbeat */ + cep->stats.tx_heartbeat_errors++; + if (bdp->status & BD_ENET_TX_LC) /* Late collision */ + cep->stats.tx_window_errors++; + if (bdp->status & BD_ENET_TX_RL) /* Retrans limit */ + cep->stats.tx_aborted_errors++; + if (bdp->status & BD_ENET_TX_UN) /* Underrun */ + cep->stats.tx_fifo_errors++; + if (bdp->status & BD_ENET_TX_CSL) /* Carrier lost */ + cep->stats.tx_carrier_errors++; + + + /* No heartbeat or Lost carrier are not really bad errors. + * The others require a restart transmit command. + */ + if (bdp->status & + (BD_ENET_TX_LC | BD_ENET_TX_RL | BD_ENET_TX_UN)) { + must_restart = 1; + cep->stats.tx_errors++; + } + + cep->stats.tx_packets++; + + /* Deferred means some collisions occurred during transmit, + * but we eventually sent the packet OK. + */ + if (bdp->status & BD_ENET_TX_DEF) + cep->stats.collisions++; + + /* Free the sk buffer associated with this last transmit. + */ + /* dev_kfree_skb_irq(cep->tx_skbuff[cep->skb_dirty]); */ + dev_kfree_skb (cep->tx_skbuff[cep->skb_dirty]); + cep->skb_dirty = (cep->skb_dirty + 1) & TX_RING_MOD_MASK; + + /* Update pointer to next buffer descriptor to be transmitted. + */ + if (bdp->status & BD_ENET_TX_WRAP) + bdp = cep->tx_bd_base; + else + bdp++; + + /* I don't know if we can be held off from processing these + * interrupts for more than one frame time. I really hope + * not. In such a case, we would now want to check the + * currently available BD (cur_tx) and determine if any + * buffers between the dirty_tx and cur_tx have also been + * sent. We would want to process anything in between that + * does not have BD_ENET_TX_READY set. + */ + + /* Since we have freed up a buffer, the ring is no longer + * full. + */ + if (cep->tx_full) { + cep->tx_full = 0; +/* if (netif_queue_stopped(dev)) */ +/* netif_wake_queue(dev); */ + } + + cep->dirty_tx = (QUICC_BD *)bdp; + } + + if (must_restart) { + volatile QUICC *cp; + + /* Some transmit errors cause the transmitter to shut + * down. We now issue a restart transmit. Since the + * errors close the BD and update the pointers, the restart + * _should_ pick up without having to reset any of our + * pointers either. + */ + cp = pquicc; + cp->cp_cr = + mk_cr_cmd(CPM_CR_ENET, CPM_CR_RESTART_TX) | CPM_CR_FLG; + while (cp->cp_cr & CPM_CR_FLG); + } + /* spin_unlock(&cep->lock); */ /* TODO: SPINLOCK */ + /* sti(); */ + cep->lock--; + } + + /* Check for receive busy, i.e. packets coming but no place to + * put them. This "can't happen" because the receive interrupt + * is tossing previous frames. + */ + if (int_events & SCCE_ENET_BSY) { + cep->stats.rx_dropped++; + printk("CPM ENET: BSY can't happen.\n"); + } + + return; +} + +/* During a receive, the cur_rx points to the current incoming buffer. + * When we update through the ring, if the next incoming buffer has + * not been given to the system, we just set the empty indicator, + * effectively tossing the packet. + */ +static int +scc_enet_rx(struct net_device *dev) +{ + struct scc_enet_private *cep; + volatile QUICC_BD *bdp; + struct sk_buff *skb; + ushort pkt_len; + + cep = (struct scc_enet_private *)dev->priv; + + /* First, grab all of the stats for the incoming packet. + * These get messed up if we get called due to a busy condition. + */ + bdp = cep->cur_rx; + + for (;;) { + if (bdp->status & BD_ENET_RX_EMPTY) + break; + +#ifndef final_version + /* Since we have allocated space to hold a complete frame, both + * the first and last indicators should be set. + */ + if ((bdp->status & (BD_ENET_RX_FIRST | BD_ENET_RX_LAST)) != + (BD_ENET_RX_FIRST | BD_ENET_RX_LAST)) + printk("CPM ENET: rcv is not first+last\n"); +#endif + + /* Frame too long or too short. + */ + if (bdp->status & (BD_ENET_RX_LG | BD_ENET_RX_SH)) + cep->stats.rx_length_errors++; + if (bdp->status & BD_ENET_RX_NO) /* Frame alignment */ + cep->stats.rx_frame_errors++; + if (bdp->status & BD_ENET_RX_CR) /* CRC Error */ + cep->stats.rx_crc_errors++; + if (bdp->status & BD_ENET_RX_OV) /* FIFO overrun */ + cep->stats.rx_crc_errors++; + + /* Report late collisions as a frame error. + * On this error, the BD is closed, but we don't know what we + * have in the buffer. So, just drop this frame on the floor. + */ + if (bdp->status & BD_ENET_RX_CL) { + cep->stats.rx_frame_errors++; + } + else { + + /* Process the incoming frame. + */ + cep->stats.rx_packets++; + pkt_len = bdp->length; + /* cep->stats.rx_bytes += pkt_len; */ /* TODO: It would really be nice... */ + + /* This does 16 byte alignment, much more than we need. + * The packet length includes FCS, but we don't want to + * include that when passing upstream as it messes up + * bridging applications. + */ + skb = dev_alloc_skb(pkt_len-4); + + if (skb == NULL) { + printk("%s: Memory squeeze, dropping packet.\n", dev->name); + cep->stats.rx_dropped++; + } + else { + skb->dev = dev; + skb_put(skb,pkt_len-4); /* Make room */ + eth_copy_and_sum(skb, (unsigned char *)bdp->buf, pkt_len-4, 0); + skb->protocol=eth_type_trans(skb,dev); + netif_rx(skb); + } + } + + /* Clear the status flags for this buffer. + */ + bdp->status &= ~BD_ENET_RX_STATS; + + /* Mark the buffer empty. + */ + bdp->status |= BD_ENET_RX_EMPTY; + + /* Update BD pointer to next entry. + */ + if (bdp->status & BD_ENET_RX_WRAP) + bdp = cep->rx_bd_base; + else + bdp++; + + } + cep->cur_rx = (QUICC_BD *)bdp; + + return 0; +} + +static int +scc_enet_close(struct net_device *dev) +{ + /* Don't know what to do yet. + */ + /* netif_stop_queue(dev); */ + + return 0; +} + +/* static struct net_device_stats *scc_enet_get_stats(struct net_device *dev) */ +static struct net_device_stats *scc_enet_get_stats(struct net_device *dev) +{ + struct scc_enet_private *cep = (struct scc_enet_private *)dev->priv; + + return &cep->stats; +} + +/* Set or clear the multicast filter for this adaptor. + * Skeleton taken from sunlance driver. + * The CPM Ethernet implementation allows Multicast as well as individual + * MAC address filtering. Some of the drivers check to make sure it is + * a group multicast address, and discard those that are not. I guess I + * will do the same for now, but just remove the test if you want + * individual filtering as well (do the upper net layers want or support + * this kind of feature?). + */ + +static void set_multicast_list(struct net_device *dev) +{ + struct scc_enet_private *cep; + struct dev_mc_list *dmi; + u_char *mcptr, *tdptr; + volatile scc_enet_t *ep; + int i, j; + volatile QUICC *cp = pquicc; + + cep = (struct scc_enet_private *)dev->priv; + + /* Get pointer to SCC area in parameter RAM. + */ + ep = (scc_enet_t *)dev->base_addr; + + if (dev->flags&IFF_PROMISC) { + + /* Log any net taps. */ + printk("%s: Promiscuous mode enabled.\n", dev->name); + cep->sccp->scc_psmr |= ETHER_PRO; + } else { + + cep->sccp->scc_psmr &= ~ETHER_PRO; + + if (dev->flags & IFF_ALLMULTI) { + /* Catch all multicast addresses, so set the + * filter to all 1's. + */ + ep->sen_gaddr1 = 0xffff; + ep->sen_gaddr2 = 0xffff; + ep->sen_gaddr3 = 0xffff; + ep->sen_gaddr4 = 0xffff; + } + else { + /* Clear filter and add the addresses in the list. + */ + ep->sen_gaddr1 = 0; + ep->sen_gaddr2 = 0; + ep->sen_gaddr3 = 0; + ep->sen_gaddr4 = 0; + + dmi = dev->mc_list; + + for (i=0; imc_count; i++) { + + /* Only support group multicast for now. + */ + if (!(dmi->dmi_addr[0] & 1)) + continue; + + /* The address in dmi_addr is LSB first, + * and taddr is MSB first. We have to + * copy bytes MSB first from dmi_addr. + */ + mcptr = (u_char *)dmi->dmi_addr + 5; + tdptr = (u_char *)&ep->sen_taddrh; + for (j=0; j<6; j++) + *tdptr++ = *mcptr--; + + /* Ask CPM to run CRC and set bit in + * filter mask. + */ + cp->cp_cr = mk_cr_cmd(CPM_CR_ENET, CPM_CR_SET_GADDR) | CPM_CR_FLG; + /* this delay is necessary here -- Cort */ + udelay(10); + while (cp->cp_cr & CPM_CR_FLG); + } + } + } +} + + +/* Initialize the CPM Ethernet on SCC. + */ +int scc_enet_init(void) +{ + struct net_device *dev; + struct scc_enet_private *cep; + int i, j; + unsigned char *eap; + /* unsigned long mem_addr; */ + /* pte_t *pte; */ + /* bd_t *bd; */ /* `board tag' used by ppc - TODO: integrate uC bootloader vars */ + volatile QUICC_BD *bdp; + volatile QUICC *cp; + volatile struct scc_regs *sccp; + volatile struct ethernet_pram *ep; + /* volatile immap_t *immap; */ + + cp = pquicc; /* Get pointer to Communication Processor */ + + /* immap = (immap_t *)IMAP_ADDR; */ /* and to internal registers */ + + /* bd = (bd_t *)__res; */ + + /* Allocate some private information. + */ + cep = (struct scc_enet_private *)kmalloc(sizeof(*cep), GFP_KERNEL); + memset(cep, 0, sizeof(*cep)); + /* __clear_user(cep,sizeof(*cep)); */ + /* spin_lock_init(&cep->lock); */ /* TODO: SPINLOCK */ + + /* Create an Ethernet device instance. + */ + dev = init_etherdev(0, 0); + + /* Get pointer to SCC area in parameter RAM. + */ + /* ep = (ethernet_pram *)(&cp->cp_dparam[PROFF_ENET]); */ + ep = &pquicc->pram[SCC_ENET].enet_scc; + + /* And another to the SCC register area. + */ + sccp = &pquicc->scc_regs[SCC_ENET]; + cep->sccp = sccp; /* Keep the pointer handy */ + + /* Disable receive and transmit in case EPPC-Bug started it. + */ + sccp->scc_gsmr.w.low &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT); + + /* Set up 360 pins for SCC interface to ethernet transceiver. + * Pin mappings (PA_xx and PC_xx) are defined in commproc.h + */ + + /* Configure port A pins for Txd and Rxd. + */ + pquicc->pio_papar |= (PA_ENET_RXD | PA_ENET_TXD); + pquicc->pio_padir &= ~(PA_ENET_RXD | PA_ENET_TXD); + pquicc->pio_paodr &= ~PA_ENET_TXD; + + /* Configure port C pins to enable CLSN and RENA. + */ + pquicc->pio_pcpar &= ~(PC_ENET_CLSN | PC_ENET_RENA); + pquicc->pio_pcdir &= ~(PC_ENET_CLSN | PC_ENET_RENA); + pquicc->pio_pcso |= (PC_ENET_CLSN | PC_ENET_RENA); + + /* Configure port A for TCLK and RCLK. + */ + pquicc->pio_papar |= (PA_ENET_TCLK | PA_ENET_RCLK); + pquicc->pio_padir &= ~(PA_ENET_TCLK | PA_ENET_RCLK); + + /* Configure Serial Interface clock routing. + * First, clear all SCC bits to zero, then set the ones we want. + */ + pquicc->si_sicr &= ~SICR_ENET_MASK; + pquicc->si_sicr |= SICR_ENET_CLKRT; + + + /* Allocate space for the buffer descriptors in the DP ram. + * These are relative offsets in the DP ram address space. + * Initialize base addresses for the buffer descriptors. + */ + i = m360_cpm_dpalloc(sizeof(QUICC_BD) * RX_RING_SIZE); + ep->rbase = i; + cep->rx_bd_base = (QUICC_BD *)((uint)pquicc + i); + + i = m360_cpm_dpalloc(sizeof(QUICC_BD) * TX_RING_SIZE); + ep->tbase = i; + cep->tx_bd_base = (QUICC_BD *)((uint)pquicc + i); + + cep->dirty_tx = cep->cur_tx = cep->tx_bd_base; + cep->cur_rx = cep->rx_bd_base; + + /* Issue init Rx BD command for SCC. + * Manual says to perform an Init Rx parameters here. We have + * to perform both Rx and Tx because the SCC may have been + * already running. [In uCquicc's case, I don't think that is so - mles] + * In addition, we have to do it later because we don't yet have + * all of the BD control/status set properly. + cp->cp_cpcr = mk_cr_cmd(CPM_CR_ENET, CPM_CR_INIT_RX) | CPM_CR_FLG; + while (cp->cp_cpcr & CPM_CR_FLG); + */ + + /* Initialize function code registers for big-endian. + */ + ep->rfcr = (SCC_EB | SCC_FC_DMA); + ep->tfcr = (SCC_EB | SCC_FC_DMA); + + /* Set maximum bytes per receive buffer. + * This appears to be an Ethernet frame size, not the buffer + * fragment size. It must be a multiple of four. + */ + ep->mrblr = PKT_MAXBLR_SIZE; + + /* Set CRC preset and mask. + */ + ep->c_pres = 0xffffffff; + ep->c_mask = 0xdebb20e3; /* see 360UM p. 7-247 */ + + ep->crcec = 0; /* CRC Error counter */ + ep->alec = 0; /* alignment error counter */ + ep->disfc = 0; /* discard frame counter */ + + ep->pads = 0x8888; /* Tx short frame pad character */ + ep->ret_lim = 0x000f; /* Retry limit threshold */ + + ep->mflr = PKT_MAXBUF_SIZE; /* maximum frame length register */ + ep->minflr = PKT_MINBUF_SIZE; /* minimum frame length register */ + + ep->maxd1 = PKT_MAXBLR_SIZE; /* maximum DMA1 length */ + ep->maxd2 = PKT_MAXBLR_SIZE; /* maximum DMA2 length */ + + /* Clear hash tables, group and individual. + */ + ep->gaddr1 = ep->gaddr2 = ep->gaddr3 = ep->gaddr4 = 0; + ep->iaddr1 = ep->iaddr2 = ep->iaddr3 = ep->iaddr4 = 0; + + /* Set Ethernet station address. + * + * The uCbootloader provides a hook to the kernel to retrieve + * stuff like the MAC address. This is retrieved in config_BSP() + */ +#if defined (CONFIG_UCQUICC) + { + extern unsigned char *scc1_hwaddr; + + eap = (char *)ep->paddr.b; + for (i=5; i>=0; i--) + *eap++ = dev->dev_addr[i] = scc1_hwaddr[i]; + } +#endif + + +/* #ifndef CONFIG_MBX */ +/* eap = (unsigned char *)&(ep->paddrh); */ + +/* for (i=5; i>=0; i--) */ +/* *eap++ = dev->dev_addr[i] = bd->bi_enetaddr[i]; */ +/* #else */ +/* for (i=5; i>=0; i--) */ +/* dev->dev_addr[i] = *eap++; */ +/* #endif */ + + ep->p_per = 0; /* 'cause the book says so */ + ep->taddr_l = 0; /* temp address (LSB) */ + ep->taddr_m = 0; + ep->taddr_h = 0; /* temp address (MSB) */ + + /* Now allocate the host memory pages and initialize the + * buffer descriptors. + */ + /* initialize rx buffer descriptors */ + bdp = cep->tx_bd_base; + for (j=0; j<(TX_RING_SIZE-1); j++) { + bdp->buf = 0; + bdp->status = 0; + bdp++; + } + bdp->buf = 0; + bdp->status = BD_SC_WRAP; + + + /* initialize rx buffer descriptors */ + bdp = cep->rx_bd_base; + for (j=0; j<(RX_RING_SIZE-1); j++) { + bdp->buf = &rx_buf_pool[j * CPM_ENET_RX_FRSIZE]; + bdp->status = BD_SC_EMPTY | BD_SC_INTRPT; + bdp++; + } + bdp->buf = &rx_buf_pool[j * CPM_ENET_RX_FRSIZE]; + bdp->status = BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT; + + + + /* Let's re-initialize the channel now. We have to do it later + * than the manual describes because we have just now finished + * the BD initialization. + */ + cp->cp_cr = mk_cr_cmd(CPM_CR_ENET, CPM_CR_INIT_TRX) | CPM_CR_FLG; + while (cp->cp_cr & CPM_CR_FLG); + + cep->skb_cur = cep->skb_dirty = 0; + + sccp->scc_scce = 0xffff; /* Clear any pending events */ + + /* Enable interrupts for transmit error, complete frame + * received, and any transmit buffer we have also set the + * interrupt flag. + */ + sccp->scc_sccm = (SCCE_ENET_TXE | SCCE_ENET_RXF | SCCE_ENET_TXB); + + /* Install our interrupt handler. + */ + /* cpm_install_handler(CPMVEC_ENET, scc_enet_interrupt, dev); */ + request_irq(CPMVEC_ENET, scc_enet_interrupt, + IRQ_FLG_LOCK, dev->name, (void *)dev); + + /* Set GSMR_H to enable all normal operating modes. + * Set GSMR_L to enable Ethernet to MC68160. + */ + sccp->scc_gsmr.w.high = 0; + sccp->scc_gsmr.w.low = (SCC_GSMRL_TCI | SCC_GSMRL_TPL_48 | + SCC_GSMRL_TPP_10 | SCC_GSMRL_MODE_ENET); + + /* Set sync/delimiters. + */ + sccp->scc_dsr = 0xd555; + + /* Set processing mode. Use Ethernet CRC, catch broadcast, and + * start frame search 22 bit times after RENA. + */ + sccp->scc_psmr = (SCC_PMSR_ENCRC /* Ethernet CRC mode */ + /* | SCC_PSMR_HBC */ /* Enable heartbeat */ + /* | SCC_PMSR_PRO */ /* Promiscuous mode */ + /* | SCC_PMSR_FDE */ /* Full duplex enable */ + | ETHER_NIB_22); + /* sccp->scc_psmr = (SCC_PMSR_PRO | ETHER_CRC_32 | ETHER_NIB_22); */ + + + /* It is now OK to enable the Ethernet transmitter. + * Unfortunately, there are board implementation differences here. + */ +#if defined(CONFIG_UCQUICC) +/* immap->im_ioport.iop_pcpar |= PC_ENET_TENA; */ +/* immap->im_ioport.iop_pcdir &= ~PC_ENET_TENA; */ + cp->pio_pcpar |= PC_ENET_TENA; /* t_en */ + cp->pio_pcdir &= ~PC_ENET_TENA; + + cp->pip_pbpar &= ~(0x00000200); /* power up ethernet transceiver */ + cp->pip_pbdir |= (0x00000200); + cp->pip_pbdat |= (0x00000200); +#endif + + + dev->base_addr = (unsigned long)ep; + dev->priv = cep; +#if 0 + dev->name = "CPM_ENET"; +#endif + + /* The CPM Ethernet specific entries in the device structure. */ + dev->open = scc_enet_open; + dev->hard_start_xmit = scc_enet_start_xmit; + /* dev->tx_timeout = scc_enet_timeout; */ + /* dev->watchdog_timeo = TX_TIMEOUT; */ + dev->stop = scc_enet_close; + dev->get_stats = scc_enet_get_stats; + dev->set_multicast_list = set_multicast_list; + + /* And last, enable the transmit and receive processing. + */ + sccp->scc_gsmr.w.low |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT); + + printk("%s: CPM ENET Version 0.3, ", dev->name); + for (i=0; i<5; i++) + printk("%02x:", dev->dev_addr[i]); + printk("%02x\n", dev->dev_addr[5]); + + return 0; +} + + + +int m68360_enet_probe(struct device *dev) +{ + return(scc_enet_init ()); +} + + +/* + * Local variables: + * c-indent-level: 4 + * c-basic-offset: 4 + * tab-width: 4 + * End: + */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/net/dl2k.c linux.2.5.45-ac1/drivers/net/dl2k.c --- linux.2.5.45/drivers/net/dl2k.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.45-ac1/drivers/net/dl2k.c 2002-10-31 17:18:20.000000000 +0000 @@ -535,7 +535,7 @@ { long ioaddr = dev->base_addr; - printk (KERN_INFO "%s: Tx timed out (%4.4lx), is buffer full?\n", + printk (KERN_INFO "%s: Tx timed out (%4.4x), is buffer full?\n", dev->name, readl (ioaddr + TxStatus)); rio_free_tx(dev, 0); dev->if_port = 0; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/net/fealnx.c linux.2.5.45-ac1/drivers/net/fealnx.c --- linux.2.5.45/drivers/net/fealnx.c 2002-10-31 14:57:04.000000000 +0000 +++ linux.2.5.45-ac1/drivers/net/fealnx.c 2002-10-31 15:05:21.000000000 +0000 @@ -1155,8 +1155,8 @@ unsigned int old_linkok = np->linkok; if (debug) - printk(KERN_DEBUG "%s: Media selection timer tick, status %8.8x " - "config %8.8x.\n", dev->name, readl(ioaddr + ISR), + printk(KERN_DEBUG "%s: Media selection timer tick, status %8.8lx " + "config %8.8lx.\n", dev->name, readl(ioaddr + ISR), readl(ioaddr + TCRRCR)); if (np->flags == HAS_MII_XCVR) { @@ -1184,7 +1184,7 @@ long ioaddr = dev->base_addr; int i; - printk(KERN_WARNING "%s: Transmit timed out, status %8.8x," + printk(KERN_WARNING "%s: Transmit timed out, status %8.8lx," " resetting...\n", dev->name, readl(ioaddr + ISR)); { @@ -1555,7 +1555,7 @@ np->stats.rx_crc_errors += (readl(ioaddr + TALLY) & 0x7fff0000) >> 16; if (debug) - printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4x.\n", + printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4lx.\n", dev->name, readl(ioaddr + ISR)); writel(np->imrvalue, ioaddr + IMR); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/net/fec.c linux.2.5.45-ac1/drivers/net/fec.c --- linux.2.5.45/drivers/net/fec.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/drivers/net/fec.c 2002-10-31 15:05:21.000000000 +0000 @@ -0,0 +1,1926 @@ +/* + * Fast Ethernet Controller (FEC) driver for Motorola MPC8xx. + * Copyright (c) 1997 Dan Malek (dmalek@jlc.net) + * + * This version of the driver is specific to the FADS implementation, + * since the board contains control registers external to the processor + * for the control of the LevelOne LXT970 transceiver. The MPC860T manual + * describes connections using the internal parallel port I/O, which + * is basically all of Port D. + * + * Right now, I am very watseful with the buffers. I allocate memory + * pages and then divide them into 2K frame buffers. This way I know I + * have buffers large enough to hold one frame within one buffer descriptor. + * Once I get this working, I will use 64 or 128 byte CPM buffers, which + * will be much more memory efficient and will easily handle lots of + * small packets. + * + * Much better multiple PHY support by Magnus Damm. + * Copyright (c) 2000 Ericsson Radio Systems AB. + * + * Support for FEC controller of ColdFire/5272. + * Copyrught (c) 2001-2002 Greg Ungerer (gerg@snapgear.com) + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_M5272 +#include +#include +#include "fec.h" +#else +#include +#include +#include "commproc.h" +#endif + +static int opened = 0; +static int found = 0; + +/* + * Define the fixed address of the FEC hardware. + */ +#ifdef CONFIG_M5272 +static volatile fec_t *fec_hwp = (volatile fec_t *) (MCF_MBAR + 0x840); +static ushort my_enet_addr[] = { 0x00d0, 0xcf00, 0x0072 }; +#else +static volatile fec_t *fec_hwp = &(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec) +static ushort my_enet_addr[3]; +#endif /* CONFIG_M5272 */ + +/* + * Some hardware gets it MAC address out of local flash memory. + * if this is non-zero then assume it is the address to get MAC from. + */ +#if defined(CONFIG_NETtel) +#define FEC_FLASHMAC 0xf0006006 +#elif defined(CONFIG_GILBARCONAP) +#define FEC_FLASHMAC 0xf0006000 +#elif defined (CONFIG_MTD_KeyTechnology) +#define FEC_FLASHMAC 0xffe04000 +#else +#define FEC_FLASHMAC 0 +#endif + +unsigned char *fec_flashmac = (unsigned char *) FEC_FLASHMAC; + +/* Forward declarations of some structures to support different PHYs +*/ + +typedef struct { + uint mii_data; + void (*funct)(uint mii_reg, struct net_device *dev); +} phy_cmd_t; + +typedef struct { + uint id; + char *name; + + const phy_cmd_t *config; + const phy_cmd_t *startup; + const phy_cmd_t *ack_int; + const phy_cmd_t *shutdown; +} phy_info_t; + +/* The number of Tx and Rx buffers. These are allocated from the page + * pool. The code may assume these are power of two, so it it best + * to keep them that size. + * We don't need to allocate pages for the transmitter. We just use + * the skbuffer directly. + */ +#if 1 +#define FEC_ENET_RX_PAGES 4 +#define FEC_ENET_RX_FRSIZE 2048 +#define FEC_ENET_RX_FRPPG (PAGE_SIZE / FEC_ENET_RX_FRSIZE) +#define RX_RING_SIZE (FEC_ENET_RX_FRPPG * FEC_ENET_RX_PAGES) +#define TX_RING_SIZE 8 /* Must be power of two */ +#define TX_RING_MOD_MASK 7 /* for this to work */ +#else +#define FEC_ENET_RX_PAGES 16 +#define FEC_ENET_RX_FRSIZE 2048 +#define FEC_ENET_RX_FRPPG (PAGE_SIZE / FEC_ENET_RX_FRSIZE) +#define RX_RING_SIZE (FEC_ENET_RX_FRPPG * FEC_ENET_RX_PAGES) +#define TX_RING_SIZE 16 /* Must be power of two */ +#define TX_RING_MOD_MASK 15 /* for this to work */ +#endif + +/* Interrupt events/masks. +*/ +#define FEC_ENET_HBERR ((uint)0x80000000) /* Heartbeat error */ +#define FEC_ENET_BABR ((uint)0x40000000) /* Babbling receiver */ +#define FEC_ENET_BABT ((uint)0x20000000) /* Babbling transmitter */ +#define FEC_ENET_GRA ((uint)0x10000000) /* Graceful stop complete */ +#define FEC_ENET_TXF ((uint)0x08000000) /* Full frame transmitted */ +#define FEC_ENET_TXB ((uint)0x04000000) /* A buffer was transmitted */ +#define FEC_ENET_RXF ((uint)0x02000000) /* Full frame received */ +#define FEC_ENET_RXB ((uint)0x01000000) /* A buffer was received */ +#define FEC_ENET_MII ((uint)0x00800000) /* MII interrupt */ +#define FEC_ENET_EBERR ((uint)0x00400000) /* SDMA bus error */ + +/* The FEC stores dest/src/type, data, and checksum for receive packets. + */ +#define PKT_MAXBUF_SIZE 1518 +#define PKT_MINBUF_SIZE 64 +#define PKT_MAXBLR_SIZE 1520 + +/* The FEC buffer descriptors track the ring buffers. The rx_bd_base and + * tx_bd_base always point to the base of the buffer descriptors. The + * cur_rx and cur_tx point to the currently available buffer. + * The dirty_tx tracks the current buffer that is being sent by the + * controller. The cur_tx and dirty_tx are equal under both completely + * empty and completely full conditions. The empty/ready indicator in + * the buffer descriptor determines the actual condition. + */ +struct fec_enet_private { + /* The saved address of a sent-in-place packet/buffer, for skfree(). */ + struct sk_buff* tx_skbuff[TX_RING_SIZE]; + ushort skb_cur; + ushort skb_dirty; + + /* CPM dual port RAM relative addresses. + */ + cbd_t *rx_bd_base; /* Address of Rx and Tx buffers. */ + cbd_t *tx_bd_base; + cbd_t *cur_rx, *cur_tx; /* The next free ring entry */ + cbd_t *dirty_tx; /* The ring entries to be free()ed. */ + struct net_device_stats stats; + uint tx_full; + spinlock_t lock; + + uint phy_id; + uint phy_id_done; + uint phy_status; + uint phy_speed; + phy_info_t *phy; + struct work_struct phy_task; + + uint sequence_done; + + uint phy_addr; + + int link; + int old_link; + int full_duplex; +}; + +static int fec_enet_open(struct net_device *dev); +static int fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev); +static void fec_enet_mii(struct net_device *dev); +static void fec_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs); +static void fec_enet_tx(struct net_device *dev); +static void fec_enet_rx(struct net_device *dev); +static int fec_enet_close(struct net_device *dev); +static struct net_device_stats *fec_enet_get_stats(struct net_device *dev); +static void set_multicast_list(struct net_device *dev); +static void fec_restart(struct net_device *dev, int duplex); +static void fec_stop(struct net_device *dev); + + +/* MII processing. We keep this as simple as possible. Requests are + * placed on the list (if there is room). When the request is finished + * by the MII, an optional function may be called. + */ +typedef struct mii_list { + uint mii_regval; + void (*mii_func)(uint val, struct net_device *dev); + struct mii_list *mii_next; +} mii_list_t; + +#define NMII 20 +mii_list_t mii_cmds[NMII]; +mii_list_t *mii_free; +mii_list_t *mii_head; +mii_list_t *mii_tail; + +static int mii_queue(struct net_device *dev, int request, + void (*func)(uint, struct net_device *)); + +/* Make MII read/write commands for the FEC. +*/ +#define mk_mii_read(REG) (0x60020000 | ((REG & 0x1f) << 18)) +#define mk_mii_write(REG, VAL) (0x50020000 | ((REG & 0x1f) << 18) | \ + (VAL & 0xffff)) +#define mk_mii_end 0 + +/* Transmitter timeout. +*/ +#define TX_TIMEOUT (2*HZ) + +/* Register definitions for the PHY. +*/ + +#define MII_REG_CR 0 /* Control Register */ +#define MII_REG_SR 1 /* Status Register */ +#define MII_REG_PHYIR1 2 /* PHY Identification Register 1 */ +#define MII_REG_PHYIR2 3 /* PHY Identification Register 2 */ +#define MII_REG_ANAR 4 /* A-N Advertisement Register */ +#define MII_REG_ANLPAR 5 /* A-N Link Partner Ability Register */ +#define MII_REG_ANER 6 /* A-N Expansion Register */ +#define MII_REG_ANNPTR 7 /* A-N Next Page Transmit Register */ +#define MII_REG_ANLPRNPR 8 /* A-N Link Partner Received Next Page Reg. */ + +/* values for phy_status */ + +#define PHY_CONF_ANE 0x0001 /* 1 auto-negotiation enabled */ +#define PHY_CONF_LOOP 0x0002 /* 1 loopback mode enabled */ +#define PHY_CONF_SPMASK 0x00f0 /* mask for speed */ +#define PHY_CONF_10HDX 0x0010 /* 10 Mbit half duplex supported */ +#define PHY_CONF_10FDX 0x0020 /* 10 Mbit full duplex supported */ +#define PHY_CONF_100HDX 0x0040 /* 100 Mbit half duplex supported */ +#define PHY_CONF_100FDX 0x0080 /* 100 Mbit full duplex supported */ + +#define PHY_STAT_LINK 0x0100 /* 1 up - 0 down */ +#define PHY_STAT_FAULT 0x0200 /* 1 remote fault */ +#define PHY_STAT_ANC 0x0400 /* 1 auto-negotiation complete */ +#define PHY_STAT_SPMASK 0xf000 /* mask for speed */ +#define PHY_STAT_10HDX 0x1000 /* 10 Mbit half duplex selected */ +#define PHY_STAT_10FDX 0x2000 /* 10 Mbit full duplex selected */ +#define PHY_STAT_100HDX 0x4000 /* 100 Mbit half duplex selected */ +#define PHY_STAT_100FDX 0x8000 /* 100 Mbit full duplex selected */ + + +static int +fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct fec_enet_private *fep; + volatile fec_t *fecp; + volatile cbd_t *bdp; + + fep = dev->priv; + fecp = (volatile fec_t*)dev->base_addr; + + if (!fep->link) { + /* Link is down or autonegotiation is in progress. */ + return 1; + } + + /* Fill in a Tx ring entry */ + bdp = fep->cur_tx; + +#ifndef final_version + if (bdp->cbd_sc & BD_ENET_TX_READY) { + /* Ooops. All transmit buffers are full. Bail out. + * This should not happen, since dev->tbusy should be set. + */ + printk("%s: tx queue full!.\n", dev->name); + return 1; + } +#endif + + /* Clear all of the status flags. + */ + bdp->cbd_sc &= ~BD_ENET_TX_STATS; + + /* Set buffer length and buffer pointer. + */ + bdp->cbd_bufaddr = __pa(skb->data); + bdp->cbd_datlen = skb->len; + + /* Save skb pointer. + */ + fep->tx_skbuff[fep->skb_cur] = skb; + + fep->stats.tx_bytes += skb->len; + fep->skb_cur = (fep->skb_cur+1) & TX_RING_MOD_MASK; + + /* Push the data cache so the CPM does not get stale memory + * data. + */ + flush_dcache_range((unsigned long)skb->data, + (unsigned long)skb->data + skb->len); + + spin_lock_irq(&fep->lock); + + /* Send it on its way. Tell FEC its ready, interrupt when done, + * its the last BD of the frame, and to put the CRC on the end. + */ + + bdp->cbd_sc |= (BD_ENET_TX_READY | BD_ENET_TX_INTR + | BD_ENET_TX_LAST | BD_ENET_TX_TC); + + dev->trans_start = jiffies; + + /* Trigger transmission start */ + fecp->fec_x_des_active = 0x01000000; + + /* If this was the last BD in the ring, start at the beginning again. + */ + if (bdp->cbd_sc & BD_ENET_TX_WRAP) { + bdp = fep->tx_bd_base; + } else { + bdp++; + } + + if (bdp == fep->dirty_tx) { + fep->tx_full = 1; + netif_stop_queue(dev); + } + + fep->cur_tx = (cbd_t *)bdp; + + spin_unlock_irq(&fep->lock); + + return 0; +} + +static void +fec_timeout(struct net_device *dev) +{ + struct fec_enet_private *fep = dev->priv; + + printk("%s: transmit timed out.\n", dev->name); + fep->stats.tx_errors++; +#ifndef final_version + { + int i; + cbd_t *bdp; + + printk("Ring data dump: cur_tx %lx%s, dirty_tx %lx cur_rx: %lx\n", + (unsigned long)fep->cur_tx, fep->tx_full ? " (full)" : "", + (unsigned long)fep->dirty_tx, + (unsigned long)fep->cur_rx); + + bdp = fep->tx_bd_base; + printk(" tx: %u buffers\n", TX_RING_SIZE); + for (i = 0 ; i < TX_RING_SIZE; i++) { + printk(" %08x: %04x %04x %08x\n", + (uint) bdp, + bdp->cbd_sc, + bdp->cbd_datlen, + (int) bdp->cbd_bufaddr); + bdp++; + } + + bdp = fep->rx_bd_base; + printk(" rx: %lu buffers\n", (unsigned long) RX_RING_SIZE); + for (i = 0 ; i < RX_RING_SIZE; i++) { + printk(" %08x: %04x %04x %08x\n", + (uint) bdp, + bdp->cbd_sc, + bdp->cbd_datlen, + (int) bdp->cbd_bufaddr); + bdp++; + } + } +#endif + fec_restart(dev, 0); + netif_wake_queue(dev); +} + +/* The interrupt handler. + * This is called from the MPC core interrupt. + */ +static void +fec_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs) +{ + struct net_device *dev = dev_id; + volatile fec_t *fecp; + uint int_events; + + fecp = (volatile fec_t*)dev->base_addr; + + /* Get the interrupt events that caused us to be here. + */ + while ((int_events = fecp->fec_ievent) != 0) { + fecp->fec_ievent = int_events; + if ((int_events & (FEC_ENET_HBERR | FEC_ENET_BABR | + FEC_ENET_BABT | FEC_ENET_EBERR)) != 0) { + printk("FEC ERROR %x\n", int_events); + } + + /* Handle receive event in its own function. + */ + if (int_events & FEC_ENET_RXF) + fec_enet_rx(dev); + + /* Transmit OK, or non-fatal error. Update the buffer + descriptors. FEC handles all errors, we just discover + them as part of the transmit process. + */ + if (int_events & FEC_ENET_TXF) + fec_enet_tx(dev); + + if (int_events & FEC_ENET_MII) + fec_enet_mii(dev); + + } +} + + +static void +fec_enet_tx(struct net_device *dev) +{ + struct fec_enet_private *fep; + volatile cbd_t *bdp; + struct sk_buff *skb; + + fep = dev->priv; + spin_lock(&fep->lock); + bdp = fep->dirty_tx; + + while ((bdp->cbd_sc&BD_ENET_TX_READY) == 0) { + if (bdp == fep->cur_tx && fep->tx_full == 0) break; + + skb = fep->tx_skbuff[fep->skb_dirty]; + /* Check for errors. */ + if (bdp->cbd_sc & (BD_ENET_TX_HB | BD_ENET_TX_LC | + BD_ENET_TX_RL | BD_ENET_TX_UN | + BD_ENET_TX_CSL)) { + fep->stats.tx_errors++; + if (bdp->cbd_sc & BD_ENET_TX_HB) /* No heartbeat */ + fep->stats.tx_heartbeat_errors++; + if (bdp->cbd_sc & BD_ENET_TX_LC) /* Late collision */ + fep->stats.tx_window_errors++; + if (bdp->cbd_sc & BD_ENET_TX_RL) /* Retrans limit */ + fep->stats.tx_aborted_errors++; + if (bdp->cbd_sc & BD_ENET_TX_UN) /* Underrun */ + fep->stats.tx_fifo_errors++; + if (bdp->cbd_sc & BD_ENET_TX_CSL) /* Carrier lost */ + fep->stats.tx_carrier_errors++; + } else { + fep->stats.tx_packets++; + } + +#ifndef final_version + if (bdp->cbd_sc & BD_ENET_TX_READY) + printk("HEY! Enet xmit interrupt and TX_READY.\n"); +#endif + /* Deferred means some collisions occurred during transmit, + * but we eventually sent the packet OK. + */ + if (bdp->cbd_sc & BD_ENET_TX_DEF) + fep->stats.collisions++; + + /* Free the sk buffer associated with this last transmit. + */ + dev_kfree_skb_any(skb); + fep->tx_skbuff[fep->skb_dirty] = NULL; + fep->skb_dirty = (fep->skb_dirty + 1) & TX_RING_MOD_MASK; + + /* Update pointer to next buffer descriptor to be transmitted. + */ + if (bdp->cbd_sc & BD_ENET_TX_WRAP) + bdp = fep->tx_bd_base; + else + bdp++; + + /* Since we have freed up a buffer, the ring is no longer + * full. + */ + if (fep->tx_full) { + fep->tx_full = 0; + if (netif_queue_stopped(dev)) + netif_wake_queue(dev); + } + } + fep->dirty_tx = (cbd_t *)bdp; + spin_unlock(&fep->lock); +} + + +/* During a receive, the cur_rx points to the current incoming buffer. + * When we update through the ring, if the next incoming buffer has + * not been given to the system, we just set the empty indicator, + * effectively tossing the packet. + */ +static void +fec_enet_rx(struct net_device *dev) +{ + struct fec_enet_private *fep; + volatile fec_t *fecp; + volatile cbd_t *bdp; + struct sk_buff *skb; + ushort pkt_len; + __u8 *data; + + fep = dev->priv; + fecp = (volatile fec_t*)dev->base_addr; + + /* First, grab all of the stats for the incoming packet. + * These get messed up if we get called due to a busy condition. + */ + bdp = fep->cur_rx; + +while (!(bdp->cbd_sc & BD_ENET_RX_EMPTY)) { + +#ifndef final_version + /* Since we have allocated space to hold a complete frame, + * the last indicator should be set. + */ + if ((bdp->cbd_sc & BD_ENET_RX_LAST) == 0) + printk("FEC ENET: rcv is not +last\n"); +#endif + + if (!opened) + goto rx_processing_done; + + /* Check for errors. */ + if (bdp->cbd_sc & (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_NO | + BD_ENET_RX_CR | BD_ENET_RX_OV)) { + fep->stats.rx_errors++; + if (bdp->cbd_sc & (BD_ENET_RX_LG | BD_ENET_RX_SH)) { + /* Frame too long or too short. */ + fep->stats.rx_length_errors++; + } + if (bdp->cbd_sc & BD_ENET_RX_NO) /* Frame alignment */ + fep->stats.rx_frame_errors++; + if (bdp->cbd_sc & BD_ENET_RX_CR) /* CRC Error */ + fep->stats.rx_crc_errors++; + if (bdp->cbd_sc & BD_ENET_RX_OV) /* FIFO overrun */ + fep->stats.rx_crc_errors++; + } + + /* Report late collisions as a frame error. + * On this error, the BD is closed, but we don't know what we + * have in the buffer. So, just drop this frame on the floor. + */ + if (bdp->cbd_sc & BD_ENET_RX_CL) { + fep->stats.rx_errors++; + fep->stats.rx_frame_errors++; + goto rx_processing_done; + } + + /* Process the incoming frame. + */ + fep->stats.rx_packets++; + pkt_len = bdp->cbd_datlen; + fep->stats.rx_bytes += pkt_len; + data = (__u8*)__va(bdp->cbd_bufaddr); + + /* This does 16 byte alignment, exactly what we need. + * The packet length includes FCS, but we don't want to + * include that when passing upstream as it messes up + * bridging applications. + */ + skb = dev_alloc_skb(pkt_len-4); + + if (skb == NULL) { + printk("%s: Memory squeeze, dropping packet.\n", dev->name); + fep->stats.rx_dropped++; + } else { + skb->dev = dev; + skb_put(skb,pkt_len-4); /* Make room */ + eth_copy_and_sum(skb, + (unsigned char *)__va(bdp->cbd_bufaddr), + pkt_len-4, 0); + skb->protocol=eth_type_trans(skb,dev); + netif_rx(skb); + } + rx_processing_done: + + /* Clear the status flags for this buffer. + */ + bdp->cbd_sc &= ~BD_ENET_RX_STATS; + + /* Mark the buffer empty. + */ + bdp->cbd_sc |= BD_ENET_RX_EMPTY; + + /* Update BD pointer to next entry. + */ + if (bdp->cbd_sc & BD_ENET_RX_WRAP) + bdp = fep->rx_bd_base; + else + bdp++; + +#if 1 + /* Doing this here will keep the FEC running while we process + * incoming frames. On a heavily loaded network, we should be + * able to keep up at the expense of system resources. + */ + fecp->fec_r_des_active = 0x01000000; +#endif + } /* while (!(bdp->cbd_sc & BD_ENET_RX_EMPTY)) */ + fep->cur_rx = (cbd_t *)bdp; + +#if 0 + /* Doing this here will allow us to process all frames in the + * ring before the FEC is allowed to put more there. On a heavily + * loaded network, some frames may be lost. Unfortunately, this + * increases the interrupt overhead since we can potentially work + * our way back to the interrupt return only to come right back + * here. + */ + fecp->fec_r_des_active = 0x01000000; +#endif +} + + +static void +fec_enet_mii(struct net_device *dev) +{ + struct fec_enet_private *fep; + volatile fec_t *ep; + mii_list_t *mip; + uint mii_reg; + + fep = (struct fec_enet_private *)dev->priv; + ep = fec_hwp; + mii_reg = ep->fec_mii_data; + + if ((mip = mii_head) == NULL) { + printk("MII and no head!\n"); + return; + } + + if (mip->mii_func != NULL) + (*(mip->mii_func))(mii_reg, dev); + + mii_head = mip->mii_next; + mip->mii_next = mii_free; + mii_free = mip; + + if ((mip = mii_head) != NULL) + ep->fec_mii_data = mip->mii_regval; +} + +static int +mii_queue(struct net_device *dev, int regval, void (*func)(uint, struct net_device *)) +{ + struct fec_enet_private *fep; + unsigned long flags; + mii_list_t *mip; + int retval; + + /* Add PHY address to register command. + */ + fep = dev->priv; + regval |= fep->phy_addr << 23; + + retval = 0; + + save_flags(flags); + cli(); + + if ((mip = mii_free) != NULL) { + mii_free = mip->mii_next; + mip->mii_regval = regval; + mip->mii_func = func; + mip->mii_next = NULL; + if (mii_head) { + mii_tail->mii_next = mip; + mii_tail = mip; + } + else { + mii_head = mii_tail = mip; + fec_hwp->fec_mii_data = regval; + } + } + else { + retval = 1; + } + + restore_flags(flags); + + return(retval); +} + +static void mii_do_cmd(struct net_device *dev, const phy_cmd_t *c) +{ + int k; + + if(!c) + return; + + for(k = 0; (c+k)->mii_data != mk_mii_end; k++) { + mii_queue(dev, (c+k)->mii_data, (c+k)->funct); + } +} + +static void mii_parse_sr(uint mii_reg, struct net_device *dev) +{ + struct fec_enet_private *fep = dev->priv; + volatile uint *s = &(fep->phy_status); + + *s &= ~(PHY_STAT_LINK | PHY_STAT_FAULT | PHY_STAT_ANC); + + if (mii_reg & 0x0004) + *s |= PHY_STAT_LINK; + if (mii_reg & 0x0010) + *s |= PHY_STAT_FAULT; + if (mii_reg & 0x0020) + *s |= PHY_STAT_ANC; +} + +static void mii_parse_cr(uint mii_reg, struct net_device *dev) +{ + struct fec_enet_private *fep = dev->priv; + volatile uint *s = &(fep->phy_status); + + *s &= ~(PHY_CONF_ANE | PHY_CONF_LOOP); + + if (mii_reg & 0x1000) + *s |= PHY_CONF_ANE; + if (mii_reg & 0x4000) + *s |= PHY_CONF_LOOP; +} + +static void mii_parse_anar(uint mii_reg, struct net_device *dev) +{ + struct fec_enet_private *fep = dev->priv; + volatile uint *s = &(fep->phy_status); + + *s &= ~(PHY_CONF_SPMASK); + + if (mii_reg & 0x0020) + *s |= PHY_CONF_10HDX; + if (mii_reg & 0x0040) + *s |= PHY_CONF_10FDX; + if (mii_reg & 0x0080) + *s |= PHY_CONF_100HDX; + if (mii_reg & 0x00100) + *s |= PHY_CONF_100FDX; +} + +/* ------------------------------------------------------------------------- */ +/* The Level one LXT970 is used by many boards */ + +#define MII_LXT970_MIRROR 16 /* Mirror register */ +#define MII_LXT970_IER 17 /* Interrupt Enable Register */ +#define MII_LXT970_ISR 18 /* Interrupt Status Register */ +#define MII_LXT970_CONFIG 19 /* Configuration Register */ +#define MII_LXT970_CSR 20 /* Chip Status Register */ + +static void mii_parse_lxt970_csr(uint mii_reg, struct net_device *dev) +{ + struct fec_enet_private *fep = dev->priv; + volatile uint *s = &(fep->phy_status); + + *s &= ~(PHY_STAT_SPMASK); + + if (mii_reg & 0x0800) { + if (mii_reg & 0x1000) + *s |= PHY_STAT_100FDX; + else + *s |= PHY_STAT_100HDX; + } else { + if (mii_reg & 0x1000) + *s |= PHY_STAT_10FDX; + else + *s |= PHY_STAT_10HDX; + } +} + +static phy_info_t phy_info_lxt970 = { + 0x07810000, + "LXT970", + + (const phy_cmd_t []) { /* config */ + { mk_mii_read(MII_REG_CR), mii_parse_cr }, + { mk_mii_read(MII_REG_ANAR), mii_parse_anar }, + { mk_mii_end, } + }, + (const phy_cmd_t []) { /* startup - enable interrupts */ + { mk_mii_write(MII_LXT970_IER, 0x0002), NULL }, + { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */ + { mk_mii_end, } + }, + (const phy_cmd_t []) { /* ack_int */ + /* read SR and ISR to acknowledge */ + { mk_mii_read(MII_REG_SR), mii_parse_sr }, + { mk_mii_read(MII_LXT970_ISR), NULL }, + + /* find out the current status */ + { mk_mii_read(MII_LXT970_CSR), mii_parse_lxt970_csr }, + { mk_mii_end, } + }, + (const phy_cmd_t []) { /* shutdown - disable interrupts */ + { mk_mii_write(MII_LXT970_IER, 0x0000), NULL }, + { mk_mii_end, } + }, +}; + +/* ------------------------------------------------------------------------- */ +/* The Level one LXT971 is used on some of my custom boards */ + +/* register definitions for the 971 */ + +#define MII_LXT971_PCR 16 /* Port Control Register */ +#define MII_LXT971_SR2 17 /* Status Register 2 */ +#define MII_LXT971_IER 18 /* Interrupt Enable Register */ +#define MII_LXT971_ISR 19 /* Interrupt Status Register */ +#define MII_LXT971_LCR 20 /* LED Control Register */ +#define MII_LXT971_TCR 30 /* Transmit Control Register */ + +/* + * I had some nice ideas of running the MDIO faster... + * The 971 should support 8MHz and I tried it, but things acted really + * wierd, so 2.5 MHz ought to be enough for anyone... + */ + +static void mii_parse_lxt971_sr2(uint mii_reg, struct net_device *dev) +{ + struct fec_enet_private *fep = dev->priv; + volatile uint *s = &(fep->phy_status); + + *s &= ~(PHY_STAT_SPMASK | PHY_STAT_LINK | PHY_STAT_ANC); + + if (mii_reg & 0x0400) { + fep->link = 1; + *s |= PHY_STAT_LINK; + } else { + fep->link = 0; + } + if (mii_reg & 0x0080) + *s |= PHY_STAT_ANC; + if (mii_reg & 0x4000) { + if (mii_reg & 0x0200) + *s |= PHY_STAT_100FDX; + else + *s |= PHY_STAT_100HDX; + } else { + if (mii_reg & 0x0200) + *s |= PHY_STAT_10FDX; + else + *s |= PHY_STAT_10HDX; + } + if (mii_reg & 0x0008) + *s |= PHY_STAT_FAULT; +} + +static phy_info_t phy_info_lxt971 = { + 0x0001378e, + "LXT971", + + (const phy_cmd_t []) { /* config */ + /* limit to 10MBit because my protorype board + * doesn't work with 100. */ + { mk_mii_read(MII_REG_CR), mii_parse_cr }, + { mk_mii_read(MII_REG_ANAR), mii_parse_anar }, + { mk_mii_read(MII_LXT971_SR2), mii_parse_lxt971_sr2 }, + { mk_mii_end, } + }, + (const phy_cmd_t []) { /* startup - enable interrupts */ + { mk_mii_write(MII_LXT971_IER, 0x00f2), NULL }, + { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */ + { mk_mii_write(MII_LXT971_LCR, 0xd422), NULL }, /* LED config */ + /* Somehow does the 971 tell me that the link is down + * the first read after power-up. + * read here to get a valid value in ack_int */ + { mk_mii_read(MII_REG_SR), mii_parse_sr }, + { mk_mii_end, } + }, + (const phy_cmd_t []) { /* ack_int */ + /* find out the current status */ + { mk_mii_read(MII_REG_SR), mii_parse_sr }, + { mk_mii_read(MII_LXT971_SR2), mii_parse_lxt971_sr2 }, + /* we only need to read ISR to acknowledge */ + { mk_mii_read(MII_LXT971_ISR), NULL }, + { mk_mii_end, } + }, + (const phy_cmd_t []) { /* shutdown - disable interrupts */ + { mk_mii_write(MII_LXT971_IER, 0x0000), NULL }, + { mk_mii_end, } + }, +}; + +/* ------------------------------------------------------------------------- */ +/* The Quality Semiconductor QS6612 is used on the RPX CLLF */ + +/* register definitions */ + +#define MII_QS6612_MCR 17 /* Mode Control Register */ +#define MII_QS6612_FTR 27 /* Factory Test Register */ +#define MII_QS6612_MCO 28 /* Misc. Control Register */ +#define MII_QS6612_ISR 29 /* Interrupt Source Register */ +#define MII_QS6612_IMR 30 /* Interrupt Mask Register */ +#define MII_QS6612_PCR 31 /* 100BaseTx PHY Control Reg. */ + +static void mii_parse_qs6612_pcr(uint mii_reg, struct net_device *dev) +{ + struct fec_enet_private *fep = dev->priv; + volatile uint *s = &(fep->phy_status); + + *s &= ~(PHY_STAT_SPMASK); + + switch((mii_reg >> 2) & 7) { + case 1: *s |= PHY_STAT_10HDX; break; + case 2: *s |= PHY_STAT_100HDX; break; + case 5: *s |= PHY_STAT_10FDX; break; + case 6: *s |= PHY_STAT_100FDX; break; + } +} + +static phy_info_t phy_info_qs6612 = { + 0x00181440, + "QS6612", + + (const phy_cmd_t []) { /* config */ + /* The PHY powers up isolated on the RPX, + * so send a command to allow operation. + */ + { mk_mii_write(MII_QS6612_PCR, 0x0dc0), NULL }, + + /* parse cr and anar to get some info */ + { mk_mii_read(MII_REG_CR), mii_parse_cr }, + { mk_mii_read(MII_REG_ANAR), mii_parse_anar }, + { mk_mii_end, } + }, + (const phy_cmd_t []) { /* startup - enable interrupts */ + { mk_mii_write(MII_QS6612_IMR, 0x003a), NULL }, + { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */ + { mk_mii_end, } + }, + (const phy_cmd_t []) { /* ack_int */ + /* we need to read ISR, SR and ANER to acknowledge */ + { mk_mii_read(MII_QS6612_ISR), NULL }, + { mk_mii_read(MII_REG_SR), mii_parse_sr }, + { mk_mii_read(MII_REG_ANER), NULL }, + + /* read pcr to get info */ + { mk_mii_read(MII_QS6612_PCR), mii_parse_qs6612_pcr }, + { mk_mii_end, } + }, + (const phy_cmd_t []) { /* shutdown - disable interrupts */ + { mk_mii_write(MII_QS6612_IMR, 0x0000), NULL }, + { mk_mii_end, } + }, +}; + +/* ------------------------------------------------------------------------- */ +/* AMD AM79C874 phy */ + +/* register definitions for the 874 */ + +#define MII_AM79C874_MFR 16 /* Miscellaneous Feature Register */ +#define MII_AM79C874_ICSR 17 /* Interrupt/Status Register */ +#define MII_AM79C874_DR 18 /* Diagnostic Register */ +#define MII_AM79C874_PMLR 19 /* Power and Loopback Register */ +#define MII_AM79C874_MCR 21 /* ModeControl Register */ +#define MII_AM79C874_DC 23 /* Disconnect Counter */ +#define MII_AM79C874_REC 24 /* Recieve Error Counter */ + +static void mii_parse_am79c874_dr(uint mii_reg, struct net_device *dev) +{ + struct fec_enet_private *fep = dev->priv; + volatile uint *s = &(fep->phy_status); + + *s &= ~(PHY_STAT_SPMASK | PHY_STAT_ANC); + + if (mii_reg & 0x0080) + *s |= PHY_STAT_ANC; + if (mii_reg & 0x0400) + *s |= ((mii_reg & 0x0800) ? PHY_STAT_100FDX : PHY_STAT_100HDX); + else + *s |= ((mii_reg & 0x0800) ? PHY_STAT_10FDX : PHY_STAT_10HDX); +} + +static phy_info_t phy_info_am79c874 = { + 0x00022561, + "AM79C874", + + (const phy_cmd_t []) { /* config */ + /* limit to 10MBit because my protorype board + * doesn't work with 100. */ + { mk_mii_read(MII_REG_CR), mii_parse_cr }, + { mk_mii_read(MII_REG_ANAR), mii_parse_anar }, + { mk_mii_read(MII_AM79C874_DR), mii_parse_am79c874_dr }, + { mk_mii_end, } + }, + (const phy_cmd_t []) { /* startup - enable interrupts */ + { mk_mii_write(MII_AM79C874_ICSR, 0xff00), NULL }, + { mk_mii_write(MII_REG_CR, 0x1200), NULL }, /* autonegotiate */ + { mk_mii_read(MII_REG_SR), mii_parse_sr }, + { mk_mii_end, } + }, + (const phy_cmd_t []) { /* ack_int */ + /* find out the current status */ + { mk_mii_read(MII_REG_SR), mii_parse_sr }, + { mk_mii_read(MII_AM79C874_DR), mii_parse_am79c874_dr }, + /* we only need to read ISR to acknowledge */ + { mk_mii_read(MII_AM79C874_ICSR), NULL }, + { mk_mii_end, } + }, + (const phy_cmd_t []) { /* shutdown - disable interrupts */ + { mk_mii_write(MII_AM79C874_ICSR, 0x0000), NULL }, + { mk_mii_end, } + }, +}; + +/* ------------------------------------------------------------------------- */ + +static phy_info_t *phy_info[] = { + &phy_info_lxt970, + &phy_info_lxt971, + &phy_info_qs6612, + &phy_info_am79c874, + NULL +}; + +/* ------------------------------------------------------------------------- */ + +static void +#ifdef CONFIG_RPXCLASSIC +mii_link_interrupt(void *dev_id); +#else +mii_link_interrupt(int irq, void * dev_id, struct pt_regs * regs); +#endif + +#ifdef CONFIG_M5272 + +/* + * Code specific to Coldfire 5272 setup. + */ +static void __inline__ fec_request_intrs(struct net_device *dev, volatile fec_t *fecp) +{ + volatile unsigned long *icrp; + + /* Setup interrupt handlers. */ + if (request_irq(86, fec_enet_interrupt, 0, "fec(RX)", dev) != 0) + printk("FEC: Could not allocate FEC(RC) IRQ(86)!\n"); + if (request_irq(87, fec_enet_interrupt, 0, "fec(TX)", dev) != 0) + printk("FEC: Could not allocate FEC(RC) IRQ(87)!\n"); + if (request_irq(88, fec_enet_interrupt, 0, "fec(OTHER)", dev) != 0) + printk("FEC: Could not allocate FEC(OTHER) IRQ(88)!\n"); + if (request_irq(66, mii_link_interrupt, 0, "fec(MII)", dev) != 0) + printk("FEC: Could not allocate MII IRQ(66)!\n"); + + /* Unmask interrupt at ColdFire 5272 SIM */ + icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR3); + *icrp = 0x00000ddd; + icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1); + *icrp = (*icrp & 0x70777777) | 0x0d000000; +} + +static void __inline__ fec_set_mii(struct net_device *dev, struct fec_enet_private *fep) +{ + volatile fec_t *fecp; + fecp = fec_hwp; + + fecp->fec_r_cntrl = 0x04; + fecp->fec_x_cntrl = 0x00; + + /* Set MII speed to 2.5 MHz + */ + fecp->fec_mii_speed = fep->phy_speed = 0x0e; + + fec_restart(dev, 0); +} + +static void __inline__ fec_get_mac(struct net_device *dev, struct fec_enet_private *fep) +{ + volatile fec_t *fecp; + unsigned char *eap, *iap, tmpaddr[6]; + int i; + + fecp = fec_hwp; + eap = (unsigned char *) my_enet_addr; + + if (fec_flashmac) { + /* + * Get MAC address from FLASH. + * If it is all 1's or 0's, use the default. + */ + iap = fec_flashmac; + if ((iap[0] == 0) && (iap[1] == 0) && (iap[2] == 0) && + (iap[3] == 0) && (iap[4] == 0) && (iap[5] == 0)) + iap = eap; + if ((iap[0] == 0xff) && (iap[1] == 0xff) && (iap[2] == 0xff) && + (iap[3] == 0xff) && (iap[4] == 0xff) && (iap[5] == 0xff)) + iap = eap; + } else { + *((unsigned long *) &tmpaddr[0]) = fecp->fec_addr_low; + *((unsigned short *) &tmpaddr[4]) = (fecp->fec_addr_high >> 16); + iap = &tmpaddr[0]; + } + + for (i=0; i<6; i++) + dev->dev_addr[i] = *eap++ = *iap++; +} + +static void __inline__ fec_enable_phy_intr(void) +{ +} + +static void __inline__ fec_disable_phy_intr(void) +{ + volatile unsigned long *icrp; + icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1); + *icrp = (*icrp & 0x70777777) | 0x08000000; +} + +static void __inline__ fec_phy_ack_intr(void) +{ + volatile unsigned long *icrp; + /* Acknowledge the interrupt */ + icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1); + *icrp = (*icrp & 0x77777777) | 0x08000000; +} + +static void __inline__ fec_localhw_setup(void) +{ +} + +/* + * Do not need to make region uncached on 5272. + */ +static void __inline__ fec_uncache(unsigned long addr) +{ +} + +/* ------------------------------------------------------------------------- */ + +#else + +/* + * Code sepcific to the MPC860T setup. + */ +static void __inline__ fec_request_intrs(struct net_device *dev, volatile fec_t *fecp) +{ + volatile immap_t *immap; + + immap = (immap_t *)IMAP_ADDR; /* pointer to internal registers */ + + if (request_8xxirq(FEC_INTERRUPT, fec_enet_interrupt, 0, "fec", dev) != 0) + panic("Could not allocate FEC IRQ!"); + +#ifdef CONFIG_RPXCLASSIC + /* Make Port C, bit 15 an input that causes interrupts. + */ + immap->im_ioport.iop_pcpar &= ~0x0001; + immap->im_ioport.iop_pcdir &= ~0x0001; + immap->im_ioport.iop_pcso &= ~0x0001; + immap->im_ioport.iop_pcint |= 0x0001; + cpm_install_handler(CPMVEC_PIO_PC15, mii_link_interrupt, dev); + + /* Make LEDS reflect Link status. + */ + *((uint *) RPX_CSR_ADDR) &= ~BCSR2_FETHLEDMODE; +#endif +#ifdef CONFIG_FADS + if (request_8xxirq(SIU_IRQ2, mii_link_interrupt, 0, "mii", dev) != 0) + panic("Could not allocate MII IRQ!"); +#endif +} + +static void __inline__ fec_get_mac(struct net_device *dev, struct fec_enet_private *fep) +{ + unsigned char *eap, *iap, tmpaddr[6]; + bd_t *bd; + int i; + + eap = (unsigned char *)my_enet_addr; + iap = bd->bi_enetaddr; + bd = (bd_t *)__res; + +#ifdef CONFIG_RPXCLASSIC + /* The Embedded Planet boards have only one MAC address in + * the EEPROM, but can have two Ethernet ports. For the + * FEC port, we create another address by setting one of + * the address bits above something that would have (up to + * now) been allocated. + */ + for (i=0; i<6; i++) + tmpaddr[i] = *iap++; + tmpaddr[3] |= 0x80; + iap = tmpaddr; +#endif + + for (i=0; i<6; i++) + dev->dev_addr[i] = *eap++ = *iap++; +} + +static void __inline__ fec_set_mii(struct net_device *dev, struct fec_enet_private *fep) +{ + extern uint _get_IMMR(void); + volatile immap_t *immap; + volatile fec_t *fecp; + + fecp = fec_hwp; + immap = (immap_t *)IMAP_ADDR; /* pointer to internal registers */ + + /* Configure all of port D for MII. + */ + immap->im_ioport.iop_pdpar = 0x1fff; + + /* Bits moved from Rev. D onward. + */ + if ((_get_IMMR() & 0xffff) < 0x0501) + immap->im_ioport.iop_pddir = 0x1c58; /* Pre rev. D */ + else + immap->im_ioport.iop_pddir = 0x1fff; /* Rev. D and later */ + + /* Set MII speed to 2.5 MHz + */ + fecp->fec_mii_speed = fep->phy_speed = + ((bd->bi_busfreq * 1000000) / 2500000) & 0x7e; +} + +static void __inline__ fec_enable_phy_intr(void) +{ + volatile fec_t *fecp; + fecp = fec_hwp; + + /* Enable MII command finished interrupt + */ + fecp->fec_ivec = (FEC_INTERRUPT/2) << 29; +} + +static void __inline__ fec_disable_phy_intr(void) +{ +} + +static void __inline__ fec_phy_ack_intr(void) +{ +} + +static void __inline__ fec_localhw_setup(void) +{ + volatile fec_t *fecp; + fecp = fec_hwp; + + fecp->fec_r_hash = PKT_MAXBUF_SIZE; + /* Enable big endian and don't care about SDMA FC. + */ + fecp->fec_fun_code = 0x78000000; +} + +static void __inline__ fec_uncache(unsigned long addr) +{ + pte_t *pte; + pte = va_to_pte(mem_addr); + pte_val(*pte) |= _PAGE_NO_CACHE; + flush_tlb_page(init_mm.mmap, mem_addr); +} + +#endif + +/* ------------------------------------------------------------------------- */ + +static void mii_display_status(struct net_device *dev) +{ + struct fec_enet_private *fep = dev->priv; + volatile uint *s = &(fep->phy_status); + + if (!fep->link && !fep->old_link) { + /* Link is still down - don't print anything */ + return; + } + + printk("%s: status: ", dev->name); + + if (!fep->link) { + printk("link down"); + } else { + printk("link up"); + + switch(*s & PHY_STAT_SPMASK) { + case PHY_STAT_100FDX: printk(", 100MBit Full Duplex"); break; + case PHY_STAT_100HDX: printk(", 100MBit Half Duplex"); break; + case PHY_STAT_10FDX: printk(", 10MBit Full Duplex"); break; + case PHY_STAT_10HDX: printk(", 10MBit Half Duplex"); break; + default: + printk(", Unknown speed/duplex"); + } + + if (*s & PHY_STAT_ANC) + printk(", auto-negotiation complete"); + } + + if (*s & PHY_STAT_FAULT) + printk(", remote fault"); + + printk(".\n"); +} + +static void mii_display_config(struct net_device *dev) +{ + struct fec_enet_private *fep = dev->priv; + volatile uint *s = &(fep->phy_status); + + printk("%s: config: auto-negotiation ", dev->name); + + if (*s & PHY_CONF_ANE) + printk("on"); + else + printk("off"); + + if (*s & PHY_CONF_100FDX) + printk(", 100FDX"); + if (*s & PHY_CONF_100HDX) + printk(", 100HDX"); + if (*s & PHY_CONF_10FDX) + printk(", 10FDX"); + if (*s & PHY_CONF_10HDX) + printk(", 10HDX"); + if (!(*s & PHY_CONF_SPMASK)) + printk(", No speed/duplex selected?"); + + if (*s & PHY_CONF_LOOP) + printk(", loopback enabled"); + + printk(".\n"); + + fep->sequence_done = 1; +} + +static void mii_relink(struct net_device *dev) +{ + struct fec_enet_private *fep = dev->priv; + int duplex; + + fep->link = (fep->phy_status & PHY_STAT_LINK) ? 1 : 0; + mii_display_status(dev); + fep->old_link = fep->link; + + if (fep->link) { + duplex = 0; + if (fep->phy_status + & (PHY_STAT_100FDX | PHY_STAT_10FDX)) + duplex = 1; + fec_restart(dev, duplex); + } + else + fec_stop(dev); + +#if 0 + enable_irq(fep->mii_irq); +#endif + +} + +static void mii_queue_relink(uint mii_reg, struct net_device *dev) +{ + struct fec_enet_private *fep = dev->priv; + + INIT_WORK(&fep->phy_task, (void*)mii_relink, dev); + schedule_work(&fep->phy_task); +} + +static void mii_queue_config(uint mii_reg, struct net_device *dev) +{ + struct fec_enet_private *fep = dev->priv; + + INIT_WORK(&fep->phy_task, (void*)mii_display_config, dev); + schedule_work(&fep->phy_task); +} + + + +phy_cmd_t phy_cmd_relink[] = { { mk_mii_read(MII_REG_CR), mii_queue_relink }, + { mk_mii_end, } }; +phy_cmd_t phy_cmd_config[] = { { mk_mii_read(MII_REG_CR), mii_queue_config }, + { mk_mii_end, } }; + + + +/* Read remainder of PHY ID. +*/ +static void +mii_discover_phy3(uint mii_reg, struct net_device *dev) +{ + struct fec_enet_private *fep; + int i; + + fep = dev->priv; + fep->phy_id |= (mii_reg & 0xffff); + printk("fec: PHY @ 0x%x, ID 0x%08x", fep->phy_addr, fep->phy_id); + + for(i = 0; phy_info[i]; i++) { + if(phy_info[i]->id == (fep->phy_id >> 4)) + break; + } + + if (phy_info[i]) + printk(" -- %s\n", phy_info[i]->name); + else + printk(" -- unknown PHY!\n"); + + fep->phy = phy_info[i]; + fep->phy_id_done = 1; +} + +/* Scan all of the MII PHY addresses looking for someone to respond + * with a valid ID. This usually happens quickly. + */ +static void +mii_discover_phy(uint mii_reg, struct net_device *dev) +{ + struct fec_enet_private *fep; + volatile fec_t *fecp; + uint phytype; + + fep = dev->priv; + fecp = fec_hwp; + + if (fep->phy_addr < 32) { + if ((phytype = (mii_reg & 0xffff)) != 0xffff && phytype != 0) { + + /* Got first part of ID, now get remainder. + */ + fep->phy_id = phytype << 16; + mii_queue(dev, mk_mii_read(MII_REG_PHYIR2), + mii_discover_phy3); + } + else { + fep->phy_addr++; + mii_queue(dev, mk_mii_read(MII_REG_PHYIR1), + mii_discover_phy); + } + } else { + printk("FEC: No PHY device found.\n"); + /* Disable external MII interface */ + fecp->fec_mii_speed = fep->phy_speed = 0; + fec_disable_phy_intr(); + } +} + +/* This interrupt occurs when the PHY detects a link change. +*/ +static void +#ifdef CONFIG_RPXCLASSIC +mii_link_interrupt(void *dev_id) +#else +mii_link_interrupt(int irq, void * dev_id, struct pt_regs * regs) +#endif +{ + struct net_device *dev = dev_id; + struct fec_enet_private *fep = dev->priv; + + fec_phy_ack_intr(); + +#if 0 + disable_irq(fep->mii_irq); /* disable now, enable later */ +#endif + + mii_do_cmd(dev, fep->phy->ack_int); + mii_do_cmd(dev, phy_cmd_relink); /* restart and display status */ + +} + +static int +fec_enet_open(struct net_device *dev) +{ + struct fec_enet_private *fep = dev->priv; + + /* I should reset the ring buffers here, but I don't yet know + * a simple way to do that. + */ + + fep->sequence_done = 0; + fep->link = 0; + + if (fep->phy) { + mii_do_cmd(dev, fep->phy->ack_int); + mii_do_cmd(dev, fep->phy->config); + mii_do_cmd(dev, phy_cmd_config); /* display configuration */ + + while(!fep->sequence_done) + schedule(); + + mii_do_cmd(dev, fep->phy->startup); + } else { + fep->link = 1; /* lets just try it and see */ + /* no phy, go full duplex, it's most likely a hub chip */ + fec_restart(dev, 1); + } + + netif_start_queue(dev); + opened = 1; + return 0; /* Success */ +} + +static int +fec_enet_close(struct net_device *dev) +{ + /* Don't know what to do yet. + */ + opened = 0; + netif_stop_queue(dev); + fec_stop(dev); + + return 0; +} + +static struct net_device_stats *fec_enet_get_stats(struct net_device *dev) +{ + struct fec_enet_private *fep = (struct fec_enet_private *)dev->priv; + + return &fep->stats; +} + +/* Set or clear the multicast filter for this adaptor. + * Skeleton taken from sunlance driver. + * The CPM Ethernet implementation allows Multicast as well as individual + * MAC address filtering. Some of the drivers check to make sure it is + * a group multicast address, and discard those that are not. I guess I + * will do the same for now, but just remove the test if you want + * individual filtering as well (do the upper net layers want or support + * this kind of feature?). + */ + +#define HASH_BITS 6 /* #bits in hash */ +#define CRC32_POLY 0xEDB88320 + +static void set_multicast_list(struct net_device *dev) +{ + struct fec_enet_private *fep; + volatile fec_t *ep; + struct dev_mc_list *dmi; + unsigned int i, j, bit, data, crc; + unsigned char hash; + + fep = (struct fec_enet_private *)dev->priv; + ep = fec_hwp; + + if (dev->flags&IFF_PROMISC) { + /* Log any net taps. */ + printk("%s: Promiscuous mode enabled.\n", dev->name); + ep->fec_r_cntrl |= 0x0008; + } else { + + ep->fec_r_cntrl &= ~0x0008; + + if (dev->flags & IFF_ALLMULTI) { + /* Catch all multicast addresses, so set the + * filter to all 1's. + */ + ep->fec_hash_table_high = 0xffffffff; + ep->fec_hash_table_low = 0xffffffff; + } else { + /* Clear filter and add the addresses in hash register. + */ + ep->fec_hash_table_high = 0; + ep->fec_hash_table_low = 0; + + dmi = dev->mc_list; + + for (j = 0; j < dev->mc_count; j++, dmi = dmi->next) + { + /* Only support group multicast for now. + */ + if (!(dmi->dmi_addr[0] & 1)) + continue; + + /* calculate crc32 value of mac address + */ + crc = 0xffffffff; + + for (i = 0; i < dmi->dmi_addrlen; i++) + { + data = dmi->dmi_addr[i]; + for (bit = 0; bit < 8; bit++, data >>= 1) + { + crc = (crc >> 1) ^ + (((crc ^ data) & 1) ? CRC32_POLY : 0); + } + } + + /* only upper 6 bits (HASH_BITS) are used + which point to specific bit in he hash registers + */ + hash = (crc >> (32 - HASH_BITS)) & 0x3f; + + if (hash > 31) + ep->fec_hash_table_high |= 1 << (hash - 32); + else + ep->fec_hash_table_low |= 1 << hash; + } + } + } +} + +/* Initialize the FEC Ethernet on 860T (or ColdFire 5272). + */ +int __init fec_enet_init(struct net_device *dev) +{ + struct fec_enet_private *fep; + unsigned long mem_addr; + volatile cbd_t *bdp; + cbd_t *cbd_base; + volatile fec_t *fecp; + int i, j; + + /* Only allow us to be probed once. */ + if (found) + return(-ENXIO); + + /* Allocate some private information. + */ + fep = (struct fec_enet_private *)kmalloc(sizeof(*fep), GFP_KERNEL); + memset(fep, 0, sizeof(*fep)); + + /* Create an Ethernet device instance. + */ + fecp = fec_hwp; + + /* Whack a reset. We should wait for this. + */ + fecp->fec_ecntrl = 1; + udelay(10); + + /* Clear and enable interrupts */ + fecp->fec_ievent = 0xffc0; + fecp->fec_imask = (FEC_ENET_TXF | FEC_ENET_TXB | + FEC_ENET_RXF | FEC_ENET_RXB | FEC_ENET_MII); + fecp->fec_hash_table_high = 0; + fecp->fec_hash_table_low = 0; + fecp->fec_r_buff_size = PKT_MAXBLR_SIZE; + fecp->fec_ecntrl = 2; + fecp->fec_r_des_active = 0x01000000; + + /* Set the Ethernet address. If using multiple Enets on the 8xx, + * this needs some work to get unique addresses. + */ + fec_get_mac(dev, fep); + + /* Allocate memory for buffer descriptors. + */ + if (((RX_RING_SIZE + TX_RING_SIZE) * sizeof(cbd_t)) > PAGE_SIZE) { + printk("FEC init error. Need more space.\n"); + printk("FEC initialization failed.\n"); + return 1; + } + mem_addr = __get_free_page(GFP_KERNEL); + cbd_base = (cbd_t *)mem_addr; + + fec_uncache(mem_addr); + + /* Set receive and transmit descriptor base. + */ + fep->rx_bd_base = cbd_base; + fep->tx_bd_base = cbd_base + RX_RING_SIZE; + + fep->dirty_tx = fep->cur_tx = fep->tx_bd_base; + fep->cur_rx = fep->rx_bd_base; + + fep->skb_cur = fep->skb_dirty = 0; + + /* Initialize the receive buffer descriptors. + */ + bdp = fep->rx_bd_base; + for (i=0; icbd_sc = BD_ENET_RX_EMPTY; + bdp->cbd_bufaddr = __pa(mem_addr); + mem_addr += FEC_ENET_RX_FRSIZE; + bdp++; + } + } + + /* Set the last buffer to wrap. + */ + bdp--; + bdp->cbd_sc |= BD_SC_WRAP; + + /* ...and the same for transmmit. + */ + bdp = fep->tx_bd_base; + for (i=0; icbd_sc = 0; + bdp->cbd_bufaddr = 0; + bdp++; + } + + /* Set the last buffer to wrap. + */ + bdp--; + bdp->cbd_sc |= BD_SC_WRAP; + + /* Set receive and transmit descriptor base. + */ + fecp->fec_r_des_start = __pa((uint)(fep->rx_bd_base)); + fecp->fec_x_des_start = __pa((uint)(fep->tx_bd_base)); + + /* Install our interrupt handlers. This varies depending on + * the architecture. + */ + fec_request_intrs(dev, fecp); + + dev->base_addr = (unsigned long)fecp; + dev->priv = fep; + + ether_setup(dev); + + /* The FEC Ethernet specific entries in the device structure. */ + dev->open = fec_enet_open; + dev->hard_start_xmit = fec_enet_start_xmit; + dev->tx_timeout = fec_timeout; + dev->watchdog_timeo = TX_TIMEOUT; + dev->stop = fec_enet_close; + dev->get_stats = fec_enet_get_stats; + dev->set_multicast_list = set_multicast_list; + + for (i=0; iname); + for (i=0; i<5; i++) + printk("%02x:", dev->dev_addr[i]); + printk("%02x\n", dev->dev_addr[5]); + + /* Queue up command to detect the PHY and initialize the + * remainder of the interface. + */ + fep->phy_id_done = 0; + fep->phy_addr = 0; + mii_queue(dev, mk_mii_read(MII_REG_PHYIR1), mii_discover_phy); + + found++; + return 0; +} + +/* This function is called to start or restart the FEC during a link + * change. This only happens when switching between half and full + * duplex. + */ +static void +fec_restart(struct net_device *dev, int duplex) +{ + struct fec_enet_private *fep; + int i; + unsigned char *eap; + volatile cbd_t *bdp; + volatile fec_t *fecp; + + fecp = fec_hwp; + + fep = dev->priv; + + /* Whack a reset. We should wait for this. + */ + fecp->fec_ecntrl = 1; + udelay(10); + + /* Enable interrupts we wish to service. + */ + fecp->fec_imask = (FEC_ENET_TXF | FEC_ENET_TXB | + FEC_ENET_RXF | FEC_ENET_RXB | FEC_ENET_MII); + + /* Clear any outstanding interrupt. + */ + fecp->fec_ievent = 0xffc0; + fec_enable_phy_intr(); + + /* Set station address. + */ + fecp->fec_addr_low = (my_enet_addr[0] << 16) | my_enet_addr[1]; + fecp->fec_addr_high = (my_enet_addr[2] << 16); + + eap = (unsigned char *)&my_enet_addr[0]; + for (i=0; i<6; i++) + dev->dev_addr[i] = *eap++; + + /* Reset all multicast. + */ + fecp->fec_hash_table_high = 0; + fecp->fec_hash_table_low = 0; + + /* Set maximum receive buffer size. + */ + fecp->fec_r_buff_size = PKT_MAXBLR_SIZE; + + fec_localhw_setup(); + + /* Set receive and transmit descriptor base. + */ + fecp->fec_r_des_start = __pa((uint)(fep->rx_bd_base)); + fecp->fec_x_des_start = __pa((uint)(fep->tx_bd_base)); + + fep->dirty_tx = fep->cur_tx = fep->tx_bd_base; + fep->cur_rx = fep->rx_bd_base; + + /* Reset SKB transmit buffers. + */ + fep->skb_cur = fep->skb_dirty = 0; + for (i=0; i<=TX_RING_MOD_MASK; i++) { + if (fep->tx_skbuff[i] != NULL) { + dev_kfree_skb_any(fep->tx_skbuff[i]); + fep->tx_skbuff[i] = NULL; + } + } + + /* Initialize the receive buffer descriptors. + */ + bdp = fep->rx_bd_base; + for (i=0; icbd_sc = BD_ENET_RX_EMPTY; + bdp++; + } + + /* Set the last buffer to wrap. + */ + bdp--; + bdp->cbd_sc |= BD_SC_WRAP; + + /* ...and the same for transmmit. + */ + bdp = fep->tx_bd_base; + for (i=0; icbd_sc = 0; + bdp->cbd_bufaddr = 0; + bdp++; + } + + /* Set the last buffer to wrap. + */ + bdp--; + bdp->cbd_sc |= BD_SC_WRAP; + + /* Enable MII mode. + */ + if (duplex) { + fecp->fec_r_cntrl = 0x04; /* MII enable */ + fecp->fec_x_cntrl = 0x04; /* FD enable */ + } + else { + fecp->fec_r_cntrl = 0x06; /* MII enable|No Rcv on Xmit */ + fecp->fec_x_cntrl = 0x00; + } + fep->full_duplex = duplex; + + /* Set MII speed. + */ + fecp->fec_mii_speed = fep->phy_speed; + + /* And last, enable the transmit and receive processing. + */ + fecp->fec_ecntrl = 2; + fecp->fec_r_des_active = 0x01000000; +} + +static void +fec_stop(struct net_device *dev) +{ + volatile fec_t *fecp; + struct fec_enet_private *fep; + + fecp = fec_hwp; + fep = dev->priv; + + fecp->fec_x_cntrl = 0x01; /* Graceful transmit stop */ + + while(!(fecp->fec_ievent & 0x10000000)); + + /* Whack a reset. We should wait for this. + */ + fecp->fec_ecntrl = 1; + udelay(10); + + /* Clear outstanding MII command interrupts. + */ + fecp->fec_ievent = FEC_ENET_MII; + fec_enable_phy_intr(); + + fecp->fec_imask = FEC_ENET_MII; + fecp->fec_mii_speed = fep->phy_speed; +} + +static struct net_device fec_dev = { + .init = fec_enet_init, +}; + +static int __init fec_enet_module_init(void) +{ + if (register_netdev(&fec_dev) != 0) + return -EIO; + return(0); +} + +module_init(fec_enet_module_init); + +MODULE_LICENSE("GPL"); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/net/fec.h linux.2.5.45-ac1/drivers/net/fec.h --- linux.2.5.45/drivers/net/fec.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/drivers/net/fec.h 2002-10-31 15:05:21.000000000 +0000 @@ -0,0 +1,115 @@ +/****************************************************************************/ + +/* + * fec.h -- Fast Ethernet Controller for Motorola ColdFire 5272. + * + * (C) Copyright 2000-2001, Greg Ungerer (gerg@snapgear.com) + * (C) Copyright 2000-2001, Lineo (www.lineo.com) + */ + +/****************************************************************************/ +#ifndef FEC_H +#define FEC_H +/****************************************************************************/ + +/* + * Define device register set address map. + */ +typedef struct fec { + unsigned long fec_ecntrl; /* Ethernet control reg */ + unsigned long fec_ievent; /* Interrupt even reg */ + unsigned long fec_imask; /* Interrupt mask reg */ + unsigned long fec_ivec; /* Interrupt vec status reg */ + unsigned long fec_r_des_active; /* Receive descriptor reg */ + unsigned long fec_x_des_active; /* Transmit descriptor reg */ + unsigned long fec_reserved1[10]; + unsigned long fec_mii_data; /* MII manage frame reg */ + unsigned long fec_mii_speed; /* MII speed control reg */ + unsigned long fec_reserved2[17]; + unsigned long fec_r_bound; /* FIFO receive bound reg */ + unsigned long fec_r_fstart; /* FIFO receive start reg */ + unsigned long fec_reserved3[4]; + unsigned long fec_x_wmrk; /* FIFO transmit water mark */ + unsigned long fec_reserved4; + unsigned long fec_x_fstart; /* FIFO transmit start reg */ + unsigned long fec_reserved5[21]; + unsigned long fec_r_cntrl; /* Receive control reg */ + unsigned long fec_max_frm_len; /* Maximum frame length reg */ + unsigned long fec_reserved6[14]; + unsigned long fec_x_cntrl; /* Transmit Control reg */ + unsigned long fec_reserved7[158]; + unsigned long fec_addr_low; /* Low 32bits MAC address */ + unsigned long fec_addr_high; /* High 16bits MAC address */ + unsigned long fec_hash_table_high; /* High 32bits hash table */ + unsigned long fec_hash_table_low; /* Low 32bits hash table */ + unsigned long fec_r_des_start; /* Receive descriptor ring */ + unsigned long fec_x_des_start; /* Transmit descriptor ring */ + unsigned long fec_r_buff_size; /* Maximum receive buff size */ + unsigned long reserved8[9]; + unsigned long fec_fifo_ram[112]; /* FIFO RAM buffer */ +} fec_t; + + +/* + * Define the buffer descriptor structure. + */ +typedef struct bufdesc { + unsigned short cbd_sc; /* Control and status info */ + unsigned short cbd_datlen; /* Data length */ + unsigned long cbd_bufaddr; /* Buffer address */ +} cbd_t; + + +/* + * The following definitions courtesy of commproc.h, which where + * Copyright (c) 1997 Dan Malek (dmalek@jlc.net). + */ +#define BD_SC_EMPTY ((ushort)0x8000) /* Recieve is empty */ +#define BD_SC_READY ((ushort)0x8000) /* Transmit is ready */ +#define BD_SC_WRAP ((ushort)0x2000) /* Last buffer descriptor */ +#define BD_SC_INTRPT ((ushort)0x1000) /* Interrupt on change */ +#define BD_SC_CM ((ushort)0x0200) /* Continous mode */ +#define BD_SC_ID ((ushort)0x0100) /* Rec'd too many idles */ +#define BD_SC_P ((ushort)0x0100) /* xmt preamble */ +#define BD_SC_BR ((ushort)0x0020) /* Break received */ +#define BD_SC_FR ((ushort)0x0010) /* Framing error */ +#define BD_SC_PR ((ushort)0x0008) /* Parity error */ +#define BD_SC_OV ((ushort)0x0002) /* Overrun */ +#define BD_SC_CD ((ushort)0x0001) /* ?? */ + +/* Buffer descriptor control/status used by Ethernet receive. +*/ +#define BD_ENET_RX_EMPTY ((ushort)0x8000) +#define BD_ENET_RX_WRAP ((ushort)0x2000) +#define BD_ENET_RX_INTR ((ushort)0x1000) +#define BD_ENET_RX_LAST ((ushort)0x0800) +#define BD_ENET_RX_FIRST ((ushort)0x0400) +#define BD_ENET_RX_MISS ((ushort)0x0100) +#define BD_ENET_RX_LG ((ushort)0x0020) +#define BD_ENET_RX_NO ((ushort)0x0010) +#define BD_ENET_RX_SH ((ushort)0x0008) +#define BD_ENET_RX_CR ((ushort)0x0004) +#define BD_ENET_RX_OV ((ushort)0x0002) +#define BD_ENET_RX_CL ((ushort)0x0001) +#define BD_ENET_RX_STATS ((ushort)0x013f) /* All status bits */ + +/* Buffer descriptor control/status used by Ethernet transmit. +*/ +#define BD_ENET_TX_READY ((ushort)0x8000) +#define BD_ENET_TX_PAD ((ushort)0x4000) +#define BD_ENET_TX_WRAP ((ushort)0x2000) +#define BD_ENET_TX_INTR ((ushort)0x1000) +#define BD_ENET_TX_LAST ((ushort)0x0800) +#define BD_ENET_TX_TC ((ushort)0x0400) +#define BD_ENET_TX_DEF ((ushort)0x0200) +#define BD_ENET_TX_HB ((ushort)0x0100) +#define BD_ENET_TX_LC ((ushort)0x0080) +#define BD_ENET_TX_RL ((ushort)0x0040) +#define BD_ENET_TX_RCMASK ((ushort)0x003c) +#define BD_ENET_TX_UN ((ushort)0x0002) +#define BD_ENET_TX_CSL ((ushort)0x0001) +#define BD_ENET_TX_STATS ((ushort)0x03ff) /* All status bits */ + + +/****************************************************************************/ +#endif /* FEC_H */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/net/ibmlana.c linux.2.5.45-ac1/drivers/net/ibmlana.c --- linux.2.5.45/drivers/net/ibmlana.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.45-ac1/drivers/net/ibmlana.c 2002-10-31 15:05:21.000000000 +0000 @@ -260,7 +260,7 @@ else tda.link = addr + sizeof(tda_t); tda.link |= 1; - isa_memcpy_to_io(dev->mem_start + addr, &tda, sizeof(tda_t)); + isa_memcpy_toio(dev->mem_start + addr, &tda, sizeof(tda_t)); addr += sizeof(tda_t); baddr += PKTSIZE; } @@ -280,7 +280,7 @@ rra.starthi = 0; rra.cntlo = PKTSIZE >> 1; rra.cnthi = 0; - isa_memcpy_to_io(dev->mem_start + raddr, &rra, sizeof(rra_t)); + isa_memcpy_toio(dev->mem_start + raddr, &rra, sizeof(rra_t)); rda.status = 0; rda.length = 0; @@ -292,7 +292,7 @@ else rda.link = 1; rda.inuse = 1; - isa_memcpy_to_io(dev->mem_start + addr, &rda, sizeof(rda_t)); + isa_memcpy_toio(dev->mem_start + addr, &rda, sizeof(rda_t)); baddr += PKTSIZE; raddr += sizeof(rra_t); @@ -429,8 +429,8 @@ /* feed CDA into SONIC, initialize RCR value (always get broadcasts) */ - isa_memcpy_to_io(dev->mem_start, cams, sizeof(camentry_t) * camcnt); - isa_memcpy_to_io(dev->mem_start + (sizeof(camentry_t) * camcnt), &cammask, sizeof(cammask)); + isa_memcpy_toio(dev->mem_start, cams, sizeof(camentry_t) * camcnt); + isa_memcpy_toio(dev->mem_start + (sizeof(camentry_t) * camcnt), &cammask, sizeof(cammask)); #ifdef DEBUG printk("CAM setup:\n"); @@ -627,14 +627,14 @@ rda.link = 1; rda.inuse = 1; - isa_memcpy_to_io(dev->mem_start + rdaaddr, &rda, + isa_memcpy_toio(dev->mem_start + rdaaddr, &rda, sizeof(rda_t)); /* set up link and EOL = 0 in currently last descriptor. Only write the link field since the SONIC may currently already access the other fields. */ - isa_memcpy_to_io(dev->mem_start + lrdaaddr + 20, &rdaaddr, 4); + isa_memcpy_toio(dev->mem_start + lrdaaddr + 20, &rdaaddr, 4); /* advance indices */ @@ -833,7 +833,7 @@ if (tmplen < 60) tmplen = 60; baddr = priv->txbufstart + (priv->nexttxdescr * PKTSIZE); - isa_memcpy_to_io(dev->mem_start + baddr, skb->data, skb->len); + isa_memcpy_toio(dev->mem_start + baddr, skb->data, skb->len); /* copy filler into RAM - in case we're filling up... we're filling a bit more than necessary, but that doesn't harm @@ -845,7 +845,7 @@ unsigned int destoffs = skb->len, l = strlen(fill); while (destoffs < tmplen) { - isa_memcpy_to_io(dev->mem_start + baddr + destoffs, fill, l); + isa_memcpy_toio(dev->mem_start + baddr + destoffs, fill, l); destoffs += l; } } @@ -854,7 +854,7 @@ addr = priv->tdastart + (priv->nexttxdescr * sizeof(tda_t)); isa_memcpy_fromio(&tda, dev->mem_start + addr, sizeof(tda_t)); tda.length = tda.fraglength = tmplen; - isa_memcpy_to_io(dev->mem_start + addr, &tda, sizeof(tda_t)); + isa_memcpy_toio(dev->mem_start + addr, &tda, sizeof(tda_t)); /* if there were no active descriptors, trigger the SONIC */ spin_lock_irqsave(&priv->lock, flags); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/net/Kconfig linux.2.5.45-ac1/drivers/net/Kconfig --- linux.2.5.45/drivers/net/Kconfig 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.45-ac1/drivers/net/Kconfig 2002-11-01 16:34:54.000000000 +0000 @@ -1541,6 +1541,20 @@ MIPS-32-based Baget embedded system. This chipset is better known via the NE2100 cards. +config 68360_ENET + bool "Motorola 68360 ethernet controller" + depends on M68360 + help + Say Y here if you want to use the built-in ethernet controller of + the Motorola 68360 processor. + +config FEC + bool "FEC ethernet controller (of ColdFire 5272)" + depends on M5272 + help + Say Y here if you want to use the built-in 10/100 Fast ethernet + controller on the Motorola ColdFire 5272 processor. + endmenu # diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/net/Makefile linux.2.5.45-ac1/drivers/net/Makefile --- linux.2.5.45/drivers/net/Makefile 2002-10-31 14:57:04.000000000 +0000 +++ linux.2.5.45-ac1/drivers/net/Makefile 2002-10-31 15:05:21.000000000 +0000 @@ -83,6 +83,8 @@ obj-$(CONFIG_SK_G16) += sk_g16.o obj-$(CONFIG_HP100) += hp100.o obj-$(CONFIG_SMC9194) += smc9194.o +obj-$(CONFIG_FEC) += fec.o +obj-$(CONFIG_68360_ENET) += 68360enet.o obj-$(CONFIG_ARM_AM79C961A) += am79c961a.o obj-$(CONFIG_ARM_ETHERH) += 8390.o obj-$(CONFIG_WD80x3) += wd.o 8390.o diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/net/tokenring/olympic.c linux.2.5.45-ac1/drivers/net/tokenring/olympic.c --- linux.2.5.45/drivers/net/tokenring/olympic.c 2002-10-31 14:57:03.000000000 +0000 +++ linux.2.5.45-ac1/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.45/drivers/net/tulip/de2104x.c linux.2.5.45-ac1/drivers/net/tulip/de2104x.c --- linux.2.5.45/drivers/net/tulip/de2104x.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.45-ac1/drivers/net/tulip/de2104x.c 2002-10-31 17:22:25.000000000 +0000 @@ -2216,7 +2216,7 @@ .name = DRV_NAME, .id_table = de_pci_tbl, .probe = de_init_one, - .remove = de_remove_one, + .remove = __devexit_p(de_remove_one), #ifdef CONFIG_PM .suspend = de_suspend, .resume = de_resume, diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/net/tulip/de4x5.c linux.2.5.45-ac1/drivers/net/tulip/de4x5.c --- linux.2.5.45/drivers/net/tulip/de4x5.c 2002-10-31 14:57:02.000000000 +0000 +++ linux.2.5.45-ac1/drivers/net/tulip/de4x5.c 2002-11-01 14:51:29.000000000 +0000 @@ -874,6 +874,7 @@ struct de4x5_srom srom; int autosense; int useSROM; + struct pci_dev *pdev; } bus; /* @@ -1151,8 +1152,7 @@ if (lp->bus == EISA) { outb(WAKEUP, PCI_CFPM); } else { - pcibios_write_config_byte(lp->bus_num, lp->device << 3, - PCI_CFDA_PSM, WAKEUP); + pci_write_config_byte(lp->pdev, PCI_CFDA_PSM, WAKEUP); } mdelay(10); @@ -2222,11 +2222,12 @@ } /* Get the chip configuration revision register */ - pcibios_read_config_dword(pb, pdev->devfn, PCI_REVISION_ID, &cfrv); + pci_read_config_dword(pdev, PCI_REVISION_ID, &cfrv); /* Set the device number information */ lp->device = dev_num; lp->bus_num = pb; + lp->pdev = pdev; /* Set the chipset information */ if (is_DC2114x) { @@ -2242,27 +2243,27 @@ if ((irq == 0) || (irq == 0xff) || ((int)irq == -1)) continue; /* Check if I/O accesses and Bus Mastering are enabled */ - pcibios_read_config_word(pb, pdev->devfn, PCI_COMMAND, &status); + pci_read_config_word(pdev, PCI_COMMAND, &status); #ifdef __powerpc__ if (!(status & PCI_COMMAND_IO)) { status |= PCI_COMMAND_IO; - pcibios_write_config_word(pb, pdev->devfn, PCI_COMMAND, status); - pcibios_read_config_word(pb, pdev->devfn, PCI_COMMAND, &status); + pci_write_config_word(pdev, PCI_COMMAND, status); + pci_read_config_word(pdev, PCI_COMMAND, &status); } #endif /* __powerpc__ */ if (!(status & PCI_COMMAND_IO)) continue; if (!(status & PCI_COMMAND_MASTER)) { status |= PCI_COMMAND_MASTER; - pcibios_write_config_word(pb, pdev->devfn, PCI_COMMAND, status); - pcibios_read_config_word(pb, pdev->devfn, PCI_COMMAND, &status); + pci_write_config_word(pdev, PCI_COMMAND, status); + pci_read_config_word(pdev, PCI_COMMAND, &status); } if (!(status & PCI_COMMAND_MASTER)) continue; /* Check the latency timer for values >= 0x60 */ - pcibios_read_config_byte(pb, pdev->devfn, PCI_LATENCY_TIMER, &timer); + pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &timer); if (timer < 0x60) { - pcibios_write_config_byte(pb, pdev->devfn, PCI_LATENCY_TIMER, 0x60); + pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x60); } DevicePresent(DE4X5_APROM); @@ -2314,7 +2315,7 @@ /* Get the chip configuration revision register */ pb = this_dev->bus->number; - pcibios_read_config_dword(pb, this_dev->devfn, PCI_REVISION_ID, &cfrv); + pci_read_config_dword(this_dev, PCI_REVISION_ID, &cfrv); /* Set the device number information */ lp->device = PCI_SLOT(this_dev->devfn); @@ -2334,7 +2335,7 @@ if ((irq == 0) || (irq == 0xff) || ((int)irq == -1)) continue; /* Check if I/O accesses are enabled */ - pcibios_read_config_word(pb, this_dev->devfn, PCI_COMMAND, &status); + pci_read_config_word(this_dev, PCI_COMMAND, &status); if (!(status & PCI_COMMAND_IO)) continue; /* Search for a valid SROM attached to this DECchip */ @@ -5325,20 +5326,17 @@ } else { switch(state) { case WAKEUP: - pcibios_write_config_byte(lp->bus_num, lp->device << 3, - PCI_CFDA_PSM, WAKEUP); + pci_write_config_byte(lp->pdev, PCI_CFDA_PSM, WAKEUP); mdelay(10); break; case SNOOZE: - pcibios_write_config_byte(lp->bus_num, lp->device << 3, - PCI_CFDA_PSM, SNOOZE); + pci_write_config_byte(lp->pdev, PCI_CFDA_PSM, SNOOZE); break; case SLEEP: outl(0, DE4X5_SICR); - pcibios_write_config_byte(lp->bus_num, lp->device << 3, - PCI_CFDA_PSM, SLEEP); + pci_write_config_byte(lp->pdev, PCI_CFDA_PSM, SLEEP); break; } } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/net/tulip/winbond-840.c linux.2.5.45-ac1/drivers/net/tulip/winbond-840.c --- linux.2.5.45/drivers/net/tulip/winbond-840.c 2002-10-31 14:57:02.000000000 +0000 +++ linux.2.5.45-ac1/drivers/net/tulip/winbond-840.c 2002-10-31 15:05:20.000000000 +0000 @@ -1428,8 +1428,9 @@ memset(mc_filter, 0, sizeof(mc_filter)); for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; i++, mclist = mclist->next) { - set_bit((ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26) ^ 0x3F, - mc_filter); + int filterbit = (ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26) ^ 0x3F; + filterbit &= 0x3f; + mc_filter[filterbit >> 5] |= cpu_to_le32(1 << (filterbit & 31)); } rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/pci/compat.c linux.2.5.45-ac1/drivers/pci/compat.c --- linux.2.5.45/drivers/pci/compat.c 2002-10-31 14:57:18.000000000 +0000 +++ linux.2.5.45-ac1/drivers/pci/compat.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,37 +0,0 @@ -/* - * $Id: compat.c,v 1.1 1998/02/16 10:35:50 mj Exp $ - * - * PCI Bus Services -- Function For Backward Compatibility - * - * Copyright 1998--2000 Martin Mares - */ - -#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.45/drivers/pci/Makefile linux.2.5.45-ac1/drivers/pci/Makefile --- linux.2.5.45/drivers/pci/Makefile 2002-10-31 14:57:18.000000000 +0000 +++ linux.2.5.45-ac1/drivers/pci/Makefile 2002-10-31 15:05:41.000000000 +0000 @@ -3,10 +3,10 @@ # export-objs := access.o hotplug.o pci-driver.o pci.o pool.o \ - probe.o proc.o search.o compat.o + probe.o proc.o search.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.45/drivers/pci/pci.ids linux.2.5.45-ac1/drivers/pci/pci.ids --- linux.2.5.45/drivers/pci/pci.ids 2002-10-31 14:57:18.000000000 +0000 +++ linux.2.5.45-ac1/drivers/pci/pci.ids 2002-10-31 15:05:41.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] @@ -3485,7 +3489,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.45/drivers/pci/probe.c linux.2.5.45-ac1/drivers/pci/probe.c --- linux.2.5.45/drivers/pci/probe.c 2002-10-31 14:57:18.000000000 +0000 +++ linux.2.5.45-ac1/drivers/pci/probe.c 2002-10-31 15:05:41.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.45/drivers/pci/setup-bus.c linux.2.5.45-ac1/drivers/pci/setup-bus.c --- linux.2.5.45/drivers/pci/setup-bus.c 2002-10-31 14:57:18.000000000 +0000 +++ linux.2.5.45-ac1/drivers/pci/setup-bus.c 2002-10-31 15:05:41.000000000 +0000 @@ -35,7 +35,7 @@ #define ROUND_UP(x, a) (((x) + (a) - 1) & ~((a) - 1)) -static int __init +static int __devinit pbus_assign_resources_sorted(struct pci_bus *bus) { struct list_head *ln; @@ -85,7 +85,7 @@ requires that if there is no I/O ports or memory behind the bridge, corresponding range must be turned off by writing base value greater than limit to the bridge's base/limit registers. */ -static void __init +static void __devinit pci_setup_bridge(struct pci_bus *bus) { struct pbus_set_ranges_data ranges; @@ -168,7 +168,7 @@ /* Check whether the bridge supports optional I/O and prefetchable memory ranges. If not, the respective base/limit registers must be read-only and read as 0. */ -static void __init +static void __devinit pci_bridge_check_ranges(struct pci_bus *bus) { u16 io; @@ -206,20 +206,38 @@ b_res[2].flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH; } +/* Find first free bus resource of a given type */ +static struct resource * __devinit +pbus_find_resource(struct pci_bus *bus, unsigned long type) +{ + int i; + struct resource *r; + + for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) { + r = bus->resource[i]; + if (r && !((r->flags ^ type) & type) && !r->parent) + return r; + } + return NULL; +} + /* Sizing the IO windows of the PCI-PCI bridge is trivial, since these windows have 4K granularity and the IO ranges of non-bridge PCI devices are limited to 256 bytes. We must be careful with the ISA aliasing though. */ -static void __init +static void __devinit pbus_size_io(struct pci_bus *bus) { struct list_head *ln; - struct resource *b_res = bus->resource[0]; + struct resource *b_res = pbus_find_resource(bus, IORESOURCE_IO); unsigned long size = 0, size1 = 0; - if (!(b_res->flags & IORESOURCE_IO)) + if (!b_res) return; + DBGC((KERN_INFO "PCI: found %s resource %ld for IO\n", + bus->name, b_res - bus->resource[0])); + for (ln=bus->devices.next; ln != &bus->devices; ln=ln->next) { struct pci_dev *dev = pci_dev_b(ln); int i; @@ -259,15 +277,21 @@ /* Calculate the size of the bus and minimal alignment which guarantees that all child resources fit in this size. */ -static void __init +static int __devinit pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long type) { struct list_head *ln; unsigned long min_align, align, size; unsigned long aligns[12]; /* Alignments from 1Mb to 2Gb */ int order, max_order; - struct resource *b_res = (type & IORESOURCE_PREFETCH) ? - bus->resource[2] : bus->resource[1]; + struct resource *b_res = pbus_find_resource(bus, type); + + if (!b_res) + return 0; + + DBGC((KERN_INFO "PCI: found %s resource %ld for %s\n", + bus->name, b_res - bus->resource[0], + type & IORESOURCE_PREFETCH ? "PREF" : "MEM")); memset(aligns, 0, sizeof(aligns)); max_order = 0; @@ -325,17 +349,18 @@ size = ROUND_UP(size, min_align); if (!size) { b_res->flags = 0; - return; + return 1; } b_res->start = min_align; b_res->end = size + min_align - 1; + return 1; } -void __init +void __devinit pbus_size_bridges(struct pci_bus *bus) { struct list_head *ln; - unsigned long mask, type; + unsigned long mask, prefetch; for (ln=bus->children.next; ln != &bus->children; ln=ln->next) pbus_size_bridges(pci_bus_b(ln)); @@ -348,17 +373,15 @@ pbus_size_io(bus); - mask = type = IORESOURCE_MEM; + mask = IORESOURCE_MEM; + prefetch = IORESOURCE_MEM | IORESOURCE_PREFETCH; /* If the bridge supports prefetchable range, size it separately. */ - if (bus->resource[2] && - bus->resource[2]->flags & IORESOURCE_PREFETCH) { - pbus_size_mem(bus, IORESOURCE_PREFETCH, IORESOURCE_PREFETCH); - mask |= IORESOURCE_PREFETCH; /* Size non-prefetch only. */ - } - pbus_size_mem(bus, mask, type); + if (pbus_size_mem(bus, prefetch, prefetch)) + mask = prefetch; /* Size non-prefetch only. */ + pbus_size_mem(bus, mask, IORESOURCE_MEM); } -void __init +void __devinit pbus_assign_resources(struct pci_bus *bus) { struct list_head *ln; @@ -367,7 +390,8 @@ if (found_vga) { struct pci_bus *b; - /* Propagate presence of the VGA to upstream bridges */ + /* Propagate presence of the VGA to upstream bridges. + This hack eventually will go away. */ for (b = bus; b->parent; b = b->parent) { b->resource[0]->flags |= IORESOURCE_BUS_HAS_VGA; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/pci/setup-res.c linux.2.5.45-ac1/drivers/pci/setup-res.c --- linux.2.5.45/drivers/pci/setup-res.c 2002-10-31 14:57:18.000000000 +0000 +++ linux.2.5.45-ac1/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.45/drivers/pnp/pnpbios/core.c linux.2.5.45-ac1/drivers/pnp/pnpbios/core.c --- linux.2.5.45/drivers/pnp/pnpbios/core.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.45-ac1/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.45/drivers/s390/block/dasd_3990_erp.c linux.2.5.45-ac1/drivers/s390/block/dasd_3990_erp.c --- linux.2.5.45/drivers/s390/block/dasd_3990_erp.c 2002-10-31 14:57:13.000000000 +0000 +++ linux.2.5.45-ac1/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.45/drivers/s390/block/dasd.c linux.2.5.45-ac1/drivers/s390/block/dasd.c --- linux.2.5.45/drivers/s390/block/dasd.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.45-ac1/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.45/drivers/s390/block/dasd_devmap.c linux.2.5.45-ac1/drivers/s390/block/dasd_devmap.c --- linux.2.5.45/drivers/s390/block/dasd_devmap.c 2002-10-31 14:57:13.000000000 +0000 +++ linux.2.5.45-ac1/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.45/drivers/s390/block/dasd_diag.c linux.2.5.45-ac1/drivers/s390/block/dasd_diag.c --- linux.2.5.45/drivers/s390/block/dasd_diag.c 2002-10-31 14:57:13.000000000 +0000 +++ linux.2.5.45-ac1/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.45/drivers/s390/block/dasd_eckd.c linux.2.5.45-ac1/drivers/s390/block/dasd_eckd.c --- linux.2.5.45/drivers/s390/block/dasd_eckd.c 2002-10-31 14:57:13.000000000 +0000 +++ linux.2.5.45-ac1/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.45/drivers/s390/block/dasd_eckd.h linux.2.5.45-ac1/drivers/s390/block/dasd_eckd.h --- linux.2.5.45/drivers/s390/block/dasd_eckd.h 2002-10-31 14:57:13.000000000 +0000 +++ linux.2.5.45-ac1/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.45/drivers/s390/block/dasd_fba.c linux.2.5.45-ac1/drivers/s390/block/dasd_fba.c --- linux.2.5.45/drivers/s390/block/dasd_fba.c 2002-10-31 14:57:13.000000000 +0000 +++ linux.2.5.45-ac1/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.45/drivers/s390/block/dasd_proc.c linux.2.5.45-ac1/drivers/s390/block/dasd_proc.c --- linux.2.5.45/drivers/s390/block/dasd_proc.c 2002-10-31 14:57:13.000000000 +0000 +++ linux.2.5.45-ac1/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.45/drivers/s390/net/lcs.c linux.2.5.45-ac1/drivers/s390/net/lcs.c --- linux.2.5.45/drivers/s390/net/lcs.c 2002-10-31 14:57:13.000000000 +0000 +++ linux.2.5.45-ac1/drivers/s390/net/lcs.c 2002-10-31 15:05:34.000000000 +0000 @@ -126,7 +126,6 @@ #include #include #include -#include #include #include #include diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/sbus/char/aurora.c linux.2.5.45-ac1/drivers/sbus/char/aurora.c --- linux.2.5.45/drivers/sbus/char/aurora.c 2002-10-31 14:57:13.000000000 +0000 +++ linux.2.5.45-ac1/drivers/sbus/char/aurora.c 2002-10-31 15:05:38.000000000 +0000 @@ -59,7 +59,6 @@ #include #include #include -#include #include #include diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/scsi/aacraid/commctrl.c linux.2.5.45-ac1/drivers/scsi/aacraid/commctrl.c --- linux.2.5.45/drivers/scsi/aacraid/commctrl.c 2002-10-31 14:57:13.000000000 +0000 +++ linux.2.5.45-ac1/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.45/drivers/scsi/aha1740.c linux.2.5.45-ac1/drivers/scsi/aha1740.c --- linux.2.5.45/drivers/scsi/aha1740.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.45-ac1/drivers/scsi/aha1740.c 2002-11-02 23:20:53.000000000 +0000 @@ -20,6 +20,14 @@ * * aha1740_makecode may still need even more work * if it doesn't work for your devices, take a look. + * + * Reworked for new_eh and new locking by Alan Cox + * + * 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 @@ -68,7 +76,7 @@ /* One for each IRQ level (9-15) */ static struct Scsi_Host * aha_host[8] = {NULL, }; -int aha1740_proc_info(char *buffer, char **start, off_t offset, +static int aha1740_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int inout) { int len; @@ -76,7 +84,7 @@ struct aha1740_hostdata *host; if (inout) - return(-ENOSYS); + return-ENOSYS; for (len = 0; len < 8; len++) { shpnt = aha_host[len]; @@ -103,7 +111,7 @@ } -int aha1740_makecode(unchar *sense, unchar *status) +static int aha1740_makecode(unchar *sense, unchar *status) { struct statusword { @@ -179,7 +187,7 @@ return status[3] | retval << 16; } -int aha1740_test_port(unsigned int base) +static int aha1740_test_port(unsigned int base) { char name[4], tmp; @@ -212,7 +220,7 @@ } /* A "high" level interrupt handler */ -void aha1740_intr_handle(int irq, void *dev_id, struct pt_regs * regs) +static void aha1740_intr_handle(int irq, void *dev_id, struct pt_regs * regs) { struct Scsi_Host *host = aha_host[irq - 9]; void (*my_done)(Scsi_Cmnd *); @@ -303,7 +311,7 @@ spin_unlock_irqrestore(host->host_lock, flags); } -int aha1740_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)) +static int aha1740_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)) { unchar direction; unchar *cmd = (unchar *) SCpnt->cmnd; @@ -317,16 +325,6 @@ if(*cmd == REQUEST_SENSE) { -#if 0 - /* scsi_request_sense() provides a buffer of size 256, - so there is no reason to expect equality */ - - if (bufflen != sizeof(SCpnt->sense_buffer)) - { - printk("Wrong buffer length supplied for request sense (%d)\n", - bufflen); - } -#endif SCpnt->result = 0; done(SCpnt); return 0; @@ -486,7 +484,7 @@ SCpnt->SCp.Status++; } -int aha1740_command(Scsi_Cmnd * SCpnt) +static int aha1740_command(Scsi_Cmnd * SCpnt) { aha1740_queuecommand(SCpnt, internal_done); SCpnt->SCp.Status = 0; @@ -501,7 +499,7 @@ /* Query the board for its irq_level. Nothing else matters in enhanced mode on an EISA bus. */ -void aha1740_getconfig(unsigned int base, unsigned int *irq_level, +static void aha1740_getconfig(unsigned int base, unsigned int *irq_level, unsigned int *translation) { static int intab[] = { 9, 10, 11, 12, 0, 14, 15, 0 }; @@ -511,7 +509,7 @@ outb(inb(INTDEF(base)) | 0x10, INTDEF(base)); } -int aha1740_detect(Scsi_Host_Template * tpnt) +static int aha1740_detect(Scsi_Host_Template * tpnt) { int count = 0, slot; @@ -540,8 +538,8 @@ outb(G2CNTRL_HRST, G2CNTRL(slotbase)); outb(0, G2CNTRL(slotbase)); } - printk("Configuring aha174x at IO:%x, IRQ %d\n", slotbase, irq_level); - printk("aha174x: Extended translation %sabled.\n", + printk(KERN_INFO "Configuring aha174x at IO:%x, IRQ %d\n", slotbase, irq_level); + printk(KERN_INFO "aha174x: Extended translation %sabled.\n", translation ? "en" : "dis"); DEB(printk("aha1740_detect: enable interrupt channel %d\n",irq_level)); if (request_irq(irq_level,aha1740_intr_handle,0,"aha1740",NULL)) { @@ -572,31 +570,7 @@ return count; } -/* Note: They following two functions do not apply very well to the Adaptec, - which basically manages its own affairs quite well without our interference, - so I haven't put anything into them. I can faintly imagine someone with a - *very* badly behaved SCSI target (perhaps an old tape?) wanting the abort(), - but it hasn't happened yet, and doing aborts brings the Adaptec to its - knees. I cannot (at this moment in time) think of any reason to reset the - card once it's running. So there. */ - -int aha1740_abort(Scsi_Cmnd * SCpnt) -{ - DEB(printk("aha1740_abort called\n")); - return SCSI_ABORT_SNOOZE; -} - -/* We do not implement a reset function here, but the upper level code assumes - that it will get some kind of response for the command in SCpnt. We must - oblige, or the command will hang the scsi system */ - -int aha1740_reset(Scsi_Cmnd * SCpnt, unsigned int ignored) -{ - DEB(printk("aha1740_reset called\n")); - return SCSI_RESET_PUNT; -} - -int aha1740_biosparam(struct scsi_device *sdev, struct block_device *dev, +static int aha1740_biosparam(struct scsi_device *sdev, struct block_device *dev, sector_t capacity, int* ip) { int size = capacity; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/scsi/aha1740.h linux.2.5.45-ac1/drivers/scsi/aha1740.h --- linux.2.5.45/drivers/scsi/aha1740.h 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.45-ac1/drivers/scsi/aha1740.h 2002-11-02 23:22:53.000000000 +0000 @@ -13,8 +13,8 @@ #include /* Eisa Enhanced mode operation - slot locating and addressing */ -#define MINEISA 1 /* I don't have an EISA Spec to know these ranges, so I */ -#define MAXEISA 8 /* Just took my machine's specifications. Adjust to fit.*/ +#define MINEISA 1 /* I don't have an EISA Spec to know these ranges, so I */ +#define MAXEISA 8 /* Just took my machine's specifications. Adjust to fit. */ /* I just saw an ad, and bumped this from 6 to 8 */ #define SLOTBASE(x) ((x << 12) + 0xc80) #define SLOTSIZE 0x5c @@ -75,14 +75,14 @@ #define ATTN_START 0x40 /* Start CCB */ #define ATTN_ABORT 0x50 /* Abort CCB */ -#define G2CNTRL_HRST 0x80 /* Hard Reset */ -#define G2CNTRL_IRST 0x40 /* Clear EISA Interrupt */ -#define G2CNTRL_HRDY 0x20 /* Sets HOST ready */ +#define G2CNTRL_HRST 0x80 /* Hard Reset */ +#define G2CNTRL_IRST 0x40 /* Clear EISA Interrupt */ +#define G2CNTRL_HRDY 0x20 /* Sets HOST ready */ /* This is used with scatter-gather */ struct aha1740_chain { - u32 dataptr; /* Location of data */ - u32 datalen; /* Size of this part of chain */ + u32 dataptr; /* Location of data */ + u32 datalen; /* Size of this part of chain */ }; /* These belong in scsi.h */ @@ -107,40 +107,40 @@ #define MAX_STATUS 32 struct ecb { /* Enhanced Control Block 6.1 */ - u16 cmdw; /* Command Word */ - /* Flag Word 1 */ - u16 cne:1, /* Control Block Chaining */ - :6, di:1, /* Disable Interrupt */ - :2, ses:1, /* Suppress Underrun error */ - :1, sg:1, /* Scatter/Gather */ - :1, dsb:1, /* Disable Status Block */ - ars:1; /* Automatic Request Sense */ - /* Flag Word 2 */ - u16 lun:3, /* Logical Unit */ - tag:1, /* Tagged Queuing */ - tt:2, /* Tag Type */ - nd:1, /* No Disconnect */ - :1, dat:1, /* Data transfer - check direction */ - dir:1, /* Direction of transfer 1 = datain */ - st:1, /* Suppress Transfer */ - chk:1, /* Calculate Checksum */ - :2, rec:1, :1; /* Error Recovery */ - u16 nil0; /* nothing */ - u32 dataptr; /* Data or Scatter List ptr */ - u32 datalen; /* Data or Scatter List len */ - u32 statusptr; /* Status Block ptr */ - u32 linkptr; /* Chain Address */ - u32 nil1; /* nothing */ - u32 senseptr; /* Sense Info Pointer */ - u8 senselen; /* Sense Length */ - u8 cdblen; /* CDB Length */ - u16 datacheck; /* Data checksum */ - u8 cdb[MAX_CDB]; /* CDB area */ + u16 cmdw; /* Command Word */ + /* Flag Word 1 */ + u16 cne:1, /* Control Block Chaining */ + :6, di:1, /* Disable Interrupt */ + :2, ses:1, /* Suppress Underrun error */ + :1, sg:1, /* Scatter/Gather */ + :1, dsb:1, /* Disable Status Block */ + ars:1; /* Automatic Request Sense */ + /* Flag Word 2 */ + u16 lun:3, /* Logical Unit */ + tag:1, /* Tagged Queuing */ + tt:2, /* Tag Type */ + nd:1, /* No Disconnect */ + :1, dat:1, /* Data transfer - check direction */ + dir:1, /* Direction of transfer 1 = datain */ + st:1, /* Suppress Transfer */ + chk:1, /* Calculate Checksum */ + :2, rec:1,:1; /* Error Recovery */ + u16 nil0; /* nothing */ + u32 dataptr; /* Data or Scatter List ptr */ + u32 datalen; /* Data or Scatter List len */ + u32 statusptr; /* Status Block ptr */ + u32 linkptr; /* Chain Address */ + u32 nil1; /* nothing */ + u32 senseptr; /* Sense Info Pointer */ + u8 senselen; /* Sense Length */ + u8 cdblen; /* CDB Length */ + u16 datacheck; /* Data checksum */ + u8 cdb[MAX_CDB]; /* CDB area */ /* Hardware defined portion ends here, rest is driver defined */ - u8 sense[MAX_SENSE]; /* Sense area */ - u8 status[MAX_STATUS]; /* Status area */ - Scsi_Cmnd *SCpnt; /* Link to the SCSI Command Block */ - void (*done)(Scsi_Cmnd *); /* Completion Function */ + u8 sense[MAX_SENSE]; /* Sense area */ + u8 status[MAX_STATUS]; /* Status area */ + Scsi_Cmnd *SCpnt; /* Link to the SCSI Command Block */ + void (*done) (Scsi_Cmnd *); /* Completion Function */ }; #define AHA1740CMD_NOP 0x00 /* No OP */ @@ -152,32 +152,22 @@ #define AHA1740CMD_RINQ 0x0a /* Read Host Adapter Inquiry Data */ #define AHA1740CMD_TARG 0x10 /* Target SCSI Command */ -int aha1740_detect(Scsi_Host_Template *); -int aha1740_command(Scsi_Cmnd *); -int aha1740_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); -int aha1740_abort(Scsi_Cmnd *); -int aha1740_reset(Scsi_Cmnd *, unsigned int); -int aha1740_biosparam(struct scsi_device *, struct block_device *, - sector_t, int*); -int aha1740_proc_info(char *buffer, char **start, off_t offset, - int length, int hostno, int inout); +static int aha1740_detect(Scsi_Host_Template *); +static int aha1740_command(Scsi_Cmnd *); +static int aha1740_queuecommand(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *)); +static int aha1740_biosparam(struct scsi_device *, struct block_device *, sector_t, int *); +static int aha1740_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int inout); #define AHA1740_ECBS 32 #define AHA1740_SCATTER 16 #define AHA1740_CMDLUN 1 -#ifndef NULL - #define NULL 0 -#endif - #define AHA1740 { proc_name: "aha1740", \ proc_info: aha1740_proc_info, \ name: "Adaptec 174x (EISA)", \ detect: aha1740_detect, \ command: aha1740_command, \ queuecommand: aha1740_queuecommand, \ - abort: aha1740_abort, \ - reset: aha1740_reset, \ bios_param: aha1740_biosparam, \ can_queue: AHA1740_ECBS, \ this_id: 7, \ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/scsi/aic7xxx/aic7xxx_reg.h linux.2.5.45-ac1/drivers/scsi/aic7xxx/aic7xxx_reg.h --- linux.2.5.45/drivers/scsi/aic7xxx/aic7xxx_reg.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/drivers/scsi/aic7xxx/aic7xxx_reg.h 2002-10-31 15:05:32.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.45/drivers/scsi/aic7xxx/aic7xxx_seq.h linux.2.5.45-ac1/drivers/scsi/aic7xxx/aic7xxx_seq.h --- linux.2.5.45/drivers/scsi/aic7xxx/aic7xxx_seq.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/drivers/scsi/aic7xxx/aic7xxx_seq.h 2002-10-31 15:05:32.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.45/drivers/scsi/dpt_i2o.c linux.2.5.45-ac1/drivers/scsi/dpt_i2o.c --- linux.2.5.45/drivers/scsi/dpt_i2o.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.45-ac1/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.45/drivers/scsi/dpti.h linux.2.5.45-ac1/drivers/scsi/dpti.h --- linux.2.5.45/drivers/scsi/dpti.h 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.45-ac1/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.45/drivers/scsi/eata.c linux.2.5.45-ac1/drivers/scsi/eata.c --- linux.2.5.45/drivers/scsi/eata.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.45-ac1/drivers/scsi/eata.c 2002-11-03 01:06:16.000000000 +0000 @@ -1,6 +1,17 @@ /* * eata.c - Low-level driver for EATA/DMA SCSI host adapters. * + * 28 Oct 2002 Rev. 8.00 for linux 2.5.44-ac4 + * + Use new tcq and adjust_queue_depth api. + * + New command line option (tm:[0-2]) to choose the type of tags: + * 0 -> disable tagging ; 1 -> simple tags ; 2 -> ordered tags. + * Default is tm:0 (tagged commands disabled). + * For compatibility the "tc:" option is an alias of the "tm:" + * option; tc:n is equivalent to tm:0 and tc:y is equivalent to + * tm:1. + * + The tagged_comm module parameter has been removed, use tag_mode + * instead, equivalent to the "tm:" boot option. + * * 10 Oct 2002 Rev. 7.70 for linux 2.5.42 * + Foreport from revision 6.70. * @@ -362,24 +373,21 @@ * rs:n use BIOS order while detecting PCI boards; * lc:y enables linked commands; * lc:n disables linked commands; - * tc:y enables tagged commands; - * tc:n disables tagged commands; - * tm:0 use head/simple/ordered queue tag sequences; - * tm:1 use only simple queue tags; - * tm:2 use only head of queue tags; - * tm:3 use only ordered queue tags; + * tm:0 disables tagged commands (same as tc:n); + * tm:1 use simple queue tags (same as tc:y); + * tm:2 use ordered queue tags (same as tc:2); * mq:xx set the max queue depth to the value xx (2 <= xx <= 32). * - * The default value is: "eata=lc:n,tc:n,mq:16,tm:0,et:n,rs:n". + * The default value is: "eata=lc:n,mq:16,tm:0,et:n,rs:n". * An example using the list of detection probes could be: - * "eata=0x7410,0x230,lc:y,tc:n,mq:4,et:n". + * "eata=0x7410,0x230,lc:y,tm:2,mq:4,et:n". * * When loading as a module, parameters can be specified as well. * The above example would be (use 1 in place of y and 0 in place of n): * - * modprobe eata io_port=0x7410,0x230 linked_comm=1 tagged_comm=0 \ - * max_queue_depth=4 tag_mode=0 \ - * ext_tran=0 rev_scan=1 + * modprobe eata io_port=0x7410,0x230 linked_comm=1 \ + * max_queue_depth=4 ext_tran=0 tag_mode=2 \ + * rev_scan=1 * * ---------------------------------------------------------------------------- * In this implementation, linked commands are designed to work with any DISK @@ -447,15 +455,11 @@ MODULE_PARM(boot_options, "s"); MODULE_PARM(io_port, "1-" __MODULE_STRING(MAX_INT_PARAM) "i"); MODULE_PARM(linked_comm, "i"); -MODULE_PARM(tagged_comm, "i"); MODULE_PARM(link_statistics, "i"); MODULE_PARM(max_queue_depth, "i"); MODULE_PARM(tag_mode, "i"); MODULE_PARM(ext_tran, "i"); MODULE_PARM(rev_scan, "i"); -MODULE_PARM(isa_probe, "i"); -MODULE_PARM(eisa_probe, "i"); -MODULE_PARM(pci_probe, "i"); MODULE_AUTHOR("Dario Ballabio"); #endif @@ -481,6 +485,7 @@ #include #include #include +#include #if !defined(__BIG_ENDIAN_BITFIELD) && !defined(__LITTLE_ENDIAN_BITFIELD) #error "Adjust your defines" @@ -528,10 +533,9 @@ #define ABORTING 6 #define NO_DMA 0xff #define MAXLOOP 10000 -#define TAG_MIXED 0 +#define TAG_DISABLED 0 #define TAG_SIMPLE 1 -#define TAG_HEAD 2 -#define TAG_ORDERED 3 +#define TAG_ORDERED 2 #define REG_CMD 7 #define REG_STATUS 7 @@ -543,7 +547,7 @@ #define REG_LM 3 #define REG_MID 4 #define REG_MSB 5 -#define REGION_SIZE 9UL +#define REGION_SIZE 9 #define MAX_ISA_ADDR 0x03ff #define MIN_EISA_ADDR 0x1c88 #define MAX_EISA_ADDR 0xfc88 @@ -567,7 +571,7 @@ #define TLDEV(type) ((type) == TYPE_DISK || (type) == TYPE_ROM) /* "EATA", in Big Endian format */ -#define EATA_SIG_BE 0x45415441 +#define EATA_SIGNATURE 0x41544145 /* Number of valid bytes in the board config structure for EATA 2.0x */ #define EATA_2_0A_SIZE 28 @@ -578,12 +582,6 @@ struct eata_info { u_int32_t data_len; /* Number of valid bytes after this field */ u_int32_t sign; /* ASCII "EATA" signature */ - -#if defined(__BIG_ENDIAN_BITFIELD) - unchar version:4, :4; - unchar haaval:1, ata:1, drqvld:1, dmasup:1, morsup:1, trnxfr:1, tarsup:1, - ocsena:1; -#else unchar :4, /* unused low nibble */ version:4; /* EATA version, should be 0x1 */ unchar ocsena:1, /* Overlap Command Support Enabled */ @@ -594,8 +592,6 @@ drqvld:1, /* DRQ Index (DRQX) is valid */ ata:1, /* This is an ATA device */ haaval:1; /* Host Adapter Address Valid */ -#endif - ushort cp_pad_len; /* Number of pad bytes after cp_len */ unchar host_addr[4]; /* Host Adapter SCSI ID for channels 3, 2, 1, 0 */ u_int32_t cp_len; /* Number of valid bytes in cp */ @@ -603,15 +599,6 @@ ushort queue_size; /* Max number of cp that can be queued */ ushort unused; ushort scatt_size; /* Max number of entries in scatter/gather table */ - -#if defined(__BIG_ENDIAN_BITFIELD) - unchar drqx:2, second:1, irq_tr:1, irq:4; - unchar sync; - unchar :4, res1:1, large_sg:1, forcaddr:1, isaena:1; - unchar max_chan:3, max_id:5; - unchar max_lun; - unchar eisa:1, pci:1, idquest:1, m1:1, :4; -#else unchar irq:4, /* Interrupt Request assigned to this controller */ irq_tr:1, /* 0 for edge triggered, 1 for level triggered */ second:1, /* 1 if this is a secondary (not primary) controller */ @@ -634,8 +621,6 @@ idquest:1, /* RAIDNUM returned is questionable */ pci:1, /* This board is PCI */ eisa:1; /* This board is EISA */ -#endif - unchar raidnum; /* Uniquely identifies this HBA in a system */ unchar notused; @@ -645,30 +630,18 @@ /* Board config structure */ struct eata_config { ushort len; /* Number of bytes following this field */ - -#if defined(__BIG_ENDIAN_BITFIELD) - unchar :4, tarena:1, mdpena:1, ocena:1, edis:1; -#else unchar edis:1, /* Disable EATA interface after config command */ ocena:1, /* Overlapped Commands Enabled */ mdpena:1, /* Transfer all Modified Data Pointer Messages */ tarena:1, /* Target Mode Enabled for this controller */ :4; -#endif - unchar cpad[511]; }; /* Returned status packet structure */ struct mssp { - -#if defined(__BIG_ENDIAN_BITFIELD) - unchar eoc:1, adapter_status:7; -#else unchar adapter_status:7, /* State related to current command */ eoc:1; /* End Of Command (1 = command completed) */ -#endif - unchar target_status; /* SCSI status received after data transfer */ unchar unused[2]; u_int32_t inv_res_len; /* Number of bytes not transferred */ @@ -683,16 +656,6 @@ /* MailBox SCSI Command Packet */ struct mscp { - -#if defined(__BIG_ENDIAN_BITFIELD) - unchar din:1, dout:1, interp:1, :1, sg:1, reqsen:1, init:1, sreset:1; - unchar sense_len; - unchar unused[3]; - unchar :7, fwnest:1; - unchar :5, hbaci:1, iat:1, phsunit:1; - unchar channel:3, target:5; - unchar one:1, dispri:1, luntar:1, lun:5; -#else unchar sreset:1, /* SCSI Bus Reset Signal should be asserted */ init:1, /* Re-initialize controller and self test */ reqsen:1, /* Transfer Request Sense Data to addr using DMA */ @@ -715,8 +678,6 @@ luntar:1, /* This cp is for Target (not LUN) */ dispri:1, /* Disconnect Privilege granted */ one:1; /* 1 */ -#endif - unchar mess[3]; /* Massage to/from Target */ unchar cdb[12]; /* Command Descriptor Block */ u_int32_t data_len; /* If sg=0 Data Length, if sg=1 sglist length */ @@ -793,28 +754,22 @@ #define BN(board) (HD(board)->board_name) /* Device is Big Endian */ -#define H2DEV(x) cpu_to_be32(x) -#define DEV2H(x) be32_to_cpu(x) -#define H2DEV16(x) cpu_to_be16(x) -#define DEV2H16(x) be16_to_cpu(x) - -/* But transfer orientation from the 16 bit data register is Little Endian */ -#define REG2H(x) le16_to_cpu(x) +#define H2DEV(x) cpu_to_be32(x) +#define DEV2H(x) be32_to_cpu(x) static void do_interrupt_handler(int, void *, struct pt_regs *); static void flush_dev(Scsi_Device *, unsigned long, unsigned int, unsigned int); static int do_trace = FALSE; static int setup_done = FALSE; static int link_statistics; -static int tag_mode = TAG_MIXED; static int ext_tran = FALSE; static int rev_scan = TRUE; static char *boot_options; #if defined(CONFIG_SCSI_EATA_TAGGED_QUEUE) -static int tagged_comm = TRUE; +static int tag_mode = TAG_SIMPLE; #else -static int tagged_comm = FALSE; +static int tag_mode = TAG_DISABLED; #endif #if defined(CONFIG_SCSI_EATA_LINKED_COMMANDS) @@ -846,38 +801,57 @@ #else static int pci_probe = FALSE; #endif - + static int eata2x_slave_attach(Scsi_Device *dev) { int j, tqd, utqd; - char *link_suffix = ""; + char *tag_suffix, *link_suffix; struct Scsi_Host *host = dev->host; j = ((struct hostdata *) host->hostdata)->board_number; utqd = MAX_CMD_PER_LUN; - tqd = (host->can_queue - utqd); + tqd = max_queue_depth; - if (TLDEV(dev->type) && (dev->tagged_supported || linked_comm)) { - if(!dev->tagged_supported) - scsi_adjust_queue_depth(dev, 0, tqd); - else + if (TLDEV(dev->type) && dev->tagged_supported) + + if (tag_mode == TAG_SIMPLE) { scsi_adjust_queue_depth(dev, MSG_SIMPLE_TAG, tqd); - } else { + tag_suffix = ", simple tags"; + } + else if (tag_mode == TAG_ORDERED) { + scsi_adjust_queue_depth(dev, MSG_ORDERED_TAG, tqd); + tag_suffix = ", ordered tags"; + } + else { + scsi_adjust_queue_depth(dev, 0, tqd); + tag_suffix = ", no tags"; + } + + else if (TLDEV(dev->type) && linked_comm) { + scsi_adjust_queue_depth(dev, 0, tqd); + tag_suffix = ", untagged"; + } + + else { scsi_adjust_queue_depth(dev, 0, utqd); - } + tag_suffix = ""; + } - if (!dev->simple_tags && dev->new_queue_depth > 2) + if (TLDEV(dev->type) && linked_comm && dev->new_queue_depth > 2) link_suffix = ", sorted"; - else if (dev->simple_tags) + else if (TLDEV(dev->type)) link_suffix = ", unsorted"; + else + link_suffix = ""; - printk("%s: scsi%d, channel %d, id %d, lun %d, cmds/lun %d%s.\n", + printk("%s: scsi%d, channel %d, id %d, lun %d, cmds/lun %d%s%s.\n", BN(j), host->host_no, dev->channel, dev->id, dev->lun, - dev->new_queue_depth, link_suffix); - return 0; + dev->new_queue_depth, link_suffix, tag_suffix); + + return FALSE; } -static inline int wait_on_busy(unsigned long iobase, unsigned int loop) { +static int wait_on_busy(unsigned long iobase, unsigned int loop) { while (inb(iobase + REG_AUX_STATUS) & ABSY_ASSERTED) { udelay(1L); @@ -887,7 +861,7 @@ return FALSE; } -static inline int do_dma(unsigned long iobase, unsigned long addr, unchar cmd) { +static int do_dma(unsigned long iobase, unsigned long addr, unchar cmd) { unsigned char *byaddr; unsigned long devaddr; @@ -906,7 +880,7 @@ return FALSE; } -static inline int read_pio(unsigned long iobase, ushort *start, ushort *end) { +static int read_pio(unsigned long iobase, ushort *start, ushort *end) { unsigned int loop = MAXLOOP; ushort *p; @@ -918,13 +892,13 @@ } loop = MAXLOOP; - *p = REG2H(inw(iobase)); + *p = inw(iobase); } return FALSE; } -static inline struct pci_dev *get_pci_dev(unsigned long port_base) { +static struct pci_dev *get_pci_dev(unsigned long port_base) { #if defined(CONFIG_PCI) @@ -972,12 +946,12 @@ #endif /* end CONFIG_PCI */ } -static inline int port_detect \ +static int port_detect \ (unsigned long port_base, unsigned int j, Scsi_Host_Template *tpnt) { unsigned char irq, dma_channel, subversion, i, is_pci = FALSE; unsigned char protocol_rev; struct eata_info info; - char *bus_type, dma_name[16], tag_type; + char *bus_type, dma_name[16]; struct pci_dev *pdev; /* Allowed DMA channels for ISA (0 indicates reserved) */ @@ -995,48 +969,31 @@ } if (do_dma(port_base, 0, READ_CONFIG_PIO)) { -#if defined(DEBUG_DETECT) - printk("%s: detect, do_dma failed at 0x%03lx.\n", name, port_base); -#endif release_region(port_base, REGION_SIZE); return FALSE; } /* Read the info structure */ if (read_pio(port_base, (ushort *)&info, (ushort *)&info.ipad[0])) { -#if defined(DEBUG_DETECT) - printk("%s: detect, read_pio failed at 0x%03lx.\n", name, port_base); -#endif release_region(port_base, REGION_SIZE); return FALSE; } - info.data_len = DEV2H(info.data_len); - info.sign = DEV2H(info.sign); - info.cp_pad_len = DEV2H16(info.cp_pad_len); - info.cp_len = DEV2H(info.cp_len); - info.sp_len = DEV2H(info.sp_len); - info.scatt_size = DEV2H16(info.scatt_size); - info.queue_size = DEV2H16(info.queue_size); - /* Check the controller "EATA" signature */ - if (info.sign != EATA_SIG_BE) { -#if defined(DEBUG_DETECT) - printk("%s: signature 0x%04x discarded.\n", name, info.sign); -#endif + if (info.sign != EATA_SIGNATURE) { release_region(port_base, REGION_SIZE); return FALSE; } - if (info.data_len < EATA_2_0A_SIZE) { + if (DEV2H(info.data_len) < EATA_2_0A_SIZE) { printk("%s: config structure size (%d bytes) too short, detaching.\n", - name, info.data_len); + name, DEV2H(info.data_len)); release_region(port_base, REGION_SIZE); return FALSE; } - else if (info.data_len == EATA_2_0A_SIZE) + else if (DEV2H(info.data_len) == EATA_2_0A_SIZE) protocol_rev = 'A'; - else if (info.data_len == EATA_2_0B_SIZE) + else if (DEV2H(info.data_len) == EATA_2_0B_SIZE) protocol_rev = 'B'; else protocol_rev = 'C'; @@ -1148,7 +1105,7 @@ /* Set board configuration */ memset((char *)cf, 0, sizeof(struct eata_config)); - cf->len = (ushort) H2DEV16((ushort)510); + cf->len = (ushort) cpu_to_be16((ushort)510); cf->ocena = TRUE; if (do_dma(port_base, cf_dma_addr, SET_CONFIG_DMA)) { @@ -1179,9 +1136,9 @@ sh[j]->n_io_port = REGION_SIZE; sh[j]->dma_channel = dma_channel; sh[j]->irq = irq; - sh[j]->sg_tablesize = (ushort) info.scatt_size; + sh[j]->sg_tablesize = (ushort) be16_to_cpu(info.scatt_size); sh[j]->this_id = (ushort) info.host_addr[3]; - sh[j]->can_queue = (ushort) info.queue_size; + sh[j]->can_queue = (ushort) be16_to_cpu(info.queue_size); sh[j]->cmd_per_lun = MAX_CMD_PER_LUN; memset(HD(j), 0, sizeof(struct hostdata)); HD(j)->subversion = subversion; @@ -1268,18 +1225,13 @@ if (max_queue_depth < MAX_CMD_PER_LUN) max_queue_depth = MAX_CMD_PER_LUN; - if (tagged_comm) { - if (tag_mode == TAG_SIMPLE) tag_type = '1'; - else if (tag_mode == TAG_HEAD) tag_type = '2'; - else if (tag_mode == TAG_ORDERED) tag_type = '3'; - else tag_type = 'y'; - } - else tag_type = 'n'; + if (tag_mode != TAG_DISABLED && tag_mode != TAG_SIMPLE) + tag_mode = TAG_ORDERED; if (j == 0) { printk("EATA/DMA 2.0x: Copyright (C) 1994-2002 Dario Ballabio.\n"); - printk("%s config options -> tc:%c, lc:%c, mq:%d, rs:%c, et:%c, "\ - "ip:%c, ep:%c, pp:%c.\n", driver_name, tag_type, + printk("%s config options -> tm:%d, lc:%c, mq:%d, rs:%c, et:%c, "\ + "ip:%c, ep:%c, pp:%c.\n", driver_name, tag_mode, YESNO(linked_comm), max_queue_depth, YESNO(rev_scan), YESNO(ext_tran), YESNO(isa_probe), YESNO(eisa_probe), YESNO(pci_probe)); @@ -1301,8 +1253,8 @@ printk("%s: Vers. 0x%x, ocs %u, tar %u, trnxfr %u, more %u, SYNC 0x%x, "\ "sec. %u, infol %d, cpl %d spl %d.\n", name, info.version, info.ocsena, info.tarsup, info.trnxfr, info.morsup, info.sync, - info.second, info.data_len, info.cp_len, - info.sp_len); + info.second, DEV2H(info.data_len), DEV2H(info.cp_len), + DEV2H(info.sp_len)); if (protocol_rev == 'B' || protocol_rev == 'C') printk("%s: isaena %u, forcaddr %u, max_id %u, max_chan %u, "\ @@ -1346,15 +1298,12 @@ else val = (int) simple_strtoul(pc, NULL, 0); if (!strncmp(cur, "lc:", 3)) linked_comm = val; - else if (!strncmp(cur, "tc:", 3)) tagged_comm = val; else if (!strncmp(cur, "tm:", 3)) tag_mode = val; + else if (!strncmp(cur, "tc:", 3)) tag_mode = val; else if (!strncmp(cur, "mq:", 3)) max_queue_depth = val; else if (!strncmp(cur, "ls:", 3)) link_statistics = val; else if (!strncmp(cur, "et:", 3)) ext_tran = val; else if (!strncmp(cur, "rs:", 3)) rev_scan = val; - else if (!strncmp(cur, "ip:", 3)) isa_probe = val; - else if (!strncmp(cur, "ep:", 3)) eisa_probe = val; - else if (!strncmp(cur, "pp:", 3)) pci_probe = val; if ((cur = strchr(cur, ','))) ++cur; } @@ -1419,7 +1368,7 @@ return; } -int eata2x_detect(Scsi_Host_Template *tpnt) { +static int eata2x_detect(Scsi_Host_Template *tpnt) { unsigned int j = 0, k; unsigned long spin_flags; @@ -1439,19 +1388,7 @@ for (k = 0; k < MAX_BOARDS + 1; k++) sh[k] = NULL; - for (k = MAX_INT_PARAM; io_port[k]; k++) - if (io_port[k] == SKIP) continue; - else if (io_port[k] <= MAX_ISA_ADDR) { - if (!isa_probe) io_port[k] = SKIP; - } - else if (io_port[k] >= MIN_EISA_ADDR && io_port[k] <= MAX_EISA_ADDR) { - if (!eisa_probe) io_port[k] = SKIP; - } - - if (pci_probe) { - if (!setup_done) add_pci_ports(); - else enable_pci_ports(); - } + if (!setup_done) add_pci_ports(); for (k = 0; io_port[k]; k++) { @@ -1465,7 +1402,7 @@ return j; } -static inline void map_dma(unsigned int i, unsigned int j) { +static void map_dma(unsigned int i, unsigned int j) { unsigned int k, count, pci_dir; struct scatterlist *sgpnt; struct mscp *cpp; @@ -1552,7 +1489,7 @@ DEV2H(cpp->data_len), pci_dir); } -static inline void scsi_to_dev_dir(unsigned int i, unsigned int j) { +static void scsi_to_dev_dir(unsigned int i, unsigned int j) { unsigned int k; static const unsigned char data_out_cmds[] = { @@ -1606,7 +1543,7 @@ } -static inline int do_qcomm(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { +static int eata2x_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { unsigned int i, j, k; struct mscp *cpp; @@ -1670,25 +1607,8 @@ /* Map DMA buffers and SG list */ map_dma(i, j); - if (SCpnt->device->simple_tags) { - - if (HD(j)->target_redo[SCpnt->target][SCpnt->channel] || - HD(j)->target_to[SCpnt->target][SCpnt->channel]) - cpp->mess[0] = ORDERED_QUEUE_TAG; - else if (tag_mode == TAG_SIMPLE) cpp->mess[0] = SIMPLE_QUEUE_TAG; - else if (tag_mode == TAG_HEAD) cpp->mess[0] = HEAD_OF_QUEUE_TAG; - else if (tag_mode == TAG_ORDERED) cpp->mess[0] = ORDERED_QUEUE_TAG; - else if (SCpnt->device->current_tag == 0) - cpp->mess[0] = ORDERED_QUEUE_TAG; - else if (SCpnt->device->current_tag == 1) - cpp->mess[0] = HEAD_OF_QUEUE_TAG; - else - cpp->mess[0] = SIMPLE_QUEUE_TAG; - - cpp->mess[1] = SCpnt->device->current_tag++; - } - - if (SCpnt->device->new_queue_depth > 2 && !SCpnt->device->simple_tags) { + if (linked_comm && SCpnt->device->new_queue_depth > 2 + && TLDEV(SCpnt->device->type)) { HD(j)->cp_stat[i] = READY; flush_dev(SCpnt->device, SCpnt->request->sector, j, FALSE); return 0; @@ -1707,14 +1627,7 @@ return 0; } -int eata2x_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { - int rtn; - - rtn = do_qcomm(SCpnt, done); - return rtn; -} - -static inline int do_abort(Scsi_Cmnd *SCarg) { +static int eata2x_eh_abort(Scsi_Cmnd *SCarg) { unsigned int i, j; j = ((struct hostdata *) SCarg->host->hostdata)->board_number; @@ -1788,12 +1701,7 @@ panic("%s: abort, mbox %d, invalid cp_stat.\n", BN(j), i); } -int eata2x_abort(Scsi_Cmnd *SCarg) { - - return do_abort(SCarg); -} - -static inline int do_reset(Scsi_Cmnd *SCarg) { +static int eata2x_eh_host_reset(Scsi_Cmnd *SCarg) { unsigned int i, j, time, k, c, limit = 0; int arg_done = FALSE; Scsi_Cmnd *SCpnt; @@ -1925,12 +1833,7 @@ return SUCCESS; } -int eata2x_reset(Scsi_Cmnd *SCarg) { - - return do_reset(SCarg); -} - -int eata2x_biosparam(struct scsi_device *sdev, struct block_device *bdev, +int eata2x_bios_param(struct scsi_device *sdev, struct block_device *bdev, sector_t capacity, int *dkinfo) { int size = capacity; @@ -1941,7 +1844,7 @@ } #if defined (DEBUG_GEOMETRY) - printk ("%s: biosparam, head=%d, sec=%d, cyl=%d.\n", driver_name, + printk ("%s: bios_param, head=%d, sec=%d, cyl=%d.\n", driver_name, dkinfo[0], dkinfo[1], dkinfo[2]); #endif @@ -1973,7 +1876,7 @@ return; } -static inline int reorder(unsigned int j, unsigned long cursec, +static int reorder(unsigned int j, unsigned long cursec, unsigned int ihdlr, unsigned int il[], unsigned int n_ready) { Scsi_Cmnd *SCpnt; struct mscp *cpp; @@ -2108,7 +2011,7 @@ } -static inline void ihdlr(int irq, unsigned int j) { +static void ihdlr(int irq, unsigned int j) { Scsi_Cmnd *SCpnt; unsigned int i, k, c, status, tstatus, reg; struct mssp *spp; @@ -2351,7 +2254,7 @@ spin_unlock_irqrestore(sh[j]->host_lock, spin_flags); } -int eata2x_release(struct Scsi_Host *shpnt) { +static int eata2x_release(struct Scsi_Host *shpnt) { unsigned int i, j; for (j = 0; sh[j] != NULL && sh[j] != shpnt; j++); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/scsi/eata.h linux.2.5.45-ac1/drivers/scsi/eata.h --- linux.2.5.45/drivers/scsi/eata.h 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.45-ac1/drivers/scsi/eata.h 2002-11-03 01:06:26.000000000 +0000 @@ -1,34 +1,30 @@ /* * eata.h - used by the low-level driver for EATA/DMA SCSI host adapters. */ -#ifndef _EATA_H -#define _EATA_H -#include - -int eata2x_detect(Scsi_Host_Template *); -int eata2x_release(struct Scsi_Host *); -int eata2x_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); -int eata2x_abort(Scsi_Cmnd *); -int eata2x_reset(Scsi_Cmnd *); -int eata2x_biosparam(struct scsi_device *, struct block_device *, +static int eata2x_detect(Scsi_Host_Template *); +static int eata2x_release(struct Scsi_Host *); +static int eata2x_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); +static int eata2x_eh_abort(Scsi_Cmnd *); +static int eata2x_eh_host_reset(Scsi_Cmnd *); +static int eata2x_biosparam(struct scsi_device *, struct block_device *, sector_t, int *); static int eata2x_slave_attach(Scsi_Device *); -#define EATA_VERSION "7.70.00" +#define EATA_VERSION "8.00.00" #define EATA { \ name: "EATA/DMA 2.0x rev. " EATA_VERSION " ", \ detect: eata2x_detect, \ release: eata2x_release, \ queuecommand: eata2x_queuecommand, \ - eh_abort_handler: eata2x_abort, \ - eh_host_reset_handler: eata2x_reset, \ - bios_param: eata2x_biosparam, \ + eh_abort_handler: eata2x_eh_abort, \ + eh_device_reset_handler: NULL, \ + eh_bus_reset_handler: NULL, \ + eh_host_reset_handler: eata2x_eh_host_reset, \ + bios_param: eata2x_bios_param, \ slave_attach: eata2x_slave_attach, \ this_id: 7, \ unchecked_isa_dma: 1, \ - use_clustering: ENABLE_CLUSTERING, \ + use_clustering: ENABLE_CLUSTERING \ } - -#endif diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/scsi/eata_pio.c linux.2.5.45-ac1/drivers/scsi/eata_pio.c --- linux.2.5.45/drivers/scsi/eata_pio.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.45-ac1/drivers/scsi/eata_pio.c 2002-11-03 00:30:17.000000000 +0000 @@ -14,6 +14,9 @@ * neuffer@goofy.zdv.uni-mainz.de * * a.arnold@kfa-juelich.de * * * + * Updated 2002 by Alan Cox for Linux * + * 2.5.x and the newer locking and error handling * + * * * 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 * @@ -30,15 +33,23 @@ * Public License along with this kernel; if not, write to * * the Free Software Foundation, Inc., 675 Mass Ave, * * Cambridge, MA 02139, USA. * + * * + * 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 are deemed to be part of the source code. * * * ************************************************************ - * last change: 96/07/16 OS: Linux 2.0.8 * + * last change: 2002/11/02 OS: Linux 2.5.45 * ************************************************************/ /* Look in eata_pio.h for configuration information */ #include - + #include #include #include @@ -57,902 +68,830 @@ #include #include -static uint ISAbases[MAXISA] = -{0x1F0, 0x170, 0x330, 0x230}; -static uint ISAirqs[MAXISA] = -{14,12,15,11}; -static unchar EISAbases[] = -{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; +static uint ISAbases[MAXISA] = { + 0x1F0, 0x170, 0x330, 0x230 +}; + +static uint ISAirqs[MAXISA] = { + 14, 12, 15, 11 +}; + +static unsigned char EISAbases[] = { + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1 +}; + static uint registered_HBAs = 0; -static struct Scsi_Host *last_HBA = NULL; -static struct Scsi_Host *first_HBA = NULL; -static unchar reg_IRQ[] = -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; -static unchar reg_IRQL[] = -{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static struct Scsi_Host *last_HBA; +static struct Scsi_Host *first_HBA; +static unsigned char reg_IRQ[]; +static unsigned char reg_IRQL[]; -static ulong int_counter = 0; -static ulong queue_counter = 0; +static unsigned long int_counter = 0; +static unsigned long queue_counter = 0; #include "eata_pio_proc.c" - -#ifdef MODULE -int eata_pio_release(struct Scsi_Host *sh) -{ - if (sh->irq && reg_IRQ[sh->irq] == 1) free_irq(sh->irq, NULL); - else reg_IRQ[sh->irq]--; - if (SD(sh)->channel == 0) { - if (sh->io_port && sh->n_io_port) - release_region(sh->io_port, sh->n_io_port); - } - return(TRUE); -} -#endif -void IncStat(Scsi_Pointer *SCp, uint Increment) +static int eata_pio_release(struct Scsi_Host *sh) { - SCp->ptr+=Increment; - if ((SCp->this_residual-=Increment)==0) - { - if ((--SCp->buffers_residual)==0) SCp->Status=FALSE; + if (sh->irq && reg_IRQ[sh->irq] == 1) + free_irq(sh->irq, NULL); else + reg_IRQ[sh->irq]--; + if (SD(sh)->channel == 0) { + if (sh->io_port && sh->n_io_port) + release_region(sh->io_port, sh->n_io_port); + } + return (TRUE); +} + +static void IncStat(Scsi_Pointer * SCp, uint Increment) +{ + SCp->ptr += Increment; + if ((SCp->this_residual -= Increment) == 0) { + if ((--SCp->buffers_residual) == 0) + SCp->Status = FALSE; + else { + SCp->buffer++; + SCp->ptr = page_address(SCp->buffer->page) + SCp->buffer->offset; + SCp->this_residual = SCp->buffer->length; + } + } +} + +static void eata_pio_int_handler(int irq, void *dev_id, struct pt_regs *regs); + +static void do_eata_pio_int_handler(int irq, void *dev_id, struct pt_regs *regs) +{ + unsigned long flags; + struct Scsi_Host *dev = dev_id; + + spin_lock_irqsave(dev->host_lock, flags); + eata_pio_int_handler(irq, dev_id, regs); + spin_unlock_irqrestore(dev->host_lock, flags); +} + +static void eata_pio_int_handler(int irq, void *dev_id, struct pt_regs *regs) +{ + uint eata_stat = 0xfffff; + Scsi_Cmnd *cmd; + hostdata *hd; + struct eata_ccb *cp; + uint base; + uint x, z; + struct Scsi_Host *sh; + unsigned short zwickel = 0; + unsigned char stat, odd; + + for (x = 1, sh = first_HBA; x <= registered_HBAs; x++, sh = SD(sh)->prev) { - SCp->buffer++; - SCp->ptr=page_address(SCp->buffer->page) + SCp->buffer->offset; - SCp->this_residual=SCp->buffer->length; - } - } -} - -void eata_pio_int_handler(int irq, void *dev_id, struct pt_regs * regs); - -void do_eata_pio_int_handler(int irq, void *dev_id, struct pt_regs * regs) -{ - unsigned long flags; - struct Scsi_Host *dev = dev_id; - - spin_lock_irqsave(dev->host_lock, flags); - eata_pio_int_handler(irq, dev_id, regs); - spin_unlock_irqrestore(dev->host_lock, flags); -} - -void eata_pio_int_handler(int irq, void *dev_id, struct pt_regs * regs) -{ - uint eata_stat = 0xfffff; - Scsi_Cmnd *cmd; - hostdata *hd; - struct eata_ccb *cp; - uint base; - uint x,z; - struct Scsi_Host *sh; - ushort zwickel=0; - unchar stat,odd; - - for (x = 1, sh = first_HBA; x <= registered_HBAs; x++, sh = SD(sh)->prev) { - if (sh->irq != irq) - continue; - if (inb((uint)sh->base + HA_RSTATUS) & HA_SBUSY) - continue; - - int_counter++; - - hd=SD(sh); - - cp = &hd->ccb[0]; - cmd = cp->cmd; - base = (uint) cmd->host->base; - - do - { - stat=inb(base+HA_RSTATUS); - if (stat&HA_SDRQ) { - if (cp->DataIn) - { - z=256; odd=FALSE; - while ((cmd->SCp.Status)&&((z>0)||(odd))) - { - if (odd) - { - *(cmd->SCp.ptr)=zwickel>>8; - IncStat(&cmd->SCp,1); - odd=FALSE; - } - x=min_t(unsigned int,z,cmd->SCp.this_residual/2); - insw(base+HA_RDATA,cmd->SCp.ptr,x); - z-=x; - IncStat(&cmd->SCp,2*x); - if ((z>0)&&(cmd->SCp.this_residual==1)) - { - zwickel=inw(base+HA_RDATA); - *(cmd->SCp.ptr)=zwickel&0xff; - IncStat(&cmd->SCp,1); z--; - odd=TRUE; + if (sh->irq != irq) + continue; + if (inb((uint) sh->base + HA_RSTATUS) & HA_SBUSY) + continue; + + int_counter++; + + hd = SD(sh); + + cp = &hd->ccb[0]; + cmd = cp->cmd; + base = (uint) cmd->host->base; + + do { + stat = inb(base + HA_RSTATUS); + if (stat & HA_SDRQ) { + if (cp->DataIn) { + z = 256; + odd = FALSE; + while ((cmd->SCp.Status) && ((z > 0) || (odd))) { + if (odd) { + *(cmd->SCp.ptr) = zwickel >> 8; + IncStat(&cmd->SCp, 1); + odd = FALSE; + } + x = min_t(unsigned int, z, cmd->SCp.this_residual / 2); + insw(base + HA_RDATA, cmd->SCp.ptr, x); + z -= x; + IncStat(&cmd->SCp, 2 * x); + if ((z > 0) && (cmd->SCp.this_residual == 1)) { + zwickel = inw(base + HA_RDATA); + *(cmd->SCp.ptr) = zwickel & 0xff; + IncStat(&cmd->SCp, 1); + z--; + odd = TRUE; + } + } + while (z > 0) { + zwickel = inw(base + HA_RDATA); + z--; + } + } else { /* cp->DataOut */ + + odd = FALSE; + z = 256; + while ((cmd->SCp.Status) && ((z > 0) || (odd))) { + if (odd) { + zwickel += *(cmd->SCp.ptr) << 8; + IncStat(&cmd->SCp, 1); + outw(zwickel, base + HA_RDATA); + z--; + odd = FALSE; + } + x = min_t(unsigned int, z, cmd->SCp.this_residual / 2); + outsw(base + HA_RDATA, cmd->SCp.ptr, x); + z -= x; + IncStat(&cmd->SCp, 2 * x); + if ((z > 0) && (cmd->SCp.this_residual == 1)) { + zwickel = *(cmd->SCp.ptr); + zwickel &= 0xff; + IncStat(&cmd->SCp, 1); + odd = TRUE; + } + } + while (z > 0 || odd) { + outw(zwickel, base + HA_RDATA); + z--; + odd = FALSE; + } + } } - } - while (z>0) { - zwickel=inw(base+HA_RDATA); - z--; - } - } - else /* cp->DataOut */ - { - odd=FALSE; z=256; - while ((cmd->SCp.Status)&&((z>0)||(odd))) - { - if (odd) - { - zwickel+=*(cmd->SCp.ptr)<<8; - IncStat(&cmd->SCp,1); - outw(zwickel,base+HA_RDATA); - z--; - odd=FALSE; - } - x=min_t(unsigned int,z,cmd->SCp.this_residual/2); - outsw(base+HA_RDATA,cmd->SCp.ptr,x); - z-=x; - IncStat(&cmd->SCp,2*x); - if ((z>0)&&(cmd->SCp.this_residual==1)) - { - zwickel=*(cmd->SCp.ptr); - zwickel&=0xff; - IncStat(&cmd->SCp,1); - odd=TRUE; - } - } - while (z>0||odd) { - outw(zwickel,base+HA_RDATA); - z--; - odd=FALSE; - } - } - } - } - while ((stat&HA_SDRQ)||((stat&HA_SMORE)&&hd->moresupport)); - - /* terminate handler if HBA goes busy again, i.e. transfers - * more data */ - - if (stat&HA_SBUSY) break; - - /* OK, this is quite stupid, but I haven't found any correct - * way to get HBA&SCSI status so far */ - - if (!(inb(base+HA_RSTATUS)&HA_SERROR)) - { - cmd->result=(DID_OK<<16); - hd->devflags|=(1<cp_id); - } - else if (hd->devflags&1<cp_id) - cmd->result=(DID_OK<<16)+0x02; - else cmd->result=(DID_NO_CONNECT<<16); - - if (cp->status == LOCKED) { - cp->status = FREE; - eata_stat = inb(base + HA_RSTATUS); - printk(KERN_CRIT "eata_pio: int_handler, freeing locked " - "queueslot\n"); - return; - } - + } + while ((stat & HA_SDRQ) || ((stat & HA_SMORE) && hd->moresupport)); + + /* terminate handler if HBA goes busy again, i.e. transfers + * more data */ + + if (stat & HA_SBUSY) + break; + + /* OK, this is quite stupid, but I haven't found any correct + * way to get HBA&SCSI status so far */ + + if (!(inb(base + HA_RSTATUS) & HA_SERROR)) { + cmd->result = (DID_OK << 16); + hd->devflags |= (1 << cp->cp_id); + } else if (hd->devflags & 1 << cp->cp_id) + cmd->result = (DID_OK << 16) + 0x02; + else + cmd->result = (DID_NO_CONNECT << 16); + + if (cp->status == LOCKED) { + cp->status = FREE; + eata_stat = inb(base + HA_RSTATUS); + printk(KERN_CRIT "eata_pio: int_handler, freeing locked " "queueslot\n"); + return; + } #if DBG_INTR2 - if (stat != 0x50) - printk(KERN_DEBUG "stat: %#.2x, result: %#.8x\n", stat, - cmd->result); + if (stat != 0x50) + printk(KERN_DEBUG "stat: %#.2x, result: %#.8x\n", stat, cmd->result); #endif - - cp->status = FREE; /* now we can release the slot */ - - cmd->scsi_done(cmd); - } - - return; -} - -inline uint eata_pio_send_command(uint base, unchar command) -{ - uint loop = HZ/2; - - while (inb(base + HA_RSTATUS) & HA_SBUSY) - if (--loop == 0) - return(TRUE); - - /* Enable interrupts for HBA. It is not the best way to do it at this - * place, but I hope that it doesn't interfere with the IDE driver - * initialization this way */ - - outb(HA_CTRL_8HEADS,base+HA_CTRLREG); - - outb(command, base + HA_WCOMMAND); - return(FALSE); -} - -int eata_pio_queue(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) -{ - uint x, y; - uint base; - - hostdata *hd; - struct Scsi_Host *sh; - struct eata_ccb *cp; - - queue_counter++; - - hd = HD(cmd); - sh = cmd->host; - base = (uint) sh->base; - - /* use only slot 0, as 2001 can handle only one cmd at a time */ - - y = x = 0; - - if (hd->ccb[y].status!=FREE) { - - DBG(DBG_QUEUE, printk(KERN_EMERG "can_queue %d, x %d, y %d\n", - sh->can_queue,x,y)); + + cp->status = FREE; /* now we can release the slot */ + + cmd->scsi_done(cmd); + } + + return; +} + +static inline uint eata_pio_send_command(uint base, unsigned char command) +{ + uint loop = HZ / 2; + + while (inb(base + HA_RSTATUS) & HA_SBUSY) + if (--loop == 0) + return (TRUE); + + /* Enable interrupts for HBA. It is not the best way to do it at this + * place, but I hope that it doesn't interfere with the IDE driver + * initialization this way */ + + outb(HA_CTRL_8HEADS, base + HA_CTRLREG); + + outb(command, base + HA_WCOMMAND); + return (FALSE); +} + +static int eata_pio_queue(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) +{ + uint x, y; + uint base; + + hostdata *hd; + struct Scsi_Host *sh; + struct eata_ccb *cp; + + queue_counter++; + + hd = HD(cmd); + sh = cmd->host; + base = (uint) sh->base; + + /* use only slot 0, as 2001 can handle only one cmd at a time */ + + y = x = 0; + + if (hd->ccb[y].status != FREE) { + + DBG(DBG_QUEUE, printk(KERN_EMERG "can_queue %d, x %d, y %d\n", sh->can_queue, x, y)); #if DEBUG_EATA - panic(KERN_EMERG "eata_pio: run out of queue slots cmdno:%ld " - "intrno: %ld\n", queue_counter, int_counter); + panic(KERN_EMERG "eata_pio: run out of queue slots cmdno:%ld " "intrno: %ld\n", queue_counter, int_counter); #else - panic(KERN_EMERG "eata_pio: run out of queue slots....\n"); + panic(KERN_EMERG "eata_pio: run out of queue slots....\n"); #endif - } - - cp = &hd->ccb[y]; - - memset(cp, 0, sizeof(struct eata_ccb)); - memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer)); - - cp->status = USED; /* claim free slot */ - - DBG(DBG_QUEUE, printk(KERN_DEBUG "eata_pio_queue pid %ld, target: %x, lun:" - " %x, y %d\n", cmd->pid, cmd->target, cmd->lun, y)); - - cmd->scsi_done = (void *)done; - - /* FIXME: use passed direction flag !! */ - switch (cmd->cmnd[0]) { - case CHANGE_DEFINITION: case COMPARE: case COPY: - case COPY_VERIFY: case LOG_SELECT: case MODE_SELECT: - case MODE_SELECT_10: case SEND_DIAGNOSTIC: case WRITE_BUFFER: - case FORMAT_UNIT: case REASSIGN_BLOCKS: case RESERVE: - case SEARCH_EQUAL: case SEARCH_HIGH: case SEARCH_LOW: - case WRITE_6: case WRITE_10: case WRITE_VERIFY: - case UPDATE_BLOCK: case WRITE_LONG: case WRITE_SAME: - case SEARCH_HIGH_12: case SEARCH_EQUAL_12: case SEARCH_LOW_12: - case WRITE_12: case WRITE_VERIFY_12: case SET_WINDOW: - case MEDIUM_SCAN: case SEND_VOLUME_TAG: - case 0xea: /* alternate number for WRITE LONG */ - cp->DataOut = TRUE; /* Output mode */ - break; - case TEST_UNIT_READY: - default: - cp->DataIn = TRUE; /* Input mode */ - } - - cp->Interpret = (cmd->target == hd->hostid); - cp->cp_datalen = htonl((ulong)cmd->request_bufflen); - cp->Auto_Req_Sen = FALSE; - cp->cp_reqDMA = htonl(0); - cp->reqlen = 0; - - cp->cp_id = cmd->target; - cp->cp_lun = cmd->lun; - cp->cp_dispri = FALSE; - cp->cp_identify = TRUE; - memcpy(cp->cp_cdb, cmd->cmnd, COMMAND_SIZE(*cmd->cmnd)); - - cp->cp_statDMA = htonl(0); - - cp->cp_viraddr = cp; - cp->cmd = cmd; - cmd->host_scribble = (char *)&hd->ccb[y]; - - if (cmd->use_sg == 0) - { - cmd->SCp.buffers_residual=1; - cmd->SCp.ptr = cmd->request_buffer; - cmd->SCp.this_residual = cmd->request_bufflen; - cmd->SCp.buffer = NULL; - } else { - cmd->SCp.buffer = cmd->request_buffer; - cmd->SCp.buffers_residual = cmd->use_sg; - cmd->SCp.ptr = page_address(cmd->SCp.buffer->page) + cmd->SCp.buffer->offset; - cmd->SCp.this_residual = cmd->SCp.buffer->length; - } - cmd->SCp.Status = (cmd->SCp.this_residual != 0); /* TRUE as long as bytes - * are to transfer */ - - if (eata_pio_send_command(base, EATA_CMD_PIO_SEND_CP)) - { - cmd->result = DID_BUS_BUSY << 16; - printk(KERN_NOTICE "eata_pio_queue target %d, pid %ld, HBA busy, " - "returning DID_BUS_BUSY, done.\n", cmd->target, cmd->pid); - done(cmd); - cp->status = FREE; - return (0); - } - while (!(inb(base + HA_RSTATUS) & HA_SDRQ)) - cpu_relax(); - outsw(base + HA_RDATA, cp, hd->cplen); - outb(EATA_CMD_PIO_TRUNC, base + HA_WCOMMAND); - for (x = 0; x < hd->cppadlen; x++) outw(0, base + HA_RDATA); - - DBG(DBG_QUEUE,printk(KERN_DEBUG "Queued base %#.4lx pid: %ld target: %x " - "lun: %x slot %d irq %d\n", (long)sh->base, cmd->pid, - cmd->target, cmd->lun, y, sh->irq)); - - return (0); -} - -int eata_pio_abort(Scsi_Cmnd * cmd) -{ - ulong flags; - uint loop = HZ; - - spin_lock_irqsave(cmd->host->host_lock, flags); - DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_abort called pid: %ld " - "target: %x lun: %x reason %x\n", cmd->pid, - cmd->target, cmd->lun, cmd->abort_reason)); - - - while (inb((uint)(cmd->host->base) + HA_RAUXSTAT) & HA_ABUSY) - if (--loop == 0) { - printk(KERN_WARNING "eata_pio: abort, timeout error.\n"); - spin_unlock_irqrestore(cmd->host->host_lock, flags); - return (SCSI_ABORT_ERROR); - } - if (CD(cmd)->status == FREE) { - DBG(DBG_ABNORM, printk(KERN_WARNING "Returning: SCSI_ABORT_NOT_RUNNING\n")); - spin_unlock_irqrestore(cmd->host->host_lock, flags); - return (SCSI_ABORT_NOT_RUNNING); - } - if (CD(cmd)->status == USED) { - DBG(DBG_ABNORM, printk(KERN_WARNING "Returning: SCSI_ABORT_BUSY\n")); - spin_unlock_irqrestore(cmd->host->host_lock, flags); - return (SCSI_ABORT_BUSY); /* SNOOZE */ - } - if (CD(cmd)->status == RESET) { - spin_unlock_irqrestore(cmd->host->host_lock, flags); - printk(KERN_WARNING "eata_pio: abort, command reset error.\n"); - return (SCSI_ABORT_ERROR); - } - if (CD(cmd)->status == LOCKED) { - spin_unlock_irqrestore(cmd->host->host_lock, flags); - DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio: abort, queue slot " - "locked.\n")); - return (SCSI_ABORT_NOT_RUNNING); - } - spin_unlock_irqrestore(cmd->host->host_lock, flags); - panic("eata_pio: abort: invalid slot status\n"); -} - -int eata_pio_reset(Scsi_Cmnd * cmd, unsigned int dummy) -{ - uint x, limit = 0; - ulong flags; - unchar success = FALSE; - Scsi_Cmnd *sp; - - DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_reset called pid:%ld target:" - " %x lun: %x reason %x\n", cmd->pid, cmd->target, - cmd->lun, cmd->abort_reason)); - - spin_lock_irqsave(cmd->host->host_lock, flags); - if (HD(cmd)->state == RESET) { - printk(KERN_WARNING "eata_pio_reset: exit, already in reset.\n"); - spin_unlock_irqrestore(cmd->host->host_lock, flags); - return (SCSI_RESET_ERROR); - } - - /* force all slots to be free */ - - for (x = 0; x < cmd->host->can_queue; x++) { - - if (HD(cmd)->ccb[x].status == FREE) - continue; - - sp = HD(cmd)->ccb[x].cmd; - HD(cmd)->ccb[x].status = RESET; - printk(KERN_WARNING "eata_pio_reset: slot %d in reset, pid %ld.\n", x, - sp->pid); - - if (sp == NULL) - panic("eata_pio_reset: slot %d, sp==NULL.\n", x); - } - - /* hard reset the HBA */ - outb(EATA_CMD_RESET, (uint) cmd->host->base+HA_WCOMMAND); - - DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_reset: board reset done.\n")); - HD(cmd)->state = RESET; - - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(3*HZ); - - DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_reset: interrupts disabled, " - "loops %d.\n", limit)); - - for (x = 0; x < cmd->host->can_queue; x++) { - - /* Skip slots already set free by interrupt */ - if (HD(cmd)->ccb[x].status != RESET) - continue; - - sp = HD(cmd)->ccb[x].cmd; - sp->result = DID_RESET << 16; - - /* This mailbox is terminated */ - printk(KERN_WARNING "eata_pio_reset: reset ccb %d.\n",x); - HD(cmd)->ccb[x].status = FREE; - - sp->scsi_done(sp); - } - - HD(cmd)->state = FALSE; - spin_unlock_irqrestore(cmd->host->host_lock, flags); - - if (success) { /* hmmm... */ - DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_reset: exit, success.\n")); - return (SCSI_RESET_SUCCESS); - } else { - DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_reset: exit, wakeup.\n")); - return (SCSI_RESET_PUNT); - } -} - -char * get_pio_board_data(ulong base, uint irq, uint id, ulong cplen, ushort cppadlen) -{ - struct eata_ccb cp; - static char buff[256]; - int z; - - memset(&cp, 0, sizeof(struct eata_ccb)); - memset(buff, 0, sizeof(buff)); - - cp.DataIn = TRUE; - cp.Interpret = TRUE; /* Interpret command */ - - cp.cp_datalen = htonl(254); - cp.cp_dataDMA = htonl(0); - - cp.cp_id = id; - cp.cp_lun = 0; - - cp.cp_cdb[0] = INQUIRY; - cp.cp_cdb[1] = 0; - cp.cp_cdb[2] = 0; - cp.cp_cdb[3] = 0; - cp.cp_cdb[4] = 254; - cp.cp_cdb[5] = 0; - - if (eata_pio_send_command((uint) base, EATA_CMD_PIO_SEND_CP)) - return (NULL); - while (!(inb(base + HA_RSTATUS) & HA_SDRQ)); - outsw(base + HA_RDATA, &cp, cplen); - outb(EATA_CMD_PIO_TRUNC, base + HA_WCOMMAND); - for (z = 0; z < cppadlen; z++) outw(0, base + HA_RDATA); - - while (inb(base + HA_RSTATUS) & HA_SBUSY); - if (inb(base + HA_RSTATUS) & HA_SERROR) - return (NULL); - else if (!(inb(base + HA_RSTATUS) & HA_SDRQ)) - return (NULL); - else - { - insw(base+HA_RDATA, &buff, 127); - while (inb(base + HA_RSTATUS)&HA_SDRQ) inw(base + HA_RDATA); - return (buff); - } -} - -int get_pio_conf_PIO(u32 base, struct get_conf *buf) -{ - ulong loop = HZ/2; - int z; - ushort *p; - - if(check_region(base, 9)) - return (FALSE); - - memset(buf, 0, sizeof(struct get_conf)); - - while (inb(base + HA_RSTATUS) & HA_SBUSY) - if (--loop == 0) - return (FALSE); - - DBG(DBG_PIO && DBG_PROBE, - printk(KERN_DEBUG "Issuing PIO READ CONFIG to HBA at %#x\n", base)); - eata_pio_send_command(base, EATA_CMD_PIO_READ_CONFIG); - - loop = HZ/2; - for (p = (ushort *) buf; - (long)p <= ((long)buf + (sizeof(struct get_conf) / 2)); p++) { + } + + cp = &hd->ccb[y]; + + memset(cp, 0, sizeof(struct eata_ccb)); + memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer)); + + cp->status = USED; /* claim free slot */ + + DBG(DBG_QUEUE, printk(KERN_DEBUG "eata_pio_queue pid %ld, target: %x, lun:" " %x, y %d\n", cmd->pid, cmd->target, cmd->lun, y)); + + cmd->scsi_done = (void *) done; + + if(cmd->sc_data_direction == SCSI_DATA_WRITE) + cp->DataOut = TRUE; /* Output mode */ + else + cp->DataIn = TRUE; /* Input mode */ + + cp->Interpret = (cmd->target == hd->hostid); + cp->cp_datalen = htonl((unsigned long) cmd->request_bufflen); + cp->Auto_Req_Sen = FALSE; + cp->cp_reqDMA = htonl(0); + cp->reqlen = 0; + + cp->cp_id = cmd->target; + cp->cp_lun = cmd->lun; + cp->cp_dispri = FALSE; + cp->cp_identify = TRUE; + memcpy(cp->cp_cdb, cmd->cmnd, COMMAND_SIZE(*cmd->cmnd)); + + cp->cp_statDMA = htonl(0); + + cp->cp_viraddr = cp; + cp->cmd = cmd; + cmd->host_scribble = (char *) &hd->ccb[y]; + + if (cmd->use_sg == 0) { + cmd->SCp.buffers_residual = 1; + cmd->SCp.ptr = cmd->request_buffer; + cmd->SCp.this_residual = cmd->request_bufflen; + cmd->SCp.buffer = NULL; + } else { + cmd->SCp.buffer = cmd->request_buffer; + cmd->SCp.buffers_residual = cmd->use_sg; + cmd->SCp.ptr = page_address(cmd->SCp.buffer->page) + cmd->SCp.buffer->offset; + cmd->SCp.this_residual = cmd->SCp.buffer->length; + } + cmd->SCp.Status = (cmd->SCp.this_residual != 0); /* TRUE as long as bytes + * are to transfer */ + + if (eata_pio_send_command(base, EATA_CMD_PIO_SEND_CP)) { + cmd->result = DID_BUS_BUSY << 16; + printk(KERN_NOTICE "eata_pio_queue target %d, pid %ld, HBA busy, " "returning DID_BUS_BUSY, done.\n", cmd->target, cmd->pid); + done(cmd); + cp->status = FREE; + return (0); + } + /* FIXME: timeout */ while (!(inb(base + HA_RSTATUS) & HA_SDRQ)) - if (--loop == 0) + cpu_relax(); + outsw(base + HA_RDATA, cp, hd->cplen); + outb(EATA_CMD_PIO_TRUNC, base + HA_WCOMMAND); + for (x = 0; x < hd->cppadlen; x++) + outw(0, base + HA_RDATA); + + DBG(DBG_QUEUE, printk(KERN_DEBUG "Queued base %#.4lx pid: %ld target: %x " "lun: %x slot %d irq %d\n", (long) sh->base, cmd->pid, cmd->target, cmd->lun, y, sh->irq)); + + return (0); +} + +static int eata_pio_abort(Scsi_Cmnd * cmd) +{ + uint loop = HZ; + + DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_abort called pid: %ld " "target: %x lun: %x reason %x\n", cmd->pid, cmd->target, cmd->lun, cmd->abort_reason)); + + + while (inb(cmd->host->base + HA_RAUXSTAT) & HA_ABUSY) + if (--loop == 0) { + printk(KERN_WARNING "eata_pio: abort, timeout error.\n"); + return FAILED; + } + if (CD(cmd)->status == FREE) { + DBG(DBG_ABNORM, printk(KERN_WARNING "Returning: SCSI_ABORT_NOT_RUNNING\n")); + return FAILED; + } + if (CD(cmd)->status == USED) { + DBG(DBG_ABNORM, printk(KERN_WARNING "Returning: SCSI_ABORT_BUSY\n")); + /* We want to sleep a bit more here */ + return FAILED; /* SNOOZE */ + } + if (CD(cmd)->status == RESET) { + printk(KERN_WARNING "eata_pio: abort, command reset error.\n"); + return FAILED; + } + if (CD(cmd)->status == LOCKED) { + DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio: abort, queue slot " "locked.\n")); + return FAILED; + } + panic("eata_pio: abort: invalid slot status\n"); +} + +static int eata_pio_host_reset(Scsi_Cmnd * cmd) +{ + uint x, limit = 0; + unsigned char success = FALSE; + Scsi_Cmnd *sp; + struct Scsi_Host *host = cmd->host; + + DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_reset called pid:%ld target:" " %x lun: %x reason %x\n", cmd->pid, cmd->target, cmd->lun, cmd->abort_reason)); + + if (HD(cmd)->state == RESET) { + printk(KERN_WARNING "eata_pio_reset: exit, already in reset.\n"); + return FAILED; + } + + /* force all slots to be free */ + + for (x = 0; x < cmd->host->can_queue; x++) { + + if (HD(cmd)->ccb[x].status == FREE) + continue; + + sp = HD(cmd)->ccb[x].cmd; + HD(cmd)->ccb[x].status = RESET; + printk(KERN_WARNING "eata_pio_reset: slot %d in reset, pid %ld.\n", x, sp->pid); + + if (sp == NULL) + panic("eata_pio_reset: slot %d, sp==NULL.\n", x); + } + + /* hard reset the HBA */ + outb(EATA_CMD_RESET, (uint) cmd->host->base + HA_WCOMMAND); + + DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_reset: board reset done.\n")); + HD(cmd)->state = RESET; + + spin_unlock_irq(host->host_lock); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(3 * HZ); + spin_lock_irq(host->host_lock); + + DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_reset: interrupts disabled, " "loops %d.\n", limit)); + + for (x = 0; x < cmd->host->can_queue; x++) { + + /* Skip slots already set free by interrupt */ + if (HD(cmd)->ccb[x].status != RESET) + continue; + + sp = HD(cmd)->ccb[x].cmd; + sp->result = DID_RESET << 16; + + /* This mailbox is terminated */ + printk(KERN_WARNING "eata_pio_reset: reset ccb %d.\n", x); + HD(cmd)->ccb[x].status = FREE; + + sp->scsi_done(sp); + } + + HD(cmd)->state = FALSE; + + if (success) { /* hmmm... */ + DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_reset: exit, success.\n")); + return SUCCESS; + } else { + DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_reset: exit, wakeup.\n")); + return FAILED; + } +} + +static char *get_pio_board_data(unsigned long base, uint irq, uint id, unsigned long cplen, unsigned short cppadlen) +{ + struct eata_ccb cp; + static char buff[256]; + int z; + + memset(&cp, 0, sizeof(struct eata_ccb)); + memset(buff, 0, sizeof(buff)); + + cp.DataIn = TRUE; + cp.Interpret = TRUE; /* Interpret command */ + + cp.cp_datalen = htonl(254); + cp.cp_dataDMA = htonl(0); + + cp.cp_id = id; + cp.cp_lun = 0; + + cp.cp_cdb[0] = INQUIRY; + cp.cp_cdb[1] = 0; + cp.cp_cdb[2] = 0; + cp.cp_cdb[3] = 0; + cp.cp_cdb[4] = 254; + cp.cp_cdb[5] = 0; + + if (eata_pio_send_command((uint) base, EATA_CMD_PIO_SEND_CP)) + return (NULL); + while (!(inb(base + HA_RSTATUS) & HA_SDRQ)); + outsw(base + HA_RDATA, &cp, cplen); + outb(EATA_CMD_PIO_TRUNC, base + HA_WCOMMAND); + for (z = 0; z < cppadlen; z++) + outw(0, base + HA_RDATA); + + while (inb(base + HA_RSTATUS) & HA_SBUSY); + if (inb(base + HA_RSTATUS) & HA_SERROR) + return (NULL); + else if (!(inb(base + HA_RSTATUS) & HA_SDRQ)) + return (NULL); + else { + insw(base + HA_RDATA, &buff, 127); + while (inb(base + HA_RSTATUS) & HA_SDRQ) + inw(base + HA_RDATA); + return (buff); + } +} + +static int get_pio_conf_PIO(u32 base, struct get_conf *buf) +{ + unsigned long loop = HZ / 2; + int z; + unsigned short *p; + + if (check_region(base, 9)) return (FALSE); - loop = HZ/2; - *p = inw(base + HA_RDATA); - } - if (!(inb(base + HA_RSTATUS) & HA_SERROR)) { /* Error ? */ - if (htonl(EATA_SIGNATURE) == buf->signature) { - DBG(DBG_PIO&&DBG_PROBE, printk(KERN_NOTICE "EATA Controller found " - "at %#4x EATA Level: %x\n", base, - (uint) (buf->version))); - - while (inb(base + HA_RSTATUS) & HA_SDRQ) - inw(base + HA_RDATA); - if(ALLOW_DMA_BOARDS == FALSE) { - for (z = 0; z < MAXISA; z++) - if (base == ISAbases[z]) { - buf->IRQ = ISAirqs[z]; - break; - } - } - return (TRUE); - } - } else { - DBG(DBG_PROBE, printk("eata_dma: get_conf_PIO, error during transfer " - "for HBA at %x\n", base)); - } - return (FALSE); -} - -void print_pio_config(struct get_conf *gc) -{ - printk("Please check values: (read config data)\n"); - printk("LEN: %d ver:%d OCS:%d TAR:%d TRNXFR:%d MORES:%d\n", - (uint) ntohl(gc->len), gc->version, - gc->OCS_enabled, gc->TAR_support, gc->TRNXFR, gc->MORE_support); - printk("HAAV:%d SCSIID0:%d ID1:%d ID2:%d QUEUE:%d SG:%d SEC:%d\n", - gc->HAA_valid, gc->scsi_id[3], gc->scsi_id[2], - gc->scsi_id[1], ntohs(gc->queuesiz), ntohs(gc->SGsiz), gc->SECOND); - printk("IRQ:%d IRQT:%d FORCADR:%d MCH:%d RIDQ:%d\n", - gc->IRQ, gc->IRQ_TR, gc->FORCADR, - gc->MAX_CHAN, gc->ID_qest); + memset(buf, 0, sizeof(struct get_conf)); + + while (inb(base + HA_RSTATUS) & HA_SBUSY) + if (--loop == 0) + return (FALSE); + + DBG(DBG_PIO && DBG_PROBE, printk(KERN_DEBUG "Issuing PIO READ CONFIG to HBA at %#x\n", base)); + eata_pio_send_command(base, EATA_CMD_PIO_READ_CONFIG); + + loop = HZ / 2; + for (p = (unsigned short *) buf; (long) p <= ((long) buf + (sizeof(struct get_conf) / 2)); p++) { + while (!(inb(base + HA_RSTATUS) & HA_SDRQ)) + if (--loop == 0) + return (FALSE); + + loop = HZ / 2; + *p = inw(base + HA_RDATA); + } + if (!(inb(base + HA_RSTATUS) & HA_SERROR)) { /* Error ? */ + if (htonl(EATA_SIGNATURE) == buf->signature) { + DBG(DBG_PIO && DBG_PROBE, printk(KERN_NOTICE "EATA Controller found " "at %#4x EATA Level: %x\n", base, (uint) (buf->version))); + + while (inb(base + HA_RSTATUS) & HA_SDRQ) + inw(base + HA_RDATA); + if (ALLOW_DMA_BOARDS == FALSE) { + for (z = 0; z < MAXISA; z++) + if (base == ISAbases[z]) { + buf->IRQ = ISAirqs[z]; + break; + } + } + return (TRUE); + } + } else { + DBG(DBG_PROBE, printk("eata_dma: get_conf_PIO, error during transfer " "for HBA at %x\n", base)); + } + return (FALSE); +} + +static void print_pio_config(struct get_conf *gc) +{ + printk("Please check values: (read config data)\n"); + printk("LEN: %d ver:%d OCS:%d TAR:%d TRNXFR:%d MORES:%d\n", (uint) ntohl(gc->len), gc->version, gc->OCS_enabled, gc->TAR_support, gc->TRNXFR, gc->MORE_support); + printk("HAAV:%d SCSIID0:%d ID1:%d ID2:%d QUEUE:%d SG:%d SEC:%d\n", gc->HAA_valid, gc->scsi_id[3], gc->scsi_id[2], gc->scsi_id[1], ntohs(gc->queuesiz), ntohs(gc->SGsiz), gc->SECOND); + printk("IRQ:%d IRQT:%d FORCADR:%d MCH:%d RIDQ:%d\n", gc->IRQ, gc->IRQ_TR, gc->FORCADR, gc->MAX_CHAN, gc->ID_qest); } static uint print_selftest(uint base) { - unchar buffer[512]; + unsigned char buffer[512]; #ifdef VERBOSE_SETUP - int z; + int z; #endif - - printk("eata_pio: executing controller self test & setup...\n"); - while (inb(base + HA_RSTATUS) & HA_SBUSY); - outb(EATA_CMD_PIO_SETUPTEST, base + HA_WCOMMAND); - do { - while (inb(base + HA_RSTATUS) & HA_SBUSY) - /* nothing */ ; - if (inb(base + HA_RSTATUS) & HA_SDRQ) - { - insw(base + HA_RDATA, &buffer, 256); + + printk("eata_pio: executing controller self test & setup...\n"); + while (inb(base + HA_RSTATUS) & HA_SBUSY); + outb(EATA_CMD_PIO_SETUPTEST, base + HA_WCOMMAND); + do { + while (inb(base + HA_RSTATUS) & HA_SBUSY) + /* nothing */ ; + if (inb(base + HA_RSTATUS) & HA_SDRQ) { + insw(base + HA_RDATA, &buffer, 256); #ifdef VERBOSE_SETUP - /* no beeps please... */ - for (z = 0; z < 511 && buffer[z]; z++) - if (buffer[z] != 7) printk("%c", buffer[z]); + /* no beeps please... */ + for (z = 0; z < 511 && buffer[z]; z++) + if (buffer[z] != 7) + printk("%c", buffer[z]); #endif + } + } while (inb(base + HA_RSTATUS) & (HA_SBUSY | HA_SDRQ)); + + return (!(inb(base + HA_RSTATUS) & HA_SERROR)); +} + +static int register_pio_HBA(long base, struct get_conf *gc, Scsi_Host_Template * tpnt) +{ + unsigned long size = 0; + char *buff; + unsigned long cplen; + unsigned short cppadlen; + struct Scsi_Host *sh; + hostdata *hd; + + DBG(DBG_REGISTER, print_pio_config(gc)); + + if (gc->DMA_support == TRUE) { + printk("HBA at %#.4lx supports DMA. Please use EATA-DMA driver.\n", base); + if (ALLOW_DMA_BOARDS == FALSE) + return (FALSE); } - } while (inb(base+HA_RSTATUS) & (HA_SBUSY|HA_SDRQ)); - - return (!(inb(base+HA_RSTATUS) & HA_SERROR)); -} - -int register_pio_HBA(long base, struct get_conf *gc, Scsi_Host_Template * tpnt) -{ - ulong size = 0; - char *buff; - ulong cplen; - ushort cppadlen; - struct Scsi_Host *sh; - hostdata *hd; - - DBG(DBG_REGISTER, print_pio_config(gc)); - - if (gc->DMA_support == TRUE) { - printk("HBA at %#.4lx supports DMA. Please use EATA-DMA driver.\n",base); - if(ALLOW_DMA_BOARDS == FALSE) - return (FALSE); - } - - if ((buff = get_pio_board_data((uint)base, gc->IRQ, gc->scsi_id[3], - cplen =(htonl(gc->cplen )+1)/2, - cppadlen=(htons(gc->cppadlen)+1)/2)) == NULL) - { - printk("HBA at %#lx didn't react on INQUIRY. Sorry.\n", (ulong) base); - return (FALSE); - } - - if (print_selftest(base) == FALSE && ALLOW_DMA_BOARDS == FALSE) - { - printk("HBA at %#lx failed while performing self test & setup.\n", - (ulong) base); - return (FALSE); - } - - request_region(base, 8, "eata_pio"); - - size = sizeof(hostdata) + (sizeof(struct eata_ccb) * ntohs(gc->queuesiz)); - - sh = scsi_register(tpnt, size); - if(sh == NULL) - { - release_region(base, 8); - return FALSE; - } - - if (!reg_IRQ[gc->IRQ]) { /* Interrupt already registered ? */ - if (!request_irq(gc->IRQ, do_eata_pio_int_handler, SA_INTERRUPT, - "EATA-PIO", sh)){ - reg_IRQ[gc->IRQ]++; - if (!gc->IRQ_TR) - reg_IRQL[gc->IRQ] = TRUE; /* IRQ is edge triggered */ + + if ((buff = get_pio_board_data((uint) base, gc->IRQ, gc->scsi_id[3], cplen = (htonl(gc->cplen) + 1) / 2, cppadlen = (htons(gc->cppadlen) + 1) / 2)) == NULL) { + printk("HBA at %#lx didn't react on INQUIRY. Sorry.\n", (unsigned long) base); + return (FALSE); + } + + if (print_selftest(base) == FALSE && ALLOW_DMA_BOARDS == FALSE) { + printk("HBA at %#lx failed while performing self test & setup.\n", (unsigned long) base); + return (FALSE); + } + + request_region(base, 8, "eata_pio"); + + size = sizeof(hostdata) + (sizeof(struct eata_ccb) * ntohs(gc->queuesiz)); + + sh = scsi_register(tpnt, size); + if (sh == NULL) { + release_region(base, 8); + return FALSE; + } + + if (!reg_IRQ[gc->IRQ]) { /* Interrupt already registered ? */ + if (!request_irq(gc->IRQ, do_eata_pio_int_handler, SA_INTERRUPT, "EATA-PIO", sh)) { + reg_IRQ[gc->IRQ]++; + if (!gc->IRQ_TR) + reg_IRQL[gc->IRQ] = TRUE; /* IRQ is edge triggered */ + } else { + printk("Couldn't allocate IRQ %d, Sorry.\n", gc->IRQ); + release_region(base, 8); + return (FALSE); + } + } else { /* More than one HBA on this IRQ */ + if (reg_IRQL[gc->IRQ] == TRUE) { + printk("Can't support more than one HBA on this IRQ,\n" " if the IRQ is edge triggered. Sorry.\n"); + release_region(base, 8); + return (FALSE); + } else + reg_IRQ[gc->IRQ]++; + } + + hd = SD(sh); + + memset(hd->ccb, 0, (sizeof(struct eata_ccb) * ntohs(gc->queuesiz))); + memset(hd->reads, 0, sizeof(unsigned long) * 26); + + strncpy(SD(sh)->vendor, &buff[8], 8); + SD(sh)->vendor[8] = 0; + strncpy(SD(sh)->name, &buff[16], 17); + SD(sh)->name[17] = 0; + SD(sh)->revision[0] = buff[32]; + SD(sh)->revision[1] = buff[33]; + SD(sh)->revision[2] = buff[34]; + SD(sh)->revision[3] = '.'; + SD(sh)->revision[4] = buff[35]; + SD(sh)->revision[5] = 0; + + switch (ntohl(gc->len)) { + case 0x1c: + SD(sh)->EATA_revision = 'a'; + break; + case 0x1e: + SD(sh)->EATA_revision = 'b'; + break; + case 0x22: + SD(sh)->EATA_revision = 'c'; + break; + case 0x24: + SD(sh)->EATA_revision = 'z'; + default: + SD(sh)->EATA_revision = '?'; + } + + if (ntohl(gc->len) >= 0x22) { + if (gc->is_PCI == TRUE) + hd->bustype = IS_PCI; + else if (gc->is_EISA == TRUE) + hd->bustype = IS_EISA; + else + hd->bustype = IS_ISA; } else { - printk("Couldn't allocate IRQ %d, Sorry.\n", gc->IRQ); - release_region(base, 8); - return (FALSE); - } - } else { /* More than one HBA on this IRQ */ - if (reg_IRQL[gc->IRQ] == TRUE) { - printk("Can't support more than one HBA on this IRQ,\n" - " if the IRQ is edge triggered. Sorry.\n"); - release_region(base, 8); - return (FALSE); - } else - reg_IRQ[gc->IRQ]++; - } - - hd = SD(sh); - - memset(hd->ccb, 0, (sizeof(struct eata_ccb) * ntohs(gc->queuesiz))); - memset(hd->reads, 0, sizeof(ulong) * 26); - - strncpy(SD(sh)->vendor, &buff[8], 8); - SD(sh)->vendor[8] = 0; - strncpy(SD(sh)->name, &buff[16], 17); - SD(sh)->name[17] = 0; - SD(sh)->revision[0] = buff[32]; - SD(sh)->revision[1] = buff[33]; - SD(sh)->revision[2] = buff[34]; - SD(sh)->revision[3] = '.'; - SD(sh)->revision[4] = buff[35]; - SD(sh)->revision[5] = 0; - - switch (ntohl(gc->len)) { - case 0x1c: - SD(sh)->EATA_revision = 'a'; - break; - case 0x1e: - SD(sh)->EATA_revision = 'b'; - break; - case 0x22: - SD(sh)->EATA_revision = 'c'; - break; - case 0x24: - SD(sh)->EATA_revision = 'z'; - default: - SD(sh)->EATA_revision = '?'; - } - - if(ntohl(gc->len) >= 0x22) { - if (gc->is_PCI == TRUE) - hd->bustype = IS_PCI; - else if (gc->is_EISA == TRUE) - hd->bustype = IS_EISA; - else - hd->bustype = IS_ISA; - } else { - if (buff[21] == '4') - hd->bustype = IS_PCI; - else if (buff[21] == '2') - hd->bustype = IS_EISA; + if (buff[21] == '4') + hd->bustype = IS_PCI; + else if (buff[21] == '2') + hd->bustype = IS_EISA; + else + hd->bustype = IS_ISA; + } + + SD(sh)->cplen = cplen; + SD(sh)->cppadlen = cppadlen; + SD(sh)->hostid = gc->scsi_id[3]; + SD(sh)->devflags = 1 << gc->scsi_id[3]; + SD(sh)->moresupport = gc->MORE_support; + sh->unique_id = base; + sh->base = base; + sh->io_port = base; + sh->n_io_port = 8; + sh->irq = gc->IRQ; + sh->dma_channel = PIO; + sh->this_id = gc->scsi_id[3]; + sh->can_queue = 1; + sh->cmd_per_lun = 1; + sh->sg_tablesize = SG_ALL; + + hd->channel = 0; + + sh->max_id = 8; + sh->max_lun = 8; + + if (gc->SECOND) + hd->primary = FALSE; else - hd->bustype = IS_ISA; - } - - SD(sh)->cplen=cplen; - SD(sh)->cppadlen=cppadlen; - SD(sh)->hostid=gc->scsi_id[3]; - SD(sh)->devflags=1<scsi_id[3]; - SD(sh)->moresupport=gc->MORE_support; - sh->unique_id = base; - sh->base = base; - sh->io_port = base; - sh->n_io_port = 8; - sh->irq = gc->IRQ; - sh->dma_channel = PIO; - sh->this_id = gc->scsi_id[3]; - sh->can_queue = 1; - sh->cmd_per_lun = 1; - sh->sg_tablesize = SG_ALL; - - hd->channel = 0; - - sh->max_id = 8; - sh->max_lun = 8; - - if (gc->SECOND) - hd->primary = FALSE; - else - hd->primary = TRUE; - - sh->unchecked_isa_dma = FALSE; /* We can only do PIO */ - - hd->next = NULL; /* build a linked list of all HBAs */ - hd->prev = last_HBA; - if(hd->prev != NULL) - SD(hd->prev)->next = sh; - last_HBA = sh; - if (first_HBA == NULL) - first_HBA = sh; - registered_HBAs++; - return (1); -} - -void find_pio_ISA(struct get_conf *buf, Scsi_Host_Template * tpnt) -{ - int i; - - for (i = 0; i < MAXISA; i++) { - if (ISAbases[i]) { - if (get_pio_conf_PIO(ISAbases[i], buf) == TRUE){ - register_pio_HBA(ISAbases[i], buf, tpnt); - } - ISAbases[i] = 0; + hd->primary = TRUE; + + sh->unchecked_isa_dma = FALSE; /* We can only do PIO */ + + hd->next = NULL; /* build a linked list of all HBAs */ + hd->prev = last_HBA; + if (hd->prev != NULL) + SD(hd->prev)->next = sh; + last_HBA = sh; + if (first_HBA == NULL) + first_HBA = sh; + registered_HBAs++; + return (1); +} + +static void find_pio_ISA(struct get_conf *buf, Scsi_Host_Template * tpnt) +{ + int i; + + for (i = 0; i < MAXISA; i++) { + if (ISAbases[i]) { + if (get_pio_conf_PIO(ISAbases[i], buf) == TRUE) { + register_pio_HBA(ISAbases[i], buf, tpnt); + } + ISAbases[i] = 0; + } } - } - return; + return; } -void find_pio_EISA(struct get_conf *buf, Scsi_Host_Template * tpnt) +static void find_pio_EISA(struct get_conf *buf, Scsi_Host_Template * tpnt) { - u32 base; - int i; + u32 base; + int i; #if CHECKPAL - u8 pal1, pal2, pal3; + u8 pal1, pal2, pal3; #endif - for (i = 0; i < MAXEISA; i++) { - if (EISAbases[i] == TRUE) { /* Still a possibility ? */ + for (i = 0; i < MAXEISA; i++) { + if (EISAbases[i] == TRUE) { /* Still a possibility ? */ - base = 0x1c88 + (i * 0x1000); + base = 0x1c88 + (i * 0x1000); #if CHECKPAL - pal1 = inb((u16)base - 8); - pal2 = inb((u16)base - 7); - pal3 = inb((u16)base - 6); - - if (((pal1 == 0x12) && (pal2 == 0x14)) || - ((pal1 == 0x38) && (pal2 == 0xa3) && (pal3 == 0x82)) || - ((pal1 == 0x06) && (pal2 == 0x94) && (pal3 == 0x24))) { - DBG(DBG_PROBE, printk(KERN_NOTICE "EISA EATA id tags found: " - "%x %x %x \n", - (int)pal1, (int)pal2, (int)pal3)); + pal1 = inb((u16) base - 8); + pal2 = inb((u16) base - 7); + pal3 = inb((u16) base - 6); + + if (((pal1 == 0x12) && (pal2 == 0x14)) || ((pal1 == 0x38) && (pal2 == 0xa3) && (pal3 == 0x82)) || ((pal1 == 0x06) && (pal2 == 0x94) && (pal3 == 0x24))) { + DBG(DBG_PROBE, printk(KERN_NOTICE "EISA EATA id tags found: " "%x %x %x \n", (int) pal1, (int) pal2, (int) pal3)); #endif - if (get_pio_conf_PIO(base, buf) == TRUE) { - DBG(DBG_PROBE && DBG_EISA, print_pio_config(buf)); - if (buf->IRQ) { - register_pio_HBA(base, buf, tpnt); - } else - printk(KERN_NOTICE "eata_dma: No valid IRQ. HBA " - "removed from list\n"); - } - /* Nothing found here so we take it from the list */ - EISAbases[i] = 0; + if (get_pio_conf_PIO(base, buf) == TRUE) { + DBG(DBG_PROBE && DBG_EISA, print_pio_config(buf)); + if (buf->IRQ) { + register_pio_HBA(base, buf, tpnt); + } else + printk(KERN_NOTICE "eata_dma: No valid IRQ. HBA " "removed from list\n"); + } + /* Nothing found here so we take it from the list */ + EISAbases[i] = 0; #if CHECKPAL - } + } #endif + } } - } - return; + return; } -void find_pio_PCI(struct get_conf *buf, Scsi_Host_Template * tpnt) +static void find_pio_PCI(struct get_conf *buf, Scsi_Host_Template * tpnt) { #ifndef CONFIG_PCI - printk("eata_dma: kernel PCI support not enabled. Skipping scan for PCI HBAs.\n"); + printk("eata_dma: kernel PCI support not enabled. Skipping scan for PCI HBAs.\n"); #else - struct pci_dev *dev = NULL; - u32 base, x; + struct pci_dev *dev = NULL; + u32 base, x; - while ((dev = pci_find_device(PCI_VENDOR_ID_DPT, PCI_DEVICE_ID_DPT, dev)) != NULL) { - DBG(DBG_PROBE && DBG_PCI, - printk("eata_pio: find_PCI, HBA at %s\n", dev->name)); - if (pci_enable_device(dev)) - continue; - pci_set_master(dev); - base = pci_resource_flags(dev, 0); - if (base & IORESOURCE_MEM) { - printk("eata_pio: invalid base address of device %s\n", dev->name); - continue; - } - base = pci_resource_start(dev, 0); - /* EISA tag there ? */ - if ((inb(base) == 0x12) && (inb(base + 1) == 0x14)) - continue; /* Jep, it's forced, so move on */ - base += 0x10; /* Now, THIS is the real address */ - if (base != 0x1f8) { - /* We didn't find it in the primary search */ - if (get_pio_conf_PIO(base, buf) == TRUE) { - if (buf->FORCADR) /* If the address is forced */ - continue; /* we'll find it later */ - - /* OK. We made it till here, so we can go now - * and register it. We only have to check and - * eventually remove it from the EISA and ISA list - */ - - register_pio_HBA(base, buf, tpnt); - - if (base < 0x1000) { - for (x = 0; x < MAXISA; ++x) { - if (ISAbases[x] == base) { - ISAbases[x] = 0; - break; - } + while ((dev = pci_find_device(PCI_VENDOR_ID_DPT, PCI_DEVICE_ID_DPT, dev)) != NULL) { + DBG(DBG_PROBE && DBG_PCI, printk("eata_pio: find_PCI, HBA at %s\n", dev->name)); + if (pci_enable_device(dev)) + continue; + pci_set_master(dev); + base = pci_resource_flags(dev, 0); + if (base & IORESOURCE_MEM) { + printk("eata_pio: invalid base address of device %s\n", dev->name); + continue; + } + base = pci_resource_start(dev, 0); + /* EISA tag there ? */ + if ((inb(base) == 0x12) && (inb(base + 1) == 0x14)) + continue; /* Jep, it's forced, so move on */ + base += 0x10; /* Now, THIS is the real address */ + if (base != 0x1f8) { + /* We didn't find it in the primary search */ + if (get_pio_conf_PIO(base, buf) == TRUE) { + if (buf->FORCADR) /* If the address is forced */ + continue; /* we'll find it later */ + + /* OK. We made it till here, so we can go now + * and register it. We only have to check and + * eventually remove it from the EISA and ISA list + */ + + register_pio_HBA(base, buf, tpnt); + + if (base < 0x1000) { + for (x = 0; x < MAXISA; ++x) { + if (ISAbases[x] == base) { + ISAbases[x] = 0; + break; + } + } + } else if ((base & 0x0fff) == 0x0c88) { + x = (base >> 12) & 0x0f; + EISAbases[x] = 0; + } } - } else if ((base & 0x0fff) == 0x0c88) { - x = (base >> 12) & 0x0f; - EISAbases[x] = 0; - } - } #if CHECK_BLINK - else if (check_blink_state(base) == TRUE) { - printk("eata_pio: HBA is in BLINK state.\n" - "Consult your HBAs manual to correct this.\n"); - } + else if (check_blink_state(base) == TRUE) { + printk("eata_pio: HBA is in BLINK state.\n" "Consult your HBAs manual to correct this.\n"); + } #endif - } + } } -#endif /* #ifndef CONFIG_PCI */ +#endif /* #ifndef CONFIG_PCI */ } -int eata_pio_detect(Scsi_Host_Template * tpnt) +static int eata_pio_detect(Scsi_Host_Template * tpnt) { - struct Scsi_Host *HBA_ptr; - struct get_conf gc; - int i; - - tpnt->proc_name = "eata_pio"; - - find_pio_PCI(&gc, tpnt); - - find_pio_EISA(&gc, tpnt); - - find_pio_ISA(&gc, tpnt); - - for (i = 0; i <= MAXIRQ; i++) - if (reg_IRQ[i]) - request_irq(i, do_eata_pio_int_handler, SA_INTERRUPT, "EATA-PIO", NULL); - - HBA_ptr = first_HBA; - - if (registered_HBAs != 0) { - printk("EATA (Extended Attachment) PIO driver version: %d.%d%s\n" - "(c) 1993-95 Michael Neuffer, neuffer@goofy.zdv.uni-mainz.de\n" - " Alfred Arnold, a.arnold@kfa-juelich.de\n" - "This release only supports DASD devices (harddisks)\n", - VER_MAJOR, VER_MINOR, VER_SUB); - - printk("Registered HBAs:\n"); - printk("HBA no. Boardtype: Revis: EATA: Bus: BaseIO: IRQ: Ch: ID: Pr:" - " QS: SG: CPL:\n"); - for (i = 1; i <= registered_HBAs; i++) { - printk("scsi%-2d: %.10s v%s 2.0%c %s %#.4x %2d %d %d %c" - " %2d %2d %2d\n", - HBA_ptr->host_no, SD(HBA_ptr)->name, SD(HBA_ptr)->revision, - SD(HBA_ptr)->EATA_revision, (SD(HBA_ptr)->bustype == 'P')? - "PCI ":(SD(HBA_ptr)->bustype == 'E')?"EISA":"ISA ", - (uint) HBA_ptr->base, HBA_ptr->irq, SD(HBA_ptr)->channel, - HBA_ptr->this_id, (SD(HBA_ptr)->primary == TRUE)?'Y':'N', - HBA_ptr->can_queue, HBA_ptr->sg_tablesize, - HBA_ptr->cmd_per_lun); - HBA_ptr = SD(HBA_ptr)->next; + struct Scsi_Host *HBA_ptr; + struct get_conf gc; + int i; + + tpnt->proc_name = "eata_pio"; + + find_pio_PCI(&gc, tpnt); + + find_pio_EISA(&gc, tpnt); + + find_pio_ISA(&gc, tpnt); + + for (i = 0; i <= MAXIRQ; i++) + if (reg_IRQ[i]) + request_irq(i, do_eata_pio_int_handler, SA_INTERRUPT, "EATA-PIO", NULL); + + HBA_ptr = first_HBA; + + if (registered_HBAs != 0) { + printk("EATA (Extended Attachment) PIO driver version: %d.%d%s\n" + "(c) 1993-95 Michael Neuffer, neuffer@goofy.zdv.uni-mainz.de\n" " Alfred Arnold, a.arnold@kfa-juelich.de\n" "This release only supports DASD devices (harddisks)\n", VER_MAJOR, VER_MINOR, VER_SUB); + + printk("Registered HBAs:\n"); + printk("HBA no. Boardtype: Revis: EATA: Bus: BaseIO: IRQ: Ch: ID: Pr:" " QS: SG: CPL:\n"); + for (i = 1; i <= registered_HBAs; i++) { + printk("scsi%-2d: %.10s v%s 2.0%c %s %#.4x %2d %d %d %c" + " %2d %2d %2d\n", + HBA_ptr->host_no, SD(HBA_ptr)->name, SD(HBA_ptr)->revision, + SD(HBA_ptr)->EATA_revision, (SD(HBA_ptr)->bustype == 'P') ? + "PCI " : (SD(HBA_ptr)->bustype == 'E') ? "EISA" : "ISA ", + (uint) HBA_ptr->base, HBA_ptr->irq, SD(HBA_ptr)->channel, HBA_ptr->this_id, (SD(HBA_ptr)->primary == TRUE) ? 'Y' : 'N', HBA_ptr->can_queue, HBA_ptr->sg_tablesize, HBA_ptr->cmd_per_lun); + HBA_ptr = SD(HBA_ptr)->next; + } } - } - return (registered_HBAs); + return (registered_HBAs); } /* Eventually this will go into an include file, but this will be later */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/scsi/eata_pio.h linux.2.5.45-ac1/drivers/scsi/eata_pio.h --- linux.2.5.45/drivers/scsi/eata_pio.h 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.45-ac1/drivers/scsi/eata_pio.h 2002-11-03 00:29:58.000000000 +0000 @@ -2,7 +2,7 @@ * Header file for eata_pio.c Linux EATA-PIO SCSI driver * * (c) 1993-96 Michael Neuffer * ********************************************************* -* last change: 96/05/05 * +* last change: 2002/11/02 * ********************************************************/ @@ -14,7 +14,6 @@ #include "hosts.h" #include -#ifndef HOSTS_C #include "eata_generic.h" #define VER_MAJOR 0 @@ -25,82 +24,55 @@ * Here you can switch parts of the code on and of * ************************************************************************/ -#define VERBOSE_SETUP /* show startup screen of 2001 */ +#define VERBOSE_SETUP /* show startup screen of 2001 */ #define ALLOW_DMA_BOARDS 1 /************************************************************************ * Debug options. * * Enable DEBUG and whichever options you require. * ************************************************************************/ -#define DEBUG_EATA 1 /* Enable debug code. */ -#define DPT_DEBUG 0 /* Bobs special */ -#define DBG_DELAY 0 /* Build in delays so debug messages can be - * be read before they vanish of the top of - * the screen! - */ -#define DBG_PROBE 0 /* Debug probe routines. */ -#define DBG_ISA 0 /* Trace ISA routines */ -#define DBG_EISA 0 /* Trace EISA routines */ -#define DBG_PCI 0 /* Trace PCI routines */ -#define DBG_PIO 0 /* Trace get_config_PIO */ -#define DBG_COM 0 /* Trace command call */ -#define DBG_QUEUE 0 /* Trace command queueing. */ -#define DBG_INTR 0 /* Trace interrupt service routine. */ -#define DBG_INTR2 0 /* Trace interrupt service routine. */ -#define DBG_PROC 0 /* Debug proc-fs related statistics */ +#define DEBUG_EATA 1 /* Enable debug code. */ +#define DPT_DEBUG 0 /* Bobs special */ +#define DBG_DELAY 0 /* Build in delays so debug messages can be + * be read before they vanish of the top of + * the screen! + */ +#define DBG_PROBE 0 /* Debug probe routines. */ +#define DBG_ISA 0 /* Trace ISA routines */ +#define DBG_EISA 0 /* Trace EISA routines */ +#define DBG_PCI 0 /* Trace PCI routines */ +#define DBG_PIO 0 /* Trace get_config_PIO */ +#define DBG_COM 0 /* Trace command call */ +#define DBG_QUEUE 0 /* Trace command queueing. */ +#define DBG_INTR 0 /* Trace interrupt service routine. */ +#define DBG_INTR2 0 /* Trace interrupt service routine. */ +#define DBG_PROC 0 /* Debug proc-fs related statistics */ #define DBG_PROC_WRITE 0 -#define DBG_REGISTER 0 /* */ -#define DBG_ABNORM 1 /* Debug abnormal actions (reset, abort) */ +#define DBG_REGISTER 0 /* */ +#define DBG_ABNORM 1 /* Debug abnormal actions (reset, abort) */ -#if DEBUG_EATA -#define DBG(x, y) if ((x)) {y;} +#if DEBUG_EATA +#define DBG(x, y) if ((x)) {y;} #else #define DBG(x, y) #endif -#endif /* !HOSTS_C */ +static int eata_pio_detect(Scsi_Host_Template *); +static int eata_pio_queue(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *)); +static int eata_pio_abort(Scsi_Cmnd *); +static int eata_pio_host_reset(Scsi_Cmnd *); +static int eata_pio_proc_info(char *, char **, off_t, int, int, int); +static int eata_pio_release(struct Scsi_Host *); + +#define EATA_PIO { \ + proc_info: eata_pio_proc_info, /* procinfo */ \ + name: "EATA (Extended Attachment) PIO driver",\ + detect: eata_pio_detect, \ + release: eata_pio_release, \ + queuecommand: eata_pio_queue, \ + eh_abort_handler: eata_pio_abort, \ + eh_host_reset_handler: eata_pio_host_reset, \ + use_clustering: ENABLE_CLUSTERING \ +} -int eata_pio_detect(Scsi_Host_Template *); -const char *eata_pio_info(struct Scsi_Host *); -int eata_pio_command(Scsi_Cmnd *); -int eata_pio_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); -int eata_pio_abort(Scsi_Cmnd *); -int eata_pio_reset(Scsi_Cmnd *, unsigned int); -int eata_pio_proc_info(char *, char **, off_t, int, int, int); -#ifdef MODULE -int eata_pio_release(struct Scsi_Host *); -#else -#define eata_pio_release NULL -#endif - - -#define EATA_PIO { \ - proc_info: eata_pio_proc_info, /* procinfo */ \ - name: "EATA (Extended Attachment) PIO driver", \ - detect: eata_pio_detect, \ - release: eata_pio_release, \ - queuecommand: eata_pio_queue, \ - abort: eata_pio_abort, \ - reset: eata_pio_reset, \ - unchecked_isa_dma: 1, /* True if ISA */ \ - use_clustering: ENABLE_CLUSTERING } - -#endif /* _EATA_PIO_H */ - -/* - * Overrides for Emacs so that we almost 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-indent-level: 4 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -4 - * c-argdecl-indent: 4 - * c-label-offset: -4 - * c-continued-statement-offset: 4 - * c-continued-brace-offset: 0 - * tab-width: 8 - * End: - */ +#endif /* _EATA_PIO_H */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/scsi/fd_mcs.c linux.2.5.45-ac1/drivers/scsi/fd_mcs.c --- linux.2.5.45/drivers/scsi/fd_mcs.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.45-ac1/drivers/scsi/fd_mcs.c 2002-11-03 00:03:24.000000000 +0000 @@ -1325,118 +1325,115 @@ return FAILED; } -static int fd_mcs_device_reset(Scsi_Cmnd * SCpnt) { - return FAILED; - } +static int fd_mcs_device_reset(Scsi_Cmnd * SCpnt) +{ + return FAILED; +} - static int fd_mcs_bus_reset(Scsi_Cmnd * SCpnt) { - struct Scsi_Host *shpnt = SCpnt->host; - unsigned long flags; +static int fd_mcs_bus_reset(Scsi_Cmnd * SCpnt) { + struct Scsi_Host *shpnt = SCpnt->host; #if DEBUG_RESET - static int called_once = 0; + static int called_once = 0; #endif #if ERRORS_ONLY - if (SCpnt) - printk("fd_mcs: SCSI Bus Reset\n"); + if (SCpnt) + printk("fd_mcs: SCSI Bus Reset\n"); #endif #if DEBUG_RESET - if (called_once) - fd_mcs_print_info(current_SC); - called_once = 1; + if (called_once) + fd_mcs_print_info(current_SC); + called_once = 1; #endif - spin_lock_irqsave(shpnt->host_lock, flags); - - 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); - - /* Unless this is the very first call (i.e., SCPnt == NULL), everything - is probably hosed at this point. We will, however, try to keep - things going by informing the high-level code that we need help. */ - - spin_unlock_irqrestore(shpnt->host_lock, flags); + 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); + + /* Unless this is the very first call (i.e., SCPnt == NULL), everything + is probably hosed at this point. We will, however, try to keep + things going by informing the high-level code that we need help. */ return SUCCESS; - } +} #include - static int fd_mcs_biosparam(Scsi_Disk * disk, struct block_device *bdev, - sector_t capacity, int *info_array) { - unsigned char buf[512 + sizeof(int) * 2]; - int size = capacity; - int *sizes = (int *) buf; - unsigned char *data = (unsigned char *) (sizes + 2); - unsigned char do_read[] = { READ_6, 0, 0, 0, 1, 0 }; - int retcode; - - /* BIOS >= 3.4 for MCA cards */ - /* This algorithm was provided by Future Domain (much thanks!). */ - - sizes[0] = 0; /* zero bytes out */ - sizes[1] = 512; /* one sector in */ - memcpy(data, do_read, sizeof(do_read)); - retcode = kernel_scsi_ioctl(disk->device, SCSI_IOCTL_SEND_COMMAND, (void *) buf); - 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 */ +static int fd_mcs_biosparam(struct scsi_device * disk, struct block_device *bdev, + sector_t capacity, int *info_array) +{ + unsigned char buf[512 + sizeof(int) * 2]; + int size = capacity; + int *sizes = (int *) buf; + unsigned char *data = (unsigned char *) (sizes + 2); + unsigned char do_read[] = { READ_6, 0, 0, 0, 1, 0 }; + int retcode; + + /* BIOS >= 3.4 for MCA cards */ + /* This algorithm was provided by Future Domain (much thanks!). */ + + sizes[0] = 0; /* zero bytes out */ + sizes[1] = 512; /* one sector in */ + memcpy(data, do_read, sizeof(do_read)); + retcode = kernel_scsi_ioctl(disk, SCSI_IOCTL_SEND_COMMAND, (void *) buf); + 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 { - - /* 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 */ - } + 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]); + } + /* For both methods, compute the cylinders */ + info_array[2] = (unsigned int) size / (info_array[0] * info_array[1]); + return 0; +} /* Eventually this will go into an include file, but this will be later */ static Scsi_Host_Template driver_template = FD_MCS; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/scsi/fd_mcs.h linux.2.5.45-ac1/drivers/scsi/fd_mcs.h --- linux.2.5.45/drivers/scsi/fd_mcs.h 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.45-ac1/drivers/scsi/fd_mcs.h 2002-11-03 00:00:41.000000000 +0000 @@ -30,7 +30,7 @@ static int fd_mcs_device_reset(Scsi_Cmnd *); static int fd_mcs_host_reset(Scsi_Cmnd *); static int fd_mcs_queue(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *)); -static int fd_mcs_biosparam(Disk *, struct block_device *, +static int fd_mcs_biosparam(struct scsi_device *, struct block_device *, sector_t, int *); static int fd_mcs_proc_info(char *, char **, off_t, int, int, int); static const char *fd_mcs_info(struct Scsi_Host *); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/scsi/g_NCR5380.h linux.2.5.45-ac1/drivers/scsi/g_NCR5380.h --- linux.2.5.45/drivers/scsi/g_NCR5380.h 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.45-ac1/drivers/scsi/g_NCR5380.h 2002-11-03 00:14:55.000000000 +0000 @@ -54,7 +54,7 @@ static int notyet_generic_proc_info (char *buffer ,char **start, off_t offset, int length, int hostno, int inout); static const char* generic_NCR5380_info(struct Scsi_Host *); -static int generic_NCR5380_biosparam(Disk *, struct block_device *, sector_t, int *); +static int generic_NCR5380_biosparam(struct scsi_device *, struct block_device *, sector_t, int *); static int generic_NCR5380_proc_info(char* buffer, char** start, off_t offset, int length, int hostno, int inout); #ifndef CMD_PER_LUN diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/scsi/i60uscsi.c linux.2.5.45-ac1/drivers/scsi/i60uscsi.c --- linux.2.5.45/drivers/scsi/i60uscsi.c 2002-10-31 14:57:11.000000000 +0000 +++ linux.2.5.45-ac1/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.45/drivers/scsi/ibmmca.c linux.2.5.45-ac1/drivers/scsi/ibmmca.c --- linux.2.5.45/drivers/scsi/ibmmca.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.45-ac1/drivers/scsi/ibmmca.c 2002-11-03 01:05:01.000000000 +0000 @@ -8,13 +8,19 @@ the commandline arguments and the history of its development. See the WWW-page: http://www.uni-mainz.de/~langm000/linux.html for latest updates, info and ADF-files for adapters supported by this driver. -*/ + + Alan Cox + Updated for Linux 2.5.45 to use the new error handler, cleaned up the + lock macros and did a few unavoidable locking tweaks, plus one locking + fix in the irq and completion path. + + */ #ifndef LINUX_VERSION_CODE #include #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) -#error "This driver works only with kernel 2.4.0 or higher!" +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,45) +#error "This driver works only with kernel 2.5.45 or higher!" #endif #include #include @@ -39,24 +45,21 @@ #include /* current version of this driver-source: */ -#define IBMMCA_SCSI_DRIVER_VERSION "4.0b" - -#define IBMLOCK(dev) spin_lock_irqsave(dev->host_lock, flags); -#define IBMUNLOCK(dev) spin_unlock_irqrestore(dev->host_lock, flags); +#define IBMMCA_SCSI_DRIVER_VERSION "4.0b-ac" /* driver configuration */ -#define IM_MAX_HOSTS 8 /* maximum number of host adapters */ -#define IM_RESET_DELAY 60 /* seconds allowed for a reset */ +#define IM_MAX_HOSTS 8 /* maximum number of host adapters */ +#define IM_RESET_DELAY 60 /* seconds allowed for a reset */ /* driver debugging - #undef all for normal operation */ /* if defined: count interrupts and ignore this special one: */ -#undef IM_DEBUG_TIMEOUT //50 +#undef IM_DEBUG_TIMEOUT //50 #define TIMEOUT_PUN 0 #define TIMEOUT_LUN 0 /* verbose interrupt: */ -#undef IM_DEBUG_INT +#undef IM_DEBUG_INT /* verbose queuecommand: */ -#undef IM_DEBUG_CMD +#undef IM_DEBUG_CMD /* verbose queucommand for specific SCSI-device type: */ #undef IM_DEBUG_CMD_SPEC_DEV /* verbose device probing */ @@ -66,11 +69,11 @@ #define IM_DEBUG_CMD_DEVICE TYPE_TAPE /* relative addresses of hardware registers on a subsystem */ -#define IM_CMD_REG(hi) (hosts[(hi)]->io_port) /*Command Interface, (4 bytes long) */ -#define IM_ATTN_REG(hi) (hosts[(hi)]->io_port+4) /*Attention (1 byte) */ -#define IM_CTR_REG(hi) (hosts[(hi)]->io_port+5) /*Basic Control (1 byte) */ -#define IM_INTR_REG(hi) (hosts[(hi)]->io_port+6) /*Interrupt Status (1 byte, r/o) */ -#define IM_STAT_REG(hi) (hosts[(hi)]->io_port+7) /*Basic Status (1 byte, read only) */ +#define IM_CMD_REG(hi) (hosts[(hi)]->io_port) /*Command Interface, (4 bytes long) */ +#define IM_ATTN_REG(hi) (hosts[(hi)]->io_port+4) /*Attention (1 byte) */ +#define IM_CTR_REG(hi) (hosts[(hi)]->io_port+5) /*Basic Control (1 byte) */ +#define IM_INTR_REG(hi) (hosts[(hi)]->io_port+6) /*Interrupt Status (1 byte, r/o) */ +#define IM_STAT_REG(hi) (hosts[(hi)]->io_port+7) /*Basic Status (1 byte, read only) */ /* basic I/O-port of first adapter */ #define IM_IO_PORT 0x3540 @@ -116,53 +119,53 @@ /*SCB (Subsystem Control Block) structure */ struct im_scb { - unsigned short command; /*command word (read, etc.) */ - unsigned short enable; /*enable word, modifies cmd */ - union { - unsigned long log_blk_adr; /*block address on SCSI device */ - unsigned char scsi_cmd_length; /*6,10,12, for other scsi cmd */ - } u1; - unsigned long sys_buf_adr; /*physical system memory adr */ - unsigned long sys_buf_length; /*size of sys mem buffer */ - unsigned long tsb_adr; /*Termination Status Block adr */ - unsigned long scb_chain_adr; /*optional SCB chain address */ - union { - struct { - unsigned short count; /*block count, on SCSI device */ - unsigned short length; /*block length, on SCSI device */ - } blk; - unsigned char scsi_command[12]; /*other scsi command */ - } u2; + unsigned short command; /*command word (read, etc.) */ + unsigned short enable; /*enable word, modifies cmd */ + union { + unsigned long log_blk_adr; /*block address on SCSI device */ + unsigned char scsi_cmd_length; /*6,10,12, for other scsi cmd */ + } u1; + unsigned long sys_buf_adr; /*physical system memory adr */ + unsigned long sys_buf_length; /*size of sys mem buffer */ + unsigned long tsb_adr; /*Termination Status Block adr */ + unsigned long scb_chain_adr; /*optional SCB chain address */ + union { + struct { + unsigned short count; /*block count, on SCSI device */ + unsigned short length; /*block length, on SCSI device */ + } blk; + unsigned char scsi_command[12]; /*other scsi command */ + } u2; }; /*structure scatter-gather element (for list of system memory areas) */ struct im_sge { - void *address; - unsigned long byte_length; + void *address; + unsigned long byte_length; }; /*structure returned by a get_pos_info command: */ struct im_pos_info { - unsigned short pos_id; /* adapter id */ - unsigned char pos_3a; /* pos 3 (if pos 6 = 0) */ - unsigned char pos_2; /* pos 2 */ - unsigned char int_level; /* interrupt level IRQ 11 or 14 */ - unsigned char pos_4a; /* pos 4 (if pos 6 = 0) */ - unsigned short connector_size; /* MCA connector size: 16 or 32 Bit */ - unsigned char num_luns; /* number of supported luns per device */ - unsigned char num_puns; /* number of supported puns */ - unsigned char pacing_factor; /* pacing factor */ - unsigned char num_ldns; /* number of ldns available */ - unsigned char eoi_off; /* time EOI and interrupt inactive */ - unsigned char max_busy; /* time between reset and busy on */ - unsigned short cache_stat; /* ldn cachestat. Bit=1 = not cached */ - unsigned short retry_stat; /* retry status of ldns. Bit=1=disabled */ - unsigned char pos_4b; /* pos 4 (if pos 6 = 1) */ - unsigned char pos_3b; /* pos 3 (if pos 6 = 1) */ - unsigned char pos_6; /* pos 6 */ - unsigned char pos_5; /* pos 5 */ - unsigned short max_overlap; /* maximum overlapping requests */ - unsigned short num_bus; /* number of SCSI-busses */ + unsigned short pos_id; /* adapter id */ + unsigned char pos_3a; /* pos 3 (if pos 6 = 0) */ + unsigned char pos_2; /* pos 2 */ + unsigned char int_level; /* interrupt level IRQ 11 or 14 */ + unsigned char pos_4a; /* pos 4 (if pos 6 = 0) */ + unsigned short connector_size; /* MCA connector size: 16 or 32 Bit */ + unsigned char num_luns; /* number of supported luns per device */ + unsigned char num_puns; /* number of supported puns */ + unsigned char pacing_factor; /* pacing factor */ + unsigned char num_ldns; /* number of ldns available */ + unsigned char eoi_off; /* time EOI and interrupt inactive */ + unsigned char max_busy; /* time between reset and busy on */ + unsigned short cache_stat; /* ldn cachestat. Bit=1 = not cached */ + unsigned short retry_stat; /* retry status of ldns. Bit=1=disabled */ + unsigned char pos_4b; /* pos 4 (if pos 6 = 1) */ + unsigned char pos_3b; /* pos 3 (if pos 6 = 1) */ + unsigned char pos_6; /* pos 6 */ + unsigned char pos_5; /* pos 5 */ + unsigned short max_overlap; /* maximum overlapping requests */ + unsigned short num_bus; /* number of SCSI-busses */ }; /*values for SCB command word */ @@ -179,11 +182,11 @@ #define IM_OTHER_SCSI_CMD_CMD 0x241f /* unused, but supported, SCB commands */ -#define IM_GET_COMMAND_COMPLETE_STATUS_CMD 0x1c07 /* command status */ -#define IM_GET_POS_INFO_CMD 0x1c0a /* returns neat stuff */ -#define IM_READ_PREFETCH_CMD 0x1c31 /* caching controller only */ -#define IM_FOMAT_UNIT_CMD 0x1c16 /* format unit */ -#define IM_REASSIGN_BLOCK_CMD 0x1c18 /* in case of error */ +#define IM_GET_COMMAND_COMPLETE_STATUS_CMD 0x1c07 /* command status */ +#define IM_GET_POS_INFO_CMD 0x1c0a /* returns neat stuff */ +#define IM_READ_PREFETCH_CMD 0x1c31 /* caching controller only */ +#define IM_FOMAT_UNIT_CMD 0x1c16 /* format unit */ +#define IM_REASSIGN_BLOCK_CMD 0x1c18 /* in case of error */ /*values to set bits in the enable word of SCB */ #define IM_READ_CONTROL 0x8000 @@ -196,19 +199,19 @@ /*TSB (Termination Status Block) structure */ struct im_tsb { - unsigned short end_status; - unsigned short reserved1; - unsigned long residual_byte_count; - unsigned long sg_list_element_adr; - unsigned short status_length; - unsigned char dev_status; - unsigned char cmd_status; - unsigned char dev_error; - unsigned char cmd_error; - unsigned short reserved2; - unsigned short reserved3; - unsigned short low_of_last_scb_adr; - unsigned short high_of_last_scb_adr; + unsigned short end_status; + unsigned short reserved1; + unsigned long residual_byte_count; + unsigned long sg_list_element_adr; + unsigned short status_length; + unsigned char dev_status; + unsigned char cmd_status; + unsigned char dev_error; + unsigned char cmd_error; + unsigned short reserved2; + unsigned short reserved3; + unsigned short low_of_last_scb_adr; + unsigned short high_of_last_scb_adr; }; /*subsystem uses interrupt request level 14 */ @@ -247,7 +250,7 @@ /* for probing on feature-command: */ static unsigned int global_command_error_excuse = 0; /* global setting by command line for adapter_speed */ -static int global_adapter_speed = 0; /* full speed by default */ +static int global_adapter_speed = 0; /* full speed by default */ /* Panel / LED on, do it right for F/W addressin, too. adisplay will * just ignore ids>7, as the panel has only 7 digits available */ @@ -269,8 +272,8 @@ /*list of supported subsystems */ struct subsys_list_struct { - unsigned short mca_id; - char *description; + unsigned short mca_id; + char *description; }; /* types of different supported hardware that goes to hostdata special */ @@ -286,11 +289,11 @@ /* List of possible IBM-SCSI-adapters */ struct subsys_list_struct subsys_list[] = { - {0x8efc,"IBM SCSI-2 F/W Adapter"}, /* special = 0 */ - {0x8efd,"IBM 7568 Industrial Computer SCSI Adapter w/Cache"}, /* special = 1 */ - {0x8ef8,"IBM Expansion Unit SCSI Controller"},/* special = 2 */ - {0x8eff,"IBM SCSI Adapter w/Cache"}, /* special = 3 */ - {0x8efe,"IBM SCSI Adapter"}, /* special = 4 */ + {0x8efc, "IBM SCSI-2 F/W Adapter"}, /* special = 0 */ + {0x8efd, "IBM 7568 Industrial Computer SCSI Adapter w/Cache"}, /* special = 1 */ + {0x8ef8, "IBM Expansion Unit SCSI Controller"}, /* special = 2 */ + {0x8eff, "IBM SCSI Adapter w/Cache"}, /* special = 3 */ + {0x8efe, "IBM SCSI Adapter"}, /* special = 4 */ }; /* Max number of logical devices (can be up from 0 to 14). 15 is the address @@ -299,80 +302,80 @@ /*local data for a logical device */ struct logical_device { - struct im_scb scb; /* SCSI-subsystem-control-block structure */ - struct im_tsb tsb; /* SCSI command complete status block structure */ - struct im_sge sge[16]; /* scatter gather list structure */ - unsigned char buf[256]; /* SCSI command return data buffer */ - Scsi_Cmnd *cmd; /* SCSI-command that is currently in progress */ - int device_type; /* type of the SCSI-device. See include/scsi/scsi.h - for interpretation of the possible values */ - int block_length; /* blocksize of a particular logical SCSI-device */ - int cache_flag; /* 1 if this is uncached, 0 if cache is present for ldn */ - int retry_flag; /* 1 if adapter retry is disabled, 0 if enabled */ + struct im_scb scb; /* SCSI-subsystem-control-block structure */ + struct im_tsb tsb; /* SCSI command complete status block structure */ + struct im_sge sge[16]; /* scatter gather list structure */ + unsigned char buf[256]; /* SCSI command return data buffer */ + Scsi_Cmnd *cmd; /* SCSI-command that is currently in progress */ + int device_type; /* type of the SCSI-device. See include/scsi/scsi.h + for interpretation of the possible values */ + int block_length; /* blocksize of a particular logical SCSI-device */ + int cache_flag; /* 1 if this is uncached, 0 if cache is present for ldn */ + int retry_flag; /* 1 if adapter retry is disabled, 0 if enabled */ }; /* statistics of the driver during operations (for proc_info) */ struct Driver_Statistics { - /* SCSI statistics on the adapter */ - int ldn_access[MAX_LOG_DEV+1]; /* total accesses on a ldn */ - int ldn_read_access[MAX_LOG_DEV+1]; /* total read-access on a ldn */ - int ldn_write_access[MAX_LOG_DEV+1]; /* total write-access on a ldn */ - int ldn_inquiry_access[MAX_LOG_DEV+1]; /* total inquiries on a ldn */ - int ldn_modeselect_access[MAX_LOG_DEV+1]; /* total mode selects on ldn */ - int scbs; /* short SCBs queued */ - int long_scbs; /* long SCBs queued */ - int total_accesses; /* total accesses on all ldns */ - int total_interrupts; /* total interrupts (should be - same as total_accesses) */ - int total_errors; /* command completed with error */ - /* dynamical assignment statistics */ - int total_scsi_devices; /* number of physical pun,lun */ - int dyn_flag; /* flag showing dynamical mode */ - int dynamical_assignments; /* number of remappings of ldns */ - int ldn_assignments[MAX_LOG_DEV+1]; /* number of remappings of each - ldn */ + /* SCSI statistics on the adapter */ + int ldn_access[MAX_LOG_DEV + 1]; /* total accesses on a ldn */ + int ldn_read_access[MAX_LOG_DEV + 1]; /* total read-access on a ldn */ + int ldn_write_access[MAX_LOG_DEV + 1]; /* total write-access on a ldn */ + int ldn_inquiry_access[MAX_LOG_DEV + 1]; /* total inquiries on a ldn */ + int ldn_modeselect_access[MAX_LOG_DEV + 1]; /* total mode selects on ldn */ + int scbs; /* short SCBs queued */ + int long_scbs; /* long SCBs queued */ + int total_accesses; /* total accesses on all ldns */ + int total_interrupts; /* total interrupts (should be + same as total_accesses) */ + int total_errors; /* command completed with error */ + /* dynamical assignment statistics */ + int total_scsi_devices; /* number of physical pun,lun */ + int dyn_flag; /* flag showing dynamical mode */ + int dynamical_assignments; /* number of remappings of ldns */ + int ldn_assignments[MAX_LOG_DEV + 1]; /* number of remappings of each + ldn */ }; /* data structure for each host adapter */ struct ibmmca_hostdata { - /* array of logical devices: */ - struct logical_device _ld[MAX_LOG_DEV+1]; - /* array to convert (pun, lun) into logical device number: */ - unsigned char _get_ldn[16][8]; - /*array that contains the information about the physical SCSI-devices - attached to this host adapter: */ - unsigned char _get_scsi[16][8]; - /* used only when checking logical devices: */ - int _local_checking_phase_flag; - /* report received interrupt: */ - int _got_interrupt; - /* report termination-status of SCSI-command: */ - int _stat_result; - /* reset status (used only when doing reset): */ - int _reset_status; - /* code of the last SCSI command (needed for panic info): */ - int _last_scsi_command[MAX_LOG_DEV+1]; - /* identifier of the last SCSI-command type */ - int _last_scsi_type[MAX_LOG_DEV+1]; - /* last blockcount */ - int _last_scsi_blockcount[MAX_LOG_DEV+1]; - /* last locgical block address */ - unsigned long _last_scsi_logical_block[MAX_LOG_DEV+1]; - /* Counter that points on the next reassignable ldn for dynamical - remapping. The default value is 7, that is the first reassignable - number in the list at boottime: */ - int _next_ldn; - /* Statistics-structure for this IBM-SCSI-host: */ - struct Driver_Statistics _IBM_DS; - /* This hostadapters pos-registers pos2 until pos6 */ - unsigned int _pos[8]; - /* assign a special variable, that contains dedicated info about the - adaptertype */ - int _special; - /* connector size on the MCA bus */ - int _connector_size; - /* synchronous SCSI transfer rate bitpattern */ - int _adapter_speed; + /* array of logical devices: */ + struct logical_device _ld[MAX_LOG_DEV + 1]; + /* array to convert (pun, lun) into logical device number: */ + unsigned char _get_ldn[16][8]; + /*array that contains the information about the physical SCSI-devices + attached to this host adapter: */ + unsigned char _get_scsi[16][8]; + /* used only when checking logical devices: */ + int _local_checking_phase_flag; + /* report received interrupt: */ + int _got_interrupt; + /* report termination-status of SCSI-command: */ + int _stat_result; + /* reset status (used only when doing reset): */ + int _reset_status; + /* code of the last SCSI command (needed for panic info): */ + int _last_scsi_command[MAX_LOG_DEV + 1]; + /* identifier of the last SCSI-command type */ + int _last_scsi_type[MAX_LOG_DEV + 1]; + /* last blockcount */ + int _last_scsi_blockcount[MAX_LOG_DEV + 1]; + /* last locgical block address */ + unsigned long _last_scsi_logical_block[MAX_LOG_DEV + 1]; + /* Counter that points on the next reassignable ldn for dynamical + remapping. The default value is 7, that is the first reassignable + number in the list at boottime: */ + int _next_ldn; + /* Statistics-structure for this IBM-SCSI-host: */ + struct Driver_Statistics _IBM_DS; + /* This hostadapters pos-registers pos2 until pos6 */ + unsigned int _pos[8]; + /* assign a special variable, that contains dedicated info about the + adaptertype */ + int _special; + /* connector size on the MCA bus */ + int _connector_size; + /* synchronous SCSI transfer rate bitpattern */ + int _adapter_speed; }; /* macros to access host data structure */ @@ -457,9 +460,10 @@ /* host information */ static int found = 0; -static struct Scsi_Host *hosts[IM_MAX_HOSTS+1] = { - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; -static unsigned int pos[8]; /* whole pos register-line for diagnosis */ +static struct Scsi_Host *hosts[IM_MAX_HOSTS + 1] = { + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; +static unsigned int pos[8]; /* whole pos register-line for diagnosis */ /* Taking into account the additions, made by ZP Gu. * This selects now the preset value from the configfile and * offers the 'normal' commandline option to be accepted */ @@ -469,12 +473,11 @@ static char ibm_ansi_order = 0; #endif -static void interrupt_handler (int, void *, struct pt_regs *); -static void issue_cmd (int, unsigned long, unsigned char); -static void internal_done (Scsi_Cmnd * cmd); -static void check_devices (int, int); -static int immediate_assign(int, unsigned int, unsigned int, unsigned int, - unsigned int); +static void interrupt_handler(int, void *, struct pt_regs *); +static void issue_cmd(int, unsigned long, unsigned char); +static void internal_done(Scsi_Cmnd * cmd); +static void check_devices(int, int); +static int immediate_assign(int, unsigned int, unsigned int, unsigned int, unsigned int); static int immediate_feature(int, unsigned int, unsigned int); #ifdef CONFIG_IBMMCA_SCSI_DEV_RESET static int immediate_reset(int, unsigned int); @@ -487,2083 +490,1994 @@ static char *ibmrate(unsigned int, int); static int probe_display(int); static int probe_bus_mode(int); -static int device_exists (int, int, int *, int *); -static struct Scsi_Host *ibmmca_register(Scsi_Host_Template *, - int, int, int, char *); +static int device_exists(int, int, int *, int *); +static struct Scsi_Host *ibmmca_register(Scsi_Host_Template *, int, int, int, char *); static int option_setup(char *); /* local functions needed for proc_info */ static int ldn_access_load(int, int); static int ldn_access_total_read_write(int); -static void interrupt_handler (int irq, void *dev_id, struct pt_regs *regs) +static void interrupt_handler(int irq, void *dev_id, struct pt_regs *regs) { - int host_index, ihost_index; - unsigned int intr_reg; - unsigned int cmd_result; - unsigned int ldn; - unsigned long flags; - Scsi_Cmnd *cmd; - int lastSCSI; - struct Scsi_Host *dev = dev_id; - - IBMLOCK(dev) - /* search for one adapter-response on shared interrupt */ - for (host_index=0; - hosts[host_index] && !(inb(IM_STAT_REG(host_index)) & IM_INTR_REQUEST); - host_index++); - /* return if some other device on this IRQ caused the interrupt */ - if (!hosts[host_index]) { - IBMUNLOCK(dev) - return; - } - - /* the reset-function already did all the job, even ints got - renabled on the subsystem, so just return */ - if ((reset_status(host_index) == IM_RESET_NOT_IN_PROGRESS_NO_INT)|| - (reset_status(host_index) == IM_RESET_FINISHED_OK_NO_INT)) { - reset_status(host_index) = IM_RESET_NOT_IN_PROGRESS; - IBMUNLOCK(dev) - return; - } - - /*must wait for attention reg not busy, then send EOI to subsystem */ - while (1) { - if (!(inb (IM_STAT_REG(host_index)) & IM_BUSY)) break; - IBMUNLOCK(dev) /* cycle interrupt */ - cpu_relax(); - IBMLOCK(dev) - } - ihost_index=host_index; - /*get command result and logical device */ - intr_reg = (unsigned char)(inb (IM_INTR_REG(ihost_index))); - cmd_result = intr_reg & 0xf0; - ldn = intr_reg & 0x0f; - /* get the last_scsi_command here */ - lastSCSI = last_scsi_command(ihost_index)[ldn]; - outb (IM_EOI | ldn, IM_ATTN_REG(ihost_index)); - IBMUNLOCK(dev) - /*these should never happen (hw fails, or a local programming bug) */ - if (!global_command_error_excuse) { - switch (cmd_result) { - /* Prevent from Ooopsing on error to show the real reason */ - case IM_ADAPTER_HW_FAILURE: - case IM_SOFTWARE_SEQUENCING_ERROR: - case IM_CMD_ERROR: - printk("\nIBM MCA SCSI: Fatal Subsystem ERROR!\n"); - printk(" Last cmd=0x%x, ena=%x, len=",lastSCSI, - ld(ihost_index)[ldn].scb.enable); - if (ld(ihost_index)[ldn].cmd) - printk("%ld/%ld,",(long)(ld(ihost_index)[ldn].cmd->request_bufflen), - (long)(ld(ihost_index)[ldn].scb.sys_buf_length)); - else - printk("none,"); - if (ld(ihost_index)[ldn].cmd) - printk("Blocksize=%d",ld(ihost_index)[ldn].scb.u2.blk.length); - else - printk("Blocksize=none"); - printk(", host=0x%x, ldn=0x%x\n",ihost_index, ldn); - if (ld(ihost_index)[ldn].cmd) { - printk("Blockcount=%d/%d\n",last_scsi_blockcount(ihost_index)[ldn], - ld(ihost_index)[ldn].scb.u2.blk.count); - printk("Logical block=%lx/%lx\n",last_scsi_logical_block(ihost_index)[ldn], - ld(ihost_index)[ldn].scb.u1.log_blk_adr); - } - printk("Reason given: %s\n", - (cmd_result==IM_ADAPTER_HW_FAILURE) ? "HARDWARE FAILURE" : - (cmd_result==IM_SOFTWARE_SEQUENCING_ERROR) ? "SOFTWARE SEQUENCING ERROR" : - (cmd_result==IM_CMD_ERROR) ? "COMMAND ERROR" : "UNKNOWN"); - /* if errors appear, enter this section to give detailed info */ - printk("IBM MCA SCSI: Subsystem Error-Status follows:\n"); - printk(" Command Type................: %x\n", - last_scsi_type(ihost_index)[ldn]); - printk(" Attention Register..........: %x\n", - inb (IM_ATTN_REG(ihost_index))); - printk(" Basic Control Register......: %x\n", - inb (IM_CTR_REG(ihost_index))); - printk(" Interrupt Status Register...: %x\n", - intr_reg); - printk(" Basic Status Register.......: %x\n", - inb (IM_STAT_REG(ihost_index))); - if ((last_scsi_type(ihost_index)[ldn]==IM_SCB)|| - (last_scsi_type(ihost_index)[ldn]==IM_LONG_SCB)) { - printk(" SCB-Command.................: %x\n", - ld(ihost_index)[ldn].scb.command); - printk(" SCB-Enable..................: %x\n", - ld(ihost_index)[ldn].scb.enable); - printk(" SCB-logical block address...: %lx\n", - ld(ihost_index)[ldn].scb.u1.log_blk_adr); - printk(" SCB-system buffer address...: %lx\n", - ld(ihost_index)[ldn].scb.sys_buf_adr); - printk(" SCB-system buffer length....: %lx\n", - ld(ihost_index)[ldn].scb.sys_buf_length); - printk(" SCB-tsb address.............: %lx\n", - ld(ihost_index)[ldn].scb.tsb_adr); - printk(" SCB-Chain address...........: %lx\n", - ld(ihost_index)[ldn].scb.scb_chain_adr); - printk(" SCB-block count.............: %x\n", - ld(ihost_index)[ldn].scb.u2.blk.count); - printk(" SCB-block length............: %x\n", - ld(ihost_index)[ldn].scb.u2.blk.length); - } - printk(" Send this report to the maintainer.\n"); - panic("IBM MCA SCSI: Fatal errormessage from the subsystem (0x%X,0x%X)!\n", - lastSCSI,cmd_result); - break; - } - } else { - /* The command error handling is made silent, but we tell the - * calling function, that there is a reported error from the - * adapter. */ - switch (cmd_result) { - case IM_ADAPTER_HW_FAILURE: case IM_SOFTWARE_SEQUENCING_ERROR: - case IM_CMD_ERROR: global_command_error_excuse = CMD_FAIL; break; - default: global_command_error_excuse = 0; break; - } - } - /* if no panic appeared, increase the interrupt-counter */ - IBM_DS(ihost_index).total_interrupts++; - /*only for local checking phase */ - if (local_checking_phase_flag(ihost_index)) { - stat_result(ihost_index) = cmd_result; - got_interrupt(ihost_index) = 1; - reset_status(ihost_index) = IM_RESET_FINISHED_OK; - last_scsi_command(ihost_index)[ldn] = NO_SCSI; - return; - } - /* handling of commands coming from upper level of scsi driver */ - if (last_scsi_type(ihost_index)[ldn] == IM_IMM_CMD) { - /* verify ldn, and may handle rare reset immediate command */ - if ((reset_status(ihost_index) == IM_RESET_IN_PROGRESS)&& - (last_scsi_command(ihost_index)[ldn] == IM_RESET_IMM_CMD)) { - if (cmd_result == IM_CMD_COMPLETED_WITH_FAILURE) { - disk_rw_in_progress = 0; - PS2_DISK_LED_OFF (); - reset_status(ihost_index) = IM_RESET_FINISHED_FAIL; - } else { - /*reset disk led counter, turn off disk led */ - disk_rw_in_progress = 0; - PS2_DISK_LED_OFF (); - reset_status(ihost_index) = IM_RESET_FINISHED_OK; - } - stat_result(ihost_index) = cmd_result; - last_scsi_command(ihost_index)[ldn] = NO_SCSI; - last_scsi_type(ihost_index)[ldn] = 0; - return; - } else if (last_scsi_command(ihost_index)[ldn] == IM_ABORT_IMM_CMD) { - /* react on SCSI abort command */ + int host_index, ihost_index; + unsigned int intr_reg; + unsigned int cmd_result; + unsigned int ldn; + Scsi_Cmnd *cmd; + int lastSCSI; + struct Scsi_Host *dev = dev_id; + + spin_lock(dev->host_lock); + /* search for one adapter-response on shared interrupt */ + for (host_index = 0; hosts[host_index] && !(inb(IM_STAT_REG(host_index)) & IM_INTR_REQUEST); host_index++); + /* return if some other device on this IRQ caused the interrupt */ + if (!hosts[host_index]) { + spin_unlock(dev->host_lock); + return; + } + + /* the reset-function already did all the job, even ints got + renabled on the subsystem, so just return */ + if ((reset_status(host_index) == IM_RESET_NOT_IN_PROGRESS_NO_INT) || (reset_status(host_index) == IM_RESET_FINISHED_OK_NO_INT)) { + reset_status(host_index) = IM_RESET_NOT_IN_PROGRESS; + spin_unlock(dev->host_lock); + return; + } + + /*must wait for attention reg not busy, then send EOI to subsystem */ + while (1) { + if (!(inb(IM_STAT_REG(host_index)) & IM_BUSY)) + break; + cpu_relax(); + } + ihost_index = host_index; + /*get command result and logical device */ + intr_reg = (unsigned char) (inb(IM_INTR_REG(ihost_index))); + cmd_result = intr_reg & 0xf0; + ldn = intr_reg & 0x0f; + /* get the last_scsi_command here */ + lastSCSI = last_scsi_command(ihost_index)[ldn]; + outb(IM_EOI | ldn, IM_ATTN_REG(ihost_index)); + + /*these should never happen (hw fails, or a local programming bug) */ + if (!global_command_error_excuse) { + switch (cmd_result) { + /* Prevent from Ooopsing on error to show the real reason */ + case IM_ADAPTER_HW_FAILURE: + case IM_SOFTWARE_SEQUENCING_ERROR: + case IM_CMD_ERROR: + printk(KERN_ERR "IBM MCA SCSI: Fatal Subsystem ERROR!\n"); + printk(KERN_ERR " Last cmd=0x%x, ena=%x, len=", lastSCSI, ld(ihost_index)[ldn].scb.enable); + if (ld(ihost_index)[ldn].cmd) + printk("%ld/%ld,", (long) (ld(ihost_index)[ldn].cmd->request_bufflen), (long) (ld(ihost_index)[ldn].scb.sys_buf_length)); + else + printk("none,"); + if (ld(ihost_index)[ldn].cmd) + printk("Blocksize=%d", ld(ihost_index)[ldn].scb.u2.blk.length); + else + printk("Blocksize=none"); + printk(", host=0x%x, ldn=0x%x\n", ihost_index, ldn); + if (ld(ihost_index)[ldn].cmd) { + printk(KERN_ERR "Blockcount=%d/%d\n", last_scsi_blockcount(ihost_index)[ldn], ld(ihost_index)[ldn].scb.u2.blk.count); + printk(KERN_ERR "Logical block=%lx/%lx\n", last_scsi_logical_block(ihost_index)[ldn], ld(ihost_index)[ldn].scb.u1.log_blk_adr); + } + printk(KERN_ERR "Reason given: %s\n", (cmd_result == IM_ADAPTER_HW_FAILURE) ? "HARDWARE FAILURE" : (cmd_result == IM_SOFTWARE_SEQUENCING_ERROR) ? "SOFTWARE SEQUENCING ERROR" : (cmd_result == IM_CMD_ERROR) ? "COMMAND ERROR" : "UNKNOWN"); + /* if errors appear, enter this section to give detailed info */ + printk(KERN_ERR "IBM MCA SCSI: Subsystem Error-Status follows:\n"); + printk(KERN_ERR " Command Type................: %x\n", last_scsi_type(ihost_index)[ldn]); + printk(KERN_ERR " Attention Register..........: %x\n", inb(IM_ATTN_REG(ihost_index))); + printk(KERN_ERR " Basic Control Register......: %x\n", inb(IM_CTR_REG(ihost_index))); + printk(KERN_ERR " Interrupt Status Register...: %x\n", intr_reg); + printk(KERN_ERR " Basic Status Register.......: %x\n", inb(IM_STAT_REG(ihost_index))); + if ((last_scsi_type(ihost_index)[ldn] == IM_SCB) || (last_scsi_type(ihost_index)[ldn] == IM_LONG_SCB)) { + printk(KERN_ERR " SCB-Command.................: %x\n", ld(ihost_index)[ldn].scb.command); + printk(KERN_ERR " SCB-Enable..................: %x\n", ld(ihost_index)[ldn].scb.enable); + printk(KERN_ERR " SCB-logical block address...: %lx\n", ld(ihost_index)[ldn].scb.u1.log_blk_adr); + printk(KERN_ERR " SCB-system buffer address...: %lx\n", ld(ihost_index)[ldn].scb.sys_buf_adr); + printk(KERN_ERR " SCB-system buffer length....: %lx\n", ld(ihost_index)[ldn].scb.sys_buf_length); + printk(KERN_ERR " SCB-tsb address.............: %lx\n", ld(ihost_index)[ldn].scb.tsb_adr); + printk(KERN_ERR " SCB-Chain address...........: %lx\n", ld(ihost_index)[ldn].scb.scb_chain_adr); + printk(KERN_ERR " SCB-block count.............: %x\n", ld(ihost_index)[ldn].scb.u2.blk.count); + printk(KERN_ERR " SCB-block length............: %x\n", ld(ihost_index)[ldn].scb.u2.blk.length); + } + printk(KERN_ERR " Send this report to the maintainer.\n"); + panic("IBM MCA SCSI: Fatal error message from the subsystem (0x%X,0x%X)!\n", lastSCSI, cmd_result); + break; + } + } else { + /* The command error handling is made silent, but we tell the + * calling function, that there is a reported error from the + * adapter. */ + switch (cmd_result) { + case IM_ADAPTER_HW_FAILURE: + case IM_SOFTWARE_SEQUENCING_ERROR: + case IM_CMD_ERROR: + global_command_error_excuse = CMD_FAIL; + break; + default: + global_command_error_excuse = 0; + break; + } + } + /* if no panic appeared, increase the interrupt-counter */ + IBM_DS(ihost_index).total_interrupts++; + /*only for local checking phase */ + if (local_checking_phase_flag(ihost_index)) { + stat_result(ihost_index) = cmd_result; + got_interrupt(ihost_index) = 1; + reset_status(ihost_index) = IM_RESET_FINISHED_OK; + last_scsi_command(ihost_index)[ldn] = NO_SCSI; + spin_unlock(dev->host_lock); + return; + } + /* handling of commands coming from upper level of scsi driver */ + if (last_scsi_type(ihost_index)[ldn] == IM_IMM_CMD) { + /* verify ldn, and may handle rare reset immediate command */ + if ((reset_status(ihost_index) == IM_RESET_IN_PROGRESS) && (last_scsi_command(ihost_index)[ldn] == IM_RESET_IMM_CMD)) { + if (cmd_result == IM_CMD_COMPLETED_WITH_FAILURE) { + disk_rw_in_progress = 0; + PS2_DISK_LED_OFF(); + reset_status(ihost_index) = IM_RESET_FINISHED_FAIL; + } else { + /*reset disk led counter, turn off disk led */ + disk_rw_in_progress = 0; + PS2_DISK_LED_OFF(); + reset_status(ihost_index) = IM_RESET_FINISHED_OK; + } + stat_result(ihost_index) = cmd_result; + last_scsi_command(ihost_index)[ldn] = NO_SCSI; + last_scsi_type(ihost_index)[ldn] = 0; + spin_unlock(dev->host_lock); + return; + } else if (last_scsi_command(ihost_index)[ldn] == IM_ABORT_IMM_CMD) { + /* react on SCSI abort command */ #ifdef IM_DEBUG_PROBE - printk("IBM MCA SCSI: Interrupt from SCSI-abort.\n"); + printk("IBM MCA SCSI: Interrupt from SCSI-abort.\n"); #endif - disk_rw_in_progress = 0; - PS2_DISK_LED_OFF(); - cmd = ld(ihost_index)[ldn].cmd; - ld(ihost_index)[ldn].cmd = NULL; - if (cmd_result == IM_CMD_COMPLETED_WITH_FAILURE) - cmd->result = DID_NO_CONNECT << 16; - else - cmd->result = DID_ABORT << 16; - stat_result(ihost_index) = cmd_result; - last_scsi_command(ihost_index)[ldn] = NO_SCSI; - last_scsi_type(ihost_index)[ldn] = 0; - if (cmd->scsi_done) - (cmd->scsi_done)(cmd); /* should be the internal_done */ - return; - } else { - disk_rw_in_progress = 0; - PS2_DISK_LED_OFF (); - reset_status(ihost_index) = IM_RESET_FINISHED_OK; - stat_result(ihost_index) = cmd_result; - last_scsi_command(ihost_index)[ldn] = NO_SCSI; - return; - } - } - last_scsi_command(ihost_index)[ldn] = NO_SCSI; - last_scsi_type(ihost_index)[ldn] = 0; - cmd = ld(ihost_index)[ldn].cmd; - ld(ihost_index)[ldn].cmd = NULL; + disk_rw_in_progress = 0; + PS2_DISK_LED_OFF(); + cmd = ld(ihost_index)[ldn].cmd; + ld(ihost_index)[ldn].cmd = NULL; + if (cmd_result == IM_CMD_COMPLETED_WITH_FAILURE) + cmd->result = DID_NO_CONNECT << 16; + else + cmd->result = DID_ABORT << 16; + stat_result(ihost_index) = cmd_result; + last_scsi_command(ihost_index)[ldn] = NO_SCSI; + last_scsi_type(ihost_index)[ldn] = 0; + if (cmd->scsi_done) + (cmd->scsi_done) (cmd); /* should be the internal_done */ + spin_unlock(dev->host_lock); + return; + } else { + disk_rw_in_progress = 0; + PS2_DISK_LED_OFF(); + reset_status(ihost_index) = IM_RESET_FINISHED_OK; + stat_result(ihost_index) = cmd_result; + last_scsi_command(ihost_index)[ldn] = NO_SCSI; + spin_unlock(dev->host_lock); + return; + } + } + last_scsi_command(ihost_index)[ldn] = NO_SCSI; + last_scsi_type(ihost_index)[ldn] = 0; + cmd = ld(ihost_index)[ldn].cmd; + ld(ihost_index)[ldn].cmd = NULL; #ifdef IM_DEBUG_TIMEOUT - if (cmd) { - if ((cmd->target == TIMEOUT_PUN)&&(cmd->lun == TIMEOUT_LUN)) { - printk("IBM MCA SCSI: Ignoring interrupt from pun=%x, lun=%x.\n", - cmd->target, cmd->lun); - return; - } - } + if (cmd) { + if ((cmd->target == TIMEOUT_PUN) && (cmd->lun == TIMEOUT_LUN)) { + printk("IBM MCA SCSI: Ignoring interrupt from pun=%x, lun=%x.\n", cmd->target, cmd->lun); + return; + } + } #endif - /*if no command structure, just return, else clear cmd */ - if (!cmd) return; + /*if no command structure, just return, else clear cmd */ + if (!cmd) + { + spin_unlock(dev->host_lock); + return; + } #ifdef IM_DEBUG_INT - printk("cmd=%02x ireg=%02x ds=%02x cs=%02x de=%02x ce=%02x\n", - cmd->cmnd[0], intr_reg, - ld(ihost_index)[ldn].tsb.dev_status, - ld(ihost_index)[ldn].tsb.cmd_status, - ld(ihost_index)[ldn].tsb.dev_error, - ld(ihost_index)[ldn].tsb.cmd_error); -#endif - /*if this is end of media read/write, may turn off PS/2 disk led */ - if ((ld(ihost_index)[ldn].device_type!=TYPE_NO_LUN)&& - (ld(ihost_index)[ldn].device_type!=TYPE_NO_DEVICE)) { - /* only access this, if there was a valid device addressed */ - if (--disk_rw_in_progress == 0) PS2_DISK_LED_OFF (); - } - - /* IBM describes the status-mask to be 0x1e, but this is not conform - * with SCSI-definition, I suppose, the reason for it is that IBM - * adapters do not support CMD_TERMINATED, TASK_SET_FULL and - * ACA_ACTIVE as returning statusbyte information. (ML) */ - if (cmd_result == IM_CMD_COMPLETED_WITH_FAILURE) { - cmd->result = (unsigned char)(ld(ihost_index)[ldn].tsb.dev_status & 0x1e); - IBM_DS(ihost_index).total_errors++; - } else - cmd->result = 0; - /* write device status into cmd->result, and call done function */ - if (lastSCSI == NO_SCSI) { /* unexpected interrupt :-( */ - cmd->result |= DID_BAD_INTR << 16; - printk("IBM MCA SCSI: WARNING - Interrupt from non-pending SCSI-command!\n"); - } else /* things went right :-) */ - cmd->result |= DID_OK << 16; - if (cmd->scsi_done) (cmd->scsi_done)(cmd); - return; -} - -static void issue_cmd (int host_index, unsigned long cmd_reg, - unsigned char attn_reg) -{ - unsigned long flags; - /* must wait for attention reg not busy */ - while (1) { - IBMLOCK(hosts[host_index]) - if (!(inb(IM_STAT_REG(host_index)) & IM_BUSY)) break; - IBMUNLOCK(hosts[host_index]) - } - /* write registers and enable system interrupts */ - outl (cmd_reg, IM_CMD_REG(host_index)); - outb (attn_reg, IM_ATTN_REG(host_index)); - IBMUNLOCK(hosts[host_index]) - return; + printk("cmd=%02x ireg=%02x ds=%02x cs=%02x de=%02x ce=%02x\n", cmd->cmnd[0], intr_reg, ld(ihost_index)[ldn].tsb.dev_status, ld(ihost_index)[ldn].tsb.cmd_status, ld(ihost_index)[ldn].tsb.dev_error, ld(ihost_index)[ldn].tsb.cmd_error); +#endif + /*if this is end of media read/write, may turn off PS/2 disk led */ + if ((ld(ihost_index)[ldn].device_type != TYPE_NO_LUN) && (ld(ihost_index)[ldn].device_type != TYPE_NO_DEVICE)) { + /* only access this, if there was a valid device addressed */ + if (--disk_rw_in_progress == 0) + PS2_DISK_LED_OFF(); + } + + /* IBM describes the status-mask to be 0x1e, but this is not conform + * with SCSI-definition, I suppose, the reason for it is that IBM + * adapters do not support CMD_TERMINATED, TASK_SET_FULL and + * ACA_ACTIVE as returning statusbyte information. (ML) */ + if (cmd_result == IM_CMD_COMPLETED_WITH_FAILURE) { + cmd->result = (unsigned char) (ld(ihost_index)[ldn].tsb.dev_status & 0x1e); + IBM_DS(ihost_index).total_errors++; + } else + cmd->result = 0; + /* write device status into cmd->result, and call done function */ + if (lastSCSI == NO_SCSI) { /* unexpected interrupt :-( */ + cmd->result |= DID_BAD_INTR << 16; + printk("IBM MCA SCSI: WARNING - Interrupt from non-pending SCSI-command!\n"); + } else /* things went right :-) */ + cmd->result |= DID_OK << 16; + if (cmd->scsi_done) + (cmd->scsi_done) (cmd); + spin_unlock(dev->host_lock); + return; +} + +static void issue_cmd(int host_index, unsigned long cmd_reg, unsigned char attn_reg) +{ + unsigned long flags; + /* must wait for attention reg not busy */ + while (1) { + spin_lock_irqsave(hosts[host_index]->host_lock, flags); + if (!(inb(IM_STAT_REG(host_index)) & IM_BUSY)) + break; + spin_unlock_irqrestore(hosts[host_index]->host_lock, flags); + } + /* write registers and enable system interrupts */ + outl(cmd_reg, IM_CMD_REG(host_index)); + outb(attn_reg, IM_ATTN_REG(host_index)); + spin_unlock_irqrestore(hosts[host_index]->host_lock, flags); } -static void internal_done (Scsi_Cmnd * cmd) +static void internal_done(Scsi_Cmnd * cmd) { - cmd->SCp.Status++; - return; + cmd->SCp.Status++; + return; } /* SCSI-SCB-command for device_inquiry */ static int device_inquiry(int host_index, int ldn) { - int retr; - struct im_scb *scb; - struct im_tsb *tsb; - unsigned char *buf; - - scb = &(ld(host_index)[ldn].scb); - tsb = &(ld(host_index)[ldn].tsb); - buf = (unsigned char *)(&(ld(host_index)[ldn].buf)); - ld(host_index)[ldn].tsb.dev_status = 0; /* prepare statusblock */ - for (retr=0; retr<3; retr++) { - /* fill scb with inquiry command */ - scb->command = IM_DEVICE_INQUIRY_CMD | IM_NO_DISCONNECT; - scb->enable = IM_REPORT_TSB_ONLY_ON_ERROR | IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT | IM_RETRY_ENABLE | IM_BYPASS_BUFFER; - last_scsi_command(host_index)[ldn] = IM_DEVICE_INQUIRY_CMD; - last_scsi_type(host_index)[ldn] = IM_SCB; - scb->sys_buf_adr = isa_virt_to_bus(buf); - scb->sys_buf_length = 255; /* maximum bufferlength gives max info */ - scb->tsb_adr = isa_virt_to_bus(tsb); - /* issue scb to passed ldn, and busy wait for interrupt */ - got_interrupt(host_index) = 0; - issue_cmd (host_index, isa_virt_to_bus(scb), IM_SCB | ldn); - while (!got_interrupt(host_index)) - barrier (); - - /*if command succesful, break */ - if ((stat_result(host_index) == IM_SCB_CMD_COMPLETED)|| - (stat_result(host_index) == IM_SCB_CMD_COMPLETED_WITH_RETRIES)) - return 1; - } - /*if all three retries failed, return "no device at this ldn" */ - if (retr >= 3) - return 0; - else - return 1; + int retr; + struct im_scb *scb; + struct im_tsb *tsb; + unsigned char *buf; + + scb = &(ld(host_index)[ldn].scb); + tsb = &(ld(host_index)[ldn].tsb); + buf = (unsigned char *) (&(ld(host_index)[ldn].buf)); + ld(host_index)[ldn].tsb.dev_status = 0; /* prepare statusblock */ + for (retr = 0; retr < 3; retr++) { + /* fill scb with inquiry command */ + scb->command = IM_DEVICE_INQUIRY_CMD | IM_NO_DISCONNECT; + scb->enable = IM_REPORT_TSB_ONLY_ON_ERROR | IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT | IM_RETRY_ENABLE | IM_BYPASS_BUFFER; + last_scsi_command(host_index)[ldn] = IM_DEVICE_INQUIRY_CMD; + last_scsi_type(host_index)[ldn] = IM_SCB; + scb->sys_buf_adr = isa_virt_to_bus(buf); + scb->sys_buf_length = 255; /* maximum bufferlength gives max info */ + scb->tsb_adr = isa_virt_to_bus(tsb); + /* issue scb to passed ldn, and busy wait for interrupt */ + got_interrupt(host_index) = 0; + issue_cmd(host_index, isa_virt_to_bus(scb), IM_SCB | ldn); + while (!got_interrupt(host_index)) + barrier(); + + /*if command succesful, break */ + if ((stat_result(host_index) == IM_SCB_CMD_COMPLETED) || (stat_result(host_index) == IM_SCB_CMD_COMPLETED_WITH_RETRIES)) + return 1; + } + /*if all three retries failed, return "no device at this ldn" */ + if (retr >= 3) + return 0; + else + return 1; } static int read_capacity(int host_index, int ldn) { - int retr; - struct im_scb *scb; - struct im_tsb *tsb; - unsigned char *buf; - - scb = &(ld(host_index)[ldn].scb); - tsb = &(ld(host_index)[ldn].tsb); - buf = (unsigned char *)(&(ld(host_index)[ldn].buf)); - ld(host_index)[ldn].tsb.dev_status = 0; - for (retr=0; retr<3; retr++) { - /*fill scb with read capacity command */ - scb->command = IM_READ_CAPACITY_CMD; - scb->enable = IM_REPORT_TSB_ONLY_ON_ERROR | IM_READ_CONTROL | IM_RETRY_ENABLE | IM_BYPASS_BUFFER; - last_scsi_command(host_index)[ldn] = IM_READ_CAPACITY_CMD; - last_scsi_type(host_index)[ldn] = IM_SCB; - scb->sys_buf_adr = isa_virt_to_bus(buf); - scb->sys_buf_length = 8; - scb->tsb_adr = isa_virt_to_bus(tsb); - /*issue scb to passed ldn, and busy wait for interrupt */ - got_interrupt(host_index) = 0; - issue_cmd (host_index, isa_virt_to_bus(scb), IM_SCB | ldn); - while (!got_interrupt(host_index)) - barrier (); - - /*if got capacity, get block length and return one device found */ - if ((stat_result(host_index) == IM_SCB_CMD_COMPLETED)|| - (stat_result(host_index) == IM_SCB_CMD_COMPLETED_WITH_RETRIES)) - return 1; - } - /*if all three retries failed, return "no device at this ldn" */ - if (retr >= 3) - return 0; - else - return 1; + int retr; + struct im_scb *scb; + struct im_tsb *tsb; + unsigned char *buf; + + scb = &(ld(host_index)[ldn].scb); + tsb = &(ld(host_index)[ldn].tsb); + buf = (unsigned char *) (&(ld(host_index)[ldn].buf)); + ld(host_index)[ldn].tsb.dev_status = 0; + for (retr = 0; retr < 3; retr++) { + /*fill scb with read capacity command */ + scb->command = IM_READ_CAPACITY_CMD; + scb->enable = IM_REPORT_TSB_ONLY_ON_ERROR | IM_READ_CONTROL | IM_RETRY_ENABLE | IM_BYPASS_BUFFER; + last_scsi_command(host_index)[ldn] = IM_READ_CAPACITY_CMD; + last_scsi_type(host_index)[ldn] = IM_SCB; + scb->sys_buf_adr = isa_virt_to_bus(buf); + scb->sys_buf_length = 8; + scb->tsb_adr = isa_virt_to_bus(tsb); + /*issue scb to passed ldn, and busy wait for interrupt */ + got_interrupt(host_index) = 0; + issue_cmd(host_index, isa_virt_to_bus(scb), IM_SCB | ldn); + while (!got_interrupt(host_index)) + barrier(); + + /*if got capacity, get block length and return one device found */ + if ((stat_result(host_index) == IM_SCB_CMD_COMPLETED) || (stat_result(host_index) == IM_SCB_CMD_COMPLETED_WITH_RETRIES)) + return 1; + } + /*if all three retries failed, return "no device at this ldn" */ + if (retr >= 3) + return 0; + else + return 1; } static int get_pos_info(int host_index) { - int retr; - struct im_scb *scb; - struct im_tsb *tsb; - unsigned char *buf; - - scb = &(ld(host_index)[MAX_LOG_DEV].scb); - tsb = &(ld(host_index)[MAX_LOG_DEV].tsb); - buf = (unsigned char *)(&(ld(host_index)[MAX_LOG_DEV].buf)); - ld(host_index)[MAX_LOG_DEV].tsb.dev_status = 0; - for (retr=0; retr<3; retr++) { - /*fill scb with get_pos_info command */ - scb->command = IM_GET_POS_INFO_CMD; - scb->enable = IM_READ_CONTROL | IM_REPORT_TSB_ONLY_ON_ERROR | IM_RETRY_ENABLE | IM_BYPASS_BUFFER; - last_scsi_command(host_index)[MAX_LOG_DEV] = IM_GET_POS_INFO_CMD; - last_scsi_type(host_index)[MAX_LOG_DEV] = IM_SCB; - scb->sys_buf_adr = isa_virt_to_bus(buf); - if (special(host_index)==IBM_SCSI2_FW) - scb->sys_buf_length = 256; /* get all info from F/W adapter */ - else - scb->sys_buf_length = 18; /* get exactly 18 bytes for other SCSI */ - scb->tsb_adr = isa_virt_to_bus(tsb); - /*issue scb to ldn=15, and busy wait for interrupt */ - got_interrupt(host_index) = 0; - issue_cmd (host_index, isa_virt_to_bus(scb), IM_SCB | MAX_LOG_DEV); - while (!got_interrupt(host_index)) - barrier (); - - /*if got POS-stuff, get block length and return one device found */ - if ((stat_result(host_index) == IM_SCB_CMD_COMPLETED)|| - (stat_result(host_index) == IM_SCB_CMD_COMPLETED_WITH_RETRIES)) - return 1; - } - /* if all three retries failed, return "no device at this ldn" */ - if (retr >= 3) - return 0; - else - return 1; + int retr; + struct im_scb *scb; + struct im_tsb *tsb; + unsigned char *buf; + + scb = &(ld(host_index)[MAX_LOG_DEV].scb); + tsb = &(ld(host_index)[MAX_LOG_DEV].tsb); + buf = (unsigned char *) (&(ld(host_index)[MAX_LOG_DEV].buf)); + ld(host_index)[MAX_LOG_DEV].tsb.dev_status = 0; + for (retr = 0; retr < 3; retr++) { + /*fill scb with get_pos_info command */ + scb->command = IM_GET_POS_INFO_CMD; + scb->enable = IM_READ_CONTROL | IM_REPORT_TSB_ONLY_ON_ERROR | IM_RETRY_ENABLE | IM_BYPASS_BUFFER; + last_scsi_command(host_index)[MAX_LOG_DEV] = IM_GET_POS_INFO_CMD; + last_scsi_type(host_index)[MAX_LOG_DEV] = IM_SCB; + scb->sys_buf_adr = isa_virt_to_bus(buf); + if (special(host_index) == IBM_SCSI2_FW) + scb->sys_buf_length = 256; /* get all info from F/W adapter */ + else + scb->sys_buf_length = 18; /* get exactly 18 bytes for other SCSI */ + scb->tsb_adr = isa_virt_to_bus(tsb); + /*issue scb to ldn=15, and busy wait for interrupt */ + got_interrupt(host_index) = 0; + issue_cmd(host_index, isa_virt_to_bus(scb), IM_SCB | MAX_LOG_DEV); + + /* FIXME: timeout */ + while (!got_interrupt(host_index)) + barrier(); + + /*if got POS-stuff, get block length and return one device found */ + if ((stat_result(host_index) == IM_SCB_CMD_COMPLETED) || (stat_result(host_index) == IM_SCB_CMD_COMPLETED_WITH_RETRIES)) + return 1; + } + /* if all three retries failed, return "no device at this ldn" */ + if (retr >= 3) + return 0; + else + return 1; } /* SCSI-immediate-command for assign. This functions maps/unmaps specific ldn-numbers on SCSI (PUN,LUN). It is needed for presetting of the subsystem and for dynamical remapping od ldns. */ -static int immediate_assign(int host_index, unsigned int pun, - unsigned int lun, unsigned int ldn, - unsigned int operation) -{ - int retr; - unsigned long imm_cmd; - - for (retr=0; retr<3; retr++) { - /* select mutation level of the SCSI-adapter */ - switch (special(host_index)) { - case IBM_SCSI2_FW: - imm_cmd = (unsigned long)(IM_ASSIGN_IMM_CMD); - imm_cmd |= (unsigned long)((lun & 7) << 24); - imm_cmd |= (unsigned long)((operation & 1) << 23); - imm_cmd |= (unsigned long)((pun & 7)<< 20)|((pun & 8)<< 24); - imm_cmd |= (unsigned long)((ldn & 15) << 16); - break; - default: - imm_cmd = inl(IM_CMD_REG(host_index)); - imm_cmd &= (unsigned long)(0xF8000000); /* keep reserved bits */ - imm_cmd |= (unsigned long)(IM_ASSIGN_IMM_CMD); - imm_cmd |= (unsigned long)((lun & 7) << 24); - imm_cmd |= (unsigned long)((operation & 1) << 23); - imm_cmd |= (unsigned long)((pun & 7) << 20); - imm_cmd |= (unsigned long)((ldn & 15) << 16); - break; - } - last_scsi_command(host_index)[MAX_LOG_DEV] = IM_ASSIGN_IMM_CMD; - last_scsi_type(host_index)[MAX_LOG_DEV] = IM_IMM_CMD; - got_interrupt(host_index) = 0; - issue_cmd (host_index, (unsigned long)(imm_cmd), IM_IMM_CMD | MAX_LOG_DEV); - while (!got_interrupt(host_index)) - barrier (); - - /*if command succesful, break */ - if (stat_result(host_index) == IM_IMMEDIATE_CMD_COMPLETED) - return 1; - } - if (retr >= 3) - return 0; - else - return 1; -} - -static int immediate_feature(int host_index, unsigned int speed, - unsigned int timeout) -{ - int retr; - unsigned long imm_cmd; - - for (retr=0; retr<3; retr++) { - /* select mutation level of the SCSI-adapter */ - imm_cmd = IM_FEATURE_CTR_IMM_CMD; - imm_cmd |= (unsigned long)((speed & 0x7) << 29); - imm_cmd |= (unsigned long)((timeout & 0x1fff) << 16); - last_scsi_command(host_index)[MAX_LOG_DEV] = IM_FEATURE_CTR_IMM_CMD; - last_scsi_type(host_index)[MAX_LOG_DEV] = IM_IMM_CMD; - got_interrupt(host_index) = 0; - /* we need to run into command errors in order to probe for the - * right speed! */ - global_command_error_excuse = 1; - issue_cmd (host_index, (unsigned long)(imm_cmd), IM_IMM_CMD | MAX_LOG_DEV); - while (!got_interrupt(host_index)) - barrier (); - if (global_command_error_excuse == CMD_FAIL) { - global_command_error_excuse = 0; - return 2; - } else - global_command_error_excuse = 0; - /*if command succesful, break */ - if (stat_result(host_index) == IM_IMMEDIATE_CMD_COMPLETED) - return 1; - } - if (retr >= 3) - return 0; - else - return 1; +static int immediate_assign(int host_index, unsigned int pun, unsigned int lun, unsigned int ldn, unsigned int operation) +{ + int retr; + unsigned long imm_cmd; + + for (retr = 0; retr < 3; retr++) { + /* select mutation level of the SCSI-adapter */ + switch (special(host_index)) { + case IBM_SCSI2_FW: + imm_cmd = (unsigned long) (IM_ASSIGN_IMM_CMD); + imm_cmd |= (unsigned long) ((lun & 7) << 24); + imm_cmd |= (unsigned long) ((operation & 1) << 23); + imm_cmd |= (unsigned long) ((pun & 7) << 20) | ((pun & 8) << 24); + imm_cmd |= (unsigned long) ((ldn & 15) << 16); + break; + default: + imm_cmd = inl(IM_CMD_REG(host_index)); + imm_cmd &= (unsigned long) (0xF8000000); /* keep reserved bits */ + imm_cmd |= (unsigned long) (IM_ASSIGN_IMM_CMD); + imm_cmd |= (unsigned long) ((lun & 7) << 24); + imm_cmd |= (unsigned long) ((operation & 1) << 23); + imm_cmd |= (unsigned long) ((pun & 7) << 20); + imm_cmd |= (unsigned long) ((ldn & 15) << 16); + break; + } + last_scsi_command(host_index)[MAX_LOG_DEV] = IM_ASSIGN_IMM_CMD; + last_scsi_type(host_index)[MAX_LOG_DEV] = IM_IMM_CMD; + got_interrupt(host_index) = 0; + issue_cmd(host_index, (unsigned long) (imm_cmd), IM_IMM_CMD | MAX_LOG_DEV); + while (!got_interrupt(host_index)) + barrier(); + + /*if command succesful, break */ + if (stat_result(host_index) == IM_IMMEDIATE_CMD_COMPLETED) + return 1; + } + if (retr >= 3) + return 0; + else + return 1; +} + +static int immediate_feature(int host_index, unsigned int speed, unsigned int timeout) +{ + int retr; + unsigned long imm_cmd; + + for (retr = 0; retr < 3; retr++) { + /* select mutation level of the SCSI-adapter */ + imm_cmd = IM_FEATURE_CTR_IMM_CMD; + imm_cmd |= (unsigned long) ((speed & 0x7) << 29); + imm_cmd |= (unsigned long) ((timeout & 0x1fff) << 16); + last_scsi_command(host_index)[MAX_LOG_DEV] = IM_FEATURE_CTR_IMM_CMD; + last_scsi_type(host_index)[MAX_LOG_DEV] = IM_IMM_CMD; + got_interrupt(host_index) = 0; + /* we need to run into command errors in order to probe for the + * right speed! */ + global_command_error_excuse = 1; + issue_cmd(host_index, (unsigned long) (imm_cmd), IM_IMM_CMD | MAX_LOG_DEV); + + /* FIXME: timeout */ + while (!got_interrupt(host_index)) + barrier(); + if (global_command_error_excuse == CMD_FAIL) { + global_command_error_excuse = 0; + return 2; + } else + global_command_error_excuse = 0; + /*if command succesful, break */ + if (stat_result(host_index) == IM_IMMEDIATE_CMD_COMPLETED) + return 1; + } + if (retr >= 3) + return 0; + else + return 1; } #ifdef CONFIG_IBMMCA_SCSI_DEV_RESET static int immediate_reset(int host_index, unsigned int ldn) { - int retries; - int ticks; - unsigned long imm_command; - - for (retries=0; retries<3; retries ++) { - imm_command = inl(IM_CMD_REG(host_index)); - imm_command &= (unsigned long)(0xFFFF0000); /* keep reserved bits */ - imm_command |= (unsigned long)(IM_RESET_IMM_CMD); - last_scsi_command(host_index)[ldn] = IM_RESET_IMM_CMD; - last_scsi_type(host_index)[ldn] = IM_IMM_CMD; - got_interrupt(host_index) = 0; - reset_status(host_index) = IM_RESET_IN_PROGRESS; - issue_cmd (host_index, (unsigned long)(imm_command), IM_IMM_CMD | ldn); - ticks = IM_RESET_DELAY*HZ; - while (reset_status(host_index) == IM_RESET_IN_PROGRESS && --ticks) { - udelay((1+999/HZ)*1000); - barrier(); - } - /* if reset did not complete, just complain */ - if (!ticks) { - printk("IBM MCA SCSI: reset did not complete within %d seconds.\n", - IM_RESET_DELAY); - reset_status(host_index) = IM_RESET_FINISHED_OK; - /* did not work, finish */ - return 1; - } - /*if command succesful, break */ - if (stat_result(host_index) == IM_IMMEDIATE_CMD_COMPLETED) - return 1; - } - if (retries >= 3) - return 0; - else - return 1; + int retries; + int ticks; + unsigned long imm_command; + + for (retries = 0; retries < 3; retries++) { + imm_command = inl(IM_CMD_REG(host_index)); + imm_command &= (unsigned long) (0xFFFF0000); /* keep reserved bits */ + imm_command |= (unsigned long) (IM_RESET_IMM_CMD); + last_scsi_command(host_index)[ldn] = IM_RESET_IMM_CMD; + last_scsi_type(host_index)[ldn] = IM_IMM_CMD; + got_interrupt(host_index) = 0; + reset_status(host_index) = IM_RESET_IN_PROGRESS; + issue_cmd(host_index, (unsigned long) (imm_command), IM_IMM_CMD | ldn); + ticks = IM_RESET_DELAY * HZ; + while (reset_status(host_index) == IM_RESET_IN_PROGRESS && --ticks) { + udelay((1 + 999 / HZ) * 1000); + barrier(); + } + /* if reset did not complete, just complain */ + if (!ticks) { + printk(KERN_ERR "IBM MCA SCSI: reset did not complete within %d seconds.\n", IM_RESET_DELAY); + reset_status(host_index) = IM_RESET_FINISHED_OK; + /* did not work, finish */ + return 1; + } + /*if command succesful, break */ + if (stat_result(host_index) == IM_IMMEDIATE_CMD_COMPLETED) + return 1; + } + if (retries >= 3) + return 0; + else + return 1; } #endif /* type-interpreter for physical device numbers */ static char *ti_p(int dev) { - switch (dev) { - case TYPE_IBM_SCSI_ADAPTER: return("A"); - case TYPE_DISK: return("D"); - case TYPE_TAPE: return("T"); - case TYPE_PROCESSOR: return("P"); - case TYPE_WORM: return("W"); - case TYPE_ROM: return("R"); - case TYPE_SCANNER: return("S"); - case TYPE_MOD: return("M"); - case TYPE_MEDIUM_CHANGER: return("C"); - case TYPE_NO_LUN: return("+"); /* show NO_LUN */ - } - return("-"); /* TYPE_NO_DEVICE and others */ + switch (dev) { + case TYPE_IBM_SCSI_ADAPTER: + return ("A"); + case TYPE_DISK: + return ("D"); + case TYPE_TAPE: + return ("T"); + case TYPE_PROCESSOR: + return ("P"); + case TYPE_WORM: + return ("W"); + case TYPE_ROM: + return ("R"); + case TYPE_SCANNER: + return ("S"); + case TYPE_MOD: + return ("M"); + case TYPE_MEDIUM_CHANGER: + return ("C"); + case TYPE_NO_LUN: + return ("+"); /* show NO_LUN */ + } + return ("-"); /* TYPE_NO_DEVICE and others */ } /* interpreter for logical device numbers (ldn) */ static char *ti_l(int val) { - const char hex[16] = "0123456789abcdef"; - static char answer[2]; + const char hex[16] = "0123456789abcdef"; + static char answer[2]; - answer[1] = (char)(0x0); - if (val<=MAX_LOG_DEV) answer[0] = hex[val]; else answer[0] = '-'; - return (char *)&answer; + answer[1] = (char) (0x0); + if (val <= MAX_LOG_DEV) + answer[0] = hex[val]; + else + answer[0] = '-'; + return (char *) &answer; } /* transfers bitpattern of the feature command to values in MHz */ static char *ibmrate(unsigned int speed, int i) { - switch (speed) { - case 0: return i ? "5.00" : "10.00"; - case 1: return i ? "4.00" : "8.00"; - case 2: return i ? "3.33" : "6.66"; - case 3: return i ? "2.86" : "5.00"; - case 4: return i ? "2.50" : "4.00"; - case 5: return i ? "2.22" : "3.10"; - case 6: return i ? "2.00" : "2.50"; - case 7: return i ? "1.82" : "2.00"; - } - return "---"; + switch (speed) { + case 0: + return i ? "5.00" : "10.00"; + case 1: + return i ? "4.00" : "8.00"; + case 2: + return i ? "3.33" : "6.66"; + case 3: + return i ? "2.86" : "5.00"; + case 4: + return i ? "2.50" : "4.00"; + case 5: + return i ? "2.22" : "3.10"; + case 6: + return i ? "2.00" : "2.50"; + case 7: + return i ? "1.82" : "2.00"; + } + return "---"; } static int probe_display(int what) { - static int rotator = 0; - const char rotor[] = "|/-\\"; + static int rotator = 0; + const char rotor[] = "|/-\\"; - if (!(display_mode & LED_DISP)) - return 0; - if (!what) { - outl(0x20202020,MOD95_LED_PORT); - outl(0x20202020,MOD95_LED_PORT+4); - } else { - outb('S',MOD95_LED_PORT+7); outb('C',MOD95_LED_PORT+6); - outb('S',MOD95_LED_PORT+5); outb('I',MOD95_LED_PORT+4); - outb('i',MOD95_LED_PORT+3); outb('n',MOD95_LED_PORT+2); - outb('i',MOD95_LED_PORT+1); outb((char)(rotor[rotator]),MOD95_LED_PORT); - rotator++; - if (rotator>3) rotator=0; - } - return 0; + if (!(display_mode & LED_DISP)) + return 0; + if (!what) { + outl(0x20202020, MOD95_LED_PORT); + outl(0x20202020, MOD95_LED_PORT + 4); + } else { + outb('S', MOD95_LED_PORT + 7); + outb('C', MOD95_LED_PORT + 6); + outb('S', MOD95_LED_PORT + 5); + outb('I', MOD95_LED_PORT + 4); + outb('i', MOD95_LED_PORT + 3); + outb('n', MOD95_LED_PORT + 2); + outb('i', MOD95_LED_PORT + 1); + outb((char) (rotor[rotator]), MOD95_LED_PORT); + rotator++; + if (rotator > 3) + rotator = 0; + } + return 0; } static int probe_bus_mode(int host_index) { - struct im_pos_info *info; - int num_bus = 0; - int ldn; - - info = (struct im_pos_info *)(&(ld(host_index)[MAX_LOG_DEV].buf)); - if (get_pos_info(host_index)) { - if (info->connector_size & 0xf000) - subsystem_connector_size(host_index)=16; - else - subsystem_connector_size(host_index)=32; - num_bus |= (info->pos_4b & 8) >> 3; - for (ldn=0; ldn<=MAX_LOG_DEV; ldn++) { - if ((special(host_index)==IBM_SCSI_WCACHE)|| - (special(host_index)==IBM_7568_WCACHE)) { - if (!((info->cache_stat >> ldn) & 1)) - ld(host_index)[ldn].cache_flag = 0; - } - if (!((info->retry_stat >> ldn) & 1)) - ld(host_index)[ldn].retry_flag = 0; - } + struct im_pos_info *info; + int num_bus = 0; + int ldn; + + info = (struct im_pos_info *) (&(ld(host_index)[MAX_LOG_DEV].buf)); + if (get_pos_info(host_index)) { + if (info->connector_size & 0xf000) + subsystem_connector_size(host_index) = 16; + else + subsystem_connector_size(host_index) = 32; + num_bus |= (info->pos_4b & 8) >> 3; + for (ldn = 0; ldn <= MAX_LOG_DEV; ldn++) { + if ((special(host_index) == IBM_SCSI_WCACHE) || (special(host_index) == IBM_7568_WCACHE)) { + if (!((info->cache_stat >> ldn) & 1)) + ld(host_index)[ldn].cache_flag = 0; + } + if (!((info->retry_stat >> ldn) & 1)) + ld(host_index)[ldn].retry_flag = 0; + } #ifdef IM_DEBUG_PROBE - printk("IBM MCA SCSI: SCSI-Cache bits: "); - for (ldn=0; ldn<=MAX_LOG_DEV; ldn++) { - printk("%d",ld(host_index)[ldn].cache_flag); - } - printk("\nIBM MCA SCSI: SCSI-Retry bits: "); - for (ldn=0; ldn<=MAX_LOG_DEV; ldn++) { - printk("%d",ld(host_index)[ldn].retry_flag); - } - printk("\n"); + printk("IBM MCA SCSI: SCSI-Cache bits: "); + for (ldn = 0; ldn <= MAX_LOG_DEV; ldn++) { + printk("%d", ld(host_index)[ldn].cache_flag); + } + printk("\nIBM MCA SCSI: SCSI-Retry bits: "); + for (ldn = 0; ldn <= MAX_LOG_DEV; ldn++) { + printk("%d", ld(host_index)[ldn].retry_flag); + } + printk("\n"); #endif - } - return num_bus; + } + return num_bus; } /* probing scsi devices */ -static void check_devices (int host_index, int adaptertype) +static void check_devices(int host_index, int adaptertype) { - int id, lun, ldn, ticks; - int count_devices; /* local counter for connected device */ - int max_pun; - int num_bus; - int speedrun; /* local adapter_speed check variable */ - - /* assign default values to certain variables */ - ticks = 0; - count_devices = 0; - IBM_DS(host_index).dyn_flag = 0; /* normally no need for dynamical ldn management */ - IBM_DS(host_index).total_errors = 0; /* set errorcounter to 0 */ - next_ldn(host_index) = 7; /* next ldn to be assigned is 7, because 0-6 is 'hardwired'*/ - - /* initialize the very important driver-informational arrays/structs */ - memset (ld(host_index), 0, sizeof(ld(host_index))); - for (ldn=0; ldn<=MAX_LOG_DEV; ldn++) { - last_scsi_command(host_index)[ldn] = NO_SCSI; /* emptify last SCSI-command storage */ - last_scsi_type(host_index)[ldn] = 0; - ld(host_index)[ldn].cache_flag = 1; - ld(host_index)[ldn].retry_flag = 1; - } - memset (get_ldn(host_index), TYPE_NO_DEVICE, sizeof(get_ldn(host_index))); /* this is essential ! */ - memset (get_scsi(host_index), TYPE_NO_DEVICE, sizeof(get_scsi(host_index))); /* this is essential ! */ - for (lun=0; lun<8; lun++) { - /* mark the adapter at its pun on all luns*/ - get_scsi(host_index)[subsystem_pun(host_index)][lun] = TYPE_IBM_SCSI_ADAPTER; - get_ldn(host_index)[subsystem_pun(host_index)][lun] = MAX_LOG_DEV; /* make sure, the subsystem - ldn is active for all - luns. */ - } - probe_display(0); /* Supercool display usage during SCSI-probing. */ - /* This makes sense, when booting without any */ - /* monitor connected on model XX95. */ - - /* STEP 1: */ - adapter_speed(host_index) = global_adapter_speed; - speedrun = adapter_speed(host_index); - while (immediate_feature(host_index,speedrun,adapter_timeout)==2) { - probe_display(1); - if (speedrun==7) - panic("IBM MCA SCSI: Cannot set Synchronous-Transfer-Rate!\n"); - speedrun++; - if (speedrun>7) - speedrun=7; - } - adapter_speed(host_index) = speedrun; - /* Get detailed information about the current adapter, necessary for - * device operations: */ - num_bus=probe_bus_mode(host_index); - - /* num_bus contains only valid data for the F/W adapter! */ - if (adaptertype==IBM_SCSI2_FW) { /* F/W SCSI adapter: */ - /* F/W adapter PUN-space extension evaluation: */ - if (num_bus) { - printk("IBM MCA SCSI: Seperate bus mode (wide-addressing enabled)\n"); - subsystem_maxid(host_index) = 16; - } else { - printk("IBM MCA SCSI: Combined bus mode (wide-addressing disabled)\n"); - subsystem_maxid(host_index) = 8; - } - printk("IBM MCA SCSI: Sync.-Rate (F/W: 20, Int.: 10, Ext.: %s) MBytes/s\n", - ibmrate(speedrun,adaptertype)); - } else /* all other IBM SCSI adapters: */ - printk("IBM MCA SCSI: Synchronous-SCSI-Transfer-Rate: %s MBytes/s\n", - ibmrate(speedrun,adaptertype)); + int id, lun, ldn, ticks; + int count_devices; /* local counter for connected device */ + int max_pun; + int num_bus; + int speedrun; /* local adapter_speed check variable */ + + /* assign default values to certain variables */ + ticks = 0; + count_devices = 0; + IBM_DS(host_index).dyn_flag = 0; /* normally no need for dynamical ldn management */ + IBM_DS(host_index).total_errors = 0; /* set errorcounter to 0 */ + next_ldn(host_index) = 7; /* next ldn to be assigned is 7, because 0-6 is 'hardwired' */ + + /* initialize the very important driver-informational arrays/structs */ + memset(ld(host_index), 0, sizeof(ld(host_index))); + for (ldn = 0; ldn <= MAX_LOG_DEV; ldn++) { + last_scsi_command(host_index)[ldn] = NO_SCSI; /* emptify last SCSI-command storage */ + last_scsi_type(host_index)[ldn] = 0; + ld(host_index)[ldn].cache_flag = 1; + ld(host_index)[ldn].retry_flag = 1; + } + memset(get_ldn(host_index), TYPE_NO_DEVICE, sizeof(get_ldn(host_index))); /* this is essential ! */ + memset(get_scsi(host_index), TYPE_NO_DEVICE, sizeof(get_scsi(host_index))); /* this is essential ! */ + for (lun = 0; lun < 8; lun++) { + /* mark the adapter at its pun on all luns */ + get_scsi(host_index)[subsystem_pun(host_index)][lun] = TYPE_IBM_SCSI_ADAPTER; + get_ldn(host_index)[subsystem_pun(host_index)][lun] = MAX_LOG_DEV; /* make sure, the subsystem + ldn is active for all + luns. */ + } + probe_display(0); /* Supercool display usage during SCSI-probing. */ + /* This makes sense, when booting without any */ + /* monitor connected on model XX95. */ + + /* STEP 1: */ + adapter_speed(host_index) = global_adapter_speed; + speedrun = adapter_speed(host_index); + while (immediate_feature(host_index, speedrun, adapter_timeout) == 2) { + probe_display(1); + if (speedrun == 7) + panic("IBM MCA SCSI: Cannot set Synchronous-Transfer-Rate!\n"); + speedrun++; + if (speedrun > 7) + speedrun = 7; + } + adapter_speed(host_index) = speedrun; + /* Get detailed information about the current adapter, necessary for + * device operations: */ + num_bus = probe_bus_mode(host_index); + + /* num_bus contains only valid data for the F/W adapter! */ + if (adaptertype == IBM_SCSI2_FW) { /* F/W SCSI adapter: */ + /* F/W adapter PUN-space extension evaluation: */ + if (num_bus) { + printk(KERN_INFO "IBM MCA SCSI: Seperate bus mode (wide-addressing enabled)\n"); + subsystem_maxid(host_index) = 16; + } else { + printk(KERN_INFO "IBM MCA SCSI: Combined bus mode (wide-addressing disabled)\n"); + subsystem_maxid(host_index) = 8; + } + printk(KERN_INFO "IBM MCA SCSI: Sync.-Rate (F/W: 20, Int.: 10, Ext.: %s) MBytes/s\n", ibmrate(speedrun, adaptertype)); + } else /* all other IBM SCSI adapters: */ + printk(KERN_INFO "IBM MCA SCSI: Synchronous-SCSI-Transfer-Rate: %s MBytes/s\n", ibmrate(speedrun, adaptertype)); - /* assign correct PUN device space */ - max_pun = subsystem_maxid(host_index); + /* assign correct PUN device space */ + max_pun = subsystem_maxid(host_index); #ifdef IM_DEBUG_PROBE - printk("IBM MCA SCSI: Current SCSI-host index: %d\n",host_index); - printk("IBM MCA SCSI: Removing default logical SCSI-device mapping."); + printk("IBM MCA SCSI: Current SCSI-host index: %d\n", host_index); + printk("IBM MCA SCSI: Removing default logical SCSI-device mapping."); #else - printk("IBM MCA SCSI: Dev. Order: %s, Mapping (takes <2min): ", - (ibm_ansi_order) ? "ANSI" : "New"); + printk(KERN_INFO "IBM MCA SCSI: Dev. Order: %s, Mapping (takes <2min): ", (ibm_ansi_order) ? "ANSI" : "New"); #endif - for (ldn=0; ldn 0) { - /* remove mapping */ - get_ldn(host_index)[id][lun]=TYPE_NO_DEVICE; - immediate_assign(host_index,0,0,ldn,REMOVE_LDN); - } else ldn++; - } - } else if (lun == 0) { - /* map lun == 0, even if no device exists */ - immediate_assign(host_index,id,lun,ldn,SET_LDN); - get_ldn(host_index)[id][lun]=ldn; /* map ldn */ - ldn++; - } - } - } - /* STEP 4: */ - - /* map remaining ldns to non-existing devices */ - for (lun=1; lun<8 && ldn 0) { + /* remove mapping */ + get_ldn(host_index)[id][lun] = TYPE_NO_DEVICE; + immediate_assign(host_index, 0, 0, ldn, REMOVE_LDN); + } else + ldn++; + } + } else if (lun == 0) { + /* map lun == 0, even if no device exists */ + immediate_assign(host_index, id, lun, ldn, SET_LDN); + get_ldn(host_index)[id][lun] = ldn; /* map ldn */ + ldn++; + } + } + } + /* STEP 4: */ + + /* map remaining ldns to non-existing devices */ + for (lun = 1; lun < 8 && ldn < MAX_LOG_DEV; lun++) + for (id = 0; id < max_pun && ldn < MAX_LOG_DEV; id++) { + if (get_scsi(host_index)[id][lun] == TYPE_NO_LUN || get_scsi(host_index)[id][lun] == TYPE_NO_DEVICE) { + probe_display(1); + /* Map remaining ldns only to NON-existing pun,lun + combinations to make sure an inquiry will fail. + For MULTI_LUN, it is needed to avoid adapter autonome + SCSI-remapping. */ + immediate_assign(host_index, id, lun, ldn, SET_LDN); + get_ldn(host_index)[id][lun] = ldn; + ldn++; + } + } #ifndef IM_DEBUG_PROBE - printk("mapped."); + printk("mapped."); #endif - printk("\n"); + printk("\n"); #ifdef IM_DEBUG_PROBE - if (ibm_ansi_order) - printk("IBM MCA SCSI: Device order: IBM/ANSI (pun=7 is first).\n"); - else - printk("IBM MCA SCSI: Device order: New Industry Standard (pun=0 is first).\n"); + if (ibm_ansi_order) + printk("IBM MCA SCSI: Device order: IBM/ANSI (pun=7 is first).\n"); + else + printk("IBM MCA SCSI: Device order: New Industry Standard (pun=0 is first).\n"); #endif #ifdef IM_DEBUG_PROBE - /* Show the physical and logical mapping during boot. */ - printk("IBM MCA SCSI: Determined SCSI-device-mapping:\n"); - printk(" Physical SCSI-Device Map Logical SCSI-Device Map\n"); - printk("ID\\LUN 0 1 2 3 4 5 6 7 ID\\LUN 0 1 2 3 4 5 6 7\n"); - for (id=0; id=MAX_LOG_DEV) - IBM_DS(host_index).dyn_flag = 1; /* dynamical assignment is necessary */ - else - IBM_DS(host_index).dyn_flag = 0; /* dynamical assignment is not necessary */ - - /* If no SCSI-devices are assigned, return 1 in order to cause message. */ - if (ldn == 0) - printk("IBM MCA SCSI: Warning: No SCSI-devices found/assigned!\n"); - - /* reset the counters for statistics on the current adapter */ - IBM_DS(host_index).scbs = 0; - IBM_DS(host_index).long_scbs = 0; - IBM_DS(host_index).total_accesses = 0; - IBM_DS(host_index).total_interrupts = 0; - IBM_DS(host_index).dynamical_assignments = 0; - memset (IBM_DS(host_index).ldn_access, 0x0, - sizeof (IBM_DS(host_index).ldn_access)); - memset (IBM_DS(host_index).ldn_read_access, 0x0, - sizeof (IBM_DS(host_index).ldn_read_access)); - memset (IBM_DS(host_index).ldn_write_access, 0x0, - sizeof (IBM_DS(host_index).ldn_write_access)); - memset (IBM_DS(host_index).ldn_inquiry_access, 0x0, - sizeof (IBM_DS(host_index).ldn_inquiry_access)); - memset (IBM_DS(host_index).ldn_modeselect_access, 0x0, - sizeof (IBM_DS(host_index).ldn_modeselect_access)); - memset (IBM_DS(host_index).ldn_assignments, 0x0, - sizeof (IBM_DS(host_index).ldn_assignments)); - probe_display(0); - return; -} - -static int device_exists (int host_index, int ldn, int *block_length, - int *device_type) -{ - unsigned char *buf; - /* if no valid device found, return immediately with 0 */ - if (!(device_inquiry(host_index, ldn))) - return 0; - buf = (unsigned char *)(&(ld(host_index)[ldn].buf)); - if (*buf == TYPE_ROM) { - *device_type = TYPE_ROM; - *block_length = 2048; /* (standard blocksize for yellow-/red-book) */ - return 1; - } - if (*buf == TYPE_WORM) { - *device_type = TYPE_WORM; - *block_length = 2048; - return 1; - } - if (*buf == TYPE_DISK) { - *device_type = TYPE_DISK; - if (read_capacity( host_index, ldn)) { - *block_length = *(buf+7) + (*(buf+6) << 8) + - (*(buf+5) << 16) + (*(buf+4) << 24); - return 1; - } else - return 0; - } - if (*buf == TYPE_MOD) { - *device_type = TYPE_MOD; - if (read_capacity( host_index, ldn)) { - *block_length = *(buf+7) + (*(buf+6) << 8) + - (*(buf+5) << 16) + (*(buf+4) << 24); - return 1; - } else + /* Show the physical and logical mapping during boot. */ + printk("IBM MCA SCSI: Determined SCSI-device-mapping:\n"); + printk(" Physical SCSI-Device Map Logical SCSI-Device Map\n"); + printk("ID\\LUN 0 1 2 3 4 5 6 7 ID\\LUN 0 1 2 3 4 5 6 7\n"); + for (id = 0; id < max_pun; id++) { + printk("%2d ", id); + for (lun = 0; lun < 8; lun++) + printk("%2s ", ti_p(get_scsi(host_index)[id][lun])); + printk(" %2d ", id); + for (lun = 0; lun < 8; lun++) + printk("%2s ", ti_l(get_ldn(host_index)[id][lun])); + printk("\n"); + } +#endif + + /* assign total number of found SCSI-devices to the statistics struct */ + IBM_DS(host_index).total_scsi_devices = count_devices; + + /* decide for output in /proc-filesystem, if the configuration of + SCSI-devices makes dynamical reassignment of devices necessary */ + if (count_devices >= MAX_LOG_DEV) + IBM_DS(host_index).dyn_flag = 1; /* dynamical assignment is necessary */ + else + IBM_DS(host_index).dyn_flag = 0; /* dynamical assignment is not necessary */ + + /* If no SCSI-devices are assigned, return 1 in order to cause message. */ + if (ldn == 0) + printk("IBM MCA SCSI: Warning: No SCSI-devices found/assigned!\n"); + + /* reset the counters for statistics on the current adapter */ + IBM_DS(host_index).scbs = 0; + IBM_DS(host_index).long_scbs = 0; + IBM_DS(host_index).total_accesses = 0; + IBM_DS(host_index).total_interrupts = 0; + IBM_DS(host_index).dynamical_assignments = 0; + memset(IBM_DS(host_index).ldn_access, 0x0, sizeof(IBM_DS(host_index).ldn_access)); + memset(IBM_DS(host_index).ldn_read_access, 0x0, sizeof(IBM_DS(host_index).ldn_read_access)); + memset(IBM_DS(host_index).ldn_write_access, 0x0, sizeof(IBM_DS(host_index).ldn_write_access)); + memset(IBM_DS(host_index).ldn_inquiry_access, 0x0, sizeof(IBM_DS(host_index).ldn_inquiry_access)); + memset(IBM_DS(host_index).ldn_modeselect_access, 0x0, sizeof(IBM_DS(host_index).ldn_modeselect_access)); + memset(IBM_DS(host_index).ldn_assignments, 0x0, sizeof(IBM_DS(host_index).ldn_assignments)); + probe_display(0); + return; +} + +static int device_exists(int host_index, int ldn, int *block_length, int *device_type) +{ + unsigned char *buf; + /* if no valid device found, return immediately with 0 */ + if (!(device_inquiry(host_index, ldn))) + return 0; + buf = (unsigned char *) (&(ld(host_index)[ldn].buf)); + if (*buf == TYPE_ROM) { + *device_type = TYPE_ROM; + *block_length = 2048; /* (standard blocksize for yellow-/red-book) */ + return 1; + } + if (*buf == TYPE_WORM) { + *device_type = TYPE_WORM; + *block_length = 2048; + return 1; + } + if (*buf == TYPE_DISK) { + *device_type = TYPE_DISK; + if (read_capacity(host_index, ldn)) { + *block_length = *(buf + 7) + (*(buf + 6) << 8) + (*(buf + 5) << 16) + (*(buf + 4) << 24); + return 1; + } else + return 0; + } + if (*buf == TYPE_MOD) { + *device_type = TYPE_MOD; + if (read_capacity(host_index, ldn)) { + *block_length = *(buf + 7) + (*(buf + 6) << 8) + (*(buf + 5) << 16) + (*(buf + 4) << 24); + return 1; + } else + return 0; + } + if (*buf == TYPE_TAPE) { + *device_type = TYPE_TAPE; + *block_length = 0; /* not in use (setting by mt and mtst in op.) */ + return 1; + } + if (*buf == TYPE_PROCESSOR) { + *device_type = TYPE_PROCESSOR; + *block_length = 0; /* they set their stuff on drivers */ + return 1; + } + if (*buf == TYPE_SCANNER) { + *device_type = TYPE_SCANNER; + *block_length = 0; /* they set their stuff on drivers */ + return 1; + } + if (*buf == TYPE_MEDIUM_CHANGER) { + *device_type = TYPE_MEDIUM_CHANGER; + *block_length = 0; /* One never knows, what to expect on a medium + changer device. */ + return 1; + } return 0; - } - if (*buf == TYPE_TAPE) { - *device_type = TYPE_TAPE; - *block_length = 0; /* not in use (setting by mt and mtst in op.) */ - return 1; - } - if (*buf == TYPE_PROCESSOR) { - *device_type = TYPE_PROCESSOR; - *block_length = 0; /* they set their stuff on drivers */ - return 1; - } - if (*buf == TYPE_SCANNER) { - *device_type = TYPE_SCANNER; - *block_length = 0; /* they set their stuff on drivers */ - return 1; - } - if (*buf == TYPE_MEDIUM_CHANGER) { - *device_type = TYPE_MEDIUM_CHANGER; - *block_length = 0; /* One never knows, what to expect on a medium - changer device. */ - return 1; - } - return 0; -} - -void internal_ibmmca_scsi_setup (char *str, int *ints) -{ - int i, j, io_base, id_base; - char *token; - - io_base = 0; - id_base = 0; - if (str) { - token = strtok(str,","); - j = 0; - while (token) { - if (!strcmp(token,"activity")) display_mode |= LED_ACTIVITY; - if (!strcmp(token,"display")) display_mode |= LED_DISP; - if (!strcmp(token,"adisplay")) display_mode |= LED_ADISP; - if (!strcmp(token,"normal")) ibm_ansi_order = 0; - if (!strcmp(token,"ansi")) ibm_ansi_order = 1; - if (!strcmp(token,"fast")) global_adapter_speed = 0; - if (!strcmp(token,"medium")) global_adapter_speed = 4; - if (!strcmp(token,"slow")) global_adapter_speed = 7; - if ((*token == '-') || (isdigit(*token))) { - if (!(j%2) && (io_base < IM_MAX_HOSTS)) - io_port[io_base++] = simple_strtoul(token,NULL,0); - if ((j%2) && (id_base < IM_MAX_HOSTS)) - scsi_id[id_base++] = simple_strtoul(token,NULL,0); - j++; - } - token = strtok(NULL,","); - } - } else if (ints) { - for (i = 0; i < IM_MAX_HOSTS && 2*i+2 < ints[0]; i++) { - io_port[i] = ints[2*i+2]; - scsi_id[i] = ints[2*i+2]; - } - } - return; -} - -static int ibmmca_getinfo (char *buf, int slot, void *dev_id) -{ - struct Scsi_Host *shpnt; - int len, speciale, connectore, k; - unsigned int pos[8]; - unsigned long flags; - struct Scsi_Host *dev = dev_id; - - IBMLOCK(dev) - shpnt = dev; /* assign host-structure to local pointer */ - len = 0; /* set filled text-buffer index to 0 */ - /* get the _special contents of the hostdata structure */ - speciale = ((struct ibmmca_hostdata *)shpnt->hostdata)->_special; - connectore = ((struct ibmmca_hostdata *)shpnt->hostdata)->_connector_size; - for (k=2;k<4;k++) - pos[k] = ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos[k]; - if (speciale == FORCED_DETECTION) { /* forced detection */ - len += sprintf (buf+len, - "Adapter category: forced detected\n" - "***************************************\n" - "*** Forced detected SCSI Adapter ***\n" - "*** No chip-information available ***\n" - "***************************************\n"); - } else if (speciale == INTEGRATED_SCSI) { - /* if the integrated subsystem has been found automatically: */ - len += sprintf (buf+len, - "Adapter category: integrated\n" - "Chip revision level: %d\n" - "Chip status: %s\n" - "8 kByte NVRAM status: %s\n", - ((pos[2] & 0xf0) >> 4), - (pos[2] & 1) ? "enabled" : "disabled", - (pos[2] & 2) ? "locked" : "accessible"); - } else if ((speciale>=0)&& - (speciale<(sizeof(subsys_list)/sizeof(struct subsys_list_struct)))) { - /* if the subsystem is a slot adapter */ - len += sprintf (buf+len, - "Adapter category: slot-card\n" - "ROM Segment Address: "); - if ((pos[2] & 0xf0) == 0xf0) - len += sprintf (buf+len, "off\n"); - else - len += sprintf (buf+len, "0x%x\n", - ((pos[2] & 0xf0) << 13) + 0xc0000); - len += sprintf (buf + len, "Chip status: %s\n", - (pos[2] & 1) ? "enabled" : "disabled"); - len += sprintf (buf + len, "Adapter I/O Offset: 0x%x\n", - ((pos[2] & 0x0e) << 2)); - } else { - len += sprintf (buf + len, "Adapter category: unknown\n"); - } - /* common subsystem information to write to the slotn file */ - len += sprintf (buf + len, "Subsystem PUN: %d\n", shpnt->this_id); - len += sprintf (buf + len, "I/O base address range: 0x%x-0x%x\n", - (unsigned int)(shpnt->io_port), - (unsigned int)(shpnt->io_port+7)); - len += sprintf (buf + len, "MCA-slot size: %d bits",connectore); - /* Now make sure, the bufferlength is devidable by 4 to avoid - * paging problems of the buffer. */ - while ( len % sizeof( int ) != ( sizeof ( int ) - 1 ) ) - len += sprintf (buf+len, " "); - len += sprintf (buf+len, "\n"); - IBMUNLOCK(shpnt) - return len; -} - -int ibmmca_detect (Scsi_Host_Template * scsi_template) -{ - struct Scsi_Host *shpnt; - int port, id, i, j, k, list_size, slot; - int devices_on_irq_11 = 0; - int devices_on_irq_14 = 0; - int IRQ14_registered = 0; - int IRQ11_registered = 0; - - found = 0; /* make absolutely sure, that found is set to 0 */ - - /* First of all, print the version number of the driver. This is - * important to allow better user bugreports in case of already - * having problems with the MCA_bus probing. */ - printk("IBM MCA SCSI: Version %s\n",IBMMCA_SCSI_DRIVER_VERSION); - /* if this is not MCA machine, return "nothing found" */ - if (!MCA_bus) { - printk("IBM MCA SCSI: No Microchannel-bus present --> Aborting.\n" - " This machine does not have any IBM MCA-bus\n" - " or the MCA-Kernel-support is not enabled!\n"); - return 0; - } +} + +static void internal_ibmmca_scsi_setup(char *str, int *ints) +{ + int i, j, io_base, id_base; + char *token; + + io_base = 0; + id_base = 0; + if (str) { + token = strtok(str, ","); + j = 0; + while (token) { + if (!strcmp(token, "activity")) + display_mode |= LED_ACTIVITY; + if (!strcmp(token, "display")) + display_mode |= LED_DISP; + if (!strcmp(token, "adisplay")) + display_mode |= LED_ADISP; + if (!strcmp(token, "normal")) + ibm_ansi_order = 0; + if (!strcmp(token, "ansi")) + ibm_ansi_order = 1; + if (!strcmp(token, "fast")) + global_adapter_speed = 0; + if (!strcmp(token, "medium")) + global_adapter_speed = 4; + if (!strcmp(token, "slow")) + global_adapter_speed = 7; + if ((*token == '-') || (isdigit(*token))) { + if (!(j % 2) && (io_base < IM_MAX_HOSTS)) + io_port[io_base++] = simple_strtoul(token, NULL, 0); + if ((j % 2) && (id_base < IM_MAX_HOSTS)) + scsi_id[id_base++] = simple_strtoul(token, NULL, 0); + j++; + } + token = strtok(NULL, ","); + } + } else if (ints) { + for (i = 0; i < IM_MAX_HOSTS && 2 * i + 2 < ints[0]; i++) { + io_port[i] = ints[2 * i + 2]; + scsi_id[i] = ints[2 * i + 2]; + } + } + return; +} + +static int ibmmca_getinfo(char *buf, int slot, void *dev_id) +{ + struct Scsi_Host *shpnt; + int len, speciale, connectore, k; + unsigned int pos[8]; + unsigned long flags; + struct Scsi_Host *dev = dev_id; + + spin_lock_irqsave(dev->host_lock, flags); + + shpnt = dev; /* assign host-structure to local pointer */ + len = 0; /* set filled text-buffer index to 0 */ + /* get the _special contents of the hostdata structure */ + speciale = ((struct ibmmca_hostdata *) shpnt->hostdata)->_special; + connectore = ((struct ibmmca_hostdata *) shpnt->hostdata)->_connector_size; + for (k = 2; k < 4; k++) + pos[k] = ((struct ibmmca_hostdata *) shpnt->hostdata)->_pos[k]; + if (speciale == FORCED_DETECTION) { /* forced detection */ + len += sprintf(buf + len, + "Adapter category: forced detected\n" "***************************************\n" "*** Forced detected SCSI Adapter ***\n" "*** No chip-information available ***\n" "***************************************\n"); + } else if (speciale == INTEGRATED_SCSI) { + /* if the integrated subsystem has been found automatically: */ + len += sprintf(buf + len, + "Adapter category: integrated\n" "Chip revision level: %d\n" "Chip status: %s\n" "8 kByte NVRAM status: %s\n", ((pos[2] & 0xf0) >> 4), (pos[2] & 1) ? "enabled" : "disabled", (pos[2] & 2) ? "locked" : "accessible"); + } else if ((speciale >= 0) && (speciale < (sizeof(subsys_list) / sizeof(struct subsys_list_struct)))) { + /* if the subsystem is a slot adapter */ + len += sprintf(buf + len, "Adapter category: slot-card\n" "ROM Segment Address: "); + if ((pos[2] & 0xf0) == 0xf0) + len += sprintf(buf + len, "off\n"); + else + len += sprintf(buf + len, "0x%x\n", ((pos[2] & 0xf0) << 13) + 0xc0000); + len += sprintf(buf + len, "Chip status: %s\n", (pos[2] & 1) ? "enabled" : "disabled"); + len += sprintf(buf + len, "Adapter I/O Offset: 0x%x\n", ((pos[2] & 0x0e) << 2)); + } else { + len += sprintf(buf + len, "Adapter category: unknown\n"); + } + /* common subsystem information to write to the slotn file */ + len += sprintf(buf + len, "Subsystem PUN: %d\n", shpnt->this_id); + len += sprintf(buf + len, "I/O base address range: 0x%x-0x%x\n", (unsigned int) (shpnt->io_port), (unsigned int) (shpnt->io_port + 7)); + len += sprintf(buf + len, "MCA-slot size: %d bits", connectore); + /* Now make sure, the bufferlength is devidable by 4 to avoid + * paging problems of the buffer. */ + while (len % sizeof(int) != (sizeof(int) - 1)) + len += sprintf(buf + len, " "); + len += sprintf(buf + len, "\n"); + + spin_unlock_irqrestore(shpnt->host_lock, flags); + + return len; +} + +int ibmmca_detect(Scsi_Host_Template * scsi_template) +{ + struct Scsi_Host *shpnt; + int port, id, i, j, k, list_size, slot; + int devices_on_irq_11 = 0; + int devices_on_irq_14 = 0; + int IRQ14_registered = 0; + int IRQ11_registered = 0; + + found = 0; /* make absolutely sure, that found is set to 0 */ + + /* First of all, print the version number of the driver. This is + * important to allow better user bugreports in case of already + * having problems with the MCA_bus probing. */ + printk(KERN_INFO "IBM MCA SCSI: Version %s\n", IBMMCA_SCSI_DRIVER_VERSION); + /* if this is not MCA machine, return "nothing found" */ + if (!MCA_bus) { + printk(KERN_INFO "IBM MCA SCSI: No Microchannel-bus present --> Aborting.\n" " This machine does not have any IBM MCA-bus\n" " or the MCA-Kernel-support is not enabled!\n"); + return 0; + } #ifdef MODULE - /* If the driver is run as module, read from conf.modules or cmd-line */ - if (boot_options) option_setup(boot_options); -#endif + /* If the driver is run as module, read from conf.modules or cmd-line */ + if (boot_options) + option_setup(boot_options); +#endif + + /* get interrupt request level */ + if (request_irq(IM_IRQ, interrupt_handler, SA_SHIRQ, "ibmmcascsi", hosts)) { + printk(KERN_ERR "IBM MCA SCSI: Unable to get shared IRQ %d.\n", IM_IRQ); + return 0; + } else + IRQ14_registered++; + + /* if ibmmcascsi setup option was passed to kernel, return "found" */ + for (i = 0; i < IM_MAX_HOSTS; i++) + if (io_port[i] > 0 && scsi_id[i] >= 0 && scsi_id[i] < 8) { + printk("IBM MCA SCSI: forced detected SCSI Adapter, io=0x%x, scsi id=%d.\n", io_port[i], scsi_id[i]); + if ((shpnt = ibmmca_register(scsi_template, io_port[i], scsi_id[i], FORCED_DETECTION, "forced detected SCSI Adapter"))) { + for (k = 2; k < 7; k++) + ((struct ibmmca_hostdata *) shpnt->hostdata)->_pos[k] = 0; + ((struct ibmmca_hostdata *) shpnt->hostdata)->_special = FORCED_DETECTION; + mca_set_adapter_name(MCA_INTEGSCSI, "forced detected SCSI Adapter"); + mca_set_adapter_procfn(MCA_INTEGSCSI, (MCA_ProcFn) ibmmca_getinfo, shpnt); + mca_mark_as_used(MCA_INTEGSCSI); + devices_on_irq_14++; + } + } + if (found) + return found; + + /* The POS2-register of all PS/2 model SCSI-subsystems has the following + * interpretation of bits: + * Bit 7 - 4 : Chip Revision ID (Release) + * Bit 3 - 2 : Reserved + * Bit 1 : 8k NVRAM Disabled + * Bit 0 : Chip Enable (EN-Signal) + * The POS3-register is interpreted as follows: + * Bit 7 - 5 : SCSI ID + * Bit 4 : Reserved = 0 + * Bit 3 - 0 : Reserved = 0 + * (taken from "IBM, PS/2 Hardware Interface Technical Reference, Common + * Interfaces (1991)"). + * In short words, this means, that IBM PS/2 machines only support + * 1 single subsystem by default. The slot-adapters must have another + * configuration on pos2. Here, one has to assume the following + * things for POS2-register: + * Bit 7 - 4 : Chip Revision ID (Release) + * Bit 3 - 1 : port offset factor + * Bit 0 : Chip Enable (EN-Signal) + * As I found a patch here, setting the IO-registers to 0x3540 forced, + * as there was a 0x05 in POS2 on a model 56, I assume, that the + * port 0x3540 must be fix for integrated SCSI-controllers. + * Ok, this discovery leads to the following implementation: (M.Lang) */ + + /* first look for the IBM SCSI integrated subsystem on the motherboard */ + for (j = 0; j < 8; j++) /* read the pos-information */ + pos[j] = mca_read_stored_pos(MCA_INTEGSCSI, j); + /* pos2 = pos3 = 0xff if there is no integrated SCSI-subsystem present, but + * if we ignore the settings of all surrounding pos registers, it is not + * completely sufficient to only check pos2 and pos3. */ + /* Therefore, now the following if statement is used to + * make sure, we see a real integrated onboard SCSI-interface and no + * internal system information, which gets mapped to some pos registers + * on models 95xx. */ + if ((!pos[0] && !pos[1] && pos[2] > 0 && pos[3] > 0 && !pos[4] && !pos[5] && !pos[6] && !pos[7]) || (pos[0] == 0xff && pos[1] == 0xff && pos[2] < 0xff && pos[3] < 0xff && pos[4] == 0xff && pos[5] == 0xff && pos[6] == 0xff && pos[7] == 0xff)) { + if ((pos[2] & 1) == 1) /* is the subsystem chip enabled ? */ + port = IM_IO_PORT; + else { /* if disabled, no IRQs will be generated, as the chip won't + * listen to the incoming commands and will do really nothing, + * except for listening to the pos-register settings. If this + * happens, I need to hugely think about it, as one has to + * write something to the MCA-Bus pos register in order to + * enable the chip. Normally, IBM-SCSI won't pass the POST, + * when the chip is disabled (see IBM tech. ref.). */ + port = IM_IO_PORT; /* anyway, set the portnumber and warn */ + printk("IBM MCA SCSI: WARNING - Your SCSI-subsystem is disabled!\n" " SCSI-operations may not work.\n"); + } + id = (pos[3] & 0xe0) >> 5; /* this is correct and represents the PUN */ + /* give detailed information on the subsystem. This helps me + * additionally during debugging and analyzing bug-reports. */ + printk(KERN_INFO "IBM MCA SCSI: IBM Integrated SCSI Controller ffound, io=0x%x, scsi id=%d,\n", port, id); + printk(KERN_INFO " chip rev.=%d, 8K NVRAM=%s, subsystem=%s\n", ((pos[2] & 0xf0) >> 4), (pos[2] & 2) ? "locked" : "accessible", (pos[2] & 1) ? "enabled." : "disabled."); + + /* register the found integrated SCSI-subsystem */ + if ((shpnt = ibmmca_register(scsi_template, port, id, INTEGRATED_SCSI, "IBM Integrated SCSI Controller"))) + { + for (k = 2; k < 7; k++) + ((struct ibmmca_hostdata *) shpnt->hostdata)->_pos[k] = pos[k]; + ((struct ibmmca_hostdata *) shpnt->hostdata)->_special = INTEGRATED_SCSI; + mca_set_adapter_name(MCA_INTEGSCSI, "IBM Integrated SCSI Controller"); + mca_set_adapter_procfn(MCA_INTEGSCSI, (MCA_ProcFn) ibmmca_getinfo, shpnt); + mca_mark_as_used(MCA_INTEGSCSI); + devices_on_irq_14++; + } + } + + /* now look for other adapters in MCA slots, */ + /* determine the number of known IBM-SCSI-subsystem types */ + /* see the pos[2] dependence to get the adapter port-offset. */ + list_size = sizeof(subsys_list) / sizeof(struct subsys_list_struct); + for (i = 0; i < list_size; i++) { + /* scan each slot for a fitting adapter id */ + slot = 0; /* start at slot 0 */ + while ((slot = mca_find_adapter(subsys_list[i].mca_id, slot)) + != MCA_NOTFOUND) { /* scan through all slots */ + for (j = 0; j < 8; j++) /* read the pos-information */ + pos[j] = mca_read_stored_pos(slot, j); + if ((pos[2] & 1) == 1) + /* is the subsystem chip enabled ? */ + /* (explanations see above) */ + port = IM_IO_PORT + ((pos[2] & 0x0e) << 2); + else { + /* anyway, set the portnumber and warn */ + port = IM_IO_PORT + ((pos[2] & 0x0e) << 2); + printk(KERN_WARNING "IBM MCA SCSI: WARNING - Your SCSI-subsystem is disabled!\n"); + printk(KERN_WARNING " SCSI-operations may not work.\n"); + } + if ((i == IBM_SCSI2_FW) && (pos[6] != 0)) { + printk(KERN_ERR "IBM MCA SCSI: ERROR - Wrong POS(6)-register setting!\n"); + printk(KERN_ERR " Impossible to determine adapter PUN!\n"); + printk(KERN_ERR " Guessing adapter PUN = 7.\n"); + id = 7; + } else { + id = (pos[3] & 0xe0) >> 5; /* get subsystem PUN */ + if (i == IBM_SCSI2_FW) { + id |= (pos[3] & 0x10) >> 1; /* get subsystem PUN high-bit + * for F/W adapters */ + } + } + if ((i == IBM_SCSI2_FW) && (pos[4] & 0x01) && (pos[6] == 0)) { + /* IRQ11 is used by SCSI-2 F/W Adapter/A */ + printk(KERN_DEBUG "IBM MCA SCSI: SCSI-2 F/W adapter needs IRQ 11.\n"); + /* get interrupt request level */ + if (request_irq(IM_IRQ_FW, interrupt_handler, SA_SHIRQ, "ibmmcascsi", hosts)) { + printk(KERN_ERR "IBM MCA SCSI: Unable to get shared IRQ %d.\n", IM_IRQ_FW); + } else + IRQ11_registered++; + } + printk(KERN_INFO "IBM MCA SCSI: %s found in slot %d, io=0x%x, scsi id=%d,\n", subsys_list[i].description, slot + 1, port, id); + if ((pos[2] & 0xf0) == 0xf0) + printk(KERN_DEBUG" ROM Addr.=off,"); + else + printk(KERN_DEBUG " ROM Addr.=0x%x,", ((pos[2] & 0xf0) << 13) + 0xc0000); + printk(KERN_DEBUG " port-offset=0x%x, subsystem=%s\n", ((pos[2] & 0x0e) << 2), (pos[2] & 1) ? "enabled." : "disabled."); + + /* register the hostadapter */ + if ((shpnt = ibmmca_register(scsi_template, port, id, i, subsys_list[i].description))) { + for (k = 2; k < 8; k++) + ((struct ibmmca_hostdata *) shpnt->hostdata)->_pos[k] = pos[k]; + ((struct ibmmca_hostdata *) shpnt->hostdata)->_special = i; + mca_set_adapter_name(slot, subsys_list[i].description); + mca_set_adapter_procfn(slot, (MCA_ProcFn) ibmmca_getinfo, shpnt); + mca_mark_as_used(slot); + if ((i == IBM_SCSI2_FW) && (pos[4] & 0x01) && (pos[6] == 0)) + devices_on_irq_11++; + else + devices_on_irq_14++; + } + slot++; /* advance to next slot */ + } /* advance to next adapter id in the list of IBM-SCSI-subsystems */ + } + + /* now check for SCSI-adapters, mapped to the integrated SCSI + * area. E.g. a W/Cache in MCA-slot 9(!). Do the check correct here, + * as this is a known effect on some models 95xx. */ + list_size = sizeof(subsys_list) / sizeof(struct subsys_list_struct); + for (i = 0; i < list_size; i++) { + /* scan each slot for a fitting adapter id */ + slot = mca_find_adapter(subsys_list[i].mca_id, MCA_INTEGSCSI); + if (slot != MCA_NOTFOUND) { /* scan through all slots */ + for (j = 0; j < 8; j++) /* read the pos-information */ + pos[j] = mca_read_stored_pos(slot, j); + if ((pos[2] & 1) == 1) { /* is the subsystem chip enabled ? */ + /* (explanations see above) */ + port = IM_IO_PORT + ((pos[2] & 0x0e) << 2); + } else { /* anyway, set the portnumber and warn */ + port = IM_IO_PORT + ((pos[2] & 0x0e) << 2); + printk(KERN_WARNING "IBM MCA SCSI: WARNING - Your SCSI-subsystem is disabled!\n"); + printk(KERN_WARNING " SCSI-operations may not work.\n"); + } + if ((i == IBM_SCSI2_FW) && (pos[6] != 0)) { + printk(KERN_ERR "IBM MCA SCSI: ERROR - Wrong POS(6)-register setting!\n"); + printk(KERN_ERR " Impossible to determine adapter PUN!\n"); + printk(KERN_ERR " Guessing adapter PUN = 7.\n"); + id = 7; + } else { + id = (pos[3] & 0xe0) >> 5; /* get subsystem PUN */ + if (i == IBM_SCSI2_FW) + id |= (pos[3] & 0x10) >> 1; /* get subsystem PUN high-bit + * for F/W adapters */ + } + if ((i == IBM_SCSI2_FW) && (pos[4] & 0x01) && (pos[6] == 0)) { + /* IRQ11 is used by SCSI-2 F/W Adapter/A */ + printk(KERN_DEBUG "IBM MCA SCSI: SCSI-2 F/W adapter needs IRQ 11.\n"); + /* get interrupt request level */ + if (request_irq(IM_IRQ_FW, interrupt_handler, SA_SHIRQ, "ibmmcascsi", hosts)) + printk(KERN_ERR "IBM MCA SCSI: Unable to get shared IRQ %d.\n", IM_IRQ_FW); + else + IRQ11_registered++; + } + printk(KERN_INFO "IBM MCA SCSI: %s found in slot %d, io=0x%x, scsi id=%d,\n", subsys_list[i].description, slot + 1, port, id); + if ((pos[2] & 0xf0) == 0xf0) + printk(KERN_DEBUG " ROM Addr.=off,"); + else + printk(KERN_DEBUG " ROM Addr.=0x%x,", ((pos[2] & 0xf0) << 13) + 0xc0000); + printk(KERN_DEBUG " port-offset=0x%x, subsystem=%s\n", ((pos[2] & 0x0e) << 2), (pos[2] & 1) ? "enabled." : "disabled."); + + /* register the hostadapter */ + if ((shpnt = ibmmca_register(scsi_template, port, id, i, subsys_list[i].description))) { + for (k = 2; k < 7; k++) + ((struct ibmmca_hostdata *) shpnt->hostdata)->_pos[k] = pos[k]; + ((struct ibmmca_hostdata *) shpnt->hostdata)->_special = i; + mca_set_adapter_name(slot, subsys_list[i].description); + mca_set_adapter_procfn(slot, (MCA_ProcFn) ibmmca_getinfo, shpnt); + mca_mark_as_used(slot); + if ((i == IBM_SCSI2_FW) && (pos[4] & 0x01) && (pos[6] == 0)) + devices_on_irq_11++; + else + devices_on_irq_14++; + } + slot++; /* advance to next slot */ + } /* advance to next adapter id in the list of IBM-SCSI-subsystems */ + } + if (IRQ11_registered && !devices_on_irq_11) + free_irq(IM_IRQ_FW, hosts); /* no devices on IRQ 11 */ + if (IRQ14_registered && !devices_on_irq_14) + free_irq(IM_IRQ, hosts); /* no devices on IRQ 14 */ + if (!devices_on_irq_11 && !devices_on_irq_14) + printk(KERN_WARNING "IBM MCA SCSI: No IBM SCSI-subsystem adapter attached.\n"); + return found; /* return the number of found SCSI hosts. Should be 1 or 0. */ +} + +static struct Scsi_Host *ibmmca_register(Scsi_Host_Template * scsi_template, int port, int id, int adaptertype, char *hostname) +{ + struct Scsi_Host *shpnt; + int i, j; + unsigned int ctrl; + + /* check I/O region */ + if (!request_region(port, IM_N_IO_PORT, hostname)) { + printk(KERN_ERR "IBM MCA SCSI: Unable to get I/O region 0x%x-0x%x (%d ports).\n", port, port + IM_N_IO_PORT - 1, IM_N_IO_PORT); + return NULL; + } + + /* register host */ + shpnt = scsi_register(scsi_template, sizeof(struct ibmmca_hostdata)); + if (!shpnt) { + printk(KERN_ERR "IBM MCA SCSI: Unable to register host.\n"); + release_region(port, IM_N_IO_PORT); + return NULL; + } - /* get interrupt request level */ - if (request_irq (IM_IRQ, interrupt_handler, SA_SHIRQ, "ibmmcascsi", - hosts)) { - printk("IBM MCA SCSI: Unable to get shared IRQ %d.\n", IM_IRQ); - return 0; - } else - IRQ14_registered++; - - /* if ibmmcascsi setup option was passed to kernel, return "found" */ - for (i = 0; i < IM_MAX_HOSTS; i++) - if (io_port[i] > 0 && scsi_id[i] >= 0 && scsi_id[i] < 8) { - printk("IBM MCA SCSI: forced detected SCSI Adapter, io=0x%x, scsi id=%d.\n", - io_port[i], scsi_id[i]); - if ((shpnt = ibmmca_register(scsi_template, io_port[i], scsi_id[i], - FORCED_DETECTION, "forced detected SCSI Adapter"))) { - for (k=2;k<7;k++) - ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos[k] = 0; - ((struct ibmmca_hostdata *)shpnt->hostdata)->_special = FORCED_DETECTION; - mca_set_adapter_name(MCA_INTEGSCSI, "forced detected SCSI Adapter"); - mca_set_adapter_procfn(MCA_INTEGSCSI, (MCA_ProcFn) ibmmca_getinfo, - shpnt); - mca_mark_as_used(MCA_INTEGSCSI); - devices_on_irq_14++; - } - } - if (found) return found; - - /* The POS2-register of all PS/2 model SCSI-subsystems has the following - * interpretation of bits: - * Bit 7 - 4 : Chip Revision ID (Release) - * Bit 3 - 2 : Reserved - * Bit 1 : 8k NVRAM Disabled - * Bit 0 : Chip Enable (EN-Signal) - * The POS3-register is interpreted as follows: - * Bit 7 - 5 : SCSI ID - * Bit 4 : Reserved = 0 - * Bit 3 - 0 : Reserved = 0 - * (taken from "IBM, PS/2 Hardware Interface Technical Reference, Common - * Interfaces (1991)"). - * In short words, this means, that IBM PS/2 machines only support - * 1 single subsystem by default. The slot-adapters must have another - * configuration on pos2. Here, one has to assume the following - * things for POS2-register: - * Bit 7 - 4 : Chip Revision ID (Release) - * Bit 3 - 1 : port offset factor - * Bit 0 : Chip Enable (EN-Signal) - * As I found a patch here, setting the IO-registers to 0x3540 forced, - * as there was a 0x05 in POS2 on a model 56, I assume, that the - * port 0x3540 must be fix for integrated SCSI-controllers. - * Ok, this discovery leads to the following implementation: (M.Lang) */ - - /* first look for the IBM SCSI integrated subsystem on the motherboard */ - for (j=0;j<8;j++) /* read the pos-information */ - pos[j] = mca_read_stored_pos(MCA_INTEGSCSI,j); - /* pos2 = pos3 = 0xff if there is no integrated SCSI-subsystem present, but - * if we ignore the settings of all surrounding pos registers, it is not - * completely sufficient to only check pos2 and pos3. */ - /* Therefore, now the following if statement is used to - * make sure, we see a real integrated onboard SCSI-interface and no - * internal system information, which gets mapped to some pos registers - * on models 95xx. */ - if ((!pos[0] && !pos[1] && pos[2]>0 && pos[3]>0 && !pos[4] && !pos[5] && !pos[6] && !pos[7]) || - (pos[0]==0xff && pos[1]==0xff && pos[2]<0xff && pos[3]<0xff && pos[4]==0xff && pos[5]==0xff && pos[6]==0xff && pos[7]==0xff)) { - if ((pos[2] & 1) == 1) /* is the subsystem chip enabled ? */ - port = IM_IO_PORT; - else { /* if disabled, no IRQs will be generated, as the chip won't - * listen to the incoming commands and will do really nothing, - * except for listening to the pos-register settings. If this - * happens, I need to hugely think about it, as one has to - * write something to the MCA-Bus pos register in order to - * enable the chip. Normally, IBM-SCSI won't pass the POST, - * when the chip is disabled (see IBM tech. ref.). */ - port = IM_IO_PORT; /* anyway, set the portnumber and warn */ - printk("IBM MCA SCSI: WARNING - Your SCSI-subsystem is disabled!\n" - " SCSI-operations may not work.\n"); - } - id = (pos[3] & 0xe0) >> 5; /* this is correct and represents the PUN */ - /* give detailed information on the subsystem. This helps me - * additionally during debugging and analyzing bug-reports. */ - printk("IBM MCA SCSI: IBM Integrated SCSI Controller found, io=0x%x, scsi id=%d,\n" - " chip rev.=%d, 8K NVRAM=%s, subsystem=%s\n", - port, id, - ((pos[2] & 0xf0) >> 4), (pos[2] & 2) ? "locked" : "accessible", - (pos[2] & 1) ? "enabled." : "disabled."); - - /* register the found integrated SCSI-subsystem */ - if ((shpnt = ibmmca_register(scsi_template, port, id, INTEGRATED_SCSI, - "IBM Integrated SCSI Controller"))) { - for (k=2;k<7;k++) - ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos[k] = pos[k]; - ((struct ibmmca_hostdata *)shpnt->hostdata)->_special = INTEGRATED_SCSI; - mca_set_adapter_name(MCA_INTEGSCSI, "IBM Integrated SCSI Controller"); - mca_set_adapter_procfn(MCA_INTEGSCSI, (MCA_ProcFn) ibmmca_getinfo, - shpnt); - mca_mark_as_used(MCA_INTEGSCSI); - devices_on_irq_14++; - } - } - - /* now look for other adapters in MCA slots, */ - /* determine the number of known IBM-SCSI-subsystem types */ - /* see the pos[2] dependence to get the adapter port-offset. */ - list_size = sizeof(subsys_list) / sizeof(struct subsys_list_struct); - for (i = 0; i < list_size; i++) { - /* scan each slot for a fitting adapter id */ - slot = 0; /* start at slot 0 */ - while ((slot = mca_find_adapter(subsys_list[i].mca_id, slot)) - != MCA_NOTFOUND) { /* scan through all slots */ - for (j=0;j<8;j++) /* read the pos-information */ - pos[j] = mca_read_stored_pos(slot, j); - if ((pos[2] & 1) == 1) /* is the subsystem chip enabled ? */ - /* (explanations see above) */ - port = IM_IO_PORT + ((pos[2] & 0x0e) << 2); - else { - /* anyway, set the portnumber and warn */ - port = IM_IO_PORT + ((pos[2] & 0x0e) << 2); - printk("IBM MCA SCSI: WARNING - Your SCSI-subsystem is disabled!\n" - " SCSI-operations may not work.\n"); - } - if ((i==IBM_SCSI2_FW)&&(pos[6]!=0)) { - printk("IBM MCA SCSI: ERROR - Wrong POS(6)-register setting!\n" - " Impossible to determine adapter PUN!\n" - " Guessing adapter PUN = 7.\n"); - id = 7; - } else { - id = (pos[3] & 0xe0) >> 5; /* get subsystem PUN */ - if (i==IBM_SCSI2_FW) { - id |= (pos[3] & 0x10) >> 1; /* get subsystem PUN high-bit - * for F/W adapters */ - } - } - if ((i==IBM_SCSI2_FW)&&(pos[4] & 0x01)&&(pos[6]==0)) { - /* IRQ11 is used by SCSI-2 F/W Adapter/A */ - printk("IBM MCA SCSI: SCSI-2 F/W adapter needs IRQ 11.\n"); - /* get interrupt request level */ - if (request_irq (IM_IRQ_FW, interrupt_handler, SA_SHIRQ, - "ibmmcascsi", hosts)) { - printk("IBM MCA SCSI: Unable to get shared IRQ %d.\n", - IM_IRQ_FW); - } else - IRQ11_registered++; - } - printk("IBM MCA SCSI: %s found in slot %d, io=0x%x, scsi id=%d,\n", - subsys_list[i].description, slot + 1, port, id); - if ((pos[2] & 0xf0) == 0xf0) - printk(" ROM Addr.=off,"); - else - printk(" ROM Addr.=0x%x,", - ((pos[2] & 0xf0) << 13) + 0xc0000); - printk(" port-offset=0x%x, subsystem=%s\n", - ((pos[2] & 0x0e) << 2), - (pos[2] & 1) ? "enabled." : "disabled."); - - /* register the hostadapter */ - if ((shpnt = ibmmca_register(scsi_template, port, id, i, - subsys_list[i].description))) { - for (k=2;k<8;k++) - ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos[k] = pos[k]; - ((struct ibmmca_hostdata *)shpnt->hostdata)->_special = i; - mca_set_adapter_name (slot, subsys_list[i].description); - mca_set_adapter_procfn (slot, (MCA_ProcFn) ibmmca_getinfo, - shpnt); - mca_mark_as_used(slot); - if ((i==IBM_SCSI2_FW)&&(pos[4] & 0x01)&&(pos[6]==0)) - devices_on_irq_11++; - else - devices_on_irq_14++; - } - slot++; /* advance to next slot */ - } /* advance to next adapter id in the list of IBM-SCSI-subsystems*/ - } - - /* now check for SCSI-adapters, mapped to the integrated SCSI - * area. E.g. a W/Cache in MCA-slot 9(!). Do the check correct here, - * as this is a known effect on some models 95xx. */ - list_size = sizeof(subsys_list) / sizeof(struct subsys_list_struct); - for (i = 0; i < list_size; i++) { - /* scan each slot for a fitting adapter id */ - slot = mca_find_adapter(subsys_list[i].mca_id, MCA_INTEGSCSI); - if (slot != MCA_NOTFOUND) { /* scan through all slots */ - for (j=0;j<8;j++) /* read the pos-information */ - pos[j] = mca_read_stored_pos(slot, j); - if ((pos[2] & 1) == 1) { /* is the subsystem chip enabled ? */ - /* (explanations see above) */ - port = IM_IO_PORT + ((pos[2] & 0x0e) << 2); - } else { /* anyway, set the portnumber and warn */ - port = IM_IO_PORT + ((pos[2] & 0x0e) << 2); - printk("IBM MCA SCSI: WARNING - Your SCSI-subsystem is disabled!\n" - " SCSI-operations may not work.\n"); - } - if ((i==IBM_SCSI2_FW)&&(pos[6]!=0)) { - printk("IBM MCA SCSI: ERROR - Wrong POS(6)-register setting!\n" - " Impossible to determine adapter PUN!\n" - " Guessing adapter PUN = 7.\n"); - id = 7; - } else { - id = (pos[3] & 0xe0) >> 5; /* get subsystem PUN */ - if (i==IBM_SCSI2_FW) - id |= (pos[3] & 0x10) >> 1; /* get subsystem PUN high-bit - * for F/W adapters */ - } - if ((i==IBM_SCSI2_FW)&&(pos[4] & 0x01)&&(pos[6]==0)) { - /* IRQ11 is used by SCSI-2 F/W Adapter/A */ - printk("IBM MCA SCSI: SCSI-2 F/W adapter needs IRQ 11.\n"); - /* get interrupt request level */ - if (request_irq (IM_IRQ_FW, interrupt_handler, SA_SHIRQ, - "ibmmcascsi", hosts)) - printk("IBM MCA SCSI: Unable to get shared IRQ %d.\n", - IM_IRQ_FW); - else - IRQ11_registered++; - } - printk("IBM MCA SCSI: %s found in slot %d, io=0x%x, scsi id=%d,\n", - subsys_list[i].description, slot + 1, port, id); - if ((pos[2] & 0xf0) == 0xf0) - printk(" ROM Addr.=off,"); - else - printk(" ROM Addr.=0x%x,", - ((pos[2] & 0xf0) << 13) + 0xc0000); - printk(" port-offset=0x%x, subsystem=%s\n", - ((pos[2] & 0x0e) << 2), - (pos[2] & 1) ? "enabled." : "disabled."); - - /* register the hostadapter */ - if ((shpnt = ibmmca_register(scsi_template, port, id, i, - subsys_list[i].description))) { - for (k=2;k<7;k++) - ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos[k] = pos[k]; - ((struct ibmmca_hostdata *)shpnt->hostdata)->_special = i; - mca_set_adapter_name (slot, subsys_list[i].description); - mca_set_adapter_procfn (slot, (MCA_ProcFn) ibmmca_getinfo, shpnt); - mca_mark_as_used(slot); - if ((i==IBM_SCSI2_FW)&&(pos[4] & 0x01)&&(pos[6]==0)) - devices_on_irq_11++; - else - devices_on_irq_14++; - } - slot++; /* advance to next slot */ - } /* advance to next adapter id in the list of IBM-SCSI-subsystems*/ - } - if ( IRQ11_registered && !devices_on_irq_11 ) - free_irq(IM_IRQ_FW, hosts); /* no devices on IRQ 11 */ - if ( IRQ14_registered && !devices_on_irq_14 ) - free_irq(IM_IRQ, hosts); /* no devices on IRQ 14 */ - if ( !devices_on_irq_11 && !devices_on_irq_14 ) - printk("IBM MCA SCSI: No IBM SCSI-subsystem adapter attached.\n"); - return found; /* return the number of found SCSI hosts. Should be 1 or 0. */ -} - -static struct Scsi_Host * -ibmmca_register(Scsi_Host_Template * scsi_template, int port, int id, - int adaptertype, char *hostname) -{ - struct Scsi_Host *shpnt; - int i, j; - unsigned int ctrl; - - /* check I/O region */ - if (check_region(port, IM_N_IO_PORT)) { - printk("IBM MCA SCSI: Unable to get I/O region 0x%x-0x%x (%d ports).\n", - port, port + IM_N_IO_PORT - 1, IM_N_IO_PORT); - return NULL; - } - - /* register host */ - shpnt = scsi_register(scsi_template, sizeof(struct ibmmca_hostdata)); - if (!shpnt) { - printk("IBM MCA SCSI: Unable to register host.\n"); - return NULL; - } - - /* request I/O region */ - request_region(port, IM_N_IO_PORT, hostname); - hosts[found] = shpnt; /* add new found hostadapter to the list */ - special(found) = adaptertype; /* important assignment or else crash! */ - subsystem_connector_size(found) = 0; /* preset slot-size */ - shpnt->irq = IM_IRQ; /* assign necessary stuff for the adapter */ - shpnt->io_port = port; - shpnt->n_io_port = IM_N_IO_PORT; - shpnt->this_id = id; - shpnt->max_id = 8; /* 8 PUNs are default */ - /* now, the SCSI-subsystem is connected to Linux */ + /* request I/O region */ + hosts[found] = shpnt; /* add new found hostadapter to the list */ + special(found) = adaptertype; /* important assignment or else crash! */ + subsystem_connector_size(found) = 0; /* preset slot-size */ + shpnt->irq = IM_IRQ; /* assign necessary stuff for the adapter */ + shpnt->io_port = port; + shpnt->n_io_port = IM_N_IO_PORT; + shpnt->this_id = id; + shpnt->max_id = 8; /* 8 PUNs are default */ + /* now, the SCSI-subsystem is connected to Linux */ - ctrl = (unsigned int)(inb(IM_CTR_REG(found))); /* get control-register status */ + ctrl = (unsigned int) (inb(IM_CTR_REG(found))); /* get control-register status */ #ifdef IM_DEBUG_PROBE - printk("IBM MCA SCSI: Control Register contents: %x, status: %x\n", - ctrl,inb(IM_STAT_REG(found))); - printk("IBM MCA SCSI: This adapters' POS-registers: "); - for (i=0;i<8;i++) - printk("%x ",pos[i]); - printk("\n"); -#endif - reset_status(found) = IM_RESET_NOT_IN_PROGRESS; - - for (i = 0; i < 16; i++) /* reset the tables */ - for (j = 0; j < 8; j++) - get_ldn(found)[i][j] = MAX_LOG_DEV; - - /* check which logical devices exist */ - /* after this line, local interrupting is possible: */ - local_checking_phase_flag(found) = 1; - check_devices(found,adaptertype); /* call by value, using the global variable hosts*/ - local_checking_phase_flag(found) = 0; - found++; /* now increase index to be prepared for next found subsystem */ - /* an ibm mca subsystem has been detected */ - return shpnt; -} - -int ibmmca_command (Scsi_Cmnd * cmd) -{ - ibmmca_queuecommand (cmd, internal_done); - cmd->SCp.Status = 0; - while (!cmd->SCp.Status) barrier (); - return cmd->result; -} - -int ibmmca_release(struct Scsi_Host *shpnt) -{ - release_region(shpnt->io_port, shpnt->n_io_port); - if (!(--found)) free_irq(shpnt->irq, hosts); - return 0; + printk("IBM MCA SCSI: Control Register contents: %x, status: %x\n", ctrl, inb(IM_STAT_REG(found))); + printk("IBM MCA SCSI: This adapters' POS-registers: "); + for (i = 0; i < 8; i++) + printk("%x ", pos[i]); + printk("\n"); +#endif + reset_status(found) = IM_RESET_NOT_IN_PROGRESS; + + for (i = 0; i < 16; i++) /* reset the tables */ + for (j = 0; j < 8; j++) + get_ldn(found)[i][j] = MAX_LOG_DEV; + + /* check which logical devices exist */ + /* after this line, local interrupting is possible: */ + local_checking_phase_flag(found) = 1; + check_devices(found, adaptertype); /* call by value, using the global variable hosts */ + local_checking_phase_flag(found) = 0; + found++; /* now increase index to be prepared for next found subsystem */ + /* an ibm mca subsystem has been detected */ + return shpnt; +} + +static int ibmmca_command(Scsi_Cmnd * cmd) +{ + ibmmca_queuecommand(cmd, internal_done); + cmd->SCp.Status = 0; + while (!cmd->SCp.Status) + barrier(); + return cmd->result; +} + +static int ibmmca_release(struct Scsi_Host *shpnt) +{ + release_region(shpnt->io_port, shpnt->n_io_port); + if (!(--found)) + free_irq(shpnt->irq, hosts); + return 0; } /* The following routine is the SCSI command queue for the midlevel driver */ -int ibmmca_queuecommand (Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) +static int ibmmca_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) { - unsigned int ldn; - unsigned int scsi_cmd; - struct im_scb *scb; - struct Scsi_Host *shpnt; - int current_ldn; - int id,lun; - int target; - int host_index; - int max_pun; - int i; - struct scatterlist *sl; - - shpnt = cmd->host; - /* search for the right hostadapter */ - for (host_index = 0; hosts[host_index] && hosts[host_index]->host_no != shpnt->host_no; host_index++); - - if (!hosts[host_index]) { /* invalid hostadapter descriptor address */ - cmd->result = DID_NO_CONNECT << 16; - if (done) done (cmd); - return 0; - } - max_pun = subsystem_maxid(host_index); - if (ibm_ansi_order) { - target = max_pun - 1 - cmd->target; - if ((target <= subsystem_pun(host_index))&&(cmd->target <= subsystem_pun(host_index))) - target--; - else if ((target >= subsystem_pun(host_index))&&(cmd->target >= subsystem_pun(host_index))) - target++; - } else - target = cmd->target; - - /* if (target,lun) is NO LUN or not existing at all, return error */ - if ((get_scsi(host_index)[target][cmd->lun] == TYPE_NO_LUN)|| - (get_scsi(host_index)[target][cmd->lun] == TYPE_NO_DEVICE)) { - cmd->result = DID_NO_CONNECT << 16; - if (done) done (cmd); - return 0; - } - - /*if (target,lun) unassigned, do further checks... */ - ldn = get_ldn(host_index)[target][cmd->lun]; - if (ldn >= MAX_LOG_DEV) { /* on invalid ldn do special stuff */ - if (ldn > MAX_LOG_DEV) { /* dynamical remapping if ldn unassigned */ - current_ldn = next_ldn(host_index); /* stop-value for one circle */ - while (ld(host_index)[next_ldn(host_index)].cmd) { /* search for a occupied, but not in */ - /* command-processing ldn. */ - next_ldn(host_index)++; - if (next_ldn(host_index)>=MAX_LOG_DEV) - next_ldn(host_index) = 7; - if (current_ldn == next_ldn(host_index)) { /* One circle done ? */ - /* no non-processing ldn found */ - printk("IBM MCA SCSI: Cannot assign SCSI-device dynamically!\n" \ - " On ldn 7-14 SCSI-commands everywhere in progress.\n" \ - " Reporting DID_NO_CONNECT for device (%d,%d).\n", - target, cmd->lun); - cmd->result = DID_NO_CONNECT << 16;/* return no connect*/ - if (done) done (cmd); - return 0; - } - } - - /* unmap non-processing ldn */ - for (id=0; idlun] = next_ldn(host_index); - /* change ldn to the right value, that is now next_ldn */ - ldn = next_ldn(host_index); - /* unassign all ldns (pun,lun,ldn does not matter for remove) */ - immediate_assign(host_index,0,0,0,REMOVE_LDN); - /* set only LDN for remapped device */ - immediate_assign(host_index,target,cmd->lun,ldn,SET_LDN); - /* get device information for ld[ldn] */ - if (device_exists (host_index, ldn, - &ld(host_index)[ldn].block_length, - &ld(host_index)[ldn].device_type)) { - ld(host_index)[ldn].cmd = NULL; /* To prevent panic set 0, because - devices that were not assigned, - should have nothing in progress. */ - get_scsi(host_index)[target][cmd->lun] = ld(host_index)[ldn].device_type; - /* increase assignment counters for statistics in /proc */ - IBM_DS(host_index).dynamical_assignments++; - IBM_DS(host_index).ldn_assignments[ldn]++; - } else - /* panic here, because a device, found at boottime has - vanished */ - panic("IBM MCA SCSI: ldn=0x%x, SCSI-device on (%d,%d) vanished!\n", - ldn, target, cmd->lun); - /* unassign again all ldns (pun,lun,ldn does not matter for remove) */ - immediate_assign(host_index,0,0,0,REMOVE_LDN); - /* remap all ldns, as written in the pun/lun table */ - lun=0; + unsigned int ldn; + unsigned int scsi_cmd; + struct im_scb *scb; + struct Scsi_Host *shpnt; + int current_ldn; + int id, lun; + int target; + int host_index; + int max_pun; + int i; + struct scatterlist *sl; + + shpnt = cmd->host; + /* search for the right hostadapter */ + for (host_index = 0; hosts[host_index] && hosts[host_index]->host_no != shpnt->host_no; host_index++); + + if (!hosts[host_index]) { /* invalid hostadapter descriptor address */ + cmd->result = DID_NO_CONNECT << 16; + if (done) + done(cmd); + return 0; + } + max_pun = subsystem_maxid(host_index); + if (ibm_ansi_order) { + target = max_pun - 1 - cmd->target; + if ((target <= subsystem_pun(host_index)) && (cmd->target <= subsystem_pun(host_index))) + target--; + else if ((target >= subsystem_pun(host_index)) && (cmd->target >= subsystem_pun(host_index))) + target++; + } else + target = cmd->target; + + /* if (target,lun) is NO LUN or not existing at all, return error */ + if ((get_scsi(host_index)[target][cmd->lun] == TYPE_NO_LUN) || (get_scsi(host_index)[target][cmd->lun] == TYPE_NO_DEVICE)) { + cmd->result = DID_NO_CONNECT << 16; + if (done) + done(cmd); + return 0; + } + + /*if (target,lun) unassigned, do further checks... */ + ldn = get_ldn(host_index)[target][cmd->lun]; + if (ldn >= MAX_LOG_DEV) { /* on invalid ldn do special stuff */ + if (ldn > MAX_LOG_DEV) { /* dynamical remapping if ldn unassigned */ + current_ldn = next_ldn(host_index); /* stop-value for one circle */ + while (ld(host_index)[next_ldn(host_index)].cmd) { /* search for a occupied, but not in */ + /* command-processing ldn. */ + next_ldn(host_index)++; + if (next_ldn(host_index) >= MAX_LOG_DEV) + next_ldn(host_index) = 7; + if (current_ldn == next_ldn(host_index)) { /* One circle done ? */ + /* no non-processing ldn found */ + printk("IBM MCA SCSI: Cannot assign SCSI-device dynamically!\n" " On ldn 7-14 SCSI-commands everywhere in progress.\n" " Reporting DID_NO_CONNECT for device (%d,%d).\n", target, cmd->lun); + cmd->result = DID_NO_CONNECT << 16; /* return no connect */ + if (done) + done(cmd); + return 0; + } + } + + /* unmap non-processing ldn */ + for (id = 0; id < max_pun; id++) + for (lun = 0; lun < 8; lun++) { + if (get_ldn(host_index)[id][lun] == next_ldn(host_index)) { + get_ldn(host_index)[id][lun] = TYPE_NO_DEVICE; + get_scsi(host_index)[id][lun] = TYPE_NO_DEVICE; + /* unmap entry */ + } + } + /* set reduced interrupt_handler-mode for checking */ + local_checking_phase_flag(host_index) = 1; + /* map found ldn to pun,lun */ + get_ldn(host_index)[target][cmd->lun] = next_ldn(host_index); + /* change ldn to the right value, that is now next_ldn */ + ldn = next_ldn(host_index); + /* unassign all ldns (pun,lun,ldn does not matter for remove) */ + immediate_assign(host_index, 0, 0, 0, REMOVE_LDN); + /* set only LDN for remapped device */ + immediate_assign(host_index, target, cmd->lun, ldn, SET_LDN); + /* get device information for ld[ldn] */ + if (device_exists(host_index, ldn, &ld(host_index)[ldn].block_length, &ld(host_index)[ldn].device_type)) { + ld(host_index)[ldn].cmd = NULL; /* To prevent panic set 0, because + devices that were not assigned, + should have nothing in progress. */ + get_scsi(host_index)[target][cmd->lun] = ld(host_index)[ldn].device_type; + /* increase assignment counters for statistics in /proc */ + IBM_DS(host_index).dynamical_assignments++; + IBM_DS(host_index).ldn_assignments[ldn]++; + } else + /* panic here, because a device, found at boottime has + vanished */ + panic("IBM MCA SCSI: ldn=0x%x, SCSI-device on (%d,%d) vanished!\n", ldn, target, cmd->lun); + /* unassign again all ldns (pun,lun,ldn does not matter for remove) */ + immediate_assign(host_index, 0, 0, 0, REMOVE_LDN); + /* remap all ldns, as written in the pun/lun table */ + lun = 0; #ifdef CONFIG_SCSI_MULTI_LUN - for (lun=0; lun<8; lun++) + for (lun = 0; lun < 8; lun++) #endif - for (id=0; idlun); -#endif - /* increase next_ldn for next dynamical assignment */ - next_ldn(host_index)++; - if (next_ldn(host_index)>=MAX_LOG_DEV) - next_ldn(host_index) = 7; - } else { /* wall against Linux accesses to the subsystem adapter */ - cmd->result = DID_BAD_TARGET << 16; - if (done) done (cmd); - return 0; - } - } - - /*verify there is no command already in progress for this log dev */ - if (ld(host_index)[ldn].cmd) - panic ("IBM MCA SCSI: cmd already in progress for this ldn.\n"); - - /*save done in cmd, and save cmd for the interrupt handler */ - cmd->scsi_done = done; - ld(host_index)[ldn].cmd = cmd; - - /*fill scb information independent of the scsi command */ - scb = &(ld(host_index)[ldn].scb); - ld(host_index)[ldn].tsb.dev_status = 0; - scb->enable = IM_REPORT_TSB_ONLY_ON_ERROR | IM_RETRY_ENABLE; - scb->tsb_adr = isa_virt_to_bus(&(ld(host_index)[ldn].tsb)); - scsi_cmd = cmd->cmnd[0]; - - if (cmd->use_sg) { - i = cmd->use_sg; - sl = (struct scatterlist *)(cmd->request_buffer); - if (i > 16) - panic ("IBM MCA SCSI: scatter-gather list too long.\n"); - while (--i >= 0) { - ld(host_index)[ldn].sge[i].address = (void *)(isa_page_to_bus(sl[i].page) + sl[i].offset); - ld(host_index)[ldn].sge[i].byte_length = sl[i].length; - } - scb->enable |= IM_POINTER_TO_LIST; - scb->sys_buf_adr = isa_virt_to_bus(&(ld(host_index)[ldn].sge[0])); - scb->sys_buf_length = cmd->use_sg * sizeof (struct im_sge); - } else { - scb->sys_buf_adr = isa_virt_to_bus(cmd->request_buffer); - /* recent Linux midlevel SCSI places 1024 byte for inquiry - * command. Far too much for old PS/2 hardware. */ - switch (scsi_cmd) { - /* avoid command errors by setting bufferlengths to - * ANSI-standard. Beware of forcing it to 255, - * this could SEGV the kernel!!! */ - case INQUIRY: - case REQUEST_SENSE: - case MODE_SENSE: - case MODE_SELECT: - if (cmd->request_bufflen > 255) scb->sys_buf_length = 255; - else scb->sys_buf_length = cmd->request_bufflen; - break; - case TEST_UNIT_READY: - scb->sys_buf_length = 0; - break; - default: - scb->sys_buf_length = cmd->request_bufflen; - break; - } - } - /*fill scb information dependent on scsi command */ + /* Information on syslog terminal */ + printk("IBM MCA SCSI: ldn=0x%x dynamically reassigned to (%d,%d).\n", ldn, target, cmd->lun); +#endif + /* increase next_ldn for next dynamical assignment */ + next_ldn(host_index)++; + if (next_ldn(host_index) >= MAX_LOG_DEV) + next_ldn(host_index) = 7; + } else { /* wall against Linux accesses to the subsystem adapter */ + cmd->result = DID_BAD_TARGET << 16; + if (done) + done(cmd); + return 0; + } + } + + /*verify there is no command already in progress for this log dev */ + if (ld(host_index)[ldn].cmd) + panic("IBM MCA SCSI: cmd already in progress for this ldn.\n"); + + /*save done in cmd, and save cmd for the interrupt handler */ + cmd->scsi_done = done; + ld(host_index)[ldn].cmd = cmd; + + /*fill scb information independent of the scsi command */ + scb = &(ld(host_index)[ldn].scb); + ld(host_index)[ldn].tsb.dev_status = 0; + scb->enable = IM_REPORT_TSB_ONLY_ON_ERROR | IM_RETRY_ENABLE; + scb->tsb_adr = isa_virt_to_bus(&(ld(host_index)[ldn].tsb)); + scsi_cmd = cmd->cmnd[0]; + + if (cmd->use_sg) { + i = cmd->use_sg; + sl = (struct scatterlist *) (cmd->request_buffer); + if (i > 16) + panic("IBM MCA SCSI: scatter-gather list too long.\n"); + while (--i >= 0) { + ld(host_index)[ldn].sge[i].address = (void *) (isa_page_to_bus(sl[i].page) + sl[i].offset); + ld(host_index)[ldn].sge[i].byte_length = sl[i].length; + } + scb->enable |= IM_POINTER_TO_LIST; + scb->sys_buf_adr = isa_virt_to_bus(&(ld(host_index)[ldn].sge[0])); + scb->sys_buf_length = cmd->use_sg * sizeof(struct im_sge); + } else { + scb->sys_buf_adr = isa_virt_to_bus(cmd->request_buffer); + /* recent Linux midlevel SCSI places 1024 byte for inquiry + * command. Far too much for old PS/2 hardware. */ + switch (scsi_cmd) { + /* avoid command errors by setting bufferlengths to + * ANSI-standard. Beware of forcing it to 255, + * this could SEGV the kernel!!! */ + case INQUIRY: + case REQUEST_SENSE: + case MODE_SENSE: + case MODE_SELECT: + if (cmd->request_bufflen > 255) + scb->sys_buf_length = 255; + else + scb->sys_buf_length = cmd->request_bufflen; + break; + case TEST_UNIT_READY: + scb->sys_buf_length = 0; + break; + default: + scb->sys_buf_length = cmd->request_bufflen; + break; + } + } + /*fill scb information dependent on scsi command */ #ifdef IM_DEBUG_CMD - printk("issue scsi cmd=%02x to ldn=%d\n", scsi_cmd, ldn); + printk("issue scsi cmd=%02x to ldn=%d\n", scsi_cmd, ldn); #endif - /* for specific device-type debugging: */ + /* for specific device-type debugging: */ #ifdef IM_DEBUG_CMD_SPEC_DEV - if (ld(host_index)[ldn].device_type==IM_DEBUG_CMD_DEVICE) - printk("(SCSI-device-type=0x%x) issue scsi cmd=%02x to ldn=%d\n", - ld(host_index)[ldn].device_type, scsi_cmd, ldn); -#endif - - /* for possible panics store current command */ - last_scsi_command(host_index)[ldn] = scsi_cmd; - last_scsi_type(host_index)[ldn] = IM_SCB; - /* update statistical info */ - IBM_DS(host_index).total_accesses++; - IBM_DS(host_index).ldn_access[ldn]++; - - switch (scsi_cmd) { - case READ_6: - case WRITE_6: - case READ_10: - case WRITE_10: - case READ_12: - case WRITE_12: - /* Distinguish between disk and other devices. Only disks (that are the - most frequently accessed devices) should be supported by the - IBM-SCSI-Subsystem commands. */ - switch (ld(host_index)[ldn].device_type) { - case TYPE_DISK: /* for harddisks enter here ... */ - case TYPE_MOD: /* ... try it also for MO-drives (send flames as */ - /* you like, if this won't work.) */ - if (scsi_cmd == READ_6 || scsi_cmd == READ_10 || scsi_cmd == READ_12) { - /* read command preparations */ - scb->enable |= IM_READ_CONTROL; - IBM_DS(host_index).ldn_read_access[ldn]++; /* increase READ-access on ldn stat. */ - scb->command = IM_READ_DATA_CMD | IM_NO_DISCONNECT; - } else { /* write command preparations */ - IBM_DS(host_index).ldn_write_access[ldn]++; /* increase write-count on ldn stat.*/ - scb->command = IM_WRITE_DATA_CMD | IM_NO_DISCONNECT; - } - if (scsi_cmd == READ_6 || scsi_cmd == WRITE_6) { - scb->u1.log_blk_adr = (((unsigned) cmd->cmnd[3]) << 0) | - (((unsigned) cmd->cmnd[2]) << 8) | - ((((unsigned) cmd->cmnd[1]) & 0x1f) << 16); - scb->u2.blk.count = (unsigned) cmd->cmnd[4]; - } else { - scb->u1.log_blk_adr = (((unsigned) cmd->cmnd[5]) << 0) | - (((unsigned) cmd->cmnd[4]) << 8) | - (((unsigned) cmd->cmnd[3]) << 16) | - (((unsigned) cmd->cmnd[2]) << 24); - scb->u2.blk.count = (((unsigned) cmd->cmnd[8]) << 0) | - (((unsigned) cmd->cmnd[7]) << 8); - } - last_scsi_logical_block(host_index)[ldn] = scb->u1.log_blk_adr; - last_scsi_blockcount(host_index)[ldn] = scb->u2.blk.count; - scb->u2.blk.length = ld(host_index)[ldn].block_length; - break; - /* for other devices, enter here. Other types are not known by - Linux! TYPE_NO_LUN is forbidden as valid device. */ - case TYPE_ROM: - case TYPE_TAPE: - case TYPE_PROCESSOR: - case TYPE_WORM: - case TYPE_SCANNER: - case TYPE_MEDIUM_CHANGER: - /* If there is a sequential-device, IBM recommends to use - IM_OTHER_SCSI_CMD_CMD instead of subsystem READ/WRITE. - This includes CD-ROM devices, too, due to the partial sequential - read capabilities. */ - scb->command = IM_OTHER_SCSI_CMD_CMD; - if (scsi_cmd == READ_6 || scsi_cmd == READ_10 || scsi_cmd == READ_12) - /* enable READ */ - scb->enable |= IM_READ_CONTROL; - scb->enable |= IM_BYPASS_BUFFER; - scb->u1.scsi_cmd_length = cmd->cmd_len; - memcpy (scb->u2.scsi_command, cmd->cmnd, cmd->cmd_len); - last_scsi_type(host_index)[ldn] = IM_LONG_SCB; - /* Read/write on this non-disk devices is also displayworthy, - so flash-up the LED/display. */ - break; - } - break; - case INQUIRY: - IBM_DS(host_index).ldn_inquiry_access[ldn]++; - scb->command = IM_DEVICE_INQUIRY_CMD; - scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT | IM_BYPASS_BUFFER; - scb->u1.log_blk_adr = 0; - break; - case TEST_UNIT_READY: - scb->command = IM_OTHER_SCSI_CMD_CMD; - scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT | IM_BYPASS_BUFFER; - scb->u1.log_blk_adr = 0; - scb->u1.scsi_cmd_length = 6; - memcpy (scb->u2.scsi_command, cmd->cmnd, 6); - last_scsi_type(host_index)[ldn] = IM_LONG_SCB; - break; - case READ_CAPACITY: - /* the length of system memory buffer must be exactly 8 bytes */ - scb->command = IM_READ_CAPACITY_CMD; - scb->enable |= IM_READ_CONTROL | IM_BYPASS_BUFFER; - if (scb->sys_buf_length > 8) scb->sys_buf_length = 8; - break; - /* Commands that need read-only-mode (system <- device): */ - case REQUEST_SENSE: - scb->command = IM_REQUEST_SENSE_CMD; - scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT | IM_BYPASS_BUFFER; - break; - /* Commands that need write-only-mode (system -> device): */ - case MODE_SELECT: - case MODE_SELECT_10: - IBM_DS(host_index).ldn_modeselect_access[ldn]++; - scb->command = IM_OTHER_SCSI_CMD_CMD; - scb->enable |= IM_SUPRESS_EXCEPTION_SHORT | IM_BYPASS_BUFFER; /*Select needs WRITE-enabled*/ - scb->u1.scsi_cmd_length = cmd->cmd_len; - memcpy (scb->u2.scsi_command, cmd->cmnd, cmd->cmd_len); - last_scsi_type(host_index)[ldn] = IM_LONG_SCB; - break; - /* For other commands, read-only is useful. Most other commands are - running without an input-data-block. */ - default: - scb->command = IM_OTHER_SCSI_CMD_CMD; - scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT | IM_BYPASS_BUFFER; - scb->u1.scsi_cmd_length = cmd->cmd_len; - memcpy (scb->u2.scsi_command, cmd->cmnd, cmd->cmd_len); - last_scsi_type(host_index)[ldn] = IM_LONG_SCB; - break; - } - /*issue scb command, and return */ - if (++disk_rw_in_progress == 1) - PS2_DISK_LED_ON (shpnt->host_no, target); - - if (last_scsi_type(host_index)[ldn] == IM_LONG_SCB) { - issue_cmd (host_index, isa_virt_to_bus(scb), IM_LONG_SCB | ldn); - IBM_DS(host_index).long_scbs++; - } else { - issue_cmd (host_index, isa_virt_to_bus(scb), IM_SCB | ldn); - IBM_DS(host_index).scbs++; - } - return 0; -} - -int ibmmca_abort (Scsi_Cmnd * cmd) -{ - /* Abort does not work, as the adapter never generates an interrupt on - * whatever situation is simulated, even when really pending commands - * are running on the adapters' hardware ! */ - - struct Scsi_Host *shpnt; - unsigned int ldn; - void (*saved_done) (Scsi_Cmnd *); - int target; - int host_index; - int max_pun; - static unsigned long flags; - unsigned long imm_command; + if (ld(host_index)[ldn].device_type == IM_DEBUG_CMD_DEVICE) + printk("(SCSI-device-type=0x%x) issue scsi cmd=%02x to ldn=%d\n", ld(host_index)[ldn].device_type, scsi_cmd, ldn); +#endif + + /* for possible panics store current command */ + last_scsi_command(host_index)[ldn] = scsi_cmd; + last_scsi_type(host_index)[ldn] = IM_SCB; + /* update statistical info */ + IBM_DS(host_index).total_accesses++; + IBM_DS(host_index).ldn_access[ldn]++; + + switch (scsi_cmd) { + case READ_6: + case WRITE_6: + case READ_10: + case WRITE_10: + case READ_12: + case WRITE_12: + /* Distinguish between disk and other devices. Only disks (that are the + most frequently accessed devices) should be supported by the + IBM-SCSI-Subsystem commands. */ + switch (ld(host_index)[ldn].device_type) { + case TYPE_DISK: /* for harddisks enter here ... */ + case TYPE_MOD: /* ... try it also for MO-drives (send flames as */ + /* you like, if this won't work.) */ + if (scsi_cmd == READ_6 || scsi_cmd == READ_10 || scsi_cmd == READ_12) { + /* read command preparations */ + scb->enable |= IM_READ_CONTROL; + IBM_DS(host_index).ldn_read_access[ldn]++; /* increase READ-access on ldn stat. */ + scb->command = IM_READ_DATA_CMD | IM_NO_DISCONNECT; + } else { /* write command preparations */ + IBM_DS(host_index).ldn_write_access[ldn]++; /* increase write-count on ldn stat. */ + scb->command = IM_WRITE_DATA_CMD | IM_NO_DISCONNECT; + } + if (scsi_cmd == READ_6 || scsi_cmd == WRITE_6) { + scb->u1.log_blk_adr = (((unsigned) cmd->cmnd[3]) << 0) | (((unsigned) cmd->cmnd[2]) << 8) | ((((unsigned) cmd->cmnd[1]) & 0x1f) << 16); + scb->u2.blk.count = (unsigned) cmd->cmnd[4]; + } else { + scb->u1.log_blk_adr = (((unsigned) cmd->cmnd[5]) << 0) | (((unsigned) cmd->cmnd[4]) << 8) | (((unsigned) cmd->cmnd[3]) << 16) | (((unsigned) cmd->cmnd[2]) << 24); + scb->u2.blk.count = (((unsigned) cmd->cmnd[8]) << 0) | (((unsigned) cmd->cmnd[7]) << 8); + } + last_scsi_logical_block(host_index)[ldn] = scb->u1.log_blk_adr; + last_scsi_blockcount(host_index)[ldn] = scb->u2.blk.count; + scb->u2.blk.length = ld(host_index)[ldn].block_length; + break; + /* for other devices, enter here. Other types are not known by + Linux! TYPE_NO_LUN is forbidden as valid device. */ + case TYPE_ROM: + case TYPE_TAPE: + case TYPE_PROCESSOR: + case TYPE_WORM: + case TYPE_SCANNER: + case TYPE_MEDIUM_CHANGER: + /* If there is a sequential-device, IBM recommends to use + IM_OTHER_SCSI_CMD_CMD instead of subsystem READ/WRITE. + This includes CD-ROM devices, too, due to the partial sequential + read capabilities. */ + scb->command = IM_OTHER_SCSI_CMD_CMD; + if (scsi_cmd == READ_6 || scsi_cmd == READ_10 || scsi_cmd == READ_12) + /* enable READ */ + scb->enable |= IM_READ_CONTROL; + scb->enable |= IM_BYPASS_BUFFER; + scb->u1.scsi_cmd_length = cmd->cmd_len; + memcpy(scb->u2.scsi_command, cmd->cmnd, cmd->cmd_len); + last_scsi_type(host_index)[ldn] = IM_LONG_SCB; + /* Read/write on this non-disk devices is also displayworthy, + so flash-up the LED/display. */ + break; + } + break; + case INQUIRY: + IBM_DS(host_index).ldn_inquiry_access[ldn]++; + scb->command = IM_DEVICE_INQUIRY_CMD; + scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT | IM_BYPASS_BUFFER; + scb->u1.log_blk_adr = 0; + break; + case TEST_UNIT_READY: + scb->command = IM_OTHER_SCSI_CMD_CMD; + scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT | IM_BYPASS_BUFFER; + scb->u1.log_blk_adr = 0; + scb->u1.scsi_cmd_length = 6; + memcpy(scb->u2.scsi_command, cmd->cmnd, 6); + last_scsi_type(host_index)[ldn] = IM_LONG_SCB; + break; + case READ_CAPACITY: + /* the length of system memory buffer must be exactly 8 bytes */ + scb->command = IM_READ_CAPACITY_CMD; + scb->enable |= IM_READ_CONTROL | IM_BYPASS_BUFFER; + if (scb->sys_buf_length > 8) + scb->sys_buf_length = 8; + break; + /* Commands that need read-only-mode (system <- device): */ + case REQUEST_SENSE: + scb->command = IM_REQUEST_SENSE_CMD; + scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT | IM_BYPASS_BUFFER; + break; + /* Commands that need write-only-mode (system -> device): */ + case MODE_SELECT: + case MODE_SELECT_10: + IBM_DS(host_index).ldn_modeselect_access[ldn]++; + scb->command = IM_OTHER_SCSI_CMD_CMD; + scb->enable |= IM_SUPRESS_EXCEPTION_SHORT | IM_BYPASS_BUFFER; /*Select needs WRITE-enabled */ + scb->u1.scsi_cmd_length = cmd->cmd_len; + memcpy(scb->u2.scsi_command, cmd->cmnd, cmd->cmd_len); + last_scsi_type(host_index)[ldn] = IM_LONG_SCB; + break; + /* For other commands, read-only is useful. Most other commands are + running without an input-data-block. */ + default: + scb->command = IM_OTHER_SCSI_CMD_CMD; + scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT | IM_BYPASS_BUFFER; + scb->u1.scsi_cmd_length = cmd->cmd_len; + memcpy(scb->u2.scsi_command, cmd->cmnd, cmd->cmd_len); + last_scsi_type(host_index)[ldn] = IM_LONG_SCB; + break; + } + /*issue scb command, and return */ + if (++disk_rw_in_progress == 1) + PS2_DISK_LED_ON(shpnt->host_no, target); + + if (last_scsi_type(host_index)[ldn] == IM_LONG_SCB) { + issue_cmd(host_index, isa_virt_to_bus(scb), IM_LONG_SCB | ldn); + IBM_DS(host_index).long_scbs++; + } else { + issue_cmd(host_index, isa_virt_to_bus(scb), IM_SCB | ldn); + IBM_DS(host_index).scbs++; + } + return 0; +} + +static int ibmmca_abort(Scsi_Cmnd * cmd) +{ + /* Abort does not work, as the adapter never generates an interrupt on + * whatever situation is simulated, even when really pending commands + * are running on the adapters' hardware ! */ + + struct Scsi_Host *shpnt; + unsigned int ldn; + void (*saved_done) (Scsi_Cmnd *); + int target; + int host_index; + int max_pun; + unsigned long imm_command; #ifdef IM_DEBUG_PROBE - printk("IBM MCA SCSI: Abort subroutine called...\n"); + printk("IBM MCA SCSI: Abort subroutine called...\n"); #endif - IBMLOCK(cmd->host) - shpnt = cmd->host; - /* search for the right hostadapter */ - for (host_index = 0; hosts[host_index] && hosts[host_index]->host_no != shpnt->host_no; host_index++); - - if (!hosts[host_index]) { /* invalid hostadapter descriptor address */ - cmd->result = DID_NO_CONNECT << 16; - if (cmd->scsi_done) (cmd->scsi_done) (cmd); - shpnt = cmd->host; - IBMUNLOCK(shpnt) + + shpnt = cmd->host; + /* search for the right hostadapter */ + for (host_index = 0; hosts[host_index] && hosts[host_index]->host_no != shpnt->host_no; host_index++); + + if (!hosts[host_index]) { /* invalid hostadapter descriptor address */ + cmd->result = DID_NO_CONNECT << 16; + if (cmd->scsi_done) + (cmd->scsi_done) (cmd); + shpnt = cmd->host; #ifdef IM_DEBUG_PROBE - printk("IBM MCA SCSI: Abort adapter selection failed!\n"); + printk(KERN_DEBUG "IBM MCA SCSI: Abort adapter selection failed!\n"); #endif - return SCSI_ABORT_SNOOZE; - } - max_pun = subsystem_maxid(host_index); - if (ibm_ansi_order) { - target = max_pun - 1 - cmd->target; - if ((target <= subsystem_pun(host_index))&&(cmd->target <= subsystem_pun(host_index))) - target--; - else if ((target >= subsystem_pun(host_index))&&(cmd->target >= subsystem_pun(host_index))) - target++; - } else - target = cmd->target; - - /* get logical device number, and disable system interrupts */ - printk ("IBM MCA SCSI: Sending abort to device pun=%d, lun=%d.\n", - target, cmd->lun); - ldn = get_ldn(host_index)[target][cmd->lun]; - - /*if cmd for this ldn has already finished, no need to abort */ - if (!ld(host_index)[ldn].cmd) { - IBMUNLOCK(shpnt) - return SCSI_ABORT_NOT_RUNNING; - } - - /* Clear ld.cmd, save done function, install internal done, - * send abort immediate command (this enables sys. interrupts), - * and wait until the interrupt arrives. - */ - saved_done = cmd->scsi_done; - cmd->scsi_done = internal_done; - cmd->SCp.Status = 0; - last_scsi_command(host_index)[ldn] = IM_ABORT_IMM_CMD; - last_scsi_type(host_index)[ldn] = IM_IMM_CMD; - imm_command = inl(IM_CMD_REG(host_index)); - imm_command &= (unsigned long)(0xffff0000); /* mask reserved stuff */ - imm_command |= (unsigned long)(IM_ABORT_IMM_CMD); - /* must wait for attention reg not busy */ - while (1) { - if (!(inb (IM_STAT_REG(host_index)) & IM_BUSY)) - break; - IBMUNLOCK(shpnt) - IBMLOCK(shpnt) - } - /* write registers and enable system interrupts */ - outl (imm_command, IM_CMD_REG(host_index)); - outb (IM_IMM_CMD | ldn, IM_ATTN_REG(host_index)); - IBMUNLOCK(shpnt) + return SUCCESS; + } + max_pun = subsystem_maxid(host_index); + if (ibm_ansi_order) { + target = max_pun - 1 - cmd->target; + if ((target <= subsystem_pun(host_index)) && (cmd->target <= subsystem_pun(host_index))) + target--; + else if ((target >= subsystem_pun(host_index)) && (cmd->target >= subsystem_pun(host_index))) + target++; + } else + target = cmd->target; + + /* get logical device number, and disable system interrupts */ + printk(KERN_WARNING "IBM MCA SCSI: Sending abort to device pun=%d, lun=%d.\n", target, cmd->lun); + ldn = get_ldn(host_index)[target][cmd->lun]; + + /*if cmd for this ldn has already finished, no need to abort */ + if (!ld(host_index)[ldn].cmd) { + return SUCCESS; + } + + /* Clear ld.cmd, save done function, install internal done, + * send abort immediate command (this enables sys. interrupts), + * and wait until the interrupt arrives. + */ + saved_done = cmd->scsi_done; + cmd->scsi_done = internal_done; + cmd->SCp.Status = 0; + last_scsi_command(host_index)[ldn] = IM_ABORT_IMM_CMD; + last_scsi_type(host_index)[ldn] = IM_IMM_CMD; + imm_command = inl(IM_CMD_REG(host_index)); + imm_command &= (unsigned long) (0xffff0000); /* mask reserved stuff */ + imm_command |= (unsigned long) (IM_ABORT_IMM_CMD); + /* must wait for attention reg not busy */ + /* FIXME - timeout, politeness */ + while (1) { + if (!(inb(IM_STAT_REG(host_index)) & IM_BUSY)) + break; + } + /* write registers and enable system interrupts */ + outl(imm_command, IM_CMD_REG(host_index)); + outb(IM_IMM_CMD | ldn, IM_ATTN_REG(host_index)); #ifdef IM_DEBUG_PROBE - printk("IBM MCA SCSI: Abort queued to adapter...\n"); + printk("IBM MCA SCSI: Abort queued to adapter...\n"); #endif - while (!cmd->SCp.Status) barrier (); - cmd->scsi_done = saved_done; + spin_unlock_irq(shpnt->host_lock); + while (!cmd->SCp.Status) + yield(); + spin_lock_irq(shpnt->host_lock); + cmd->scsi_done = saved_done; #ifdef IM_DEBUG_PROBE - printk("IBM MCA SCSI: Abort returned with adapter response...\n"); + printk("IBM MCA SCSI: Abort returned with adapter response...\n"); #endif - /*if abort went well, call saved done, then return success or error */ - if (cmd->result == (DID_ABORT << 16)) { - IBMLOCK(shpnt) - cmd->result |= DID_ABORT << 16; - if (cmd->scsi_done) (cmd->scsi_done) (cmd); - ld(host_index)[ldn].cmd = NULL; - IBMUNLOCK(shpnt) + /*if abort went well, call saved done, then return success or error */ + if (cmd->result == (DID_ABORT << 16)) + { + cmd->result |= DID_ABORT << 16; + if (cmd->scsi_done) + (cmd->scsi_done) (cmd); + ld(host_index)[ldn].cmd = NULL; #ifdef IM_DEBUG_PROBE - printk("IBM MCA SCSI: Abort finished with success.\n"); + printk("IBM MCA SCSI: Abort finished with success.\n"); #endif - return SCSI_ABORT_SUCCESS; - } else { - IBMLOCK(shpnt) - cmd->result |= DID_NO_CONNECT << 16; - if (cmd->scsi_done) (cmd->scsi_done) (cmd); - ld(host_index)[ldn].cmd = NULL; - IBMUNLOCK(shpnt) + return SUCCESS; + } else { + cmd->result |= DID_NO_CONNECT << 16; + if (cmd->scsi_done) + (cmd->scsi_done) (cmd); + ld(host_index)[ldn].cmd = NULL; #ifdef IM_DEBUG_PROBE - printk("IBM MCA SCSI: Abort failed.\n"); + printk("IBM MCA SCSI: Abort failed.\n"); #endif - return SCSI_ABORT_ERROR; - } + return FAILED; + } +} + +static int ibmmca_host_reset(Scsi_Cmnd * cmd) +{ + struct Scsi_Host *shpnt; + Scsi_Cmnd *cmd_aid; + int ticks, i; + int host_index; + unsigned long imm_command; + + if (cmd == NULL) + BUG(); + + ticks = IM_RESET_DELAY * HZ; + shpnt = cmd->host; + /* search for the right hostadapter */ + for (host_index = 0; hosts[host_index] && hosts[host_index]->host_no != shpnt->host_no; host_index++); + + if (!hosts[host_index]) /* invalid hostadapter descriptor address */ + return FAILED; + + if (local_checking_phase_flag(host_index)) { + printk(KERN_WARNING "IBM MCA SCSI: unable to reset while checking devices.\n"); + return FAILED; + } + + /* issue reset immediate command to subsystem, and wait for interrupt */ + printk("IBM MCA SCSI: resetting all devices.\n"); + reset_status(host_index) = IM_RESET_IN_PROGRESS; + last_scsi_command(host_index)[0xf] = IM_RESET_IMM_CMD; + last_scsi_type(host_index)[0xf] = IM_IMM_CMD; + imm_command = inl(IM_CMD_REG(host_index)); + imm_command &= (unsigned long) (0xffff0000); /* mask reserved stuff */ + imm_command |= (unsigned long) (IM_RESET_IMM_CMD); + /* must wait for attention reg not busy */ + while (1) { + if (!(inb(IM_STAT_REG(host_index)) & IM_BUSY)) + break; + spin_unlock_irq(shpnt->host_lock); + yield(); + spin_lock_irq(shpnt->host_lock); + } + /*write registers and enable system interrupts */ + outl(imm_command, IM_CMD_REG(host_index)); + outb(IM_IMM_CMD | 0xf, IM_ATTN_REG(host_index)); + /* wait for interrupt finished or intr_stat register to be set, as the + * interrupt will not be executed, while we are in here! */ + + /* FIXME: This is really really icky we so want a sleeping version of this ! */ + while (reset_status(host_index) == IM_RESET_IN_PROGRESS && --ticks && ((inb(IM_INTR_REG(host_index)) & 0x8f) != 0x8f)) { + udelay((1 + 999 / HZ) * 1000); + barrier(); + } + /* if reset did not complete, just return an error */ + if (!ticks) { + printk(KERN_ERR "IBM MCA SCSI: reset did not complete within %d seconds.\n", IM_RESET_DELAY); + reset_status(host_index) = IM_RESET_FINISHED_FAIL; + return FAILED; + } + + if ((inb(IM_INTR_REG(host_index)) & 0x8f) == 0x8f) { + /* analysis done by this routine and not by the intr-routine */ + if (inb(IM_INTR_REG(host_index)) == 0xaf) + reset_status(host_index) = IM_RESET_FINISHED_OK_NO_INT; + else if (inb(IM_INTR_REG(host_index)) == 0xcf) + reset_status(host_index) = IM_RESET_FINISHED_FAIL; + else /* failed, 4get it */ + reset_status(host_index) = IM_RESET_NOT_IN_PROGRESS_NO_INT; + outb(IM_EOI | 0xf, IM_ATTN_REG(host_index)); + } + + /* if reset failed, just return an error */ + if (reset_status(host_index) == IM_RESET_FINISHED_FAIL) { + printk(KERN_ERR "IBM MCA SCSI: reset failed.\n"); + return FAILED; + } + + /* so reset finished ok - call outstanding done's, and return success */ + printk(KERN_INFO "IBM MCA SCSI: Reset successfully completed.\n"); + for (i = 0; i < MAX_LOG_DEV; i++) { + cmd_aid = ld(host_index)[i].cmd; + if (cmd_aid && cmd_aid->scsi_done) { + ld(host_index)[i].cmd = NULL; + cmd_aid->result = DID_RESET << 16; + } + } + return SUCCESS; } -int ibmmca_reset (Scsi_Cmnd * cmd, unsigned int reset_flags) +static int ibmmca_biosparam(struct scsi_device *sdev, struct block_device *bdev, sector_t capacity, int *info) { - struct Scsi_Host *shpnt; - Scsi_Cmnd *cmd_aid; - int ticks,i; - int host_index; - static unsigned long flags; - unsigned long imm_command; - - if (cmd == NULL) { - printk("IBM MCA SCSI: Reset called with NULL-command!\n"); - return(SCSI_RESET_SNOOZE); - } - IBMLOCK(cmd->host) - ticks = IM_RESET_DELAY*HZ; - shpnt = cmd->host; - /* search for the right hostadapter */ - for (host_index = 0; hosts[host_index] && hosts[host_index]->host_no != shpnt->host_no; host_index++); - - if (!hosts[host_index]) /* invalid hostadapter descriptor address */ - return SCSI_ABORT_SNOOZE; - - if (local_checking_phase_flag(host_index)) { - printk("IBM MCA SCSI: unable to reset while checking devices.\n"); - IBMUNLOCK(shpnt) - return SCSI_RESET_SNOOZE; - } - - /* issue reset immediate command to subsystem, and wait for interrupt */ - printk("IBM MCA SCSI: resetting all devices.\n"); - reset_status(host_index) = IM_RESET_IN_PROGRESS; - last_scsi_command(host_index)[0xf] = IM_RESET_IMM_CMD; - last_scsi_type(host_index)[0xf] = IM_IMM_CMD; - imm_command = inl(IM_CMD_REG(host_index)); - imm_command &= (unsigned long)(0xffff0000); /* mask reserved stuff */ - imm_command |= (unsigned long)(IM_RESET_IMM_CMD); - /* must wait for attention reg not busy */ - while (1) { - if (!(inb (IM_STAT_REG(host_index)) & IM_BUSY)) - break; - IBMUNLOCK(shpnt) - IBMLOCK(shpnt) - } - /*write registers and enable system interrupts */ - outl (imm_command, IM_CMD_REG(host_index)); - outb (IM_IMM_CMD | 0xf, IM_ATTN_REG(host_index)); - /* wait for interrupt finished or intr_stat register to be set, as the - * interrupt will not be executed, while we are in here! */ - while (reset_status(host_index) == IM_RESET_IN_PROGRESS && --ticks - && ((inb(IM_INTR_REG(host_index)) & 0x8f)!=0x8f)) { - udelay((1+999/HZ)*1000); - barrier(); - } - /* if reset did not complete, just return an error*/ - if (!ticks) { - printk("IBM MCA SCSI: reset did not complete within %d seconds.\n", - IM_RESET_DELAY); - reset_status(host_index) = IM_RESET_FINISHED_FAIL; - IBMUNLOCK(shpnt) - return SCSI_RESET_ERROR; - } - - if ((inb(IM_INTR_REG(host_index)) & 0x8f)==0x8f) { - /* analysis done by this routine and not by the intr-routine */ - if (inb(IM_INTR_REG(host_index))==0xaf) - reset_status(host_index) = IM_RESET_FINISHED_OK_NO_INT; - else if (inb(IM_INTR_REG(host_index))==0xcf) - reset_status(host_index) = IM_RESET_FINISHED_FAIL; - else /* failed, 4get it */ - reset_status(host_index) = IM_RESET_NOT_IN_PROGRESS_NO_INT; - outb (IM_EOI | 0xf, IM_ATTN_REG(host_index)); - } - - /* if reset failed, just return an error */ - if (reset_status(host_index) == IM_RESET_FINISHED_FAIL) { - printk("IBM MCA SCSI: reset failed.\n"); - IBMUNLOCK(shpnt) - return SCSI_RESET_ERROR; - } - - /* so reset finished ok - call outstanding done's, and return success */ - printk ("IBM MCA SCSI: Reset successfully completed.\n"); - IBMUNLOCK(shpnt) - for (i = 0; i < MAX_LOG_DEV; i++) { - cmd_aid = ld(host_index)[i].cmd; - if (cmd_aid && cmd_aid->scsi_done) { - ld(host_index)[i].cmd = NULL; - cmd_aid->result = DID_RESET << 16; - } - } - if (reset_flags & SCSI_RESET_SUGGEST_HOST_RESET) - return (SCSI_RESET_SUCCESS | SCSI_RESET_HOST_RESET); - else if (reset_flags & SCSI_RESET_SUGGEST_BUS_RESET) - return (SCSI_RESET_SUCCESS | SCSI_RESET_BUS_RESET); - else - return SCSI_RESET_SUCCESS; -} - -int ibmmca_biosparam (struct scsi_device *sdev, struct block_device *bdev, - sector_t capacity, int *info) -{ - int size = capacity; - info[0] = 64; - info[1] = 32; - info[2] = size / (info[0] * info[1]); - if (info[2] >= 1024) { - info[0] = 128; - info[1] = 63; - info[2] = size / (info[0] * info[1]); - if (info[2] >= 1024) { - info[0] = 255; - info[1] = 63; - info[2] = size / (info[0] * info[1]); - if (info[2] >= 1024) - info[2] = 1023; - } - } - return 0; + int size = capacity; + info[0] = 64; + info[1] = 32; + info[2] = size / (info[0] * info[1]); + if (info[2] >= 1024) { + info[0] = 128; + info[1] = 63; + info[2] = size / (info[0] * info[1]); + if (info[2] >= 1024) { + info[0] = 255; + info[1] = 63; + info[2] = size / (info[0] * info[1]); + if (info[2] >= 1024) + info[2] = 1023; + } + } + return 0; } /* calculate percentage of total accesses on a ldn */ static int ldn_access_load(int host_index, int ldn) { - if (IBM_DS(host_index).total_accesses == 0) return (0); - if (IBM_DS(host_index).ldn_access[ldn] == 0) return (0); - return (IBM_DS(host_index).ldn_access[ldn] * 100) / IBM_DS(host_index).total_accesses; + if (IBM_DS(host_index).total_accesses == 0) + return (0); + if (IBM_DS(host_index).ldn_access[ldn] == 0) + return (0); + return (IBM_DS(host_index).ldn_access[ldn] * 100) / IBM_DS(host_index).total_accesses; } /* calculate total amount of r/w-accesses */ static int ldn_access_total_read_write(int host_index) { - int a; - int i; + int a; + int i; - a = 0; - for (i=0; i<=MAX_LOG_DEV; i++) - a+=IBM_DS(host_index).ldn_read_access[i]+IBM_DS(host_index).ldn_write_access[i]; - return(a); + a = 0; + for (i = 0; i <= MAX_LOG_DEV; i++) + a += IBM_DS(host_index).ldn_read_access[i] + IBM_DS(host_index).ldn_write_access[i]; + return (a); } static int ldn_access_total_inquiry(int host_index) { - int a; - int i; + int a; + int i; - a = 0; - for (i=0; i<=MAX_LOG_DEV; i++) - a+=IBM_DS(host_index).ldn_inquiry_access[i]; - return(a); + a = 0; + for (i = 0; i <= MAX_LOG_DEV; i++) + a += IBM_DS(host_index).ldn_inquiry_access[i]; + return (a); } static int ldn_access_total_modeselect(int host_index) { - int a; - int i; + int a; + int i; - a = 0; - for (i=0; i<=MAX_LOG_DEV; i++) - a+=IBM_DS(host_index).ldn_modeselect_access[i]; - return(a); + a = 0; + for (i = 0; i <= MAX_LOG_DEV; i++) + a += IBM_DS(host_index).ldn_modeselect_access[i]; + return (a); } /* routine to display info in the proc-fs-structure (a deluxe feature) */ -int ibmmca_proc_info (char *buffer, char **start, off_t offset, int length, - int hostno, int inout) +static int ibmmca_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int inout) { - int len=0; - int i,id,lun,host_index; - struct Scsi_Host *shpnt; - unsigned long flags; - int max_pun; - - for (i = 0; hosts[i] && hosts[i]->host_no != hostno; i++); - IBMLOCK(hosts[i]) /* Check it */ - shpnt = hosts[i]; - host_index = i; - if (!shpnt) { - len += sprintf(buffer+len, "\nIBM MCA SCSI: Can't find adapter for host number %d\n", hostno); - return len; - } - max_pun = subsystem_maxid(host_index); - - len += sprintf(buffer+len, "\n IBM-SCSI-Subsystem-Linux-Driver, Version %s\n\n\n", - IBMMCA_SCSI_DRIVER_VERSION); - len += sprintf(buffer+len, " SCSI Access-Statistics:\n"); - len += sprintf(buffer+len, " Device Scanning Order....: %s\n", - (ibm_ansi_order) ? "IBM/ANSI" : "New Industry Standard"); + int len = 0; + int i, id, lun, host_index; + struct Scsi_Host *shpnt; + unsigned long flags; + int max_pun; + + for (i = 0; hosts[i] && hosts[i]->host_no != hostno; i++); + + spin_lock_irqsave(hosts[i]->host_lock, flags); /* Check it */ + shpnt = hosts[i]; + host_index = i; + if (!shpnt) { + len += sprintf(buffer + len, "\nIBM MCA SCSI: Can't find adapter for host number %d\n", hostno); + return len; + } + max_pun = subsystem_maxid(host_index); + + len += sprintf(buffer + len, "\n IBM-SCSI-Subsystem-Linux-Driver, Version %s\n\n\n", IBMMCA_SCSI_DRIVER_VERSION); + len += sprintf(buffer + len, " SCSI Access-Statistics:\n"); + len += sprintf(buffer + len, " Device Scanning Order....: %s\n", (ibm_ansi_order) ? "IBM/ANSI" : "New Industry Standard"); #ifdef CONFIG_SCSI_MULTI_LUN - len += sprintf(buffer+len, " Multiple LUN probing.....: Yes\n"); + len += sprintf(buffer + len, " Multiple LUN probing.....: Yes\n"); #else - len += sprintf(buffer+len, " Multiple LUN probing.....: No\n"); + len += sprintf(buffer + len, " Multiple LUN probing.....: No\n"); #endif - len += sprintf(buffer+len, " This Hostnumber..........: %d\n", - hostno); - len += sprintf(buffer+len, " Base I/O-Port............: 0x%x\n", - (unsigned int)(IM_CMD_REG(host_index))); - len += sprintf(buffer+len, " (Shared) IRQ.............: %d\n", - IM_IRQ); - len += sprintf(buffer+len, " Total Interrupts.........: %d\n", - IBM_DS(host_index).total_interrupts); - len += sprintf(buffer+len, " Total SCSI Accesses......: %d\n", - IBM_DS(host_index).total_accesses); - len += sprintf(buffer+len, " Total short SCBs.........: %d\n", - IBM_DS(host_index).scbs); - len += sprintf(buffer+len, " Total long SCBs..........: %d\n", - IBM_DS(host_index).long_scbs); - len += sprintf(buffer+len, " Total SCSI READ/WRITE..: %d\n", - ldn_access_total_read_write(host_index)); - len += sprintf(buffer+len, " Total SCSI Inquiries...: %d\n", - ldn_access_total_inquiry(host_index)); - len += sprintf(buffer+len, " Total SCSI Modeselects.: %d\n", - ldn_access_total_modeselect(host_index)); - len += sprintf(buffer+len, " Total SCSI other cmds..: %d\n", - IBM_DS(host_index).total_accesses - ldn_access_total_read_write(host_index) - - ldn_access_total_modeselect(host_index) - - ldn_access_total_inquiry(host_index)); - len += sprintf(buffer+len, " Total SCSI command fails.: %d\n\n", - IBM_DS(host_index).total_errors); - len += sprintf(buffer+len, " Logical-Device-Number (LDN) Access-Statistics:\n"); - len += sprintf(buffer+len, " LDN | Accesses [%%] | READ | WRITE | ASSIGNMENTS\n"); - len += sprintf(buffer+len, " -----|--------------|-----------|-----------|--------------\n"); - for (i=0; i<=MAX_LOG_DEV; i++) - len += sprintf(buffer+len, " %2X | %3d | %8d | %8d | %8d\n", - i, ldn_access_load(host_index, i), IBM_DS(host_index).ldn_read_access[i], - IBM_DS(host_index).ldn_write_access[i], IBM_DS(host_index).ldn_assignments[i]); - len += sprintf(buffer+len, " -----------------------------------------------------------\n\n"); - len += sprintf(buffer+len, " Dynamical-LDN-Assignment-Statistics:\n"); - len += sprintf(buffer+len, " Number of physical SCSI-devices..: %d (+ Adapter)\n", - IBM_DS(host_index).total_scsi_devices); - len += sprintf(buffer+len, " Dynamical Assignment necessary...: %s\n", - IBM_DS(host_index).dyn_flag ? "Yes" : "No "); - len += sprintf(buffer+len, " Next LDN to be assigned..........: 0x%x\n", - next_ldn(host_index)); - len += sprintf(buffer+len, " Dynamical assignments done yet...: %d\n", - IBM_DS(host_index).dynamical_assignments); - len += sprintf(buffer+len, "\n Current SCSI-Device-Mapping:\n"); - len += sprintf(buffer+len, " Physical SCSI-Device Map Logical SCSI-Device Map\n"); - len += sprintf(buffer+len, " ID\\LUN 0 1 2 3 4 5 6 7 ID\\LUN 0 1 2 3 4 5 6 7\n"); - for (id=0; id length) len = length; - IBMUNLOCK(shpnt) - return len; + len += sprintf(buffer + len, " This Hostnumber..........: %d\n", hostno); + len += sprintf(buffer + len, " Base I/O-Port............: 0x%x\n", (unsigned int) (IM_CMD_REG(host_index))); + len += sprintf(buffer + len, " (Shared) IRQ.............: %d\n", IM_IRQ); + len += sprintf(buffer + len, " Total Interrupts.........: %d\n", IBM_DS(host_index).total_interrupts); + len += sprintf(buffer + len, " Total SCSI Accesses......: %d\n", IBM_DS(host_index).total_accesses); + len += sprintf(buffer + len, " Total short SCBs.........: %d\n", IBM_DS(host_index).scbs); + len += sprintf(buffer + len, " Total long SCBs..........: %d\n", IBM_DS(host_index).long_scbs); + len += sprintf(buffer + len, " Total SCSI READ/WRITE..: %d\n", ldn_access_total_read_write(host_index)); + len += sprintf(buffer + len, " Total SCSI Inquiries...: %d\n", ldn_access_total_inquiry(host_index)); + len += sprintf(buffer + len, " Total SCSI Modeselects.: %d\n", ldn_access_total_modeselect(host_index)); + len += sprintf(buffer + len, " Total SCSI other cmds..: %d\n", IBM_DS(host_index).total_accesses - ldn_access_total_read_write(host_index) + - ldn_access_total_modeselect(host_index) + - ldn_access_total_inquiry(host_index)); + len += sprintf(buffer + len, " Total SCSI command fails.: %d\n\n", IBM_DS(host_index).total_errors); + len += sprintf(buffer + len, " Logical-Device-Number (LDN) Access-Statistics:\n"); + len += sprintf(buffer + len, " LDN | Accesses [%%] | READ | WRITE | ASSIGNMENTS\n"); + len += sprintf(buffer + len, " -----|--------------|-----------|-----------|--------------\n"); + for (i = 0; i <= MAX_LOG_DEV; i++) + len += sprintf(buffer + len, " %2X | %3d | %8d | %8d | %8d\n", i, ldn_access_load(host_index, i), IBM_DS(host_index).ldn_read_access[i], IBM_DS(host_index).ldn_write_access[i], IBM_DS(host_index).ldn_assignments[i]); + len += sprintf(buffer + len, " -----------------------------------------------------------\n\n"); + len += sprintf(buffer + len, " Dynamical-LDN-Assignment-Statistics:\n"); + len += sprintf(buffer + len, " Number of physical SCSI-devices..: %d (+ Adapter)\n", IBM_DS(host_index).total_scsi_devices); + len += sprintf(buffer + len, " Dynamical Assignment necessary...: %s\n", IBM_DS(host_index).dyn_flag ? "Yes" : "No "); + len += sprintf(buffer + len, " Next LDN to be assigned..........: 0x%x\n", next_ldn(host_index)); + len += sprintf(buffer + len, " Dynamical assignments done yet...: %d\n", IBM_DS(host_index).dynamical_assignments); + len += sprintf(buffer + len, "\n Current SCSI-Device-Mapping:\n"); + len += sprintf(buffer + len, " Physical SCSI-Device Map Logical SCSI-Device Map\n"); + len += sprintf(buffer + len, " ID\\LUN 0 1 2 3 4 5 6 7 ID\\LUN 0 1 2 3 4 5 6 7\n"); + for (id = 0; id < max_pun; id++) { + len += sprintf(buffer + len, " %2d ", id); + for (lun = 0; lun < 8; lun++) + len += sprintf(buffer + len, "%2s ", ti_p(get_scsi(host_index)[id][lun])); + len += sprintf(buffer + len, " %2d ", id); + for (lun = 0; lun < 8; lun++) + len += sprintf(buffer + len, "%2s ", ti_l(get_ldn(host_index)[id][lun])); + len += sprintf(buffer + len, "\n"); + } + + len += sprintf(buffer + len, "(A = IBM-Subsystem, D = Harddisk, T = Tapedrive, P = Processor, W = WORM,\n"); + len += sprintf(buffer + len, " R = CD-ROM, S = Scanner, M = MO-Drive, C = Medium-Changer, + = unprovided LUN,\n"); + len += sprintf(buffer + len, " - = nothing found, nothing assigned or unprobed LUN)\n\n"); + + *start = buffer + offset; + len -= offset; + if (len > length) + len = length; + spin_unlock_irqrestore(shpnt->host_lock, flags); + return len; } -void ibmmca_scsi_setup (char *str, int *ints) +static void ibmmca_scsi_setup(char *str, int *ints) { - internal_ibmmca_scsi_setup (str, ints); + internal_ibmmca_scsi_setup(str, ints); } static int option_setup(char *str) { - int ints[IM_MAX_HOSTS]; - char *cur = str; - int i = 1; - - while (cur && isdigit(*cur) && i <= IM_MAX_HOSTS) { - ints[i++] = simple_strtoul(cur, NULL, 0); - if ((cur = strchr(cur,',')) != NULL) cur++; - } - ints[0] = i - 1; - internal_ibmmca_scsi_setup(cur, ints); - return 0; + int ints[IM_MAX_HOSTS]; + char *cur = str; + int i = 1; + + while (cur && isdigit(*cur) && i <= IM_MAX_HOSTS) { + ints[i++] = simple_strtoul(cur, NULL, 0); + if ((cur = strchr(cur, ',')) != NULL) + cur++; + } + ints[0] = i - 1; + internal_ibmmca_scsi_setup(cur, ints); + return 0; } __setup("ibmmcascsi=", option_setup); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/scsi/ibmmca.h linux.2.5.45-ac1/drivers/scsi/ibmmca.h --- linux.2.5.45/drivers/scsi/ibmmca.h 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.45-ac1/drivers/scsi/ibmmca.h 2002-11-03 01:05:41.000000000 +0000 @@ -10,18 +10,14 @@ /* Common forward declarations for all Linux-versions: */ /* Interfaces to the midlevel Linux SCSI driver */ -extern int ibmmca_proc_info (char *, char **, off_t, int, int, int); -extern int ibmmca_detect (Scsi_Host_Template *); -extern int ibmmca_release (struct Scsi_Host *); -extern int ibmmca_command (Scsi_Cmnd *); -extern int ibmmca_queuecommand (Scsi_Cmnd *, void (*done) (Scsi_Cmnd *)); -extern int ibmmca_abort (Scsi_Cmnd *); -extern int ibmmca_reset (Scsi_Cmnd *, unsigned int); -extern int ibmmca_biosparam (struct scsi_device *, struct block_device *, - sector_t, int *); - -/*structure for /proc filesystem */ -extern struct proc_dir_entry proc_scsi_ibmmca; +static int ibmmca_proc_info (char *, char **, off_t, int, int, int); +static int ibmmca_detect (Scsi_Host_Template *); +static int ibmmca_release (struct Scsi_Host *); +static int ibmmca_command (Scsi_Cmnd *); +static int ibmmca_queuecommand (Scsi_Cmnd *, void (*done) (Scsi_Cmnd *)); +static int ibmmca_abort (Scsi_Cmnd *); +static int ibmmca_host_reset (Scsi_Cmnd *); +static int ibmmca_biosparam (struct scsi_device *, struct block_device *, sector_t, int *); /* * 2/8/98 @@ -37,8 +33,8 @@ release: ibmmca_release, /*release fn*/ \ command: ibmmca_command, /*command fn*/ \ queuecommand: ibmmca_queuecommand, /*queuecommand fn*/ \ - abort: ibmmca_abort, /*abort fn*/ \ - reset: ibmmca_reset, /*reset fn*/ \ + eh_abort_handler:ibmmca_abort, /*abort fn*/ \ + eh_host_reset_handler:ibmmca_host_reset, /*reset fn*/ \ bios_param: ibmmca_biosparam, /*bios fn*/ \ can_queue: 16, /*can_queue*/ \ this_id: 7, /*set by detect*/ \ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/scsi/in2000.c linux.2.5.45-ac1/drivers/scsi/in2000.c --- linux.2.5.45/drivers/scsi/in2000.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.45-ac1/drivers/scsi/in2000.c 2002-11-03 00:04:07.000000000 +0000 @@ -16,6 +16,11 @@ * 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. * * Drew Eckhardt's excellent 'Generic NCR5380' sources provided * much of the inspiration and some of the code for this driver. @@ -102,6 +107,10 @@ * this thing into as good a shape as possible, and I'm positive * there are lots of lurking bugs and "Stupid Places". * + * Updated for Linux 2.5 by Alan Cox + * - Using new_eh handler + * - Hopefully got all the locking right again + * See "FIXME" notes for items that could do with more work */ #include @@ -121,8 +130,8 @@ #include "scsi.h" #include "hosts.h" -#define IN2000_VERSION "1.33" -#define IN2000_DATE "26/August/1998" +#define IN2000_VERSION "1.33-2.5" +#define IN2000_DATE "2002/11/03" #include "in2000.h" @@ -174,8 +183,7 @@ */ /* Normally, no defaults are specified... */ -static char *setup_args[] = - {"","","","","","","","",""}; +static char *setup_args[] = { "", "", "", "", "", "", "", "", "" }; /* filled in by 'insmod' */ static char *setup_strings = 0; @@ -184,15 +192,10 @@ MODULE_PARM(setup_strings, "s"); #endif - -static struct Scsi_Host *instance_list = 0; - - - static inline uchar read_3393(struct IN2000_hostdata *hostdata, uchar reg_num) { - write1_io(reg_num,IO_WD_ADDR); - return read1_io(IO_WD_DATA); + write1_io(reg_num, IO_WD_ADDR); + return read1_io(IO_WD_DATA); } @@ -201,8 +204,8 @@ static inline void write_3393(struct IN2000_hostdata *hostdata, uchar reg_num, uchar value) { - write1_io(reg_num,IO_WD_ADDR); - write1_io(value,IO_WD_DATA); + write1_io(reg_num, IO_WD_ADDR); + write1_io(value, IO_WD_DATA); } @@ -210,44 +213,44 @@ { /* while (READ_AUX_STAT() & ASR_CIP) printk("|");*/ - write1_io(WD_COMMAND,IO_WD_ADDR); - write1_io(cmd,IO_WD_DATA); + write1_io(WD_COMMAND, IO_WD_ADDR); + write1_io(cmd, IO_WD_DATA); } static uchar read_1_byte(struct IN2000_hostdata *hostdata) { -uchar asr, x = 0; + uchar asr, x = 0; - write_3393(hostdata,WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED); - write_3393_cmd(hostdata,WD_CMD_TRANS_INFO|0x80); - do { - asr = READ_AUX_STAT(); - if (asr & ASR_DBR) - x = read_3393(hostdata,WD_DATA); - } while (!(asr & ASR_INT)); - return x; + write_3393(hostdata, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED); + write_3393_cmd(hostdata, WD_CMD_TRANS_INFO | 0x80); + do { + asr = READ_AUX_STAT(); + if (asr & ASR_DBR) + x = read_3393(hostdata, WD_DATA); + } while (!(asr & ASR_INT)); + return x; } static void write_3393_count(struct IN2000_hostdata *hostdata, unsigned long value) { - write1_io(WD_TRANSFER_COUNT_MSB,IO_WD_ADDR); - write1_io((value >> 16),IO_WD_DATA); - write1_io((value >> 8),IO_WD_DATA); - write1_io(value,IO_WD_DATA); + write1_io(WD_TRANSFER_COUNT_MSB, IO_WD_ADDR); + write1_io((value >> 16), IO_WD_DATA); + write1_io((value >> 8), IO_WD_DATA); + write1_io(value, IO_WD_DATA); } static unsigned long read_3393_count(struct IN2000_hostdata *hostdata) { -unsigned long value; + unsigned long value; - write1_io(WD_TRANSFER_COUNT_MSB,IO_WD_ADDR); - value = read1_io(IO_WD_DATA) << 16; - value |= read1_io(IO_WD_DATA) << 8; - value |= read1_io(IO_WD_DATA); - return value; + write1_io(WD_TRANSFER_COUNT_MSB, IO_WD_ADDR); + value = read1_io(IO_WD_DATA) << 16; + value |= read1_io(IO_WD_DATA) << 8; + value |= read1_io(IO_WD_DATA); + return value; } @@ -256,87 +259,104 @@ * will be a DATA_OUT phase with this command, false otherwise. * (Thanks to Joerg Dorchain for the research and suggestion.) */ -static int is_dir_out(Scsi_Cmnd *cmd) +static int is_dir_out(Scsi_Cmnd * cmd) { - switch (cmd->cmnd[0]) { - case WRITE_6: case WRITE_10: case WRITE_12: - case WRITE_LONG: case WRITE_SAME: case WRITE_BUFFER: - case WRITE_VERIFY: case WRITE_VERIFY_12: - case COMPARE: case COPY: case COPY_VERIFY: - case SEARCH_EQUAL: case SEARCH_HIGH: case SEARCH_LOW: - case SEARCH_EQUAL_12: case SEARCH_HIGH_12: case SEARCH_LOW_12: - case FORMAT_UNIT: case REASSIGN_BLOCKS: case RESERVE: - case MODE_SELECT: case MODE_SELECT_10: case LOG_SELECT: - case SEND_DIAGNOSTIC: case CHANGE_DEFINITION: case UPDATE_BLOCK: - case SET_WINDOW: case MEDIUM_SCAN: case SEND_VOLUME_TAG: - case 0xea: - return 1; - default: - return 0; - } + switch (cmd->cmnd[0]) { + case WRITE_6: + case WRITE_10: + case WRITE_12: + case WRITE_LONG: + case WRITE_SAME: + case WRITE_BUFFER: + case WRITE_VERIFY: + case WRITE_VERIFY_12: + case COMPARE: + case COPY: + case COPY_VERIFY: + case SEARCH_EQUAL: + case SEARCH_HIGH: + case SEARCH_LOW: + case SEARCH_EQUAL_12: + case SEARCH_HIGH_12: + case SEARCH_LOW_12: + case FORMAT_UNIT: + case REASSIGN_BLOCKS: + case RESERVE: + case MODE_SELECT: + case MODE_SELECT_10: + case LOG_SELECT: + case SEND_DIAGNOSTIC: + case CHANGE_DEFINITION: + case UPDATE_BLOCK: + case SET_WINDOW: + case MEDIUM_SCAN: + case SEND_VOLUME_TAG: + case 0xea: + return 1; + default: + return 0; + } } static struct sx_period sx_table[] = { - { 1, 0x20}, - {252, 0x20}, - {376, 0x30}, - {500, 0x40}, - {624, 0x50}, - {752, 0x60}, - {876, 0x70}, - {1000,0x00}, - {0, 0} }; + {1, 0x20}, + {252, 0x20}, + {376, 0x30}, + {500, 0x40}, + {624, 0x50}, + {752, 0x60}, + {876, 0x70}, + {1000, 0x00}, + {0, 0} +}; static int round_period(unsigned int period) { -int x; + int x; - for (x=1; sx_table[x].period_ns; x++) { - if ((period <= sx_table[x-0].period_ns) && - (period > sx_table[x-1].period_ns)) { - return x; - } - } - return 7; + for (x = 1; sx_table[x].period_ns; x++) { + if ((period <= sx_table[x - 0].period_ns) && (period > sx_table[x - 1].period_ns)) { + return x; + } + } + return 7; } static uchar calc_sync_xfer(unsigned int period, unsigned int offset) { -uchar result; + uchar result; - period *= 4; /* convert SDTR code to ns */ - result = sx_table[round_period(period)].reg_value; - result |= (offset < OPTIMUM_SX_OFF)?offset:OPTIMUM_SX_OFF; - return result; + period *= 4; /* convert SDTR code to ns */ + result = sx_table[round_period(period)].reg_value; + result |= (offset < OPTIMUM_SX_OFF) ? offset : OPTIMUM_SX_OFF; + return result; } static void in2000_execute(struct Scsi_Host *instance); -static int in2000_queuecommand (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) +static int in2000_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) { -struct Scsi_Host *instance; -struct IN2000_hostdata *hostdata; -Scsi_Cmnd *tmp; -unsigned long flags; + struct Scsi_Host *instance; + struct IN2000_hostdata *hostdata; + Scsi_Cmnd *tmp; - instance = cmd->host; - hostdata = (struct IN2000_hostdata *)instance->hostdata; + instance = cmd->host; + hostdata = (struct IN2000_hostdata *) instance->hostdata; -DB(DB_QUEUE_COMMAND,printk("Q-%d-%02x-%ld(",cmd->target,cmd->cmnd[0],cmd->pid)) + DB(DB_QUEUE_COMMAND, printk("Q-%d-%02x-%ld(", cmd->target, cmd->cmnd[0], cmd->pid)) /* Set up a few fields in the Scsi_Cmnd structure for our own use: * - host_scribble is the pointer to the next cmd in the input queue * - scsi_done points to the routine we call when a cmd is finished * - result is what you'd expect */ - - cmd->host_scribble = NULL; - cmd->scsi_done = done; - cmd->result = 0; + cmd->host_scribble = NULL; + cmd->scsi_done = done; + cmd->result = 0; /* We use the Scsi_Pointer structure that's included with each command * as a scratchpad (as it's intended to be used!). The handy thing about @@ -353,19 +373,18 @@ * - SCp.phase records this command's SRCID_ER bit setting */ - if (cmd->use_sg) { - cmd->SCp.buffer = (struct scatterlist *)cmd->buffer; - cmd->SCp.buffers_residual = cmd->use_sg - 1; - cmd->SCp.ptr = (char *)page_address(cmd->SCp.buffer->page)+cmd->SCp.buffer->offset; - cmd->SCp.this_residual = cmd->SCp.buffer->length; - } - else { - cmd->SCp.buffer = NULL; - cmd->SCp.buffers_residual = 0; - cmd->SCp.ptr = (char *)cmd->request_buffer; - cmd->SCp.this_residual = cmd->request_bufflen; - } - cmd->SCp.have_data_in = 0; + if (cmd->use_sg) { + cmd->SCp.buffer = (struct scatterlist *) cmd->buffer; + cmd->SCp.buffers_residual = cmd->use_sg - 1; + cmd->SCp.ptr = (char *) page_address(cmd->SCp.buffer->page) + cmd->SCp.buffer->offset; + cmd->SCp.this_residual = cmd->SCp.buffer->length; + } else { + cmd->SCp.buffer = NULL; + cmd->SCp.buffers_residual = 0; + cmd->SCp.ptr = (char *) cmd->request_buffer; + cmd->SCp.this_residual = cmd->request_bufflen; + } + cmd->SCp.have_data_in = 0; /* We don't set SCp.phase here - that's done in in2000_execute() */ @@ -386,39 +405,34 @@ * status byte is stored. */ - cmd->SCp.Status = ILLEGAL_STATUS_BYTE; + cmd->SCp.Status = ILLEGAL_STATUS_BYTE; /* We need to disable interrupts before messing with the input * queue and calling in2000_execute(). */ - spin_lock_irqsave(instance->host_lock, flags); - /* - * Add the cmd to the end of 'input_Q'. Note that REQUEST_SENSE - * commands are added to the head of the queue so that the desired - * sense data is not lost before REQUEST_SENSE executes. - */ - - if (!(hostdata->input_Q) || (cmd->cmnd[0] == REQUEST_SENSE)) { - cmd->host_scribble = (uchar *)hostdata->input_Q; - hostdata->input_Q = cmd; - } - else { /* find the end of the queue */ - for (tmp=(Scsi_Cmnd *)hostdata->input_Q; tmp->host_scribble; - tmp=(Scsi_Cmnd *)tmp->host_scribble) - ; - tmp->host_scribble = (uchar *)cmd; - } + /* + * Add the cmd to the end of 'input_Q'. Note that REQUEST_SENSE + * commands are added to the head of the queue so that the desired + * sense data is not lost before REQUEST_SENSE executes. + */ + + if (!(hostdata->input_Q) || (cmd->cmnd[0] == REQUEST_SENSE)) { + cmd->host_scribble = (uchar *) hostdata->input_Q; + hostdata->input_Q = cmd; + } else { /* find the end of the queue */ + for (tmp = (Scsi_Cmnd *) hostdata->input_Q; tmp->host_scribble; tmp = (Scsi_Cmnd *) tmp->host_scribble); + tmp->host_scribble = (uchar *) cmd; + } /* We know that there's at least one command in 'input_Q' now. * Go see if any of them are runnable! */ - in2000_execute(cmd->host); + in2000_execute(cmd->host); -DB(DB_QUEUE_COMMAND,printk(")Q-%ld ",cmd->pid)) - spin_unlock_irqrestore(instance->host_lock, flags); - return 0; + DB(DB_QUEUE_COMMAND, printk(")Q-%ld ", cmd->pid)) + return 0; } @@ -431,69 +445,69 @@ * Note that this function is always called with interrupts already * disabled (either from in2000_queuecommand() or in2000_intr()). */ -static void in2000_execute (struct Scsi_Host *instance) +static void in2000_execute(struct Scsi_Host *instance) { -struct IN2000_hostdata *hostdata; -Scsi_Cmnd *cmd, *prev; -int i; -unsigned short *sp; -unsigned short f; -unsigned short flushbuf[16]; + struct IN2000_hostdata *hostdata; + Scsi_Cmnd *cmd, *prev; + int i; + unsigned short *sp; + unsigned short f; + unsigned short flushbuf[16]; - hostdata = (struct IN2000_hostdata *)instance->hostdata; + hostdata = (struct IN2000_hostdata *) instance->hostdata; -DB(DB_EXECUTE,printk("EX(")) + DB(DB_EXECUTE, printk("EX(")) - if (hostdata->selecting || hostdata->connected) { + if (hostdata->selecting || hostdata->connected) { -DB(DB_EXECUTE,printk(")EX-0 ")) + DB(DB_EXECUTE, printk(")EX-0 ")) - return; - } + return; + } - /* - * Search through the input_Q for a command destined - * for an idle target/lun. - */ + /* + * Search through the input_Q for a command destined + * for an idle target/lun. + */ - cmd = (Scsi_Cmnd *)hostdata->input_Q; - prev = 0; - while (cmd) { - if (!(hostdata->busy[cmd->target] & (1 << cmd->lun))) - break; - prev = cmd; - cmd = (Scsi_Cmnd *)cmd->host_scribble; - } + cmd = (Scsi_Cmnd *) hostdata->input_Q; + prev = 0; + while (cmd) { + if (!(hostdata->busy[cmd->target] & (1 << cmd->lun))) + break; + prev = cmd; + cmd = (Scsi_Cmnd *) cmd->host_scribble; + } - /* quit if queue empty or all possible targets are busy */ + /* quit if queue empty or all possible targets are busy */ - if (!cmd) { + if (!cmd) { -DB(DB_EXECUTE,printk(")EX-1 ")) + DB(DB_EXECUTE, printk(")EX-1 ")) - return; - } + return; + } - /* remove command from queue */ - - if (prev) - prev->host_scribble = cmd->host_scribble; - else - hostdata->input_Q = (Scsi_Cmnd *)cmd->host_scribble; + /* remove command from queue */ + + if (prev) + prev->host_scribble = cmd->host_scribble; + else + hostdata->input_Q = (Scsi_Cmnd *) cmd->host_scribble; #ifdef PROC_STATISTICS - hostdata->cmd_cnt[cmd->target]++; + hostdata->cmd_cnt[cmd->target]++; #endif /* * Start the selection process */ - if (is_dir_out(cmd)) - write_3393(hostdata,WD_DESTINATION_ID, cmd->target); - else - write_3393(hostdata,WD_DESTINATION_ID, cmd->target | DSTID_DPD); + if (is_dir_out(cmd)) + write_3393(hostdata, WD_DESTINATION_ID, cmd->target); + else + write_3393(hostdata, WD_DESTINATION_ID, cmd->target | DSTID_DPD); /* Now we need to figure out whether or not this command is a good * candidate for disconnect/reselect. We guess to the best of our @@ -518,54 +532,51 @@ * to change around and experiment with for now. */ - cmd->SCp.phase = 0; /* assume no disconnect */ - if (hostdata->disconnect == DIS_NEVER) - goto no; - if (hostdata->disconnect == DIS_ALWAYS) - goto yes; - if (cmd->device->type == 1) /* tape drive? */ - goto yes; - if (hostdata->disconnected_Q) /* other commands disconnected? */ - goto yes; - if (!(hostdata->input_Q)) /* input_Q empty? */ - goto no; - for (prev=(Scsi_Cmnd *)hostdata->input_Q; prev; - prev=(Scsi_Cmnd *)prev->host_scribble) { - if ((prev->target != cmd->target) || (prev->lun != cmd->lun)) { - for (prev=(Scsi_Cmnd *)hostdata->input_Q; prev; - prev=(Scsi_Cmnd *)prev->host_scribble) - prev->SCp.phase = 1; - goto yes; - } - } - goto no; + cmd->SCp.phase = 0; /* assume no disconnect */ + if (hostdata->disconnect == DIS_NEVER) + goto no; + if (hostdata->disconnect == DIS_ALWAYS) + goto yes; + if (cmd->device->type == 1) /* tape drive? */ + goto yes; + if (hostdata->disconnected_Q) /* other commands disconnected? */ + goto yes; + if (!(hostdata->input_Q)) /* input_Q empty? */ + goto no; + for (prev = (Scsi_Cmnd *) hostdata->input_Q; prev; prev = (Scsi_Cmnd *) prev->host_scribble) { + if ((prev->target != cmd->target) || (prev->lun != cmd->lun)) { + for (prev = (Scsi_Cmnd *) hostdata->input_Q; prev; prev = (Scsi_Cmnd *) prev->host_scribble) + prev->SCp.phase = 1; + goto yes; + } + } + goto no; -yes: - cmd->SCp.phase = 1; + yes: + cmd->SCp.phase = 1; #ifdef PROC_STATISTICS - hostdata->disc_allowed_cnt[cmd->target]++; + hostdata->disc_allowed_cnt[cmd->target]++; #endif -no: - write_3393(hostdata,WD_SOURCE_ID,((cmd->SCp.phase)?SRCID_ER:0)); + no: + write_3393(hostdata, WD_SOURCE_ID, ((cmd->SCp.phase) ? SRCID_ER : 0)); - write_3393(hostdata,WD_TARGET_LUN, cmd->lun); - write_3393(hostdata,WD_SYNCHRONOUS_TRANSFER,hostdata->sync_xfer[cmd->target]); - hostdata->busy[cmd->target] |= (1 << cmd->lun); - - if ((hostdata->level2 <= L2_NONE) || - (hostdata->sync_stat[cmd->target] == SS_UNSET)) { - - /* - * Do a 'Select-With-ATN' command. This will end with - * one of the following interrupts: - * CSR_RESEL_AM: failure - can try again later. - * CSR_TIMEOUT: failure - give up. - * CSR_SELECT: success - proceed. - */ + write_3393(hostdata, WD_TARGET_LUN, cmd->lun); + write_3393(hostdata, WD_SYNCHRONOUS_TRANSFER, hostdata->sync_xfer[cmd->target]); + hostdata->busy[cmd->target] |= (1 << cmd->lun); + + if ((hostdata->level2 <= L2_NONE) || (hostdata->sync_stat[cmd->target] == SS_UNSET)) { + + /* + * Do a 'Select-With-ATN' command. This will end with + * one of the following interrupts: + * CSR_RESEL_AM: failure - can try again later. + * CSR_TIMEOUT: failure - give up. + * CSR_SELECT: success - proceed. + */ - hostdata->selecting = cmd; + hostdata->selecting = cmd; /* Every target has its own synchronous transfer setting, kept in * the sync_xfer array, and a corresponding status byte in sync_stat[]. @@ -577,176 +588,173 @@ * unless we don't want to even _try_ synchronous transfers: In this * case we set SS_SET to make the defaults final. */ - if (hostdata->sync_stat[cmd->target] == SS_UNSET) { - if (hostdata->sync_off & (1 << cmd->target)) - hostdata->sync_stat[cmd->target] = SS_SET; - else - hostdata->sync_stat[cmd->target] = SS_FIRST; - } - hostdata->state = S_SELECTING; - write_3393_count(hostdata,0); /* this guarantees a DATA_PHASE interrupt */ - write_3393_cmd(hostdata,WD_CMD_SEL_ATN); - } - - else { - - /* - * Do a 'Select-With-ATN-Xfer' command. This will end with - * one of the following interrupts: - * CSR_RESEL_AM: failure - can try again later. - * CSR_TIMEOUT: failure - give up. - * anything else: success - proceed. - */ - - hostdata->connected = cmd; - write_3393(hostdata,WD_COMMAND_PHASE, 0); - - /* copy command_descriptor_block into WD chip - * (take advantage of auto-incrementing) - */ - - write1_io(WD_CDB_1, IO_WD_ADDR); - for (i=0; icmd_len; i++) - write1_io(cmd->cmnd[i], IO_WD_DATA); - - /* The wd33c93 only knows about Group 0, 1, and 5 commands when - * it's doing a 'select-and-transfer'. To be safe, we write the - * size of the CDB into the OWN_ID register for every case. This - * way there won't be problems with vendor-unique, audio, etc. - */ - - write_3393(hostdata, WD_OWN_ID, cmd->cmd_len); - - /* When doing a non-disconnect command, we can save ourselves a DATA - * phase interrupt later by setting everything up now. With writes we - * need to pre-fill the fifo; if there's room for the 32 flush bytes, - * put them in there too - that'll avoid a fifo interrupt. Reads are - * somewhat simpler. - * KLUDGE NOTE: It seems that you can't completely fill the fifo here: - * This results in the IO_FIFO_COUNT register rolling over to zero, - * and apparently the gate array logic sees this as empty, not full, - * so the 3393 chip is never signalled to start reading from the - * fifo. Or maybe it's seen as a permanent fifo interrupt condition. - * Regardless, we fix this by temporarily pretending that the fifo - * is 16 bytes smaller. (I see now that the old driver has a comment - * about "don't fill completely" in an analogous place - must be the - * same deal.) This results in CDROM, swap partitions, and tape drives - * needing an extra interrupt per write command - I think we can live - * with that! - */ - - if (!(cmd->SCp.phase)) { - write_3393_count(hostdata, cmd->SCp.this_residual); - write_3393(hostdata,WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_BUS); - write1_io(0, IO_FIFO_WRITE); /* clear fifo counter, write mode */ - - if (is_dir_out(cmd)) { - hostdata->fifo = FI_FIFO_WRITING; - if ((i = cmd->SCp.this_residual) > (IN2000_FIFO_SIZE - 16) ) - i = IN2000_FIFO_SIZE - 16; - cmd->SCp.have_data_in = i; /* this much data in fifo */ - i >>= 1; /* Gulp. Assuming modulo 2. */ - sp = (unsigned short *)cmd->SCp.ptr; - f = hostdata->io_base + IO_FIFO; + if (hostdata->sync_stat[cmd->target] == SS_UNSET) { + if (hostdata->sync_off & (1 << cmd->target)) + hostdata->sync_stat[cmd->target] = SS_SET; + else + hostdata->sync_stat[cmd->target] = SS_FIRST; + } + hostdata->state = S_SELECTING; + write_3393_count(hostdata, 0); /* this guarantees a DATA_PHASE interrupt */ + write_3393_cmd(hostdata, WD_CMD_SEL_ATN); + } + + else { + + /* + * Do a 'Select-With-ATN-Xfer' command. This will end with + * one of the following interrupts: + * CSR_RESEL_AM: failure - can try again later. + * CSR_TIMEOUT: failure - give up. + * anything else: success - proceed. + */ + + hostdata->connected = cmd; + write_3393(hostdata, WD_COMMAND_PHASE, 0); + + /* copy command_descriptor_block into WD chip + * (take advantage of auto-incrementing) + */ + + write1_io(WD_CDB_1, IO_WD_ADDR); + for (i = 0; i < cmd->cmd_len; i++) + write1_io(cmd->cmnd[i], IO_WD_DATA); + + /* The wd33c93 only knows about Group 0, 1, and 5 commands when + * it's doing a 'select-and-transfer'. To be safe, we write the + * size of the CDB into the OWN_ID register for every case. This + * way there won't be problems with vendor-unique, audio, etc. + */ + + write_3393(hostdata, WD_OWN_ID, cmd->cmd_len); + + /* When doing a non-disconnect command, we can save ourselves a DATA + * phase interrupt later by setting everything up now. With writes we + * need to pre-fill the fifo; if there's room for the 32 flush bytes, + * put them in there too - that'll avoid a fifo interrupt. Reads are + * somewhat simpler. + * KLUDGE NOTE: It seems that you can't completely fill the fifo here: + * This results in the IO_FIFO_COUNT register rolling over to zero, + * and apparently the gate array logic sees this as empty, not full, + * so the 3393 chip is never signalled to start reading from the + * fifo. Or maybe it's seen as a permanent fifo interrupt condition. + * Regardless, we fix this by temporarily pretending that the fifo + * is 16 bytes smaller. (I see now that the old driver has a comment + * about "don't fill completely" in an analogous place - must be the + * same deal.) This results in CDROM, swap partitions, and tape drives + * needing an extra interrupt per write command - I think we can live + * with that! + */ + + if (!(cmd->SCp.phase)) { + write_3393_count(hostdata, cmd->SCp.this_residual); + write_3393(hostdata, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_BUS); + write1_io(0, IO_FIFO_WRITE); /* clear fifo counter, write mode */ + + if (is_dir_out(cmd)) { + hostdata->fifo = FI_FIFO_WRITING; + if ((i = cmd->SCp.this_residual) > (IN2000_FIFO_SIZE - 16)) + i = IN2000_FIFO_SIZE - 16; + cmd->SCp.have_data_in = i; /* this much data in fifo */ + i >>= 1; /* Gulp. Assuming modulo 2. */ + sp = (unsigned short *) cmd->SCp.ptr; + f = hostdata->io_base + IO_FIFO; #ifdef FAST_WRITE_IO - FAST_WRITE2_IO(); + FAST_WRITE2_IO(); #else - while (i--) - write2_io(*sp++,IO_FIFO); + while (i--) + write2_io(*sp++, IO_FIFO); #endif - /* Is there room for the flush bytes? */ + /* Is there room for the flush bytes? */ - if (cmd->SCp.have_data_in <= ((IN2000_FIFO_SIZE - 16) - 32)) { - sp = flushbuf; - i = 16; + if (cmd->SCp.have_data_in <= ((IN2000_FIFO_SIZE - 16) - 32)) { + sp = flushbuf; + i = 16; #ifdef FAST_WRITE_IO - FAST_WRITE2_IO(); + FAST_WRITE2_IO(); #else - while (i--) - write2_io(0,IO_FIFO); + while (i--) + write2_io(0, IO_FIFO); #endif - } - } + } + } + + else { + write1_io(0, IO_FIFO_READ); /* put fifo in read mode */ + hostdata->fifo = FI_FIFO_READING; + cmd->SCp.have_data_in = 0; /* nothing transferred yet */ + } - else { - write1_io(0, IO_FIFO_READ); /* put fifo in read mode */ - hostdata->fifo = FI_FIFO_READING; - cmd->SCp.have_data_in = 0; /* nothing transferred yet */ - } + } else { + write_3393_count(hostdata, 0); /* this guarantees a DATA_PHASE interrupt */ + } + hostdata->state = S_RUNNING_LEVEL2; + write_3393_cmd(hostdata, WD_CMD_SEL_ATN_XFER); + } - } - else { - write_3393_count(hostdata,0); /* this guarantees a DATA_PHASE interrupt */ - } - hostdata->state = S_RUNNING_LEVEL2; - write_3393_cmd(hostdata,WD_CMD_SEL_ATN_XFER); - } + /* + * Since the SCSI bus can handle only 1 connection at a time, + * we get out of here now. If the selection fails, or when + * the command disconnects, we'll come back to this routine + * to search the input_Q again... + */ - /* - * Since the SCSI bus can handle only 1 connection at a time, - * we get out of here now. If the selection fails, or when - * the command disconnects, we'll come back to this routine - * to search the input_Q again... - */ - -DB(DB_EXECUTE,printk("%s%ld)EX-2 ",(cmd->SCp.phase)?"d:":"",cmd->pid)) + DB(DB_EXECUTE, printk("%s%ld)EX-2 ", (cmd->SCp.phase) ? "d:" : "", cmd->pid)) } -static void transfer_pio(uchar *buf, int cnt, - int data_in_dir, struct IN2000_hostdata *hostdata) +static void transfer_pio(uchar * buf, int cnt, int data_in_dir, struct IN2000_hostdata *hostdata) { -uchar asr; + uchar asr; -DB(DB_TRANSFER,printk("(%p,%d,%s)",buf,cnt,data_in_dir?"in":"out")) + DB(DB_TRANSFER, printk("(%p,%d,%s)", buf, cnt, data_in_dir ? "in" : "out")) - write_3393(hostdata,WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED); - write_3393_count(hostdata,cnt); - write_3393_cmd(hostdata,WD_CMD_TRANS_INFO); - if (data_in_dir) { - do { - asr = READ_AUX_STAT(); - if (asr & ASR_DBR) - *buf++ = read_3393(hostdata,WD_DATA); - } while (!(asr & ASR_INT)); - } - else { - do { - asr = READ_AUX_STAT(); - if (asr & ASR_DBR) - write_3393(hostdata,WD_DATA, *buf++); - } while (!(asr & ASR_INT)); - } + write_3393(hostdata, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED); + write_3393_count(hostdata, cnt); + write_3393_cmd(hostdata, WD_CMD_TRANS_INFO); + if (data_in_dir) { + do { + asr = READ_AUX_STAT(); + if (asr & ASR_DBR) + *buf++ = read_3393(hostdata, WD_DATA); + } while (!(asr & ASR_INT)); + } else { + do { + asr = READ_AUX_STAT(); + if (asr & ASR_DBR) + write_3393(hostdata, WD_DATA, *buf++); + } while (!(asr & ASR_INT)); + } - /* Note: we are returning with the interrupt UN-cleared. - * Since (presumably) an entire I/O operation has - * completed, the bus phase is probably different, and - * the interrupt routine will discover this when it - * responds to the uncleared int. - */ + /* Note: we are returning with the interrupt UN-cleared. + * Since (presumably) an entire I/O operation has + * completed, the bus phase is probably different, and + * the interrupt routine will discover this when it + * responds to the uncleared int. + */ } -static void transfer_bytes(Scsi_Cmnd *cmd, int data_in_dir) +static void transfer_bytes(Scsi_Cmnd * cmd, int data_in_dir) { -struct IN2000_hostdata *hostdata; -unsigned short *sp; -unsigned short f; -int i; + struct IN2000_hostdata *hostdata; + unsigned short *sp; + unsigned short f; + int i; - hostdata = (struct IN2000_hostdata *)cmd->host->hostdata; + hostdata = (struct IN2000_hostdata *) cmd->host->hostdata; /* Normally, you'd expect 'this_residual' to be non-zero here. * In a series of scatter-gather transfers, however, this @@ -756,67 +764,63 @@ * now we need to setup the next scatter-gather buffer as the * source or destination for THIS transfer. */ - if (!cmd->SCp.this_residual && cmd->SCp.buffers_residual) { - ++cmd->SCp.buffer; - --cmd->SCp.buffers_residual; - cmd->SCp.this_residual = cmd->SCp.buffer->length; - cmd->SCp.ptr = page_address(cmd->SCp.buffer->page) + cmd->SCp.buffer->offset; - } + if (!cmd->SCp.this_residual && cmd->SCp.buffers_residual) { + ++cmd->SCp.buffer; + --cmd->SCp.buffers_residual; + cmd->SCp.this_residual = cmd->SCp.buffer->length; + cmd->SCp.ptr = page_address(cmd->SCp.buffer->page) + cmd->SCp.buffer->offset; + } /* Set up hardware registers */ - write_3393(hostdata,WD_SYNCHRONOUS_TRANSFER,hostdata->sync_xfer[cmd->target]); - write_3393_count(hostdata,cmd->SCp.this_residual); - write_3393(hostdata,WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_BUS); - write1_io(0,IO_FIFO_WRITE); /* zero counter, assume write */ + write_3393(hostdata, WD_SYNCHRONOUS_TRANSFER, hostdata->sync_xfer[cmd->target]); + write_3393_count(hostdata, cmd->SCp.this_residual); + write_3393(hostdata, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_BUS); + write1_io(0, IO_FIFO_WRITE); /* zero counter, assume write */ /* Reading is easy. Just issue the command and return - we'll * get an interrupt later when we have actual data to worry about. */ - if (data_in_dir) { - write1_io(0,IO_FIFO_READ); - if ((hostdata->level2 >= L2_DATA) || - (hostdata->level2 == L2_BASIC && cmd->SCp.phase == 0)) { - write_3393(hostdata,WD_COMMAND_PHASE,0x45); - write_3393_cmd(hostdata,WD_CMD_SEL_ATN_XFER); - hostdata->state = S_RUNNING_LEVEL2; - } - else - write_3393_cmd(hostdata,WD_CMD_TRANS_INFO); - hostdata->fifo = FI_FIFO_READING; - cmd->SCp.have_data_in = 0; - return; - } + if (data_in_dir) { + write1_io(0, IO_FIFO_READ); + if ((hostdata->level2 >= L2_DATA) || (hostdata->level2 == L2_BASIC && cmd->SCp.phase == 0)) { + write_3393(hostdata, WD_COMMAND_PHASE, 0x45); + write_3393_cmd(hostdata, WD_CMD_SEL_ATN_XFER); + hostdata->state = S_RUNNING_LEVEL2; + } else + write_3393_cmd(hostdata, WD_CMD_TRANS_INFO); + hostdata->fifo = FI_FIFO_READING; + cmd->SCp.have_data_in = 0; + return; + } /* Writing is more involved - we'll start the WD chip and write as * much data to the fifo as we can right now. Later interrupts will * write any bytes that don't make it at this stage. */ - if ((hostdata->level2 >= L2_DATA) || - (hostdata->level2 == L2_BASIC && cmd->SCp.phase == 0)) { - write_3393(hostdata,WD_COMMAND_PHASE,0x45); - write_3393_cmd(hostdata,WD_CMD_SEL_ATN_XFER); - hostdata->state = S_RUNNING_LEVEL2; - } - else - write_3393_cmd(hostdata,WD_CMD_TRANS_INFO); - hostdata->fifo = FI_FIFO_WRITING; - sp = (unsigned short *)cmd->SCp.ptr; - - if ((i = cmd->SCp.this_residual) > IN2000_FIFO_SIZE) - i = IN2000_FIFO_SIZE; - cmd->SCp.have_data_in = i; - i >>= 1; /* Gulp. We assume this_residual is modulo 2 */ - f = hostdata->io_base + IO_FIFO; + if ((hostdata->level2 >= L2_DATA) || (hostdata->level2 == L2_BASIC && cmd->SCp.phase == 0)) { + write_3393(hostdata, WD_COMMAND_PHASE, 0x45); + write_3393_cmd(hostdata, WD_CMD_SEL_ATN_XFER); + hostdata->state = S_RUNNING_LEVEL2; + } else + write_3393_cmd(hostdata, WD_CMD_TRANS_INFO); + hostdata->fifo = FI_FIFO_WRITING; + sp = (unsigned short *) cmd->SCp.ptr; + + if ((i = cmd->SCp.this_residual) > IN2000_FIFO_SIZE) + i = IN2000_FIFO_SIZE; + cmd->SCp.have_data_in = i; + i >>= 1; /* Gulp. We assume this_residual is modulo 2 */ + f = hostdata->io_base + IO_FIFO; #ifdef FAST_WRITE_IO - FAST_WRITE2_IO(); + FAST_WRITE2_IO(); #else - while (i--) - write2_io(*sp++,IO_FIFO); + while (i--) + write2_io(*sp++, IO_FIFO); #endif @@ -829,26 +833,26 @@ * but it _does_ need to be able to compile and run in an SMP kernel.) */ -static void in2000_intr (int irqnum, void * dev_id, struct pt_regs *ptregs) +static void in2000_intr(int irqnum, void *dev_id, struct pt_regs *ptregs) { -struct Scsi_Host *instance = dev_id; -struct IN2000_hostdata *hostdata; -Scsi_Cmnd *patch, *cmd; -uchar asr, sr, phs, id, lun, *ucp, msg; -int i,j; -unsigned long length; -unsigned short *sp; -unsigned short f; -unsigned long flags; + struct Scsi_Host *instance = dev_id; + struct IN2000_hostdata *hostdata; + Scsi_Cmnd *patch, *cmd; + uchar asr, sr, phs, id, lun, *ucp, msg; + int i, j; + unsigned long length; + unsigned short *sp; + unsigned short f; + unsigned long flags; - hostdata = (struct IN2000_hostdata *)instance->hostdata; + hostdata = (struct IN2000_hostdata *) instance->hostdata; /* Get the spin_lock and disable further ints, for SMP */ - spin_lock_irqsave(instance->host_lock, flags); + spin_lock_irqsave(instance->host_lock, flags); #ifdef PROC_STATISTICS - hostdata->int_cnt++; + hostdata->int_cnt++; #endif /* The IN2000 card has 2 interrupt sources OR'ed onto its IRQ line - the @@ -886,9 +890,9 @@ * state. Who'd a thought? */ - write1_io(0, IO_LED_ON); - asr = READ_AUX_STAT(); - if (!(asr & ASR_INT)) { /* no WD33c93 interrupt? */ + write1_io(0, IO_LED_ON); + asr = READ_AUX_STAT(); + if (!(asr & ASR_INT)) { /* no WD33c93 interrupt? */ /* Ok. This is definitely a FIFO-only interrupt. * @@ -909,35 +913,35 @@ * (Big thanks to Bill Earnest for getting me out of the mud in here.) */ - cmd = (Scsi_Cmnd *)hostdata->connected; /* assume we're connected */ -CHECK_NULL(cmd,"fifo_int") + cmd = (Scsi_Cmnd *) hostdata->connected; /* assume we're connected */ + CHECK_NULL(cmd, "fifo_int") - if (hostdata->fifo == FI_FIFO_READING) { + if (hostdata->fifo == FI_FIFO_READING) { -DB(DB_FIFO,printk("{R:%02x} ",read1_io(IO_FIFO_COUNT))) + DB(DB_FIFO, printk("{R:%02x} ", read1_io(IO_FIFO_COUNT))) - sp = (unsigned short *)(cmd->SCp.ptr + cmd->SCp.have_data_in); - i = read1_io(IO_FIFO_COUNT) & 0xfe; - i <<= 2; /* # of words waiting in the fifo */ - f = hostdata->io_base + IO_FIFO; + sp = (unsigned short *) (cmd->SCp.ptr + cmd->SCp.have_data_in); + i = read1_io(IO_FIFO_COUNT) & 0xfe; + i <<= 2; /* # of words waiting in the fifo */ + f = hostdata->io_base + IO_FIFO; #ifdef FAST_READ_IO - FAST_READ2_IO(); + FAST_READ2_IO(); #else - while (i--) - *sp++ = read2_io(IO_FIFO); + while (i--) + *sp++ = read2_io(IO_FIFO); #endif - i = sp - (unsigned short *)(cmd->SCp.ptr + cmd->SCp.have_data_in); - i <<= 1; - cmd->SCp.have_data_in += i; - } + i = sp - (unsigned short *) (cmd->SCp.ptr + cmd->SCp.have_data_in); + i <<= 1; + cmd->SCp.have_data_in += i; + } - else if (hostdata->fifo == FI_FIFO_WRITING) { + else if (hostdata->fifo == FI_FIFO_WRITING) { -DB(DB_FIFO,printk("{W:%02x} ",read1_io(IO_FIFO_COUNT))) + DB(DB_FIFO, printk("{W:%02x} ", read1_io(IO_FIFO_COUNT))) /* If all bytes have been written to the fifo, flush out the stragglers. * Note that while writing 16 dummy words seems arbitrary, we don't @@ -949,63 +953,62 @@ * UPDATE: Bill says this is exactly what Always does, so there. * More thanks due him for help in this section. */ - - if (cmd->SCp.this_residual == cmd->SCp.have_data_in) { - i = 16; - while (i--) /* write 32 dummy bytes */ - write2_io(0,IO_FIFO); - } + if (cmd->SCp.this_residual == cmd->SCp.have_data_in) { + i = 16; + while (i--) /* write 32 dummy bytes */ + write2_io(0, IO_FIFO); + } /* If there are still bytes left in the SCSI buffer, write as many as we * can out to the fifo. */ - else { - sp = (unsigned short *)(cmd->SCp.ptr + cmd->SCp.have_data_in); - i = cmd->SCp.this_residual - cmd->SCp.have_data_in; /* bytes yet to go */ - j = read1_io(IO_FIFO_COUNT) & 0xfe; - j <<= 2; /* how many words the fifo has room for */ - if ((j << 1) > i) - j = (i >> 1); - while (j--) - write2_io(*sp++,IO_FIFO); - - i = sp - (unsigned short *)(cmd->SCp.ptr + cmd->SCp.have_data_in); - i <<= 1; - cmd->SCp.have_data_in += i; - } - } - - else { - printk("*** Spurious FIFO interrupt ***"); - } + else { + sp = (unsigned short *) (cmd->SCp.ptr + cmd->SCp.have_data_in); + i = cmd->SCp.this_residual - cmd->SCp.have_data_in; /* bytes yet to go */ + j = read1_io(IO_FIFO_COUNT) & 0xfe; + j <<= 2; /* how many words the fifo has room for */ + if ((j << 1) > i) + j = (i >> 1); + while (j--) + write2_io(*sp++, IO_FIFO); + + i = sp - (unsigned short *) (cmd->SCp.ptr + cmd->SCp.have_data_in); + i <<= 1; + cmd->SCp.have_data_in += i; + } + } + + else { + printk("*** Spurious FIFO interrupt ***"); + } - write1_io(0, IO_LED_OFF); + write1_io(0, IO_LED_OFF); /* release the SMP spin_lock and restore irq state */ - spin_unlock_irqrestore(instance->host_lock, flags); - return; - } + spin_unlock_irqrestore(instance->host_lock, flags); + return; + } /* This interrupt was triggered by the WD33c93 chip. The fifo interrupt * may also be asserted, but we don't bother to check it: we get more * detailed info from FIFO_READING and FIFO_WRITING (see below). */ - cmd = (Scsi_Cmnd *)hostdata->connected; /* assume we're connected */ - sr = read_3393(hostdata,WD_SCSI_STATUS); /* clear the interrupt */ - phs = read_3393(hostdata,WD_COMMAND_PHASE); - - if (!cmd && (sr != CSR_RESEL_AM && sr != CSR_TIMEOUT && sr != CSR_SELECT)) { - printk("\nNR:wd-intr-1\n"); - write1_io(0, IO_LED_OFF); + cmd = (Scsi_Cmnd *) hostdata->connected; /* assume we're connected */ + sr = read_3393(hostdata, WD_SCSI_STATUS); /* clear the interrupt */ + phs = read_3393(hostdata, WD_COMMAND_PHASE); + + if (!cmd && (sr != CSR_RESEL_AM && sr != CSR_TIMEOUT && sr != CSR_SELECT)) { + printk("\nNR:wd-intr-1\n"); + write1_io(0, IO_LED_OFF); /* release the SMP spin_lock and restore irq state */ - spin_unlock_irqrestore(instance->host_lock, flags); - return; - } + spin_unlock_irqrestore(instance->host_lock, flags); + return; + } -DB(DB_INTR,printk("{%02x:%02x-",asr,sr)) + DB(DB_INTR, printk("{%02x:%02x-", asr, sr)) /* After starting a FIFO-based transfer, the next _WD3393_ interrupt is * guaranteed to be in response to the completion of the transfer. @@ -1019,239 +1022,234 @@ * After doing whatever is necessary with the fifo, we go on and * service the WD3393 interrupt normally. */ - - if (hostdata->fifo == FI_FIFO_READING) { + if (hostdata->fifo == FI_FIFO_READING) { /* buffer index = start-of-buffer + #-of-bytes-already-read */ - sp = (unsigned short *)(cmd->SCp.ptr + cmd->SCp.have_data_in); + sp = (unsigned short *) (cmd->SCp.ptr + cmd->SCp.have_data_in); /* bytes remaining in fifo = (total-wanted - #-not-got) - #-already-read */ - i = (cmd->SCp.this_residual - read_3393_count(hostdata)) - cmd->SCp.have_data_in; - i >>= 1; /* Gulp. We assume this will always be modulo 2 */ - f = hostdata->io_base + IO_FIFO; + i = (cmd->SCp.this_residual - read_3393_count(hostdata)) - cmd->SCp.have_data_in; + i >>= 1; /* Gulp. We assume this will always be modulo 2 */ + f = hostdata->io_base + IO_FIFO; #ifdef FAST_READ_IO - FAST_READ2_IO(); + FAST_READ2_IO(); #else - while (i--) - *sp++ = read2_io(IO_FIFO); + while (i--) + *sp++ = read2_io(IO_FIFO); #endif - hostdata->fifo = FI_FIFO_UNUSED; - length = cmd->SCp.this_residual; - cmd->SCp.this_residual = read_3393_count(hostdata); - cmd->SCp.ptr += (length - cmd->SCp.this_residual); + hostdata->fifo = FI_FIFO_UNUSED; + length = cmd->SCp.this_residual; + cmd->SCp.this_residual = read_3393_count(hostdata); + cmd->SCp.ptr += (length - cmd->SCp.this_residual); -DB(DB_TRANSFER,printk("(%p,%d)",cmd->SCp.ptr,cmd->SCp.this_residual)) + DB(DB_TRANSFER, printk("(%p,%d)", cmd->SCp.ptr, cmd->SCp.this_residual)) - } + } - else if (hostdata->fifo == FI_FIFO_WRITING) { - hostdata->fifo = FI_FIFO_UNUSED; - length = cmd->SCp.this_residual; - cmd->SCp.this_residual = read_3393_count(hostdata); - cmd->SCp.ptr += (length - cmd->SCp.this_residual); + else if (hostdata->fifo == FI_FIFO_WRITING) { + hostdata->fifo = FI_FIFO_UNUSED; + length = cmd->SCp.this_residual; + cmd->SCp.this_residual = read_3393_count(hostdata); + cmd->SCp.ptr += (length - cmd->SCp.this_residual); -DB(DB_TRANSFER,printk("(%p,%d)",cmd->SCp.ptr,cmd->SCp.this_residual)) + DB(DB_TRANSFER, printk("(%p,%d)", cmd->SCp.ptr, cmd->SCp.this_residual)) - } + } /* Respond to the specific WD3393 interrupt - there are quite a few! */ - switch (sr) { + switch (sr) { - case CSR_TIMEOUT: -DB(DB_INTR,printk("TIMEOUT")) + case CSR_TIMEOUT: + DB(DB_INTR, printk("TIMEOUT")) - if (hostdata->state == S_RUNNING_LEVEL2) - hostdata->connected = NULL; - else { - cmd = (Scsi_Cmnd *)hostdata->selecting; /* get a valid cmd */ -CHECK_NULL(cmd,"csr_timeout") - hostdata->selecting = NULL; - } - - cmd->result = DID_NO_CONNECT << 16; - hostdata->busy[cmd->target] &= ~(1 << cmd->lun); - hostdata->state = S_UNCONNECTED; - cmd->scsi_done(cmd); + if (hostdata->state == S_RUNNING_LEVEL2) + hostdata->connected = NULL; + else { + cmd = (Scsi_Cmnd *) hostdata->selecting; /* get a valid cmd */ + CHECK_NULL(cmd, "csr_timeout") + hostdata->selecting = NULL; + } + + cmd->result = DID_NO_CONNECT << 16; + hostdata->busy[cmd->target] &= ~(1 << cmd->lun); + hostdata->state = S_UNCONNECTED; + cmd->scsi_done(cmd); /* We are not connected to a target - check to see if there * are commands waiting to be executed. */ - in2000_execute(instance); - break; + in2000_execute(instance); + break; /* Note: this interrupt should not occur in a LEVEL2 command */ - case CSR_SELECT: -DB(DB_INTR,printk("SELECT")) - hostdata->connected = cmd = (Scsi_Cmnd *)hostdata->selecting; -CHECK_NULL(cmd,"csr_select") - hostdata->selecting = NULL; - - /* construct an IDENTIFY message with correct disconnect bit */ - - hostdata->outgoing_msg[0] = (0x80 | 0x00 | cmd->lun); - if (cmd->SCp.phase) - hostdata->outgoing_msg[0] |= 0x40; + case CSR_SELECT: + DB(DB_INTR, printk("SELECT")) + hostdata->connected = cmd = (Scsi_Cmnd *) hostdata->selecting; + CHECK_NULL(cmd, "csr_select") + hostdata->selecting = NULL; + + /* construct an IDENTIFY message with correct disconnect bit */ + + hostdata->outgoing_msg[0] = (0x80 | 0x00 | cmd->lun); + if (cmd->SCp.phase) + hostdata->outgoing_msg[0] |= 0x40; - if (hostdata->sync_stat[cmd->target] == SS_FIRST) { + if (hostdata->sync_stat[cmd->target] == SS_FIRST) { #ifdef SYNC_DEBUG -printk(" sending SDTR "); + printk(" sending SDTR "); #endif - hostdata->sync_stat[cmd->target] = SS_WAITING; + hostdata->sync_stat[cmd->target] = SS_WAITING; - /* tack on a 2nd message to ask about synchronous transfers */ + /* tack on a 2nd message to ask about synchronous transfers */ - hostdata->outgoing_msg[1] = EXTENDED_MESSAGE; - hostdata->outgoing_msg[2] = 3; - hostdata->outgoing_msg[3] = EXTENDED_SDTR; - hostdata->outgoing_msg[4] = OPTIMUM_SX_PER/4; - hostdata->outgoing_msg[5] = OPTIMUM_SX_OFF; - hostdata->outgoing_len = 6; - } - else - hostdata->outgoing_len = 1; - - hostdata->state = S_CONNECTED; - break; - - - case CSR_XFER_DONE|PHS_DATA_IN: - case CSR_UNEXP |PHS_DATA_IN: - case CSR_SRV_REQ |PHS_DATA_IN: -DB(DB_INTR,printk("IN-%d.%d",cmd->SCp.this_residual,cmd->SCp.buffers_residual)) - transfer_bytes(cmd, DATA_IN_DIR); - if (hostdata->state != S_RUNNING_LEVEL2) - hostdata->state = S_CONNECTED; - break; - - - case CSR_XFER_DONE|PHS_DATA_OUT: - case CSR_UNEXP |PHS_DATA_OUT: - case CSR_SRV_REQ |PHS_DATA_OUT: -DB(DB_INTR,printk("OUT-%d.%d",cmd->SCp.this_residual,cmd->SCp.buffers_residual)) - transfer_bytes(cmd, DATA_OUT_DIR); - if (hostdata->state != S_RUNNING_LEVEL2) - hostdata->state = S_CONNECTED; - break; + hostdata->outgoing_msg[1] = EXTENDED_MESSAGE; + hostdata->outgoing_msg[2] = 3; + hostdata->outgoing_msg[3] = EXTENDED_SDTR; + hostdata->outgoing_msg[4] = OPTIMUM_SX_PER / 4; + hostdata->outgoing_msg[5] = OPTIMUM_SX_OFF; + hostdata->outgoing_len = 6; + } else + hostdata->outgoing_len = 1; + + hostdata->state = S_CONNECTED; + break; + + + case CSR_XFER_DONE | PHS_DATA_IN: + case CSR_UNEXP | PHS_DATA_IN: + case CSR_SRV_REQ | PHS_DATA_IN: + DB(DB_INTR, printk("IN-%d.%d", cmd->SCp.this_residual, cmd->SCp.buffers_residual)) + transfer_bytes(cmd, DATA_IN_DIR); + if (hostdata->state != S_RUNNING_LEVEL2) + hostdata->state = S_CONNECTED; + break; + + + case CSR_XFER_DONE | PHS_DATA_OUT: + case CSR_UNEXP | PHS_DATA_OUT: + case CSR_SRV_REQ | PHS_DATA_OUT: + DB(DB_INTR, printk("OUT-%d.%d", cmd->SCp.this_residual, cmd->SCp.buffers_residual)) + transfer_bytes(cmd, DATA_OUT_DIR); + if (hostdata->state != S_RUNNING_LEVEL2) + hostdata->state = S_CONNECTED; + break; /* Note: this interrupt should not occur in a LEVEL2 command */ - case CSR_XFER_DONE|PHS_COMMAND: - case CSR_UNEXP |PHS_COMMAND: - case CSR_SRV_REQ |PHS_COMMAND: -DB(DB_INTR,printk("CMND-%02x,%ld",cmd->cmnd[0],cmd->pid)) - transfer_pio(cmd->cmnd, cmd->cmd_len, DATA_OUT_DIR, hostdata); - hostdata->state = S_CONNECTED; - break; - - - case CSR_XFER_DONE|PHS_STATUS: - case CSR_UNEXP |PHS_STATUS: - case CSR_SRV_REQ |PHS_STATUS: -DB(DB_INTR,printk("STATUS=")) - - cmd->SCp.Status = read_1_byte(hostdata); -DB(DB_INTR,printk("%02x",cmd->SCp.Status)) - if (hostdata->level2 >= L2_BASIC) { - sr = read_3393(hostdata,WD_SCSI_STATUS); /* clear interrupt */ - hostdata->state = S_RUNNING_LEVEL2; - write_3393(hostdata,WD_COMMAND_PHASE, 0x50); - write_3393_cmd(hostdata,WD_CMD_SEL_ATN_XFER); - } - else { - hostdata->state = S_CONNECTED; - } - break; - - - case CSR_XFER_DONE|PHS_MESS_IN: - case CSR_UNEXP |PHS_MESS_IN: - case CSR_SRV_REQ |PHS_MESS_IN: -DB(DB_INTR,printk("MSG_IN=")) - - msg = read_1_byte(hostdata); - sr = read_3393(hostdata,WD_SCSI_STATUS); /* clear interrupt */ - - hostdata->incoming_msg[hostdata->incoming_ptr] = msg; - if (hostdata->incoming_msg[0] == EXTENDED_MESSAGE) - msg = EXTENDED_MESSAGE; - else - hostdata->incoming_ptr = 0; - - cmd->SCp.Message = msg; - switch (msg) { - - case COMMAND_COMPLETE: -DB(DB_INTR,printk("CCMP-%ld",cmd->pid)) - write_3393_cmd(hostdata,WD_CMD_NEGATE_ACK); - hostdata->state = S_PRE_CMP_DISC; - break; - - case SAVE_POINTERS: -DB(DB_INTR,printk("SDP")) - write_3393_cmd(hostdata,WD_CMD_NEGATE_ACK); - hostdata->state = S_CONNECTED; - break; - - case RESTORE_POINTERS: -DB(DB_INTR,printk("RDP")) - if (hostdata->level2 >= L2_BASIC) { - write_3393(hostdata,WD_COMMAND_PHASE, 0x45); - write_3393_cmd(hostdata,WD_CMD_SEL_ATN_XFER); - hostdata->state = S_RUNNING_LEVEL2; - } - else { - write_3393_cmd(hostdata,WD_CMD_NEGATE_ACK); - hostdata->state = S_CONNECTED; - } - break; - - case DISCONNECT: -DB(DB_INTR,printk("DIS")) - cmd->device->disconnect = 1; - write_3393_cmd(hostdata,WD_CMD_NEGATE_ACK); - hostdata->state = S_PRE_TMP_DISC; - break; + case CSR_XFER_DONE | PHS_COMMAND: + case CSR_UNEXP | PHS_COMMAND: + case CSR_SRV_REQ | PHS_COMMAND: + DB(DB_INTR, printk("CMND-%02x,%ld", cmd->cmnd[0], cmd->pid)) + transfer_pio(cmd->cmnd, cmd->cmd_len, DATA_OUT_DIR, hostdata); + hostdata->state = S_CONNECTED; + break; + + + case CSR_XFER_DONE | PHS_STATUS: + case CSR_UNEXP | PHS_STATUS: + case CSR_SRV_REQ | PHS_STATUS: + DB(DB_INTR, printk("STATUS=")) + + cmd->SCp.Status = read_1_byte(hostdata); + DB(DB_INTR, printk("%02x", cmd->SCp.Status)) + if (hostdata->level2 >= L2_BASIC) { + sr = read_3393(hostdata, WD_SCSI_STATUS); /* clear interrupt */ + hostdata->state = S_RUNNING_LEVEL2; + write_3393(hostdata, WD_COMMAND_PHASE, 0x50); + write_3393_cmd(hostdata, WD_CMD_SEL_ATN_XFER); + } else { + hostdata->state = S_CONNECTED; + } + break; + + + case CSR_XFER_DONE | PHS_MESS_IN: + case CSR_UNEXP | PHS_MESS_IN: + case CSR_SRV_REQ | PHS_MESS_IN: + DB(DB_INTR, printk("MSG_IN=")) + + msg = read_1_byte(hostdata); + sr = read_3393(hostdata, WD_SCSI_STATUS); /* clear interrupt */ + + hostdata->incoming_msg[hostdata->incoming_ptr] = msg; + if (hostdata->incoming_msg[0] == EXTENDED_MESSAGE) + msg = EXTENDED_MESSAGE; + else + hostdata->incoming_ptr = 0; + + cmd->SCp.Message = msg; + switch (msg) { + + case COMMAND_COMPLETE: + DB(DB_INTR, printk("CCMP-%ld", cmd->pid)) + write_3393_cmd(hostdata, WD_CMD_NEGATE_ACK); + hostdata->state = S_PRE_CMP_DISC; + break; + + case SAVE_POINTERS: + DB(DB_INTR, printk("SDP")) + write_3393_cmd(hostdata, WD_CMD_NEGATE_ACK); + hostdata->state = S_CONNECTED; + break; + + case RESTORE_POINTERS: + DB(DB_INTR, printk("RDP")) + if (hostdata->level2 >= L2_BASIC) { + write_3393(hostdata, WD_COMMAND_PHASE, 0x45); + write_3393_cmd(hostdata, WD_CMD_SEL_ATN_XFER); + hostdata->state = S_RUNNING_LEVEL2; + } else { + write_3393_cmd(hostdata, WD_CMD_NEGATE_ACK); + hostdata->state = S_CONNECTED; + } + break; + + case DISCONNECT: + DB(DB_INTR, printk("DIS")) + cmd->device->disconnect = 1; + write_3393_cmd(hostdata, WD_CMD_NEGATE_ACK); + hostdata->state = S_PRE_TMP_DISC; + break; - case MESSAGE_REJECT: -DB(DB_INTR,printk("REJ")) + case MESSAGE_REJECT: + DB(DB_INTR, printk("REJ")) #ifdef SYNC_DEBUG -printk("-REJ-"); + printk("-REJ-"); #endif - if (hostdata->sync_stat[cmd->target] == SS_WAITING) - hostdata->sync_stat[cmd->target] = SS_SET; - write_3393_cmd(hostdata,WD_CMD_NEGATE_ACK); - hostdata->state = S_CONNECTED; - break; + if (hostdata->sync_stat[cmd->target] == SS_WAITING) + hostdata->sync_stat[cmd->target] = SS_SET; + write_3393_cmd(hostdata, WD_CMD_NEGATE_ACK); + hostdata->state = S_CONNECTED; + break; - case EXTENDED_MESSAGE: -DB(DB_INTR,printk("EXT")) + case EXTENDED_MESSAGE: + DB(DB_INTR, printk("EXT")) - ucp = hostdata->incoming_msg; + ucp = hostdata->incoming_msg; #ifdef SYNC_DEBUG -printk("%02x",ucp[hostdata->incoming_ptr]); + printk("%02x", ucp[hostdata->incoming_ptr]); #endif - /* Is this the last byte of the extended message? */ + /* Is this the last byte of the extended message? */ - if ((hostdata->incoming_ptr >= 2) && - (hostdata->incoming_ptr == (ucp[1] + 1))) { + if ((hostdata->incoming_ptr >= 2) && (hostdata->incoming_ptr == (ucp[1] + 1))) { - switch (ucp[2]) { /* what's the EXTENDED code? */ - case EXTENDED_SDTR: - id = calc_sync_xfer(ucp[3],ucp[4]); - if (hostdata->sync_stat[cmd->target] != SS_WAITING) { + switch (ucp[2]) { /* what's the EXTENDED code? */ + case EXTENDED_SDTR: + id = calc_sync_xfer(ucp[3], ucp[4]); + if (hostdata->sync_stat[cmd->target] != SS_WAITING) { /* A device has sent an unsolicited SDTR message; rather than go * through the effort of decoding it and then figuring out what @@ -1262,120 +1260,117 @@ * specifically ask for sync transfers, we won't do any. */ - write_3393_cmd(hostdata,WD_CMD_ASSERT_ATN); /* want MESS_OUT */ - hostdata->outgoing_msg[0] = EXTENDED_MESSAGE; - hostdata->outgoing_msg[1] = 3; - hostdata->outgoing_msg[2] = EXTENDED_SDTR; - hostdata->outgoing_msg[3] = hostdata->default_sx_per/4; - hostdata->outgoing_msg[4] = 0; - hostdata->outgoing_len = 5; - hostdata->sync_xfer[cmd->target] = - calc_sync_xfer(hostdata->default_sx_per/4,0); - } - else { - hostdata->sync_xfer[cmd->target] = id; - } + write_3393_cmd(hostdata, WD_CMD_ASSERT_ATN); /* want MESS_OUT */ + hostdata->outgoing_msg[0] = EXTENDED_MESSAGE; + hostdata->outgoing_msg[1] = 3; + hostdata->outgoing_msg[2] = EXTENDED_SDTR; + hostdata->outgoing_msg[3] = hostdata->default_sx_per / 4; + hostdata->outgoing_msg[4] = 0; + hostdata->outgoing_len = 5; + hostdata->sync_xfer[cmd->target] = calc_sync_xfer(hostdata->default_sx_per / 4, 0); + } else { + hostdata->sync_xfer[cmd->target] = id; + } #ifdef SYNC_DEBUG -printk("sync_xfer=%02x",hostdata->sync_xfer[cmd->target]); + printk("sync_xfer=%02x", hostdata->sync_xfer[cmd->target]); #endif - hostdata->sync_stat[cmd->target] = SS_SET; - write_3393_cmd(hostdata,WD_CMD_NEGATE_ACK); - hostdata->state = S_CONNECTED; - break; - case EXTENDED_WDTR: - write_3393_cmd(hostdata,WD_CMD_ASSERT_ATN); /* want MESS_OUT */ - printk("sending WDTR "); - hostdata->outgoing_msg[0] = EXTENDED_MESSAGE; - hostdata->outgoing_msg[1] = 2; - hostdata->outgoing_msg[2] = EXTENDED_WDTR; - hostdata->outgoing_msg[3] = 0; /* 8 bit transfer width */ - hostdata->outgoing_len = 4; - write_3393_cmd(hostdata,WD_CMD_NEGATE_ACK); - hostdata->state = S_CONNECTED; - break; - default: - write_3393_cmd(hostdata,WD_CMD_ASSERT_ATN); /* want MESS_OUT */ - printk("Rejecting Unknown Extended Message(%02x). ",ucp[2]); - hostdata->outgoing_msg[0] = MESSAGE_REJECT; - hostdata->outgoing_len = 1; - write_3393_cmd(hostdata,WD_CMD_NEGATE_ACK); - hostdata->state = S_CONNECTED; - break; - } - hostdata->incoming_ptr = 0; - } - - /* We need to read more MESS_IN bytes for the extended message */ - - else { - hostdata->incoming_ptr++; - write_3393_cmd(hostdata,WD_CMD_NEGATE_ACK); - hostdata->state = S_CONNECTED; - } - break; - - default: - printk("Rejecting Unknown Message(%02x) ",msg); - write_3393_cmd(hostdata,WD_CMD_ASSERT_ATN); /* want MESS_OUT */ - hostdata->outgoing_msg[0] = MESSAGE_REJECT; - hostdata->outgoing_len = 1; - write_3393_cmd(hostdata,WD_CMD_NEGATE_ACK); - hostdata->state = S_CONNECTED; - } - break; + hostdata->sync_stat[cmd->target] = SS_SET; + write_3393_cmd(hostdata, WD_CMD_NEGATE_ACK); + hostdata->state = S_CONNECTED; + break; + case EXTENDED_WDTR: + write_3393_cmd(hostdata, WD_CMD_ASSERT_ATN); /* want MESS_OUT */ + printk("sending WDTR "); + hostdata->outgoing_msg[0] = EXTENDED_MESSAGE; + hostdata->outgoing_msg[1] = 2; + hostdata->outgoing_msg[2] = EXTENDED_WDTR; + hostdata->outgoing_msg[3] = 0; /* 8 bit transfer width */ + hostdata->outgoing_len = 4; + write_3393_cmd(hostdata, WD_CMD_NEGATE_ACK); + hostdata->state = S_CONNECTED; + break; + default: + write_3393_cmd(hostdata, WD_CMD_ASSERT_ATN); /* want MESS_OUT */ + printk("Rejecting Unknown Extended Message(%02x). ", ucp[2]); + hostdata->outgoing_msg[0] = MESSAGE_REJECT; + hostdata->outgoing_len = 1; + write_3393_cmd(hostdata, WD_CMD_NEGATE_ACK); + hostdata->state = S_CONNECTED; + break; + } + hostdata->incoming_ptr = 0; + } + + /* We need to read more MESS_IN bytes for the extended message */ + + else { + hostdata->incoming_ptr++; + write_3393_cmd(hostdata, WD_CMD_NEGATE_ACK); + hostdata->state = S_CONNECTED; + } + break; + + default: + printk("Rejecting Unknown Message(%02x) ", msg); + write_3393_cmd(hostdata, WD_CMD_ASSERT_ATN); /* want MESS_OUT */ + hostdata->outgoing_msg[0] = MESSAGE_REJECT; + hostdata->outgoing_len = 1; + write_3393_cmd(hostdata, WD_CMD_NEGATE_ACK); + hostdata->state = S_CONNECTED; + } + break; /* Note: this interrupt will occur only after a LEVEL2 command */ - case CSR_SEL_XFER_DONE: + case CSR_SEL_XFER_DONE: /* Make sure that reselection is enabled at this point - it may * have been turned off for the command that just completed. */ - write_3393(hostdata,WD_SOURCE_ID, SRCID_ER); - if (phs == 0x60) { -DB(DB_INTR,printk("SX-DONE-%ld",cmd->pid)) - cmd->SCp.Message = COMMAND_COMPLETE; - lun = read_3393(hostdata,WD_TARGET_LUN); -DB(DB_INTR,printk(":%d.%d",cmd->SCp.Status,lun)) - hostdata->connected = NULL; - hostdata->busy[cmd->target] &= ~(1 << cmd->lun); - hostdata->state = S_UNCONNECTED; - if (cmd->SCp.Status == ILLEGAL_STATUS_BYTE) - cmd->SCp.Status = lun; - if (cmd->cmnd[0] == REQUEST_SENSE && cmd->SCp.Status != GOOD) - cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16); - else - cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8); - cmd->scsi_done(cmd); + write_3393(hostdata, WD_SOURCE_ID, SRCID_ER); + if (phs == 0x60) { + DB(DB_INTR, printk("SX-DONE-%ld", cmd->pid)) + cmd->SCp.Message = COMMAND_COMPLETE; + lun = read_3393(hostdata, WD_TARGET_LUN); + DB(DB_INTR, printk(":%d.%d", cmd->SCp.Status, lun)) + hostdata->connected = NULL; + hostdata->busy[cmd->target] &= ~(1 << cmd->lun); + hostdata->state = S_UNCONNECTED; + if (cmd->SCp.Status == ILLEGAL_STATUS_BYTE) + cmd->SCp.Status = lun; + if (cmd->cmnd[0] == REQUEST_SENSE && cmd->SCp.Status != GOOD) + cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16); + else + cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8); + cmd->scsi_done(cmd); /* We are no longer connected to a target - check to see if * there are commands waiting to be executed. */ - in2000_execute(instance); - } - else { - printk("%02x:%02x:%02x-%ld: Unknown SEL_XFER_DONE phase!!---",asr,sr,phs,cmd->pid); - } - break; + in2000_execute(instance); + } else { + printk("%02x:%02x:%02x-%ld: Unknown SEL_XFER_DONE phase!!---", asr, sr, phs, cmd->pid); + } + break; /* Note: this interrupt will occur only after a LEVEL2 command */ - case CSR_SDP: -DB(DB_INTR,printk("SDP")) - hostdata->state = S_RUNNING_LEVEL2; - write_3393(hostdata,WD_COMMAND_PHASE, 0x41); - write_3393_cmd(hostdata,WD_CMD_SEL_ATN_XFER); - break; + case CSR_SDP: + DB(DB_INTR, printk("SDP")) + hostdata->state = S_RUNNING_LEVEL2; + write_3393(hostdata, WD_COMMAND_PHASE, 0x41); + write_3393_cmd(hostdata, WD_CMD_SEL_ATN_XFER); + break; - case CSR_XFER_DONE|PHS_MESS_OUT: - case CSR_UNEXP |PHS_MESS_OUT: - case CSR_SRV_REQ |PHS_MESS_OUT: -DB(DB_INTR,printk("MSG_OUT=")) + case CSR_XFER_DONE | PHS_MESS_OUT: + case CSR_UNEXP | PHS_MESS_OUT: + case CSR_SRV_REQ | PHS_MESS_OUT: + DB(DB_INTR, printk("MSG_OUT=")) /* To get here, we've probably requested MESSAGE_OUT and have * already put the correct bytes in outgoing_msg[] and filled @@ -1389,20 +1384,18 @@ * NOP messages in these situations results in no harm and * makes everyone happy. */ + if (hostdata->outgoing_len == 0) { + hostdata->outgoing_len = 1; + hostdata->outgoing_msg[0] = NOP; + } + transfer_pio(hostdata->outgoing_msg, hostdata->outgoing_len, DATA_OUT_DIR, hostdata); + DB(DB_INTR, printk("%02x", hostdata->outgoing_msg[0])) + hostdata->outgoing_len = 0; + hostdata->state = S_CONNECTED; + break; - if (hostdata->outgoing_len == 0) { - hostdata->outgoing_len = 1; - hostdata->outgoing_msg[0] = NOP; - } - transfer_pio(hostdata->outgoing_msg, hostdata->outgoing_len, - DATA_OUT_DIR, hostdata); -DB(DB_INTR,printk("%02x",hostdata->outgoing_msg[0])) - hostdata->outgoing_len = 0; - hostdata->state = S_CONNECTED; - break; - - case CSR_UNEXP_DISC: + case CSR_UNEXP_DISC: /* I think I've seen this after a request-sense that was in response * to an error condition, but not sure. We certainly need to do @@ -1417,189 +1410,186 @@ * have been turned off for the command that just completed. */ - write_3393(hostdata,WD_SOURCE_ID, SRCID_ER); - if (cmd == NULL) { - printk(" - Already disconnected! "); - hostdata->state = S_UNCONNECTED; + write_3393(hostdata, WD_SOURCE_ID, SRCID_ER); + if (cmd == NULL) { + printk(" - Already disconnected! "); + hostdata->state = S_UNCONNECTED; /* release the SMP spin_lock and restore irq state */ - spin_unlock_irqrestore(instance->host_lock, flags); - return; - } -DB(DB_INTR,printk("UNEXP_DISC-%ld",cmd->pid)) - hostdata->connected = NULL; - hostdata->busy[cmd->target] &= ~(1 << cmd->lun); - hostdata->state = S_UNCONNECTED; - if (cmd->cmnd[0] == REQUEST_SENSE && cmd->SCp.Status != GOOD) - cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16); - else - cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8); - cmd->scsi_done(cmd); + spin_unlock_irqrestore(instance->host_lock, flags); + return; + } + DB(DB_INTR, printk("UNEXP_DISC-%ld", cmd->pid)) + hostdata->connected = NULL; + hostdata->busy[cmd->target] &= ~(1 << cmd->lun); + hostdata->state = S_UNCONNECTED; + if (cmd->cmnd[0] == REQUEST_SENSE && cmd->SCp.Status != GOOD) + cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16); + else + cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8); + cmd->scsi_done(cmd); /* We are no longer connected to a target - check to see if * there are commands waiting to be executed. */ - in2000_execute(instance); - break; + in2000_execute(instance); + break; - case CSR_DISC: + case CSR_DISC: /* Make sure that reselection is enabled at this point - it may * have been turned off for the command that just completed. */ - write_3393(hostdata,WD_SOURCE_ID, SRCID_ER); -DB(DB_INTR,printk("DISC-%ld",cmd->pid)) - if (cmd == NULL) { - printk(" - Already disconnected! "); - hostdata->state = S_UNCONNECTED; - } - switch (hostdata->state) { - case S_PRE_CMP_DISC: - hostdata->connected = NULL; - hostdata->busy[cmd->target] &= ~(1 << cmd->lun); - hostdata->state = S_UNCONNECTED; -DB(DB_INTR,printk(":%d",cmd->SCp.Status)) - if (cmd->cmnd[0] == REQUEST_SENSE && cmd->SCp.Status != GOOD) - cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16); - else - cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8); - cmd->scsi_done(cmd); - break; - case S_PRE_TMP_DISC: - case S_RUNNING_LEVEL2: - cmd->host_scribble = (uchar *)hostdata->disconnected_Q; - hostdata->disconnected_Q = cmd; - hostdata->connected = NULL; - hostdata->state = S_UNCONNECTED; + write_3393(hostdata, WD_SOURCE_ID, SRCID_ER); + DB(DB_INTR, printk("DISC-%ld", cmd->pid)) + if (cmd == NULL) { + printk(" - Already disconnected! "); + hostdata->state = S_UNCONNECTED; + } + switch (hostdata->state) { + case S_PRE_CMP_DISC: + hostdata->connected = NULL; + hostdata->busy[cmd->target] &= ~(1 << cmd->lun); + hostdata->state = S_UNCONNECTED; + DB(DB_INTR, printk(":%d", cmd->SCp.Status)) + if (cmd->cmnd[0] == REQUEST_SENSE && cmd->SCp.Status != GOOD) + cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16); + else + cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8); + cmd->scsi_done(cmd); + break; + case S_PRE_TMP_DISC: + case S_RUNNING_LEVEL2: + cmd->host_scribble = (uchar *) hostdata->disconnected_Q; + hostdata->disconnected_Q = cmd; + hostdata->connected = NULL; + hostdata->state = S_UNCONNECTED; #ifdef PROC_STATISTICS - hostdata->disc_done_cnt[cmd->target]++; + hostdata->disc_done_cnt[cmd->target]++; #endif - break; - default: - printk("*** Unexpected DISCONNECT interrupt! ***"); - hostdata->state = S_UNCONNECTED; - } + break; + default: + printk("*** Unexpected DISCONNECT interrupt! ***"); + hostdata->state = S_UNCONNECTED; + } /* We are no longer connected to a target - check to see if * there are commands waiting to be executed. */ - in2000_execute(instance); - break; + in2000_execute(instance); + break; - case CSR_RESEL_AM: -DB(DB_INTR,printk("RESEL")) + case CSR_RESEL_AM: + DB(DB_INTR, printk("RESEL")) - /* First we have to make sure this reselection didn't */ - /* happen during Arbitration/Selection of some other device. */ - /* If yes, put losing command back on top of input_Q. */ - - if (hostdata->level2 <= L2_NONE) { - - if (hostdata->selecting) { - cmd = (Scsi_Cmnd *)hostdata->selecting; - hostdata->selecting = NULL; - hostdata->busy[cmd->target] &= ~(1 << cmd->lun); - cmd->host_scribble = (uchar *)hostdata->input_Q; - hostdata->input_Q = cmd; - } - } - - else { - - if (cmd) { - if (phs == 0x00) { - hostdata->busy[cmd->target] &= ~(1 << cmd->lun); - cmd->host_scribble = (uchar *)hostdata->input_Q; - hostdata->input_Q = cmd; - } - else { - printk("---%02x:%02x:%02x-TROUBLE: Intrusive ReSelect!---",asr,sr,phs); - while (1) - printk("\r"); - } - } - - } - - /* OK - find out which device reselected us. */ - - id = read_3393(hostdata,WD_SOURCE_ID); - id &= SRCID_MASK; - - /* and extract the lun from the ID message. (Note that we don't - * bother to check for a valid message here - I guess this is - * not the right way to go, but....) - */ - - lun = read_3393(hostdata,WD_DATA); - if (hostdata->level2 < L2_RESELECT) - write_3393_cmd(hostdata,WD_CMD_NEGATE_ACK); - lun &= 7; - - /* Now we look for the command that's reconnecting. */ - - cmd = (Scsi_Cmnd *)hostdata->disconnected_Q; - patch = NULL; - while (cmd) { - if (id == cmd->target && lun == cmd->lun) - break; - patch = cmd; - cmd = (Scsi_Cmnd *)cmd->host_scribble; - } - - /* Hmm. Couldn't find a valid command.... What to do? */ - - if (!cmd) { - printk("---TROUBLE: target %d.%d not in disconnect queue---",id,lun); - break; - } - - /* Ok, found the command - now start it up again. */ - - if (patch) - patch->host_scribble = cmd->host_scribble; - else - hostdata->disconnected_Q = (Scsi_Cmnd *)cmd->host_scribble; - hostdata->connected = cmd; - - /* We don't need to worry about 'initialize_SCp()' or 'hostdata->busy[]' - * because these things are preserved over a disconnect. - * But we DO need to fix the DPD bit so it's correct for this command. - */ - - if (is_dir_out(cmd)) - write_3393(hostdata,WD_DESTINATION_ID,cmd->target); - else - write_3393(hostdata,WD_DESTINATION_ID,cmd->target | DSTID_DPD); - if (hostdata->level2 >= L2_RESELECT) { - write_3393_count(hostdata,0); /* we want a DATA_PHASE interrupt */ - write_3393(hostdata,WD_COMMAND_PHASE, 0x45); - write_3393_cmd(hostdata,WD_CMD_SEL_ATN_XFER); - hostdata->state = S_RUNNING_LEVEL2; - } - else - hostdata->state = S_CONNECTED; - -DB(DB_INTR,printk("-%ld",cmd->pid)) - break; - - default: - printk("--UNKNOWN INTERRUPT:%02x:%02x:%02x--",asr,sr,phs); - } + /* First we have to make sure this reselection didn't */ + /* happen during Arbitration/Selection of some other device. */ + /* If yes, put losing command back on top of input_Q. */ + if (hostdata->level2 <= L2_NONE) { + + if (hostdata->selecting) { + cmd = (Scsi_Cmnd *) hostdata->selecting; + hostdata->selecting = NULL; + hostdata->busy[cmd->target] &= ~(1 << cmd->lun); + cmd->host_scribble = (uchar *) hostdata->input_Q; + hostdata->input_Q = cmd; + } + } + + else { + + if (cmd) { + if (phs == 0x00) { + hostdata->busy[cmd->target] &= ~(1 << cmd->lun); + cmd->host_scribble = (uchar *) hostdata->input_Q; + hostdata->input_Q = cmd; + } else { + printk("---%02x:%02x:%02x-TROUBLE: Intrusive ReSelect!---", asr, sr, phs); + while (1) + printk("\r"); + } + } + + } + + /* OK - find out which device reselected us. */ + + id = read_3393(hostdata, WD_SOURCE_ID); + id &= SRCID_MASK; + + /* and extract the lun from the ID message. (Note that we don't + * bother to check for a valid message here - I guess this is + * not the right way to go, but....) + */ + + lun = read_3393(hostdata, WD_DATA); + if (hostdata->level2 < L2_RESELECT) + write_3393_cmd(hostdata, WD_CMD_NEGATE_ACK); + lun &= 7; + + /* Now we look for the command that's reconnecting. */ + + cmd = (Scsi_Cmnd *) hostdata->disconnected_Q; + patch = NULL; + while (cmd) { + if (id == cmd->target && lun == cmd->lun) + break; + patch = cmd; + cmd = (Scsi_Cmnd *) cmd->host_scribble; + } + + /* Hmm. Couldn't find a valid command.... What to do? */ + + if (!cmd) { + printk("---TROUBLE: target %d.%d not in disconnect queue---", id, lun); + break; + } + + /* Ok, found the command - now start it up again. */ + + if (patch) + patch->host_scribble = cmd->host_scribble; + else + hostdata->disconnected_Q = (Scsi_Cmnd *) cmd->host_scribble; + hostdata->connected = cmd; + + /* We don't need to worry about 'initialize_SCp()' or 'hostdata->busy[]' + * because these things are preserved over a disconnect. + * But we DO need to fix the DPD bit so it's correct for this command. + */ + + if (is_dir_out(cmd)) + write_3393(hostdata, WD_DESTINATION_ID, cmd->target); + else + write_3393(hostdata, WD_DESTINATION_ID, cmd->target | DSTID_DPD); + if (hostdata->level2 >= L2_RESELECT) { + write_3393_count(hostdata, 0); /* we want a DATA_PHASE interrupt */ + write_3393(hostdata, WD_COMMAND_PHASE, 0x45); + write_3393_cmd(hostdata, WD_CMD_SEL_ATN_XFER); + hostdata->state = S_RUNNING_LEVEL2; + } else + hostdata->state = S_CONNECTED; + + DB(DB_INTR, printk("-%ld", cmd->pid)) + break; + + default: + printk("--UNKNOWN INTERRUPT:%02x:%02x:%02x--", asr, sr, phs); + } - write1_io(0, IO_LED_OFF); + write1_io(0, IO_LED_OFF); -DB(DB_INTR,printk("} ")) + DB(DB_INTR, printk("} ")) /* release the SMP spin_lock and restore irq state */ - spin_unlock_irqrestore(instance->host_lock, flags); + spin_unlock_irqrestore(instance->host_lock, flags); } @@ -1612,135 +1602,124 @@ /* * Caller must hold instance lock! */ - + static int reset_hardware(struct Scsi_Host *instance, int type) { -struct IN2000_hostdata *hostdata; -int qt,x; + struct IN2000_hostdata *hostdata; + int qt, x; - hostdata = (struct IN2000_hostdata *)instance->hostdata; + hostdata = (struct IN2000_hostdata *) instance->hostdata; - write1_io(0, IO_LED_ON); - if (type == RESET_CARD_AND_BUS) { - write1_io(0,IO_CARD_RESET); - x = read1_io(IO_HARDWARE); - } - x = read_3393(hostdata,WD_SCSI_STATUS); /* clear any WD intrpt */ - write_3393(hostdata,WD_OWN_ID, instance->this_id | - OWNID_EAF | OWNID_RAF | OWNID_FS_8); - write_3393(hostdata,WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED); - write_3393(hostdata,WD_SYNCHRONOUS_TRANSFER, - calc_sync_xfer(hostdata->default_sx_per/4,DEFAULT_SX_OFF)); - - write1_io(0,IO_FIFO_WRITE); /* clear fifo counter */ - write1_io(0,IO_FIFO_READ); /* start fifo out in read mode */ - write_3393(hostdata,WD_COMMAND, WD_CMD_RESET); - /* FIXME: timeout ?? */ - while (!(READ_AUX_STAT() & ASR_INT)) - cpu_relax(); /* wait for RESET to complete */ - - x = read_3393(hostdata,WD_SCSI_STATUS); /* clear interrupt */ - - write_3393(hostdata,WD_QUEUE_TAG,0xa5); /* any random number */ - qt = read_3393(hostdata,WD_QUEUE_TAG); - if (qt == 0xa5) { - x |= B_FLAG; - write_3393(hostdata,WD_QUEUE_TAG,0); - } - write_3393(hostdata,WD_TIMEOUT_PERIOD, TIMEOUT_PERIOD_VALUE); - write_3393(hostdata,WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED); - write1_io(0, IO_LED_OFF); - return x; -} - - - -static int in2000_bus_reset(Scsi_Cmnd *cmd) -{ -unsigned long flags; -struct Scsi_Host *instance; -struct IN2000_hostdata *hostdata; -int x; - - instance = cmd->host; - hostdata = (struct IN2000_hostdata *)instance->hostdata; - - printk(KERN_WARNING "scsi%d: Reset. ", instance->host_no); - - spin_lock_irqsave(instance->host_lock, flags); - /* do scsi-reset here */ - - reset_hardware(instance, RESET_CARD_AND_BUS); - for (x = 0; x < 8; x++) { - hostdata->busy[x] = 0; - hostdata->sync_xfer[x] = calc_sync_xfer(DEFAULT_SX_PER/4,DEFAULT_SX_OFF); - hostdata->sync_stat[x] = SS_UNSET; /* using default sync values */ - } - hostdata->input_Q = NULL; - hostdata->selecting = NULL; - hostdata->connected = NULL; - hostdata->disconnected_Q = NULL; - hostdata->state = S_UNCONNECTED; - hostdata->fifo = FI_FIFO_UNUSED; - hostdata->incoming_ptr = 0; - hostdata->outgoing_len = 0; - - cmd->result = DID_RESET << 16; - spin_unlock_irqrestore(instance->host_lock, flags); - return SUCCESS; + write1_io(0, IO_LED_ON); + if (type == RESET_CARD_AND_BUS) { + write1_io(0, IO_CARD_RESET); + x = read1_io(IO_HARDWARE); + } + x = read_3393(hostdata, WD_SCSI_STATUS); /* clear any WD intrpt */ + write_3393(hostdata, WD_OWN_ID, instance->this_id | OWNID_EAF | OWNID_RAF | OWNID_FS_8); + write_3393(hostdata, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED); + write_3393(hostdata, WD_SYNCHRONOUS_TRANSFER, calc_sync_xfer(hostdata->default_sx_per / 4, DEFAULT_SX_OFF)); + + write1_io(0, IO_FIFO_WRITE); /* clear fifo counter */ + write1_io(0, IO_FIFO_READ); /* start fifo out in read mode */ + write_3393(hostdata, WD_COMMAND, WD_CMD_RESET); + /* FIXME: timeout ?? */ + while (!(READ_AUX_STAT() & ASR_INT)) + cpu_relax(); /* wait for RESET to complete */ + + x = read_3393(hostdata, WD_SCSI_STATUS); /* clear interrupt */ + + write_3393(hostdata, WD_QUEUE_TAG, 0xa5); /* any random number */ + qt = read_3393(hostdata, WD_QUEUE_TAG); + if (qt == 0xa5) { + x |= B_FLAG; + write_3393(hostdata, WD_QUEUE_TAG, 0); + } + write_3393(hostdata, WD_TIMEOUT_PERIOD, TIMEOUT_PERIOD_VALUE); + write_3393(hostdata, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED); + write1_io(0, IO_LED_OFF); + return x; +} + + + +static int in2000_bus_reset(Scsi_Cmnd * cmd) +{ + struct Scsi_Host *instance; + struct IN2000_hostdata *hostdata; + int x; + + instance = cmd->host; + hostdata = (struct IN2000_hostdata *) instance->hostdata; + + printk(KERN_WARNING "scsi%d: Reset. ", instance->host_no); + + /* do scsi-reset here */ + + reset_hardware(instance, RESET_CARD_AND_BUS); + for (x = 0; x < 8; x++) { + hostdata->busy[x] = 0; + hostdata->sync_xfer[x] = calc_sync_xfer(DEFAULT_SX_PER / 4, DEFAULT_SX_OFF); + hostdata->sync_stat[x] = SS_UNSET; /* using default sync values */ + } + hostdata->input_Q = NULL; + hostdata->selecting = NULL; + hostdata->connected = NULL; + hostdata->disconnected_Q = NULL; + hostdata->state = S_UNCONNECTED; + hostdata->fifo = FI_FIFO_UNUSED; + hostdata->incoming_ptr = 0; + hostdata->outgoing_len = 0; + + cmd->result = DID_RESET << 16; + return SUCCESS; } -static int in2000_host_reset(Scsi_Cmnd *cmd) +static int in2000_host_reset(Scsi_Cmnd * cmd) { return FAILED; } -static int in2000_device_reset(Scsi_Cmnd *cmd) +static int in2000_device_reset(Scsi_Cmnd * cmd) { return FAILED; } -static int in2000_abort (Scsi_Cmnd *cmd) +static int in2000_abort(Scsi_Cmnd * cmd) { -struct Scsi_Host *instance; -struct IN2000_hostdata *hostdata; -Scsi_Cmnd *tmp, *prev; -unsigned long flags; -uchar sr, asr; -unsigned long timeout; - - instance = cmd->host; - hostdata = (struct IN2000_hostdata *)instance->hostdata; - - printk(KERN_DEBUG "scsi%d: Abort-", instance->host_no); - printk("(asr=%02x,count=%ld,resid=%d,buf_resid=%d,have_data=%d,FC=%02x)- ", - READ_AUX_STAT(),read_3393_count(hostdata),cmd->SCp.this_residual,cmd->SCp.buffers_residual, - cmd->SCp.have_data_in,read1_io(IO_FIFO_COUNT)); + struct Scsi_Host *instance; + struct IN2000_hostdata *hostdata; + Scsi_Cmnd *tmp, *prev; + uchar sr, asr; + unsigned long timeout; + + instance = cmd->host; + hostdata = (struct IN2000_hostdata *) instance->hostdata; + + printk(KERN_DEBUG "scsi%d: Abort-", instance->host_no); + printk("(asr=%02x,count=%ld,resid=%d,buf_resid=%d,have_data=%d,FC=%02x)- ", READ_AUX_STAT(), read_3393_count(hostdata), cmd->SCp.this_residual, cmd->SCp.buffers_residual, cmd->SCp.have_data_in, read1_io(IO_FIFO_COUNT)); /* * Case 1 : If the command hasn't been issued yet, we simply remove it * from the inout_Q. */ - spin_lock_irqsave(instance->host_lock, flags); - tmp = (Scsi_Cmnd *)hostdata->input_Q; - prev = 0; - while (tmp) { - if (tmp == cmd) { - if (prev) - prev->host_scribble = cmd->host_scribble; - cmd->host_scribble = NULL; - cmd->result = DID_ABORT << 16; - printk(KERN_WARNING "scsi%d: Abort - removing command %ld from input_Q. ", - instance->host_no, cmd->pid); - cmd->scsi_done(cmd); - spin_unlock_irqrestore(instance->host_lock, flags); - return SUCCESS; - } - prev = tmp; - tmp = (Scsi_Cmnd *)tmp->host_scribble; - } + tmp = (Scsi_Cmnd *) hostdata->input_Q; + prev = 0; + while (tmp) { + if (tmp == cmd) { + if (prev) + prev->host_scribble = cmd->host_scribble; + cmd->host_scribble = NULL; + cmd->result = DID_ABORT << 16; + printk(KERN_WARNING "scsi%d: Abort - removing command %ld from input_Q. ", instance->host_no, cmd->pid); + cmd->scsi_done(cmd); + return SUCCESS; + } + prev = tmp; + tmp = (Scsi_Cmnd *) tmp->host_scribble; + } /* * Case 2 : If the command is connected, we're going to fail the abort @@ -1753,54 +1732,52 @@ * we fail. */ - if (hostdata->connected == cmd) { + if (hostdata->connected == cmd) { - printk(KERN_WARNING "scsi%d: Aborting connected command %ld - ", - instance->host_no, cmd->pid); + printk(KERN_WARNING "scsi%d: Aborting connected command %ld - ", instance->host_no, cmd->pid); - printk("sending wd33c93 ABORT command - "); - write_3393(hostdata, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED); - write_3393_cmd(hostdata, WD_CMD_ABORT); + printk("sending wd33c93 ABORT command - "); + write_3393(hostdata, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED); + write_3393_cmd(hostdata, WD_CMD_ABORT); /* Now we have to attempt to flush out the FIFO... */ - printk("flushing fifo - "); - timeout = 1000000; - do { - asr = READ_AUX_STAT(); - if (asr & ASR_DBR) - read_3393(hostdata, WD_DATA); - } while (!(asr & ASR_INT) && timeout-- > 0); - sr = read_3393(hostdata, WD_SCSI_STATUS); - printk("asr=%02x, sr=%02x, %ld bytes un-transferred (timeout=%ld) - ", - asr, sr, read_3393_count(hostdata), timeout); - - /* - * Abort command processed. - * Still connected. - * We must disconnect. - */ - - printk("sending wd33c93 DISCONNECT command - "); - write_3393_cmd(hostdata, WD_CMD_DISCONNECT); - - timeout = 1000000; - asr = READ_AUX_STAT(); - while ((asr & ASR_CIP) && timeout-- > 0) - asr = READ_AUX_STAT(); - sr = read_3393(hostdata, WD_SCSI_STATUS); - printk("asr=%02x, sr=%02x.",asr,sr); - - hostdata->busy[cmd->target] &= ~(1 << cmd->lun); - hostdata->connected = NULL; - hostdata->state = S_UNCONNECTED; - cmd->result = DID_ABORT << 16; - cmd->scsi_done(cmd); + printk("flushing fifo - "); + timeout = 1000000; + do { + asr = READ_AUX_STAT(); + if (asr & ASR_DBR) + read_3393(hostdata, WD_DATA); + } while (!(asr & ASR_INT) && timeout-- > 0); + sr = read_3393(hostdata, WD_SCSI_STATUS); + printk("asr=%02x, sr=%02x, %ld bytes un-transferred (timeout=%ld) - ", asr, sr, read_3393_count(hostdata), timeout); + + /* + * Abort command processed. + * Still connected. + * We must disconnect. + */ + + printk("sending wd33c93 DISCONNECT command - "); + write_3393_cmd(hostdata, WD_CMD_DISCONNECT); + + timeout = 1000000; + asr = READ_AUX_STAT(); + while ((asr & ASR_CIP) && timeout-- > 0) + asr = READ_AUX_STAT(); + sr = read_3393(hostdata, WD_SCSI_STATUS); + printk("asr=%02x, sr=%02x.", asr, sr); + + hostdata->busy[cmd->target] &= ~(1 << cmd->lun); + hostdata->connected = NULL; + hostdata->state = S_UNCONNECTED; + cmd->result = DID_ABORT << 16; + cmd->scsi_done(cmd); - in2000_execute (instance); + in2000_execute(instance); - return SCSI_ABORT_SUCCESS; - } + return SUCCESS; + } /* * Case 3: If the command is currently disconnected from the bus, @@ -1808,13 +1785,11 @@ * an ABORT_SNOOZE and hope for the best... */ - for (tmp=(Scsi_Cmnd *)hostdata->disconnected_Q; tmp; - tmp=(Scsi_Cmnd *)tmp->host_scribble) - if (cmd == tmp) { - spin_unlock_irqrestore(instance->host_lock, flags); - printk(KERN_DEBUG "scsi%d: unable to abort disconnected command.\n", instance->host_no); - return FAILED; - } + for (tmp = (Scsi_Cmnd *) hostdata->disconnected_Q; tmp; tmp = (Scsi_Cmnd *) tmp->host_scribble) + if (cmd == tmp) { + printk(KERN_DEBUG "scsi%d: unable to abort disconnected command.\n", instance->host_no); + return FAILED; + } /* * Case 4 : If we reached this point, the command was not found in any of @@ -1826,12 +1801,10 @@ * broke. */ - in2000_execute (instance); + in2000_execute(instance); - spin_unlock_irqrestore(instance->host_lock, flags); - printk("scsi%d: warning : SCSI command probably completed successfully" - " before abortion. ", instance->host_no); - return SUCCESS; + printk("scsi%d: warning : SCSI command probably completed successfully" " before abortion. ", instance->host_no); + return SUCCESS; } @@ -1843,32 +1816,31 @@ static char setup_used[MAX_SETUP_ARGS]; static int done_setup = 0; -static void __init in2000_setup (char *str, int *ints) +static void __init in2000_setup(char *str, int *ints) { -int i; -char *p1,*p2; + int i; + char *p1, *p2; - strncpy(setup_buffer,str,SETUP_BUFFER_SIZE); - setup_buffer[SETUP_BUFFER_SIZE - 1] = '\0'; - p1 = setup_buffer; - i = 0; - while (*p1 && (i < MAX_SETUP_ARGS)) { - p2 = strchr(p1, ','); - if (p2) { - *p2 = '\0'; - if (p1 != p2) - setup_args[i] = p1; - p1 = p2 + 1; - i++; - } - else { - setup_args[i] = p1; - break; - } - } - for (i=0; i= '0') && (*cp <= '9')) { - *val = simple_strtoul(cp,NULL,0); - } - return ++x; + for (x = 0; x < MAX_SETUP_ARGS; x++) { + if (setup_used[x]) + continue; + if (!strncmp(setup_args[x], key, strlen(key))) + break; + } + if (x == MAX_SETUP_ARGS) + return 0; + setup_used[x] = 1; + cp = setup_args[x] + strlen(key); + *val = -1; + if (*cp != ':') + return ++x; + cp++; + if ((*cp >= '0') && (*cp <= '9')) { + *val = simple_strtoul(cp, NULL, 0); + } + return ++x; } @@ -1908,40 +1880,40 @@ * when reading from the card's BIOS area in in2000_detect(). */ static u32 bios_tab[] in2000__INITDATA = { - 0xc8000, - 0xd0000, - 0xd8000, - 0 - }; + 0xc8000, + 0xd0000, + 0xd8000, + 0 +}; static const unsigned short base_tab[] in2000__INITDATA = { - 0x220, - 0x200, - 0x110, - 0x100, - }; + 0x220, + 0x200, + 0x110, + 0x100, +}; static const int int_tab[] in2000__INITDATA = { - 15, - 14, - 11, - 10 - }; + 15, + 14, + 11, + 10 +}; static int __init in2000_detect(Scsi_Host_Template * tpnt) { -struct Scsi_Host *instance; -struct IN2000_hostdata *hostdata; -int detect_count; -int bios; -int x; -unsigned short base; -uchar switches; -uchar hrev; -int flags; -int val; -char buf[32]; + struct Scsi_Host *instance; + struct IN2000_hostdata *hostdata; + int detect_count; + int bios; + int x; + unsigned short base; + uchar switches; + uchar hrev; + int flags; + int val; + char buf[32]; /* Thanks to help from Bill Earnest, probing for IN2000 cards is a * pretty straightforward and fool-proof operation. There are 3 @@ -1955,203 +1927,187 @@ * or disabled. */ - if (!done_setup && setup_strings) - in2000_setup(setup_strings,0); + if (!done_setup && setup_strings) + in2000_setup(setup_strings, 0); - detect_count = 0; - for (bios = 0; bios_tab[bios]; bios++) { - if (check_setup_args("ioport",&flags,&val,buf)) { - base = val; - switches = ~inb(base + IO_SWITCHES) & 0xff; - printk("Forcing IN2000 detection at IOport 0x%x ",base); - bios = 2; - } + detect_count = 0; + for (bios = 0; bios_tab[bios]; bios++) { + if (check_setup_args("ioport", &flags, &val, buf)) { + base = val; + switches = ~inb(base + IO_SWITCHES) & 0xff; + printk("Forcing IN2000 detection at IOport 0x%x ", base); + bios = 2; + } /* * There have been a couple of BIOS versions with different layouts * for the obvious ID strings. We look for the 2 most common ones and * hope that they cover all the cases... */ - else if (isa_readl(bios_tab[bios]+0x10) == 0x41564f4e || - isa_readl(bios_tab[bios]+0x30) == 0x61776c41) { - printk("Found IN2000 BIOS at 0x%x ",(unsigned int)bios_tab[bios]); + else if (isa_readl(bios_tab[bios] + 0x10) == 0x41564f4e || isa_readl(bios_tab[bios] + 0x30) == 0x61776c41) { + printk("Found IN2000 BIOS at 0x%x ", (unsigned int) bios_tab[bios]); /* Read the switch image that's mapped into EPROM space */ - switches = ~((isa_readb(bios_tab[bios]+0x20) & 0xff)); + switches = ~((isa_readb(bios_tab[bios] + 0x20) & 0xff)); /* Find out where the IO space is */ - x = switches & (SW_ADDR0 | SW_ADDR1); - base = base_tab[x]; + x = switches & (SW_ADDR0 | SW_ADDR1); + base = base_tab[x]; /* Check for the IN2000 signature in IO space. */ - x = ~inb(base + IO_SWITCHES) & 0xff; - if (x != switches) { - printk("Bad IO signature: %02x vs %02x.\n",x,switches); - continue; - } - } - else - continue; + x = ~inb(base + IO_SWITCHES) & 0xff; + if (x != switches) { + printk("Bad IO signature: %02x vs %02x.\n", x, switches); + continue; + } + } else + continue; /* OK. We have a base address for the IO ports - run a few safety checks */ - if (!(switches & SW_BIT7)) { /* I _think_ all cards do this */ - printk("There is no IN-2000 SCSI card at IOport 0x%03x!\n",base); - continue; - } + if (!(switches & SW_BIT7)) { /* I _think_ all cards do this */ + printk("There is no IN-2000 SCSI card at IOport 0x%03x!\n", base); + continue; + } /* Let's assume any hardware version will work, although the driver * has only been tested on 0x21, 0x22, 0x25, 0x26, and 0x27. We'll * print out the rev number for reference later, but accept them all. */ - hrev = inb(base + IO_HARDWARE); + hrev = inb(base + IO_HARDWARE); - /* Bit 2 tells us if interrupts are disabled */ - if (switches & SW_DISINT) { - printk("The IN-2000 SCSI card at IOport 0x%03x ",base); - printk("is not configured for interrupt operation!\n"); - printk("This driver requires an interrupt: cancelling detection.\n"); - continue; - } + /* Bit 2 tells us if interrupts are disabled */ + if (switches & SW_DISINT) { + printk("The IN-2000 SCSI card at IOport 0x%03x ", base); + printk("is not configured for interrupt operation!\n"); + printk("This driver requires an interrupt: cancelling detection.\n"); + continue; + } /* Ok. We accept that there's an IN2000 at ioaddr 'base'. Now * initialize it. */ - tpnt->proc_name = "in2000"; - instance = scsi_register(tpnt, sizeof(struct IN2000_hostdata)); - if(instance == NULL) - continue; - detect_count++; - if (!instance_list) - instance_list = instance; - hostdata = (struct IN2000_hostdata *)instance->hostdata; - instance->io_port = hostdata->io_base = base; - hostdata->dip_switch = switches; - hostdata->hrev = hrev; - - write1_io(0,IO_FIFO_WRITE); /* clear fifo counter */ - write1_io(0,IO_FIFO_READ); /* start fifo out in read mode */ - write1_io(0,IO_INTR_MASK); /* allow all ints */ - x = int_tab[(switches & (SW_INT0 | SW_INT1)) >> SW_INT_SHIFT]; - if (request_irq(x, in2000_intr, SA_INTERRUPT, "in2000", instance)) { - printk("in2000_detect: Unable to allocate IRQ.\n"); - detect_count--; - continue; - } - instance->irq = x; - instance->n_io_port = 13; - request_region(base, 13, "in2000"); /* lock in this IO space for our use */ - - for (x = 0; x < 8; x++) { - hostdata->busy[x] = 0; - hostdata->sync_xfer[x] = calc_sync_xfer(DEFAULT_SX_PER/4,DEFAULT_SX_OFF); - hostdata->sync_stat[x] = SS_UNSET; /* using default sync values */ + tpnt->proc_name = "in2000"; + instance = scsi_register(tpnt, sizeof(struct IN2000_hostdata)); + if (instance == NULL) + continue; + detect_count++; + hostdata = (struct IN2000_hostdata *) instance->hostdata; + instance->io_port = hostdata->io_base = base; + hostdata->dip_switch = switches; + hostdata->hrev = hrev; + + write1_io(0, IO_FIFO_WRITE); /* clear fifo counter */ + write1_io(0, IO_FIFO_READ); /* start fifo out in read mode */ + write1_io(0, IO_INTR_MASK); /* allow all ints */ + x = int_tab[(switches & (SW_INT0 | SW_INT1)) >> SW_INT_SHIFT]; + if (request_irq(x, in2000_intr, SA_INTERRUPT, "in2000", instance)) { + printk("in2000_detect: Unable to allocate IRQ.\n"); + detect_count--; + continue; + } + instance->irq = x; + instance->n_io_port = 13; + request_region(base, 13, "in2000"); /* lock in this IO space for our use */ + + for (x = 0; x < 8; x++) { + hostdata->busy[x] = 0; + hostdata->sync_xfer[x] = calc_sync_xfer(DEFAULT_SX_PER / 4, DEFAULT_SX_OFF); + hostdata->sync_stat[x] = SS_UNSET; /* using default sync values */ #ifdef PROC_STATISTICS - hostdata->cmd_cnt[x] = 0; - hostdata->disc_allowed_cnt[x] = 0; - hostdata->disc_done_cnt[x] = 0; + hostdata->cmd_cnt[x] = 0; + hostdata->disc_allowed_cnt[x] = 0; + hostdata->disc_done_cnt[x] = 0; #endif - } - hostdata->input_Q = NULL; - hostdata->selecting = NULL; - hostdata->connected = NULL; - hostdata->disconnected_Q = NULL; - hostdata->state = S_UNCONNECTED; - hostdata->fifo = FI_FIFO_UNUSED; - hostdata->level2 = L2_BASIC; - hostdata->disconnect = DIS_ADAPTIVE; - hostdata->args = DEBUG_DEFAULTS; - hostdata->incoming_ptr = 0; - hostdata->outgoing_len = 0; - hostdata->default_sx_per = DEFAULT_SX_PER; + } + hostdata->input_Q = NULL; + hostdata->selecting = NULL; + hostdata->connected = NULL; + hostdata->disconnected_Q = NULL; + hostdata->state = S_UNCONNECTED; + hostdata->fifo = FI_FIFO_UNUSED; + hostdata->level2 = L2_BASIC; + hostdata->disconnect = DIS_ADAPTIVE; + hostdata->args = DEBUG_DEFAULTS; + hostdata->incoming_ptr = 0; + hostdata->outgoing_len = 0; + hostdata->default_sx_per = DEFAULT_SX_PER; /* Older BIOS's had a 'sync on/off' switch - use its setting */ - if (isa_readl(bios_tab[bios]+0x10) == 0x41564f4e && (switches & SW_SYNC_DOS5)) - hostdata->sync_off = 0x00; /* sync defaults to on */ - else - hostdata->sync_off = 0xff; /* sync defaults to off */ + if (isa_readl(bios_tab[bios] + 0x10) == 0x41564f4e && (switches & SW_SYNC_DOS5)) + hostdata->sync_off = 0x00; /* sync defaults to on */ + else + hostdata->sync_off = 0xff; /* sync defaults to off */ #ifdef PROC_INTERFACE - hostdata->proc = PR_VERSION|PR_INFO|PR_STATISTICS| - PR_CONNECTED|PR_INPUTQ|PR_DISCQ| - PR_STOP; + hostdata->proc = PR_VERSION | PR_INFO | PR_STATISTICS | PR_CONNECTED | PR_INPUTQ | PR_DISCQ | PR_STOP; #ifdef PROC_STATISTICS - hostdata->int_cnt = 0; + hostdata->int_cnt = 0; #endif #endif - if (check_setup_args("nosync",&flags,&val,buf)) - hostdata->sync_off = val; + if (check_setup_args("nosync", &flags, &val, buf)) + hostdata->sync_off = val; - if (check_setup_args("period",&flags,&val,buf)) - hostdata->default_sx_per = sx_table[round_period((unsigned int)val)].period_ns; + if (check_setup_args("period", &flags, &val, buf)) + hostdata->default_sx_per = sx_table[round_period((unsigned int) val)].period_ns; - if (check_setup_args("disconnect",&flags,&val,buf)) { - if ((val >= DIS_NEVER) && (val <= DIS_ALWAYS)) - hostdata->disconnect = val; - else - hostdata->disconnect = DIS_ADAPTIVE; - } + if (check_setup_args("disconnect", &flags, &val, buf)) { + if ((val >= DIS_NEVER) && (val <= DIS_ALWAYS)) + hostdata->disconnect = val; + else + hostdata->disconnect = DIS_ADAPTIVE; + } - if (check_setup_args("noreset",&flags,&val,buf)) - hostdata->args ^= A_NO_SCSI_RESET; + if (check_setup_args("noreset", &flags, &val, buf)) + hostdata->args ^= A_NO_SCSI_RESET; - if (check_setup_args("level2",&flags,&val,buf)) - hostdata->level2 = val; + if (check_setup_args("level2", &flags, &val, buf)) + hostdata->level2 = val; - if (check_setup_args("debug",&flags,&val,buf)) - hostdata->args = (val & DB_MASK); + if (check_setup_args("debug", &flags, &val, buf)) + hostdata->args = (val & DB_MASK); #ifdef PROC_INTERFACE - if (check_setup_args("proc",&flags,&val,buf)) - hostdata->proc = val; + if (check_setup_args("proc", &flags, &val, buf)) + hostdata->proc = val; #endif - /* FIXME: not strictly needed I think but the called code expects - to be locked */ - spin_lock_irqsave(instance->host_lock, flags); - x = reset_hardware(instance,(hostdata->args & A_NO_SCSI_RESET)?RESET_CARD:RESET_CARD_AND_BUS); - spin_unlock_irqrestore(instance->host_lock, flags); - - hostdata->microcode = read_3393(hostdata,WD_CDB_1); - if (x & 0x01) { - if (x & B_FLAG) - hostdata->chip = C_WD33C93B; - else - hostdata->chip = C_WD33C93A; - } - else - hostdata->chip = C_WD33C93; - - printk("dip_switch=%02x irq=%d ioport=%02x floppy=%s sync/DOS5=%s ", - (switches & 0x7f), - instance->irq,hostdata->io_base, - (switches & SW_FLOPPY)?"Yes":"No", - (switches & SW_SYNC_DOS5)?"Yes":"No"); - printk("hardware_ver=%02x chip=%s microcode=%02x\n", - hrev, - (hostdata->chip==C_WD33C93)?"WD33c93": - (hostdata->chip==C_WD33C93A)?"WD33c93A": - (hostdata->chip==C_WD33C93B)?"WD33c93B":"unknown", - hostdata->microcode); + /* FIXME: not strictly needed I think but the called code expects + to be locked */ + spin_lock_irqsave(instance->host_lock, flags); + x = reset_hardware(instance, (hostdata->args & A_NO_SCSI_RESET) ? RESET_CARD : RESET_CARD_AND_BUS); + spin_unlock_irqrestore(instance->host_lock, flags); + + hostdata->microcode = read_3393(hostdata, WD_CDB_1); + if (x & 0x01) { + if (x & B_FLAG) + hostdata->chip = C_WD33C93B; + else + hostdata->chip = C_WD33C93A; + } else + hostdata->chip = C_WD33C93; + + printk("dip_switch=%02x irq=%d ioport=%02x floppy=%s sync/DOS5=%s ", (switches & 0x7f), instance->irq, hostdata->io_base, (switches & SW_FLOPPY) ? "Yes" : "No", (switches & SW_SYNC_DOS5) ? "Yes" : "No"); + printk("hardware_ver=%02x chip=%s microcode=%02x\n", hrev, (hostdata->chip == C_WD33C93) ? "WD33c93" : (hostdata->chip == C_WD33C93A) ? "WD33c93A" : (hostdata->chip == C_WD33C93B) ? "WD33c93B" : "unknown", hostdata->microcode); #ifdef DEBUGGING_ON - printk("setup_args = "); - for (x=0; xsync_off == 0xff) - printk("Sync-transfer DISABLED on all devices: ENABLE from command-line\n"); - printk("IN2000 driver version %s - %s\n",IN2000_VERSION,IN2000_DATE); - } + if (hostdata->sync_off == 0xff) + printk("Sync-transfer DISABLED on all devices: ENABLE from command-line\n"); + printk("IN2000 driver version %s - %s\n", IN2000_VERSION, IN2000_DATE); + } - return detect_count; + return detect_count; } static int in2000_release(struct Scsi_Host *shost) @@ -2163,43 +2119,40 @@ return 0; } - /* NOTE: I lifted this function straight out of the old driver, * and have not tested it. Presumably it does what it's * supposed to do... */ -static int in2000_biosparam(struct scsi_device *sdev, - struct block_device *bdev, - sector_t capacity, int *iinfo) -{ -int size; - - size = capacity; - iinfo[0] = 64; - iinfo[1] = 32; - iinfo[2] = size >> 11; +static int in2000_biosparam(struct scsi_device *sdev, struct block_device *bdev, sector_t capacity, int *iinfo) +{ + int size; + + size = capacity; + iinfo[0] = 64; + iinfo[1] = 32; + iinfo[2] = size >> 11; /* This should approximate the large drive handling that the DOS ASPI manager uses. Drives very near the boundaries may not be handled correctly (i.e. near 2.0 Gb and 4.0 Gb) */ - if (iinfo[2] > 1024) { - iinfo[0] = 64; - iinfo[1] = 63; - iinfo[2] = (unsigned long)capacity / (iinfo[0] * iinfo[1]); - } - if (iinfo[2] > 1024) { - iinfo[0] = 128; - iinfo[1] = 63; - iinfo[2] = (unsigned long)capacity / (iinfo[0] * iinfo[1]); - } - if (iinfo[2] > 1024) { - iinfo[0] = 255; - iinfo[1] = 63; - iinfo[2] = (unsigned long)capacity / (iinfo[0] * iinfo[1]); - } - return 0; + if (iinfo[2] > 1024) { + iinfo[0] = 64; + iinfo[1] = 63; + iinfo[2] = (unsigned long) capacity / (iinfo[0] * iinfo[1]); + } + if (iinfo[2] > 1024) { + iinfo[0] = 128; + iinfo[1] = 63; + iinfo[2] = (unsigned long) capacity / (iinfo[0] * iinfo[1]); + } + if (iinfo[2] > 1024) { + iinfo[0] = 255; + iinfo[1] = 63; + iinfo[2] = (unsigned long) capacity / (iinfo[0] * iinfo[1]); + } + return 0; } @@ -2208,21 +2161,21 @@ #ifdef PROC_INTERFACE -char *bp; -char tbuf[128]; -unsigned long flags; -struct Scsi_Host *instance; -struct IN2000_hostdata *hd; -Scsi_Cmnd *cmd; -int x,i; -static int stop = 0; - - instance = scsi_host_hn_get(hn); - if (!instance) { - printk("*** Hmm... Can't find host #%d!\n",hn); - return (-ESRCH); - } - hd = (struct IN2000_hostdata *)instance->hostdata; + char *bp; + char tbuf[128]; + unsigned long flags; + struct Scsi_Host *instance; + struct IN2000_hostdata *hd; + Scsi_Cmnd *cmd; + int x, i; + static int stop = 0; + + instance = scsi_host_hn_get(hn); + if (!instance) { + printk("*** Hmm... Can't find host #%d!\n", hn); + return (-ESRCH); + } + hd = (struct IN2000_hostdata *) instance->hostdata; /* If 'in' is TRUE we need to _read_ the proc file. We accept the following * keywords (same format as command-line, but only ONE per read): @@ -2233,139 +2186,127 @@ * proc */ - if (in) { - buf[len] = '\0'; - bp = buf; - if (!strncmp(bp,"debug:",6)) { - bp += 6; - hd->args = simple_strtoul(bp,NULL,0) & DB_MASK; - } - else if (!strncmp(bp,"disconnect:",11)) { - bp += 11; - x = simple_strtoul(bp,NULL,0); - if (x < DIS_NEVER || x > DIS_ALWAYS) - x = DIS_ADAPTIVE; - hd->disconnect = x; - } - else if (!strncmp(bp,"period:",7)) { - bp += 7; - x = simple_strtoul(bp,NULL,0); - hd->default_sx_per = sx_table[round_period((unsigned int)x)].period_ns; - } - else if (!strncmp(bp,"resync:",7)) { - bp += 7; - x = simple_strtoul(bp,NULL,0); - for (i=0; i<7; i++) - if (x & (1<sync_stat[i] = SS_UNSET; - } - else if (!strncmp(bp,"proc:",5)) { - bp += 5; - hd->proc = simple_strtoul(bp,NULL,0); - } - else if (!strncmp(bp,"level2:",7)) { - bp += 7; - hd->level2 = simple_strtoul(bp,NULL,0); - } - return len; - } - - spin_lock_irqsave(instance->host_lock, flags); - bp = buf; - *bp = '\0'; - if (hd->proc & PR_VERSION) { - sprintf(tbuf,"\nVersion %s - %s. Compiled %s %s", - IN2000_VERSION,IN2000_DATE,__DATE__,__TIME__); - strcat(bp,tbuf); - } - if (hd->proc & PR_INFO) { - sprintf(tbuf,"\ndip_switch=%02x: irq=%d io=%02x floppy=%s sync/DOS5=%s", - (hd->dip_switch & 0x7f), instance->irq, hd->io_base, - (hd->dip_switch & 0x40)?"Yes":"No", - (hd->dip_switch & 0x20)?"Yes":"No"); - strcat(bp,tbuf); - strcat(bp,"\nsync_xfer[] = "); - for (x=0; x<7; x++) { - sprintf(tbuf,"\t%02x",hd->sync_xfer[x]); - strcat(bp,tbuf); - } - strcat(bp,"\nsync_stat[] = "); - for (x=0; x<7; x++) { - sprintf(tbuf,"\t%02x",hd->sync_stat[x]); - strcat(bp,tbuf); - } - } + if (in) { + buf[len] = '\0'; + bp = buf; + if (!strncmp(bp, "debug:", 6)) { + bp += 6; + hd->args = simple_strtoul(bp, NULL, 0) & DB_MASK; + } else if (!strncmp(bp, "disconnect:", 11)) { + bp += 11; + x = simple_strtoul(bp, NULL, 0); + if (x < DIS_NEVER || x > DIS_ALWAYS) + x = DIS_ADAPTIVE; + hd->disconnect = x; + } else if (!strncmp(bp, "period:", 7)) { + bp += 7; + x = simple_strtoul(bp, NULL, 0); + hd->default_sx_per = sx_table[round_period((unsigned int) x)].period_ns; + } else if (!strncmp(bp, "resync:", 7)) { + bp += 7; + x = simple_strtoul(bp, NULL, 0); + for (i = 0; i < 7; i++) + if (x & (1 << i)) + hd->sync_stat[i] = SS_UNSET; + } else if (!strncmp(bp, "proc:", 5)) { + bp += 5; + hd->proc = simple_strtoul(bp, NULL, 0); + } else if (!strncmp(bp, "level2:", 7)) { + bp += 7; + hd->level2 = simple_strtoul(bp, NULL, 0); + } + return len; + } + + spin_lock_irqsave(instance->host_lock, flags); + bp = buf; + *bp = '\0'; + if (hd->proc & PR_VERSION) { + sprintf(tbuf, "\nVersion %s - %s. Compiled %s %s", IN2000_VERSION, IN2000_DATE, __DATE__, __TIME__); + strcat(bp, tbuf); + } + if (hd->proc & PR_INFO) { + sprintf(tbuf, "\ndip_switch=%02x: irq=%d io=%02x floppy=%s sync/DOS5=%s", (hd->dip_switch & 0x7f), instance->irq, hd->io_base, (hd->dip_switch & 0x40) ? "Yes" : "No", (hd->dip_switch & 0x20) ? "Yes" : "No"); + strcat(bp, tbuf); + strcat(bp, "\nsync_xfer[] = "); + for (x = 0; x < 7; x++) { + sprintf(tbuf, "\t%02x", hd->sync_xfer[x]); + strcat(bp, tbuf); + } + strcat(bp, "\nsync_stat[] = "); + for (x = 0; x < 7; x++) { + sprintf(tbuf, "\t%02x", hd->sync_stat[x]); + strcat(bp, tbuf); + } + } #ifdef PROC_STATISTICS - if (hd->proc & PR_STATISTICS) { - strcat(bp,"\ncommands issued: "); - for (x=0; x<7; x++) { - sprintf(tbuf,"\t%ld",hd->cmd_cnt[x]); - strcat(bp,tbuf); - } - strcat(bp,"\ndisconnects allowed:"); - for (x=0; x<7; x++) { - sprintf(tbuf,"\t%ld",hd->disc_allowed_cnt[x]); - strcat(bp,tbuf); - } - strcat(bp,"\ndisconnects done: "); - for (x=0; x<7; x++) { - sprintf(tbuf,"\t%ld",hd->disc_done_cnt[x]); - strcat(bp,tbuf); - } - sprintf(tbuf,"\ninterrupts: \t%ld",hd->int_cnt); - strcat(bp,tbuf); - } + if (hd->proc & PR_STATISTICS) { + strcat(bp, "\ncommands issued: "); + for (x = 0; x < 7; x++) { + sprintf(tbuf, "\t%ld", hd->cmd_cnt[x]); + strcat(bp, tbuf); + } + strcat(bp, "\ndisconnects allowed:"); + for (x = 0; x < 7; x++) { + sprintf(tbuf, "\t%ld", hd->disc_allowed_cnt[x]); + strcat(bp, tbuf); + } + strcat(bp, "\ndisconnects done: "); + for (x = 0; x < 7; x++) { + sprintf(tbuf, "\t%ld", hd->disc_done_cnt[x]); + strcat(bp, tbuf); + } + sprintf(tbuf, "\ninterrupts: \t%ld", hd->int_cnt); + strcat(bp, tbuf); + } #endif - if (hd->proc & PR_CONNECTED) { - strcat(bp,"\nconnected: "); - if (hd->connected) { - cmd = (Scsi_Cmnd *)hd->connected; - sprintf(tbuf," %ld-%d:%d(%02x)", - cmd->pid, cmd->target, cmd->lun, cmd->cmnd[0]); - strcat(bp,tbuf); - } - } - if (hd->proc & PR_INPUTQ) { - strcat(bp,"\ninput_Q: "); - cmd = (Scsi_Cmnd *)hd->input_Q; - while (cmd) { - sprintf(tbuf," %ld-%d:%d(%02x)", - cmd->pid, cmd->target, cmd->lun, cmd->cmnd[0]); - strcat(bp,tbuf); - cmd = (Scsi_Cmnd *)cmd->host_scribble; - } - } - if (hd->proc & PR_DISCQ) { - strcat(bp,"\ndisconnected_Q:"); - cmd = (Scsi_Cmnd *)hd->disconnected_Q; - while (cmd) { - sprintf(tbuf," %ld-%d:%d(%02x)", - cmd->pid, cmd->target, cmd->lun, cmd->cmnd[0]); - strcat(bp,tbuf); - cmd = (Scsi_Cmnd *)cmd->host_scribble; - } - } - if (hd->proc & PR_TEST) { - ; /* insert your own custom function here */ - } - strcat(bp,"\n"); - spin_unlock_irqrestore(instance->host_lock, flags); - *start = buf; - if (stop) { - stop = 0; - return 0; /* return 0 to signal end-of-file */ - } - if (off > 0x40000) /* ALWAYS stop after 256k bytes have been read */ - stop = 1;; - if (hd->proc & PR_STOP) /* stop every other time */ - stop = 1; - return strlen(bp); + if (hd->proc & PR_CONNECTED) { + strcat(bp, "\nconnected: "); + if (hd->connected) { + cmd = (Scsi_Cmnd *) hd->connected; + sprintf(tbuf, " %ld-%d:%d(%02x)", cmd->pid, cmd->target, cmd->lun, cmd->cmnd[0]); + strcat(bp, tbuf); + } + } + if (hd->proc & PR_INPUTQ) { + strcat(bp, "\ninput_Q: "); + cmd = (Scsi_Cmnd *) hd->input_Q; + while (cmd) { + sprintf(tbuf, " %ld-%d:%d(%02x)", cmd->pid, cmd->target, cmd->lun, cmd->cmnd[0]); + strcat(bp, tbuf); + cmd = (Scsi_Cmnd *) cmd->host_scribble; + } + } + if (hd->proc & PR_DISCQ) { + strcat(bp, "\ndisconnected_Q:"); + cmd = (Scsi_Cmnd *) hd->disconnected_Q; + while (cmd) { + sprintf(tbuf, " %ld-%d:%d(%02x)", cmd->pid, cmd->target, cmd->lun, cmd->cmnd[0]); + strcat(bp, tbuf); + cmd = (Scsi_Cmnd *) cmd->host_scribble; + } + } + if (hd->proc & PR_TEST) { + ; /* insert your own custom function here */ + } + strcat(bp, "\n"); + spin_unlock_irqrestore(instance->host_lock, flags); + *start = buf; + if (stop) { + stop = 0; + return 0; /* return 0 to signal end-of-file */ + } + if (off > 0x40000) /* ALWAYS stop after 256k bytes have been read */ + stop = 1;; + if (hd->proc & PR_STOP) /* stop every other time */ + stop = 1; + return strlen(bp); -#else /* PROC_INTERFACE */ +#else /* PROC_INTERFACE */ - return 0; + return 0; -#endif /* PROC_INTERFACE */ +#endif /* PROC_INTERFACE */ } @@ -2374,4 +2315,3 @@ static Scsi_Host_Template driver_template = IN2000; #include "scsi_module.c" - diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/scsi/inia100.c linux.2.5.45-ac1/drivers/scsi/inia100.c --- linux.2.5.45/drivers/scsi/inia100.c 2002-11-03 01:15:47.000000000 +0000 +++ linux.2.5.45-ac1/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.45/drivers/scsi/inia100.h linux.2.5.45-ac1/drivers/scsi/inia100.h --- linux.2.5.45/drivers/scsi/inia100.h 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.45-ac1/drivers/scsi/inia100.h 2002-11-03 01:15:35.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,6 +90,9 @@ detect: inia100_detect, \ release: inia100_release, \ queuecommand: inia100_queue, \ + 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.45/drivers/scsi/megaraid.c linux.2.5.45-ac1/drivers/scsi/megaraid.c --- linux.2.5.45/drivers/scsi/megaraid.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.45-ac1/drivers/scsi/megaraid.c 2002-11-02 21:51:08.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,121 +560,8 @@ 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 +#define pci_alloc_consistent pci_alloc_consistent +#define pci_free_consistent pci_free_consistent /* set SERDEBUG to 1 to enable serial debugging */ #define SERDEBUG 0 @@ -705,7 +572,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 +583,6 @@ memcpy(page, &megaCfg->procbuf[offset], count); \ megaCfg->procidx = 0; \ megaCfg->procbuf[0] = 0; -#endif /* * ================================================================ @@ -730,11 +595,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 +621,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 +647,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 +742,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 +781,6 @@ default: break; } -#endif /* Unlink from pending queue */ if (pScb == megaCfg->qPendingH) { @@ -991,9 +844,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 +910,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 +925,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 +934,6 @@ pScb->bounce_buffer, SCpnt->request_bufflen); break; } -#endif mega_freeSCB (megaCfg, pScb); @@ -1101,11 +942,6 @@ * 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 ) { @@ -1114,11 +950,6 @@ } else { memcpy(&c, SCpnt->request_buffer, 0x1); } -#if 0 - if( (c & 0x1F ) == TYPE_DISK ) { - status = 0xF0; - } -#endif if( IS_RAID_CH(SCpnt->channel) && ((c & 0x1F ) == TYPE_DISK) ) { status = 0xF0; } @@ -1214,22 +1045,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 +1141,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 +1153,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 +1166,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 +1191,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 +1262,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 +1281,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 +1307,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 +1314,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 +1327,6 @@ } else { pScb->dma_type = M_RD_PTHRU_WITH_BULK_DATA; } -#else - mbox->xferaddr = virt_to_bus(pthru); -#endif } return pScb; } @@ -1597,11 +1376,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 +1393,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 +1405,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 +1419,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 +1436,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 +1455,6 @@ ); break; } -#else - epthru->numsgelements = - mega_build_sglist( - megacfg, scb, (u32 *)&epthru->dataxferaddr, - (u32 *)&epthru->dataxferlen - ); -#endif return epthru; } @@ -1741,8 +1495,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 +1507,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 +1526,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 +1579,7 @@ for (idx = 0; idx < MAX_FIRMWARE_STATUS; idx++) completed[idx] = 0; - IO_LOCK(megaCfg->host); + spin_lock_irqsave(megaCfg->host, io_flags); megaCfg->nInterrupts++; qCnt = 0xff; @@ -2124,27 +1600,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 +1679,7 @@ megaCfg->flag &= ~IN_ISR; /* Loop through any pending requests */ mega_runpendq (megaCfg); - IO_UNLOCK(megaCfg->host); + spin_unlock_irqrestore(megaCfg->host, io_flags); } @@ -2267,9 +1724,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 +1738,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); @@ -2299,9 +1750,7 @@ printk ("Blocked mailbox......!!\n"); udelay (1000); -#if DEBUG showMbox (pLastScb); -#endif /* Abort command */ if (pScb == NULL) { @@ -2320,7 +1769,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 +1777,6 @@ mbox->xferaddr = 0xFFFFFFFF; break; } -#endif /* Kick IO */ if (intr) { @@ -2417,9 +1864,7 @@ struct scatterlist *sgList; int idx; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) int sgcnt; -#endif mega_mailbox *mbox = NULL; @@ -2427,7 +1872,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 +1892,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 +1918,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 +1948,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 +1959,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 +2028,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 +2044,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 +2063,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 +2089,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 +2096,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 +2113,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 +2128,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 +2176,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,116 +2189,54 @@ 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)) { - pcibios_read_config_word (pciBus, pciDevFun, - 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) - pcibios_read_config_dword (pciBus, pciDevFun, - PCI_CONF_AMISIG64, &magic64); + 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) { + 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 + pci_read_config_word (pdev, PCI_SUBSYSTEM_VENDOR_ID, &subsysvid); + pci_read_config_word (pdev, PCI_SUBSYSTEM_ID, &subsysid); } - 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)); + 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++; @@ -2973,8 +2271,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; @@ -2993,10 +2290,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; @@ -3014,41 +2308,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 (subsysid == 0x1111 && subsysvid == 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 " @@ -3066,20 +2349,21 @@ /* * 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(subsysvid == HP_SUBSYS_ID && (subsysid == 0x60E7 || subsysid == 0x60E8 || subsysid == 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"); @@ -3149,21 +2433,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); } @@ -3174,23 +2456,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') { @@ -3215,17 +2486,10 @@ count += mega_findCard (pHostTmpl, PCI_VENDOR_ID_AMI, PCI_DEVICE_ID_AMI_MEGARAID3, BOARD_QUARTZ); - mega_reorder_hosts (); #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 @@ -3263,7 +2527,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; @@ -3371,9 +2635,7 @@ 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; @@ -3386,14 +2648,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 @@ -3410,13 +2668,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 - } @@ -3432,10 +2685,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; @@ -3446,14 +2696,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; @@ -3473,180 +2719,11 @@ } } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) pci_unmap_single(megacfg->dev, dma_handle, (2 * 1024L), PCI_DMA_FROMDEVICE); -#endif - -} - - -static void mega_reorder_hosts (void) -{ - struct Scsi_Host *shpnt; - struct Scsi_Host *shone; - struct Scsi_Host *shtwo; - mega_host_config *boot_host; - int i; - - /* - * Find the (first) host which has it's BIOS enabled - */ - boot_host = NULL; - for (i = 0; i < MAX_CONTROLLERS; i++) { - if (mega_hbas[i].is_bios_enabled) { - boot_host = mega_hbas[i].hostdata_addr; - break; - } - } - - if (boot_host == NULL) { - printk (KERN_WARNING "megaraid: no BIOS enabled.\n"); - return; - } - - /* - * Traverse through the list of SCSI hosts for our HBA locations - */ - shone = shtwo = NULL; - for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) { - /* Is it one of ours? */ - for (i = 0; i < MAX_CONTROLLERS; i++) { - if ((mega_host_config *) shpnt->hostdata == - mega_hbas[i].hostdata_addr) { - /* Does this one has BIOS enabled */ - if (mega_hbas[i].hostdata_addr == boot_host) { - - /* Are we first */ - if (shtwo == NULL) /* Yes! */ - return; - else { /* :-( */ - shone = shpnt; - } - } else { - if (!shtwo) { - /* were we here before? xchng first */ - shtwo = shpnt; - } - } - break; - } - } - /* - * Have we got the boot host and one which does not have the bios - * enabled. - */ - if (shone && shtwo) - break; - } - if (shone && shtwo) { - mega_swap_hosts (shone, shtwo); - } - return; } -static void mega_swap_hosts (struct Scsi_Host *shone, struct Scsi_Host *shtwo) -{ - struct Scsi_Host *prevtoshtwo; - struct Scsi_Host *prevtoshone; - struct Scsi_Host *save = NULL;; - - /* Are these two nodes adjacent */ - if (shtwo->next == shone) { - - if (shtwo == scsi_hostlist && shone->next == NULL) { - - /* just two nodes */ - scsi_hostlist = shone; - shone->next = shtwo; - shtwo->next = NULL; - } else if (shtwo == scsi_hostlist) { - /* first two nodes of the list */ - - scsi_hostlist = shone; - shtwo->next = shone->next; - scsi_hostlist->next = shtwo; - } else if (shone->next == NULL) { - /* last two nodes of the list */ - - prevtoshtwo = scsi_hostlist; - - while (prevtoshtwo->next != shtwo) - prevtoshtwo = prevtoshtwo->next; - - prevtoshtwo->next = shone; - shone->next = shtwo; - shtwo->next = NULL; - } else { - prevtoshtwo = scsi_hostlist; - - while (prevtoshtwo->next != shtwo) - prevtoshtwo = prevtoshtwo->next; - - prevtoshtwo->next = shone; - shtwo->next = shone->next; - shone->next = shtwo; - } - - } else if (shtwo == scsi_hostlist && shone->next == NULL) { - /* shtwo at head, shone at tail, not adjacent */ - - prevtoshone = scsi_hostlist; - - while (prevtoshone->next != shone) - prevtoshone = prevtoshone->next; - - scsi_hostlist = shone; - shone->next = shtwo->next; - prevtoshone->next = shtwo; - shtwo->next = NULL; - } else if (shtwo == scsi_hostlist && shone->next != NULL) { - /* shtwo at head, shone is not at tail */ - - prevtoshone = scsi_hostlist; - while (prevtoshone->next != shone) - prevtoshone = prevtoshone->next; - - scsi_hostlist = shone; - prevtoshone->next = shtwo; - save = shtwo->next; - shtwo->next = shone->next; - shone->next = save; - } else if (shone->next == NULL) { - /* shtwo not at head, shone at tail */ - - prevtoshtwo = scsi_hostlist; - prevtoshone = scsi_hostlist; - - while (prevtoshtwo->next != shtwo) - prevtoshtwo = prevtoshtwo->next; - while (prevtoshone->next != shone) - prevtoshone = prevtoshone->next; - - prevtoshtwo->next = shone; - shone->next = shtwo->next; - prevtoshone->next = shtwo; - shtwo->next = NULL; - - } else { - prevtoshtwo = scsi_hostlist; - prevtoshone = scsi_hostlist; - save = NULL;; - - while (prevtoshtwo->next != shtwo) - prevtoshtwo = prevtoshtwo->next; - while (prevtoshone->next != shone) - prevtoshone = prevtoshone->next; - - prevtoshtwo->next = shone; - save = shone->next; - shone->next = shtwo->next; - prevtoshone->next = shtwo; - shtwo->next = save; - } - return; -} static inline void mega_freeSgList (mega_host_config * megaCfg) { @@ -3660,16 +2737,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; @@ -3701,12 +2775,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) @@ -3741,7 +2814,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); @@ -3756,7 +2828,6 @@ megaCfg->qCompletedT->host_scribble = (unsigned char *) NULL; megaCfg->qCcnt++; - DRIVER_UNLOCK (megaCfg); return 0; } @@ -3781,7 +2852,6 @@ megaCfg->qPcnt++; if (mega_runpendq (megaCfg) == -1) { - DRIVER_UNLOCK (megaCfg); return 0; } } @@ -3799,38 +2869,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); 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); 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); @@ -3843,30 +2906,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; @@ -3875,9 +2939,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, @@ -3894,10 +2956,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 */ @@ -3914,12 +2976,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; @@ -3951,6 +3012,7 @@ } mega_rundoneq (megaCfg); + spin_unlock_irqrestore(host->host_lock, flags); return rc; } @@ -3958,22 +3020,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, @@ -3996,7 +3058,8 @@ megaCfg->flag &= ~IN_RESET; mega_rundoneq (megaCfg); - return rc; + spin_unlock_irqrestore(host->host_lock, flags); + return SUCCESS; } #ifdef CONFIG_PROC_FS @@ -4144,42 +3207,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 }; @@ -4188,25 +3219,15 @@ 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); } } @@ -4222,7 +3243,7 @@ * 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; @@ -4287,13 +3308,12 @@ * * Returns : -1 on failure, 0 on success. */ -static int -mega_partsize(struct block_device *bdev, sector_t capacity, int *geom) +static int mega_partsize(struct block_device *bdev, sector_t capacity, int *geom) { struct partition *p, *largest = NULL; int i, largest_cyl; - int heads, cyls, sectors; - int capacity = capacity; + int heads, sectors; + sector_t cyls; unsigned char *buf; if (!(buf = scsi_bios_ptable(bdev))) @@ -4323,8 +3343,9 @@ kfree(buf); return -1; } - - cyls = capacity/(heads * sectors); + + cyls = capacity; + do_div(cyls, heads * sectors); geom[0] = heads; geom[1] = sectors; @@ -4399,7 +3420,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, @@ -4408,9 +3428,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 @@ -4418,20 +3435,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) ); @@ -4443,16 +3453,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) { /* @@ -4460,8 +3466,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); } } @@ -4509,7 +3514,6 @@ */ static int megadev_open (struct inode *inode, struct file *filep) { - MOD_INC_USE_COUNT; return 0; /* success */ } @@ -4521,9 +3525,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; @@ -4539,22 +3543,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; @@ -4565,10 +3565,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; @@ -4613,24 +3609,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; @@ -4671,54 +3660,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 */ - for( shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next ) { - if( shpnt->hostdata == (unsigned long *)megaCtlrs[adapno] ) { - megacfg = (mega_host_config *)shpnt->hostdata; - break; - } - } + 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; } @@ -4735,10 +3698,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); @@ -4756,17 +3719,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; @@ -4781,7 +3741,7 @@ adapno = GETADAP (adapno); if (adapno >= numCtlrs) - return (-ENODEV); + return -ENODEV; /* save the user address */ uaddr = ioc.data; @@ -4789,27 +3749,14 @@ 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 */ - for( shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next ) { - if( shpnt->hostdata == (unsigned long *)megaCtlrs[adapno] ) { - megacfg = (mega_host_config *)shpnt->hostdata; - break; - } - } - if(shpnt == NULL) return -ENODEV; + shpnt = megaCtlrs[adapno]->host; + if(shpnt == NULL) + return -ENODEV; /* * ioctls for deleting logical drives is a special case, so check @@ -4818,7 +3765,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; } @@ -4833,37 +3779,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; } @@ -4884,10 +3818,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) { @@ -4911,14 +3845,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; @@ -4933,14 +3863,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; @@ -4973,14 +3901,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 @@ -5003,14 +3926,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; @@ -5033,18 +3948,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]; @@ -5069,8 +3978,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]; @@ -5091,11 +4000,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; @@ -5103,16 +4011,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, flags); /* * Attach the internal queue to the pending queue */ @@ -5146,25 +4053,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]; @@ -5182,12 +4083,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 @@ -5198,100 +4098,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.45/drivers/scsi/megaraid.h linux.2.5.45-ac1/drivers/scsi/megaraid.h --- linux.2.5.45/drivers/scsi/megaraid.h 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.45-ac1/drivers/scsi/megaraid.h 2002-11-02 21:15:08.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,54 +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 */\ - abort: megaraid_abort, /* Abort Command Function */\ - reset: megaraid_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, \ - } -#endif - /*********************************************************************** * Structure Declarations for the Firmware supporting 40 Logical Drives * and 256 Physical Drives. @@ -943,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, @@ -989,8 +937,6 @@ int lock, int intr); static int mega_is_bios_enabled (mega_host_config *); -static void mega_reorder_hosts (void); -static void mega_swap_hosts (struct Scsi_Host *, struct Scsi_Host *); static void mega_create_proc_entry (int index, struct proc_dir_entry *); static int mega_support_ext_cdb(mega_host_config *); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/scsi/NCR5380.c linux.2.5.45-ac1/drivers/scsi/NCR5380.c --- linux.2.5.45/drivers/scsi/NCR5380.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.45-ac1/drivers/scsi/NCR5380.c 2002-11-03 00:20:17.000000000 +0000 @@ -345,6 +345,51 @@ } } +/** + * NCR5380_poll_politely - wait for NCR5380 status bits + * @instance: controller to poll + * @reg: 5380 register to poll + * @bit: Bitmask to check + * @val: Value required to exit + * + * Polls the NCR5380 in a reasonably efficient manner waiting for + * an event to occur, after a short quick poll we begin giving the + * CPU back in non IRQ contexts + * + * Returns the value of the register or a negative error code. + */ + +static int NCR5380_poll_politely(struct Scsi_Host *instance, int reg, int bit, int val, int t) +{ + NCR5380_local_declare(); + int n = 500; /* At about 8uS a cycle for the cpu access */ + unsigned long end = jiffies + t; + int r; + + NCR5380_setup(instance); + + while( n-- > 0) + { + r = NCR5380_read(reg); + if((r & bit) == val) + return r; + cpu_relax(); + } + + /* t time yet ? */ + while(time_before(jiffies, end)) + { + r = NCR5380_read(reg); + if((r & bit) == val) + return r; + if(!in_interrupt()) + yield(); + else + cpu_relax(); + } + return -ETIMEDOUT; +} + static struct { unsigned char value; const char *name; @@ -679,8 +724,11 @@ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA | ICR_ASSERT_SEL); while (probe_irq == IRQ_NONE && time_before(jiffies, timeout)) - barrier(); - + { + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1); + } + NCR5380_write(SELECT_ENABLE_REG, 0); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); @@ -1026,11 +1074,7 @@ case 5: printk(KERN_INFO "scsi%d: SCSI bus busy, waiting up to five seconds\n", instance->host_no); timeout = jiffies + 5 * HZ; - while (time_before(jiffies, timeout) && (NCR5380_read(STATUS_REG) & SR_BSY)) - { - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); - } + NCR5380_poll_politely(instance, STATUS_REG, SR_BSY, 0, 5*HZ); break; case 2: printk(KERN_WARNING "scsi%d: bus busy, attempting abort\n", instance->host_no); @@ -1057,8 +1101,7 @@ * twiddling done to the host specific fields of cmd. If the * main coroutine is not running, it is restarted. * - * Locks: host lock taken by caller. Called functions drop and - * retake this lock. Called functions take dma lock. + * Locks: host lock taken by caller */ static int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) @@ -1164,7 +1207,8 @@ instance = hostdata->host; - spin_lock_irqsave(instance->host_lock, flags); + if(instance->irq != IRQ_NONE) + spin_lock_irqsave(instance->host_lock, flags); do { /* Lock held here */ @@ -1243,12 +1287,9 @@ do not respond to commands immediately after a scan */ printk(KERN_DEBUG "scsi%d: device %d did not respond in time\n", instance->host_no, tmp->target); - //spin_lock_irq(&io_request_lock); LIST(tmp, hostdata->issue_queue); tmp->host_scribble = (unsigned char *) hostdata->issue_queue; hostdata->issue_queue = tmp; - //spin_unlock_irq(&io_request_lock); - hostdata->time_expires = jiffies + USLEEP_WAITLONG; NCR5380_set_timer(instance); } @@ -1267,7 +1308,8 @@ break; } while (!done); - spin_unlock_irqrestore(instance->host_lock, flags); + if(instance->irq != IRQ_NONE) + spin_unlock_irqrestore(instance->host_lock, flags); } #ifndef DONT_USE_INTR @@ -1341,24 +1383,9 @@ hostdata->dmalen = 0; (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG); -#if NCR_TIMEOUT - { - unsigned long timeout = jiffies + NCR_TIMEOUT; - - spin_unlock_irq(instance->host_lock); - /* FIXME: prove timer is always running here! */ - while (NCR5380_read(BUS_AND_STATUS_REG) & BASR_ACK && time_before(jiffies, timeout)) - cpu_relax(); - spin_lock_irq(instance->host_lock); - - if (time_after_eq(jiffies, timeout)) - printk("scsi%d: timeout at NCR5380.c:%d\n", host->host_no, __LINE__); - } -#else /* NCR_TIMEOUT */ - while (NCR5380_read(BUS_AND_STATUS_REG) & BASR_ACK) - cpu_relax(); -#endif + /* FIXME: we need to poll briefly then defer a workqueue task ! */ + NCR5380_poll_politely(hostdata, BUS_AND_STATUS_REG, BASR_ACK, 0, 2*HZ); NCR5380_write(MODE_REG, MR_BASE); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); @@ -1438,7 +1465,7 @@ * If failed (no target) : cmd->scsi_done() will be called, and the * cmd->result host byte set to DID_BAD_TARGET. * - * Locks: caller holds hostdata lock + * Locks: caller holds hostdata lock in IRQ mode */ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag) @@ -1451,8 +1478,11 @@ unsigned long timeout; unsigned char value; NCR5380_setup(instance); + int err; if (hostdata->selecting) { + if(instance->irq != IRQ_NONE) + spin_unlock_irq(instance->host_lock); goto part2; /* RvC: sorry prof. Dijkstra, but it keeps the rest of the code nearly the same */ } @@ -1476,29 +1506,22 @@ NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask); NCR5380_write(MODE_REG, MR_ARBITRATE); - /* Wait for arbitration logic to complete */ -#if NCR_TIMEOUT - { - unsigned long timeout = jiffies + 2 * NCR_TIMEOUT; - + if(instance->irq != IRQ_NONE) spin_unlock_irq(instance->host_lock); - while (!(NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS) - && time_before(jiffies, timeout)) - cpu_relax(); + /* We can be relaxed here, interrupts are on, we are + in workqueue context, the birds are singing in the trees */ + err = NCR5380_poll_politely(instance, INITIATOR_COMMAND_REG, ICR_ARBITRATION_PROGRESS, ICR_ARBITRATION_PROGRESS, 5*HZ); + if(instance->irq != IRQ_NONE) spin_lock_irq(instance->host_lock); - if (time_after_eq(jiffies, timeout)) { - printk("scsi: arbitration timeout at %d\n", __LINE__); - NCR5380_write(MODE_REG, MR_BASE); - NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); - return -1; - } + if (err < 0) { + printk(KERN_DEBUG "scsi: arbitration timeout at %d\n", __LINE__); + NCR5380_write(MODE_REG, MR_BASE); + NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); + goto failed; } -#else /* NCR_TIMEOUT */ - while (!(NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS)); -#endif dprintk(NDEBUG_ARBITRATION, ("scsi%d : arbitration complete\n", instance->host_no)); @@ -1515,7 +1538,7 @@ if ((NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) || (NCR5380_read(CURRENT_SCSI_DATA_REG) & hostdata->id_higher_mask) || (NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST)) { NCR5380_write(MODE_REG, MR_BASE); dprintk(NDEBUG_ARBITRATION, ("scsi%d : lost arbitration, deasserting MR_ARBITRATE\n", instance->host_no)); - return -1; + goto failed; } NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_SEL); @@ -1528,7 +1551,7 @@ NCR5380_write(MODE_REG, MR_BASE); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); dprintk(NDEBUG_ARBITRATION, ("scsi%d : lost arbitration, deasserting ICR_ASSERT_SEL\n", instance->host_no)); - return -1; + goto failed; } /* * Again, bus clear + bus settle time is 1.2us, however, this is @@ -1613,8 +1636,7 @@ we poll only once ech clock tick */ value = NCR5380_read(STATUS_REG) & (SR_BSY | SR_IO); - /* FIXME HZ=100 assumption ? */ - if (!value && (hostdata->select_time < 25)) { + if (!value && (hostdata->select_time < HZ/4)) { /* RvC: we still must wait for a device response */ hostdata->select_time++; /* after 25 ticks the device has failed */ hostdata->time_expires = jiffies + 1; @@ -1627,6 +1649,8 @@ waiting period */ if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == (SR_SEL | SR_IO)) { NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); + if(instance->irq != IRQ_NONE) + spin_lock_irq(instance->host_lock); NCR5380_reselect(instance); printk("scsi%d : reselection after won arbitration?\n", instance->host_no); NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); @@ -1645,13 +1669,15 @@ if (!(NCR5380_read(STATUS_REG) & SR_BSY)) { NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); if (hostdata->targets_present & (1 << cmd->target)) { - printk("scsi%d : weirdness\n", instance->host_no); + printk(KERN_DEBUG "scsi%d : weirdness\n", instance->host_no); if (hostdata->restart_select) - printk("\trestart select\n"); + printk(KERN_DEBUG "\trestart select\n"); NCR5380_dprint(NDEBUG_SELECTION, instance); NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); return -1; } + if(instance->irq != IRQ_NONE) + spin_lock_irq(instance->host_lock); cmd->result = DID_BAD_TARGET << 16; collect_stats(hostdata, cmd); cmd->scsi_done(cmd); @@ -1678,29 +1704,21 @@ */ /* Wait for start of REQ/ACK handshake */ -#ifdef NCR_TIMEOUT - { - unsigned long timeout = jiffies + NCR_TIMEOUT; - - spin_unlock_irq(instance->host_lock); - while (!(NCR5380_read(STATUS_REG) & SR_REQ) && time_before(jiffies, timeout)) - cpu_relax(); - spin_lock_irq(instance->host_lock); - - if (time_after_eq(jiffies, timeout)) { - printk("scsi%d: timeout at NCR5380.c:%d\n", instance->host_no, __LINE__); - NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); - return -1; - } + + err = NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, HZ); + + if(err) + { printk(KERN_ERR "scsi%d: timeout at NCR5380.c:%d\n", instance->host_no, __LINE__); + NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); + goto failed; } -#else /* NCR_TIMEOUT */ - while (!(NCR5380_read(STATUS_REG) & SR_REQ)) - cpu_relax(); -#endif /* def NCR_TIMEOUT */ dprintk(NDEBUG_SELECTION, ("scsi%d : target %d selected, going into MESSAGE OUT phase.\n", instance->host_no, cmd->target)); tmp[0] = IDENTIFY(((instance->irq == IRQ_NONE) ? 0 : 1), cmd->lun); + if(instance->irq != IRQ_NONE) + spin_lock_irq(instance->host_lock); + len = 1; cmd->tag = 0; @@ -1717,6 +1735,13 @@ return 0; + + /* Selection failed */ +failed: + if(instance->irq != IRQ_NONE) + spin_lock_irq(instance->host_lock); + return -1; + } /* @@ -1786,6 +1811,7 @@ * if breaking is not allowed, we keep polling as long as needed */ + /* FIXME */ while (!((tmp = NCR5380_read(STATUS_REG)) & SR_REQ) && !break_allowed); if (!(tmp & SR_REQ)) { /* timeout condition */ @@ -1832,8 +1858,8 @@ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ACK); } - while (NCR5380_read(STATUS_REG) & SR_REQ); - + /* FIXME - if this fails bus reset ?? */ + NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, 0, 5*HZ); dprintk(NDEBUG_HANDSHAKE, ("scsi%d : req false, handshake complete\n", instance->host_no)); /* @@ -1905,8 +1931,9 @@ static int do_abort(struct Scsi_Host *host) { NCR5380_local_declare(); - unsigned char tmp, *msgptr, phase; + unsigned char *msgptr, phase, tmp; int len; + int rc; NCR5380_setup(host); @@ -1923,15 +1950,21 @@ * the target sees, so we just handshake. */ - while (!(tmp = NCR5380_read(STATUS_REG)) & SR_REQ) - cpu_relax(); + rc = NCR5380_poll_politely(host, STATUS_REG, SR_REQ, 0, 60 * HZ); + + if(rc < 0) + return -1; + tmp = (unsigned char)rc; + NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp)); if ((tmp & PHASE_MASK) != PHASE_MSGOUT) { NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN | ICR_ASSERT_ACK); - while (NCR5380_read(STATUS_REG) & SR_REQ); + rc = NCR5380_poll_politely(host, STATUS_REG, SR_REQ, 0, 3*HZ); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN); + if(rc == -1) + return -1; } tmp = ABORT; msgptr = &tmp; @@ -2245,7 +2278,7 @@ * XXX Note : we need to watch for bus free or a reset condition here * to recover from an unexpected bus free condition. * - * Locks: io_request_lock held by caller + * Locks: io_request_lock held by caller in IRQ mode */ static void NCR5380_information_transfer(struct Scsi_Host *instance) { @@ -2503,7 +2536,8 @@ /* Enable reselect interrupts */ NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); - /* Wait for bus free to avoid nasty timeouts */ + /* Wait for bus free to avoid nasty timeouts - FIXME timeout !*/ + /* NCR538_poll_politely(instance, STATUS_REG, SR_BSY, 0, 30 * HZ); */ while ((NCR5380_read(STATUS_REG) & SR_BSY) && !hostdata->connected) barrier(); return; @@ -2658,7 +2692,7 @@ * * Inputs : instance - this instance of the NCR5380. * - * Locks: io_request_lock held by caller + * Locks: io_request_lock held by caller if IRQ driven */ static void NCR5380_reselect(struct Scsi_Host *instance) { @@ -2696,16 +2730,19 @@ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_BSY); - while (NCR5380_read(STATUS_REG) & SR_SEL); + /* FIXME: timeout too long, must fail to workqueue */ + if(NCR5380_poll_politely(instance, STATUS_REG, SR_SEL, 0, 2*HZ)<0) + abort = 1; + NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); /* * Wait for target to go into MSGIN. - * FIXME: timeout needed + * FIXME: timeout needed and fail to work queeu */ - while (!(NCR5380_read(STATUS_REG) & SR_REQ)) - cpu_relax(); + if(NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, 2*HZ)) + abort = 1; len = 1; data = msg; @@ -2713,7 +2750,7 @@ NCR5380_transfer_pio(instance, &phase, &len, &data); if (!msg[0] & 0x80) { - printk("scsi%d : expecting IDENTIFY message, got ", instance->host_no); + printk(KERN_ERR "scsi%d : expecting IDENTIFY message, got ", instance->host_no); print_msg(msg); abort = 1; } else { @@ -2747,7 +2784,7 @@ break; } if (!tmp) { - printk("scsi%d : warning : target bitmask %02x lun %d not in disconnect_queue.\n", instance->host_no, target_mask, lun); + printk(KERN_ERR "scsi%d : warning : target bitmask %02x lun %d not in disconnect_queue.\n", instance->host_no, target_mask, lun); /* * Since we have an established nexus that we can't do anything with, * we must abort it. @@ -2790,9 +2827,11 @@ * * We should use the Last Byte Sent bit, unfortunately this is * not available on the 5380/5381 (only the various CMOS chips) + * + * FIXME: timeout, and need to handle long timeout/irq case */ - while (NCR5380_read(BUS_AND_STATUS_REG) & BASR_ACK); + NCR5380_poll_politely(instance, BUS_AND_STATUS_REG, BASR_ACK, 0, 5*HZ); NCR5380_write(MODE_REG, MR_BASE); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); @@ -2827,21 +2866,15 @@ * a problem, we could implement longjmp() / setjmp(), setjmp() * called where the loop started in NCR5380_main(). * - * Locks: host lock taken by function + * Locks: host lock taken by caller */ -#ifndef NCR5380_abort -static -#endif -int NCR5380_abort(Scsi_Cmnd * cmd) { +static int NCR5380_abort(Scsi_Cmnd * cmd) { NCR5380_local_declare(); struct Scsi_Host *instance = cmd->host; - unsigned long flags; struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata; Scsi_Cmnd *tmp, **prev; - spin_lock_irqsave(instance->host_lock, flags); - printk(KERN_WARNING "scsi%d : aborting command\n", instance->host_no); print_Scsi_Cmnd(cmd); @@ -2884,7 +2917,6 @@ * aborted flag and get back into our main loop. */ - spin_unlock_irqrestore(instance->host_lock, flags); return 0; } #endif @@ -2894,8 +2926,6 @@ * from the issue queue. */ - /* FIXME: check - I think we need the hostdata lock here */ - /* KLL */ dprintk(NDEBUG_ABORT, ("scsi%d : abort going into loop.\n", instance->host_no)); for (prev = (Scsi_Cmnd **) & (hostdata->issue_queue), tmp = (Scsi_Cmnd *) hostdata->issue_queue; tmp; prev = (Scsi_Cmnd **) & (tmp->host_scribble), tmp = (Scsi_Cmnd *) tmp->host_scribble) if (cmd == tmp) { @@ -2905,7 +2935,6 @@ tmp->result = DID_ABORT << 16; dprintk(NDEBUG_ABORT, ("scsi%d : abort removed command from issue queue.\n", instance->host_no)); tmp->done(tmp); - spin_unlock_irqrestore(instance->host_lock, flags); return SUCCESS; } #if (NDEBUG & NDEBUG_ABORT) @@ -2927,7 +2956,6 @@ if (hostdata->connected) { dprintk(NDEBUG_ABORT, ("scsi%d : abort failed, command connected.\n", instance->host_no)); - spin_unlock_irqrestore(instance->host_lock, flags); return FAILED; } /* @@ -2972,7 +3000,6 @@ tmp->host_scribble = NULL; tmp->result = DID_ABORT << 16; tmp->done(tmp); - spin_unlock_irqrestore(instance->host_lock, flags); return SUCCESS; } } @@ -2985,7 +3012,6 @@ * so we won't panic, but we will notify the user in case something really * broke. */ - spin_unlock_irqrestore(instance->host_lock, flags); printk(KERN_WARNING "scsi%d : warning : SCSI command probably completed successfully\n" " before abortion\n", instance->host_no); return FAILED; @@ -2999,22 +3025,15 @@ * * Returns : SUCCESS * - * Locks: host lock taken by function + * Locks: host lock taken by caller */ -#ifndef NCR5380_bus_reset -static -#endif -int NCR5380_bus_reset(Scsi_Cmnd * cmd) { - unsigned long flags; - struct Scsi_Host *instance = cmd->host; +static int NCR5380_bus_reset(Scsi_Cmnd * cmd) { NCR5380_local_declare(); NCR5380_setup(cmd->host); - spin_lock_irqsave(instance->host_lock, flags); NCR5380_print_status(cmd->host); do_reset(cmd->host); - spin_unlock_irqrestore(instance->host_lock, flags); return SUCCESS; } @@ -3028,12 +3047,7 @@ * Locks: io_request_lock held by caller */ -#ifndef NCR5380_device_reset -static -#endif -int NCR5380_device_reset(Scsi_Cmnd * cmd) { - NCR5380_local_declare(); - NCR5380_setup(cmd->host); +static int NCR5380_device_reset(Scsi_Cmnd * cmd) { return FAILED; } @@ -3047,11 +3061,6 @@ * Locks: io_request_lock held by caller */ -#ifndef NCR5380_host_reset -static -#endif -int NCR5380_host_reset(Scsi_Cmnd * cmd) { - NCR5380_local_declare(); - NCR5380_setup(cmd->host); +static int NCR5380_host_reset(Scsi_Cmnd * cmd) { return FAILED; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/scsi/NCR53c406a.c linux.2.5.45-ac1/drivers/scsi/NCR53c406a.c --- linux.2.5.45/drivers/scsi/NCR53c406a.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.45-ac1/drivers/scsi/NCR53c406a.c 2002-11-03 00:23:29.000000000 +0000 @@ -677,22 +677,6 @@ NCR53c406a_intr(0, NULL, NULL); } -static int NCR53c406a_command(Scsi_Cmnd * SCpnt) -{ - DEB(printk("NCR53c406a_command called\n")); - NCR53c406a_queue(SCpnt, internal_done); - if (irq_level) - while (!internal_done_flag) - cpu_relax(); - else /* interrupts not supported */ - while (!internal_done_flag) - wait_intr(); - - internal_done_flag = 0; - return internal_done_errcode; -} - - static int NCR53c406a_queue(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *)) { int i; @@ -726,6 +710,21 @@ return 0; } +static int NCR53c406a_command(Scsi_Cmnd * SCpnt) +{ + DEB(printk("NCR53c406a_command called\n")); + NCR53c406a_queue(SCpnt, internal_done); + if (irq_level) + while (!internal_done_flag) + cpu_relax(); + else /* interrupts not supported */ + while (!internal_done_flag) + wait_intr(); + + internal_done_flag = 0; + return internal_done_errcode; +} + static int NCR53c406a_abort(Scsi_Cmnd * SCpnt) { DEB(printk("NCR53c406a_abort called\n")); @@ -755,7 +754,7 @@ return FAILED; } -static int NCR53c406a_biosparm(struct scsi_disk *disk, +static int NCR53c406a_biosparm(struct scsi_device *disk, struct block_device *dev, sector_t capacity, int *info_array) { @@ -1065,8 +1064,30 @@ MODULE_LICENSE("GPL"); -/* Eventually this will go into an include file, but this will be later */ -static Scsi_Host_Template driver_template = NCR53c406a; +/* NOTE: scatter-gather support only works in PIO mode. + * Use SG_NONE if DMA mode is enabled! + */ + +static Scsi_Host_Template driver_template = +{ + proc_name: "NCR53c406a" /* proc_name */, + name: "NCR53c406a" /* name */, + detect: NCR53c406a_detect /* detect */, + info: NCR53c406a_info /* info */, + command: NCR53c406a_command /* command */, + queuecommand: NCR53c406a_queue /* queuecommand */, + eh_abort_handler: NCR53c406a_abort /* abort */, + eh_bus_reset_handler: NCR53c406a_bus_reset /* reset */, + eh_device_reset_handler: NCR53c406a_device_reset /* reset */, + eh_host_reset_handler: NCR53c406a_host_reset /* reset */, + bios_param: NCR53c406a_biosparm /* biosparm */, + can_queue: 1 /* can_queue */, + this_id: 7 /* SCSI ID of the chip */, + sg_tablesize: 32 /*SG_ALL*/ /*SG_NONE*/, + cmd_per_lun: 1 /* commands per lun */, + unchecked_isa_dma: 1 /* unchecked_isa_dma */, + use_clustering: ENABLE_CLUSTERING +}; #include "scsi_module.c" diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/scsi/NCR53c406a.h linux.2.5.45-ac1/drivers/scsi/NCR53c406a.h --- linux.2.5.45/drivers/scsi/NCR53c406a.h 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.45-ac1/drivers/scsi/NCR53c406a.h 2002-11-03 00:21:20.000000000 +0000 @@ -1,58 +0,0 @@ -#ifndef _NCR53C406A_H -#define _NCR53C406A_H - -/* - * NCR53c406a.h - * - * Copyright (C) 1994 Normunds Saumanis (normunds@rx.tech.swh.lv) - * - * 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. - * - */ - -#ifndef NULL -#define NULL 0 -#endif - -/* NOTE: scatter-gather support only works in PIO mode. - * Use SG_NONE if DMA mode is enabled! - */ -#define NCR53c406a { \ - proc_name: "NCR53c406a" /* proc_name */, \ - name: "NCR53c406a" /* name */, \ - detect: NCR53c406a_detect /* detect */, \ - info: NCR53c406a_info /* info */, \ - command: NCR53c406a_command /* command */, \ - queuecommand: NCR53c406a_queue /* queuecommand */, \ - eh_abort_handler: NCR53c406a_abort /* abort */, \ - eh_bus_reset_handler: NCR53c406a_bus_reset /* reset */, \ - eh_device_reset_handler: NCR53c406a_device_reset /* reset */, \ - eh_host_reset_handler: NCR53c406a_host_reset /* reset */, \ - bios_param: NCR53c406a_biosparm /* biosparm */, \ - can_queue: 1 /* can_queue */, \ - this_id: 7 /* SCSI ID of the chip */, \ - sg_tablesize: 32 /*SG_ALL*/ /*SG_NONE*/, \ - cmd_per_lun: 1 /* commands per lun */, \ - unchecked_isa_dma: 1 /* unchecked_isa_dma */, \ - use_clustering: ENABLE_CLUSTERING \ -} - -static int NCR53c406a_detect(Scsi_Host_Template *); -static const char *NCR53c406a_info(struct Scsi_Host *); -static int NCR53c406a_command(Scsi_Cmnd *); -static int NCR53c406a_queue(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *)); -static int NCR53c406a_abort(Scsi_Cmnd *); -static int NCR53c406a_bus_reset(Scsi_Cmnd *); -static int NCR53c406a_device_reset(Scsi_Cmnd *); -static int NCR53c406a_host_reset(Scsi_Cmnd *); -static int NCR53c406a_biosparm(Disk *, struct block_device *, sector_t, int[]); - -#endif /* _NCR53C406A_H */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/scsi/ncr53c8xx.h linux.2.5.45-ac1/drivers/scsi/ncr53c8xx.h --- linux.2.5.45/drivers/scsi/ncr53c8xx.h 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.45-ac1/drivers/scsi/ncr53c8xx.h 2002-11-01 14:57:21.000000000 +0000 @@ -76,6 +76,8 @@ info: ncr53c8xx_info, \ queuecommand: ncr53c8xx_queue_command,\ slave_attach: ncr53c8xx_slave_attach, \ + abort: ncr53c8xx_abort, \ + reset: ncr53c8xx_reset, \ can_queue: SCSI_NCR_CAN_QUEUE, \ this_id: 7, \ sg_tablesize: SCSI_NCR_SG_TABLESIZE, \ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/scsi/pcmcia/aha152x.c linux.2.5.45-ac1/drivers/scsi/pcmcia/aha152x.c --- linux.2.5.45/drivers/scsi/pcmcia/aha152x.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/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.45/drivers/scsi/pcmcia/fdomain_stub.c linux.2.5.45-ac1/drivers/scsi/pcmcia/fdomain_stub.c --- linux.2.5.45/drivers/scsi/pcmcia/fdomain_stub.c 2002-10-31 14:57:12.000000000 +0000 +++ linux.2.5.45-ac1/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.45/drivers/scsi/pcmcia/Makefile linux.2.5.45-ac1/drivers/scsi/pcmcia/Makefile --- linux.2.5.45/drivers/scsi/pcmcia/Makefile 2002-10-31 14:57:12.000000000 +0000 +++ linux.2.5.45-ac1/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.45/drivers/scsi/pcmcia/nsp_cs.c linux.2.5.45-ac1/drivers/scsi/pcmcia/nsp_cs.c --- linux.2.5.45/drivers/scsi/pcmcia/nsp_cs.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.45-ac1/drivers/scsi/pcmcia/nsp_cs.c 2002-11-03 01:33:26.000000000 +0000 @@ -147,8 +147,6 @@ /* .eh_device_reset_handler = nsp_eh_device_reset,*/ .eh_bus_reset_handler = nsp_eh_bus_reset, .eh_host_reset_handler = nsp_eh_host_reset, - .abort = nsp_abort, - .reset = nsp_reset, /* .slave_attach = NULL,*/ /* .bios_param = NULL,*/ .can_queue = 1, @@ -1393,45 +1391,6 @@ } #undef SPRINTF -/*---------------------------------------------------------------*/ -/* error handler */ -/*---------------------------------------------------------------*/ -static int nsp_reset(Scsi_Cmnd *SCpnt, unsigned int reset_flags) -{ - nsp_hw_data *data = &nsp_data; - int ret = 0; - - DEBUG(0, "%s: SCpnt=0x%p why=%d\n", __FUNCTION__, SCpnt, reset_flags); - - if (reset_flags & SCSI_RESET_SUGGEST_BUS_RESET) { - nsp_eh_bus_reset(SCpnt); - - ret |= SCSI_RESET_BUS_RESET; - } - - if (reset_flags & SCSI_RESET_SUGGEST_HOST_RESET) { - nsp_eh_host_reset(SCpnt); - - ret |= SCSI_RESET_HOST_RESET; - } - - if (ret != 0) { - return SCSI_RESET_SUCCESS | ret; - } else { - nsphw_init_sync(data); - return SCSI_RESET_PUNT; - } -} - -static int nsp_abort(Scsi_Cmnd *SCpnt) -{ - DEBUG(0, "%s: SCpnt=0x%p\n", __FUNCTION__, SCpnt); - - nsp_eh_host_reset(SCpnt); - nsp_eh_bus_reset(SCpnt); - - return SCSI_ABORT_SUCCESS; -} /*static int nsp_eh_strategy(struct Scsi_Host *Shost) { diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/scsi/pcmcia/nsp_cs.h linux.2.5.45-ac1/drivers/scsi/pcmcia/nsp_cs.h --- linux.2.5.45/drivers/scsi/pcmcia/nsp_cs.h 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.45-ac1/drivers/scsi/pcmcia/nsp_cs.h 2002-11-03 01:33:50.000000000 +0000 @@ -285,8 +285,6 @@ int length, int hostno, int inout); static int nsp_queuecommand(Scsi_Cmnd *, void (* done)(Scsi_Cmnd *)); -static int nsp_abort(Scsi_Cmnd *); -static int nsp_reset(Scsi_Cmnd *, unsigned int); /*static int nsp_eh_abort(Scsi_Cmnd * SCpnt);*/ /*static int nsp_eh_device_reset(Scsi_Cmnd *SCpnt);*/ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/scsi/pcmcia/qlogicfas.c linux.2.5.45-ac1/drivers/scsi/pcmcia/qlogicfas.c --- linux.2.5.45/drivers/scsi/pcmcia/qlogicfas.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/drivers/scsi/pcmcia/qlogicfas.c 2002-11-03 01:32:09.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.45/drivers/scsi/pcmcia/qlogic_stub.c linux.2.5.45-ac1/drivers/scsi/pcmcia/qlogic_stub.c --- linux.2.5.45/drivers/scsi/pcmcia/qlogic_stub.c 2002-10-31 14:57:12.000000000 +0000 +++ linux.2.5.45-ac1/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.45/drivers/scsi/ppa.c linux.2.5.45-ac1/drivers/scsi/ppa.c --- linux.2.5.45/drivers/scsi/ppa.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.45-ac1/drivers/scsi/ppa.c 2002-11-03 01:30:56.000000000 +0000 @@ -697,7 +697,7 @@ ppa_fail(host_no, DID_ERROR); return -1; /* ERROR_RETURN */ } - + /* On some hardware we have SCSI disconnected (6th bit low) * for about 100usecs. It is too expensive to wait a * tick on every loop so we busy wait for no more than diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/scsi/qla1280.h linux.2.5.45-ac1/drivers/scsi/qla1280.h --- linux.2.5.45/drivers/scsi/qla1280.h 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.45-ac1/drivers/scsi/qla1280.h 2002-10-31 19:21:41.000000000 +0000 @@ -1331,6 +1331,9 @@ release: qla1280_release, \ info: qla1280_info, \ queuecommand: qla1280_queuecommand, \ +/* use_new_eh_code: 0, */ \ + abort: qla1280_abort, \ + reset: qla1280_reset, \ slave_attach: qla1280_slave_attach, \ bios_param: qla1280_biosparam, \ can_queue: 255, /* max simultaneous cmds */\ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/scsi/qlogicfas.c linux.2.5.45-ac1/drivers/scsi/qlogicfas.c --- linux.2.5.45/drivers/scsi/qlogicfas.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.45-ac1/drivers/scsi/qlogicfas.c 2002-11-03 01:31:56.000000000 +0000 @@ -613,7 +613,7 @@ #ifdef PCMCIA /* - * Allow PCMCIA code to preset the port */ + * Allow PCMCIA code to preset the port * port should be 0 and irq to -1 respectively for autoprobing */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/scsi/README.nsp_cs linux.2.5.45-ac1/drivers/scsi/README.nsp_cs --- linux.2.5.45/drivers/scsi/README.nsp_cs 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/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.45/drivers/scsi/sim710.c linux.2.5.45-ac1/drivers/scsi/sim710.c --- linux.2.5.45/drivers/scsi/sim710.c 2002-10-31 14:57:12.000000000 +0000 +++ linux.2.5.45-ac1/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.45/drivers/scsi/sim710_d.h linux.2.5.45-ac1/drivers/scsi/sim710_d.h --- linux.2.5.45/drivers/scsi/sim710_d.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/drivers/scsi/sim710_d.h 2002-10-31 15:05:34.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.45/drivers/scsi/sym53c8xx.h linux.2.5.45-ac1/drivers/scsi/sym53c8xx.h --- linux.2.5.45/drivers/scsi/sym53c8xx.h 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.45-ac1/drivers/scsi/sym53c8xx.h 2002-11-01 11:48:52.000000000 +0000 @@ -91,6 +91,8 @@ info: sym53c8xx_info, \ queuecommand: sym53c8xx_queue_command,\ slave_attach: sym53c8xx_slave_attach, \ + abort: sym53c8xx_abort, \ + reset: sym53c8xx_reset, \ can_queue: SCSI_NCR_CAN_QUEUE, \ this_id: 7, \ sg_tablesize: SCSI_NCR_SG_TABLESIZE, \ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/scsi/u14-34f.c linux.2.5.45-ac1/drivers/scsi/u14-34f.c --- linux.2.5.45/drivers/scsi/u14-34f.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.45-ac1/drivers/scsi/u14-34f.c 2002-11-03 00:28:26.000000000 +0000 @@ -1,6 +1,15 @@ /* * u14-34f.c - Low-level driver for UltraStor 14F/34F SCSI host adapters. * + * 28 Oct 2002 Rev. 8.00 for linux 2.5.44-ac4 + * + Use new tcq and adjust_queue_depth api. + * + New command line option (tm:[0-2]) to choose the type of tags: + * 0 -> disable tagging ; 1 -> simple tags ; 2 -> ordered tags. + * Default is tm:0 (tagged commands disabled). + * For compatibility the "tc:" option is an alias of the "tm:" + * option; tc:n is equivalent to tm:0 and tc:y is equivalent to + * tm:1. + * * 10 Oct 2002 Rev. 7.70 for linux 2.5.42 * + Foreport from revision 6.70. * @@ -304,19 +313,22 @@ * et:n use disk geometry jumpered on the board; * lc:y enables linked commands; * lc:n disables linked commands; + * tm:0 disables tagged commands (same as tc:n); + * tm:1 use simple queue tags (same as tc:y); + * tm:2 use ordered queue tags (same as tc:2); * of:y enables old firmware support; * of:n disables old firmware support; * mq:xx set the max queue depth to the value xx (2 <= xx <= 8). * - * The default value is: "u14-34f=lc:n,of:n,mq:8,et:n". + * The default value is: "u14-34f=lc:n,of:n,mq:8,tm:0,et:n". * An example using the list of detection probes could be: - * "u14-34f=0x230,0x340,lc:y,of:n,mq:4,et:n". + * "u14-34f=0x230,0x340,lc:y,tm:2,of:n,mq:4,et:n". * * When loading as a module, parameters can be specified as well. * The above example would be (use 1 in place of y and 0 in place of n): * * modprobe u14-34f io_port=0x230,0x340 linked_comm=1 have_old_firmware=0 \ - * max_queue_depth=4 ext_tran=0 + * max_queue_depth=4 ext_tran=0 tag_mode=2 * * ---------------------------------------------------------------------------- * In this implementation, linked commands are designed to work with any DISK @@ -374,6 +386,7 @@ MODULE_PARM(have_old_firmware, "i"); MODULE_PARM(link_statistics, "i"); MODULE_PARM(max_queue_depth, "i"); +MODULE_PARM(tag_mode, "i"); MODULE_PARM(ext_tran, "i"); MODULE_AUTHOR("Dario Ballabio"); @@ -400,6 +413,7 @@ #include #include #include +#include #if !defined(__BIG_ENDIAN_BITFIELD) && !defined(__LITTLE_ENDIAN_BITFIELD) #error "Adjust your defines" @@ -460,6 +474,9 @@ #define ABORTING 6 #define NO_DMA 0xff #define MAXLOOP 10000 +#define TAG_DISABLED 0 +#define TAG_SIMPLE 1 +#define TAG_ORDERED 2 #define REG_LCL_MASK 0 #define REG_LCL_INTR 1 @@ -593,6 +610,12 @@ static int have_old_firmware = FALSE; #endif +#if defined(CONFIG_SCSI_U14_34F_TAGGED_QUEUE) +static int tag_mode = TAG_SIMPLE; +#else +static int tag_mode = TAG_DISABLED; +#endif + #if defined(CONFIG_SCSI_U14_34F_LINKED_COMMANDS) static int linked_comm = TRUE; #else @@ -605,61 +628,56 @@ static int max_queue_depth = MAX_CMD_PER_LUN; #endif -static void select_queue_depths(struct Scsi_Host *host, Scsi_Device *devlist) { - Scsi_Device *dev; - int j, ntag = 0, nuntag = 0, tqd, utqd; +static int u14_34f_slave_attach(Scsi_Device *dev) { + int j, tqd, utqd; + char *tag_suffix, *link_suffix; + struct Scsi_Host *host = dev->host; j = ((struct hostdata *) host->hostdata)->board_number; - for(dev = devlist; dev; dev = dev->next) { - - if (dev->host != host) continue; - - if (TLDEV(dev->type) && (dev->tagged_supported || linked_comm)) - ntag++; - else - nuntag++; - } - utqd = MAX_CMD_PER_LUN; + tqd = max_queue_depth; - tqd = (host->can_queue - utqd * nuntag) / (ntag ? ntag : 1); + if (TLDEV(dev->type) && dev->tagged_supported) - if (tqd > max_queue_depth) tqd = max_queue_depth; - - if (tqd < MAX_CMD_PER_LUN) tqd = MAX_CMD_PER_LUN; - - for(dev = devlist; dev; dev = dev->next) { - char *tag_suffix = "", *link_suffix = ""; - - if (dev->host != host) continue; - - if (TLDEV(dev->type) && (dev->tagged_supported || linked_comm)) - dev->queue_depth = tqd; - else - dev->queue_depth = utqd; - - if (TLDEV(dev->type)) { - if (linked_comm && dev->queue_depth > 2) - link_suffix = ", sorted"; - else - link_suffix = ", unsorted"; + if (tag_mode == TAG_SIMPLE) { + scsi_adjust_queue_depth(dev, MSG_SIMPLE_TAG, tqd); + tag_suffix = ", simple tags"; + } + else if (tag_mode == TAG_ORDERED) { + scsi_adjust_queue_depth(dev, MSG_ORDERED_TAG, tqd); + tag_suffix = ", ordered tags"; + } + else { + scsi_adjust_queue_depth(dev, 0, tqd); + tag_suffix = ", no tags"; } - if (dev->tagged_supported && TLDEV(dev->type) && dev->tagged_queue) - tag_suffix = ", soft-tagged"; - else if (dev->tagged_supported && TLDEV(dev->type)) - tag_suffix = ", tagged"; - - printk("%s: scsi%d, channel %d, id %d, lun %d, cmds/lun %d%s%s.\n", - BN(j), host->host_no, dev->channel, dev->id, dev->lun, - dev->queue_depth, link_suffix, tag_suffix); + else if (TLDEV(dev->type) && linked_comm) { + scsi_adjust_queue_depth(dev, 0, tqd); + tag_suffix = ", untagged"; } - return; + else { + scsi_adjust_queue_depth(dev, 0, utqd); + tag_suffix = ""; + } + + if (TLDEV(dev->type) && linked_comm && dev->new_queue_depth > 2) + link_suffix = ", sorted"; + else if (TLDEV(dev->type)) + link_suffix = ", unsorted"; + else + link_suffix = ""; + + printk("%s: scsi%d, channel %d, id %d, lun %d, cmds/lun %d%s%s.\n", + BN(j), host->host_no, dev->channel, dev->id, dev->lun, + dev->new_queue_depth, link_suffix, tag_suffix); + + return FALSE; } -static inline int wait_on_busy(unsigned long iobase, unsigned int loop) { +static int wait_on_busy(unsigned long iobase, unsigned int loop) { while (inb(iobase + REG_LCL_INTR) & BSY_ASSERTED) { udelay(1L); @@ -721,7 +739,7 @@ return FALSE; } -static inline int port_detect \ +static int port_detect \ (unsigned long port_base, unsigned int j, Scsi_Host_Template *tpnt) { unsigned char irq, dma_channel, subversion, i; unsigned char in_byte; @@ -843,7 +861,6 @@ sh[j]->this_id = config_2.ha_scsi_id; sh[j]->can_queue = MAX_MAILBOXES; sh[j]->cmd_per_lun = MAX_CMD_PER_LUN; - sh[j]->select_queue_depths = select_queue_depths; #if defined(DEBUG_DETECT) { @@ -930,11 +947,14 @@ if (max_queue_depth < MAX_CMD_PER_LUN) max_queue_depth = MAX_CMD_PER_LUN; + if (tag_mode != TAG_DISABLED && tag_mode != TAG_SIMPLE) + tag_mode = TAG_ORDERED; + if (j == 0) { printk("UltraStor 14F/34F: Copyright (C) 1994-2002 Dario Ballabio.\n"); - printk("%s config options -> of:%c, lc:%c, mq:%d, et:%c.\n", - driver_name, YESNO(have_old_firmware), YESNO(linked_comm), - max_queue_depth, YESNO(ext_tran)); + printk("%s config options -> of:%c, tm:%d, lc:%c, mq:%d, et:%c.\n", + driver_name, YESNO(have_old_firmware), tag_mode, + YESNO(linked_comm), max_queue_depth, YESNO(ext_tran)); } printk("%s: %s 0x%03lx, BIOS 0x%05x, IRQ %u, %s, SG %d, MB %d.\n", @@ -975,6 +995,8 @@ if (!strncmp(cur, "lc:", 3)) linked_comm = val; else if (!strncmp(cur, "of:", 3)) have_old_firmware = val; + else if (!strncmp(cur, "tm:", 3)) tag_mode = val; + else if (!strncmp(cur, "tc:", 3)) tag_mode = val; else if (!strncmp(cur, "mq:", 3)) max_queue_depth = val; else if (!strncmp(cur, "ls:", 3)) link_statistics = val; else if (!strncmp(cur, "et:", 3)) ext_tran = val; @@ -1001,7 +1023,7 @@ return 1; } -int u14_34f_detect(Scsi_Host_Template *tpnt) { +static int u14_34f_detect(Scsi_Host_Template *tpnt) { unsigned int j = 0, k; unsigned long spin_flags; @@ -1033,7 +1055,7 @@ return j; } -static inline void map_dma(unsigned int i, unsigned int j) { +static void map_dma(unsigned int i, unsigned int j) { unsigned int data_len = 0; unsigned int k, count, pci_dir; struct scatterlist *sgpnt; @@ -1123,7 +1145,7 @@ DEV2H(cpp->data_len), pci_dir); } -static inline void scsi_to_dev_dir(unsigned int i, unsigned int j) { +static void scsi_to_dev_dir(unsigned int i, unsigned int j) { unsigned int k; static const unsigned char data_out_cmds[] = { @@ -1176,7 +1198,7 @@ } -static inline int do_qcomm(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { +static int u14_34f_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { unsigned int i, j, k; struct mscp *cpp; @@ -1232,7 +1254,7 @@ /* Map DMA buffers and SG list */ map_dma(i, j); - if (linked_comm && SCpnt->device->queue_depth > 2 + if (linked_comm && SCpnt->device->new_queue_depth > 2 && TLDEV(SCpnt->device->type)) { HD(j)->cp_stat[i] = READY; flush_dev(SCpnt->device, SCpnt->request->sector, j, FALSE); @@ -1257,14 +1279,7 @@ return 0; } -int u14_34f_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { - int rtn; - - rtn = do_qcomm(SCpnt, done); - return rtn; -} - -static inline int do_abort(Scsi_Cmnd *SCarg) { +static int u14_34f_eh_abort(Scsi_Cmnd *SCarg) { unsigned int i, j; j = ((struct hostdata *) SCarg->host->hostdata)->board_number; @@ -1338,12 +1353,7 @@ panic("%s: abort, mbox %d, invalid cp_stat.\n", BN(j), i); } -int u14_34f_abort(Scsi_Cmnd *SCarg) { - - return do_abort(SCarg); -} - -static inline int do_reset(Scsi_Cmnd *SCarg) { +static int u14_34f_eh_host_reset(Scsi_Cmnd *SCarg) { unsigned int i, j, time, k, c, limit = 0; int arg_done = FALSE; Scsi_Cmnd *SCpnt; @@ -1476,15 +1486,10 @@ return SUCCESS; } -int u14_34f_reset(Scsi_Cmnd *SCarg) { - - return do_reset(SCarg); -} - -int u14_34f_biosparam(struct scsi_device *sdev, struct block_device *bdev, - sector_t capacity, int *dkinfo) { +static int u14_34f_bios_param(struct scsi_device *disk, struct block_device *bdev, + sector_t capacity, int *dkinfo) { unsigned int j = 0; - int size = capacity; + unsigned int size = capacity; dkinfo[0] = HD(j)->heads; dkinfo[1] = HD(j)->sectors; @@ -1497,7 +1502,7 @@ } #if defined (DEBUG_GEOMETRY) - printk ("%s: biosparam, head=%d, sec=%d, cyl=%d.\n", driver_name, + printk ("%s: bios_param, head=%d, sec=%d, cyl=%d.\n", driver_name, dkinfo[0], dkinfo[1], dkinfo[2]); #endif @@ -1529,7 +1534,7 @@ return; } -static inline int reorder(unsigned int j, unsigned long cursec, +static int reorder(unsigned int j, unsigned long cursec, unsigned int ihdlr, unsigned int il[], unsigned int n_ready) { Scsi_Cmnd *SCpnt; struct mscp *cpp; @@ -1666,7 +1671,7 @@ } -static inline void ihdlr(int irq, unsigned int j) { +static void ihdlr(int irq, unsigned int j) { Scsi_Cmnd *SCpnt; unsigned int i, k, c, status, tstatus, reg, ret; struct mscp *spp, *cpp; @@ -1746,7 +1751,7 @@ sync_dma(i, j); - if (linked_comm && SCpnt->device->queue_depth > 2 + if (linked_comm && SCpnt->device->new_queue_depth > 2 && TLDEV(SCpnt->device->type)) flush_dev(SCpnt->device, SCpnt->request->sector, j, TRUE); @@ -1888,7 +1893,7 @@ spin_unlock_irqrestore(sh[j]->host_lock, spin_flags); } -int u14_34f_release(struct Scsi_Host *shpnt) { +static int u14_34f_release(struct Scsi_Host *shpnt) { unsigned int i, j; for (j = 0; sh[j] != NULL && sh[j] != shpnt; j++); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/scsi/u14-34f.h linux.2.5.45-ac1/drivers/scsi/u14-34f.h --- linux.2.5.45/drivers/scsi/u14-34f.h 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.45-ac1/drivers/scsi/u14-34f.h 2002-11-03 00:27:27.000000000 +0000 @@ -1,36 +1,29 @@ /* * u14-34f.h - used by the low-level driver for UltraStor 14F/34F */ -#ifndef _U14_34F_H -#define _U14_34F_H -#include +static int u14_34f_detect(Scsi_Host_Template *); +static int u14_34f_release(struct Scsi_Host *); +static int u14_34f_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); +static int u14_34f_eh_abort(Scsi_Cmnd *); +static int u14_34f_eh_host_reset(Scsi_Cmnd *); +static int u14_34f_bios_param(struct scsi_device *, struct block_device *, sector_t, int *); +static int u14_34f_slave_attach(Scsi_Device *); -int u14_34f_detect(Scsi_Host_Template *); -int u14_34f_release(struct Scsi_Host *); -int u14_34f_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); -int u14_34f_abort(Scsi_Cmnd *); -int u14_34f_reset(Scsi_Cmnd *); -int u14_34f_biosparam(struct scsi_device *, struct block_device *, - sector_t, int *); - -#define U14_34F_VERSION "7.70.00" +#define U14_34F_VERSION "8.00.00" #define ULTRASTOR_14_34F { \ name: "UltraStor 14F/34F rev. " U14_34F_VERSION " ", \ detect: u14_34f_detect, \ release: u14_34f_release, \ queuecommand: u14_34f_queuecommand, \ - abort: NULL, \ - reset: NULL, \ - eh_abort_handler: u14_34f_abort, \ + eh_abort_handler: u14_34f_eh_abort, \ eh_device_reset_handler: NULL, \ eh_bus_reset_handler: NULL, \ - eh_host_reset_handler: u14_34f_reset, \ - bios_param: u14_34f_biosparam, \ + eh_host_reset_handler: u14_34f_eh_host_reset, \ + bios_param: u14_34f_bios_param, \ + slave_attach: u14_34f_slave_attach, \ this_id: 7, \ unchecked_isa_dma: 1, \ - use_clustering: ENABLE_CLUSTERING, \ + use_clustering: ENABLE_CLUSTERING \ } - -#endif diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/scsi/ultrastor.c linux.2.5.45-ac1/drivers/scsi/ultrastor.c --- linux.2.5.45/drivers/scsi/ultrastor.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.45-ac1/drivers/scsi/ultrastor.c 2002-11-02 23:13:13.000000000 +0000 @@ -8,6 +8,9 @@ * John's work modified by Caleb Epstein (cae@jpmorgan.com) and * Eric Youngdale (ericy@cais.com). * Thanks to UltraStor for providing the necessary documentation + * + * This is an old driver, for the 14F and 34F you should be using the + * u14-34f driver instead. */ /* @@ -164,8 +167,8 @@ packed structure. */ typedef struct { - unsigned int address; - unsigned int num_bytes; + u32 address; + u32 num_bytes; } ultrastor_sg_list; @@ -190,7 +193,7 @@ unsigned char scsi_cdbs[12]; /* SCSI commands */ unsigned char adapter_status; /* non-zero indicates HA error */ unsigned char target_status; /* non-zero indicates target error */ - unsigned int sense_data PACKED; + u32 sense_data PACKED; /* The following fields are for software only. They are included in the MSCP structure because they are associated with SCSI requests. */ void (*done)(Scsi_Cmnd *); @@ -289,17 +292,15 @@ static inline void build_sg_list(struct mscp *, Scsi_Cmnd *SCpnt); +/* Always called with host lock held */ + static inline int find_and_clear_bit_16(unsigned short *field) { int rv; - unsigned long flags; - save_flags(flags); - cli(); if (*field == 0) panic("No free mscp"); asm("xorl %0,%0\n0:\tbsfw %1,%w0\n\tbtr %0,%1\n\tjnc 0b" : "=&r" (rv), "=m" (*field) : "1" (*field)); - restore_flags(flags); return rv; } @@ -320,14 +321,12 @@ #if ULTRASTOR_DEBUG & (UD_COMMAND | UD_ABORT) -static void log_ultrastor_abort(register struct ultrastor_config *config, +/* Always called with the host lock held */ +static void log_ultrastor_abort(struct ultrastor_config *config, int command) { static char fmt[80] = "abort %d (%x); MSCP free pool: %x;"; - register int i; - unsigned long flags; - save_flags(flags); - cli(); + int i; for (i = 0; i < ULTRASTOR_MAX_CMDS; i++) { @@ -340,7 +339,7 @@ fmt[20 + ULTRASTOR_MAX_CMDS * 2] = '\n'; fmt[21 + ULTRASTOR_MAX_CMDS * 2] = 0; printk(fmt, command, &config->mscp[command], config->mscp_free); - restore_flags(flags); + } #endif @@ -528,7 +527,7 @@ static int ultrastor_24f_detect(Scsi_Host_Template * tpnt) { - register int i; + int i; struct Scsi_Host * shpnt = NULL; #if (ULTRASTOR_DEBUG & UD_DETECT) @@ -638,13 +637,13 @@ return FALSE; } -int ultrastor_detect(Scsi_Host_Template * tpnt) +static int ultrastor_detect(Scsi_Host_Template * tpnt) { - tpnt->proc_name = "ultrastor"; - return ultrastor_14f_detect(tpnt) || ultrastor_24f_detect(tpnt); + tpnt->proc_name = "ultrastor"; + return ultrastor_14f_detect(tpnt) || ultrastor_24f_detect(tpnt); } -const char *ultrastor_info(struct Scsi_Host * shpnt) +static const char *ultrastor_info(struct Scsi_Host * shpnt) { static char buf[64]; @@ -662,7 +661,7 @@ return buf; } -static inline void build_sg_list(register struct mscp *mscp, Scsi_Cmnd *SCpnt) +static inline void build_sg_list(struct mscp *mscp, Scsi_Cmnd *SCpnt) { struct scatterlist *sl; long transfer_length = 0; @@ -683,14 +682,13 @@ mscp->transfer_data_length = transfer_length; } -int ultrastor_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) +static int ultrastor_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { - register struct mscp *my_mscp; + struct mscp *my_mscp; #if ULTRASTOR_MAX_CMDS > 1 int mscp_index; #endif unsigned int status; - unsigned long flags; /* Next test is for debugging; "can't happen" */ if ((config.mscp_free & ((1U << ULTRASTOR_MAX_CMDS) - 1)) == 0) @@ -706,14 +704,8 @@ my_mscp = &config.mscp[mscp_index]; -#if 1 - /* This way is faster. */ *(unsigned char *)my_mscp = OP_SCSI | (DTD_SCSI << 3); -#else - my_mscp->opcode = OP_SCSI; - my_mscp->xdir = DTD_SCSI; - my_mscp->dcn = FALSE; -#endif + /* Tape drives don't work properly if the cache is used. The SCSI READ command for a tape doesn't have a block offset, and the adapter incorrectly assumes that all reads from the tape read the same @@ -748,35 +740,31 @@ SCpnt->host_scribble = (unsigned char *)my_mscp; /* Find free OGM slot. On 24F, look for OGM status byte == 0. - On 14F and 34F, wait for local interrupt pending flag to clear. */ + On 14F and 34F, wait for local interrupt pending flag to clear. + + FIXME: now we are using new_eh we should punt here and let the + midlayer sort it out */ - retry: +retry: if (config.slot) - while (inb(config.ogm_address - 1) != 0 && - config.aborted[mscp_index] == 0xff) barrier(); + while (inb(config.ogm_address - 1) != 0 && config.aborted[mscp_index] == 0xff) + barrier(); /* else??? */ - while ((inb(LCL_DOORBELL_INTR(config.doorbell_address)) & - (config.slot ? 2 : 1)) - && config.aborted[mscp_index] == 0xff) barrier(); - - /* To avoid race conditions, make the code to write to the adapter - atomic. This simplifies the abort code. */ + while ((inb(LCL_DOORBELL_INTR(config.doorbell_address)) & (config.slot ? 2 : 1)) && config.aborted[mscp_index] == 0xff) + barrier(); - save_flags(flags); - cli(); + /* To avoid race conditions, keep the code to write to the adapter + atomic. This simplifies the abort code. Right now the + scsi mid layer has the host_lock already held + */ - if (inb(LCL_DOORBELL_INTR(config.doorbell_address)) & - (config.slot ? 2 : 1)) - { - restore_flags(flags); + if (inb(LCL_DOORBELL_INTR(config.doorbell_address)) & (config.slot ? 2 : 1)) goto retry; - } status = xchgb(0, &config.aborted[mscp_index]); if (status != 0xff) { - restore_flags(flags); #if ULTRASTOR_DEBUG & (UD_COMMAND | UD_ABORT) printk("USx4F: queuecommand: aborted\n"); @@ -811,8 +799,6 @@ outb(0x1, LCL_DOORBELL_INTR(config.doorbell_address)); } - restore_flags(flags); - #if (ULTRASTOR_DEBUG & UD_COMMAND) printk("USx4F: queuecommand: returning\n"); #endif @@ -835,7 +821,7 @@ */ -int ultrastor_abort(Scsi_Cmnd *SCpnt) +static int ultrastor_abort(Scsi_Cmnd *SCpnt) { #if ULTRASTOR_DEBUG & UD_ABORT char out[108]; @@ -844,14 +830,16 @@ #endif unsigned int mscp_index; unsigned char old_aborted; + unsigned long flags; void (*done)(Scsi_Cmnd *); + struct Scsi_Host *host = SCpnt->host; if(config.slot) - return SCSI_ABORT_SNOOZE; /* Do not attempt an abort for the 24f */ - + return FAILED; /* Do not attempt an abort for the 24f */ + /* Simple consistency checking */ if(!SCpnt->host_scribble) - return SCSI_ABORT_NOT_RUNNING; + return FAILED; mscp_index = ((struct mscp *)SCpnt->host_scribble) - config.mscp; if (mscp_index >= ULTRASTOR_MAX_CMDS) @@ -863,8 +851,8 @@ int port0 = (config.slot << 12) | 0xc80; int i; unsigned long flags; - save_flags(flags); - cli(); + + spin_lock_irqsave(host->host_lock, flags); strcpy(out, "OGM %d:%x ICM %d:%x ports: "); for (i = 0; i < 16; i++) { @@ -879,7 +867,7 @@ ogm_addr = (unsigned int)isa_bus_to_virt(inl(port0 + 23)); icm_status = inb(port0 + 27); icm_addr = (unsigned int)isa_bus_to_virt(inl(port0 + 28)); - restore_flags(flags); + spin_lock_irqsave(host->host_lock, flags); } /* First check to see if an interrupt is pending. I suspect the SiS @@ -888,14 +876,13 @@ if (config.slot ? inb(config.icm_address - 1) == 2 : (inb(SYS_DOORBELL_INTR(config.doorbell_address)) & 1)) { - unsigned long flags; - save_flags(flags); printk("Ux4F: abort while completed command pending\n"); - restore_flags(flags); - cli(); + + spin_lock_irqsave(host->host_lock, flags); + /* FIXME: Ewww... need to think about passing host around properly */ ultrastor_interrupt(0, NULL, NULL); - restore_flags(flags); - return SCSI_ABORT_SUCCESS; /* FIXME - is this correct? -ERY */ + spin_unlock_irqrestore(host->host_lock, flags); + return SUCCESS; } #endif @@ -904,7 +891,7 @@ /* aborted == 0xff is the signal that queuecommand has not yet sent the command. It will notice the new abort flag and fail. */ if (old_aborted == 0xff) - return SCSI_ABORT_SUCCESS; + return SUCCESS; /* On 24F, send an abort MSCP request. The adapter will interrupt and the interrupt handler will call done. */ @@ -912,18 +899,18 @@ { unsigned long flags; - save_flags(flags); - cli(); + spin_lock_irqsave(host->host_lock, flags); outl(isa_virt_to_bus(&config.mscp[mscp_index]), config.ogm_address); - inb(0xc80); /* delay */ + udelay(8); outb(0x80, config.ogm_address - 1); outb(0x2, LCL_DOORBELL_INTR(config.doorbell_address)); #if ULTRASTOR_DEBUG & UD_ABORT log_ultrastor_abort(&config, mscp_index); printk(out, ogm_status, ogm_addr, icm_status, icm_addr); #endif - restore_flags(flags); - return SCSI_ABORT_PENDING; + spin_unlock_irqrestore(host->host_lock, flags); + /* FIXME: add a wait for the abort to complete */ + return SUCCESS; } #if ULTRASTOR_DEBUG & UD_ABORT @@ -953,27 +940,30 @@ done = config.mscp[mscp_index].done; config.mscp[mscp_index].done = 0; SCpnt->result = DID_ABORT << 16; - /* I worry about reentrancy in scsi.c */ + + /* Take the host lock to guard against scsi layer re-entry */ + spin_lock_irqsave(host->host_lock, flags); done(SCpnt); + spin_unlock_irqrestore(host->host_lock, flags); /* Need to set a timeout here in case command never completes. */ - return SCSI_ABORT_SUCCESS; + return SUCCESS; } -int ultrastor_reset(Scsi_Cmnd * SCpnt, unsigned int reset_flags) +static int ultrastor_host_reset(Scsi_Cmnd * SCpnt) { unsigned long flags; - register int i; + int i; + struct Scsi_Host *host = SCpnt->host; + #if (ULTRASTOR_DEBUG & UD_RESET) printk("US14F: reset: called\n"); #endif if(config.slot) - return SCSI_RESET_PUNT; /* Do not attempt a reset for the 24f */ - - save_flags(flags); - cli(); + return FAILED; + spin_lock_irqsave(host->host_lock, flags); /* Reset the adapter and SCSI bus. The SCSI bus reset can be inhibited by clearing ultrastor_bus_reset before probe. */ outb(0xc0, LCL_DOORBELL_INTR(config.doorbell_address)); @@ -1005,7 +995,10 @@ #endif /* FIXME - if the device implements soft resets, then the command - will still be running. ERY */ + will still be running. ERY + + Even bigger deal with new_eh! + */ memset((unsigned char *)config.aborted, 0, sizeof config.aborted); #if ULTRASTOR_MAX_CMDS == 1 @@ -1014,7 +1007,7 @@ config.mscp_free = ~0; #endif - restore_flags(flags); + spin_unlock_irqrestore(host->host_lock, flags); return SCSI_RESET_SUCCESS; } @@ -1041,7 +1034,7 @@ #if ULTRASTOR_MAX_CMDS > 1 unsigned int mscp_index; #endif - register struct mscp *mscp; + struct mscp *mscp; void (*done)(Scsi_Cmnd *); Scsi_Cmnd *SCtmp; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/scsi/ultrastor.h linux.2.5.45-ac1/drivers/scsi/ultrastor.h --- linux.2.5.45/drivers/scsi/ultrastor.h 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.45-ac1/drivers/scsi/ultrastor.h 2002-11-02 23:11:29.000000000 +0000 @@ -13,13 +13,12 @@ #ifndef _ULTRASTOR_H #define _ULTRASTOR_H -int ultrastor_detect(Scsi_Host_Template *); -const char *ultrastor_info(struct Scsi_Host * shpnt); -int ultrastor_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); -int ultrastor_abort(Scsi_Cmnd *); -int ultrastor_reset(Scsi_Cmnd *, unsigned int); -int ultrastor_biosparam(struct scsi_device *, struct block_device *, - sector_t, int *); +static int ultrastor_detect(Scsi_Host_Template *); +static const char *ultrastor_info(struct Scsi_Host * shpnt); +static int ultrastor_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); +static int ultrastor_abort(Scsi_Cmnd *); +static int ultrastor_host_reset(Scsi_Cmnd *); +static int ultrastor_biosparam(struct scsi_device *, struct block_device *, sector_t, int *); #define ULTRASTOR_14F_MAX_SG 16 @@ -35,8 +34,8 @@ detect: ultrastor_detect, \ info: ultrastor_info, \ queuecommand: ultrastor_queuecommand, \ - abort: ultrastor_abort, \ - reset: ultrastor_reset, \ + eh_abort_handler: ultrastor_abort, \ + eh_host_reset_handler: ultrastor_host_reset, \ bios_param: ultrastor_biosparam, \ can_queue: ULTRASTOR_MAX_CMDS, \ this_id: 0, \ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/scsi/wd7000.c linux.2.5.45-ac1/drivers/scsi/wd7000.c --- linux.2.5.45/drivers/scsi/wd7000.c 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.45-ac1/drivers/scsi/wd7000.c 2002-11-02 23:39:26.000000000 +0000 @@ -1240,7 +1240,7 @@ host->control = 0; /* this must always shadow ASC_CONTROL */ if (WAIT(host->iobase + ASC_STAT, ASC_STATMASK, CMD_RDY, 0)) { - printk("wd7000_init: WAIT timed out.\n"); + printk(KERN_ERR "wd7000_init: WAIT timed out.\n"); return -1; /* -1 = not ok */ } @@ -1249,25 +1249,25 @@ switch (diag) { case 2: - printk("RAM failure.\n"); + printk(KERN_ERR "RAM failure.\n"); break; case 3: - printk("FIFO R/W failed\n"); + printk(KERN_ERR "FIFO R/W failed\n"); break; case 4: - printk("SBIC register R/W failed\n"); + printk(KERN_ERR "SBIC register R/W failed\n"); break; case 5: - printk("Initialization D-FF failed.\n"); + printk(KERN_ERR "Initialization D-FF failed.\n"); break; case 6: - printk("Host IRQ D-FF failed.\n"); + printk(KERN_ERR "Host IRQ D-FF failed.\n"); break; case 7: - printk("ROM checksum error.\n"); + printk(KERN_ERR "ROM checksum error.\n"); break; default: - printk("diagnostic code 0x%02Xh received.\n", diag); + printk(KERN_ERR "diagnostic code 0x%02Xh received.\n", diag); } return -1; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/serial/68328serial.c linux.2.5.45-ac1/drivers/serial/68328serial.c --- linux.2.5.45/drivers/serial/68328serial.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/drivers/serial/68328serial.c 2002-10-31 15:05:46.000000000 +0000 @@ -0,0 +1,1698 @@ +/* 68328serial.c: Serial port driver for 68328 microcontroller + * + * Copyright (C) 1995 David S. Miller + * Copyright (C) 1998 Kenneth Albanowski + * Copyright (C) 1998, 1999 D. Jeff Dionne + * Copyright (C) 1999 Vladimir Gurevich + * Copyright (C) 2002 David McCullough + * Copyright (C) 2002 Greg Ungerer + * + * VZ Support/Fixes Evan Stawnyczy + * Multiple UART support Daniel Potts + * Power management support Daniel Potts + * VZ Second Serial Port enable Phil Wilshire + * 2.4/2.5 port David McCullough + */ + +#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 + +/* (es) */ +/* note: perhaps we can murge these files, so that you can just + * define 1 of them, and they can sort that out for themselves + */ +#if defined(CONFIG_M68EZ328) +#include +#else +#if defined(CONFIG_M68VZ328) +#include +#else +#include +#endif /* CONFIG_M68VZ328 */ +#endif /* CONFIG_M68EZ328 */ + +#include "68328serial.h" + +/* Turn off usage of real serial interrupt code, to "support" Copilot */ +#ifdef CONFIG_XCOPILOT_BUGS +#undef USE_INTS +#else +#define USE_INTS +#endif + +static struct m68k_serial m68k_soft[NR_PORTS]; +struct m86k_serial *IRQ_ports[NR_IRQS]; + +static unsigned int uart_irqs[NR_PORTS] = UART_IRQ_DEFNS; + +/* multiple ports are contiguous in memory */ +m68328_uart *uart_addr = USTCNT_ADDR; + +struct tty_struct m68k_ttys; +struct m68k_serial *m68k_consinfo = 0; + +#define M68K_CLOCK (16667000) /* FIXME: 16MHz is likely wrong */ + +#ifdef CONFIG_CONSOLE +extern wait_queue_head_t keypress_wait; +#endif + +struct tty_driver serial_driver, callout_driver; +static int serial_refcount; + +/* serial subtype definitions */ +#define SERIAL_TYPE_NORMAL 1 +#define SERIAL_TYPE_CALLOUT 2 + +/* number of characters left in xmit buffer before we ask for more */ +#define WAKEUP_CHARS 256 + +/* Debugging... DEBUG_INTR is bad to use when one of the zs + * lines is your console ;( + */ +#undef SERIAL_DEBUG_INTR +#undef SERIAL_DEBUG_OPEN +#undef SERIAL_DEBUG_FLOW + +#define RS_ISR_PASS_LIMIT 256 + +#define _INLINE_ inline + +static void change_speed(struct m68k_serial *info); + +static struct tty_struct *serial_table[NR_PORTS]; +static struct termios *serial_termios[NR_PORTS]; +static struct termios *serial_termios_locked[NR_PORTS]; + +/* + * Setup for console. Argument comes from the boot command line. + */ + +#if defined(CONFIG_M68EZ328ADS) || defined(CONFIG_ALMA_ANS) || defined(CONFIG_DRAGONIXVZ) +#define CONSOLE_BAUD_RATE 115200 +#define DEFAULT_CBAUD B115200 +#else + /* (es) */ + /* note: this is messy, but it works, again, perhaps defined somewhere else?*/ + #ifdef CONFIG_M68VZ328 + #define CONSOLE_BAUD_RATE 19200 + #define DEFAULT_CBAUD B19200 + #endif + /* (/es) */ +#endif + +#ifndef CONSOLE_BAUD_RATE +#define CONSOLE_BAUD_RATE 9600 +#define DEFAULT_CBAUD B9600 +#endif + + +static int m68328_console_initted = 0; +static int m68328_console_baud = CONSOLE_BAUD_RATE; +static int m68328_console_cbaud = DEFAULT_CBAUD; + + +/* + * tmp_buf is used as a temporary buffer by serial_write. We need to + * lock it in case the memcpy_fromfs blocks while swapping in a page, + * and some other program tries to do a serial write at the same time. + * Since the lock will only come under contention when the system is + * swapping and available memory is low, it makes sense to share one + * buffer across all the serial ports, since it significantly saves + * memory if large numbers of serial ports are open. + */ +static unsigned char tmp_buf[SERIAL_XMIT_SIZE]; /* This is cheating */ +DECLARE_MUTEX(tmp_buf_sem); + +static inline int serial_paranoia_check(struct m68k_serial *info, + kdev_t device, const char *routine) +{ +#ifdef SERIAL_PARANOIA_CHECK + static const char *badmagic = + "Warning: bad magic number for serial struct (%d, %d) in %s\n"; + static const char *badinfo = + "Warning: null m68k_serial for (%d, %d) in %s\n"; + + if (!info) { + printk(badinfo, major(device), minor(device), routine); + return 1; + } + if (info->magic != SERIAL_MAGIC) { + printk(badmagic, major(device), minor(device), routine); + return 1; + } +#endif + return 0; +} + +/* + * This is used to figure out the divisor speeds and the timeouts + */ +static int baud_table[] = { + 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, + 9600, 19200, 38400, 57600, 115200, 0 }; + +#define BAUD_TABLE_SIZE (sizeof(baud_table)/sizeof(baud_table[0])) + +/* Sets or clears DTR/RTS on the requested line */ +static inline void m68k_rtsdtr(struct m68k_serial *ss, int set) +{ + if (set) { + /* set the RTS/CTS line */ + } else { + /* clear it */ + } + return; +} + +/* Utility routines */ +static inline int get_baud(struct m68k_serial *ss) +{ + unsigned long result = 115200; + unsigned short int baud = uart_addr[ss->line].ubaud; + if (GET_FIELD(baud, UBAUD_PRESCALER) == 0x38) result = 38400; + result >>= GET_FIELD(baud, UBAUD_DIVIDE); + + return result; +} + +/* + * ------------------------------------------------------------ + * rs_stop() and rs_start() + * + * This routines are called before setting or resetting tty->stopped. + * They enable or disable transmitter interrupts, as necessary. + * ------------------------------------------------------------ + */ +static void rs_stop(struct tty_struct *tty) +{ + struct m68k_serial *info = (struct m68k_serial *)tty->driver_data; + m68328_uart *uart = &uart_addr[info->line]; + unsigned long flags; + + if (serial_paranoia_check(info, tty->device, "rs_stop")) + return; + + save_flags(flags); cli(); + uart->ustcnt &= ~USTCNT_TXEN; + restore_flags(flags); +} + +static void rs_put_char(char ch) +{ + int flags, loops = 0; + + save_flags(flags); cli(); + + while (!(UTX & UTX_TX_AVAIL) && (loops < 1000)) { + loops++; + udelay(5); + } + + UTX_TXDATA = ch; + udelay(5); + restore_flags(flags); +} + +static void rs_start(struct tty_struct *tty) +{ + struct m68k_serial *info = (struct m68k_serial *)tty->driver_data; + m68328_uart *uart = &uart_addr[info->line]; + unsigned long flags; + + if (serial_paranoia_check(info, tty->device, "rs_start")) + return; + + save_flags(flags); cli(); + if (info->xmit_cnt && info->xmit_buf && !(uart->ustcnt & USTCNT_TXEN)) { +#ifdef USE_INTS + uart->ustcnt |= USTCNT_TXEN | USTCNT_TX_INTR_MASK; +#else + uart->ustcnt |= USTCNT_TXEN; +#endif + } + restore_flags(flags); +} + +/* Drop into either the boot monitor or kadb upon receiving a break + * from keyboard/console input. + */ +static void batten_down_hatches(void) +{ + /* Drop into the debugger */ +} + +static _INLINE_ void status_handle(struct m68k_serial *info, unsigned short status) +{ +#if 0 + if(status & DCD) { + if((info->tty->termios->c_cflag & CRTSCTS) && + ((info->curregs[3] & AUTO_ENAB)==0)) { + info->curregs[3] |= AUTO_ENAB; + info->pendregs[3] |= AUTO_ENAB; + write_zsreg(info->m68k_channel, 3, info->curregs[3]); + } + } else { + if((info->curregs[3] & AUTO_ENAB)) { + info->curregs[3] &= ~AUTO_ENAB; + info->pendregs[3] &= ~AUTO_ENAB; + write_zsreg(info->m68k_channel, 3, info->curregs[3]); + } + } +#endif + /* If this is console input and this is a + * 'break asserted' status change interrupt + * see if we can drop into the debugger + */ + if((status & URX_BREAK) && info->break_abort) + batten_down_hatches(); + return; +} + +static _INLINE_ void receive_chars(struct m68k_serial *info, struct pt_regs *regs, unsigned short rx) +{ + struct tty_struct *tty = info->tty; + m68328_uart *uart = &uart_addr[info->line]; + unsigned char ch; + + /* + * This do { } while() loop will get ALL chars out of Rx FIFO + */ +#ifndef CONFIG_XCOPILOT_BUGS + do { +#endif + ch = GET_FIELD(rx, URX_RXDATA); + + if(info->is_cons) { + if(URX_BREAK & rx) { /* whee, break received */ + status_handle(info, rx); + return; +#ifdef CONFIG_MAGIC_SYSRQ + } else if (ch == 0x10) { /* ^P */ + show_state(); + show_free_areas(); + show_buffers(); +/* show_net_buffers(); */ + return; + } else if (ch == 0x12) { /* ^R */ + machine_restart(NULL); + return; +#endif /* CONFIG_MAGIC_SYSRQ */ + } + /* It is a 'keyboard interrupt' ;-) */ +#ifdef CONFIG_CONSOLE + wake_up(&keypress_wait); +#endif + } + + if(!tty) + goto clear_and_exit; + + /* + * Make sure that we do not overflow the buffer + */ + if (tty->flip.count >= TTY_FLIPBUF_SIZE) { + schedule_work(&tty->flip.work); + return; + } + + if(rx & URX_PARITY_ERROR) { + *tty->flip.flag_buf_ptr++ = TTY_PARITY; + status_handle(info, rx); + } else if(rx & URX_OVRUN) { + *tty->flip.flag_buf_ptr++ = TTY_OVERRUN; + status_handle(info, rx); + } else if(rx & URX_FRAME_ERROR) { + *tty->flip.flag_buf_ptr++ = TTY_FRAME; + status_handle(info, rx); + } else { + *tty->flip.flag_buf_ptr++ = 0; /* XXX */ + } + *tty->flip.char_buf_ptr++ = ch; + tty->flip.count++; + +#ifndef CONFIG_XCOPILOT_BUGS + } while((rx = uart->urx.w) & URX_DATA_READY); +#endif + + schedule_work(&tty->flip.work); + +clear_and_exit: + return; +} + +static _INLINE_ void transmit_chars(struct m68k_serial *info) +{ + m68328_uart *uart = &uart_addr[info->line]; + + if (info->x_char) { + /* Send next char */ + uart->utx.b.txdata = info->x_char; + info->x_char = 0; + goto clear_and_return; + } + + if((info->xmit_cnt <= 0) || info->tty->stopped) { + /* That's peculiar... TX ints off */ + uart->ustcnt &= ~USTCNT_TX_INTR_MASK; + goto clear_and_return; + } + + /* Send char */ + uart->utx.b.txdata = info->xmit_buf[info->xmit_tail++]; + info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1); + info->xmit_cnt--; + + if (info->xmit_cnt < WAKEUP_CHARS) + schedule_work(&info->tqueue); + + if(info->xmit_cnt <= 0) { + /* All done for now... TX ints off */ + uart->ustcnt &= ~USTCNT_TX_INTR_MASK; + goto clear_and_return; + } + +clear_and_return: + /* Clear interrupt (should be auto)*/ + return; +} + +/* + * This is the serial driver's generic interrupt routine + */ +void rs_interrupt(int irq, void *dev_id, struct pt_regs * regs) +{ + struct m68k_serial * info; + m68328_uart *uart; + unsigned short rx; + unsigned short tx; + + info = IRQ_ports[irq]; + if(!info) + return; + + uart = &uart_addr[info->line]; + rx = uart->urx.w; + +#ifdef USE_INTS + tx = uart->utx.w; + + if (rx & URX_DATA_READY) receive_chars(info, regs, rx); + if (tx & UTX_TX_AVAIL) transmit_chars(info); +#else + receive_chars(info, regs, rx); +#endif + return; +} + +static void do_softint(void *private) +{ + struct m68k_serial *info = (struct m68k_serial *) private; + struct tty_struct *tty; + + tty = info->tty; + if (!tty) + return; +#if 0 + if (clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) { + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + tty->ldisc.write_wakeup) + (tty->ldisc.write_wakeup)(tty); + wake_up_interruptible(&tty->write_wait); + } +#endif +} + +/* + * This routine is called from the scheduler tqueue when the interrupt + * routine has signalled that a hangup has occurred. The path of + * hangup processing is: + * + * serial interrupt routine -> (scheduler tqueue) -> + * do_serial_hangup() -> tty->hangup() -> rs_hangup() + * + */ +static void do_serial_hangup(void *private) +{ + struct m68k_serial *info = (struct m68k_serial *) private; + struct tty_struct *tty; + + tty = info->tty; + if (!tty) + return; + + tty_hangup(tty); +} + + +static int startup(struct m68k_serial * info) +{ + m68328_uart *uart = &uart_addr[info->line]; + unsigned long flags; + + if (info->flags & S_INITIALIZED) + return 0; + + if (!info->xmit_buf) { + info->xmit_buf = (unsigned char *) __get_free_page(GFP_KERNEL); + if (!info->xmit_buf) + return -ENOMEM; + } + + save_flags(flags); cli(); + + /* + * Clear the FIFO buffers and disable them + * (they will be reenabled in change_speed()) + */ + + uart->ustcnt = USTCNT_UEN; + info->xmit_fifo_size = 1; + uart->ustcnt = USTCNT_UEN | USTCNT_RXEN | USTCNT_TXEN; + (void)uart->urx.w; + + /* + * Finally, enable sequencing and interrupts + */ +#ifdef USE_INTS + uart->ustcnt = USTCNT_UEN | USTCNT_RXEN | + USTCNT_RX_INTR_MASK | USTCNT_TX_INTR_MASK; +#else + uart->ustcnt = USTCNT_UEN | USTCNT_RXEN | USTCNT_RX_INTR_MASK; +#endif + + if (info->tty) + clear_bit(TTY_IO_ERROR, &info->tty->flags); + info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; + + /* + * and set the speed of the serial port + */ + + change_speed(info); + + info->flags |= S_INITIALIZED; + restore_flags(flags); + return 0; +} + +/* + * This routine will shutdown a serial port; interrupts are disabled, and + * DTR is dropped if the hangup on close termio flag is on. + */ +static void shutdown(struct m68k_serial * info) +{ + m68328_uart *uart = &uart_addr[info->line]; + unsigned long flags; + + uart->ustcnt = 0; /* All off! */ + if (!(info->flags & S_INITIALIZED)) + return; + + save_flags(flags); cli(); /* Disable interrupts */ + + if (info->xmit_buf) { + free_page((unsigned long) info->xmit_buf); + info->xmit_buf = 0; + } + + if (info->tty) + set_bit(TTY_IO_ERROR, &info->tty->flags); + + info->flags &= ~S_INITIALIZED; + restore_flags(flags); +} + +struct { + int divisor, prescale; +} +#ifndef CONFIG_M68VZ328 + hw_baud_table[18] = { + {0,0}, /* 0 */ + {0,0}, /* 50 */ + {0,0}, /* 75 */ + {0,0}, /* 110 */ + {0,0}, /* 134 */ + {0,0}, /* 150 */ + {0,0}, /* 200 */ + {7,0x26}, /* 300 */ + {6,0x26}, /* 600 */ + {5,0x26}, /* 1200 */ + {0,0}, /* 1800 */ + {4,0x26}, /* 2400 */ + {3,0x26}, /* 4800 */ + {2,0x26}, /* 9600 */ + {1,0x26}, /* 19200 */ + {0,0x26}, /* 38400 */ + {1,0x38}, /* 57600 */ + {0,0x38}, /* 115200 */ +}; +#else + hw_baud_table[18] = { + {0,0}, /* 0 */ + {0,0}, /* 50 */ + {0,0}, /* 75 */ + {0,0}, /* 110 */ + {0,0}, /* 134 */ + {0,0}, /* 150 */ + {0,0}, /* 200 */ + {0,0}, /* 300 */ + {7,0x26}, /* 600 */ + {6,0x26}, /* 1200 */ + {0,0}, /* 1800 */ + {5,0x26}, /* 2400 */ + {4,0x26}, /* 4800 */ + {3,0x26}, /* 9600 */ + {2,0x26}, /* 19200 */ + {1,0x26}, /* 38400 */ + {0,0x26}, /* 57600 */ + {1,0x38}, /* 115200 */ +}; +#endif +/* rate = 1036800 / ((65 - prescale) * (1<line]; + unsigned short port; + unsigned short ustcnt; + unsigned cflag; + int i; + + if (!info->tty || !info->tty->termios) + return; + cflag = info->tty->termios->c_cflag; + if (!(port = info->port)) + return; + + ustcnt = uart->ustcnt; + uart->ustcnt = ustcnt & ~USTCNT_TXEN; + + i = cflag & CBAUD; + if (i & CBAUDEX) { + i = (i & ~CBAUDEX) + B38400; + } + + info->baud = baud_table[i]; + uart->ubaud = PUT_FIELD(UBAUD_DIVIDE, hw_baud_table[i].divisor) | + PUT_FIELD(UBAUD_PRESCALER, hw_baud_table[i].prescale); + + ustcnt &= ~(USTCNT_PARITYEN | USTCNT_ODD_EVEN | USTCNT_STOP | USTCNT_8_7); + + if ((cflag & CSIZE) == CS8) + ustcnt |= USTCNT_8_7; + + if (cflag & CSTOPB) + ustcnt |= USTCNT_STOP; + + if (cflag & PARENB) + ustcnt |= USTCNT_PARITYEN; + if (cflag & PARODD) + ustcnt |= USTCNT_ODD_EVEN; + +#ifdef CONFIG_SERIAL_68328_RTS_CTS + if (cflag & CRTSCTS) { + uart->utx.w &= ~ UTX_NOCTS; + } else { + uart->utx.w |= UTX_NOCTS; + } +#endif + + ustcnt |= USTCNT_TXEN; + + uart->ustcnt = ustcnt; + return; +} + +/* + * Fair output driver allows a process to speak. + */ +static void rs_fair_output(void) +{ + int left; /* Output no more than that */ + unsigned long flags; + struct m68k_serial *info = &m68k_soft[0]; + char c; + + if (info == 0) return; + if (info->xmit_buf == 0) return; + + save_flags(flags); cli(); + left = info->xmit_cnt; + while (left != 0) { + c = info->xmit_buf[info->xmit_tail]; + info->xmit_tail = (info->xmit_tail+1) & (SERIAL_XMIT_SIZE-1); + info->xmit_cnt--; + restore_flags(flags); + + rs_put_char(c); + + save_flags(flags); cli(); + left = min(info->xmit_cnt, left-1); + } + + /* Last character is being transmitted now (hopefully). */ + udelay(5); + + restore_flags(flags); + return; +} + +/* + * m68k_console_print is registered for printk. + */ +void console_print_68328(const char *p) +{ + char c; + + while((c=*(p++)) != 0) { + if(c == '\n') + rs_put_char('\r'); + rs_put_char(c); + } + + /* Comment this if you want to have a strict interrupt-driven output */ + rs_fair_output(); + + return; +} + +static void rs_set_ldisc(struct tty_struct *tty) +{ + struct m68k_serial *info = (struct m68k_serial *)tty->driver_data; + + if (serial_paranoia_check(info, tty->device, "rs_set_ldisc")) + return; + + info->is_cons = (tty->termios->c_line == N_TTY); + + printk("ttyS%d console mode %s\n", info->line, info->is_cons ? "on" : "off"); +} + +static void rs_flush_chars(struct tty_struct *tty) +{ + struct m68k_serial *info = (struct m68k_serial *)tty->driver_data; + m68328_uart *uart = &uart_addr[info->line]; + unsigned long flags; + + if (serial_paranoia_check(info, tty->device, "rs_flush_chars")) + return; +#ifndef USE_INTS + for(;;) { +#endif + + /* Enable transmitter */ + save_flags(flags); cli(); + + if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || + !info->xmit_buf) { + restore_flags(flags); + return; + } + +#ifdef USE_INTS + uart->ustcnt |= USTCNT_TXEN | USTCNT_TX_INTR_MASK; +#else + uart->ustcnt |= USTCNT_TXEN; +#endif + +#ifdef USE_INTS + if (uart->utx.w & UTX_TX_AVAIL) { +#else + if (1) { +#endif + /* Send char */ + uart->utx.b.txdata = info->xmit_buf[info->xmit_tail++]; + info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1); + info->xmit_cnt--; + } + +#ifndef USE_INTS + while (!(uart->utx.w & UTX_TX_AVAIL)) udelay(5); + } +#endif + restore_flags(flags); +} + +extern void console_printn(const char * b, int count); + +static int rs_write(struct tty_struct * tty, int from_user, + const unsigned char *buf, int count) +{ + int c, total = 0; + struct m68k_serial *info = (struct m68k_serial *)tty->driver_data; + m68328_uart *uart = &uart_addr[info->line]; + unsigned long flags; + + if (serial_paranoia_check(info, tty->device, "rs_write")) + return 0; + + if (!tty || !info->xmit_buf) + return 0; + + save_flags(flags); + while (1) { + cli(); + c = min(count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, + SERIAL_XMIT_SIZE - info->xmit_head)); + if (c <= 0) + break; + + if (from_user) { + down(&tmp_buf_sem); + copy_from_user(tmp_buf, buf, c); + c = min(c, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, + SERIAL_XMIT_SIZE - info->xmit_head)); + memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c); + up(&tmp_buf_sem); + } else + memcpy(info->xmit_buf + info->xmit_head, buf, c); + info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1); + info->xmit_cnt += c; + restore_flags(flags); + buf += c; + count -= c; + total += c; + } + + if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped) { + /* Enable transmitter */ + cli(); +#ifndef USE_INTS + while(info->xmit_cnt) { +#endif + + uart->ustcnt |= USTCNT_TXEN; +#ifdef USE_INTS + uart->ustcnt |= USTCNT_TX_INTR_MASK; +#else + while (!(uart->utx.w & UTX_TX_AVAIL)) udelay(5); +#endif + if (uart->utx.w & UTX_TX_AVAIL) { + uart->utx.b.txdata = info->xmit_buf[info->xmit_tail++]; + info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1); + info->xmit_cnt--; + } + +#ifndef USE_INTS + } +#endif + restore_flags(flags); + } + restore_flags(flags); + return total; +} + +static int rs_write_room(struct tty_struct *tty) +{ + struct m68k_serial *info = (struct m68k_serial *)tty->driver_data; + int ret; + + if (serial_paranoia_check(info, tty->device, "rs_write_room")) + return 0; + ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1; + if (ret < 0) + ret = 0; + return ret; +} + +static int rs_chars_in_buffer(struct tty_struct *tty) +{ + struct m68k_serial *info = (struct m68k_serial *)tty->driver_data; + + if (serial_paranoia_check(info, tty->device, "rs_chars_in_buffer")) + return 0; + return info->xmit_cnt; +} + +static void rs_flush_buffer(struct tty_struct *tty) +{ + struct m68k_serial *info = (struct m68k_serial *)tty->driver_data; + + if (serial_paranoia_check(info, tty->device, "rs_flush_buffer")) + return; + cli(); + info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; + sti(); + wake_up_interruptible(&tty->write_wait); + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + tty->ldisc.write_wakeup) + (tty->ldisc.write_wakeup)(tty); +} + +/* + * ------------------------------------------------------------ + * rs_throttle() + * + * This routine is called by the upper-layer tty layer to signal that + * incoming characters should be throttled. + * ------------------------------------------------------------ + */ +static void rs_throttle(struct tty_struct * tty) +{ + struct m68k_serial *info = (struct m68k_serial *)tty->driver_data; + + if (serial_paranoia_check(info, tty->device, "rs_throttle")) + return; + + if (I_IXOFF(tty)) + info->x_char = STOP_CHAR(tty); + + /* Turn off RTS line (do this atomic) */ +} + +static void rs_unthrottle(struct tty_struct * tty) +{ + struct m68k_serial *info = (struct m68k_serial *)tty->driver_data; + + if (serial_paranoia_check(info, tty->device, "rs_unthrottle")) + return; + + if (I_IXOFF(tty)) { + if (info->x_char) + info->x_char = 0; + else + info->x_char = START_CHAR(tty); + } + + /* Assert RTS line (do this atomic) */ +} + +/* + * ------------------------------------------------------------ + * rs_ioctl() and friends + * ------------------------------------------------------------ + */ + +static int get_serial_info(struct m68k_serial * info, + struct serial_struct * retinfo) +{ + struct serial_struct tmp; + + if (!retinfo) + return -EFAULT; + memset(&tmp, 0, sizeof(tmp)); + tmp.type = info->type; + tmp.line = info->line; + tmp.port = info->port; + tmp.irq = info->irq; + tmp.flags = info->flags; + tmp.baud_base = info->baud_base; + tmp.close_delay = info->close_delay; + tmp.closing_wait = info->closing_wait; + tmp.custom_divisor = info->custom_divisor; + copy_to_user(retinfo,&tmp,sizeof(*retinfo)); + return 0; +} + +static int set_serial_info(struct m68k_serial * info, + struct serial_struct * new_info) +{ + struct serial_struct new_serial; + struct m68k_serial old_info; + int retval = 0; + + if (!new_info) + return -EFAULT; + copy_from_user(&new_serial,new_info,sizeof(new_serial)); + old_info = *info; + + if (!capable(CAP_SYS_ADMIN)) { + if ((new_serial.baud_base != info->baud_base) || + (new_serial.type != info->type) || + (new_serial.close_delay != info->close_delay) || + ((new_serial.flags & ~S_USR_MASK) != + (info->flags & ~S_USR_MASK))) + return -EPERM; + info->flags = ((info->flags & ~S_USR_MASK) | + (new_serial.flags & S_USR_MASK)); + info->custom_divisor = new_serial.custom_divisor; + goto check_and_exit; + } + + if (info->count > 1) + return -EBUSY; + + /* + * OK, past this point, all the error checking has been done. + * At this point, we start making changes..... + */ + + info->baud_base = new_serial.baud_base; + info->flags = ((info->flags & ~S_FLAGS) | + (new_serial.flags & S_FLAGS)); + info->type = new_serial.type; + info->close_delay = new_serial.close_delay; + info->closing_wait = new_serial.closing_wait; + +check_and_exit: + retval = startup(info); + return retval; +} + +/* + * get_lsr_info - get line status register info + * + * Purpose: Let user call ioctl() to get info when the UART physically + * is emptied. On bus types like RS485, the transmitter must + * release the bus after transmitting. This must be done when + * the transmit shift register is empty, not be done when the + * transmit holding register is empty. This functionality + * allows an RS485 driver to be written in user space. + */ +static int get_lsr_info(struct m68k_serial * info, unsigned int *value) +{ +#ifdef CONFIG_SERIAL_68328_RTS_CTS + m68328_uart *uart = &uart_addr[info->line]; +#endif + unsigned char status; + + cli(); +#ifdef CONFIG_SERIAL_68328_RTS_CTS + status = (uart->utx.w & UTX_CTS_STAT) ? 1 : 0; +#else + status = 0; +#endif + sti(); + put_user(status,value); + return 0; +} + +/* + * This routine sends a break character out the serial port. + */ +static void send_break( struct m68k_serial * info, int duration) +{ + m68328_uart *uart = &uart_addr[info->line]; + unsigned long flags; + if (!info->port) + return; + current->state = TASK_INTERRUPTIBLE; + save_flags(flags); + cli(); +#ifdef USE_INTS + uart->utx.w |= UTX_SEND_BREAK; + schedule_timeout(duration); + uart->utx.w &= ~UTX_SEND_BREAK; +#endif + restore_flags(flags); +} + +static int rs_ioctl(struct tty_struct *tty, struct file * file, + unsigned int cmd, unsigned long arg) +{ + int error; + struct m68k_serial * info = (struct m68k_serial *)tty->driver_data; + int retval; + + if (serial_paranoia_check(info, tty->device, "rs_ioctl")) + return -ENODEV; + + if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && + (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD) && + (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT)) { + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; + } + + switch (cmd) { + case TCSBRK: /* SVID version: non-zero arg --> no break */ + retval = tty_check_change(tty); + if (retval) + return retval; + tty_wait_until_sent(tty, 0); + if (!arg) + send_break(info, HZ/4); /* 1/4 second */ + return 0; + case TCSBRKP: /* support for POSIX tcsendbreak() */ + retval = tty_check_change(tty); + if (retval) + return retval; + tty_wait_until_sent(tty, 0); + send_break(info, arg ? arg*(HZ/10) : HZ/4); + return 0; + case TIOCGSOFTCAR: + error = verify_area(VERIFY_WRITE, (void *) arg,sizeof(long)); + if (error) + return error; + put_user(C_CLOCAL(tty) ? 1 : 0, + (unsigned long *) arg); + return 0; + case TIOCSSOFTCAR: + get_user(arg, (unsigned long *) arg); + tty->termios->c_cflag = + ((tty->termios->c_cflag & ~CLOCAL) | + (arg ? CLOCAL : 0)); + return 0; + case TIOCGSERIAL: + error = verify_area(VERIFY_WRITE, (void *) arg, + sizeof(struct serial_struct)); + if (error) + return error; + return get_serial_info(info, + (struct serial_struct *) arg); + case TIOCSSERIAL: + return set_serial_info(info, + (struct serial_struct *) arg); + case TIOCSERGETLSR: /* Get line status register */ + error = verify_area(VERIFY_WRITE, (void *) arg, + sizeof(unsigned int)); + if (error) + return error; + else + return get_lsr_info(info, (unsigned int *) arg); + + case TIOCSERGSTRUCT: + error = verify_area(VERIFY_WRITE, (void *) arg, + sizeof(struct m68k_serial)); + if (error) + return error; + copy_to_user((struct m68k_serial *) arg, + info, sizeof(struct m68k_serial)); + return 0; + + default: + return -ENOIOCTLCMD; + } + return 0; +} + +static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios) +{ + struct m68k_serial *info = (struct m68k_serial *)tty->driver_data; + + if (tty->termios->c_cflag == old_termios->c_cflag) + return; + + change_speed(info); + + if ((old_termios->c_cflag & CRTSCTS) && + !(tty->termios->c_cflag & CRTSCTS)) { + tty->hw_stopped = 0; + rs_start(tty); + } + +} + +/* + * ------------------------------------------------------------ + * rs_close() + * + * This routine is called when the serial port gets closed. First, we + * wait for the last remaining data to be sent. Then, we unlink its + * S structure from the interrupt chain if necessary, and we free + * that IRQ if nothing is left in the chain. + * ------------------------------------------------------------ + */ +static void rs_close(struct tty_struct *tty, struct file * filp) +{ + struct m68k_serial * info = (struct m68k_serial *)tty->driver_data; + m68328_uart *uart = &uart_addr[info->line]; + unsigned long flags; + + if (!info || serial_paranoia_check(info, tty->device, "rs_close")) + return; + + save_flags(flags); cli(); + + if (tty_hung_up_p(filp)) { + restore_flags(flags); + return; + } + + if ((tty->count == 1) && (info->count != 1)) { + /* + * Uh, oh. tty->count is 1, which means that the tty + * structure will be freed. Info->count should always + * be one in these conditions. If it's greater than + * one, we've got real problems, since it means the + * serial port won't be shutdown. + */ + printk("rs_close: bad serial port count; tty->count is 1, " + "info->count is %d\n", info->count); + info->count = 1; + } + if (--info->count < 0) { + printk("rs_close: bad serial port count for ttyS%d: %d\n", + info->line, info->count); + info->count = 0; + } + if (info->count) { + restore_flags(flags); + return; + } + info->flags |= S_CLOSING; + /* + * Save the termios structure, since this port may have + * separate termios for callout and dialin. + */ + if (info->flags & S_NORMAL_ACTIVE) + info->normal_termios = *tty->termios; + if (info->flags & S_CALLOUT_ACTIVE) + info->callout_termios = *tty->termios; + /* + * Now we wait for the transmit buffer to clear; and we notify + * the line discipline to only process XON/XOFF characters. + */ + tty->closing = 1; + if (info->closing_wait != S_CLOSING_WAIT_NONE) + tty_wait_until_sent(tty, info->closing_wait); + /* + * At this point we stop accepting input. To do this, we + * disable the receive line status interrupts, and tell the + * interrupt driver to stop checking the data ready bit in the + * line status register. + */ + + uart->ustcnt &= ~USTCNT_RXEN; + uart->ustcnt &= ~(USTCNT_RXEN | USTCNT_RX_INTR_MASK); + + shutdown(info); + if (tty->driver.flush_buffer) + tty->driver.flush_buffer(tty); + if (tty->ldisc.flush_buffer) + tty->ldisc.flush_buffer(tty); + tty->closing = 0; + info->event = 0; + info->tty = 0; + if (tty->ldisc.num != ldiscs[N_TTY].num) { + if (tty->ldisc.close) + (tty->ldisc.close)(tty); + tty->ldisc = ldiscs[N_TTY]; + tty->termios->c_line = N_TTY; + if (tty->ldisc.open) + (tty->ldisc.open)(tty); + } + if (info->blocked_open) { + if (info->close_delay) { + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(info->close_delay); + } + wake_up_interruptible(&info->open_wait); + } + info->flags &= ~(S_NORMAL_ACTIVE|S_CALLOUT_ACTIVE| + S_CLOSING); + wake_up_interruptible(&info->close_wait); + restore_flags(flags); +} + +/* + * rs_hangup() --- called by tty_hangup() when a hangup is signaled. + */ +void rs_hangup(struct tty_struct *tty) +{ + struct m68k_serial * info = (struct m68k_serial *)tty->driver_data; + + if (serial_paranoia_check(info, tty->device, "rs_hangup")) + return; + + rs_flush_buffer(tty); + shutdown(info); + info->event = 0; + info->count = 0; + info->flags &= ~(S_NORMAL_ACTIVE|S_CALLOUT_ACTIVE); + info->tty = 0; + wake_up_interruptible(&info->open_wait); +} + +/* + * ------------------------------------------------------------ + * rs_open() and friends + * ------------------------------------------------------------ + */ +static int block_til_ready(struct tty_struct *tty, struct file * filp, + struct m68k_serial *info) +{ + DECLARE_WAITQUEUE(wait, current); + int retval; + int do_clocal = 0; + + /* + * If the device is in the middle of being closed, then block + * until it's done, and then try again. + */ + if (info->flags & S_CLOSING) { + interruptible_sleep_on(&info->close_wait); +#ifdef SERIAL_DO_RESTART + if (info->flags & S_HUP_NOTIFY) + return -EAGAIN; + else + return -ERESTARTSYS; +#else + return -EAGAIN; +#endif + } + + /* + * If this is a callout device, then just make sure the normal + * device isn't being used. + */ + if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) { + if (info->flags & S_NORMAL_ACTIVE) + return -EBUSY; + if ((info->flags & S_CALLOUT_ACTIVE) && + (info->flags & S_SESSION_LOCKOUT) && + (info->session != current->session)) + return -EBUSY; + if ((info->flags & S_CALLOUT_ACTIVE) && + (info->flags & S_PGRP_LOCKOUT) && + (info->pgrp != current->pgrp)) + return -EBUSY; + info->flags |= S_CALLOUT_ACTIVE; + return 0; + } + + /* + * If non-blocking mode is set, or the port is not enabled, + * then make the check up front and then exit. + */ + if ((filp->f_flags & O_NONBLOCK) || + (tty->flags & (1 << TTY_IO_ERROR))) { + if (info->flags & S_CALLOUT_ACTIVE) + return -EBUSY; + info->flags |= S_NORMAL_ACTIVE; + return 0; + } + + if (info->flags & S_CALLOUT_ACTIVE) { + if (info->normal_termios.c_cflag & CLOCAL) + do_clocal = 1; + } else { + if (tty->termios->c_cflag & CLOCAL) + do_clocal = 1; + } + + /* + * Block waiting for the carrier detect and the line to become + * free (i.e., not in use by the callout). While we are in + * this loop, info->count is dropped by one, so that + * rs_close() knows when to free things. We restore it upon + * exit, either normal or abnormal. + */ + retval = 0; + add_wait_queue(&info->open_wait, &wait); + + info->count--; + info->blocked_open++; + while (1) { + cli(); + if (!(info->flags & S_CALLOUT_ACTIVE)) + m68k_rtsdtr(info, 1); + sti(); + current->state = TASK_INTERRUPTIBLE; + if (tty_hung_up_p(filp) || + !(info->flags & S_INITIALIZED)) { +#ifdef SERIAL_DO_RESTART + if (info->flags & S_HUP_NOTIFY) + retval = -EAGAIN; + else + retval = -ERESTARTSYS; +#else + retval = -EAGAIN; +#endif + break; + } + if (!(info->flags & S_CALLOUT_ACTIVE) && + !(info->flags & S_CLOSING) && do_clocal) + break; + if (signal_pending(current)) { + retval = -ERESTARTSYS; + break; + } + schedule(); + } + current->state = TASK_RUNNING; + remove_wait_queue(&info->open_wait, &wait); + if (!tty_hung_up_p(filp)) + info->count++; + info->blocked_open--; + + if (retval) + return retval; + info->flags |= S_NORMAL_ACTIVE; + return 0; +} + +/* + * This routine is called whenever a serial port is opened. It + * enables interrupts for a serial port, linking in its S structure into + * the IRQ chain. It also performs the serial-specific + * initialization for the tty structure. + */ +int rs_open(struct tty_struct *tty, struct file * filp) +{ + struct m68k_serial *info; + int retval, line; + + line = minor(tty->device) - tty->driver.minor_start; + + if (line >= NR_PORTS || line < 0) /* we have exactly one */ + return -ENODEV; + + info = &m68k_soft[line]; + + if (serial_paranoia_check(info, tty->device, "rs_open")) + return -ENODEV; + + info->count++; + tty->driver_data = info; + info->tty = tty; + + /* + * Start up serial port + */ + retval = startup(info); + if (retval) + return retval; + + retval = block_til_ready(tty, filp, info); + if (retval) { + return retval; + } + + if ((info->count == 1) && (info->flags & S_SPLIT_TERMIOS)) { + if (tty->driver.subtype == SERIAL_TYPE_NORMAL) + *tty->termios = info->normal_termios; + else + *tty->termios = info->callout_termios; + change_speed(info); + } + + info->session = current->session; + info->pgrp = current->pgrp; + + return 0; +} + +/* Finally, routines used to initialize the serial driver. */ + +static void show_serial_version(void) +{ + printk("MC68328 serial driver version 1.00\n"); +} + +#ifdef CONFIG_PM +/* Serial Power management + * The console (currently fixed at line 0) is a special case for power + * management because the kernel is so chatty. The console will be + * explicitly disabled my our power manager as the last minute, so we won't + * mess with it here. + */ +static struct pm_dev *serial_pm[NR_PORTS]; + +static int serial_pm_callback(struct pm_dev *dev, pm_request_t request, void *data) +{ + struct m68k_serial *info = (struct m68k_serial *)dev->data; + + if(info == NULL) + return -1; + + /* special case for line 0 - pm restores it */ + if(info->line == 0) + return 0; + + switch (request) { + case PM_SUSPEND: + shutdown(info); + break; + + case PM_RESUME: + startup(info); + break; + } + return 0; +} + +void shutdown_console(void) +{ + struct m68k_serial *info = &m68k_soft[0]; + + /* HACK: wait a bit for any pending printk's to be dumped */ + { + int i = 10000; + while(i--); + } + + shutdown(info); +} + +void startup_console(void) +{ + struct m68k_serial *info = &m68k_soft[0]; + startup(info); +} +#endif + + +/* rs_init inits the driver */ +static int __init +rs68328_init(void) +{ + int flags, i; + struct m68k_serial *info; + + show_serial_version(); + + /* Initialize the tty_driver structure */ + /* SPARC: Not all of this is exactly right for us. */ + + memset(&serial_driver, 0, sizeof(struct tty_driver)); + serial_driver.magic = TTY_DRIVER_MAGIC; + serial_driver.name = "ttyS"; + serial_driver.major = TTY_MAJOR; + serial_driver.minor_start = 64; + serial_driver.num = NR_PORTS; + serial_driver.type = TTY_DRIVER_TYPE_SERIAL; + serial_driver.subtype = SERIAL_TYPE_NORMAL; + serial_driver.init_termios = tty_std_termios; + serial_driver.init_termios.c_cflag = + m68328_console_cbaud | CS8 | CREAD | HUPCL | CLOCAL; + serial_driver.flags = TTY_DRIVER_REAL_RAW; + serial_driver.refcount = &serial_refcount; + serial_driver.table = serial_table; + serial_driver.termios = serial_termios; + serial_driver.termios_locked = serial_termios_locked; + + serial_driver.open = rs_open; + serial_driver.close = rs_close; + serial_driver.write = rs_write; + serial_driver.flush_chars = rs_flush_chars; + serial_driver.write_room = rs_write_room; + serial_driver.chars_in_buffer = rs_chars_in_buffer; + serial_driver.flush_buffer = rs_flush_buffer; + serial_driver.ioctl = rs_ioctl; + serial_driver.throttle = rs_throttle; + serial_driver.unthrottle = rs_unthrottle; + serial_driver.set_termios = rs_set_termios; + serial_driver.stop = rs_stop; + serial_driver.start = rs_start; + serial_driver.hangup = rs_hangup; + serial_driver.set_ldisc = rs_set_ldisc; + + /* + * The callout device is just like normal device except for + * major number and the subtype code. + */ + callout_driver = serial_driver; + callout_driver.name = "cua"; + callout_driver.major = TTYAUX_MAJOR; + callout_driver.subtype = SERIAL_TYPE_CALLOUT; + + if (tty_register_driver(&serial_driver)) + panic("Couldn't register serial driver\n"); + if (tty_register_driver(&callout_driver)) + panic("Couldn't register callout driver\n"); + + save_flags(flags); cli(); + + for(i=0;imagic = SERIAL_MAGIC; + info->port = (int) &uart_addr[i]; + info->tty = 0; + info->irq = uart_irqs[i]; + info->custom_divisor = 16; + info->close_delay = 50; + info->closing_wait = 3000; + info->x_char = 0; + info->event = 0; + info->count = 0; + info->blocked_open = 0; + INIT_WORK(&info->tqueue, do_softint, info); + INIT_WORK(&info->tqueue_hangup, do_serial_hangup, info); + info->callout_termios =callout_driver.init_termios; + info->normal_termios = serial_driver.init_termios; + init_waitqueue_head(&info->open_wait); + init_waitqueue_head(&info->close_wait); + info->line = i; + info->is_cons = 1; /* Means shortcuts work */ + + printk("%s%d at 0x%08x (irq = %d)", serial_driver.name, info->line, + info->port, info->irq); + printk(" is a builtin MC68328 UART\n"); + + IRQ_ports[info->irq] = info; /* waste of space */ + +#ifdef CONFIG_M68VZ328 + if (i > 0 ) + PJSEL &= 0xCF; /* PSW enable second port output */ +#endif + + if (request_irq(uart_irqs[i], + rs_interrupt, + IRQ_FLG_STD, + "M68328_UART", NULL)) + panic("Unable to attach 68328 serial interrupt\n"); +#ifdef CONFIG_PM + serial_pm[i] = pm_register(PM_SYS_DEV, PM_SYS_COM, serial_pm_callback); + if (serial_pm[i]) + serial_pm[i]->data = info; +#endif + } + restore_flags(flags); + return 0; +} + + + +/* + * register_serial and unregister_serial allows for serial ports to be + * configured at run-time, to support PCMCIA modems. + */ +/* SPARC: Unused at this time, just here to make things link. */ +int register_serial(struct serial_struct *req) +{ + return -1; +} + +void unregister_serial(int line) +{ + return; +} + +module_init(rs68328_init); +/* DAVIDM module_exit(rs68328_fini); */ + + + +static void m68328_set_baud(void) +{ + unsigned short ustcnt; + int i; + + ustcnt = USTCNT; + USTCNT = ustcnt & ~USTCNT_TXEN; + +again: + for (i = 0; i < sizeof(baud_table) / sizeof(baud_table[0]); i++) + if (baud_table[i] == m68328_console_baud) + break; + if (i >= sizeof(baud_table) / sizeof(baud_table[0])) { + m68328_console_baud = 9600; + goto again; + } + + UBAUD = PUT_FIELD(UBAUD_DIVIDE, hw_baud_table[i].divisor) | + PUT_FIELD(UBAUD_PRESCALER, hw_baud_table[i].prescale); + ustcnt &= ~(USTCNT_PARITYEN | USTCNT_ODD_EVEN | USTCNT_STOP | USTCNT_8_7); + ustcnt |= USTCNT_8_7; + ustcnt |= USTCNT_TXEN; + USTCNT = ustcnt; + m68328_console_initted = 1; + return; +} + + +int m68328_console_setup(struct console *cp, char *arg) +{ + int i, n = CONSOLE_BAUD_RATE; + + if (!cp) + return(-1); + + if (arg) + n = simple_strtoul(arg,NULL,0); + + for (i = 0; i < BAUD_TABLE_SIZE; i++) + if (baud_table[i] == n) + break; + if (i < BAUD_TABLE_SIZE) { + m68328_console_baud = n; + m68328_console_cbaud = 0; + if (i > 15) { + m68328_console_cbaud |= CBAUDEX; + i -= 15; + } + m68328_console_cbaud |= i; + } + + m68328_set_baud(); /* make sure baud rate changes */ + return(0); +} + + +static kdev_t m68328_console_device(struct console *c) +{ + return mk_kdev(TTY_MAJOR, 64 + c->index); +} + + +void m68328_console_write (struct console *co, const char *str, + unsigned int count) +{ + if (!m68328_console_initted) + m68328_set_baud(); + while (count--) { + if (*str == '\n') + rs_put_char('\r'); + rs_put_char( *str++ ); + } +} + + +static struct console m68328_driver = { + name: "ttyS", + write: m68328_console_write, + device: m68328_console_device, + setup: m68328_console_setup, + flags: CON_PRINTBUFFER, + index: -1, +}; + + +void m68328_console_init(void) +{ + register_console(&m68328_driver); +} + diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/serial/68328serial.h linux.2.5.45-ac1/drivers/serial/68328serial.h --- linux.2.5.45/drivers/serial/68328serial.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/drivers/serial/68328serial.h 2002-10-31 15:05:46.000000000 +0000 @@ -0,0 +1,198 @@ +/* 68328serial.h: Definitions for the mc68328 serial driver. + * + * Copyright (C) 1995 David S. Miller + * Copyright (C) 1998 Kenneth Albanowski + * Copyright (C) 1998, 1999 D. Jeff Dionne + * Copyright (C) 1999 Vladimir Gurevich + * + * VZ Support/Fixes Evan Stawnyczy + */ + +#ifndef _MC683XX_SERIAL_H +#define _MC683XX_SERIAL_H + +#include + +struct serial_struct { + int type; + int line; + int port; + int irq; + int flags; + int xmit_fifo_size; + int custom_divisor; + int baud_base; + unsigned short close_delay; + char reserved_char[2]; + int hub6; /* FIXME: We don't have AT&T Hub6 boards! */ + unsigned short closing_wait; /* time to wait before closing */ + unsigned short closing_wait2; /* no longer used... */ + int reserved[4]; +}; + +/* + * For the close wait times, 0 means wait forever for serial port to + * flush its output. 65535 means don't wait at all. + */ +#define S_CLOSING_WAIT_INF 0 +#define S_CLOSING_WAIT_NONE 65535 + +/* + * Definitions for S_struct (and serial_struct) flags field + */ +#define S_HUP_NOTIFY 0x0001 /* Notify getty on hangups and closes + on the callout port */ +#define S_FOURPORT 0x0002 /* Set OU1, OUT2 per AST Fourport settings */ +#define S_SAK 0x0004 /* Secure Attention Key (Orange book) */ +#define S_SPLIT_TERMIOS 0x0008 /* Separate termios for dialin/callout */ + +#define S_SPD_MASK 0x0030 +#define S_SPD_HI 0x0010 /* Use 56000 instead of 38400 bps */ + +#define S_SPD_VHI 0x0020 /* Use 115200 instead of 38400 bps */ +#define S_SPD_CUST 0x0030 /* Use user-specified divisor */ + +#define S_SKIP_TEST 0x0040 /* Skip UART test during autoconfiguration */ +#define S_AUTO_IRQ 0x0080 /* Do automatic IRQ during autoconfiguration */ +#define S_SESSION_LOCKOUT 0x0100 /* Lock out cua opens based on session */ +#define S_PGRP_LOCKOUT 0x0200 /* Lock out cua opens based on pgrp */ +#define S_CALLOUT_NOHUP 0x0400 /* Don't do hangups for cua device */ + +#define S_FLAGS 0x0FFF /* Possible legal S flags */ +#define S_USR_MASK 0x0430 /* Legal flags that non-privileged + * users can set or reset */ + +/* Internal flags used only by kernel/chr_drv/serial.c */ +#define S_INITIALIZED 0x80000000 /* Serial port was initialized */ +#define S_CALLOUT_ACTIVE 0x40000000 /* Call out device is active */ +#define S_NORMAL_ACTIVE 0x20000000 /* Normal device is active */ +#define S_BOOT_AUTOCONF 0x10000000 /* Autoconfigure port on bootup */ +#define S_CLOSING 0x08000000 /* Serial port is closing */ +#define S_CTS_FLOW 0x04000000 /* Do CTS flow control */ +#define S_CHECK_CD 0x02000000 /* i.e., CLOCAL */ + +/* Software state per channel */ + +#ifdef __KERNEL__ + +/* + * I believe this is the optimal setting that reduces the number of interrupts. + * At high speeds the output might become a little "bursted" (use USTCNT_TXHE + * if that bothers you), but in most cases it will not, since we try to + * transmit characters every time rs_interrupt is called. Thus, quite often + * you'll see that a receive interrupt occures before the transmit one. + * -- Vladimir Gurevich + */ +#define USTCNT_TX_INTR_MASK (USTCNT_TXEE) + +/* + * 68328 and 68EZ328 UARTS are a little bit different. EZ328 has special + * "Old data interrupt" which occures whenever the data stay in the FIFO + * longer than 30 bits time. This allows us to use FIFO without compromising + * latency. '328 does not have this feature and without the real 328-based + * board I would assume that RXRE is the safest setting. + * + * For EZ328 I use RXHE (Half empty) interrupt to reduce the number of + * interrupts. RXFE (receive queue full) causes the system to loose data + * at least at 115200 baud + * + * If your board is busy doing other stuff, you might consider to use + * RXRE (data ready intrrupt) instead. + * + * The other option is to make these INTR masks run-time configurable, so + * that people can dynamically adapt them according to the current usage. + * -- Vladimir Gurevich + */ + +/* (es) */ +#if defined(CONFIG_M68EZ328) || defined(CONFIG_M68VZ328) +#define USTCNT_RX_INTR_MASK (USTCNT_RXHE | USTCNT_ODEN) +#elif defined(CONFIG_M68328) +#define USTCNT_RX_INTR_MASK (USTCNT_RXRE) +#else +#error Please, define the Rx interrupt events for your CPU +#endif +/* (/es) */ + +/* + * This is our internal structure for each serial port's state. + * + * Many fields are paralleled by the structure used by the serial_struct + * structure. + * + * For definitions of the flags field, see tty.h + */ + +struct m68k_serial { + char soft_carrier; /* Use soft carrier on this channel */ + char break_abort; /* Is serial console in, so process brk/abrt */ + char is_cons; /* Is this our console. */ + + /* We need to know the current clock divisor + * to read the bps rate the chip has currently + * loaded. + */ + unsigned char clk_divisor; /* May be 1, 16, 32, or 64 */ + int baud; + int magic; + int baud_base; + int port; + int irq; + int flags; /* defined in tty.h */ + int type; /* UART type */ + struct tty_struct *tty; + int read_status_mask; + int ignore_status_mask; + int timeout; + int xmit_fifo_size; + int custom_divisor; + int x_char; /* xon/xoff character */ + int close_delay; + unsigned short closing_wait; + unsigned short closing_wait2; + unsigned long event; + unsigned long last_active; + int line; + int count; /* # of fd on device */ + int blocked_open; /* # of blocked opens */ + long session; /* Session of opening process */ + long pgrp; /* pgrp of opening process */ + unsigned char *xmit_buf; + int xmit_head; + int xmit_tail; + int xmit_cnt; + struct workqueue tqueue; + struct workqueue tqueue_hangup; + struct termios normal_termios; + struct termios callout_termios; + wait_queue_head_t open_wait; + wait_queue_head_t close_wait; +}; + + +#define SERIAL_MAGIC 0x5301 + +/* + * The size of the serial xmit buffer is 1 page, or 4096 bytes + */ +#define SERIAL_XMIT_SIZE 4096 + +/* + * Events are used to schedule things to happen at timer-interrupt + * time, instead of at rs interrupt time. + */ +#define RS_EVENT_WRITE_WAKEUP 0 + +/* + * Define the number of ports supported and their irqs. + */ +#ifndef CONFIG_68328_SERIAL_UART2 +#define NR_PORTS 1 +#define UART_IRQ_DEFNS {UART_IRQ_NUM} +#else +#define NR_PORTS 2 +#define UART_IRQ_DEFNS {UART1_IRQ_NUM, UART2_IRQ_NUM} +#endif + +#endif /* __KERNEL__ */ +#endif /* !(_MC683XX_SERIAL_H) */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/serial/68360serial.c linux.2.5.45-ac1/drivers/serial/68360serial.c --- linux.2.5.45/drivers/serial/68360serial.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/drivers/serial/68360serial.c 2002-10-31 15:05:46.000000000 +0000 @@ -0,0 +1,3197 @@ +/* + * UART driver for 68360 CPM SCC or SMC + * Copyright (c) 2000 D. Jeff Dionne , + * Copyright (c) 2000 Michael Leslie + * Copyright (c) 1997 Dan Malek + * + * I used the serial.c driver as the framework for this driver. + * Give credit to those guys. + * The original code was written for the MBX860 board. I tried to make + * it generic, but there may be some assumptions in the structures that + * have to be fixed later. + * To save porting time, I did not bother to change any object names + * that are not accessed outside of this file. + * It still needs lots of work........When it was easy, I included code + * to support the SCCs, but this has never been tested, nor is it complete. + * Only the SCCs support modem control, so that is not complete either. + * + * This module exports the following rs232 io functions: + * + * int rs_360_init(void); + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#ifdef CONFIG_KGDB +extern void breakpoint(void); +extern void set_debug_traps(void); +extern int kgdb_output_string (const char* s, unsigned int count); +#endif + + +/* #ifdef CONFIG_SERIAL_CONSOLE */ /* This seems to be a post 2.0 thing - mles */ +#include + +/* this defines the index into rs_table for the port to use + */ +#ifndef CONFIG_SERIAL_CONSOLE_PORT +#define CONFIG_SERIAL_CONSOLE_PORT 1 /* ie SMC2 - note USE_SMC2 must be defined */ +#endif +/* #endif */ + +#if 0 +/* SCC2 for console + */ +#undef CONFIG_SERIAL_CONSOLE_PORT +#define CONFIG_SERIAL_CONSOLE_PORT 2 +#endif + + +#define TX_WAKEUP ASYNC_SHARE_IRQ + +static char *serial_name = "CPM UART driver"; +static char *serial_version = "0.03"; + +static DECLARE_TASK_QUEUE(tq_serial); + +static struct tty_driver serial_driver, callout_driver; +static int serial_refcount; +int serial_console_setup(struct console *co, char *options); + +/* + * Serial driver configuration section. Here are the various options: + */ +#define SERIAL_PARANOIA_CHECK +#define CONFIG_SERIAL_NOPAUSE_IO +#define SERIAL_DO_RESTART + +/* Set of debugging defines */ + +#undef SERIAL_DEBUG_INTR +#undef SERIAL_DEBUG_OPEN +#undef SERIAL_DEBUG_FLOW +#undef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT + +#define _INLINE_ inline + +#define DBG_CNT(s) + +/* We overload some of the items in the data structure to meet our + * needs. For example, the port address is the CPM parameter ram + * offset for the SCC or SMC. The maximum number of ports is 4 SCCs and + * 2 SMCs. The "hub6" field is used to indicate the channel number, with + * a flag indicating SCC or SMC, and the number is used as an index into + * the CPM parameter area for this device. + * The "type" field is currently set to 0, for PORT_UNKNOWN. It is + * not currently used. I should probably use it to indicate the port + * type of SMC or SCC. + * The SMCs do not support any modem control signals. + */ +#define smc_scc_num hub6 +#define NUM_IS_SCC ((int)0x00010000) +#define PORT_NUM(P) ((P) & 0x0000ffff) + + +#if defined (CONFIG_UCQUICC) + +volatile extern void *_periph_base; +/* sipex transceiver + * mode bits for are on pins + * + * SCC2 d16..19 + * SCC3 d20..23 + * SCC4 d24..27 + */ +#define SIPEX_MODE(n,m) ((m & 0x0f)<<(16+4*(n-1))) + +static uint sipex_mode_bits = 0x00000000; + +#endif + +/* There is no `serial_state' defined back here in 2.0. + * Try to get by with serial_struct + */ +/* #define serial_state serial_struct */ + +/* 2.4 -> 2.0 portability problem: async_icount in 2.4 has a few + * extras: */ + +#if 0 +struct async_icount_24 { + __u32 cts, dsr, rng, dcd, tx, rx; + __u32 frame, parity, overrun, brk; + __u32 buf_overrun; +} icount; +#endif + +#if 0 + +struct serial_state { + int magic; + int baud_base; + unsigned long port; + int irq; + int flags; + int hub6; + int type; + int line; + int revision; /* Chip revision (950) */ + int xmit_fifo_size; + int custom_divisor; + int count; + u8 *iomem_base; + u16 iomem_reg_shift; + unsigned short close_delay; + unsigned short closing_wait; /* time to wait before closing */ + struct async_icount_24 icount; + struct termios normal_termios; + struct termios callout_termios; + int io_type; + struct async_struct *info; +}; +#endif + +#define SSTATE_MAGIC 0x5302 + + + +/* SMC2 is sometimes used for low performance TDM interfaces. Define + * this as 1 if you want SMC2 as a serial port UART managed by this driver. + * Define this as 0 if you wish to use SMC2 for something else. + */ +#define USE_SMC2 1 + +#if 0 +/* Define SCC to ttySx mapping. */ +#define SCC_NUM_BASE (USE_SMC2 + 1) /* SCC base tty "number" */ + +/* Define which SCC is the first one to use for a serial port. These + * are 0-based numbers, i.e. this assumes the first SCC (SCC1) is used + * for Ethernet, and the first available SCC for serial UART is SCC2. + * NOTE: IF YOU CHANGE THIS, you have to change the PROFF_xxx and + * interrupt vectors in the table below to match. + */ +#define SCC_IDX_BASE 1 /* table index */ +#endif + + +/* Processors other than the 860 only get SMCs configured by default. + * Either they don't have SCCs or they are allocated somewhere else. + * Of course, there are now 860s without some SCCs, so we will need to + * address that someday. + * The Embedded Planet Multimedia I/O cards use TDM interfaces to the + * stereo codec parts, and we use SMC2 to help support that. + */ +static struct serial_state rs_table[] = { +/* type line PORT IRQ FLAGS smc_scc_num (F.K.A. hub6) */ + { 0, 0, PRSLOT_SMC1, CPMVEC_SMC1, 0, 0 } /* SMC1 ttyS0 */ +#if USE_SMC2 + ,{ 0, 0, PRSLOT_SMC2, CPMVEC_SMC2, 0, 1 } /* SMC2 ttyS1 */ +#endif + +#if defined(CONFIG_SERIAL_68360_SCC) + ,{ 0, 0, PRSLOT_SCC2, CPMVEC_SCC2, 0, (NUM_IS_SCC | 1) } /* SCC2 ttyS2 */ + ,{ 0, 0, PRSLOT_SCC3, CPMVEC_SCC3, 0, (NUM_IS_SCC | 2) } /* SCC3 ttyS3 */ + ,{ 0, 0, PRSLOT_SCC4, CPMVEC_SCC4, 0, (NUM_IS_SCC | 3) } /* SCC4 ttyS4 */ +#endif +}; + +#define NR_PORTS (sizeof(rs_table)/sizeof(struct serial_state)) + +static struct tty_struct *serial_table[NR_PORTS]; +static struct termios *serial_termios[NR_PORTS]; +static struct termios *serial_termios_locked[NR_PORTS]; + +/* The number of buffer descriptors and their sizes. + */ +#define RX_NUM_FIFO 4 +#define RX_BUF_SIZE 32 +#define TX_NUM_FIFO 4 +#define TX_BUF_SIZE 32 + +#define CONSOLE_NUM_FIFO 2 +#define CONSOLE_BUF_SIZE 4 + +char *console_fifos[CONSOLE_NUM_FIFO * CONSOLE_BUF_SIZE]; + +/* The async_struct in serial.h does not really give us what we + * need, so define our own here. + */ +typedef struct serial_info { + int magic; + int flags; + + struct serial_state *state; + /* struct serial_struct *state; */ + /* struct async_struct *state; */ + + struct tty_struct *tty; + int read_status_mask; + int ignore_status_mask; + int timeout; + int line; + int x_char; /* xon/xoff character */ + int close_delay; + unsigned short closing_wait; + unsigned short closing_wait2; + unsigned long event; + unsigned long last_active; + int blocked_open; /* # of blocked opens */ + long session; /* Session of opening process */ + long pgrp; /* pgrp of opening process */ + struct tq_struct tqueue; + struct tq_struct tqueue_hangup; + wait_queue_head_t open_wait; + wait_queue_head_t close_wait; +/* struct wait_queue *open_wait; */ +/* struct wait_queue *close_wait;i */ + + +/* CPM Buffer Descriptor pointers. + */ + QUICC_BD *rx_bd_base; + QUICC_BD *rx_cur; + QUICC_BD *tx_bd_base; + QUICC_BD *tx_cur; +} ser_info_t; + + +/* since kmalloc_init() does not get called until much after this initialization: */ +static ser_info_t quicc_ser_info[NR_PORTS]; +static char rx_buf_pool[NR_PORTS * RX_NUM_FIFO * RX_BUF_SIZE]; +static char tx_buf_pool[NR_PORTS * TX_NUM_FIFO * TX_BUF_SIZE]; + +static void change_speed(ser_info_t *info); +static void rs_360_wait_until_sent(struct tty_struct *tty, int timeout); + +static inline int serial_paranoia_check(ser_info_t *info, + kdev_t device, const char *routine) +{ +#ifdef SERIAL_PARANOIA_CHECK + static const char *badmagic = + "Warning: bad magic number for serial struct (%s) in %s\n"; + static const char *badinfo = + "Warning: null async_struct for (%s) in %s\n"; + + if (!info) { + printk(badinfo, kdevname(device), routine); + return 1; + } + if (info->magic != SERIAL_MAGIC) { + printk(badmagic, kdevname(device), routine); + return 1; + } +#endif + return 0; +} + +/* + * This is used to figure out the divisor speeds and the timeouts, + * indexed by the termio value. The generic CPM functions are responsible + * for setting and assigning baud rate generators for us. + */ +static int baud_table[] = { + 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, + 9600, 19200, 38400, 57600, 115200, 230400, 460800, 0 }; + +/* This sucks. There is a better way: */ +#if defined(CONFIG_CONSOLE_9600) + #define CONSOLE_BAUDRATE 9600 +#elif defined(CONFIG_CONSOLE_19200) + #define CONSOLE_BAUDRATE 19200 +#elif defined(CONFIG_CONSOLE_115200) + #define CONSOLE_BAUDRATE 115200 +#else +#error "console baud rate undefined" +#endif + +/* + * ------------------------------------------------------------ + * rs_stop() and rs_start() + * + * This routines are called before setting or resetting tty->stopped. + * They enable or disable transmitter interrupts, as necessary. + * ------------------------------------------------------------ + */ +static void rs_360_stop(struct tty_struct *tty) +{ + ser_info_t *info = (ser_info_t *)tty->driver_data; + int idx; + unsigned long flags; + volatile struct scc_regs *sccp; + volatile struct smc_regs *smcp; + + if (serial_paranoia_check(info, tty->device, "rs_stop")) + return; + + local_irq_save(flags); + idx = PORT_NUM(info->state->smc_scc_num); + if (info->state->smc_scc_num & NUM_IS_SCC) { + sccp = &pquicc->scc_regs[idx]; + sccp->scc_sccm &= ~UART_SCCM_TX; + } else { + /* smcp = &cpmp->cp_smc[idx]; */ + smcp = &pquicc->smc_regs[idx]; + smcp->smc_smcm &= ~SMCM_TX; + } + local_irq_restore(flags); +} + + +static void rs_360_start(struct tty_struct *tty) +{ + ser_info_t *info = (ser_info_t *)tty->driver_data; + int idx; + unsigned long flags; + volatile struct scc_regs *sccp; + volatile struct smc_regs *smcp; + + if (serial_paranoia_check(info, tty->device, "rs_stop")) + return; + + local_irq_save(flags); + idx = PORT_NUM(info->state->smc_scc_num); + if (info->state->smc_scc_num & NUM_IS_SCC) { + sccp = &pquicc->scc_regs[idx]; + sccp->scc_sccm |= UART_SCCM_TX; + } else { + smcp = &pquicc->smc_regs[idx]; + smcp->smc_smcm |= SMCM_TX; + } + local_irq_restore(flags); +} + +/* + * ---------------------------------------------------------------------- + * + * Here starts the interrupt handling routines. All of the following + * subroutines are declared as inline and are folded into + * rs_interrupt(). They were separated out for readability's sake. + * + * Note: rs_interrupt() is a "fast" interrupt, which means that it + * runs with interrupts turned off. People who may want to modify + * rs_interrupt() should try to keep the interrupt handler as fast as + * possible. After you are done making modifications, it is not a bad + * idea to do: + * + * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer serial.c + * + * and look at the resulting assemble code in serial.s. + * + * - Ted Ts'o (tytso@mit.edu), 7-Mar-93 + * ----------------------------------------------------------------------- + */ + +/* + * This routine is used by the interrupt handler to schedule + * processing in the software interrupt portion of the driver. + */ +static _INLINE_ void rs_sched_event(ser_info_t *info, + int event) +{ + info->event |= 1 << event; + queue_task(&info->tqueue, &tq_serial); + mark_bh(SERIAL_BH); +} + +static _INLINE_ void receive_chars(ser_info_t *info) +{ + struct tty_struct *tty = info->tty; + unsigned char ch, *cp; + /*int ignored = 0;*/ + int i; + ushort status; + struct async_icount *icount; + /* struct async_icount_24 *icount; */ + volatile QUICC_BD *bdp; + + icount = &info->state->icount; + + /* Just loop through the closed BDs and copy the characters into + * the buffer. + */ + bdp = info->rx_cur; + for (;;) { + if (bdp->status & BD_SC_EMPTY) /* If this one is empty */ + break; /* we are all done */ + + /* The read status mask tell us what we should do with + * incoming characters, especially if errors occur. + * One special case is the use of BD_SC_EMPTY. If + * this is not set, we are supposed to be ignoring + * inputs. In this case, just mark the buffer empty and + * continue. + */ + if (!(info->read_status_mask & BD_SC_EMPTY)) { + bdp->status |= BD_SC_EMPTY; + bdp->status &= + ~(BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV); + + if (bdp->status & BD_SC_WRAP) + bdp = info->rx_bd_base; + else + bdp++; + continue; + } + + /* Get the number of characters and the buffer pointer. + */ + i = bdp->length; + /* cp = (unsigned char *)__va(bdp->buf); */ + cp = (char *)bdp->buf; + status = bdp->status; + + /* Check to see if there is room in the tty buffer for + * the characters in our BD buffer. If not, we exit + * now, leaving the BD with the characters. We'll pick + * them up again on the next receive interrupt (which could + * be a timeout). + */ + if ((tty->flip.count + i) >= TTY_FLIPBUF_SIZE) + break; + + while (i-- > 0) { + ch = *cp++; + *tty->flip.char_buf_ptr = ch; + icount->rx++; + +#ifdef SERIAL_DEBUG_INTR + printk("DR%02x:%02x...", ch, status); +#endif + *tty->flip.flag_buf_ptr = 0; + if (status & (BD_SC_BR | BD_SC_FR | + BD_SC_PR | BD_SC_OV)) { + /* + * For statistics only + */ + if (status & BD_SC_BR) + icount->brk++; + else if (status & BD_SC_PR) + icount->parity++; + else if (status & BD_SC_FR) + icount->frame++; + if (status & BD_SC_OV) + icount->overrun++; + + /* + * Now check to see if character should be + * ignored, and mask off conditions which + * should be ignored. + if (status & info->ignore_status_mask) { + if (++ignored > 100) + break; + continue; + } + */ + status &= info->read_status_mask; + + if (status & (BD_SC_BR)) { +#ifdef SERIAL_DEBUG_INTR + printk("handling break...."); +#endif + *tty->flip.flag_buf_ptr = TTY_BREAK; + if (info->flags & ASYNC_SAK) + do_SAK(tty); + } else if (status & BD_SC_PR) + *tty->flip.flag_buf_ptr = TTY_PARITY; + else if (status & BD_SC_FR) + *tty->flip.flag_buf_ptr = TTY_FRAME; + if (status & BD_SC_OV) { + /* + * Overrun is special, since it's + * reported immediately, and doesn't + * affect the current character + */ + if (tty->flip.count < TTY_FLIPBUF_SIZE) { + tty->flip.count++; + tty->flip.flag_buf_ptr++; + tty->flip.char_buf_ptr++; + *tty->flip.flag_buf_ptr = + TTY_OVERRUN; + } + } + } + if (tty->flip.count >= TTY_FLIPBUF_SIZE) + break; + + tty->flip.flag_buf_ptr++; + tty->flip.char_buf_ptr++; + tty->flip.count++; + } + + /* This BD is ready to be used again. Clear status. + * Get next BD. + */ + bdp->status |= BD_SC_EMPTY; + bdp->status &= ~(BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV); + + if (bdp->status & BD_SC_WRAP) + bdp = info->rx_bd_base; + else + bdp++; + } + + info->rx_cur = (QUICC_BD *)bdp; + + queue_task(&tty->flip.tqueue, &tq_timer); +} + +static _INLINE_ void receive_break(ser_info_t *info) +{ + struct tty_struct *tty = info->tty; + + info->state->icount.brk++; + /* Check to see if there is room in the tty buffer for + * the break. If not, we exit now, losing the break. FIXME + */ + if ((tty->flip.count + 1) >= TTY_FLIPBUF_SIZE) + return; + *(tty->flip.flag_buf_ptr++) = TTY_BREAK; + *(tty->flip.char_buf_ptr++) = 0; + tty->flip.count++; + + queue_task(&tty->flip.tqueue, &tq_timer); +} + +static _INLINE_ void transmit_chars(ser_info_t *info) +{ + + if ((info->flags & TX_WAKEUP) || + (info->tty->flags & (1 << TTY_DO_WRITE_WAKEUP))) { + rs_sched_event(info, RS_EVENT_WRITE_WAKEUP); + } + +#ifdef SERIAL_DEBUG_INTR + printk("THRE..."); +#endif +} + +#ifdef notdef + /* I need to do this for the SCCs, so it is left as a reminder. + */ +static _INLINE_ void check_modem_status(struct async_struct *info) +{ + int status; + /* struct async_icount *icount; */ + struct async_icount_24 *icount; + + status = serial_in(info, UART_MSR); + + if (status & UART_MSR_ANY_DELTA) { + icount = &info->state->icount; + /* update input line counters */ + if (status & UART_MSR_TERI) + icount->rng++; + if (status & UART_MSR_DDSR) + icount->dsr++; + if (status & UART_MSR_DDCD) { + icount->dcd++; +#ifdef CONFIG_HARD_PPS + if ((info->flags & ASYNC_HARDPPS_CD) && + (status & UART_MSR_DCD)) + hardpps(); +#endif + } + if (status & UART_MSR_DCTS) + icount->cts++; + wake_up_interruptible(&info->delta_msr_wait); + } + + if ((info->flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) { +#if (defined(SERIAL_DEBUG_OPEN) || defined(SERIAL_DEBUG_INTR)) + printk("ttys%d CD now %s...", info->line, + (status & UART_MSR_DCD) ? "on" : "off"); +#endif + if (status & UART_MSR_DCD) + wake_up_interruptible(&info->open_wait); + else if (!((info->flags & ASYNC_CALLOUT_ACTIVE) && + (info->flags & ASYNC_CALLOUT_NOHUP))) { +#ifdef SERIAL_DEBUG_OPEN + printk("scheduling hangup..."); +#endif + queue_task(&info->tqueue_hangup, + &tq_scheduler); + } + } + if (info->flags & ASYNC_CTS_FLOW) { + if (info->tty->hw_stopped) { + if (status & UART_MSR_CTS) { +#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW)) + printk("CTS tx start..."); +#endif + info->tty->hw_stopped = 0; + info->IER |= UART_IER_THRI; + serial_out(info, UART_IER, info->IER); + rs_sched_event(info, RS_EVENT_WRITE_WAKEUP); + return; + } + } else { + if (!(status & UART_MSR_CTS)) { +#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW)) + printk("CTS tx stop..."); +#endif + info->tty->hw_stopped = 1; + info->IER &= ~UART_IER_THRI; + serial_out(info, UART_IER, info->IER); + } + } + } +} +#endif + +/* + * This is the serial driver's interrupt routine for a single port + */ +/* static void rs_360_interrupt(void *dev_id) */ /* until and if we start servicing irqs here */ +static void rs_360_interrupt(int vec, void *dev_id, struct pt_regs *fp) +{ + u_char events; + int idx; + ser_info_t *info; + volatile struct smc_regs *smcp; + volatile struct scc_regs *sccp; + + info = (ser_info_t *)dev_id; + + idx = PORT_NUM(info->state->smc_scc_num); + if (info->state->smc_scc_num & NUM_IS_SCC) { + sccp = &pquicc->scc_regs[idx]; + events = sccp->scc_scce; + if (events & SCCM_RX) + receive_chars(info); + if (events & SCCM_TX) + transmit_chars(info); + sccp->scc_scce = events; + } else { + smcp = &pquicc->smc_regs[idx]; + events = smcp->smc_smce; + if (events & SMCM_BRKE) + receive_break(info); + if (events & SMCM_RX) + receive_chars(info); + if (events & SMCM_TX) + transmit_chars(info); + smcp->smc_smce = events; + } + +#ifdef SERIAL_DEBUG_INTR + printk("rs_interrupt_single(%d, %x)...", + info->state->smc_scc_num, events); +#endif +#ifdef modem_control + check_modem_status(info); +#endif + info->last_active = jiffies; +#ifdef SERIAL_DEBUG_INTR + printk("end.\n"); +#endif +} + + +/* + * ------------------------------------------------------------------- + * Here ends the serial interrupt routines. + * ------------------------------------------------------------------- + */ + +/* + * This routine is used to handle the "bottom half" processing for the + * serial driver, known also the "software interrupt" processing. + * This processing is done at the kernel interrupt level, after the + * rs_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON. This + * is where time-consuming activities which can not be done in the + * interrupt driver proper are done; the interrupt driver schedules + * them using rs_sched_event(), and they get done here. + */ +static void do_serial_bh(void) +{ + run_task_queue(&tq_serial); +} + +static void do_softint(void *private_) +{ + ser_info_t *info = (ser_info_t *) private_; + struct tty_struct *tty; + + tty = info->tty; + if (!tty) + return; + + if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) { + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + tty->ldisc.write_wakeup) + (tty->ldisc.write_wakeup)(tty); + wake_up_interruptible(&tty->write_wait); + } +} + + + + +/* + * This routine is called from the scheduler tqueue when the interrupt + * routine has signalled that a hangup has occurred. The path of + * hangup processing is: + * + * serial interrupt routine -> (scheduler tqueue) -> + * do_serial_hangup() -> tty->hangup() -> rs_hangup() + * + */ +static void do_serial_hangup(void *private_) +{ + struct async_struct *info = (struct async_struct *) private_; + struct tty_struct *tty; + + tty = info->tty; + if (!tty) + return; + + tty_hangup(tty); +} + +/*static void rs_360_timer(void) +{ + printk("rs_360_timer\n"); +}*/ + + +static int startup(ser_info_t *info) +{ + unsigned long flags; + int retval=0; + int idx; + /*struct serial_state *state = info->state;*/ + volatile struct smc_regs *smcp; + volatile struct scc_regs *sccp; + volatile struct smc_uart_pram *up; + volatile struct uart_pram *scup; + + + local_irq_save(flags); + + if (info->flags & ASYNC_INITIALIZED) { + goto errout; + } + +#ifdef maybe + if (!state->port || !state->type) { + if (info->tty) + set_bit(TTY_IO_ERROR, &info->tty->flags); + goto errout; + } +#endif + +#ifdef SERIAL_DEBUG_OPEN + printk("starting up ttys%d (irq %d)...", info->line, state->irq); +#endif + + +#ifdef modem_control + info->MCR = 0; + if (info->tty->termios->c_cflag & CBAUD) + info->MCR = UART_MCR_DTR | UART_MCR_RTS; +#endif + + if (info->tty) + clear_bit(TTY_IO_ERROR, &info->tty->flags); + + /* + * and set the speed of the serial port + */ + change_speed(info); + + idx = PORT_NUM(info->state->smc_scc_num); + if (info->state->smc_scc_num & NUM_IS_SCC) { + sccp = &pquicc->scc_regs[idx]; + scup = &pquicc->pram[info->state->port].scc.pscc.u; + + scup->mrblr = RX_BUF_SIZE; + scup->max_idl = RX_BUF_SIZE; + + sccp->scc_sccm |= (UART_SCCM_TX | UART_SCCM_RX); + sccp->scc_gsmr.w.low |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT); + + } else { + smcp = &pquicc->smc_regs[idx]; + + /* Enable interrupts and I/O. + */ + smcp->smc_smcm |= (SMCM_RX | SMCM_TX); + smcp->smc_smcmr |= (SMCMR_REN | SMCMR_TEN); + + /* We can tune the buffer length and idle characters + * to take advantage of the entire incoming buffer size. + * If mrblr is something other than 1, maxidl has to be + * non-zero or we never get an interrupt. The maxidl + * is the number of character times we wait after reception + * of the last character before we decide no more characters + * are coming. + */ + /* up = (smc_uart_t *)&pquicc->cp_dparam[state->port]; */ + /* holy unionized structures, Batman: */ + up = &pquicc->pram[info->state->port].scc.pothers.idma_smc.psmc.u; + + up->mrblr = RX_BUF_SIZE; + up->max_idl = RX_BUF_SIZE; + + up->brkcr = 1; /* number of break chars */ + } + + info->flags |= ASYNC_INITIALIZED; + local_irq_restore(flags); + return 0; + +errout: + local_irq_restore(flags); + return retval; +} + +/* + * This routine will shutdown a serial port; interrupts are disabled, and + * DTR is dropped if the hangup on close termio flag is on. + */ +static void shutdown(ser_info_t *info) +{ + unsigned long flags; + struct serial_state *state; + int idx; + volatile struct smc_regs *smcp; + volatile struct scc_regs *sccp; + + if (!(info->flags & ASYNC_INITIALIZED)) + return; + + state = info->state; + +#ifdef SERIAL_DEBUG_OPEN + printk("Shutting down serial port %d (irq %d)....", info->line, + state->irq); +#endif + + local_irq_save(flags); + + idx = PORT_NUM(state->smc_scc_num); + if (state->smc_scc_num & NUM_IS_SCC) { + sccp = &pquicc->scc_regs[idx]; + sccp->scc_gsmr.w.low &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT); +#ifdef CONFIG_SERIAL_CONSOLE + /* We can't disable the transmitter if this is the + * system console. + */ + if ((state - rs_table) != CONFIG_SERIAL_CONSOLE_PORT) +#endif + sccp->scc_sccm &= ~(UART_SCCM_TX | UART_SCCM_RX); + } else { + smcp = &pquicc->smc_regs[idx]; + + /* Disable interrupts and I/O. + */ + smcp->smc_smcm &= ~(SMCM_RX | SMCM_TX); +#ifdef CONFIG_SERIAL_CONSOLE + /* We can't disable the transmitter if this is the + * system console. + */ + if ((state - rs_table) != CONFIG_SERIAL_CONSOLE_PORT) +#endif + smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN); + } + + if (info->tty) + set_bit(TTY_IO_ERROR, &info->tty->flags); + + info->flags &= ~ASYNC_INITIALIZED; + local_irq_restore(flags); +} + +/* + * This routine is called to set the UART divisor registers to match + * the specified baud rate for a serial port. + */ +static void change_speed(ser_info_t *info) +{ + int baud_rate; + unsigned cflag, cval, scval, prev_mode; + int i, bits, sbits, idx; + unsigned long flags; + struct serial_state *state; + volatile struct smc_regs *smcp; + volatile struct scc_regs *sccp; + + if (!info->tty || !info->tty->termios) + return; + cflag = info->tty->termios->c_cflag; + + state = info->state; + + /* Character length programmed into the mode register is the + * sum of: 1 start bit, number of data bits, 0 or 1 parity bit, + * 1 or 2 stop bits, minus 1. + * The value 'bits' counts this for us. + */ + cval = 0; + scval = 0; + + /* byte size and parity */ + switch (cflag & CSIZE) { + case CS5: bits = 5; break; + case CS6: bits = 6; break; + case CS7: bits = 7; break; + case CS8: bits = 8; break; + /* Never happens, but GCC is too dumb to figure it out */ + default: bits = 8; break; + } + sbits = bits - 5; + + if (cflag & CSTOPB) { + cval |= SMCMR_SL; /* Two stops */ + scval |= SCU_PMSR_SL; + bits++; + } + if (cflag & PARENB) { + cval |= SMCMR_PEN; + scval |= SCU_PMSR_PEN; + bits++; + } + if (!(cflag & PARODD)) { + cval |= SMCMR_PM_EVEN; + scval |= (SCU_PMSR_REVP | SCU_PMSR_TEVP); + } + + /* Determine divisor based on baud rate */ + i = cflag & CBAUD; + if (i >= (sizeof(baud_table)/sizeof(int))) + baud_rate = 9600; + else + baud_rate = baud_table[i]; + + info->timeout = (TX_BUF_SIZE*HZ*bits); + info->timeout += HZ/50; /* Add .02 seconds of slop */ + +#ifdef modem_control + /* CTS flow control flag and modem status interrupts */ + info->IER &= ~UART_IER_MSI; + if (info->flags & ASYNC_HARDPPS_CD) + info->IER |= UART_IER_MSI; + if (cflag & CRTSCTS) { + info->flags |= ASYNC_CTS_FLOW; + info->IER |= UART_IER_MSI; + } else + info->flags &= ~ASYNC_CTS_FLOW; + if (cflag & CLOCAL) + info->flags &= ~ASYNC_CHECK_CD; + else { + info->flags |= ASYNC_CHECK_CD; + info->IER |= UART_IER_MSI; + } + serial_out(info, UART_IER, info->IER); +#endif + + /* + * Set up parity check flag + */ +#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) + + info->read_status_mask = (BD_SC_EMPTY | BD_SC_OV); + if (I_INPCK(info->tty)) + info->read_status_mask |= BD_SC_FR | BD_SC_PR; + if (I_BRKINT(info->tty) || I_PARMRK(info->tty)) + info->read_status_mask |= BD_SC_BR; + + /* + * Characters to ignore + */ + info->ignore_status_mask = 0; + if (I_IGNPAR(info->tty)) + info->ignore_status_mask |= BD_SC_PR | BD_SC_FR; + if (I_IGNBRK(info->tty)) { + info->ignore_status_mask |= BD_SC_BR; + /* + * If we're ignore parity and break indicators, ignore + * overruns too. (For real raw support). + */ + if (I_IGNPAR(info->tty)) + info->ignore_status_mask |= BD_SC_OV; + } + /* + * !!! ignore all characters if CREAD is not set + */ + if ((cflag & CREAD) == 0) + info->read_status_mask &= ~BD_SC_EMPTY; + local_irq_save(flags); + + /* Start bit has not been added (so don't, because we would just + * subtract it later), and we need to add one for the number of + * stops bits (there is always at least one). + */ + bits++; + idx = PORT_NUM(state->smc_scc_num); + if (state->smc_scc_num & NUM_IS_SCC) { + sccp = &pquicc->scc_regs[idx]; + sccp->scc_psmr = (sbits << 12) | scval; + } else { + smcp = &pquicc->smc_regs[idx]; + + /* Set the mode register. We want to keep a copy of the + * enables, because we want to put them back if they were + * present. + */ + prev_mode = smcp->smc_smcmr; + smcp->smc_smcmr = smcr_mk_clen(bits) | cval | SMCMR_SM_UART; + smcp->smc_smcmr |= (prev_mode & (SMCMR_REN | SMCMR_TEN)); + } + + m360_cpm_setbrg((state - rs_table), baud_rate); + + local_irq_restore(flags); +} + +static void rs_360_put_char(struct tty_struct *tty, unsigned char ch) +{ + ser_info_t *info = (ser_info_t *)tty->driver_data; + volatile QUICC_BD *bdp; + + if (serial_paranoia_check(info, tty->device, "rs_put_char")) + return; + + if (!tty) + return; + + bdp = info->tx_cur; + while (bdp->status & BD_SC_READY); + + /* *((char *)__va(bdp->buf)) = ch; */ + *((char *)bdp->buf) = ch; + bdp->length = 1; + bdp->status |= BD_SC_READY; + + /* Get next BD. + */ + if (bdp->status & BD_SC_WRAP) + bdp = info->tx_bd_base; + else + bdp++; + + info->tx_cur = (QUICC_BD *)bdp; + +} + +static int rs_360_write(struct tty_struct * tty, int from_user, + const unsigned char *buf, int count) +{ + int c, ret = 0; + ser_info_t *info = (ser_info_t *)tty->driver_data; + volatile QUICC_BD *bdp; + +#ifdef CONFIG_KGDB + /* Try to let stub handle output. Returns true if it did. */ + if (kgdb_output_string(buf, count)) + return ret; +#endif + + if (serial_paranoia_check(info, tty->device, "rs_write")) + return 0; + + if (!tty) + return 0; + + bdp = info->tx_cur; + + while (1) { + c = min(count, TX_BUF_SIZE); + + if (c <= 0) + break; + + if (bdp->status & BD_SC_READY) { + info->flags |= TX_WAKEUP; + break; + } + + if (from_user) { + if (copy_from_user((void *)bdp->buf, buf, c)) { + if (!ret) + ret = -EFAULT; + break; + } + } else { + /* memcpy(__va(bdp->buf), buf, c); */ + memcpy((void *)bdp->buf, buf, c); + } + + bdp->length = c; + bdp->status |= BD_SC_READY; + + buf += c; + count -= c; + ret += c; + + /* Get next BD. + */ + if (bdp->status & BD_SC_WRAP) + bdp = info->tx_bd_base; + else + bdp++; + info->tx_cur = (QUICC_BD *)bdp; + } + return ret; +} + +static int rs_360_write_room(struct tty_struct *tty) +{ + ser_info_t *info = (ser_info_t *)tty->driver_data; + int ret; + + if (serial_paranoia_check(info, tty->device, "rs_write_room")) + return 0; + + if ((info->tx_cur->status & BD_SC_READY) == 0) { + info->flags &= ~TX_WAKEUP; + ret = TX_BUF_SIZE; + } + else { + info->flags |= TX_WAKEUP; + ret = 0; + } + return ret; +} + +/* I could track this with transmit counters....maybe later. +*/ +static int rs_360_chars_in_buffer(struct tty_struct *tty) +{ + ser_info_t *info = (ser_info_t *)tty->driver_data; + + if (serial_paranoia_check(info, tty->device, "rs_chars_in_buffer")) + return 0; + return 0; +} + +static void rs_360_flush_buffer(struct tty_struct *tty) +{ + ser_info_t *info = (ser_info_t *)tty->driver_data; + + if (serial_paranoia_check(info, tty->device, "rs_flush_buffer")) + return; + + /* There is nothing to "flush", whatever we gave the CPM + * is on its way out. + */ + wake_up_interruptible(&tty->write_wait); + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + tty->ldisc.write_wakeup) + (tty->ldisc.write_wakeup)(tty); + info->flags &= ~TX_WAKEUP; +} + +/* + * This function is used to send a high-priority XON/XOFF character to + * the device + */ +static void rs_360_send_xchar(struct tty_struct *tty, char ch) +{ + volatile QUICC_BD *bdp; + + ser_info_t *info = (ser_info_t *)tty->driver_data; + + if (serial_paranoia_check(info, tty->device, "rs_send_char")) + return; + + bdp = info->tx_cur; + while (bdp->status & BD_SC_READY); + + /* *((char *)__va(bdp->buf)) = ch; */ + *((char *)bdp->buf) = ch; + bdp->length = 1; + bdp->status |= BD_SC_READY; + + /* Get next BD. + */ + if (bdp->status & BD_SC_WRAP) + bdp = info->tx_bd_base; + else + bdp++; + + info->tx_cur = (QUICC_BD *)bdp; +} + +/* + * ------------------------------------------------------------ + * rs_throttle() + * + * This routine is called by the upper-layer tty layer to signal that + * incoming characters should be throttled. + * ------------------------------------------------------------ + */ +static void rs_360_throttle(struct tty_struct * tty) +{ + ser_info_t *info = (ser_info_t *)tty->driver_data; +#ifdef SERIAL_DEBUG_THROTTLE + char buf[64]; + + printk("throttle %s: %d....\n", _tty_name(tty, buf), + tty->ldisc.chars_in_buffer(tty)); +#endif + + if (serial_paranoia_check(info, tty->device, "rs_throttle")) + return; + + if (I_IXOFF(tty)) + rs_360_send_xchar(tty, STOP_CHAR(tty)); + +#ifdef modem_control + if (tty->termios->c_cflag & CRTSCTS) + info->MCR &= ~UART_MCR_RTS; + + local_irq_disable(); + serial_out(info, UART_MCR, info->MCR); + local_irq_enable(); +#endif +} + +static void rs_360_unthrottle(struct tty_struct * tty) +{ + ser_info_t *info = (ser_info_t *)tty->driver_data; +#ifdef SERIAL_DEBUG_THROTTLE + char buf[64]; + + printk("unthrottle %s: %d....\n", _tty_name(tty, buf), + tty->ldisc.chars_in_buffer(tty)); +#endif + + if (serial_paranoia_check(info, tty->device, "rs_unthrottle")) + return; + + if (I_IXOFF(tty)) { + if (info->x_char) + info->x_char = 0; + else + rs_360_send_xchar(tty, START_CHAR(tty)); + } +#ifdef modem_control + if (tty->termios->c_cflag & CRTSCTS) + info->MCR |= UART_MCR_RTS; + local_irq_disable(); + serial_out(info, UART_MCR, info->MCR); + local_irq_enable(); +#endif +} + +/* + * ------------------------------------------------------------ + * rs_ioctl() and friends + * ------------------------------------------------------------ + */ + +#ifdef maybe +/* + * get_lsr_info - get line status register info + * + * Purpose: Let user call ioctl() to get info when the UART physically + * is emptied. On bus types like RS485, the transmitter must + * release the bus after transmitting. This must be done when + * the transmit shift register is empty, not be done when the + * transmit holding register is empty. This functionality + * allows an RS485 driver to be written in user space. + */ +static int get_lsr_info(struct async_struct * info, unsigned int *value) +{ + unsigned char status; + unsigned int result; + + local_irq_disable(); + status = serial_in(info, UART_LSR); + local_irq_enable(); + result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0); + return put_user(result,value); +} +#endif + +static int get_modem_info(ser_info_t *info, unsigned int *value) +{ + unsigned int result = 0; +#ifdef modem_control + unsigned char control, status; + + control = info->MCR; + local_irq_disable(); + status = serial_in(info, UART_MSR); + local_irq_enable(); + result = ((control & UART_MCR_RTS) ? TIOCM_RTS : 0) + | ((control & UART_MCR_DTR) ? TIOCM_DTR : 0) +#ifdef TIOCM_OUT1 + | ((control & UART_MCR_OUT1) ? TIOCM_OUT1 : 0) + | ((control & UART_MCR_OUT2) ? TIOCM_OUT2 : 0) +#endif + | ((status & UART_MSR_DCD) ? TIOCM_CAR : 0) + | ((status & UART_MSR_RI) ? TIOCM_RNG : 0) + | ((status & UART_MSR_DSR) ? TIOCM_DSR : 0) + | ((status & UART_MSR_CTS) ? TIOCM_CTS : 0); +#endif + /* return put_user(result,value); */ + put_user(result,value); + return (0); +} + +static int set_modem_info(ser_info_t *info, unsigned int cmd, + unsigned int *value) +{ + int error; + unsigned int arg; + + error = get_user(arg,value); + if (error) + return error; +#ifdef modem_control + switch (cmd) { + case TIOCMBIS: + if (arg & TIOCM_RTS) + info->MCR |= UART_MCR_RTS; + if (arg & TIOCM_DTR) + info->MCR |= UART_MCR_DTR; +#ifdef TIOCM_OUT1 + if (arg & TIOCM_OUT1) + info->MCR |= UART_MCR_OUT1; + if (arg & TIOCM_OUT2) + info->MCR |= UART_MCR_OUT2; +#endif + break; + case TIOCMBIC: + if (arg & TIOCM_RTS) + info->MCR &= ~UART_MCR_RTS; + if (arg & TIOCM_DTR) + info->MCR &= ~UART_MCR_DTR; +#ifdef TIOCM_OUT1 + if (arg & TIOCM_OUT1) + info->MCR &= ~UART_MCR_OUT1; + if (arg & TIOCM_OUT2) + info->MCR &= ~UART_MCR_OUT2; +#endif + break; + case TIOCMSET: + info->MCR = ((info->MCR & ~(UART_MCR_RTS | +#ifdef TIOCM_OUT1 + UART_MCR_OUT1 | + UART_MCR_OUT2 | +#endif + UART_MCR_DTR)) + | ((arg & TIOCM_RTS) ? UART_MCR_RTS : 0) +#ifdef TIOCM_OUT1 + | ((arg & TIOCM_OUT1) ? UART_MCR_OUT1 : 0) + | ((arg & TIOCM_OUT2) ? UART_MCR_OUT2 : 0) +#endif + | ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0)); + break; + default: + return -EINVAL; + } + local_irq_disable(); + serial_out(info, UART_MCR, info->MCR); + local_irq_enable(); +#endif + return 0; +} + +/* Sending a break is a two step process on the SMC/SCC. It is accomplished + * by sending a STOP TRANSMIT command followed by a RESTART TRANSMIT + * command. We take advantage of the begin/end functions to make this + * happen. + */ +static ushort smc_chan_map[] = { + CPM_CR_CH_SMC1, + CPM_CR_CH_SMC2 +}; + +static ushort scc_chan_map[] = { + CPM_CR_CH_SCC1, + CPM_CR_CH_SCC2, + CPM_CR_CH_SCC3, + CPM_CR_CH_SCC4 +}; + +static void begin_break(ser_info_t *info) +{ + volatile QUICC *cp; + ushort chan; + int idx; + + cp = pquicc; + + idx = PORT_NUM(info->state->smc_scc_num); + if (info->state->smc_scc_num & NUM_IS_SCC) + chan = scc_chan_map[idx]; + else + chan = smc_chan_map[idx]; + + cp->cp_cr = mk_cr_cmd(chan, CPM_CR_STOP_TX) | CPM_CR_FLG; + while (cp->cp_cr & CPM_CR_FLG); +} + +static void end_break(ser_info_t *info) +{ + volatile QUICC *cp; + ushort chan; + int idx; + + cp = pquicc; + + idx = PORT_NUM(info->state->smc_scc_num); + if (info->state->smc_scc_num & NUM_IS_SCC) + chan = scc_chan_map[idx]; + else + chan = smc_chan_map[idx]; + + cp->cp_cr = mk_cr_cmd(chan, CPM_CR_RESTART_TX) | CPM_CR_FLG; + while (cp->cp_cr & CPM_CR_FLG); +} + +/* + * This routine sends a break character out the serial port. + */ +static void send_break(ser_info_t *info, int duration) +{ + current->state = TASK_INTERRUPTIBLE; +#ifdef SERIAL_DEBUG_SEND_BREAK + printk("rs_send_break(%d) jiff=%lu...", duration, jiffies); +#endif + begin_break(info); + schedule_timeout(duration); + end_break(info); +#ifdef SERIAL_DEBUG_SEND_BREAK + printk("done jiffies=%lu\n", jiffies); +#endif +} + + +static int rs_360_ioctl(struct tty_struct *tty, struct file * file, + unsigned int cmd, unsigned long arg) +{ + int error; + ser_info_t *info = (ser_info_t *)tty->driver_data; + int retval; + struct async_icount cnow; + /* struct async_icount_24 cnow;*/ /* kernel counter temps */ + struct serial_icounter_struct *p_cuser; /* user space */ + + if (serial_paranoia_check(info, tty->device, "rs_ioctl")) + return -ENODEV; + + if ((cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; + } + + switch (cmd) { + case TCSBRK: /* SVID version: non-zero arg --> no break */ + retval = tty_check_change(tty); + if (retval) + return retval; + tty_wait_until_sent(tty, 0); + if (signal_pending(current)) + return -EINTR; + if (!arg) { + send_break(info, HZ/4); /* 1/4 second */ + if (signal_pending(current)) + return -EINTR; + } + return 0; + case TCSBRKP: /* support for POSIX tcsendbreak() */ + retval = tty_check_change(tty); + if (retval) + return retval; + tty_wait_until_sent(tty, 0); + if (signal_pending(current)) + return -EINTR; + send_break(info, arg ? arg*(HZ/10) : HZ/4); + if (signal_pending(current)) + return -EINTR; + return 0; + case TIOCSBRK: + retval = tty_check_change(tty); + if (retval) + return retval; + tty_wait_until_sent(tty, 0); + begin_break(info); + return 0; + case TIOCCBRK: + retval = tty_check_change(tty); + if (retval) + return retval; + end_break(info); + return 0; + case TIOCGSOFTCAR: + /* return put_user(C_CLOCAL(tty) ? 1 : 0, (int *) arg); */ + put_user(C_CLOCAL(tty) ? 1 : 0, (int *) arg); + return 0; + case TIOCSSOFTCAR: + error = get_user(arg, (unsigned int *) arg); + if (error) + return error; + tty->termios->c_cflag = + ((tty->termios->c_cflag & ~CLOCAL) | + (arg ? CLOCAL : 0)); + return 0; + case TIOCMGET: + return get_modem_info(info, (unsigned int *) arg); + case TIOCMBIS: + case TIOCMBIC: + case TIOCMSET: + return set_modem_info(info, cmd, (unsigned int *) arg); +#ifdef maybe + case TIOCSERGETLSR: /* Get line status register */ + return get_lsr_info(info, (unsigned int *) arg); +#endif + /* + * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change + * - mask passed in arg for lines of interest + * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking) + * Caller should use TIOCGICOUNT to see which one it was + */ + case TIOCMIWAIT: +#ifdef modem_control + local_irq_disable(); + /* note the counters on entry */ + cprev = info->state->icount; + local_irq_enable(); + while (1) { + interruptible_sleep_on(&info->delta_msr_wait); + /* see if a signal did it */ + if (signal_pending(current)) + return -ERESTARTSYS; + local_irq_disable(); + cnow = info->state->icount; /* atomic copy */ + local_irq_enable(); + if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && + cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) + return -EIO; /* no change => error */ + if ( ((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || + ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || + ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || + ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) { + return 0; + } + cprev = cnow; + } + /* NOTREACHED */ +#else + return 0; +#endif + + /* + * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) + * Return: write counters to the user passed counter struct + * NB: both 1->0 and 0->1 transitions are counted except for + * RI where only 0->1 is counted. + */ + case TIOCGICOUNT: + local_irq_disable(); + cnow = info->state->icount; + local_irq_enable(); + p_cuser = (struct serial_icounter_struct *) arg; +/* error = put_user(cnow.cts, &p_cuser->cts); */ +/* if (error) return error; */ +/* error = put_user(cnow.dsr, &p_cuser->dsr); */ +/* if (error) return error; */ +/* error = put_user(cnow.rng, &p_cuser->rng); */ +/* if (error) return error; */ +/* error = put_user(cnow.dcd, &p_cuser->dcd); */ +/* if (error) return error; */ + + put_user(cnow.cts, &p_cuser->cts); + put_user(cnow.dsr, &p_cuser->dsr); + put_user(cnow.rng, &p_cuser->rng); + put_user(cnow.dcd, &p_cuser->dcd); + return 0; + + default: + return -ENOIOCTLCMD; + } + return 0; +} + +/* FIX UP modem control here someday...... +*/ +static void rs_360_set_termios(struct tty_struct *tty, struct termios *old_termios) +{ + ser_info_t *info = (ser_info_t *)tty->driver_data; + + if ( (tty->termios->c_cflag == old_termios->c_cflag) + && ( RELEVANT_IFLAG(tty->termios->c_iflag) + == RELEVANT_IFLAG(old_termios->c_iflag))) + return; + + change_speed(info); + +#ifdef modem_control + /* Handle transition to B0 status */ + if ((old_termios->c_cflag & CBAUD) && + !(tty->termios->c_cflag & CBAUD)) { + info->MCR &= ~(UART_MCR_DTR|UART_MCR_RTS); + local_irq_disable(); + serial_out(info, UART_MCR, info->MCR); + local_irq_enable(); + } + + /* Handle transition away from B0 status */ + if (!(old_termios->c_cflag & CBAUD) && + (tty->termios->c_cflag & CBAUD)) { + info->MCR |= UART_MCR_DTR; + if (!tty->hw_stopped || + !(tty->termios->c_cflag & CRTSCTS)) { + info->MCR |= UART_MCR_RTS; + } + local_irq_disable(); + serial_out(info, UART_MCR, info->MCR); + local_irq_enable(); + } + + /* Handle turning off CRTSCTS */ + if ((old_termios->c_cflag & CRTSCTS) && + !(tty->termios->c_cflag & CRTSCTS)) { + tty->hw_stopped = 0; + rs_360_start(tty); + } +#endif + +#if 0 + /* + * No need to wake up processes in open wait, since they + * sample the CLOCAL flag once, and don't recheck it. + * XXX It's not clear whether the current behavior is correct + * or not. Hence, this may change..... + */ + if (!(old_termios->c_cflag & CLOCAL) && + (tty->termios->c_cflag & CLOCAL)) + wake_up_interruptible(&info->open_wait); +#endif +} + +/* + * ------------------------------------------------------------ + * rs_close() + * + * This routine is called when the serial port gets closed. First, we + * wait for the last remaining data to be sent. Then, we unlink its + * async structure from the interrupt chain if necessary, and we free + * that IRQ if nothing is left in the chain. + * ------------------------------------------------------------ + */ +static void rs_360_close(struct tty_struct *tty, struct file * filp) +{ + ser_info_t *info = (ser_info_t *)tty->driver_data; + /* struct async_state *state; */ + struct serial_state *state; + unsigned long flags; + int idx; + volatile struct smc_regs *smcp; + volatile struct scc_regs *sccp; + + if (!info || serial_paranoia_check(info, tty->device, "rs_close")) + return; + + state = info->state; + + local_irq_save(flags); + + if (tty_hung_up_p(filp)) { + DBG_CNT("before DEC-hung"); + MOD_DEC_USE_COUNT; + local_irq_restore(flags); + return; + } + +#ifdef SERIAL_DEBUG_OPEN + printk("rs_close ttys%d, count = %d\n", info->line, state->count); +#endif + if ((tty->count == 1) && (state->count != 1)) { + /* + * Uh, oh. tty->count is 1, which means that the tty + * structure will be freed. state->count should always + * be one in these conditions. If it's greater than + * one, we've got real problems, since it means the + * serial port won't be shutdown. + */ + printk("rs_close: bad serial port count; tty->count is 1, " + "state->count is %d\n", state->count); + state->count = 1; + } + if (--state->count < 0) { + printk("rs_close: bad serial port count for ttys%d: %d\n", + info->line, state->count); + state->count = 0; + } + if (state->count) { + DBG_CNT("before DEC-2"); + MOD_DEC_USE_COUNT; + local_irq_restore(flags); + return; + } + info->flags |= ASYNC_CLOSING; + /* + * Save the termios structure, since this port may have + * separate termios for callout and dialin. + */ + if (info->flags & ASYNC_NORMAL_ACTIVE) + info->state->normal_termios = *tty->termios; + if (info->flags & ASYNC_CALLOUT_ACTIVE) + info->state->callout_termios = *tty->termios; + /* + * Now we wait for the transmit buffer to clear; and we notify + * the line discipline to only process XON/XOFF characters. + */ + tty->closing = 1; + if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE) + tty_wait_until_sent(tty, info->closing_wait); + /* + * At this point we stop accepting input. To do this, we + * disable the receive line status interrupts, and tell the + * interrupt driver to stop checking the data ready bit in the + * line status register. + */ + info->read_status_mask &= ~BD_SC_EMPTY; + if (info->flags & ASYNC_INITIALIZED) { + + idx = PORT_NUM(info->state->smc_scc_num); + if (info->state->smc_scc_num & NUM_IS_SCC) { + sccp = &pquicc->scc_regs[idx]; + sccp->scc_sccm &= ~UART_SCCM_RX; + sccp->scc_gsmr.w.low &= ~SCC_GSMRL_ENR; + } else { + smcp = &pquicc->smc_regs[idx]; + smcp->smc_smcm &= ~SMCM_RX; + smcp->smc_smcmr &= ~SMCMR_REN; + } + /* + * Before we drop DTR, make sure the UART transmitter + * has completely drained; this is especially + * important if there is a transmit FIFO! + */ + rs_360_wait_until_sent(tty, info->timeout); + } + shutdown(info); + if (tty->driver.flush_buffer) + tty->driver.flush_buffer(tty); + if (tty->ldisc.flush_buffer) + tty->ldisc.flush_buffer(tty); + tty->closing = 0; + info->event = 0; + info->tty = 0; + if (info->blocked_open) { + if (info->close_delay) { + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(info->close_delay); + } + wake_up_interruptible(&info->open_wait); + } + info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE| + ASYNC_CLOSING); + wake_up_interruptible(&info->close_wait); + MOD_DEC_USE_COUNT; + local_irq_restore(flags); +} + +/* + * rs_wait_until_sent() --- wait until the transmitter is empty + */ +static void rs_360_wait_until_sent(struct tty_struct *tty, int timeout) +{ + ser_info_t *info = (ser_info_t *)tty->driver_data; + unsigned long orig_jiffies, char_time; + /*int lsr;*/ + volatile QUICC_BD *bdp; + + if (serial_paranoia_check(info, tty->device, "rs_wait_until_sent")) + return; + +#ifdef maybe + if (info->state->type == PORT_UNKNOWN) + return; +#endif + + orig_jiffies = jiffies; + /* + * Set the check interval to be 1/5 of the estimated time to + * send a single character, and make it at least 1. The check + * interval should also be less than the timeout. + * + * Note: we have to use pretty tight timings here to satisfy + * the NIST-PCTS. + */ + char_time = 1; + if (timeout) + char_time = min(char_time, timeout); +#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT + printk("In rs_wait_until_sent(%d) check=%lu...", timeout, char_time); + printk("jiff=%lu...", jiffies); +#endif + + /* We go through the loop at least once because we can't tell + * exactly when the last character exits the shifter. There can + * be at least two characters waiting to be sent after the buffers + * are empty. + */ + do { +#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT + printk("lsr = %d (jiff=%lu)...", lsr, jiffies); +#endif + current->state = TASK_INTERRUPTIBLE; +/* current->counter = 0; make us low-priority */ + schedule_timeout(char_time); + if (signal_pending(current)) + break; + if (timeout && ((orig_jiffies + timeout) < jiffies)) + break; + /* The 'tx_cur' is really the next buffer to send. We + * have to back up to the previous BD and wait for it + * to go. This isn't perfect, because all this indicates + * is the buffer is available. There are still characters + * in the CPM FIFO. + */ + bdp = info->tx_cur; + if (bdp == info->tx_bd_base) + bdp += (TX_NUM_FIFO-1); + else + bdp--; + } while (bdp->status & BD_SC_READY); + current->state = TASK_RUNNING; +#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT + printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies); +#endif +} + +/* + * rs_hangup() --- called by tty_hangup() when a hangup is signaled. + */ +static void rs_360_hangup(struct tty_struct *tty) +{ + ser_info_t *info = (ser_info_t *)tty->driver_data; + struct serial_state *state = info->state; + + if (serial_paranoia_check(info, tty->device, "rs_hangup")) + return; + + state = info->state; + + rs_360_flush_buffer(tty); + shutdown(info); + info->event = 0; + state->count = 0; + info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE); + info->tty = 0; + wake_up_interruptible(&info->open_wait); +} + +/* + * ------------------------------------------------------------ + * rs_open() and friends + * ------------------------------------------------------------ + */ +static int block_til_ready(struct tty_struct *tty, struct file * filp, + ser_info_t *info) +{ +#ifdef DO_THIS_LATER + DECLARE_WAITQUEUE(wait, current); +#endif + struct serial_state *state = info->state; + int retval; + int do_clocal = 0; + + /* + * If the device is in the middle of being closed, then block + * until it's done, and then try again. + */ + if (tty_hung_up_p(filp) || + (info->flags & ASYNC_CLOSING)) { + if (info->flags & ASYNC_CLOSING) + interruptible_sleep_on(&info->close_wait); +#ifdef SERIAL_DO_RESTART + if (info->flags & ASYNC_HUP_NOTIFY) + return -EAGAIN; + else + return -ERESTARTSYS; +#else + return -EAGAIN; +#endif + } + + +#if 0 /* FIXME */ + /* + * If this is a callout device, then just make sure the normal + * device isn't being used. + */ + if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) { + if (info->flags & ASYNC_NORMAL_ACTIVE) + return -EBUSY; + if ((info->flags & ASYNC_CALLOUT_ACTIVE) && + (info->flags & ASYNC_SESSION_LOCKOUT) && + (info->session != current->session)) + return -EBUSY; + if ((info->flags & ASYNC_CALLOUT_ACTIVE) && + (info->flags & ASYNC_PGRP_LOCKOUT) && + (info->pgrp != current->pgrp)) + return -EBUSY; + info->flags |= ASYNC_CALLOUT_ACTIVE; + return 0; + } +#endif + + /* + * If non-blocking mode is set, or the port is not enabled, + * then make the check up front and then exit. + * If this is an SMC port, we don't have modem control to wait + * for, so just get out here. + */ + if ((filp->f_flags & O_NONBLOCK) || + (tty->flags & (1 << TTY_IO_ERROR)) || + !(info->state->smc_scc_num & NUM_IS_SCC)) { + if (info->flags & ASYNC_CALLOUT_ACTIVE) + return -EBUSY; + info->flags |= ASYNC_NORMAL_ACTIVE; + return 0; + } + + if (info->flags & ASYNC_CALLOUT_ACTIVE) { + if (state->normal_termios.c_cflag & CLOCAL) + do_clocal = 1; + } else { + if (tty->termios->c_cflag & CLOCAL) + do_clocal = 1; + } + + /* + * Block waiting for the carrier detect and the line to become + * free (i.e., not in use by the callout). While we are in + * this loop, state->count is dropped by one, so that + * rs_close() knows when to free things. We restore it upon + * exit, either normal or abnormal. + */ + retval = 0; +#ifdef DO_THIS_LATER + add_wait_queue(&info->open_wait, &wait); +#ifdef SERIAL_DEBUG_OPEN + printk("block_til_ready before block: ttys%d, count = %d\n", + state->line, state->count); +#endif + local_irq_disable(); + if (!tty_hung_up_p(filp)) + state->count--; + local_irq_enable(); + info->blocked_open++; + while (1) { + local_irq_disable(); + if (!(info->flags & ASYNC_CALLOUT_ACTIVE) && + (tty->termios->c_cflag & CBAUD)) + serial_out(info, UART_MCR, + serial_inp(info, UART_MCR) | + (UART_MCR_DTR | UART_MCR_RTS)); + local_irq_enable(); + set_current_state(TASK_INTERRUPTIBLE); + if (tty_hung_up_p(filp) || + !(info->flags & ASYNC_INITIALIZED)) { +#ifdef SERIAL_DO_RESTART + if (info->flags & ASYNC_HUP_NOTIFY) + retval = -EAGAIN; + else + retval = -ERESTARTSYS; +#else + retval = -EAGAIN; +#endif + break; + } + if (!(info->flags & ASYNC_CALLOUT_ACTIVE) && + !(info->flags & ASYNC_CLOSING) && + (do_clocal || (serial_in(info, UART_MSR) & + UART_MSR_DCD))) + break; + if (signal_pending(current)) { + retval = -ERESTARTSYS; + break; + } +#ifdef SERIAL_DEBUG_OPEN + printk("block_til_ready blocking: ttys%d, count = %d\n", + info->line, state->count); +#endif + schedule(); + } + current->state = TASK_RUNNING; + remove_wait_queue(&info->open_wait, &wait); + if (!tty_hung_up_p(filp)) + state->count++; + info->blocked_open--; +#ifdef SERIAL_DEBUG_OPEN + printk("block_til_ready after blocking: ttys%d, count = %d\n", + info->line, state->count); +#endif +#endif /* DO_THIS_LATER */ + if (retval) + return retval; + info->flags |= ASYNC_NORMAL_ACTIVE; + return 0; +} + +static int get_async_struct(int line, ser_info_t **ret_info) +{ + struct serial_state *sstate; + + sstate = rs_table + line; + if (sstate->info) { + sstate->count++; + *ret_info = (ser_info_t *)sstate->info; + return 0; + } + else { + return -ENOMEM; + } +} + +/* + * This routine is called whenever a serial port is opened. It + * enables interrupts for a serial port, linking in its async structure into + * the IRQ chain. It also performs the serial-specific + * initialization for the tty structure. + */ +static int rs_360_open(struct tty_struct *tty, struct file * filp) +{ + ser_info_t *info; + int retval, line; + + line = MINOR(tty->device) - tty->driver.minor_start; + if ((line < 0) || (line >= NR_PORTS)) + return -ENODEV; + retval = get_async_struct(line, &info); + if (retval) + return retval; + if (serial_paranoia_check(info, tty->device, "rs_open")) + return -ENODEV; + +#ifdef SERIAL_DEBUG_OPEN + printk("rs_open %s%d, count = %d\n", tty->driver.name, info->line, + info->state->count); +#endif + tty->driver_data = info; + info->tty = tty; + + /* + * Start up serial port + */ + retval = startup(info); + if (retval) + return retval; + + MOD_INC_USE_COUNT; + retval = block_til_ready(tty, filp, info); + if (retval) { +#ifdef SERIAL_DEBUG_OPEN + printk("rs_open returning after block_til_ready with %d\n", + retval); +#endif + MOD_DEC_USE_COUNT; + return retval; + } + + if ((info->state->count == 1) && + (info->flags & ASYNC_SPLIT_TERMIOS)) { + if (tty->driver.subtype == SERIAL_TYPE_NORMAL) + *tty->termios = info->state->normal_termios; + else + *tty->termios = info->state->callout_termios; + change_speed(info); + } + + info->session = current->session; + info->pgrp = current->pgrp; + +#ifdef SERIAL_DEBUG_OPEN + printk("rs_open ttys%d successful...", info->line); +#endif + return 0; +} + +/* + * /proc fs routines.... + */ + +static int inline line_info(char *buf, struct serial_state *state) +{ +#ifdef notdef + struct async_struct *info = state->info, scr_info; + char stat_buf[30], control, status; +#endif + int ret; + + ret = sprintf(buf, "%d: uart:%s port:%X irq:%d", + state->line, + (state->smc_scc_num & NUM_IS_SCC) ? "SCC" : "SMC", + (unsigned int)(state->port), state->irq); + + if (!state->port || (state->type == PORT_UNKNOWN)) { + ret += sprintf(buf+ret, "\n"); + return ret; + } + +#ifdef notdef + /* + * Figure out the current RS-232 lines + */ + if (!info) { + info = &scr_info; /* This is just for serial_{in,out} */ + + info->magic = SERIAL_MAGIC; + info->port = state->port; + info->flags = state->flags; + info->quot = 0; + info->tty = 0; + } + local_irq_disable(); + status = serial_in(info, UART_MSR); + control = info ? info->MCR : serial_in(info, UART_MCR); + local_irq_enable(); + + stat_buf[0] = 0; + stat_buf[1] = 0; + if (control & UART_MCR_RTS) + strcat(stat_buf, "|RTS"); + if (status & UART_MSR_CTS) + strcat(stat_buf, "|CTS"); + if (control & UART_MCR_DTR) + strcat(stat_buf, "|DTR"); + if (status & UART_MSR_DSR) + strcat(stat_buf, "|DSR"); + if (status & UART_MSR_DCD) + strcat(stat_buf, "|CD"); + if (status & UART_MSR_RI) + strcat(stat_buf, "|RI"); + + if (info->quot) { + ret += sprintf(buf+ret, " baud:%d", + state->baud_base / info->quot); + } + + ret += sprintf(buf+ret, " tx:%d rx:%d", + state->icount.tx, state->icount.rx); + + if (state->icount.frame) + ret += sprintf(buf+ret, " fe:%d", state->icount.frame); + + if (state->icount.parity) + ret += sprintf(buf+ret, " pe:%d", state->icount.parity); + + if (state->icount.brk) + ret += sprintf(buf+ret, " brk:%d", state->icount.brk); + + if (state->icount.overrun) + ret += sprintf(buf+ret, " oe:%d", state->icount.overrun); + + /* + * Last thing is the RS-232 status lines + */ + ret += sprintf(buf+ret, " %s\n", stat_buf+1); +#endif + return ret; +} + +int rs_360_read_proc(char *page, char **start, off_t off, int count, + int *eof, void *data) +{ + int i, len = 0; + off_t begin = 0; + + len += sprintf(page, "serinfo:1.0 driver:%s\n", serial_version); + for (i = 0; i < NR_PORTS && len < 4000; i++) { + len += line_info(page + len, &rs_table[i]); + if (len+begin > off+count) + goto done; + if (len+begin < off) { + begin += len; + len = 0; + } + } + *eof = 1; +done: + if (off >= len+begin) + return 0; + *start = page + (begin-off); + return ((count < begin+len-off) ? count : begin+len-off); +} + +/* + * --------------------------------------------------------------------- + * rs_init() and friends + * + * rs_init() is called at boot-time to initialize the serial driver. + * --------------------------------------------------------------------- + */ + +/* + * This routine prints out the appropriate serial driver version + * number, and identifies which options were configured into this + * driver. + */ +static _INLINE_ void show_serial_version(void) +{ + printk(KERN_INFO "%s version %s\n", serial_name, serial_version); +} + + +/* + * The serial console driver used during boot. Note that these names + * clash with those found in "serial.c", so we currently can't support + * the 16xxx uarts and these at the same time. I will fix this to become + * an indirect function call from tty_io.c (or something). + */ + +#ifdef CONFIG_SERIAL_CONSOLE + +/* + * Print a string to the serial port trying not to disturb any possible + * real use of the port... + */ +static void my_console_write(int idx, const char *s, + unsigned count) +{ + struct serial_state *ser; + ser_info_t *info; + unsigned i; + QUICC_BD *bdp, *bdbase; + volatile struct smc_uart_pram *up; + volatile u_char *cp; + + ser = rs_table + idx; + + + /* If the port has been initialized for general use, we have + * to use the buffer descriptors allocated there. Otherwise, + * we simply use the single buffer allocated. + */ + if ((info = (ser_info_t *)ser->info) != NULL) { + bdp = info->tx_cur; + bdbase = info->tx_bd_base; + } + else { + /* Pointer to UART in parameter ram. + */ + /* up = (smc_uart_t *)&cpmp->cp_dparam[ser->port]; */ + up = &pquicc->pram[ser->port].scc.pothers.idma_smc.psmc.u; + + /* Get the address of the host memory buffer. + */ + bdp = bdbase = (QUICC_BD *)((uint)pquicc + (uint)up->tbase); + } + + /* + * We need to gracefully shut down the transmitter, disable + * interrupts, then send our bytes out. + */ + + /* + * Now, do each character. This is not as bad as it looks + * since this is a holding FIFO and not a transmitting FIFO. + * We could add the complexity of filling the entire transmit + * buffer, but we would just wait longer between accesses...... + */ + for (i = 0; i < count; i++, s++) { + /* Wait for transmitter fifo to empty. + * Ready indicates output is ready, and xmt is doing + * that, not that it is ready for us to send. + */ + while (bdp->status & BD_SC_READY); + + /* Send the character out. + */ + cp = bdp->buf; + *cp = *s; + + bdp->length = 1; + bdp->status |= BD_SC_READY; + + if (bdp->status & BD_SC_WRAP) + bdp = bdbase; + else + bdp++; + + /* if a LF, also do CR... */ + if (*s == 10) { + while (bdp->status & BD_SC_READY); + /* cp = __va(bdp->buf); */ + cp = bdp->buf; + *cp = 13; + bdp->length = 1; + bdp->status |= BD_SC_READY; + + if (bdp->status & BD_SC_WRAP) { + bdp = bdbase; + } + else { + bdp++; + } + } + } + + /* + * Finally, Wait for transmitter & holding register to empty + * and restore the IER + */ + while (bdp->status & BD_SC_READY); + + if (info) + info->tx_cur = (QUICC_BD *)bdp; +} + +static void serial_console_write(struct console *c, const char *s, + unsigned count) +{ +#ifdef CONFIG_KGDB + /* Try to let stub handle output. Returns true if it did. */ + if (kgdb_output_string(s, count)) + return; +#endif + my_console_write(c->index, s, count); +} + + + +/*void console_print_68360(const char *p) +{ + const char *cp = p; + int i; + + for (i=0;cp[i]!=0;i++); + + serial_console_write (p, i); + + //Comment this if you want to have a strict interrupt-driven output + //rs_fair_output(); + + return; +}*/ + + + + + + +#ifdef CONFIG_XMON +int +xmon_360_write(const char *s, unsigned count) +{ + my_console_write(0, s, count); + return(count); +} +#endif + +#ifdef CONFIG_KGDB +void +putDebugChar(char ch) +{ + my_console_write(0, &ch, 1); +} +#endif + +/* + * Receive character from the serial port. This only works well + * before the port is initialized for real use. + */ +static int my_console_wait_key(int idx, int xmon, char *obuf) +{ + struct serial_state *ser; + u_char c, *cp; + ser_info_t *info; + QUICC_BD *bdp; + volatile struct smc_uart_pram *up; + int i; + + ser = rs_table + idx; + + /* Get the address of the host memory buffer. + * If the port has been initialized for general use, we must + * use information from the port structure. + */ + if ((info = (ser_info_t *)ser->info)) + bdp = info->rx_cur; + else + /* bdp = (QUICC_BD *)&cpmp->cp_dpmem[up->smc_rbase]; */ + bdp = (QUICC_BD *)((uint)pquicc + (uint)up->tbase); + + /* Pointer to UART in parameter ram. + */ + /* up = (smc_uart_t *)&cpmp->cp_dparam[ser->port]; */ + up = &pquicc->pram[info->state->port].scc.pothers.idma_smc.psmc.u; + + /* + * We need to gracefully shut down the receiver, disable + * interrupts, then read the input. + * XMON just wants a poll. If no character, return -1, else + * return the character. + */ + if (!xmon) { + while (bdp->status & BD_SC_EMPTY); + } + else { + if (bdp->status & BD_SC_EMPTY) + return -1; + } + + cp = (char *)bdp->buf; + + if (obuf) { + i = c = bdp->length; + while (i-- > 0) + *obuf++ = *cp++; + } + else { + c = *cp; + } + bdp->status |= BD_SC_EMPTY; + + if (info) { + if (bdp->status & BD_SC_WRAP) { + bdp = info->rx_bd_base; + } + else { + bdp++; + } + info->rx_cur = (QUICC_BD *)bdp; + } + + return((int)c); +} + +static int serial_console_wait_key(struct console *co) +{ + return(my_console_wait_key(co->index, 0, NULL)); +} + +#ifdef CONFIG_XMON +int +xmon_360_read_poll(void) +{ + return(my_console_wait_key(0, 1, NULL)); +} + +int +xmon_360_read_char(void) +{ + return(my_console_wait_key(0, 0, NULL)); +} +#endif + +#ifdef CONFIG_KGDB +static char kgdb_buf[RX_BUF_SIZE], *kgdp; +static int kgdb_chars; + +unsigned char +getDebugChar(void) +{ + if (kgdb_chars <= 0) { + kgdb_chars = my_console_wait_key(0, 0, kgdb_buf); + kgdp = kgdb_buf; + } + kgdb_chars--; + + return(*kgdp++); +} + +void kgdb_interruptible(int state) +{ +} +void kgdb_map_scc(void) +{ + struct serial_state *ser; + uint mem_addr; + volatile QUICC_BD *bdp; + volatile smc_uart_t *up; + + cpmp = (cpm360_t *)&(((immap_t *)IMAP_ADDR)->im_cpm); + + /* To avoid data cache CPM DMA coherency problems, allocate a + * buffer in the CPM DPRAM. This will work until the CPM and + * serial ports are initialized. At that time a memory buffer + * will be allocated. + * The port is already initialized from the boot procedure, all + * we do here is give it a different buffer and make it a FIFO. + */ + + ser = rs_table; + + /* Right now, assume we are using SMCs. + */ + up = (smc_uart_t *)&cpmp->cp_dparam[ser->port]; + + /* Allocate space for an input FIFO, plus a few bytes for output. + * Allocate bytes to maintain word alignment. + */ + mem_addr = (uint)(&cpmp->cp_dpmem[0x1000]); + + /* Set the physical address of the host memory buffers in + * the buffer descriptors. + */ + bdp = (QUICC_BD *)&cpmp->cp_dpmem[up->smc_rbase]; + bdp->buf = mem_addr; + + bdp = (QUICC_BD *)&cpmp->cp_dpmem[up->smc_tbase]; + bdp->buf = mem_addr+RX_BUF_SIZE; + + up->smc_mrblr = RX_BUF_SIZE; /* receive buffer length */ + up->smc_maxidl = RX_BUF_SIZE; +} +#endif + +static kdev_t serial_console_device(struct console *c) +{ + return MKDEV(TTY_MAJOR, 64 + c->index); +} + + +struct console sercons = { + name: "ttyS", + write: serial_console_write, + device: serial_console_device, + wait_key: serial_console_wait_key, + setup: serial_console_setup, + flags: CON_PRINTBUFFER, + index: CONFIG_SERIAL_CONSOLE_PORT, +}; + + + +/* + * Register console. + */ +long console_360_init(long kmem_start, long kmem_end) +{ + register_console(&sercons); + /*register_console (console_print_68360); - 2.0.38 only required a write + function pointer. */ + return kmem_start; +} + +#endif + +/* Index in baud rate table of the default console baud rate. +*/ +static int baud_idx; + + +/* int __init rs_360_init(void) */ +int rs_360_init(void) +{ + struct serial_state * state; + ser_info_t *info; + void *mem_addr; + uint dp_addr, iobits; + int i, j, idx; + ushort chan; + QUICC_BD *bdp; + volatile QUICC *cp; + volatile struct smc_regs *sp; + volatile struct smc_uart_pram *up; + volatile struct scc_regs *scp; + volatile struct uart_pram *sup; + /* volatile immap_t *immap; */ + + init_bh(SERIAL_BH, do_serial_bh); + + show_serial_version(); + + /* Initialize the tty_driver structure */ + + /* __clear_user(&serial_driver,sizeof(struct tty_driver)); */ + memset(&serial_driver, 0, sizeof(struct tty_driver)); + + serial_driver.magic = TTY_DRIVER_MAGIC; + /* serial_driver.driver_name = "serial"; */ + serial_driver.name = "ttyS"; + serial_driver.major = TTY_MAJOR; + serial_driver.minor_start = 64; + serial_driver.num = NR_PORTS; + serial_driver.type = TTY_DRIVER_TYPE_SERIAL; + serial_driver.subtype = SERIAL_TYPE_NORMAL; + serial_driver.init_termios = tty_std_termios; + serial_driver.init_termios.c_cflag = + baud_idx | CS8 | CREAD | HUPCL | CLOCAL; + serial_driver.flags = TTY_DRIVER_REAL_RAW; + serial_driver.refcount = &serial_refcount; + serial_driver.table = serial_table; + serial_driver.termios = serial_termios; + serial_driver.termios_locked = serial_termios_locked; + + serial_driver.open = rs_360_open; + serial_driver.close = rs_360_close; + serial_driver.write = rs_360_write; + serial_driver.put_char = rs_360_put_char; + serial_driver.write_room = rs_360_write_room; + serial_driver.chars_in_buffer = rs_360_chars_in_buffer; + serial_driver.flush_buffer = rs_360_flush_buffer; + serial_driver.ioctl = rs_360_ioctl; + serial_driver.throttle = rs_360_throttle; + serial_driver.unthrottle = rs_360_unthrottle; + /* serial_driver.send_xchar = rs_360_send_xchar; */ + serial_driver.set_termios = rs_360_set_termios; + serial_driver.stop = rs_360_stop; + serial_driver.start = rs_360_start; + serial_driver.hangup = rs_360_hangup; + /* serial_driver.wait_until_sent = rs_360_wait_until_sent; */ + /* serial_driver.read_proc = rs_360_read_proc; */ + + /* + * The callout device is just like normal device except for + * major number and the subtype code. + */ + callout_driver = serial_driver; + callout_driver.name = "cua"; + callout_driver.major = TTYAUX_MAJOR; + callout_driver.subtype = SERIAL_TYPE_CALLOUT; + /* callout_driver.read_proc = 0; */ + /* callout_driver.proc_entry = 0; */ + + if (tty_register_driver(&serial_driver)) + panic("Couldn't register serial driver\n"); + if (tty_register_driver(&callout_driver)) + panic("Couldn't register callout driver\n"); + + cp = pquicc; /* Get pointer to Communication Processor */ + /* immap = (immap_t *)IMAP_ADDR; */ /* and to internal registers */ + + + /* Configure SCC2, SCC3, and SCC4 instead of port A parallel I/O. + */ + /* The "standard" configuration through the 860. + */ +/* immap->im_ioport.iop_papar |= 0x00fc; */ +/* immap->im_ioport.iop_padir &= ~0x00fc; */ +/* immap->im_ioport.iop_paodr &= ~0x00fc; */ + cp->pio_papar |= 0x00fc; + cp->pio_padir &= ~0x00fc; + /* cp->pio_paodr &= ~0x00fc; */ + + + /* Since we don't yet do modem control, connect the port C pins + * as general purpose I/O. This will assert CTS and CD for the + * SCC ports. + */ + /* FIXME: see 360um p.7-365 and 860um p.34-12 + * I can't make sense of these bits - mleslie*/ +/* immap->im_ioport.iop_pcdir |= 0x03c6; */ +/* immap->im_ioport.iop_pcpar &= ~0x03c6; */ + +/* cp->pio_pcdir |= 0x03c6; */ +/* cp->pio_pcpar &= ~0x03c6; */ + + + + /* Connect SCC2 and SCC3 to NMSI. Connect BRG3 to SCC2 and + * BRG4 to SCC3. + */ + cp->si_sicr &= ~0x00ffff00; + cp->si_sicr |= 0x001b1200; + +#ifdef CONFIG_PP04 + /* Frequentis PP04 forced to RS-232 until we know better. + * Port C 12 and 13 low enables RS-232 on SCC3 and SCC4. + */ + immap->im_ioport.iop_pcdir |= 0x000c; + immap->im_ioport.iop_pcpar &= ~0x000c; + immap->im_ioport.iop_pcdat &= ~0x000c; + + /* This enables the TX driver. + */ + cp->cp_pbpar &= ~0x6000; + cp->cp_pbdat &= ~0x6000; +#endif + + for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) { + state->magic = SSTATE_MAGIC; + state->line = i; + state->type = PORT_UNKNOWN; + state->custom_divisor = 0; + state->close_delay = 5*HZ/10; + state->closing_wait = 30*HZ; + state->callout_termios = callout_driver.init_termios; + state->normal_termios = serial_driver.init_termios; + state->icount.cts = state->icount.dsr = + state->icount.rng = state->icount.dcd = 0; + state->icount.rx = state->icount.tx = 0; + state->icount.frame = state->icount.parity = 0; + state->icount.overrun = state->icount.brk = 0; + printk(KERN_INFO "ttyS%02d at irq 0x%02x is an %s\n", + i, (unsigned int)(state->irq), + (state->smc_scc_num & NUM_IS_SCC) ? "SCC" : "SMC"); + +#ifdef CONFIG_SERIAL_CONSOLE + /* If we just printed the message on the console port, and + * we are about to initialize it for general use, we have + * to wait a couple of character times for the CR/NL to + * make it out of the transmit buffer. + */ + if (i == CONFIG_SERIAL_CONSOLE_PORT) + mdelay(8); + + +/* idx = PORT_NUM(info->state->smc_scc_num); */ +/* if (info->state->smc_scc_num & NUM_IS_SCC) */ +/* chan = scc_chan_map[idx]; */ +/* else */ +/* chan = smc_chan_map[idx]; */ + +/* cp->cp_cr = mk_cr_cmd(chan, CPM_CR_STOP_TX) | CPM_CR_FLG; */ +/* while (cp->cp_cr & CPM_CR_FLG); */ + +#endif + /* info = kmalloc(sizeof(ser_info_t), GFP_KERNEL); */ + info = &quicc_ser_info[i]; + if (info) { + /* __clear_user(info,sizeof(ser_info_t)); */ + memset (info, 0, sizeof(ser_info_t)); + init_waitqueue_head(&info->open_wait); + init_waitqueue_head(&info->close_wait); + info->magic = SERIAL_MAGIC; + info->flags = state->flags; + info->tqueue.routine = do_softint; + info->tqueue.data = info; + info->tqueue_hangup.routine = do_serial_hangup; + info->tqueue_hangup.data = info; + info->line = i; + info->state = state; + state->info = (struct async_struct *)info; + + /* We need to allocate a transmit and receive buffer + * descriptors from dual port ram, and a character + * buffer area from host mem. + */ + dp_addr = m360_cpm_dpalloc(sizeof(QUICC_BD) * RX_NUM_FIFO); + + /* Allocate space for FIFOs in the host memory. + * (for now this is from a static array of buffers :( + */ + /* mem_addr = m360_cpm_hostalloc(RX_NUM_FIFO * RX_BUF_SIZE); */ + /* mem_addr = kmalloc (RX_NUM_FIFO * RX_BUF_SIZE, GFP_BUFFER); */ + mem_addr = &rx_buf_pool[i * RX_NUM_FIFO * RX_BUF_SIZE]; + + /* Set the physical address of the host memory + * buffers in the buffer descriptors, and the + * virtual address for us to work with. + */ + bdp = (QUICC_BD *)((uint)pquicc + dp_addr); + info->rx_cur = info->rx_bd_base = bdp; + + /* initialize rx buffer descriptors */ + for (j=0; j<(RX_NUM_FIFO-1); j++) { + bdp->buf = &rx_buf_pool[(i * RX_NUM_FIFO + j ) * RX_BUF_SIZE]; + bdp->status = BD_SC_EMPTY | BD_SC_INTRPT; + mem_addr += RX_BUF_SIZE; + bdp++; + } + bdp->buf = &rx_buf_pool[(i * RX_NUM_FIFO + j ) * RX_BUF_SIZE]; + bdp->status = BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT; + + + idx = PORT_NUM(info->state->smc_scc_num); + if (info->state->smc_scc_num & NUM_IS_SCC) { + +#if defined (CONFIG_UCQUICC) && 1 + /* set the transceiver mode to RS232 */ + sipex_mode_bits &= ~(uint)SIPEX_MODE(idx,0x0f); /* clear current mode */ + sipex_mode_bits |= (uint)SIPEX_MODE(idx,0x02); + *(uint *)_periph_base = sipex_mode_bits; + /* printk ("sipex bits = 0x%08x\n", sipex_mode_bits); */ +#endif + + scp = &pquicc->scc_regs[idx]; + sup = &pquicc->pram[info->state->port].scc.pscc.u; + sup->rbase = dp_addr; + } + else { + sp = &cp->smc_regs[idx]; + up = &pquicc->pram[info->state->port].scc.pothers.idma_smc.psmc.u; + up->rbase = dp_addr; + } + + dp_addr = m360_cpm_dpalloc(sizeof(QUICC_BD) * TX_NUM_FIFO); + + /* Allocate space for FIFOs in the host memory. + */ + /* mem_addr = m360_cpm_hostalloc(TX_NUM_FIFO * TX_BUF_SIZE); */ + /* mem_addr = kmalloc (TX_NUM_FIFO * TX_BUF_SIZE, GFP_BUFFER); */ + mem_addr = &tx_buf_pool[i * TX_NUM_FIFO * TX_BUF_SIZE]; + + /* Set the physical address of the host memory + * buffers in the buffer descriptors, and the + * virtual address for us to work with. + */ + /* bdp = (QUICC_BD *)&cp->cp_dpmem[dp_addr]; */ + bdp = (QUICC_BD *)((uint)pquicc + dp_addr); + info->tx_cur = info->tx_bd_base = (QUICC_BD *)bdp; + + /* initialize tx buffer descriptors */ + for (j=0; j<(TX_NUM_FIFO-1); j++) { + bdp->buf = &tx_buf_pool[(i * TX_NUM_FIFO + j ) * TX_BUF_SIZE]; + bdp->status = BD_SC_INTRPT; + mem_addr += TX_BUF_SIZE; + bdp++; + } + bdp->buf = &tx_buf_pool[(i * TX_NUM_FIFO + j ) * TX_BUF_SIZE]; + bdp->status = (BD_SC_WRAP | BD_SC_INTRPT); + + if (info->state->smc_scc_num & NUM_IS_SCC) { + sup->tbase = dp_addr; + + /* Set up the uart parameters in the + * parameter ram. + */ + sup->rfcr = SMC_EB; + sup->tfcr = SMC_EB; + + /* Set this to 1 for now, so we get single + * character interrupts. Using idle charater + * time requires some additional tuning. + */ + sup->mrblr = 1; + sup->max_idl = 0; + sup->brkcr = 1; + sup->parec = 0; + sup->frmer = 0; + sup->nosec = 0; + sup->brkec = 0; + sup->uaddr1 = 0; + sup->uaddr2 = 0; + sup->toseq = 0; + { + int i; + for (i=0;i<8;i++) + sup->cc[i] = 0x8000; + } + sup->rccm = 0xc0ff; + + /* Send the CPM an initialize command. + */ + chan = scc_chan_map[idx]; + + /* execute the INIT RX & TX PARAMS command for this channel. */ + cp->cp_cr = mk_cr_cmd(chan, CPM_CR_INIT_TRX) | CPM_CR_FLG; + while (cp->cp_cr & CPM_CR_FLG); + + /* Set UART mode, 8 bit, no parity, one stop. + * Enable receive and transmit. + */ + scp->scc_gsmr.w.high = 0; + scp->scc_gsmr.w.low = + (SCC_GSMRL_MODE_UART | SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16); + + /* Disable all interrupts and clear all pending + * events. + */ + scp->scc_sccm = 0; + scp->scc_scce = 0xffff; + scp->scc_dsr = 0x7e7e; + scp->scc_psmr = 0x3000; + + /* If the port is the console, enable Rx and Tx. + */ +#ifdef CONFIG_SERIAL_CONSOLE + if (i == CONFIG_SERIAL_CONSOLE_PORT) + scp->scc_gsmr.w.low |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT); +#endif + } + else { + /* Configure SMCs Tx/Rx instead of port B + * parallel I/O. + */ + + iobits = 0xc0 << (idx * 4); + cp->pip_pbpar |= iobits; + cp->pip_pbdir &= ~iobits; + cp->pip_pbodr &= ~iobits; + + + /* Connect the baud rate generator to the + * SMC based upon index in rs_table. Also + * make sure it is connected to NMSI. + */ + cp->si_simode &= ~(0xffff << (idx * 16)); + cp->si_simode |= (i << ((idx * 16) + 12)); + + up->tbase = dp_addr; + + /* Set up the uart parameters in the + * parameter ram. + */ + up->rfcr = SMC_EB; + up->tfcr = SMC_EB; + + /* Set this to 1 for now, so we get single + * character interrupts. Using idle charater + * time requires some additional tuning. + */ + up->mrblr = 1; + up->max_idl = 0; + up->brkcr = 1; + + /* Send the CPM an initialize command. + */ + chan = smc_chan_map[idx]; + + cp->cp_cr = mk_cr_cmd(chan, + CPM_CR_INIT_TRX) | CPM_CR_FLG; +#ifdef CONFIG_SERIAL_CONSOLE + if (i == CONFIG_SERIAL_CONSOLE_PORT) + printk(""); +#endif + while (cp->cp_cr & CPM_CR_FLG); + + /* Set UART mode, 8 bit, no parity, one stop. + * Enable receive and transmit. + */ + sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART; + + /* Disable all interrupts and clear all pending + * events. + */ + sp->smc_smcm = 0; + sp->smc_smce = 0xff; + + /* If the port is the console, enable Rx and Tx. + */ +#ifdef CONFIG_SERIAL_CONSOLE + if (i == CONFIG_SERIAL_CONSOLE_PORT) + sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN; +#endif + } + + /* Install interrupt handler. + */ + /* cpm_install_handler(IRQ_MACHSPEC | state->irq, rs_360_interrupt, info); */ + /*request_irq(IRQ_MACHSPEC | state->irq, rs_360_interrupt, */ + request_irq(state->irq, rs_360_interrupt, + IRQ_FLG_LOCK, serial_driver.name, (void *)info); + + /* Set up the baud rate generator. + */ + m360_cpm_setbrg(i, baud_table[baud_idx]); + + } + } + + return 0; +} + + + + + +/* This must always be called before the rs_360_init() function, otherwise + * it blows away the port control information. + */ +//static int __init serial_console_setup( struct console *co, char *options) +int serial_console_setup( struct console *co, char *options) +{ + struct serial_state *ser; + uint mem_addr, dp_addr, bidx, idx, iobits; + int i; + ushort chan; + QUICC_BD *bdp; + volatile QUICC *cp; + volatile struct smc_regs *sp; + volatile struct scc_regs *scp; + volatile struct smc_uart_pram *up; + volatile struct uart_pram *sup; + +/* mleslie TODO: + * add something to the 68k bootloader to store a desired initial console baud rate */ + +/* bd_t *bd; */ /* a board info struct used by EPPC-bug */ +/* bd = (bd_t *)__res; */ + + for (bidx = 0; bidx < (sizeof(baud_table) / sizeof(int)); bidx++) + /* if (bd->bi_baudrate == baud_table[bidx]) */ + if (CONSOLE_BAUDRATE == baud_table[bidx]) + break; + + /* co->cflag = CREAD|CLOCAL|bidx|CS8; */ + baud_idx = bidx; + + ser = rs_table + CONFIG_SERIAL_CONSOLE_PORT; + + cp = pquicc; /* Get pointer to Communication Processor */ + + idx = PORT_NUM(ser->smc_scc_num); + if (ser->smc_scc_num & NUM_IS_SCC) { + scp = &cp->scc_regs[idx]; + /* sup = (scc_uart_t *)&cp->cp_dparam[ser->port]; */ + sup = &pquicc->pram[ser->port].scc.pscc.u; + + /* TODO: need to set up SCC pin assignment etc. here */ + + } + else { + sp = &cp->smc_regs[idx]; + /* up = (smc_uart_t *)&cp->cp_dparam[ser->port]; */ + up = &pquicc->pram[ser->port].scc.pothers.idma_smc.psmc.u; + + iobits = 0xc0 << (idx * 4); + cp->pip_pbpar |= iobits; + cp->pip_pbdir &= ~iobits; + cp->pip_pbodr &= ~iobits; + + /* Connect the baud rate generator to the + * SMC based upon index in rs_table. Also + * make sure it is connected to NMSI. + */ + cp->si_simode &= ~(0xffff << (idx * 16)); + cp->si_simode |= (idx << ((idx * 16) + 12)); + } + + /* When we get here, the CPM has been reset, so we need + * to configure the port. + * We need to allocate a transmit and receive buffer descriptor + * from dual port ram, and a character buffer area from host mem. + */ + + /* Allocate space for two buffer descriptors in the DP ram. + */ + dp_addr = m360_cpm_dpalloc(sizeof(QUICC_BD) * CONSOLE_NUM_FIFO); + + /* Allocate space for two 2 byte FIFOs in the host memory. + */ + /* mem_addr = m360_cpm_hostalloc(8); */ + mem_addr = (uint)console_fifos; + + + /* Set the physical address of the host memory buffers in + * the buffer descriptors. + */ + /* bdp = (QUICC_BD *)&cp->cp_dpmem[dp_addr]; */ + bdp = (QUICC_BD *)((uint)pquicc + dp_addr); + bdp->buf = (char *)mem_addr; + (bdp+1)->buf = (char *)(mem_addr+4); + + /* For the receive, set empty and wrap. + * For transmit, set wrap. + */ + bdp->status = BD_SC_EMPTY | BD_SC_WRAP; + (bdp+1)->status = BD_SC_WRAP; + + /* Set up the uart parameters in the parameter ram. + */ + if (ser->smc_scc_num & NUM_IS_SCC) { + + sup->rbase = dp_addr; + sup->tbase = dp_addr + sizeof(QUICC_BD); + + /* Set up the uart parameters in the + * parameter ram. + */ + sup->rfcr = SMC_EB; + sup->tfcr = SMC_EB; + + /* Set this to 1 for now, so we get single + * character interrupts. Using idle charater + * time requires some additional tuning. + */ + sup->mrblr = 1; + sup->max_idl = 0; + sup->brkcr = 1; + sup->parec = 0; + sup->frmer = 0; + sup->nosec = 0; + sup->brkec = 0; + sup->uaddr1 = 0; + sup->uaddr2 = 0; + sup->toseq = 0; + { + int i; + for (i=0;i<8;i++) + sup->cc[i] = 0x8000; + } + sup->rccm = 0xc0ff; + + /* Send the CPM an initialize command. + */ + chan = scc_chan_map[idx]; + + cp->cp_cr = mk_cr_cmd(chan, CPM_CR_INIT_TRX) | CPM_CR_FLG; + while (cp->cp_cr & CPM_CR_FLG); + + /* Set UART mode, 8 bit, no parity, one stop. + * Enable receive and transmit. + */ + scp->scc_gsmr.w.high = 0; + scp->scc_gsmr.w.low = + (SCC_GSMRL_MODE_UART | SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16); + + /* Disable all interrupts and clear all pending + * events. + */ + scp->scc_sccm = 0; + scp->scc_scce = 0xffff; + scp->scc_dsr = 0x7e7e; + scp->scc_psmr = 0x3000; + + scp->scc_gsmr.w.low |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT); + + } + else { + up->rbase = dp_addr; /* Base of receive buffer desc. */ + up->tbase = dp_addr+sizeof(QUICC_BD); /* Base of xmt buffer desc. */ + up->rfcr = SMC_EB; + up->tfcr = SMC_EB; + + /* Set this to 1 for now, so we get single character interrupts. + */ + up->mrblr = 1; /* receive buffer length */ + up->max_idl = 0; /* wait forever for next char */ + + /* Send the CPM an initialize command. + */ + chan = smc_chan_map[idx]; + cp->cp_cr = mk_cr_cmd(chan, CPM_CR_INIT_TRX) | CPM_CR_FLG; + printk(""); + while (cp->cp_cr & CPM_CR_FLG); + + /* Set UART mode, 8 bit, no parity, one stop. + * Enable receive and transmit. + */ + sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART; + + /* And finally, enable Rx and Tx. + */ + sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN; + } + + /* Set up the baud rate generator. + */ + /* m360_cpm_setbrg((ser - rs_table), bd->bi_baudrate); */ + m360_cpm_setbrg((ser - rs_table), CONSOLE_BAUDRATE); + + return 0; +} + +/* + * Local variables: + * c-indent-level: 4 + * c-basic-offset: 4 + * tab-width: 4 + * End: + */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/serial/Kconfig linux.2.5.45-ac1/drivers/serial/Kconfig --- linux.2.5.45/drivers/serial/Kconfig 2002-10-31 15:05:01.000000000 +0000 +++ linux.2.5.45-ac1/drivers/serial/Kconfig 2002-11-01 16:39:54.000000000 +0000 @@ -325,14 +325,52 @@ (PCI) UltraSPARC systems. Say Y or M if you want to be able to these serial ports. +config SERIAL_68328 + bool "Motorola 68328 serial support" + depends on (M68328 || M68EZ328 || M68VZ328) + help + This driver supports the built-in serial port of the Motorola 68328 + (standard, EZ and VZ varities). + +config SERIAL_68360SMC + bool "Motorola 68360 SMC uart support" + depends on M68360 + help + This driver supports the SMC serial ports of the Motorola 68360 CPU. + +config SERIAL_68360SCC + bool "Motorola 68360 SCC uart support" + depends on M68360 + help + This driver supports the SCC serial ports of the Motorola 68360 CPU. + +config SERIAL_68360 + bool + default y if SERIAL_68360SMC=y || SERIAL_68360SCC=y + +config SERIAL_COLDFIRE + bool "Motorola ColdFire serial support" + depends on COLDFIRE + help + This driver supports the built-in serial ports used on the Motorola + ColdFire family of CPUs. + +config V850E_NB85E_UART + bool "NEC V850E on-chip UART support" + depends V850E_NB85E || V850E2_ANNA + default y +config V850E_NB85E_UART_CONSOLE + bool "Use NEC V850E on-chip UART for console" + depends V850E_NB85E_UART + config SERIAL_CORE tristate default m if SERIAL_AMBA!=y && SERIAL_CLPS711X!=y && SERIAL_21285!=y && !SERIAL_SA1100 && !SERIAL_ANAKIN && !SERIAL_UART00 && SERIAL_8250!=y && !SERIAL_ROCKETPORT && !SERIAL_SUNCORE && (SERIAL_AMBA=m || SERIAL_CLPS711X=m || SERIAL_21285=m || SERIAL_8250=m) - default y if SERIAL_AMBA=y || SERIAL_CLPS711X=y || SERIAL_21285=y || SERIAL_SA1100 || SERIAL_ANAKIN || SERIAL_UART00 || SERIAL_8250=y || SERIAL_ROCKETPORT || SERIAL_SUNCORE + default y if SERIAL_AMBA=y || SERIAL_CLPS711X=y || SERIAL_21285=y || SERIAL_SA1100 || SERIAL_ANAKIN || SERIAL_UART00 || SERIAL_8250=y || SERIAL_ROCKETPORT || SERIAL_SUNCORE || V850E_NB85E_UART config SERIAL_CORE_CONSOLE bool - depends on SERIAL_AMBA_CONSOLE || SERIAL_CLPS711X_CONSOLE || SERIAL_21285_CONSOLE || SERIAL_SA1100_CONSOLE || SERIAL_ANAKIN_CONSOLE || SERIAL_UART00_CONSOLE || SERIAL_8250_CONSOLE || SERIAL_SUNCORE + depends on SERIAL_AMBA_CONSOLE || SERIAL_CLPS711X_CONSOLE || SERIAL_21285_CONSOLE || SERIAL_SA1100_CONSOLE || SERIAL_ANAKIN_CONSOLE || SERIAL_UART00_CONSOLE || SERIAL_8250_CONSOLE || SERIAL_SUNCORE || V850E_NB85E_UART_CONSOLE default y endmenu diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/serial/Makefile linux.2.5.45-ac1/drivers/serial/Makefile --- linux.2.5.45/drivers/serial/Makefile 2002-10-31 14:57:20.000000000 +0000 +++ linux.2.5.45-ac1/drivers/serial/Makefile 2002-10-31 15:05:46.000000000 +0000 @@ -23,5 +23,9 @@ obj-$(CONFIG_SERIAL_SUNZILOG) += sunzilog.o obj-$(CONFIG_SERIAL_SUNSU) += sunsu.o obj-$(CONFIG_SERIAL_SUNSAB) += sunsab.o +obj-$(CONFIG_SERIAL_68328) += 68328serial.o +obj-$(CONFIG_SERIAL_68360) += 68360serial.o +obj-$(CONFIG_SERIAL_COLDFIRE) += mcfserial.o +obj-$(CONFIG_V850E_NB85E_UART) += nb85e_uart.o include $(TOPDIR)/Rules.make diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/serial/mcfserial.c linux.2.5.45-ac1/drivers/serial/mcfserial.c --- linux.2.5.45/drivers/serial/mcfserial.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/drivers/serial/mcfserial.c 2002-10-31 15:05:46.000000000 +0000 @@ -0,0 +1,1869 @@ +/* + * mcfserial.c -- serial driver for ColdFire internal UARTS. + * + * Copyright (C) 1999-2002 Greg Ungerer + * Copyright (c) 2000-2001 Lineo, Inc. + * Copyright (C) 2001-2002 SnapGear Inc. + * + * Based on code from 68332serial.c which was: + * + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + * Copyright (C) 1998 TSHG + * Copyright (c) 1999 Rt-Control Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_LEDMAN +#include +#endif +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mcfserial.h" + +/* + * the only event we use + */ +#undef RS_EVENT_WRITE_WAKEUP +#define RS_EVENT_WRITE_WAKEUP 0 + +struct timer_list mcfrs_timer_struct; + +/* + * Default console baud rate, we use this as the default + * for all ports so init can just open /dev/console and + * keep going. Perhaps one day the cflag settings for the + * console can be used instead. + */ +#if defined(CONFIG_ARNEWSH) || defined(CONFIG_MOTOROLA) || defined(CONFIG_senTec) +#define CONSOLE_BAUD_RATE 19200 +#define DEFAULT_CBAUD B19200 +#endif + +#ifndef CONSOLE_BAUD_RATE +#define CONSOLE_BAUD_RATE 9600 +#define DEFAULT_CBAUD B9600 +#endif + +int mcfrs_console_inited = 0; +int mcfrs_console_port = -1; +int mcfrs_console_baud = CONSOLE_BAUD_RATE; +int mcfrs_console_cbaud = DEFAULT_CBAUD; + +/* + * Driver data structures. + */ +struct tty_driver mcfrs_serial_driver, mcfrs_callout_driver; +static int mcfrs_serial_refcount; + +/* serial subtype definitions */ +#define SERIAL_TYPE_NORMAL 1 +#define SERIAL_TYPE_CALLOUT 2 + +/* number of characters left in xmit buffer before we ask for more */ +#define WAKEUP_CHARS 256 + +/* Debugging... + */ +#undef SERIAL_DEBUG_OPEN +#undef SERIAL_DEBUG_FLOW + +#define _INLINE_ inline + +#define IRQBASE 73 + +/* + * Configuration table, UARTs to look for at startup. + */ +static struct mcf_serial mcfrs_table[] = { + { 0, (MCF_MBAR+MCFUART_BASE1), IRQBASE, ASYNC_BOOT_AUTOCONF }, /* ttyS0 */ + { 0, (MCF_MBAR+MCFUART_BASE2), IRQBASE+1, ASYNC_BOOT_AUTOCONF }, /* ttyS1 */ +}; + + +#define NR_PORTS (sizeof(mcfrs_table) / sizeof(struct mcf_serial)) + +static struct tty_struct *mcfrs_serial_table[NR_PORTS]; +static struct termios *mcfrs_serial_termios[NR_PORTS]; +static struct termios *mcfrs_serial_termios_locked[NR_PORTS]; + +/* + * This is used to figure out the divisor speeds and the timeouts. + */ +static int mcfrs_baud_table[] = { + 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, + 9600, 19200, 38400, 57600, 115200, 230400, 460800, 0 +}; +#define MCFRS_BAUD_TABLE_SIZE \ + (sizeof(mcfrs_baud_table)/sizeof(mcfrs_baud_table[0])) + + +#ifdef CONFIG_MAGIC_SYSRQ +/* + * Magic system request keys. Used for debugging... + */ +extern int magic_sysrq_key(int ch); +#endif + + +/* + * tmp_buf is used as a temporary buffer by serial_write. We need to + * lock it in case the copy_from_user blocks while swapping in a page, + * and some other program tries to do a serial write at the same time. + * Since the lock will only come under contention when the system is + * swapping and available memory is low, it makes sense to share one + * buffer across all the serial ports, since it significantly saves + * memory if large numbers of serial ports are open. + */ +static unsigned char mcfrs_tmp_buf[4096]; /* This is cheating */ +static DECLARE_MUTEX(mcfrs_tmp_buf_sem); + +/* + * Forware declarations... + */ +static void mcfrs_change_speed(struct mcf_serial *info); + + +static inline int serial_paranoia_check(struct mcf_serial *info, + kdev_t device, const char *routine) +{ +#ifdef SERIAL_PARANOIA_CHECK + static const char *badmagic = + "MCFRS(warning): bad magic number for serial struct (%d, %d) in %s\n"; + static const char *badinfo = + "MCFRS(warning): null mcf_serial for (%d, %d) in %s\n"; + + if (!info) { + printk(badinfo, MAJOR(device), MINOR(device), routine); + return 1; + } + if (info->magic != SERIAL_MAGIC) { + printk(badmagic, MAJOR(device), MINOR(device), routine); + return 1; + } +#endif + return 0; +} + +/* + * Sets or clears DTR and RTS on the requested line. + */ +static void mcfrs_setsignals(struct mcf_serial *info, int dtr, int rts) +{ + volatile unsigned char *uartp; + unsigned long flags; + +#if 0 + printk("%s(%d): mcfrs_setsignals(info=%x,dtr=%d,rts=%d)\n", + __FILE__, __LINE__, info, dtr, rts); +#endif + + local_irq_save(flags); + if (dtr >= 0) { +#ifdef MCFPP_DTR0 + if (info->line) + mcf_setppdata(MCFPP_DTR1, (dtr ? 0 : MCFPP_DTR1)); + else + mcf_setppdata(MCFPP_DTR0, (dtr ? 0 : MCFPP_DTR0)); +#endif + } + if (rts >= 0) { + uartp = (volatile unsigned char *) info->addr; + if (rts) { + info->sigs |= TIOCM_RTS; + uartp[MCFUART_UOP1] = MCFUART_UOP_RTS; + } else { + info->sigs &= ~TIOCM_RTS; + uartp[MCFUART_UOP0] = MCFUART_UOP_RTS; + } + } + local_irq_restore(flags); + return; +} + +/* + * Gets values of serial signals. + */ +static int mcfrs_getsignals(struct mcf_serial *info) +{ + volatile unsigned char *uartp; + unsigned long flags; + int sigs; +#if defined(CONFIG_NETtel) && defined(CONFIG_M5307) + unsigned short ppdata; +#endif + +#if 0 + printk("%s(%d): mcfrs_getsignals(info=%x)\n", __FILE__, __LINE__); +#endif + + local_irq_save(flags); + uartp = (volatile unsigned char *) info->addr; + sigs = (uartp[MCFUART_UIPR] & MCFUART_UIPR_CTS) ? 0 : TIOCM_CTS; + sigs |= (info->sigs & TIOCM_RTS); + +#ifdef MCFPP_DCD0 +{ + unsigned int ppdata; + ppdata = mcf_getppdata(); + if (info->line == 0) { + sigs |= (ppdata & MCFPP_DCD0) ? 0 : TIOCM_CD; + sigs |= (ppdata & MCFPP_DTR0) ? 0 : TIOCM_DTR; + } else if (info->line == 1) { + sigs |= (ppdata & MCFPP_DCD1) ? 0 : TIOCM_CD; + sigs |= (ppdata & MCFPP_DTR1) ? 0 : TIOCM_DTR; + } +} +#endif + + local_irq_restore(flags); + return(sigs); +} + +/* + * ------------------------------------------------------------ + * mcfrs_stop() and mcfrs_start() + * + * This routines are called before setting or resetting tty->stopped. + * They enable or disable transmitter interrupts, as necessary. + * ------------------------------------------------------------ + */ +static void mcfrs_stop(struct tty_struct *tty) +{ + volatile unsigned char *uartp; + struct mcf_serial *info = (struct mcf_serial *)tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->device, "mcfrs_stop")) + return; + + local_irq_save(flags); + uartp = (volatile unsigned char *) info->addr; + info->imr &= ~MCFUART_UIR_TXREADY; + uartp[MCFUART_UIMR] = info->imr; + local_irq_restore(flags); +} + +static void mcfrs_start(struct tty_struct *tty) +{ + volatile unsigned char *uartp; + struct mcf_serial *info = (struct mcf_serial *)tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->device, "mcfrs_start")) + return; + + local_irq_save(flags); + if (info->xmit_cnt && info->xmit_buf) { + uartp = (volatile unsigned char *) info->addr; + info->imr |= MCFUART_UIR_TXREADY; + uartp[MCFUART_UIMR] = info->imr; + } + local_irq_restore(flags); +} + +/* + * ---------------------------------------------------------------------- + * + * Here starts the interrupt handling routines. All of the following + * subroutines are declared as inline and are folded into + * mcfrs_interrupt(). They were separated out for readability's sake. + * + * Note: mcfrs_interrupt() is a "fast" interrupt, which means that it + * runs with interrupts turned off. People who may want to modify + * mcfrs_interrupt() should try to keep the interrupt handler as fast as + * possible. After you are done making modifications, it is not a bad + * idea to do: + * + * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer serial.c + * + * and look at the resulting assemble code in serial.s. + * + * - Ted Ts'o (tytso@mit.edu), 7-Mar-93 + * ----------------------------------------------------------------------- + */ + +static _INLINE_ void receive_chars(struct mcf_serial *info, struct pt_regs *regs, unsigned short rx) +{ + volatile unsigned char *uartp; + struct tty_struct *tty = info->tty; + unsigned char status, ch; + + if (!tty) + return; + +#if defined(CONFIG_LEDMAN) + ledman_cmd(LEDMAN_CMD_SET, info->line ? LEDMAN_COM2_RX : LEDMAN_COM1_RX); +#endif + + uartp = (volatile unsigned char *) info->addr; + + while ((status = uartp[MCFUART_USR]) & MCFUART_USR_RXREADY) { + + if (tty->flip.count >= TTY_FLIPBUF_SIZE) + break; + + ch = uartp[MCFUART_URB]; + info->stats.rx++; + +#ifdef CONFIG_MAGIC_SYSRQ + if (mcfrs_console_inited && (info->line == mcfrs_console_port)) { + if (magic_sysrq_key(ch)) + continue; + } +#endif + + tty->flip.count++; + if (status & MCFUART_USR_RXERR) + uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETERR; + if (status & MCFUART_USR_RXBREAK) { + info->stats.rxbreak++; + *tty->flip.flag_buf_ptr++ = TTY_BREAK; + } else if (status & MCFUART_USR_RXPARITY) { + info->stats.rxparity++; + *tty->flip.flag_buf_ptr++ = TTY_PARITY; + } else if (status & MCFUART_USR_RXOVERRUN) { + info->stats.rxoverrun++; + *tty->flip.flag_buf_ptr++ = TTY_OVERRUN; + } else if (status & MCFUART_USR_RXFRAMING) { + info->stats.rxframing++; + *tty->flip.flag_buf_ptr++ = TTY_FRAME; + } else { + *tty->flip.flag_buf_ptr++ = 0; + } + *tty->flip.char_buf_ptr++ = ch; + } + + schedule_work(&tty->flip.work); + return; +} + +static _INLINE_ void transmit_chars(struct mcf_serial *info) +{ + volatile unsigned char *uartp; + +#if defined(CONFIG_LEDMAN) + ledman_cmd(LEDMAN_CMD_SET, info->line ? LEDMAN_COM2_TX : LEDMAN_COM1_TX); +#endif + + uartp = (volatile unsigned char *) info->addr; + + if (info->x_char) { + /* Send special char - probably flow control */ + uartp[MCFUART_UTB] = info->x_char; + info->x_char = 0; + info->stats.tx++; + } + + if ((info->xmit_cnt <= 0) || info->tty->stopped) { + info->imr &= ~MCFUART_UIR_TXREADY; + uartp[MCFUART_UIMR] = info->imr; + return; + } + + while (uartp[MCFUART_USR] & MCFUART_USR_TXREADY) { + uartp[MCFUART_UTB] = info->xmit_buf[info->xmit_tail++]; + info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1); + info->stats.tx++; + if (--info->xmit_cnt <= 0) + break; + } + + if (info->xmit_cnt < WAKEUP_CHARS) + schedule_work(&info->tqueue); + return; +} + +/* + * This is the serial driver's generic interrupt routine + */ +void mcfrs_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + struct mcf_serial *info; + unsigned char isr; + + info = &mcfrs_table[(irq - IRQBASE)]; + isr = (((volatile unsigned char *)info->addr)[MCFUART_UISR]) & info->imr; + + if (isr & MCFUART_UIR_RXREADY) + receive_chars(info, regs, isr); + if (isr & MCFUART_UIR_TXREADY) + transmit_chars(info); +#if 0 + if (isr & MCFUART_UIR_DELTABREAK) { + printk("%s(%d): delta break!\n", __FILE__, __LINE__); + receive_chars(info, regs, isr); + } +#endif + + return; +} + +/* + * ------------------------------------------------------------------- + * Here ends the serial interrupt routines. + * ------------------------------------------------------------------- + */ + +static void mcfrs_offintr(void *private) +{ + struct mcf_serial *info = (struct mcf_serial *) private; + struct tty_struct *tty; + + tty = info->tty; + if (!tty) + return; + + if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) { + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + tty->ldisc.write_wakeup) + (tty->ldisc.write_wakeup)(tty); + wake_up_interruptible(&tty->write_wait); + } +} + + +/* + * Change of state on a DCD line. + */ +void mcfrs_modem_change(struct mcf_serial *info, int dcd) +{ + if (info->count == 0) + return; + + if (info->flags & ASYNC_CHECK_CD) { + if (dcd) { + wake_up_interruptible(&info->open_wait); + } else if (!((info->flags & ASYNC_CALLOUT_ACTIVE) && + (info->flags & ASYNC_CALLOUT_NOHUP))) { + schedule_work(&info->tqueue_hangup); + } + } +} + + +#ifdef MCFPP_DCD0 + +unsigned short mcfrs_ppstatus; + +/* + * This subroutine is called when the RS_TIMER goes off. It is used + * to monitor the state of the DCD lines - since they have no edge + * sensors and interrupt generators. + */ +static void mcfrs_timer(void) +{ + unsigned int ppstatus, dcdval, i; + + ppstatus = mcf_getppdata() & (MCFPP_DCD0 | MCFPP_DCD1); + + if (ppstatus != mcfrs_ppstatus) { + for (i = 0; (i < 2); i++) { + dcdval = (i ? MCFPP_DCD1 : MCFPP_DCD0); + if ((ppstatus & dcdval) != (mcfrs_ppstatus & dcdval)) { + mcfrs_modem_change(&mcfrs_table[i], + ((ppstatus & dcdval) ? 0 : 1)); + } + } + } + mcfrs_ppstatus = ppstatus; + + /* Re-arm timer */ + mcfrs_timer_struct.expires = jiffies + HZ/25; + add_timer(&mcfrs_timer_struct); +} + +#endif /* MCFPP_DCD0 */ + + +/* + * This routine is called from the scheduler tqueue when the interrupt + * routine has signalled that a hangup has occurred. The path of + * hangup processing is: + * + * serial interrupt routine -> (scheduler tqueue) -> + * do_serial_hangup() -> tty->hangup() -> mcfrs_hangup() + * + */ +static void do_serial_hangup(void *private) +{ + struct mcf_serial *info = (struct mcf_serial *) private; + struct tty_struct *tty; + + tty = info->tty; + if (!tty) + return; + + tty_hangup(tty); +} + +static int startup(struct mcf_serial * info) +{ + volatile unsigned char *uartp; + unsigned long flags; + + if (info->flags & ASYNC_INITIALIZED) + return 0; + + if (!info->xmit_buf) { + info->xmit_buf = (unsigned char *) __get_free_page(GFP_KERNEL); + if (!info->xmit_buf) + return -ENOMEM; + } + + local_irq_save(flags); + +#ifdef SERIAL_DEBUG_OPEN + printk("starting up ttyS%d (irq %d)...\n", info->line, info->irq); +#endif + + /* + * Reset UART, get it into known state... + */ + uartp = (volatile unsigned char *) info->addr; + uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETRX; /* reset RX */ + uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETTX; /* reset TX */ + mcfrs_setsignals(info, 1, 1); + + if (info->tty) + clear_bit(TTY_IO_ERROR, &info->tty->flags); + info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; + + /* + * and set the speed of the serial port + */ + mcfrs_change_speed(info); + + /* + * Lastly enable the UART transmitter and receiver, and + * interrupt enables. + */ + info->imr = MCFUART_UIR_RXREADY; + uartp[MCFUART_UCR] = MCFUART_UCR_RXENABLE | MCFUART_UCR_TXENABLE; + uartp[MCFUART_UIMR] = info->imr; + + info->flags |= ASYNC_INITIALIZED; + local_irq_restore(flags); + return 0; +} + +/* + * This routine will shutdown a serial port; interrupts are disabled, and + * DTR is dropped if the hangup on close termio flag is on. + */ +static void shutdown(struct mcf_serial * info) +{ + volatile unsigned char *uartp; + unsigned long flags; + + if (!(info->flags & ASYNC_INITIALIZED)) + return; + +#ifdef SERIAL_DEBUG_OPEN + printk("Shutting down serial port %d (irq %d)....\n", info->line, + info->irq); +#endif + + local_irq_save(flags); + + uartp = (volatile unsigned char *) info->addr; + uartp[MCFUART_UIMR] = 0; /* mask all interrupts */ + uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETRX; /* reset RX */ + uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETTX; /* reset TX */ + + if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) + mcfrs_setsignals(info, 0, 0); + + if (info->xmit_buf) { + free_page((unsigned long) info->xmit_buf); + info->xmit_buf = 0; + } + + if (info->tty) + set_bit(TTY_IO_ERROR, &info->tty->flags); + + info->flags &= ~ASYNC_INITIALIZED; + local_irq_restore(flags); +} + + +/* + * This routine is called to set the UART divisor registers to match + * the specified baud rate for a serial port. + */ +static void mcfrs_change_speed(struct mcf_serial *info) +{ + volatile unsigned char *uartp; + unsigned int baudclk, cflag; + unsigned long flags; + unsigned char mr1, mr2; + int i; + + if (!info->tty || !info->tty->termios) + return; + cflag = info->tty->termios->c_cflag; + if (info->addr == 0) + return; + +#if 0 + printk("%s(%d): mcfrs_change_speed()\n", __FILE__, __LINE__); +#endif + + i = cflag & CBAUD; + if (i & CBAUDEX) { + i &= ~CBAUDEX; + if (i < 1 || i > 4) + info->tty->termios->c_cflag &= ~CBAUDEX; + else + i += 15; + } + if (i == 0) { + mcfrs_setsignals(info, 0, -1); + return; + } + baudclk = ((MCF_BUSCLK / mcfrs_baud_table[i]) + 16) / 32; + info->baud = mcfrs_baud_table[i]; + + mr1 = MCFUART_MR1_RXIRQRDY | MCFUART_MR1_RXERRCHAR; + mr2 = 0; + + switch (cflag & CSIZE) { + case CS5: mr1 |= MCFUART_MR1_CS5; break; + case CS6: mr1 |= MCFUART_MR1_CS6; break; + case CS7: mr1 |= MCFUART_MR1_CS7; break; + case CS8: + default: mr1 |= MCFUART_MR1_CS8; break; + } + + if (cflag & PARENB) { + if (cflag & PARODD) + mr1 |= MCFUART_MR1_PARITYODD; + else + mr1 |= MCFUART_MR1_PARITYEVEN; + } else { + mr1 |= MCFUART_MR1_PARITYNONE; + } + + if (cflag & CSTOPB) + mr2 |= MCFUART_MR2_STOP2; + else + mr2 |= MCFUART_MR2_STOP1; + + if (cflag & CRTSCTS) { + mr1 |= MCFUART_MR1_RXRTS; + mr2 |= MCFUART_MR2_TXCTS; + } + + if (cflag & CLOCAL) + info->flags &= ~ASYNC_CHECK_CD; + else + info->flags |= ASYNC_CHECK_CD; + + uartp = (volatile unsigned char *) info->addr; + + local_irq_save(flags); +#if 0 + printk("%s(%d): mr1=%x mr2=%x baudclk=%x\n", __FILE__, __LINE__, + mr1, mr2, baudclk); +#endif + /* + Note: pg 12-16 of MCF5206e User's Manual states that a + software reset should be performed prior to changing + UMR1,2, UCSR, UACR, bit 7 + */ + uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETRX; /* reset RX */ + uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETTX; /* reset TX */ + uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETMRPTR; /* reset MR pointer */ + uartp[MCFUART_UMR] = mr1; + uartp[MCFUART_UMR] = mr2; + uartp[MCFUART_UBG1] = (baudclk & 0xff00) >> 8; /* set msb byte */ + uartp[MCFUART_UBG2] = (baudclk & 0xff); /* set lsb byte */ + uartp[MCFUART_UCSR] = MCFUART_UCSR_RXCLKTIMER | MCFUART_UCSR_TXCLKTIMER; + uartp[MCFUART_UCR] = MCFUART_UCR_RXENABLE | MCFUART_UCR_TXENABLE; + mcfrs_setsignals(info, 1, -1); + local_irq_restore(flags); + return; +} + +static void mcfrs_flush_chars(struct tty_struct *tty) +{ + volatile unsigned char *uartp; + struct mcf_serial *info = (struct mcf_serial *)tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->device, "mcfrs_flush_chars")) + return; + + if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || + !info->xmit_buf) + return; + + /* Enable transmitter */ + local_irq_save(flags); + uartp = (volatile unsigned char *) info->addr; + info->imr |= MCFUART_UIR_TXREADY; + uartp[MCFUART_UIMR] = info->imr; + local_irq_restore(flags); +} + +static int mcfrs_write(struct tty_struct * tty, int from_user, + const unsigned char *buf, int count) +{ + volatile unsigned char *uartp; + struct mcf_serial *info = (struct mcf_serial *)tty->driver_data; + unsigned long flags; + int c, total = 0; + +#if 0 + printk("%s(%d): mcfrs_write(tty=%x,from_user=%d,buf=%x,count=%d)\n", + __FILE__, __LINE__, tty, from_user, buf, count); +#endif + + if (serial_paranoia_check(info, tty->device, "mcfrs_write")) + return 0; + + if (!tty || !info->xmit_buf) + return 0; + + local_save_flags(flags); + while (1) { + local_irq_disable(); + c = min(count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, + SERIAL_XMIT_SIZE - info->xmit_head)); + + if (c <= 0) { + local_irq_restore(flags); + break; + } + + if (from_user) { + down(&mcfrs_tmp_buf_sem); + copy_from_user(mcfrs_tmp_buf, buf, c); + local_irq_restore(flags); + local_irq_disable(); + c = min(c, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, + SERIAL_XMIT_SIZE - info->xmit_head)); + memcpy(info->xmit_buf + info->xmit_head, mcfrs_tmp_buf, c); + up(&mcfrs_tmp_buf_sem); + } else + memcpy(info->xmit_buf + info->xmit_head, buf, c); + + info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1); + info->xmit_cnt += c; + local_irq_restore(flags); + + buf += c; + count -= c; + total += c; + } + + local_irq_disable(); + uartp = (volatile unsigned char *) info->addr; + info->imr |= MCFUART_UIR_TXREADY; + uartp[MCFUART_UIMR] = info->imr; + local_irq_restore(flags); + + return total; +} + +static int mcfrs_write_room(struct tty_struct *tty) +{ + struct mcf_serial *info = (struct mcf_serial *)tty->driver_data; + int ret; + + if (serial_paranoia_check(info, tty->device, "mcfrs_write_room")) + return 0; + ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1; + if (ret < 0) + ret = 0; + return ret; +} + +static int mcfrs_chars_in_buffer(struct tty_struct *tty) +{ + struct mcf_serial *info = (struct mcf_serial *)tty->driver_data; + + if (serial_paranoia_check(info, tty->device, "mcfrs_chars_in_buffer")) + return 0; + return info->xmit_cnt; +} + +static void mcfrs_flush_buffer(struct tty_struct *tty) +{ + struct mcf_serial *info = (struct mcf_serial *)tty->driver_data; + unsigned long flags; + + if (serial_paranoia_check(info, tty->device, "mcfrs_flush_buffer")) + return; + + local_irq_save(flags); + info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; + local_irq_restore(flags); + + wake_up_interruptible(&tty->write_wait); + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + tty->ldisc.write_wakeup) + (tty->ldisc.write_wakeup)(tty); +} + +/* + * ------------------------------------------------------------ + * mcfrs_throttle() + * + * This routine is called by the upper-layer tty layer to signal that + * incoming characters should be throttled. + * ------------------------------------------------------------ + */ +static void mcfrs_throttle(struct tty_struct * tty) +{ + struct mcf_serial *info = (struct mcf_serial *)tty->driver_data; +#ifdef SERIAL_DEBUG_THROTTLE + char buf[64]; + + printk("throttle %s: %d....\n", _tty_name(tty, buf), + tty->ldisc.chars_in_buffer(tty)); +#endif + + if (serial_paranoia_check(info, tty->device, "mcfrs_throttle")) + return; + + if (I_IXOFF(tty)) + info->x_char = STOP_CHAR(tty); + + /* Turn off RTS line (do this atomic) */ +} + +static void mcfrs_unthrottle(struct tty_struct * tty) +{ + struct mcf_serial *info = (struct mcf_serial *)tty->driver_data; +#ifdef SERIAL_DEBUG_THROTTLE + char buf[64]; + + printk("unthrottle %s: %d....\n", _tty_name(tty, buf), + tty->ldisc.chars_in_buffer(tty)); +#endif + + if (serial_paranoia_check(info, tty->device, "mcfrs_unthrottle")) + return; + + if (I_IXOFF(tty)) { + if (info->x_char) + info->x_char = 0; + else + info->x_char = START_CHAR(tty); + } + + /* Assert RTS line (do this atomic) */ +} + +/* + * ------------------------------------------------------------ + * mcfrs_ioctl() and friends + * ------------------------------------------------------------ + */ + +static int get_serial_info(struct mcf_serial * info, + struct serial_struct * retinfo) +{ + struct serial_struct tmp; + + if (!retinfo) + return -EFAULT; + memset(&tmp, 0, sizeof(tmp)); + tmp.type = info->type; + tmp.line = info->line; + tmp.port = info->addr; + tmp.irq = info->irq; + tmp.flags = info->flags; + tmp.baud_base = info->baud_base; + tmp.close_delay = info->close_delay; + tmp.closing_wait = info->closing_wait; + tmp.custom_divisor = info->custom_divisor; + copy_to_user(retinfo,&tmp,sizeof(*retinfo)); + return 0; +} + +static int set_serial_info(struct mcf_serial * info, + struct serial_struct * new_info) +{ + struct serial_struct new_serial; + struct mcf_serial old_info; + int retval = 0; + + if (!new_info) + return -EFAULT; + copy_from_user(&new_serial,new_info,sizeof(new_serial)); + old_info = *info; + + if (!capable(CAP_SYS_ADMIN)) { + if ((new_serial.baud_base != info->baud_base) || + (new_serial.type != info->type) || + (new_serial.close_delay != info->close_delay) || + ((new_serial.flags & ~ASYNC_USR_MASK) != + (info->flags & ~ASYNC_USR_MASK))) + return -EPERM; + info->flags = ((info->flags & ~ASYNC_USR_MASK) | + (new_serial.flags & ASYNC_USR_MASK)); + info->custom_divisor = new_serial.custom_divisor; + goto check_and_exit; + } + + if (info->count > 1) + return -EBUSY; + + /* + * OK, past this point, all the error checking has been done. + * At this point, we start making changes..... + */ + + info->baud_base = new_serial.baud_base; + info->flags = ((info->flags & ~ASYNC_FLAGS) | + (new_serial.flags & ASYNC_FLAGS)); + info->type = new_serial.type; + info->close_delay = new_serial.close_delay; + info->closing_wait = new_serial.closing_wait; + +check_and_exit: + retval = startup(info); + return retval; +} + +/* + * get_lsr_info - get line status register info + * + * Purpose: Let user call ioctl() to get info when the UART physically + * is emptied. On bus types like RS485, the transmitter must + * release the bus after transmitting. This must be done when + * the transmit shift register is empty, not be done when the + * transmit holding register is empty. This functionality + * allows an RS485 driver to be written in user space. + */ +static int get_lsr_info(struct mcf_serial * info, unsigned int *value) +{ + volatile unsigned char *uartp; + unsigned long flags; + unsigned char status; + + local_irq_save(flags); + uartp = (volatile unsigned char *) info->addr; + status = (uartp[MCFUART_USR] & MCFUART_USR_TXEMPTY) ? TIOCSER_TEMT : 0; + local_irq_restore(flags); + + put_user(status,value); + return 0; +} + +/* + * This routine sends a break character out the serial port. + */ +static void send_break( struct mcf_serial * info, int duration) +{ + volatile unsigned char *uartp; + unsigned long flags; + + if (!info->addr) + return; + current->state = TASK_INTERRUPTIBLE; + uartp = (volatile unsigned char *) info->addr; + + local_irq_save(flags); + uartp[MCFUART_UCR] = MCFUART_UCR_CMDBREAKSTART; + schedule_timeout(jiffies + duration); + uartp[MCFUART_UCR] = MCFUART_UCR_CMDBREAKSTOP; + local_irq_restore(flags); +} + +static int mcfrs_ioctl(struct tty_struct *tty, struct file * file, + unsigned int cmd, unsigned long arg) +{ + struct mcf_serial * info = (struct mcf_serial *)tty->driver_data; + unsigned int val; + int retval, error; + int dtr, rts; + + if (serial_paranoia_check(info, tty->device, "mcfrs_ioctl")) + return -ENODEV; + + if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && + (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD) && + (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT)) { + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; + } + + switch (cmd) { + case TCSBRK: /* SVID version: non-zero arg --> no break */ + retval = tty_check_change(tty); + if (retval) + return retval; + tty_wait_until_sent(tty, 0); + if (!arg) + send_break(info, HZ/4); /* 1/4 second */ + return 0; + case TCSBRKP: /* support for POSIX tcsendbreak() */ + retval = tty_check_change(tty); + if (retval) + return retval; + tty_wait_until_sent(tty, 0); + send_break(info, arg ? arg*(HZ/10) : HZ/4); + return 0; + case TIOCGSOFTCAR: + error = verify_area(VERIFY_WRITE, (void *) arg,sizeof(long)); + if (error) + return error; + put_user(C_CLOCAL(tty) ? 1 : 0, + (unsigned long *) arg); + return 0; + case TIOCSSOFTCAR: + get_user(arg, (unsigned long *) arg); + tty->termios->c_cflag = + ((tty->termios->c_cflag & ~CLOCAL) | + (arg ? CLOCAL : 0)); + return 0; + case TIOCGSERIAL: + error = verify_area(VERIFY_WRITE, (void *) arg, + sizeof(struct serial_struct)); + if (error) + return error; + return get_serial_info(info, + (struct serial_struct *) arg); + case TIOCSSERIAL: + return set_serial_info(info, + (struct serial_struct *) arg); + case TIOCSERGETLSR: /* Get line status register */ + error = verify_area(VERIFY_WRITE, (void *) arg, + sizeof(unsigned int)); + if (error) + return error; + else + return get_lsr_info(info, (unsigned int *) arg); + + case TIOCSERGSTRUCT: + error = verify_area(VERIFY_WRITE, (void *) arg, + sizeof(struct mcf_serial)); + if (error) + return error; + copy_to_user((struct mcf_serial *) arg, + info, sizeof(struct mcf_serial)); + return 0; + + case TIOCMGET: + if ((error = verify_area(VERIFY_WRITE, (void *) arg, + sizeof(unsigned int)))) + return(error); + val = mcfrs_getsignals(info); + put_user(val, (unsigned int *) arg); + break; + + case TIOCMBIS: + if ((error = verify_area(VERIFY_WRITE, (void *) arg, + sizeof(unsigned int)))) + return(error); + + get_user(val, (unsigned int *) arg); + rts = (val & TIOCM_RTS) ? 1 : -1; + dtr = (val & TIOCM_DTR) ? 1 : -1; + mcfrs_setsignals(info, dtr, rts); + break; + + case TIOCMBIC: + if ((error = verify_area(VERIFY_WRITE, (void *) arg, + sizeof(unsigned int)))) + return(error); + get_user(val, (unsigned int *) arg); + rts = (val & TIOCM_RTS) ? 0 : -1; + dtr = (val & TIOCM_DTR) ? 0 : -1; + mcfrs_setsignals(info, dtr, rts); + break; + + case TIOCMSET: + if ((error = verify_area(VERIFY_WRITE, (void *) arg, + sizeof(unsigned int)))) + return(error); + get_user(val, (unsigned int *) arg); + rts = (val & TIOCM_RTS) ? 1 : 0; + dtr = (val & TIOCM_DTR) ? 1 : 0; + mcfrs_setsignals(info, dtr, rts); + break; + +#ifdef TIOCSET422 + case TIOCSET422: + get_user(val, (unsigned int *) arg); + mcf_setpa(MCFPP_PA11, (val ? 0 : MCFPP_PA11)); + break; + case TIOCGET422: + val = (mcf_getpa() & MCFPP_PA11) ? 0 : 1; + put_user(val, (unsigned int *) arg); + break; +#endif + + default: + return -ENOIOCTLCMD; + } + return 0; +} + +static void mcfrs_set_termios(struct tty_struct *tty, struct termios *old_termios) +{ + struct mcf_serial *info = (struct mcf_serial *)tty->driver_data; + + if (tty->termios->c_cflag == old_termios->c_cflag) + return; + + mcfrs_change_speed(info); + + if ((old_termios->c_cflag & CRTSCTS) && + !(tty->termios->c_cflag & CRTSCTS)) { + tty->hw_stopped = 0; + mcfrs_setsignals(info, -1, 1); +#if 0 + mcfrs_start(tty); +#endif + } +} + +/* + * ------------------------------------------------------------ + * mcfrs_close() + * + * This routine is called when the serial port gets closed. First, we + * wait for the last remaining data to be sent. Then, we unlink its + * S structure from the interrupt chain if necessary, and we free + * that IRQ if nothing is left in the chain. + * ------------------------------------------------------------ + */ +static void mcfrs_close(struct tty_struct *tty, struct file * filp) +{ + volatile unsigned char *uartp; + struct mcf_serial *info = (struct mcf_serial *)tty->driver_data; + unsigned long flags; + + if (!info || serial_paranoia_check(info, tty->device, "mcfrs_close")) + return; + + local_irq_save(flags); + + if (tty_hung_up_p(filp)) { + local_irq_restore(flags); + return; + } + +#ifdef SERIAL_DEBUG_OPEN + printk("mcfrs_close ttyS%d, count = %d\n", info->line, info->count); +#endif + if ((tty->count == 1) && (info->count != 1)) { + /* + * Uh, oh. tty->count is 1, which means that the tty + * structure will be freed. Info->count should always + * be one in these conditions. If it's greater than + * one, we've got real problems, since it means the + * serial port won't be shutdown. + */ + printk("MCFRS: bad serial port count; tty->count is 1, " + "info->count is %d\n", info->count); + info->count = 1; + } + if (--info->count < 0) { + printk("MCFRS: bad serial port count for ttyS%d: %d\n", + info->line, info->count); + info->count = 0; + } + if (info->count) { + local_irq_restore(flags); + return; + } + info->flags |= ASYNC_CLOSING; + + /* + * Save the termios structure, since this port may have + * separate termios for callout and dialin. + */ + if (info->flags & ASYNC_NORMAL_ACTIVE) + info->normal_termios = *tty->termios; + if (info->flags & ASYNC_CALLOUT_ACTIVE) + info->callout_termios = *tty->termios; + + /* + * Now we wait for the transmit buffer to clear; and we notify + * the line discipline to only process XON/XOFF characters. + */ + tty->closing = 1; + if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE) + tty_wait_until_sent(tty, info->closing_wait); + + /* + * At this point we stop accepting input. To do this, we + * disable the receive line status interrupts, and tell the + * interrupt driver to stop checking the data ready bit in the + * line status register. + */ + info->imr &= ~MCFUART_UIR_RXREADY; + uartp = (volatile unsigned char *) info->addr; + uartp[MCFUART_UIMR] = info->imr; + +#if 0 + /* FIXME: do we need to keep this enabled for console?? */ + if (mcfrs_console_inited && (mcfrs_console_port == info->line)) { + /* Do not disable the UART */ ; + } else +#endif + shutdown(info); + if (tty->driver.flush_buffer) + tty->driver.flush_buffer(tty); + if (tty->ldisc.flush_buffer) + tty->ldisc.flush_buffer(tty); + tty->closing = 0; + info->event = 0; + info->tty = 0; + if (tty->ldisc.num != ldiscs[N_TTY].num) { + if (tty->ldisc.close) + (tty->ldisc.close)(tty); + tty->ldisc = ldiscs[N_TTY]; + tty->termios->c_line = N_TTY; + if (tty->ldisc.open) + (tty->ldisc.open)(tty); + } + if (info->blocked_open) { + if (info->close_delay) { + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(info->close_delay); + } + wake_up_interruptible(&info->open_wait); + } + info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE| + ASYNC_CLOSING); + wake_up_interruptible(&info->close_wait); + local_irq_restore(flags); +} + +/* + * mcfrs_hangup() --- called by tty_hangup() when a hangup is signaled. + */ +void mcfrs_hangup(struct tty_struct *tty) +{ + struct mcf_serial * info = (struct mcf_serial *)tty->driver_data; + + if (serial_paranoia_check(info, tty->device, "mcfrs_hangup")) + return; + + mcfrs_flush_buffer(tty); + shutdown(info); + info->event = 0; + info->count = 0; + info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE); + info->tty = 0; + wake_up_interruptible(&info->open_wait); +} + +/* + * ------------------------------------------------------------ + * mcfrs_open() and friends + * ------------------------------------------------------------ + */ +static int block_til_ready(struct tty_struct *tty, struct file * filp, + struct mcf_serial *info) +{ + DECLARE_WAITQUEUE(wait, current); + int retval; + int do_clocal = 0; + + /* + * If the device is in the middle of being closed, then block + * until it's done, and then try again. + */ + if (info->flags & ASYNC_CLOSING) { + interruptible_sleep_on(&info->close_wait); +#ifdef SERIAL_DO_RESTART + if (info->flags & ASYNC_HUP_NOTIFY) + return -EAGAIN; + else + return -ERESTARTSYS; +#else + return -EAGAIN; +#endif + } + + /* + * If this is a callout device, then just make sure the normal + * device isn't being used. + */ + if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) { + if (info->flags & ASYNC_NORMAL_ACTIVE) + return -EBUSY; + if ((info->flags & ASYNC_CALLOUT_ACTIVE) && + (info->flags & ASYNC_SESSION_LOCKOUT) && + (info->session != current->session)) + return -EBUSY; + if ((info->flags & ASYNC_CALLOUT_ACTIVE) && + (info->flags & ASYNC_PGRP_LOCKOUT) && + (info->pgrp != current->pgrp)) + return -EBUSY; + info->flags |= ASYNC_CALLOUT_ACTIVE; + return 0; + } + + /* + * If non-blocking mode is set, or the port is not enabled, + * then make the check up front and then exit. + */ + if ((filp->f_flags & O_NONBLOCK) || + (tty->flags & (1 << TTY_IO_ERROR))) { + if (info->flags & ASYNC_CALLOUT_ACTIVE) + return -EBUSY; + info->flags |= ASYNC_NORMAL_ACTIVE; + return 0; + } + + if (info->flags & ASYNC_CALLOUT_ACTIVE) { + if (info->normal_termios.c_cflag & CLOCAL) + do_clocal = 1; + } else { + if (tty->termios->c_cflag & CLOCAL) + do_clocal = 1; + } + + /* + * Block waiting for the carrier detect and the line to become + * free (i.e., not in use by the callout). While we are in + * this loop, info->count is dropped by one, so that + * mcfrs_close() knows when to free things. We restore it upon + * exit, either normal or abnormal. + */ + retval = 0; + add_wait_queue(&info->open_wait, &wait); +#ifdef SERIAL_DEBUG_OPEN + printk("block_til_ready before block: ttyS%d, count = %d\n", + info->line, info->count); +#endif + info->count--; + info->blocked_open++; + while (1) { + local_irq_disable(); + if (!(info->flags & ASYNC_CALLOUT_ACTIVE)) + mcfrs_setsignals(info, 1, 1); + local_irq_enable(); + current->state = TASK_INTERRUPTIBLE; + if (tty_hung_up_p(filp) || + !(info->flags & ASYNC_INITIALIZED)) { +#ifdef SERIAL_DO_RESTART + if (info->flags & ASYNC_HUP_NOTIFY) + retval = -EAGAIN; + else + retval = -ERESTARTSYS; +#else + retval = -EAGAIN; +#endif + break; + } + if (!(info->flags & ASYNC_CALLOUT_ACTIVE) && + !(info->flags & ASYNC_CLOSING) && + (do_clocal || (mcfrs_getsignals(info) & TIOCM_CD))) + break; + if (signal_pending(current)) { + retval = -ERESTARTSYS; + break; + } +#ifdef SERIAL_DEBUG_OPEN + printk("block_til_ready blocking: ttyS%d, count = %d\n", + info->line, info->count); +#endif + schedule(); + } + current->state = TASK_RUNNING; + remove_wait_queue(&info->open_wait, &wait); + if (!tty_hung_up_p(filp)) + info->count++; + info->blocked_open--; +#ifdef SERIAL_DEBUG_OPEN + printk("block_til_ready after blocking: ttyS%d, count = %d\n", + info->line, info->count); +#endif + if (retval) + return retval; + info->flags |= ASYNC_NORMAL_ACTIVE; + return 0; +} + +/* + * This routine is called whenever a serial port is opened. It + * enables interrupts for a serial port, linking in its structure into + * the IRQ chain. It also performs the serial-specific + * initialization for the tty structure. + */ +int mcfrs_open(struct tty_struct *tty, struct file * filp) +{ + struct mcf_serial *info; + int retval, line; + + line = minor(tty->device) - tty->driver.minor_start; + if ((line < 0) || (line >= NR_PORTS)) + return -ENODEV; + info = mcfrs_table + line; + if (serial_paranoia_check(info, tty->device, "mcfrs_open")) + return -ENODEV; +#ifdef SERIAL_DEBUG_OPEN + printk("mcfrs_open %s%d, count = %d\n", tty->driver.name, info->line, + info->count); +#endif + info->count++; + tty->driver_data = info; + info->tty = tty; + + /* + * Start up serial port + */ + retval = startup(info); + if (retval) + return retval; + + retval = block_til_ready(tty, filp, info); + if (retval) { +#ifdef SERIAL_DEBUG_OPEN + printk("mcfrs_open returning after block_til_ready with %d\n", + retval); +#endif + return retval; + } + + if ((info->count == 1) && (info->flags & ASYNC_SPLIT_TERMIOS)) { + if (tty->driver.subtype == SERIAL_TYPE_NORMAL) + *tty->termios = info->normal_termios; + else + *tty->termios = info->callout_termios; + mcfrs_change_speed(info); + } + + info->session = current->session; + info->pgrp = current->pgrp; + +#ifdef SERIAL_DEBUG_OPEN + printk("mcfrs_open ttyS%d successful...\n", info->line); +#endif + return 0; +} + +/* + * Based on the line number set up the internal interrupt stuff. + */ +static void mcfrs_irqinit(struct mcf_serial *info) +{ +#ifdef CONFIG_M5272 + volatile unsigned long *icrp; + volatile unsigned long *portp; + volatile unsigned char *uartp; + + uartp = (volatile unsigned char *) info->addr; + icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR2); + + switch (info->line) { + case 0: + *icrp = 0xe0000000; + break; + case 1: + *icrp = 0x0e000000; + break; + default: + printk("MCFRS: don't know how to handle UART %d interrupt?\n", + info->line); + return; + } + + /* Enable the output lines for the serial ports */ + portp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_PBCNT); + *portp = (*portp & ~0x000000ff) | 0x00000055; + portp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_PDCNT); + *portp = (*portp & ~0x000003fc) | 0x000002a8; +#else + volatile unsigned char *icrp, *uartp; + + switch (info->line) { + case 0: + icrp = (volatile unsigned char *) (MCF_MBAR + MCFSIM_UART1ICR); + *icrp = /*MCFSIM_ICR_AUTOVEC |*/ MCFSIM_ICR_LEVEL6 | + MCFSIM_ICR_PRI1; + mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_UART1); + break; + case 1: + icrp = (volatile unsigned char *) (MCF_MBAR + MCFSIM_UART2ICR); + *icrp = /*MCFSIM_ICR_AUTOVEC |*/ MCFSIM_ICR_LEVEL6 | + MCFSIM_ICR_PRI2; + mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_UART2); + break; + default: + printk("MCFRS: don't know how to handle UART %d interrupt?\n", + info->line); + return; + } + + uartp = (volatile unsigned char *) info->addr; + uartp[MCFUART_UIVR] = info->irq; +#endif + + /* Clear mask, so no surprise interrupts. */ + uartp[MCFUART_UIMR] = 0; + + if (request_irq(info->irq, mcfrs_interrupt, SA_INTERRUPT, + "ColdFire UART", NULL)) { + printk("MCFRS: Unable to attach ColdFire UART %d interrupt " + "vector=%d\n", info->line, info->irq); + } + + return; +} + + +char *mcfrs_drivername = "ColdFire internal UART serial driver version 1.00\n"; + + +/* + * Serial stats reporting... + */ +int mcfrs_readproc(char *page, char **start, off_t off, int count, + int *eof, void *data) +{ + struct mcf_serial *info; + char str[20]; + int len, sigs, i; + + len = sprintf(page, mcfrs_drivername); + for (i = 0; (i < NR_PORTS); i++) { + info = &mcfrs_table[i]; + len += sprintf((page + len), "%d: port:%x irq=%d baud:%d ", + i, info->addr, info->irq, info->baud); + if (info->stats.rx || info->stats.tx) + len += sprintf((page + len), "tx:%d rx:%d ", + info->stats.tx, info->stats.rx); + if (info->stats.rxframing) + len += sprintf((page + len), "fe:%d ", + info->stats.rxframing); + if (info->stats.rxparity) + len += sprintf((page + len), "pe:%d ", + info->stats.rxparity); + if (info->stats.rxbreak) + len += sprintf((page + len), "brk:%d ", + info->stats.rxbreak); + if (info->stats.rxoverrun) + len += sprintf((page + len), "oe:%d ", + info->stats.rxoverrun); + + str[0] = str[1] = 0; + if ((sigs = mcfrs_getsignals(info))) { + if (sigs & TIOCM_RTS) + strcat(str, "|RTS"); + if (sigs & TIOCM_CTS) + strcat(str, "|CTS"); + if (sigs & TIOCM_DTR) + strcat(str, "|DTR"); + if (sigs & TIOCM_CD) + strcat(str, "|CD"); + } + + len += sprintf((page + len), "%s\n", &str[1]); + } + + return(len); +} + + +/* Finally, routines used to initialize the serial driver. */ + +static void show_serial_version(void) +{ + printk(mcfrs_drivername); +} + +/* mcfrs_init inits the driver */ +static int __init +mcfrs_init(void) +{ + struct mcf_serial *info; + unsigned long flags; + int i; + + /* Setup base handler, and timer table. */ +#ifdef MCFPP_DCD0 + init_timer(&mcfrs_timer_struct); + mcfrs_timer_struct.function = mcfrs_timer; + mcfrs_timer_struct.data = 0; + mcfrs_timer_struct.expires = jiffies + HZ/25; + add_timer(&mcfrs_timer_struct); + mcfrs_ppstatus = mcf_getppdata() & (MCFPP_DCD0 | MCFPP_DCD1); +#endif + + show_serial_version(); + + /* Initialize the tty_driver structure */ + memset(&mcfrs_serial_driver, 0, sizeof(struct tty_driver)); + mcfrs_serial_driver.magic = TTY_DRIVER_MAGIC; + mcfrs_serial_driver.name = "ttyS"; + mcfrs_serial_driver.major = TTY_MAJOR; + mcfrs_serial_driver.minor_start = 64; + mcfrs_serial_driver.num = NR_PORTS; + mcfrs_serial_driver.type = TTY_DRIVER_TYPE_SERIAL; + mcfrs_serial_driver.subtype = SERIAL_TYPE_NORMAL; + mcfrs_serial_driver.init_termios = tty_std_termios; + + mcfrs_serial_driver.init_termios.c_cflag = + mcfrs_console_cbaud | CS8 | CREAD | HUPCL | CLOCAL; + mcfrs_serial_driver.flags = TTY_DRIVER_REAL_RAW; + mcfrs_serial_driver.refcount = &mcfrs_serial_refcount; + mcfrs_serial_driver.table = mcfrs_serial_table; + mcfrs_serial_driver.termios = mcfrs_serial_termios; + mcfrs_serial_driver.termios_locked = mcfrs_serial_termios_locked; + + mcfrs_serial_driver.open = mcfrs_open; + mcfrs_serial_driver.close = mcfrs_close; + mcfrs_serial_driver.write = mcfrs_write; + mcfrs_serial_driver.flush_chars = mcfrs_flush_chars; + mcfrs_serial_driver.write_room = mcfrs_write_room; + mcfrs_serial_driver.chars_in_buffer = mcfrs_chars_in_buffer; + mcfrs_serial_driver.flush_buffer = mcfrs_flush_buffer; + mcfrs_serial_driver.ioctl = mcfrs_ioctl; + mcfrs_serial_driver.throttle = mcfrs_throttle; + mcfrs_serial_driver.unthrottle = mcfrs_unthrottle; + mcfrs_serial_driver.set_termios = mcfrs_set_termios; + mcfrs_serial_driver.stop = mcfrs_stop; + mcfrs_serial_driver.start = mcfrs_start; + mcfrs_serial_driver.hangup = mcfrs_hangup; + mcfrs_serial_driver.read_proc = mcfrs_readproc; + mcfrs_serial_driver.driver_name = "serial"; + + /* + * The callout device is just like normal device except for + * major number and the subtype code. + */ + mcfrs_callout_driver = mcfrs_serial_driver; + mcfrs_callout_driver.name = "cua"; + mcfrs_callout_driver.major = TTYAUX_MAJOR; + mcfrs_callout_driver.subtype = SERIAL_TYPE_CALLOUT; + mcfrs_callout_driver.read_proc = 0; + mcfrs_callout_driver.proc_entry = 0; + + if (tty_register_driver(&mcfrs_serial_driver)) { + printk("MCFRS: Couldn't register serial driver\n"); + return(-EBUSY); + } + if (tty_register_driver(&mcfrs_callout_driver)) { + printk("MCFRS: Couldn't register callout driver\n"); + return(-EBUSY); + } + + local_irq_save(flags); + + /* + * Configure all the attached serial ports. + */ + for (i = 0, info = mcfrs_table; (i < NR_PORTS); i++, info++) { + info->magic = SERIAL_MAGIC; + info->line = i; + info->tty = 0; + info->custom_divisor = 16; + info->close_delay = 50; + info->closing_wait = 3000; + info->x_char = 0; + info->event = 0; + info->count = 0; + info->blocked_open = 0; + INIT_WORK(&info->tqueue, mcfrs_offintr, info); + INIT_WORK(&info->tqueue_hangup, do_serial_hangup, info); + info->callout_termios = mcfrs_callout_driver.init_termios; + info->normal_termios = mcfrs_serial_driver.init_termios; + init_waitqueue_head(&info->open_wait); + init_waitqueue_head(&info->close_wait); + + info->imr = 0; + mcfrs_setsignals(info, 0, 0); + mcfrs_irqinit(info); + + printk("%s%d at 0x%04x (irq = %d)", mcfrs_serial_driver.name, + info->line, info->addr, info->irq); + printk(" is a builtin ColdFire UART\n"); + } + + local_irq_restore(flags); + return 0; +} + +module_init(mcfrs_init); +/* DAVIDM module_exit(mcfrs_fini); */ + +/****************************************************************************/ +/* Serial Console */ +/****************************************************************************/ + +/* + * Quick and dirty UART initialization, for console output. + */ + +void mcfrs_init_console(void) +{ + volatile unsigned char *uartp; + unsigned int clk; + + /* + * Reset UART, get it into known state... + */ + uartp = (volatile unsigned char *) (MCF_MBAR + + (mcfrs_console_port ? MCFUART_BASE2 : MCFUART_BASE1)); + + uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETRX; /* reset RX */ + uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETTX; /* reset TX */ + uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETMRPTR; /* reset MR pointer */ + + /* + * Set port for defined baud , 8 data bits, 1 stop bit, no parity. + */ + uartp[MCFUART_UMR] = MCFUART_MR1_PARITYNONE | MCFUART_MR1_CS8; + uartp[MCFUART_UMR] = MCFUART_MR2_STOP1; + + clk = ((MCF_BUSCLK / mcfrs_console_baud) + 16) / 32; /* set baud */ + uartp[MCFUART_UBG1] = (clk & 0xff00) >> 8; /* set msb baud */ + uartp[MCFUART_UBG2] = (clk & 0xff); /* set lsb baud */ + + uartp[MCFUART_UCSR] = MCFUART_UCSR_RXCLKTIMER | MCFUART_UCSR_TXCLKTIMER; + uartp[MCFUART_UCR] = MCFUART_UCR_RXENABLE | MCFUART_UCR_TXENABLE; + + mcfrs_console_inited++; + return; +} + + +/* + * Setup for console. Argument comes from the boot command line. + */ + +int mcfrs_console_setup(struct console *cp, char *arg) +{ + int i, n = CONSOLE_BAUD_RATE; + + if (!cp) + return(-1); + + if (!strncmp(cp->name, "ttyS", 4)) + mcfrs_console_port = cp->index; + else if (!strncmp(cp->name, "cua", 3)) + mcfrs_console_port = cp->index; + else + return(-1); + + if (arg) + n = simple_strtoul(arg,NULL,0); + for (i = 0; i < MCFRS_BAUD_TABLE_SIZE; i++) + if (mcfrs_baud_table[i] == n) + break; + if (i < MCFRS_BAUD_TABLE_SIZE) { + mcfrs_console_baud = n; + mcfrs_console_cbaud = 0; + if (i > 15) { + mcfrs_console_cbaud |= CBAUDEX; + i -= 15; + } + mcfrs_console_cbaud |= i; + } + mcfrs_init_console(); /* make sure baud rate changes */ + return(0); +} + + +static kdev_t mcfrs_console_device(struct console *c) +{ + return mk_kdev(TTY_MAJOR, 64 + c->index); +} + + +/* + * Output a single character, using UART polled mode. + * This is used for console output. + */ + +void mcfrs_put_char(char ch) +{ + volatile unsigned char *uartp; + unsigned long flags; + int i; + + uartp = (volatile unsigned char *) (MCF_MBAR + + (mcfrs_console_port ? MCFUART_BASE2 : MCFUART_BASE1)); + + local_irq_save(flags); + for (i = 0; (i < 0x10000); i++) { + if (uartp[MCFUART_USR] & MCFUART_USR_TXREADY) + break; + } + if (i < 0x10000) { + uartp[MCFUART_UTB] = ch; + for (i = 0; (i < 0x10000); i++) + if (uartp[MCFUART_USR] & MCFUART_USR_TXEMPTY) + break; + } + if (i >= 0x10000) + mcfrs_init_console(); /* try and get it back */ + local_irq_restore(flags); + + return; +} + + +/* + * rs_console_write is registered for printk output. + */ + +void mcfrs_console_write(struct console *cp, const char *p, unsigned len) +{ + if (!mcfrs_console_inited) + mcfrs_init_console(); + while (len-- > 0) { + if (*p == '\n') + mcfrs_put_char('\r'); + mcfrs_put_char(*p++); + } +} + +/* + * declare our consoles + */ + +struct console mcfrs_console = { + name: "ttyS", + write: mcfrs_console_write, + device: mcfrs_console_device, + setup: mcfrs_console_setup, + flags: CON_PRINTBUFFER, + index: -1, +}; + +void __init mcfrs_console_init(void) +{ + register_console(&mcfrs_console); +} + +/****************************************************************************/ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/serial/mcfserial.h linux.2.5.45-ac1/drivers/serial/mcfserial.h --- linux.2.5.45/drivers/serial/mcfserial.h 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/drivers/serial/mcfserial.h 2002-10-31 15:05:46.000000000 +0000 @@ -0,0 +1,84 @@ +/* + * mcfserial.c -- serial driver for ColdFire internal UARTS. + * + * Copyright (c) 1999 Greg Ungerer + * Copyright (c) 2000-2001 Lineo, Inc. + * Copyright (c) 2002 SnapGear Inc., + * + * Based on code from 68332serial.c which was: + * + * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) + * Copyright (C) 1998 TSHG + * Copyright (c) 1999 Rt-Control Inc. + */ +#ifndef _MCF_SERIAL_H +#define _MCF_SERIAL_H + +#include +#include + +#ifdef __KERNEL__ + +/* + * Define a local serial stats structure. + */ + +struct mcf_stats { + unsigned int rx; + unsigned int tx; + unsigned int rxbreak; + unsigned int rxframing; + unsigned int rxparity; + unsigned int rxoverrun; +}; + + +/* + * This is our internal structure for each serial port's state. + * Each serial port has one of these structures associated with it. + */ + +struct mcf_serial { + int magic; + unsigned int addr; /* UART memory address */ + int irq; + int flags; /* defined in tty.h */ + int type; /* UART type */ + struct tty_struct *tty; + unsigned char imr; /* Software imr register */ + unsigned int baud; + int sigs; + int custom_divisor; + int x_char; /* xon/xoff character */ + int baud_base; + int close_delay; + unsigned short closing_wait; + unsigned short closing_wait2; + unsigned long event; + int line; + int count; /* # of fd on device */ + int blocked_open; /* # of blocked opens */ + long session; /* Session of opening process */ + long pgrp; /* pgrp of opening process */ + unsigned char *xmit_buf; + int xmit_head; + int xmit_tail; + int xmit_cnt; + struct mcf_stats stats; + struct work_struct tqueue; + struct work_struct tqueue_hangup; + struct termios normal_termios; + struct termios callout_termios; +#if LINUX_VERSION_CODE <= 0x020100 + struct wait_queue *open_wait; + struct wait_queue *close_wait; +#else + wait_queue_head_t open_wait; + wait_queue_head_t close_wait; +#endif + +}; + +#endif /* __KERNEL__ */ + +#endif /* _MCF_SERIAL_H */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/serial/nb85e_uart.c linux.2.5.45-ac1/drivers/serial/nb85e_uart.c --- linux.2.5.45/drivers/serial/nb85e_uart.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/drivers/serial/nb85e_uart.c 2002-11-01 16:36:06.000000000 +0000 @@ -0,0 +1,590 @@ +/* + * drivers/serial/nb85e_uart.c -- Serial I/O using V850E/NB85E on-chip UART + * + * Copyright (C) 2001,02 NEC Corporation + * Copyright (C) 2001,02 Miles Bader + * + * 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. + * + * Written by Miles Bader + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/* Initial UART state. This may be overridden by machine-dependent headers. */ +#ifndef NB85E_UART_INIT_BAUD +#define NB85E_UART_INIT_BAUD 115200 +#endif +#ifndef NB85E_UART_INIT_CFLAGS +#define NB85E_UART_INIT_CFLAGS (B115200 | CS8 | CREAD) +#endif + +/* A string used for prefixing printed descriptions; since the same UART + macro is actually used on other chips than the V850E/NB85E. This must + be a constant string. */ +#ifndef NB85E_UART_CHIP_NAME +#define NB85E_UART_CHIP_NAME "V850E/NB85E" +#endif + + +/* Low-level UART functions. */ + +/* These masks define which control bits affect TX/RX modes, respectively. */ +#define RX_BITS \ + (NB85E_UART_ASIM_PS_MASK | NB85E_UART_ASIM_CL_8 | NB85E_UART_ASIM_ISRM) +#define TX_BITS \ + (NB85E_UART_ASIM_PS_MASK | NB85E_UART_ASIM_CL_8 | NB85E_UART_ASIM_SL_2) + +/* The UART require various delays after writing control registers. */ +static inline void nb85e_uart_delay (unsigned cycles) +{ + /* The loop takes 2 insns, so loop CYCLES / 2 times. */ + register unsigned count = cycles >> 1; + while (--count != 0) + /* nothing */; +} + +/* Configure and turn on uart channel CHAN, using the termios `control + modes' bits in CFLAGS, and a baud-rate of BAUD. */ +void nb85e_uart_configure (unsigned chan, unsigned cflags, unsigned baud) +{ + int cksr_min, flags; + unsigned new_config = 0; /* What we'll write to the control reg. */ + unsigned new_clk_divlog2; /* New baud-rate generate clock divider. */ + unsigned new_brgen_count; /* New counter max for baud-rate generator.*/ + /* These are the current values corresponding to the above. */ + unsigned old_config, old_clk_divlog2, old_brgen_count; + + /* Calculate new baud-rate generator config values. */ + cksr_min = 0; + while ((NB85E_UART_BASE_FREQ >> cksr_min) > NB85E_UART_CKSR_MAX_FREQ) + cksr_min++; + /* Calculate the log2 clock divider and baud-rate counter values + (note that the UART divides the resulting clock by 2, so + multiply BAUD by 2 here to compensate). */ + calc_counter_params (NB85E_UART_BASE_FREQ, baud * 2, + cksr_min, NB85E_UART_CKSR_MAX, 8/*bits*/, + &new_clk_divlog2, &new_brgen_count); + + /* Figure out new configuration of control register. */ + if (cflags & CSTOPB) + /* Number of stop bits, 1 or 2. */ + new_config |= NB85E_UART_ASIM_SL_2; + if ((cflags & CSIZE) == CS8) + /* Number of data bits, 7 or 8. */ + new_config |= NB85E_UART_ASIM_CL_8; + if (! (cflags & PARENB)) + /* No parity check/generation. */ + new_config |= NB85E_UART_ASIM_PS_NONE; + else if (cflags & PARODD) + /* Odd parity check/generation. */ + new_config |= NB85E_UART_ASIM_PS_ODD; + else + /* Even parity check/generation. */ + new_config |= NB85E_UART_ASIM_PS_EVEN; + if (cflags & CREAD) + /* Reading enabled. */ + new_config |= NB85E_UART_ASIM_RXE; + + new_config |= NB85E_UART_ASIM_TXE; /* Writing is always enabled. */ + new_config |= NB85E_UART_ASIM_CAE; + new_config |= NB85E_UART_ASIM_ISRM; /* Errors generate a read-irq. */ + + /* Disable interrupts while we're twiddling the hardware. */ + local_irq_save (flags); + +#ifdef NB85E_UART_PRE_CONFIGURE + NB85E_UART_PRE_CONFIGURE (chan, cflags, baud); +#endif + + old_config = NB85E_UART_ASIM (chan); + old_clk_divlog2 = NB85E_UART_CKSR (chan); + old_brgen_count = NB85E_UART_BRGC (chan); + + if (new_clk_divlog2 != old_clk_divlog2 + || new_brgen_count != old_brgen_count) + { + /* The baud rate has changed. First, disable the UART. */ + NB85E_UART_ASIM (chan) = 0; + old_config = 0; + /* Reprogram the baud-rate generator. */ + NB85E_UART_CKSR (chan) = new_clk_divlog2; + NB85E_UART_BRGC (chan) = new_brgen_count; + } + + if (! (old_config & NB85E_UART_ASIM_CAE)) { + /* If we are enabling the uart for the first time, start + by turning on the enable bit, which must be done + before turning on any other bits. */ + NB85E_UART_ASIM (chan) = NB85E_UART_ASIM_CAE; + /* Enabling the uart also resets it. */ + old_config = NB85E_UART_ASIM_CAE; + } + + if (new_config != old_config) { + /* Which of the TXE/RXE bits we'll temporarily turn off + before changing other control bits. */ + unsigned temp_disable = 0; + /* Which of the TXE/RXE bits will be enabled. */ + unsigned enable = 0; + unsigned changed_bits = new_config ^ old_config; + + /* Which of RX/TX will be enabled in the new configuration. */ + if (new_config & RX_BITS) + enable |= (new_config & NB85E_UART_ASIM_RXE); + if (new_config & TX_BITS) + enable |= (new_config & NB85E_UART_ASIM_TXE); + + /* Figure out which of RX/TX needs to be disabled; note + that this will only happen if they're not already + disabled. */ + if (changed_bits & RX_BITS) + temp_disable |= (old_config & NB85E_UART_ASIM_RXE); + if (changed_bits & TX_BITS) + temp_disable |= (old_config & NB85E_UART_ASIM_TXE); + + /* We have to turn off RX and/or TX mode before changing + any associated control bits. */ + if (temp_disable) + NB85E_UART_ASIM (chan) = old_config & ~temp_disable; + + /* Write the new control bits, while RX/TX are disabled. */ + if (changed_bits & ~enable) + NB85E_UART_ASIM (chan) = new_config & ~enable; + + /* The UART may not be reset properly unless we + wait at least 2 `basic-clocks' until turning + on the TXE/RXE bits again. A `basic clock' + is the clock used by the baud-rate generator, i.e., + the cpu clock divided by the 2^new_clk_divlog2. */ + nb85e_uart_delay (1 << (new_clk_divlog2 + 1)); + + /* Write the final version, with enable bits turned on. */ + NB85E_UART_ASIM (chan) = new_config; + } + + local_irq_restore (flags); +} + + +/* Low-level console. */ + +#ifdef CONFIG_V850E_NB85E_UART_CONSOLE + +static void nb85e_uart_cons_write (struct console *co, + const char *s, unsigned count) +{ + if (count > 0) { + unsigned chan = co->index; + unsigned irq = IRQ_INTST (chan); + int irq_was_enabled, irq_was_pending, flags; + + /* We don't want to get `transmission completed' (INTST) + interrupts, since we're busy-waiting, so we disable + them while sending (we don't disable interrupts + entirely because sending over a serial line is really + slow). We save the status of INTST and restore it + when we're done so that using printk doesn't + interfere with normal serial transmission (other than + interleaving the output, of course!). This should + work correctly even if this function is interrupted + and the interrupt printks something. */ + + /* Disable interrupts while fiddling with INTST. */ + local_irq_save (flags); + /* Get current INTST status. */ + irq_was_enabled = nb85e_intc_irq_enabled (irq); + irq_was_pending = nb85e_intc_irq_pending (irq); + /* Disable INTST if necessary. */ + if (irq_was_enabled) + nb85e_intc_disable_irq (irq); + /* Turn interrupts back on. */ + local_irq_restore (flags); + + /* Send characters. */ + while (count > 0) { + int ch = *s++; + + if (ch == '\n') { + /* We don't have the benefit of a tty + driver, so translate NL into CR LF. */ + nb85e_uart_wait_for_xmit_ok (chan); + nb85e_uart_putc (chan, '\r'); + } + + nb85e_uart_wait_for_xmit_ok (chan); + nb85e_uart_putc (chan, ch); + + count--; + } + + /* Restore saved INTST status. */ + if (irq_was_enabled) { + /* Wait for the last character we sent to be + completely transmitted (as we'll get an INTST + interrupt at that point). */ + nb85e_uart_wait_for_xmit_done (chan); + /* Clear pending interrupts received due + to our transmission, unless there was already + one pending, in which case we want the + handler to be called. */ + if (! irq_was_pending) + nb85e_intc_clear_pending_irq (irq); + /* ... and then turn back on handling. */ + nb85e_intc_enable_irq (irq); + } + } +} + +static kdev_t nb85e_uart_cons_device (struct console *c) +{ + return mk_kdev (TTY_MAJOR, NB85E_UART_MINOR_BASE + c->index); +} + +static struct console nb85e_uart_cons = +{ + name: "ttyS", + write: nb85e_uart_cons_write, + device: nb85e_uart_cons_device, + flags: CON_PRINTBUFFER, + cflag: NB85E_UART_INIT_CFLAGS, + index: -1, +}; + +void nb85e_uart_cons_init (unsigned chan) +{ + nb85e_uart_configure (chan, NB85E_UART_INIT_CFLAGS, + NB85E_UART_INIT_BAUD); + nb85e_uart_cons.index = chan; + register_console (&nb85e_uart_cons); + printk ("Console: %s on-chip UART channel %d\n", + NB85E_UART_CHIP_NAME, chan); +} + +#define NB85E_UART_CONSOLE &nb85e_uart_cons + +#else /* !CONFIG_V850E_NB85E_UART_CONSOLE */ +#define NB85E_UART_CONSOLE 0 +#endif /* CONFIG_V850E_NB85E_UART_CONSOLE */ + +/* TX/RX interrupt handlers. */ + +static void nb85e_uart_stop_tx (struct uart_port *port, unsigned tty_stop); + +void nb85e_uart_tx (struct uart_port *port) +{ + struct circ_buf *xmit = &port->info->xmit; + int stopped = uart_tx_stopped (port); + + if (nb85e_uart_xmit_ok (port->line)) { + int tx_ch; + + if (port->x_char) { + tx_ch = port->x_char; + port->x_char = 0; + } else if (!uart_circ_empty (xmit) && !stopped) { + tx_ch = xmit->buf[xmit->tail]; + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); + } else + goto no_xmit; + + nb85e_uart_putc (port->line, tx_ch); + port->icount.tx++; + + if (uart_circ_chars_pending (xmit) < WAKEUP_CHARS) + uart_event (port, EVT_WRITE_WAKEUP); + } + + no_xmit: + if (uart_circ_empty (xmit) || stopped) + nb85e_uart_stop_tx (port, stopped); +} + +static void nb85e_uart_tx_irq (int irq, void *data, struct pt_regs *regs) +{ + struct uart_port *port = data; + nb85e_uart_tx (port); +} + +static void nb85e_uart_rx_irq (int irq, void *data, struct pt_regs *regs) +{ + struct uart_port *port = data; + unsigned ch_stat = TTY_NORMAL; + unsigned ch = NB85E_UART_RXB (port->line); + unsigned err = NB85E_UART_ASIS (port->line); + + if (err) { + if (err & NB85E_UART_ASIS_OVE) { + ch_stat = TTY_OVERRUN; + port->icount.overrun++; + } else if (err & NB85E_UART_ASIS_FE) { + ch_stat = TTY_FRAME; + port->icount.frame++; + } else if (err & NB85E_UART_ASIS_PE) { + ch_stat = TTY_PARITY; + port->icount.parity++; + } + } + + port->icount.rx++; + + tty_insert_flip_char (port->info->tty, ch, ch_stat); + tty_schedule_flip (port->info->tty); +} + +/* Control functions for the serial framework. */ + +static void nb85e_uart_nop (struct uart_port *port) { } +static int nb85e_uart_success (struct uart_port *port) { return 0; } + +static unsigned nb85e_uart_tx_empty (struct uart_port *port) +{ + return TIOCSER_TEMT; /* Can't detect. */ +} + +static void nb85e_uart_set_mctrl (struct uart_port *port, unsigned mctrl) +{ +#ifdef NB85E_UART_SET_RTS + NB85E_UART_SET_RTS (port->line, (mctrl & TIOCM_RTS)); +#endif +} + +static unsigned nb85e_uart_get_mctrl (struct uart_port *port) +{ + /* We don't support DCD or DSR, so consider them permanently active. */ + int mctrl = TIOCM_CAR | TIOCM_DSR; + + /* We may support CTS. */ +#ifdef NB85E_UART_CTS + mctrl |= NB85E_UART_CTS(port->line) ? TIOCM_CTS : 0; +#else + mctrl |= TIOCM_CTS; +#endif + + return mctrl; +} + +static void nb85e_uart_start_tx (struct uart_port *port, unsigned tty_start) +{ + nb85e_intc_disable_irq (IRQ_INTST (port->line)); + nb85e_uart_tx (port); + nb85e_intc_enable_irq (IRQ_INTST (port->line)); +} + +static void nb85e_uart_stop_tx (struct uart_port *port, unsigned tty_stop) +{ + nb85e_intc_disable_irq (IRQ_INTST (port->line)); +} + +static void nb85e_uart_start_rx (struct uart_port *port) +{ + nb85e_intc_enable_irq (IRQ_INTSR (port->line)); +} + +static void nb85e_uart_stop_rx (struct uart_port *port) +{ + nb85e_intc_disable_irq (IRQ_INTSR (port->line)); +} + +static void nb85e_uart_break_ctl (struct uart_port *port, int break_ctl) +{ + /* Umm, do this later. */ +} + +static int nb85e_uart_startup (struct uart_port *port) +{ + int err; + + /* Alloc RX irq. */ + err = request_irq (IRQ_INTSR (port->line), nb85e_uart_rx_irq, + SA_INTERRUPT, "nb85e_uart", port); + if (err) + return err; + + /* Alloc TX irq. */ + err = request_irq (IRQ_INTST (port->line), nb85e_uart_tx_irq, + SA_INTERRUPT, "nb85e_uart", port); + if (err) { + free_irq (IRQ_INTSR (port->line), port); + return err; + } + + nb85e_uart_start_rx (port); + + return 0; +} + +static void nb85e_uart_shutdown (struct uart_port *port) +{ + /* Disable port interrupts. */ + free_irq (IRQ_INTST (port->line), port); + free_irq (IRQ_INTSR (port->line), port); + + /* Turn off xmit/recv enable bits. */ + NB85E_UART_ASIM (port->line) + &= ~(NB85E_UART_ASIM_TXE | NB85E_UART_ASIM_RXE); + /* Then reset the channel. */ + NB85E_UART_ASIM (port->line) = 0; +} + +static void +nb85e_uart_change_speed (struct uart_port *port, unsigned cflags, + unsigned iflag, unsigned quot) +{ + /* The serial framework doesn't give us the baud rate directly, but + insists on calculating a `quotient' from it, and giving us that + instead. Get the real baud rate from the tty code instead. */ + int baud = tty_get_baud_rate (port->info->tty); + + nb85e_uart_configure (port->line, cflags, baud); +} + +static const char *nb85e_uart_type (struct uart_port *port) +{ + return port->type == PORT_NB85E_UART ? "nb85e_uart" : 0; +} + +static void nb85e_uart_config_port (struct uart_port *port, int flags) +{ + if (flags & UART_CONFIG_TYPE) + port->type = PORT_NB85E_UART; +} + +static int +nb85e_uart_verify_port (struct uart_port *port, struct serial_struct *ser) +{ + if (ser->type != PORT_UNKNOWN && ser->type != PORT_NB85E_UART) + return -EINVAL; + if (ser->irq != IRQ_INTST (port->line)) + return -EINVAL; + return 0; +} + +static struct uart_ops nb85e_uart_ops = { + .tx_empty = nb85e_uart_tx_empty, + .get_mctrl = nb85e_uart_get_mctrl, + .set_mctrl = nb85e_uart_set_mctrl, + .start_tx = nb85e_uart_start_tx, + .stop_tx = nb85e_uart_stop_tx, + .stop_rx = nb85e_uart_stop_rx, + .enable_ms = nb85e_uart_nop, + .break_ctl = nb85e_uart_break_ctl, + .startup = nb85e_uart_startup, + .shutdown = nb85e_uart_shutdown, + .change_speed = nb85e_uart_change_speed, + .type = nb85e_uart_type, + .release_port = nb85e_uart_nop, + .request_port = nb85e_uart_success, + .config_port = nb85e_uart_config_port, + .verify_port = nb85e_uart_verify_port, +}; + +/* Initialization and cleanup. */ + +static struct uart_driver nb85e_uart_driver = { + .owner = THIS_MODULE, + .driver_name = "nb85e_uart", +#ifdef CONFIG_DEVFS_FS + .dev_name = "tts/%d", +#else + .dev_name = "ttyS", +#endif + .major = TTY_MAJOR, + .minor = NB85E_UART_MINOR_BASE, + .nr = NB85E_UART_NUM_CHANNELS, + .cons = NB85E_UART_CONSOLE, +}; + + +static struct uart_port nb85e_uart_ports[NB85E_UART_NUM_CHANNELS]; + +static int __init nb85e_uart_init (void) +{ + int rval; + + printk (KERN_INFO "%s on-chip UART\n", NB85E_UART_CHIP_NAME); + + rval = uart_register_driver (&nb85e_uart_driver); + if (rval == 0) { + unsigned chan; + + for (chan = 0; chan < NB85E_UART_NUM_CHANNELS; chan++) { + int cksr_min; + struct uart_port *port = &nb85e_uart_ports[chan]; + + memset (port, 0, sizeof *port); + + port->ops = &nb85e_uart_ops; + port->line = chan; + port->iotype = SERIAL_IO_MEM; + port->flags = UPF_BOOT_AUTOCONF; + + /* We actually use multiple IRQs, but the serial + framework seems to mainly use this for + informational purposes anyway. Here we use the TX + irq. */ + port->irq = IRQ_INTST (chan); + + /* The serial framework doesn't really use these + membase/mapbase fields for anything useful, but + it requires that they be something non-zero to + consider the port `valid', and also uses them + for informational purposes. */ + port->membase = (void *)NB85E_UART_BASE_ADDR (chan); + port->mapbase = NB85E_UART_BASE_ADDR (chan); + + /* The framework insists on knowing the uart's master + clock freq, though it doesn't seem to do anything + useful for us with it. We must make it at least + higher than (the maximum baud rate * 16), otherwise + the framework will puke during its internal + calculations, and force the baud rate to be 9600. + To be accurate though, just repeat the calculation + we use when actually setting the speed. */ + cksr_min = 0; + while ((NB85E_UART_BASE_FREQ >> cksr_min) + > NB85E_UART_CKSR_MAX_FREQ) + cksr_min++; + /* The `* 8' means `* 16 / 2': 16 to account for for + the serial framework's built-in bias, and 2 because + there's an additional / 2 in the hardware. */ + port->uartclk = (NB85E_UART_BASE_FREQ >> cksr_min) * 8; + + uart_add_one_port (&nb85e_uart_driver, port); + } + } + + return rval; +} + +static void __exit nb85e_uart_exit (void) +{ + unsigned chan; + + for (chan = 0; chan < NB85E_UART_NUM_CHANNELS; chan++) + uart_remove_one_port (&nb85e_uart_driver, + &nb85e_uart_ports[chan]); + + uart_unregister_driver (&nb85e_uart_driver); +} + +module_init (nb85e_uart_init); +module_exit (nb85e_uart_exit); + +EXPORT_NO_SYMBOLS; + +MODULE_AUTHOR ("Miles Bader"); +MODULE_DESCRIPTION ("NEC " NB85E_UART_CHIP_NAME " on-chip UART"); +MODULE_LICENSE ("GPL"); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.2.5.45/drivers/video/68328fb.c linux.2.5.45-ac1/drivers/video/68328fb.c --- linux.2.5.45/drivers/video/68328fb.c 1970-01-01 01:00:00.000000000 +0100 +++ linux.2.5.45-ac1/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