diff -Naur linux-2.4.26/Documentation/Configure.help linux-2.4.26-m68k/Documentation/Configure.help --- linux-2.4.26/Documentation/Configure.help 2004-04-14 23:05:24.000000000 +1000 +++ linux-2.4.26-m68k/Documentation/Configure.help 2004-04-15 06:41:29.000000000 +1000 @@ -17167,6 +17167,26 @@ say M here and read . If unsure, say N. +Amiga SFS file system support +CONFIG_ASFS_FS + The Amiga Smart FileSystem (SFS) is the file system used on hard + disks by Amiga(tm) and MorphOS(tm) systems. Say Y if you want + to be able to read files from an Amiga SFS partition on your hard + drive. + + This file system driver is in EXPERIMENTAL state. Use it with care. + Although it CANNOT destroy your data (because it is a read-only + driver) it MIGHT cause a crash in some circumstances. + + For more information read + + This file system is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module is called affs.o. If you want to compile it as a module, + say M here and read . + + If unsure, say N. + Apple HFS file system support CONFIG_HFS_FS If you say Y here, you will be able to mount Macintosh-formatted @@ -23357,6 +23377,29 @@ If you don't want to compile a kernel for a Sun 3x, say N. +TekXpress XP2x support +CONFIG_TEKXP + This option enables support for the TekXpress XP2x series of + X-Terminals made by Tektronix. + You will also want to enable 68030 support below. + Additional information about this port is available at + . + + If you don't want to compile a kernel for TekXpress XP2x, say N. + +Kernel command line +CONFIG_BOOTCMD + You have to specify a kernel commandline here. + There will be no possiblity to change the content on run-time. + +Report as MVME160 +CONFIG_TEKXP_REPORT_MVME + Enabling this option the TekXpress X-Terminals report as + Motorola MVME160 in /proc/harware (if available). + + Say Y, if you intend to use this kernel to install the + Debian/m68k Linux distribution. Otherwhise it is save to say N. + Sun3x builtin serial support CONFIG_SUN3X_ZS ZS refers to a type of asynchronous serial port built in to the Sun3 @@ -23810,6 +23853,18 @@ If you want to compile it as a module, say M here and read . +TekXpress on-board Sonic support +CONFIG_TEKSONIC + Say Y here if you want to use the integrated network controller of + the TekXpress X-Terminals. If you do not modify it it is unlikely + you will get Linux running without this selected. + +SCC2962 serial support +CONFIG_SCC2692 + Say Y here if you want to use the serial interfaces from user-space. + It is safe to say N here, if it will only be used for the output of + kernel messages. + Support for early boot text console CONFIG_BOOTX_TEXT Say Y here to see progress messages from the boot firmware in text diff -Naur linux-2.4.26/Documentation/filesystems/00-INDEX linux-2.4.26-m68k/Documentation/filesystems/00-INDEX --- linux-2.4.26/Documentation/filesystems/00-INDEX 2004-02-19 00:36:30.000000000 +1100 +++ linux-2.4.26-m68k/Documentation/filesystems/00-INDEX 2004-02-19 09:11:42.000000000 +1100 @@ -6,6 +6,8 @@ - info and mount options for the Acorn Advanced Disc Filing System. affs.txt - info and mount options for the Amiga Fast File System. +asfs.txt + - info and mount options for the Amiga Smart File System. befs.txt - info for the BeOS file system (BFS) bfs.txt diff -Naur linux-2.4.26/Documentation/filesystems/asfs.txt linux-2.4.26-m68k/Documentation/filesystems/asfs.txt --- linux-2.4.26/Documentation/filesystems/asfs.txt 1970-01-01 10:00:00.000000000 +1000 +++ linux-2.4.26-m68k/Documentation/filesystems/asfs.txt 2003-06-20 21:32:32.000000000 +1000 @@ -0,0 +1,40 @@ + +Amiga SmartFileSystem, Linux implementation +=========================================== + +This is a simple read-only driver. It support reading files and directories. +Symbolic links (called soft links) are not supported yet. Don't even try +to read them. + + +Mount options for the ASFS +========================== + +setuid[=uid] + This sets the owner of all files and directories in the file + system to uid or the uid of the current user, respectively. + +setgid[=gid] + Same as above, but for gid. + +mode=mode + Sets the mode flags to the given (octal) value. Directories + will get an x permission if the corresponding r bit is set. + The default mode is 0444, which means all r bits are set + (for directories this means also that all x bits are set). + + +Other information +================= + +Supported block sizes are: 512, 1024, 2048 and 4096 bytes. Larger blocks +speed up almost everything at the expense of wasted disk space. The speed +gain above 4K seems not really worth the price, so you don't lose too +much here, either. + +This file system hasn't been well tested yet. Athough it CANNOT destroy +your data, it MIGHT cause a crash. Sorry. + +This file system has been tested on Motorola PPC and Intel x86 systems. +It SHOULD also work on Motorola 68k. It probably WON'T work on other +systems (especially 64bit). diff -Naur linux-2.4.26/arch/m68k/Makefile linux-2.4.26-m68k/arch/m68k/Makefile --- linux-2.4.26/arch/m68k/Makefile 2001-06-12 12:15:27.000000000 +1000 +++ linux-2.4.26-m68k/arch/m68k/Makefile 2003-07-22 07:26:06.000000000 +1000 @@ -119,6 +119,11 @@ SUBDIRS := $(SUBDIRS) arch/m68k/sun3 arch/m68k/sun3/prom endif +ifdef CONFIG_TEKXP +CORE_FILES := $(CORE_FILES) arch/m68k/tekxp/tekxp.o +SUBDIRS := $(SUBDIRS) arch/m68k/tekxp +endif + ifdef CONFIG_M68040 CORE_FILES := $(CORE_FILES) arch/m68k/fpsp040/fpsp.o SUBDIRS := $(SUBDIRS) arch/m68k/fpsp040 @@ -172,5 +177,6 @@ rm -f arch/m68k/kernel/m68k_defs.h arch/m68k/kernel/m68k_defs.d archmrproper: + rm -f arch/m68k/boot/bootstrap bootstrap archdep: diff -Naur linux-2.4.26/arch/m68k/boot/Makefile linux-2.4.26-m68k/arch/m68k/boot/Makefile --- linux-2.4.26/arch/m68k/boot/Makefile 1970-01-01 10:00:00.000000000 +1000 +++ linux-2.4.26-m68k/arch/m68k/boot/Makefile 2003-07-22 07:26:07.000000000 +1000 @@ -0,0 +1,15 @@ + +ifdef CONFIG_TEKXP +.PHONY: bootstrap +bootstrap: boot.o + $(LD) -T tekxp.ld -Ttext 0x1000 -o $@ $< + -rm -f ../../../bootstrap + dd if=$@ of=../../../bootstrap bs=4096 conv=sync + $(STRIP) -s -o vmlinux.s ../../../vmlinux + cat vmlinux.s >> ../../../bootstrap + +boot.o: boot.S + $(CC) -c -o $@ -m68030 -O2 -I$(HPATH) -D__ASSEMBLY__ -DDEBUG $< + +endif + diff -Naur linux-2.4.26/arch/m68k/boot/boot.S linux-2.4.26-m68k/arch/m68k/boot/boot.S --- linux-2.4.26/arch/m68k/boot/boot.S 1970-01-01 10:00:00.000000000 +1000 +++ linux-2.4.26-m68k/arch/m68k/boot/boot.S 2003-07-22 07:26:07.000000000 +1000 @@ -0,0 +1,744 @@ +/* + * linux/arch/m68k/boot/boot.S + * + * Copyright (C) 2002,2003 Michael Mueller + * + * Parts taken from head.S. + * + * 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 is a wrapper to the linux kernel. Compiled as a.out binary it can be + * used to bootstrap the Linux kernel using the TekXpress Boot Monitor. + * + * In general it does copy the kernel image to the end of the available + * memory and does rearrange it to the top memory as described within the + * ELF header of wrapped vmlinux file. + * + * On some of the TekXpress systems there is not enough continous memory + * available to fit the whole kernel into. Thus this code does enable the + * MMU which is rather unusual. + */ + +#include +#include +#include +#include +#include +#include +#include + +/***********************************************************************/ + +/* + * Little helpers for defining functions + */ + +#ifdef __STDC__ +#define L(name) .L##name +#else +#define L(name) .L/**/name +#endif + +#define STACK %a6@(stackstart) +#define ARG0 %a6@(4) +#define ARG1 %a6@(8) +#define ARG2 %a6@(12) +#define ARG3 %a6@(16) +#define ARG4 %a6@(20) + +.macro func_start name,saveregs,stack=0 +L(\name): + linkw %a6,#-\stack + moveml \saveregs,%sp@- +.set stackstart,-\stack + +.macro func_return_\name + moveml %sp@+,\saveregs + unlk %a6 + rts +.endm +.endm + +.macro func_return name + func_return_\name +.endm + +.macro func_call name + jbsr L(\name) +.endm + +.macro move_stack nr,arg1,arg2,arg3,arg4 +.if \nr + move_stack "(\nr-1)",\arg2,\arg3,\arg4 + movel \arg1,%sp@- +.endif +.endm + +.macro func_define name,nr=0 +.macro \name arg1,arg2,arg3,arg4 + move_stack \nr,\arg1,\arg2,\arg3,\arg4 + func_call \name +.if \nr + lea %sp@(\nr*4),%sp +.endif +.endm +.endm + +/***********************************************************************/ + +/* + * Start of the code (not entry point!) + */ +.text +ENTRY(_stext) + +/* + * This is a faked a.out Header + */ +.long 0x10B /* a.out magic number */ +.long SYMBOL_NAME(__end) - header_end + /* size of content = size of text segment */ +.long 0 +.long 0 +.long 0 +.long SYMBOL_NAME(__start) /* entry point */ +.long 0 +.long 0 +header_end: + +/* + * Platform specific constants + */ +#define MEMSTART 0xF0000000 /* start address of CPU RAM */ +#define OPTRAMSTART 0xF4000000 /* start address of Option RAM */ +#define MEMCHUNK 0x01000000 /* spacing beetween memory chunks */ +#define MEMORY_MAP_ENTRIES 8 /* number of memory chunks */ + +/* + * MMU definitions + */ +PAGESIZE = 4096 +PAGESHIFT = 12 +ROOT_TABLE_SIZE = 128 +PTR_TABLE_SIZE = 128 +PAGE_TABLE_SIZE = 64 +ROOT_INDEX_SHIFT = 25 +PTR_INDEX_SHIFT = 18 +PAGE_INDEX_SHIFT = 12 + +/* + * Function declarations + */ +func_define mmu_map,4 +func_define mmu_get_root_table_entry,1 +func_define mmu_get_ptr_table_entry,2 +func_define build_memory_list +func_define dump_memory_list +func_define get_kernel_size +func_define get_kernel_start +func_define get_kernel_physical_headers +func_define get_kernel_entry + +/* + * Translation tables. + * + * These have to be located at the same position as within head.S. As + * they are references from the kernel later. + */ +.equ SYMBOL_NAME(kernel_pg_dir),SYMBOL_NAME(_stext) +.equ SYMBOL_NAME(kernel_ptr_dir1),SYMBOL_NAME(kernel_pg_dir)+ROOT_TABLE_SIZE*4 +.equ SYMBOL_NAME(kernel_ptr_dir2),SYMBOL_NAME(kernel_ptr_dir1)+PTR_TABLE_SIZE*4 +.equ SYMBOL_NAME(kernel_ptr_dir3),SYMBOL_NAME(kernel_ptr_dir2)+PTR_TABLE_SIZE*4 +.equ SYMBOL_NAME(kernel_ptr_dir4),SYMBOL_NAME(kernel_ptr_dir3)+PTR_TABLE_SIZE*4 +.equ .,SYMBOL_NAME(_stext)+PAGESIZE /* Skip to end of page */ + +/* + * Functions for debugging output + */ +func_define serial_init +func_define putc,1 +func_define putn,1 +func_define puts,1 +func_define dump,2 + +.macro dputc ch +#ifdef DEBUG + putc \ch +#endif +.endm + +.macro putr + putc '\r' + putc '\n' +.endm + +.macro dputr +#ifdef DEBUG + putr +#endif +.endm + +.macro dputn nr +#ifdef DEBUG + putn \nr +#endif +.endm + +.macro puts string + .data +.Lstr\@: + .asciz "\string" + .previous + pea %pc@(.Lstr\@) + func_call puts + addql #4,%sp +.endm + +.macro dputs string +#ifdef DEBUG + puts "\string" +#endif +.endm + +func_start puts,%d0/%a0 + movl ARG1,%a0 +1: + movb %a0@+,%d0 + beqs 2f + putc %d0 + bras 1b +2: +func_return puts + +func_start putn,%d0-%d2 + movl ARG1,%d0 + movl #7,%d1 +1: + roll #4,%d0 + movl %d0,%d2 + andb #15,%d2 + addb #'0',%d2 + cmpb #'9',%d2 + jls 2f + addb #'A'-('9'+1),%d2 +2: + putc %d2 + dbra %d1,1b + putc #' ' +func_return putn + +func_start putc,%d0/%a0 + movl #0xFF800000,%a0 +1: + movb 4(%a0),%d0 + andb #4,%d0 + tstb %d0 + bne 2f + bra 1b +2: + movl ARG1,%d0 + movb %d0,12(%a0) +func_return putc + +func_start dump,%d0/%a0 + movl ARG1,%a0 + movl ARG2,%d0 +1: + putn %a0 + putn %a0@ + putn %a0@(4) + putn %a0@(8) + putn %a0@(12) + putn %a0@(16) + putn %a0@(20) + putn %a0@(24) + putn %a0@(28) + putc #'\r' + putc #'\n' + addl #32,%a0 + subl #32,%d0 + bpl 1b +func_return dump + +func_start serial_init,%a0 + movl #0xFF800000,%a0 /* address of UART */ + clrb 0x34(%a0) + movb #0x80,0x10(%a0) /* ACR: baud rate set 2 */ + clrb 0x14(%a0) /* reset interrupt mask */ + movb #0x10,8(%a0) /* CRA: reset MR pointer */ + movb #0x20,8(%a0) + movb #0x30,8(%a0) + movb #2,(%a0) /* 7 bits per char */ + movb #7,(%a0) /* one stop bit */ + movb #0xBB,4(%a0) /* 9600 baud */ + movb #5,8(%a0) /* enable tx and rx */ +func_return serial_init + +.macro putc ch + pea \ch + func_call putc + addql #4,%sp +.endm + + + +/* + * Entry into the code + */ +ENTRY(__start) + + /* Use the first 256 byte of memory as scratch area + */ + movl #MEMSTART+0x100, %sp + + /* Initialize the serial port + */ + serial_init + dputs "\r\nLinux@TekXP starting...\r\n" + + /* Build a memory map for later usage + */ + putc 'a' + build_memory_list +/* dump_memory_list */ + + /* Clear the translation tables + */ + dputc 'b' + movl #PAGESIZE/4-1,%d0 + lea %pc@(SYMBOL_NAME(kernel_pg_dir)),%a0 +1: + clrl %a0@+ + dbra %d0,1b + + /* Setup pointer tables for virtual addresses starting at 0 and + * the current PC. + * We need 4 pointer tables at maximum for 128MB. + * Since both memory ranges should map equal we simple use the + * same pointer tables for both. + */ + dputc 'c' + lea %pc@(SYMBOL_NAME(_stext)),%a0 + movl %a0,%d0 + movl #ROOT_INDEX_SHIFT,%d1 + lsrl %d1,%d0 + + lea %pc@(SYMBOL_NAME(kernel_pg_dir)),%a0 + lea %pc@(SYMBOL_NAME(kernel_ptr_dir1)+_PAGE_TABLE+_PAGE_ACCESSED),%a1 + movl %a1,%a0@(%d0:l:4) + movl %a1,%a0@+ + lea %pc@(SYMBOL_NAME(kernel_ptr_dir2)+_PAGE_TABLE+_PAGE_ACCESSED),%a1 + movl %a1,%a0@(%d0:l:4) + movl %a1,%a0@+ + lea %pc@(SYMBOL_NAME(kernel_ptr_dir3)+_PAGE_TABLE+_PAGE_ACCESSED),%a1 + movl %a1,%a0@(%d0:l:4) + movl %a1,%a0@+ + lea %pc@(SYMBOL_NAME(kernel_ptr_dir4)+_PAGE_TABLE+_PAGE_ACCESSED),%a1 + movl %a1,%a0@(%d0:l:4) + movl %a1,%a0@+ + + /* Setup early terminator pages for hardware access */ + dputc 'd' + lea %pc@(SYMBOL_NAME(kernel_pg_dir) + 127*4),%a1 + movl #0xFE000000+_PAGE_PRESENT+_PAGE_ACCESSED+_PAGE_DIRTY+_PAGE_NOCACHE030,%d1 + movl %d1,%a1@ + + /* Map the memory to appear linear + */ + dputc 'e' + clrl %d0 /* virtual address */ + lea %pc@(Lmemory_list),%a0 +1: + movl %a0@+,%a1 /* address */ + movl %a0@+,%d1 /* size */ + tstl %a1 + beqs 2f + mmu_map %d0,%a1,%d1,#_PAGE_NOCACHE030 + addl %d1,%d0 + bras 1b +2: + lea %pc@(Lmemory_last),%a0 + movl %d0,%a0@ + +#if 0 + lea %pc@(SYMBOL_NAME(kernel_pg_dir)),%a0 + dump %a0,#PAGESIZE +#endif + + /* Enable the MMU + */ + dputc 'f' + .chip 68030 + lea %pc@(Lmmu_engage_030_temp),%a0 + movel #0x80000002,%a0@ + lea %pc@(SYMBOL_NAME(kernel_pg_dir)),%a1 + movl %a1,%a0@(4) + movl #0x0808,%d0 + movec %d0,%cacr + pmove %a0@,%srp + pflusha + movl #0x82c07760,%a0@(8) + pmove %a0@(8),%tc + jmp 1f:l +1: + movl #0x0808,%d0 + movec %d0,%cacr + pflusha + .chip 68k + + /* Fix the stack + */ + movl #0x100,%sp + + /* Remove the now unneeded mappings (5 mappings remain, 4 at top) */ + dputc 'g' + movl #SYMBOL_NAME(kernel_pg_dir)+16,%a0 + movl #ROOT_TABLE_SIZE-6,%d0 +1: + clrl %a0@+ + dbra %d0,1b + + /* Move yourself and the kernel to end of the memory + */ + dputc 'h' + get_kernel_size + addl #SYMBOL_NAME(__end)+4095,%d0 + andl #-PAGESIZE,%d0 + movl Lmemory_last,%a1 + subl %d0,%a1 + movl %a1,Lmemory_last + movl #0,%a0 + lsrl #2,%d0 +1: + subl #1,%d0 + bmi 2f + movl %a0@+,%a1@+ + bras 1b +2: + movl Lmemory_last,%a0 + jmpl %a0@(3f) + +3: + dputc 'i' + + /* + * Loop through the sections of the kernel and copy them over. + */ + + get_kernel_start /* in %a0 */ + movel %a0,%a1 /* offset of all numbers */ + clrl %d3 /* end of bss */ + + get_kernel_physical_headers /* count in d0, first in %a0 */ + subl #32,%a0 + +1: + dputc 'j' + subl #1,%d0 + bmi 5f + addl #32,%a0 + + movel %a0@(4),%a2 /* file offset */ + addl %a1,%a2 /* current memory address */ + + movel %a0@(8),%a3 /* load memory address */ + movel %a0@(16),%d1 /* file size */ + movel %a0@(20),%d2 /* memory size */ + + cmpl #SYMBOL_NAME(_stext)+PAGESIZE,%a3 + bpl 2f + + movl #SYMBOL_NAME(_stext)+PAGESIZE,%d3 + subl %a3,%d3 /* how much is below */ + + addl %d3,%a3 /* move it up */ + addl %d3,%a2 /* move it up */ + + subl %d3,%d2 + bmi 1b /* nothing left */ + + subl %d3,%d1 + bmi 4f +2: + subl %d1,%d2 /* do not clear what is in file */ + bpl 3f + addl %d1,%d2 + movl %d2,%d1 + clrl %d2 + +3: + subl #1,%d1 + bmi 4f + moveb %a2@+,%a3@+ + bras 3b + +4: /* clear */ + lea %a3@(%d2),%a4 + cmpl %a4,%d3 + bpl 4f + movl %a4,%d3 +4: + + subl #1,%d2 + bmi 1b + clrb %a3@+ + bras 4b +5: + + /* + * Create a boot info record + */ + dputc 'k' + addl #PAGESIZE-1,%d3 + andl #-PAGE_SIZE,%d3 + movl %d3,%a0 + + movw #BI_MACHTYPE,%a0@+ + movw #8,%a0@+ + movl #MACH_TEKXP,%a0@+ + + movw #BI_CPUTYPE,%a0@+ + movw #8,%a0@+ + movl #CPU_68030,%a0@+ + + movw #BI_FPUTYPE,%a0@+ + movw #8,%a0@+ + movl #0,%a0@+ + + movw #BI_MMUTYPE,%a0@+ + movw #8,%a0@+ + movl #MMU_68030,%a0@+ + + lea %pc@(Lmemory_list),%a1 +1: + movel %a1@+,%d1 + movel %a1@+,%d0 + tstl %d1 + beqs 2f + movw #BI_MEMCHUNK,%a0@+ + movw #12,%a0@+ + movl %d1,%a0@+ + movl %d0,%a0@+ + bras 1b +2: + + movw #BI_LAST,%a0@+ + clrw %a0@+ + + /* jump into the kernel */ + dputc 'l' + get_kernel_entry + jmpl %a0@ + +/* + * Get the position of the kernels ELF header. It is located on the next + * page after this wrapper program. + */ + +func_start get_kernel_start,%d0 + lea %pc@(__end+PAGESIZE-1),%a0 + movl %a0,%d0 + andl #-PAGESIZE,%d0 + movl %d0,%a0 +func_return get_kernel_start + +/* + * Read the entry point of the ELF executable. + */ + +func_start get_kernel_entry,%d0 + get_kernel_start + movl %a0@(0x18),%a0 +func_return get_kernel_entry + +/* + * Get the address of the first physical header (into %a0) and the number + * of those headers present (into %d0). + */ +func_start get_kernel_physical_headers,%d1 + get_kernel_start + clrl %d0 + movw %a0@(0x2C),%d0 /* Number of headers */ + movl %a0@(0x1C),%d1 /* Offset of the table */ + lea %a0@(%d1),%a0 +func_return get_kernel_physical_headers + +/* + * Calculate the size kernel image. Notice this is not its final footprint. + */ +func_start get_kernel_size,%d1/%d2/%a0 + get_kernel_physical_headers + clrl %d1 +1: + subl #1,%d0 + bmi 3f + movl %a0@(4),%d2 + addl %a0@(16),%d2 + cmpl %d2,%d1 + bpl 2f + movl %d2,%d1 +2: + addl #32,%a0 + bras 1b +3: + movl %d1,%d0 +func_return get_kernel_size + + +/* + * Fetch the memory configuration and store it in a field for later + * retrieval. + */ +func_start build_memory_list,%a2/%a4/%d0/%d1 + lea %pc@(Lmemory_list),%a4 + + movl #MEMSTART,%a2 + bfextu 0xFFD00003{4:4},%d0 + movl %pc@(Lcpsram_bitmap_table,%d0:l:4),%d0 +1: + tstl %d0 + beqs 2f + movl %d0,%d1 + andl #3,%d1 + movl %pc@(Ldram_size_table,%d1:l:4),%d1 + movl %a2,%a4@+ + movl %d1,%a4@+ + addl #MEMCHUNK,%a2 + lsrl #2,%d0 + bras 1b +2: + bfextu 0xFFD00003{0:1},%d0 + tstl %d0 + bnes 4f + movl #OPTRAMSTART,%a2 + bfextu 0xFFD00003{1:3},%d0 + movl %pc@(Lcporam_bitmap_table,%d0:l:4),%d0 +3: + tstl %d0 + beqs 4f + movl %d0,%d1 + andl #3,%d1 + movl %pc@(Ldram_size_table,%d1:l:4),%d1 + movl %a2,%a4@+ + movl %d1,%a4@+ + addl #MEMCHUNK,%a2 + lsrl #2,%d0 + bras 3b +4: +func_return build_memory_list + +Ldram_size_table: + .long 0 + .long 0x100000 + .long 0x400000 + .long 0x040000 + +Lcporam_bitmap_table: + .long 0xAA + .long 0x2A + .long 0x0A + .long 0x02 + .long 0x55 + .long 0x05 + .long 0x01 + .long 0x15 + +Lcpsram_bitmap_table: + .long 0x95 + .long 0x01 + .long 0x05 + .long 0x15 + .long 0x55 + .long 0x06 + .long 0x16 + .long 0x56 + .long 0x0A + .long 0x1A + .long 0x5A + .long 0xA5 + .long 0x2A + .long 0x6A + .long 0x02 + .long 0xAA + + +/* + * Memory mapping functions from head.S. (shortened) + */ + +func_start mmu_map,%d0-%d4/%a0-%a4 + /* Get the logical address, it is assumed to be rounded to 256KiB */ + movl ARG1,%a3 + + /* Get the end address. The length should be rounded to 256KiB */ + movl %a3,%a4 + addl ARG3,%a4 + subql #1,%a4 + + /* Get the physical address, assumed to be rounded to 256KiB too */ + movl ARG2,%a2 + + /* Augment the physical address with page attributes */ + movl ARG4,%d0 + orw #_PAGE_PRESENT+_PAGE_ACCESSED+_PAGE_DIRTY,%d0 + addw %d0,%a2 + +1: + /* Calculate the offset into the root table */ + movl %a3,%d0 + movl #ROOT_INDEX_SHIFT,%d1 + lsrl %d1,%d0 + mmu_get_root_table_entry %d0 + + /* Calculate the offset into the pointer table */ + movl %a3,%d0 + movl #PTR_INDEX_SHIFT,%d1 + lsrl %d1,%d0 + andl #PTR_TABLE_SIZE-1,%d0 + mmu_get_ptr_table_entry %a0,%d0 + + + movl %a2,%a0@ + addl #PAGE_TABLE_SIZE*PAGESIZE,%a2 + addl #PAGE_TABLE_SIZE*PAGESIZE,%a3 + + lea %a3@(-1),%a0 + cmpl %a0,%a4 + jhi 1b + +func_return mmu_map + +func_start mmu_get_root_table_entry,%d0 + movl ARG1,%d0 + lea %pc@(SYMBOL_NAME(kernel_pg_dir),%d0:l:4),%a0 +func_return mmu_get_root_table_entry + +func_start mmu_get_ptr_table_entry,%d0 + movl ARG1,%a0 + movl %a0@,%d0 + andw #-PTR_TABLE_SIZE,%d0 + movl %d0,%a0 + movl ARG2,%d0 + lea %a0@(%d0:l:4),%a0 +func_return mmu_get_ptr_table_entry + + + + +.data +Lmmu_engage_030_temp: + .space 12 + +Lmemory_last: + .long 0 /* end of virtual memory */ + +Lmemory_list: + .rept MEMORY_MAP_ENTRIES + .long 0 /* address */ + .long 0 /* size */ + .endr + diff -Naur linux-2.4.26/arch/m68k/boot/tekxp.ld linux-2.4.26-m68k/arch/m68k/boot/tekxp.ld --- linux-2.4.26/arch/m68k/boot/tekxp.ld 1970-01-01 10:00:00.000000000 +1000 +++ linux-2.4.26-m68k/arch/m68k/boot/tekxp.ld 2003-07-22 07:26:07.000000000 +1000 @@ -0,0 +1,36 @@ +OUTPUT_FORMAT("binary") +ENTRY(__start) +SECTIONS +{ + .text : + { + *(.init) + *(.text) + ___CTOR_LIST__ = .; + LONG((___CTOR_END__ - ___CTOR_LIST__) / 4 - 2) + *(.ctors) + LONG(0) + ___CTOR_END__ = .; + ___DTOR_LIST__ = .; + LONG((___DTOR_END__ - ___DTOR_LIST__) / 4 - 2) + *(.dtors) + LONG(0) + ___DTOR_END__ = .; + *(.fini) + etext = .; + __etext = .; + } + .data SIZEOF(.text) + ADDR(.text) : + { + *(.data .data2) + edata = .; + __edata = .; + } + .bss SIZEOF(.data) + ADDR(.data) : + { + *(.bss) + *(COMMON) + end = .; + __end = .; + } +} diff -Naur linux-2.4.26/arch/m68k/config.in linux-2.4.26-m68k/arch/m68k/config.in --- linux-2.4.26/arch/m68k/config.in 2004-02-19 00:36:30.000000000 +1100 +++ linux-2.4.26-m68k/arch/m68k/config.in 2004-02-19 09:12:42.000000000 +1100 @@ -56,7 +56,14 @@ fi bool 'Sun3x support' CONFIG_SUN3X bool 'Sun3 support' CONFIG_SUN3 - +bool 'TekXpress 2x support' CONFIG_TEKXP +if [ "$CONFIG_TEKXP" = "y" ] ; then + define_bool CONFIG_PSMOUSE y + define_bool CONFIG_NO_CMDLINE y + string ' Kernel command line' CONFIG_BOOTCMD "root=nfs ip=192.168.3.10:192.168.2.1:192.168.3.1:255.255.255.0:tek.malware.de:eth0:none nfsroot=192.168.2.1:/tftpboot/XP20" + bool ' Report as MVME160' CONFIG_TEKXP_REPORT_MVME +fi + bool 'Q40/Q60 support' CONFIG_Q40 comment 'Processor type' @@ -365,6 +372,9 @@ fi dep_tristate 'NE2000/NE1000 support' CONFIG_NE2000 m fi + if [ "$CONFIG_TEKXP" = "y" ]; then + bool ' TekXpress on-board Sonic support' CONFIG_TEKSONIC + fi fi endmenu @@ -474,6 +484,10 @@ define_tristate CONFIG_SERIAL $CONFIG_DN_SERIAL fi +if [ "$CONFIG_TEKXP" = "y" ] ; then + tristate 'SCC2962 serial support' CONFIG_SCC2692 +fi + if [ "$CONFIG_SUN3" = "y" -o "$CONFIG_SUN3X" = "y" ]; then bool 'Sun3/3x builtin serial support' CONFIG_SUN3X_ZS else @@ -499,7 +513,7 @@ "$CONFIG_SUN3X_ZS" = "y" -o "$CONFIG_SERIAL" = "y" -o \ "$CONFIG_MVME147_SCC" -o "$CONFIG_SERIAL167" = "y" -o \ "$CONFIG_MVME162_SCC" -o "$CONFIG_BVME6000_SCC" = "y" -o \ - "$CONFIG_DN_SERIAL" ]; then + "$CONFIG_DN_SERIAL" = "y" -o "$CONFIG_SCC2692" = "y" ]; then bool 'Support for serial port console' CONFIG_SERIAL_CONSOLE fi bool 'Support for user serial device modules' CONFIG_USERIAL diff -Naur linux-2.4.26/arch/m68k/kernel/head.S linux-2.4.26-m68k/arch/m68k/kernel/head.S --- linux-2.4.26/arch/m68k/kernel/head.S 2003-06-14 00:51:31.000000000 +1000 +++ linux-2.4.26-m68k/arch/m68k/kernel/head.S 2003-07-22 07:21:27.000000000 +1000 @@ -39,6 +39,12 @@ * Disabled caches * Put us in supervisor state. * + * On TekXpress (CONFIG_TEKXP) the boat loader enables the MMU since + * there might not be enough physically continues memory available + * for the kernel (e.g. 6 x 1MB memory configuration). The mapping is + * 1:1 for the first chunk of physical memory and does use the same + * table sizes as the temporary memory map used during enabling the MMU. + * * The kernel setup code takes the following steps: * . Raise interrupt level * . Set up initial kernel memory mapping. @@ -480,6 +486,14 @@ addql #4,%sp .endm +.macro get_bi_record_continue record,recsize,binfo + movel \binfo,%sp@- + movel \recsize,%sp@- + pea \record + func_call get_bi_record_continue + addl #12,%sp +.endm + func_define serial_putc,1 func_define console_putc,1 @@ -543,6 +557,7 @@ #define is_not_apollo(lab) cmpl &MACH_APOLLO,%pc@(m68k_machtype); jne lab #define is_not_q40(lab) cmpl &MACH_Q40,%pc@(m68k_machtype); jne lab #define is_not_sun3x(lab) cmpl &MACH_SUN3X,%pc@(m68k_machtype); jne lab +#define is_not_tekxp(lab) cmpl &MACH_TEKXP,%pc@(m68k_machtype); jne lab #define hasnt_leds(lab) cmpl &MACH_HP300,%pc@(m68k_machtype); \ jeq 42f; \ @@ -587,6 +602,7 @@ .long MACH_BVME6000, BVME6000_BOOTI_VERSION .long MACH_MAC, MAC_BOOTI_VERSION .long MACH_Q40, Q40_BOOTI_VERSION + .long MACH_TEKXP, TEKXP_BOOTI_VERSION .long 0 1: jra SYMBOL_NAME(__start) @@ -993,6 +1009,40 @@ leds 0x4 +#ifdef CONFIG_TEKXP + is_not_tekxp(5f) + + get_bi_record BI_LAST + addw #PAGESIZE-1,%a0 + movel %a0,%d2 + andw #-PAGESIZE,%d2 + + /* Convert it into a physical address */ + movl %d2,%d1 + get_bi_record BI_MEMCHUNK +1: + cmpl #-1,%d0 + beqs 2f + subl %a0@(4),%d1 + bcs 4f + get_bi_record_continue BI_MEMCHUNK,%d0,%a0 + bras 1b +4: + movl %d1,%d0 + addl %a0@(4),%d0 + addl %a0@,%d0 + bras 3f +2: + movl %d2,%d0 +3: + + movel %d0,availmem + + /* Skip all the MMU stuff here */ + bra L(engage_done) +5: +#endif + /* * mmu_init * @@ -1310,11 +1360,22 @@ putc 'P' mmu_map #0x80000000,#0,#0x02000000,#_PAGE_NOCACHE030 - -L(notapollo): jbra L(mmu_init_done) + +L(notapollo): #endif +#ifdef CONFIG_TEKXP + is_not_tekxp(L(nottekxp)) + + putc 'P' + mmu_map_tt #0,#0xff000000,#0x01000000,#_PAGE_NOCACHE030 + +L(nottekxp): +#endif + + jbra L(mmu_init_done) + L(mmu_init_done): putc 'G' @@ -1442,6 +1503,8 @@ movel L(memory_start),availmem +L(engage_done): + #ifdef CONFIG_AMIGA is_not_amiga(1f) /* fixup the Amiga custom register location before printing */ @@ -1572,10 +1635,7 @@ * Returns: d0: size (-1 if not found) * a0: data pointer (end-of-records if not found) */ -func_start get_bi_record,%d1 - - movel ARG1,%d0 - lea %pc@(SYMBOL_NAME(_end)),%a0 +.macro get_bi_record_core #ifndef CONFIG_HP300 1: tstw %a0@(BIR_TAG) jeq 3f @@ -1591,8 +1651,22 @@ lea %a0@(BIR_SIZE),%a0 4: #endif /* CONFIG_HP300 */ +.endm + +func_start get_bi_record,%d1 + + movel ARG1,%d0 + lea %pc@(SYMBOL_NAME(_end)),%a0 + get_bi_record_core func_return get_bi_record +func_start get_bi_record_continue,%d1 + movl ARG3,%a0 + addl ARG2,%a0 + subl #BIR_DATA,%a0 + movl ARG1,%d0 + get_bi_record_core +func_return get_bi_record_continue /* * MMU Initialization Begins Here @@ -3020,6 +3094,27 @@ /* We count on the PROM initializing SIO1 */ #endif +#ifdef CONFIG_TEKXP +#if 0 + is_not_tekxp(1f) + movl %a0,-(%sp) + movl #0xFF800000,%a0 /* address of UART */ + clrb 0x34(%a0) + movb #0x80,0x10(%a0) /* ACR: baud rate set 2 */ + clrb 0x14(%a0) /* reset interrupt mask */ + movb #0x10,8(%a0) /* CRA: reset MR pointer */ + movb #0x20,8(%a0) + movb #0x30,8(%a0) + movb #2,(%a0) /* 7 bits per char */ + movb #7,(%a0) /* one stop bit */ + movb #0xBB,4(%a0) /* 9600 baud */ + movb #5,8(%a0) /* enable tx and rx */ + movl (%sp)+,%a0 + bras L(serial_init_done) +1: +#endif +#endif + L(serial_init_done): func_return serial_init @@ -3215,6 +3310,23 @@ 2: #endif +#ifdef CONFIG_TEKXP + is_not_tekxp(3f) + moveml %a0/%d0-%d1,%sp@- + movl #0xFF800000,%a0 +1: + movb 4(%a0),%d1 + andb #4,%d1 + tstb %d1 + bne 2f + bra 1b +2: + movb %d0,12(%a0) + moveml %sp@+,%d0-%d1/%a0 + jbra L(serial_putc_done) +3: +#endif + L(serial_putc_done): func_return serial_putc diff -Naur linux-2.4.26/arch/m68k/kernel/m68k_ksyms.c linux-2.4.26-m68k/arch/m68k/kernel/m68k_ksyms.c --- linux-2.4.26/arch/m68k/kernel/m68k_ksyms.c 2004-02-19 00:36:30.000000000 +1100 +++ linux-2.4.26-m68k/arch/m68k/kernel/m68k_ksyms.c 2003-11-12 22:57:01.000000000 +1100 @@ -53,6 +53,7 @@ EXPORT_SYMBOL(mm_cachebits); #endif #endif /* !CONFIG_SUN3 */ +EXPORT_SYMBOL(flush_icache_user_range); EXPORT_SYMBOL(m68k_debug_device); EXPORT_SYMBOL(mach_hwclk); EXPORT_SYMBOL(mach_get_ss); diff -Naur linux-2.4.26/arch/m68k/kernel/setup.c linux-2.4.26-m68k/arch/m68k/kernel/setup.c --- linux-2.4.26/arch/m68k/kernel/setup.c 2003-06-14 00:51:31.000000000 +1000 +++ linux-2.4.26-m68k/arch/m68k/kernel/setup.c 2003-07-22 07:20:23.000000000 +1000 @@ -140,6 +140,7 @@ extern void config_hp300(void); extern void config_q40(void); extern void config_sun3x(void); +extern void config_tekxp(void); extern void mac_debugging_short (int, short); extern void mac_debugging_long (int, long); @@ -150,6 +151,10 @@ static void __init m68k_parse_bootinfo(const struct bi_record *record) { +#ifdef CONFIG_NO_CMDLINE + strncpy(m68k_command_line, CONFIG_BOOTCMD, CL_SIZE); +#endif + while (record->tag != BI_LAST) { int unknown = 0; const unsigned long *data = record->data; @@ -354,6 +359,11 @@ config_sun3x(); break; #endif +#ifdef CONFIG_TEKXP + case MACH_TEKXP: + config_tekxp(); + break; +#endif default: panic ("No configuration setup"); } diff -Naur linux-2.4.26/arch/m68k/mac/iop.c linux-2.4.26-m68k/arch/m68k/mac/iop.c --- linux-2.4.26/arch/m68k/mac/iop.c 2003-06-14 00:51:31.000000000 +1000 +++ linux-2.4.26-m68k/arch/m68k/mac/iop.c 2004-06-20 21:17:45.000000000 +1000 @@ -261,7 +261,7 @@ } else { iop_base[IOP_NUM_ISM] = (struct mac_iop *) ISM_IOP_BASE_QUADRA; } - iop_base[IOP_NUM_SCC]->status_ctrl = 0; + iop_base[IOP_NUM_ISM]->status_ctrl = 0; iop_ism_present = 1; } else { iop_base[IOP_NUM_ISM] = NULL; diff -Naur linux-2.4.26/arch/m68k/mm/Makefile linux-2.4.26-m68k/arch/m68k/mm/Makefile --- linux-2.4.26/arch/m68k/mm/Makefile 2003-06-14 00:51:31.000000000 +1000 +++ linux-2.4.26-m68k/arch/m68k/mm/Makefile 2003-07-02 09:46:59.000000000 +1000 @@ -9,7 +9,7 @@ O_TARGET := mm.o -obj-y := init.o fault.o extable.o hwtest.o +obj-y := cache.o init.o fault.o extable.o hwtest.o ifndef CONFIG_SUN3 obj-y += kmap.o memory.o motorola.o diff -Naur linux-2.4.26/arch/m68k/mm/cache.c linux-2.4.26-m68k/arch/m68k/mm/cache.c --- linux-2.4.26/arch/m68k/mm/cache.c 1970-01-01 10:00:00.000000000 +1000 +++ linux-2.4.26-m68k/arch/m68k/mm/cache.c 2003-11-13 02:23:27.000000000 +1100 @@ -0,0 +1,161 @@ +/* + * linux/arch/m68k/mm/cache.c + * + * Instruction cache handling + * + * Copyright (C) 1995 Hamish Macdonald + */ + +#include + +#include + + +static unsigned long virt_to_phys_slow(unsigned long vaddr, mm_segment_t fs) +{ + if (CPU_IS_060) { + mm_segment_t old_fs = get_fs(); + unsigned long paddr; + + set_fs(fs); + + /* The PLPAR instruction causes an access error if the translation + * is not possible. To catch this we use the same exception mechanism + * as for user space accesses in . */ + asm volatile (".chip 68060\n" + "1: plpar (%0)\n" + ".chip 68k\n" + "2:\n" + ".section .fixup,\"ax\"\n" + " .even\n" + "3: sub.l %0,%0\n" + " jra 2b\n" + ".previous\n" + ".section __ex_table,\"a\"\n" + " .align 4\n" + " .long 1b,3b\n" + ".previous" + : "=a" (paddr) + : "0" (vaddr)); + set_fs(old_fs); + return paddr; + } else if (CPU_IS_040) { + mm_segment_t old_fs = get_fs(); + unsigned long mmusr; + + set_fs(fs); + + asm volatile (".chip 68040\n\t" + "ptestr (%1)\n\t" + "movec %%mmusr, %0\n\t" + ".chip 68k" + : "=r" (mmusr) + : "a" (vaddr)); + set_fs(old_fs); + + if (mmusr & MMU_R_040) + return (mmusr & PAGE_MASK) | (vaddr & ~PAGE_MASK); + } else { + unsigned short mmusr; + unsigned long *descaddr; + + asm volatile ("ptestr %3,%2@,#7,%0\n\t" + "pmove %%psr,%1@" + : "=a&" (descaddr) + : "a" (&mmusr), "a" (vaddr), "d" (fs.seg)); + if (mmusr & (MMU_I|MMU_B|MMU_L)) + return 0; + descaddr = phys_to_virt((unsigned long)descaddr); + switch (mmusr & MMU_NUM) { + case 1: + return (*descaddr & 0xfe000000) | (vaddr & 0x01ffffff); + case 2: + return (*descaddr & 0xfffc0000) | (vaddr & 0x0003ffff); + case 3: + return (*descaddr & PAGE_MASK) | (vaddr & ~PAGE_MASK); + } + } + return 0; +} + +/* Push n pages at kernel virtual address and clear the icache */ +/* RZ: use cpush %bc instead of cpush %dc, cinv %ic */ +void flush_icache_range(unsigned long address, unsigned long endaddr) +{ + if (CPU_IS_040_OR_060) { + address &= PAGE_MASK; + + if (address >= PAGE_OFFSET && address < (unsigned long)high_memory) { + do { + asm volatile ("nop\n\t" + ".chip 68040\n\t" + "cpushp %%bc,(%0)\n\t" + ".chip 68k" + : : "a" (virt_to_phys((void *)address))); + address += PAGE_SIZE; + } while (address < endaddr); + } else { + do { + asm volatile ("nop\n\t" + ".chip 68040\n\t" + "cpushp %%bc,(%0)\n\t" + ".chip 68k" + : : "a" (virt_to_phys_slow(address, KERNEL_DS))); + address += PAGE_SIZE; + } while (address < endaddr); + } + } else { + unsigned long tmp; + asm volatile ("movec %%cacr,%0\n\t" + "orw %1,%0\n\t" + "movec %0,%%cacr" + : "=&d" (tmp) + : "di" (FLUSH_I)); + } +} + +void flush_icache_user_range(void *addr, unsigned long size) +{ + unsigned long address = (unsigned long)addr; + unsigned long endaddr = address + size; + + if (CPU_IS_040_OR_060) { + address &= PAGE_MASK; + + do { + asm volatile ("nop\n\t" + ".chip 68040\n\t" + "cpushp %%bc,(%0)\n\t" + ".chip 68k" + : : "a" (virt_to_phys_slow(address, get_fs()))); + address += PAGE_SIZE; + } while (address < endaddr); + } else { + unsigned long tmp; + asm volatile ("movec %%cacr,%0\n\t" + "orw %1,%0\n\t" + "movec %0,%%cacr" + : "=&d" (tmp) + : "di" (FLUSH_I)); + } +} + +void flush_icache_user_page(struct vm_area_struct *vma, struct page *page, + unsigned long addr, int len) +{ + if (CPU_IS_040_OR_060) { + asm volatile ("nop\n\t" + ".chip 68040\n\t" + "cpushp %%bc,(%0)\n\t" + ".chip 68k" + : : "a" (page_to_phys(page))); + } else { + unsigned long tmp; + asm volatile ("movec %%cacr,%0\n\t" + "orw %1,%0\n\t" + "movec %0,%%cacr" + : "=&d" (tmp) + : "di" (FLUSH_I)); + } +} + diff -Naur linux-2.4.26/arch/m68k/tekxp/Makefile linux-2.4.26-m68k/arch/m68k/tekxp/Makefile --- linux-2.4.26/arch/m68k/tekxp/Makefile 1970-01-01 10:00:00.000000000 +1000 +++ linux-2.4.26-m68k/arch/m68k/tekxp/Makefile 2003-07-22 07:20:23.000000000 +1000 @@ -0,0 +1,15 @@ +# +# Makefile for Linux arch/m68k/tekxp source directory +# +# 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... + +O_TARGET := tekxp.o + +export-objs := tek_ksyms.o tekuart.o nvram.o +obj-y := config.o tekuart.o nvram.o tek_ksyms.o + +include $(TOPDIR)/Rules.make diff -Naur linux-2.4.26/arch/m68k/tekxp/config.c linux-2.4.26-m68k/arch/m68k/tekxp/config.c --- linux-2.4.26/arch/m68k/tekxp/config.c 1970-01-01 10:00:00.000000000 +1000 +++ linux-2.4.26-m68k/arch/m68k/tekxp/config.c 2003-07-22 07:20:24.000000000 +1000 @@ -0,0 +1,199 @@ +/* + * linux/arch/m68k/tekxp/config.c + * + * Copyright (C) 2002,2003 Michael Mueller + * + * 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 + +unsigned char aux_device_present = 1; + +/* + * While the support for this platform is still under development we just + * spit out a stupid message whenever an unexpected IRQ does occur. + * This message when appearing once most possible will run forever, + * since we have no interrupt controller we can give an acknowledgement. + */ + +static void tekxp_int_unhandled(int irq, void *dev_id, struct pt_regs *regs) +{ + printk(KERN_ERR "Unhandled IRQ %d\n", irq); +} + +static void (*tekxp_default_handler[SYS_IRQS])(int, void *, struct pt_regs *) = { + tekxp_int_unhandled, tekxp_int_unhandled, tekxp_int_unhandled, + tekxp_int_unhandled, tekxp_int_unhandled, tekxp_int_unhandled, + tekxp_int_unhandled, tekxp_int_unhandled +}; + +/* + * Reset the machine. + */ +static void tekxp_reset(void) +{ + tek_uart_set_op(4); + __asm__ volatile("1:\tbras 1b\r\n"); +} + +#ifdef USE_VIDEO_REFRESH_AS_TIMER +/* + * Timer interrupt handler + */ + +static void tek_timer(int irq, void *dev_id, struct pt_regs *regs) +{ + register void (*handler)(int,void*,struct pt_regs*) = dev_id; + + (*(volatile unsigned char *)(0xFFB00000))++; + + handler(irq, NULL, regs); +} +#endif + +/* + * To initialize the scheduling we setup a timer on the DUART. + * The hardware offers a screen refresh interrupt but its rate varies with + * the display mode and in all cases is less than HZ. + */ + +static void __init tek_sched_init(void (*handler)(int, void *, struct pt_regs *)) +{ +#ifdef USE_VIDEO_REFRESH_AS_TIMER + /* + * Enable the timer + */ + (*(volatile unsigned char *)(0xFFB00000))++; + + if ( request_irq(TEK_IRQ_VIDEO, tek_timer, IRQ_FLG_LOCK, "timer", handler) ) + panic("Could not register timer interrupt"); +#else + tek_uart_setup_timer(handler); +#endif +} + +/* + * Currently there is no such function implemented. + * However one could read the counter registers of the DUART here. + */ + +static unsigned long tek_gettimeoffset(void) +{ + return 0; +} + +/* + * There is not much to do with the keyboard here. + * The TekXpress Bootmonitor did most of the work already. What is left + * will be done by the PC keyboard driver later. + */ + +static int __init tek_dummy_keyb_init(void) +{ + return 0; +} + +/* + * This function simply modifies the C character for a new line into the + * MSDOS-typical version of it. + */ + +static void tek_serial_console_write(struct console *co, const char *s, + unsigned int count) +{ + while ( count-- ) + { + char c = *s++; + if ( c == '\n' ) + tek_uart_putchar(0, '\r', 1); + tek_uart_putchar(0, c, 1); + } +} + +/* + */ + +static struct console tekxp_console_driver = { + name: "debug", + flags: CON_PRINTBUFFER, + index: -1, +}; + +/* + */ +static void __init tekxp_debug_init(void) +{ + extern char m68k_debug_device[]; + + if (!strcmp( m68k_debug_device, "ser" )) { + /* no initialization required (?) */ + tekxp_console_driver.write = tek_serial_console_write; + register_console(&tekxp_console_driver); + } +} + +/* + * Get the model number as stored in NVRAM and make it readable. + * + * FIXME: This does not work as expected. + */ + +static void tekxp_get_model(char *model) +{ +#ifdef CONFIG_TEKXP_REPORT_MVME + sprintf(model, "Motorola MVME160"); +#else + unsigned short m = nvram_readw(NVRAM_DISPLAY); + static const int model_number[] = {24,25,27,29,25,21,25,25}; + + if ( m < sizeof model_number ) + sprintf(model, "TekXpress XP%02d", model_number[m]); + else + sprintf(model, "TekXpress"); +#endif +} + +/* + * This basicly sets the machine dependent variables as needed by + * the m68k port of the linux kernel. + * Besides it initializes a console for kernel messages and the NVRAM + * routines. + */ + +void __init config_tekxp(void) +{ + tekxp_debug_init(); + init_nvram(NULL); + + mach_get_model = tekxp_get_model; + mach_sched_init = tek_sched_init; +#ifdef CONFIG_VT + mach_keyb_init = tek_dummy_keyb_init; +#endif + mach_init_IRQ = tek_uart_init_IRQ; + mach_request_irq = tek_uart_request_irq; + mach_free_irq = tek_uart_free_irq; + enable_irq = tek_uart_enable_irq; + disable_irq = tek_uart_disable_irq; + mach_get_irq_list = tek_uart_get_irq_list; + mach_gettimeoffset = tek_gettimeoffset; + mach_max_dma_address = 0xffffffff; +#ifdef CONFIG_DUMMY_CONSOLE + conswitchp = &dummy_con; +#endif + mach_default_handler = &tekxp_default_handler; + mach_reset = tekxp_reset; +} + diff -Naur linux-2.4.26/arch/m68k/tekxp/nvram.c linux-2.4.26-m68k/arch/m68k/tekxp/nvram.c --- linux-2.4.26/arch/m68k/tekxp/nvram.c 1970-01-01 10:00:00.000000000 +1000 +++ linux-2.4.26-m68k/arch/m68k/tekxp/nvram.c 2003-07-22 07:20:24.000000000 +1000 @@ -0,0 +1,164 @@ +/* + * linux/arch/m68k/tekxp/nvram.c + * + * Copyright (C) 2002,2003 Michael Mueller + * + * 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 + +#define DEBUG + +#ifdef DEBUG +static int nvram_init = 0; +#endif +static u_char *eeprom_ptr; +static u_char nvram_copy[EEPROM_SIZE]; + +static void ee_enable(void) +{ +#if 0 + // TODO: We still rely on the I/O being transparently mapped + // TODO: This might interfere with other code using the UART + *(volatile u_char*)0xFF800038 = (u_char)0x80; +#else + tek_uart_set_op(7); +#endif +} + +static void ee_disable(void) +{ +#if 0 + // TODO: We still rely on the I/O being transparently mapped + // TODO: This might interfere with other code using the UART + *(volatile u_char*)0xFF80003C = (u_char)0x80; +#else + tek_uart_clr_op(7); +#endif +} + +void init_nvram(unsigned long *mem_start) +{ + u_char chksum; + u_char chksum2; + u_short chksum_complete; + int i; + + // FIXME: When this code is running ioremap* is not working yet. + // So we access the EEPROM through the transparent mapping + // established in head.S +#if 0 + // Map EEPROM into kernel memory space + eeprom_ptr = ioremap_writethrough(EEPROM_BASE, EEPROM_SIZE); + if ( !eeprom_ptr ) + { + panic(KERN_ERR "Could not map NVRAM into kernel memory space\n"); + } +#else + eeprom_ptr = (u_char*)EEPROM_BASE; +#endif + + // Make a copy of the content to avoid access count excess + ee_enable(); + memcpy(nvram_copy, eeprom_ptr, EEPROM_SIZE); + ee_disable(); + + // Check the checksum of the content + chksum = 0xFF; + chksum2 = 0xFF; + for ( i = EEPROM_SIZE-1; i >= 0 ; i-- ) + { + u_long new_chk /* d0 */ = chksum + nvram_copy[i]; + if ( new_chk > 0xFF ) + new_chk++; + chksum = new_chk & 0xFF; + + new_chk = chksum2 + chksum; + if ( new_chk > 0xFF ) + new_chk++; + chksum2 = new_chk++; + } + + chksum_complete = ((u_short)chksum2 << 8) + chksum; + if ( chksum_complete == 0xFFFF ) + { + printk("NVRAM checksum is ok\n"); + } + else + { + printk(KERN_WARNING "NVRAM checksum invalid!\n"); + } + +#ifdef DEBUG + nvram_init++; +#endif +} + +u_char nvram_readb(int ofs) +{ +#ifdef DEBUG + if ( !nvram_init ) + { + printk(KERN_ERR "Trial to read uninitialized NVRAM\n"); + return 0xFF; + } +#endif + if ( ofs < 0 || ofs >= EEPROM_SIZE ) + return 0xFF; + + return nvram_copy[ofs]; +} + +u_short nvram_readw(int ofs) +{ +#ifdef DEBUG + if ( !nvram_init ) + { + printk(KERN_ERR "Trial to read uninitialized NVRAM\n"); + return 0xFFFFU; + } + if ( ofs & 1 ) + { + panic("Unaligned word access to NVRAM"); + return 0xFFFFU; + } +#endif + if ( ofs < 0 || ofs >= EEPROM_SIZE ) + return 0xFFFFU; + + return *(u_short*)(nvram_copy + ofs); +} + + +u_long nvram_readl(int ofs) +{ +#ifdef DEBUG + if ( !nvram_init ) + { + printk(KERN_ERR "Trial to read uninitialized NVRAM\n"); + return 0xFFFFFFFFUL; + } + if ( ofs & 3 ) + { + panic("Unaligned word access to NVRAM"); + return 0xFFFFFFFFUL; + } +#endif + if ( ofs < 0 || ofs >= EEPROM_SIZE ) + return 0xFFFFFFFFUL; + + return *(u_long*)(nvram_copy + ofs); +} + + diff -Naur linux-2.4.26/arch/m68k/tekxp/tek_ksyms.c linux-2.4.26-m68k/arch/m68k/tekxp/tek_ksyms.c --- linux-2.4.26/arch/m68k/tekxp/tek_ksyms.c 1970-01-01 10:00:00.000000000 +1000 +++ linux-2.4.26-m68k/arch/m68k/tekxp/tek_ksyms.c 2003-07-22 07:20:24.000000000 +1000 @@ -0,0 +1,23 @@ +/* + * linux/arch/m68k/tekxp/tek_ksyms.c + * + * Copyright (C) 2002,2003 Michael Mueller + * + * 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 + +EXPORT_SYMBOL(tek_uart_putchar); +EXPORT_SYMBOL(tek_uart_lock); +EXPORT_SYMBOL(nvram_readb); +EXPORT_SYMBOL(nvram_readw); +EXPORT_SYMBOL(nvram_readl); + diff -Naur linux-2.4.26/arch/m68k/tekxp/tekuart.c linux-2.4.26-m68k/arch/m68k/tekxp/tekuart.c --- linux-2.4.26/arch/m68k/tekxp/tekuart.c 1970-01-01 10:00:00.000000000 +1000 +++ linux-2.4.26-m68k/arch/m68k/tekxp/tekuart.c 2003-07-22 07:20:24.000000000 +1000 @@ -0,0 +1,476 @@ +/* + * linux/arch/m68k/tekxp/tekuart.c + * + * Copyright (C) 2002,2003 Michael Mueller + * + * 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 + +spinlock_t tek_uart_lock = SPIN_LOCK_UNLOCKED; +static spinlock_t tek_irq_lock = SPIN_LOCK_UNLOCKED; + +/* + * Base address of the UART + * + * Initialized to the address accessable by a transparent mapping. + * + * FIXME: This is never mapped into the memory space of the kernel + * since memory mapping is not available while initializing the + * platform specific stuff. + */ + +static tek_uart_t *uart = (tek_uart_t*)TEK_UART_BASE; + +/* + * Interrupt handler tables and call statistics + */ + +static irq_handler_t irq_handlers[UART_IRQS]; +static int tek_irq_stat[UART_IRQS]; + +#define IRQ_IDX(n) ((n)-SYS_IRQS) + +/* + * Dummy variable used as Lvalue when we need to read from the + * hardware without any need for the actual result value. + */ + +static volatile u_char dummy; + +/* + * Variables used for the interrupt routine + */ + +static u_char tek_uart_imr; /* shadow Interrupt Mask Register */ +static u_char tek_uart_isr; /* shadow Interrupt Status Register */ +#ifndef USE_VIDEO_REFRESH_AS_TIMER +static unsigned short tek_timer; /* value to put into the counter */ +#endif + +static u_char timer_mode = 0x80; /* choose second baudrate set */ + +/* + * Set the interrupt mask register. + */ + +static inline void __set_IMR(void) +{ + uart->wr.IMR = tek_uart_imr; +} + +static void set_IMR(void) +{ + unsigned long flags; + spin_lock_irqsave(tek_uart_lock, flags); + __set_IMR(); + spin_unlock_irqrestore(tek_uart_lock, flags); +} + +/* + * Interrupt handler. + * + * Besides demultiplexing the interrupt sources of the DUART it does take + * care of the counter prior to calling the kernel handler. + */ + +static void tek_irqhandler(int irq, void *dev_id, struct pt_regs *regs) +{ + int i; + + /* + * Read the ISR once. This does even clear all pending interrupts. + */ + unsigned char ISR = uart->rd.ISR; + +#ifndef USE_VIDEO_REFRESH_AS_TIMER + /* + * Handle the counter. + */ + if ( ISR & (1<rd.CounterStop; /* just ack */ +#endif + +#ifdef DEBUG + printk("tek_irqhandler: ISR=%02x IMR=%02x\n", ISR, tek_uart_imr); +#endif + + /* + * Store the interrupt status for later usage. + * + * This does also queue disabled interrupts for later usage. + */ + ISR = (tek_uart_isr |= ISR) & tek_uart_imr; + + /* + * Run the handler for each interrupt source. + */ + for ( i=0; iwr.OutputSet = 1 << nr; + + spin_unlock_irqrestore(tek_uart_lock, flags); +} + +/* + * Clear an output line (to High) + */ + +void tek_uart_clr_op(int nr) +{ + unsigned long flags; + spin_lock_irqsave(tek_uart_lock, flags); + + uart->wr.OutputClear = 1 << nr; + + spin_unlock_irqrestore(tek_uart_lock, flags); +} + +/* + * Setup an interrupt handler managing all interrupt sources of the DUART. + */ + +void __init tek_uart_init_IRQ(void) +{ + unsigned long flags; + spin_lock_irqsave(tek_uart_lock, flags); + + /* + * Disable all interrupts + */ + tek_uart_imr = 0; + __set_IMR(); + + + /* + * Clear pending interrupts + */ + tek_uart_isr = 0; + dummy = uart->rd.ISR; + + spin_unlock_irqrestore(tek_uart_lock, flags); + + /* + * Register the interrupt handler + */ + if ( request_irq(TEK_IRQ_UART, tek_irqhandler, IRQ_FLG_LOCK, "UART demux", NULL) ) + { + panic("Could not register UART demux interrupt handler"); + } +} + +/* + * Enable a specific interrupt source of the DUART. + */ + +static inline void enable_uart_irq(unsigned int irq) +{ + unsigned long flags; + spin_lock_irqsave(tek_uart_lock, flags); + + tek_uart_imr |= (1<= UART_IRQS ) + return -ENXIO; + if ( !handler ) + return -EINVAL; + + spin_lock_irqsave(tek_irq_lock, _flags); + + if ( irq_handlers[irq].handler && (irq_handlers[irq].dev_id != dev_id) ) { + spin_unlock_irqrestore(tek_irq_lock, _flags); + return -EBUSY; + } + + irq_handlers[irq].handler = handler; + irq_handlers[irq].flags = flags; + irq_handlers[irq].devname = devname; + irq_handlers[irq].dev_id = dev_id; + + spin_unlock_irqrestore(tek_irq_lock, _flags); + + enable_uart_irq(irq); + + return 0; +} + +/* + * Unregister an interrupt handler for an interrupt source of the DUART. + * + * This is also called for system interrupts. These requests are passed + * to the generic function made available by the m68k port. + */ + +void tek_uart_free_irq(unsigned int irq, void *dev_id) +{ + unsigned long flags; + + if ( irq < SYS_IRQS ) + return sys_free_irq(irq, dev_id); + irq -= SYS_IRQS; + + if ( irq >= UART_IRQS ) + return /* -ENXIO */; + + spin_lock_irqsave(tek_irq_lock, flags); + + if ( !irq_handlers[irq].handler ) + return /* -EINVAL */; + + if ( dev_id != irq_handlers[irq].dev_id ) + return /* -EPERM */; + + disable_uart_irq(irq); + irq_handlers[irq].handler = NULL; + + spin_unlock_irqrestore(tek_irq_lock, flags); +} + +/* + * Wrapper for enabling an IRQ. + */ + +void tek_uart_enable_irq(unsigned int irq) +{ + if ( irq < SYS_IRQS ) + return; + + enable_uart_irq(irq - SYS_IRQS); +} + +/* + * Wrapper for disabling an IRQ. + */ + +void tek_uart_disable_irq(unsigned int irq) +{ + if ( irq < SYS_IRQS ) + return; + + disable_uart_irq(irq - SYS_IRQS); +} + +/* + * Build an ASCII list of the interrupt handlers registered and the call + * statistics. This part of the content of /proc/interrupts. + */ + +int tek_uart_get_irq_list(char *buf) +{ + int i, len = 0; + unsigned long flags; + spin_lock_irqsave(tek_irq_lock, flags); + + for ( i=0; i < UART_IRQS; i++ ) + { + if ( irq_handlers[i].handler ) + { + len += sprintf(buf+len, "uart %2d: %10u ", i, tek_irq_stat[i]); + len += sprintf(buf+len, " "); + len += sprintf(buf+len, "%s\n", irq_handlers[i].devname); + } + } + spin_unlock_irqrestore(tek_irq_lock, flags); + return len; +} + +#ifndef USE_VIDEO_REFRESH_AS_TIMER + +static void tek_irq2(int irq, void *dev_id, struct pt_regs *regs) +{ + /* + * Acknowledge the interrupt + */ + (*(volatile unsigned char *)(0xFFB00000))++; + +} + +/* + * Setup a timer interrupt. + */ +void __init tek_uart_setup_timer(void (*handler)(int, void *, struct pt_regs *)) +{ + unsigned long flags; + + /* + * Calculate the divider of the clock interval + */ + if ( HZ < 32 ) + { + /* + * Use 115.2k base clock. + * + * Do not permit frequencies <2Hz, they can be provided + * by further software dividing only and are not very + * usefull. + */ + if ( HZ < 2 ) + panic("I will not provide such a slow timer"); + + timer_mode |= 0x70; + tek_timer = 115200 / HZ; + } + else if ( HZ <= 57600 ) + { + /* + * Use 115.2k * 16 base clock + */ + timer_mode |= 0x60; + tek_timer = (115200*16) / HZ; + } + else + /* + * We can not provide a faster timer. + */ + panic("Old hardware is no ferrari"); + + /* + * And setup an handler for the video refresh. + */ + if ( request_irq(TEK_IRQ_VIDEO, tek_irq2, IRQ_FLG_LOCK, "display", NULL) ) + panic("Could not register display interrupt"); + + /* + * Setup an handler for the timer interrupt. + */ + if ( request_irq(TEK_IRQ_TIMER_A, handler, IRQ_FLG_LOCK, "timer", NULL) ) + panic("Could not register timer interrupt"); + + spin_lock_irqsave(tek_uart_lock, flags); + + /* + * Start the timer. + */ + dummy = uart->rd.CounterStop; + uart->wr.ACR = timer_mode; + uart->wr.CRUR = tek_timer >> 8; + uart->wr.CTLR = tek_timer & 255; + dummy = uart->rd.CounterStart; + + spin_unlock_irqrestore(tek_uart_lock, flags); + + /* + * Enable the video refresh interrupt + */ + (*(volatile unsigned char *)(0xFFB00000))++; +} +#endif + +/* + * Output a character on the serial port A. + * + * This routine is called from interrupt and non-interrupt contexts. + */ + +void tek_uart_putchar(int channel, int c, int waitloop) +{ + unsigned long flags; + spin_lock_irqsave(tek_uart_lock, flags); + + channel &= 1; + + if ( waitloop ) + { +// disable_uart_irq(channel ? 4 : 0); + while ( !((channel ? uart->rd.SRB : uart->rd.SRA) & 4) ) + ; + } + + (channel ? uart->wr.THRB : uart->wr.THRA) = (u_char)c; + + if ( waitloop ) + { + while ( !((channel ? uart->rd.SRB : uart->rd.SRA) & 4) ) + ; +// enable_uart_irq(channel ? 4 : 0); + } + + spin_unlock_irqrestore(tek_uart_lock, flags); +} + diff -Naur linux-2.4.26/drivers/char/16c552.h linux-2.4.26-m68k/drivers/char/16c552.h --- linux-2.4.26/drivers/char/16c552.h 1970-01-01 10:00:00.000000000 +1000 +++ linux-2.4.26-m68k/drivers/char/16c552.h 2001-10-22 19:34:32.000000000 +1000 @@ -0,0 +1,165 @@ +/* + * Definitions for the 16c552 DACE + * (dual-asynchronous-communications-element) used on the GVP + * IO-Extender. + * + * Basically this is two 16c550 uarts's and a parallel port, which is + * why the serial definitions should be valid for the 16c550 uart + * aswell. + * + * Data was taken from National Semiconductors duart 16c552 + * data-sheets and the Texas Instruments DACE 16c552 data-sheets (the + * NS version of the chip is _non_ standard and their data-sheets did + * cost me several wasted hours of work). + * + * This file is (C) 1995 Jes Sorensen (jds@kom.auc.dk) + * + * Moved from drivers/char/ to include/linux/, because it's useful + * on more than just the one card. I'm using it on the hp300 DCA + * serial driver, for example. + * -- Peter Maydell 05/1998 + */ + +#ifndef _16C552_H_ +#define _16C552_H_ + +/* Serial stuff */ + +struct uart_16c550 { + volatile u_char skip0; + volatile u_char RBR; + volatile u_char skip1; + volatile u_char IER; + volatile u_char skip2; + volatile u_char IIR; + volatile u_char skip3; + volatile u_char LCR; + volatile u_char skip4; + volatile u_char MCR; + volatile u_char skip5; + volatile u_char LSR; + volatile u_char skip6; + volatile u_char MSR; + volatile u_char skip7; + volatile u_char SCR; +}; + +#define THR RBR +#define FCR IIR +#define DLL RBR +#define DLM IER +#define AFR IIR + +/* + * Bit-defines for the various registers. + */ + + +/* IER */ + +#define ERDAI (1<<0) +#define ETHREI (1<<1) +#define ELSI (1<<2) +#define EMSI (1<<3) + +/* IIR - Interrupt Ident. Register */ + +#define IRQ_PEND (1<<0) /* NOTE: IRQ_PEND=0 implies irq pending */ +#define IRQ_ID1 (1<<1) +#define IRQ_ID2 (1<<2) +#define IRQ_ID3 (1<<3) +#define FIFO_ENA0 (1<<6) /* Both these are set when FCR(1<<0)=1 */ +#define FIFO_ENA1 (1<<7) + +#define IRQ_RLS (IRQ_ID1 | IRQ_ID2) +#define IRQ_RDA (IRQ_ID2) +#define IRQ_CTI (IRQ_ID2 | IRQ_ID3) +#define IRQ_THRE (IRQ_ID1) +#define IRQ_MS 0 + +/* FCR - FIFO Control Register */ + +#define FIFO_ENA (1<<0) +#define RCVR_FIFO_RES (1<<1) +#define XMIT_FIFO_RES (1<<2) +#define DMA_MODE_SEL (1<<3) +#define RCVR_TRIG_LSB (1<<6) +#define RCVR_TRIG_MSB (1<<7) + +#define FIFO_TRIG_1 0x00 +#define FIFO_TRIG_4 RCVR_TRIG_LSB +#define FIFO_TRIG_8 RCVR_TRIG_MSB +#define FIFO_TRIG_14 RCVR_TRIG_LSB|RCVR_TRIG_MSB + +/* LCR - Line Control Register */ + +#define WLS0 (1<<0) +#define WLS1 (1<<1) +#define STB (1<<2) +#define PEN (1<<3) +#define EPS (1<<4) +#define STICK_PARITY (1<<5) +#define SET_BREAK (1<<6) +#define DLAB (1<<7) + +#define data_5bit 0x00 +#define data_6bit 0x01 +#define data_7bit 0x02 +#define data_8bit 0x03 + + +/* MCR - Modem Control Register */ + +#define DTR (1<<0) +#define RTS (1<<1) +#define OUT1 (1<<2) +#define OUT2 (1<<3) +#define LOOP (1<<4) + +/* LSR - Line Status Register */ + +#define DR (1<<0) +#define OE (1<<1) +#define PE (1<<2) +#define FE (1<<3) +#define BI (1<<4) +#define THRE (1<<5) +#define TEMT (1<<6) +#define RCVR_FIFO_ERR (1<<7) + +/* MSR - Modem Status Register */ + +#define DCTS (1<<0) +#define DDSR (1<<1) +#define TERI (1<<2) +#define DDCD (1<<3) +#define CTS (1<<4) +#define DSR (1<<5) +#define RING_I (1<<6) +#define DCD (1<<7) + +/* AFR - Alternate Function Register */ + +#define CONCUR_WRITE (1<<0) +#define BAUDOUT (1<<1) +#define RXRDY (1<<2) + +/* Parallel stuff */ + +/* + * Unfortunately National Semiconductors did not supply the + * specifications for the parallel port in the chip :-( + * TI succed though, so here they are :-) + * + * Defines for the bits can be found by including + */ +struct IOEXT_par { + volatile u_char skip0; + volatile u_char DATA; + volatile u_char skip1; + volatile u_char STATUS; + volatile u_char skip2; + volatile u_char CTRL; +}; + +#endif diff -Naur linux-2.4.26/drivers/char/Makefile linux-2.4.26-m68k/drivers/char/Makefile --- linux-2.4.26/drivers/char/Makefile 2004-02-19 00:36:31.000000000 +1100 +++ linux-2.4.26-m68k/drivers/char/Makefile 2004-02-19 09:16:15.000000000 +1100 @@ -321,6 +321,7 @@ obj-$(CONFIG_WAFER_WDT) += wafer5823wdt.o obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o obj-$(CONFIG_AMD7XX_TCO) += amd7xx_tco.o +obj-$(CONFIG_SCC2692) += generic_serial.o scc2692.o obj-$(CONFIG_INDYDOG) += indydog.o obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o diff -Naur linux-2.4.26/drivers/char/ioext.h linux-2.4.26-m68k/drivers/char/ioext.h --- linux-2.4.26/drivers/char/ioext.h 1970-01-01 10:00:00.000000000 +1000 +++ linux-2.4.26-m68k/drivers/char/ioext.h 2001-10-22 19:34:32.000000000 +1000 @@ -0,0 +1,108 @@ +/* + * Shared data structure for GVP IO-Extender support. + * + * Merge of ioext.h and ser_ioext.h + */ +#ifndef _IOEXT_H_ +#define _IOEXT_H_ + +#include +#include + +#include "16c552.h" + +#define MAX_IOEXT 5 /* + * The maximum number of io-extenders is 5, as you + * can't have more than 5 ZII boards in any Amiga. + */ + +#define UART_CLK 7372800 + +#define IOEXT_BAUD_BASE (UART_CLK / 16) + +#define IOEXT_MAX_LINES 2 + +#define IOEXT_PAR_PLIP 0x0001 +#define IOEXT_PAR_LP 0x0002 + + +/* + * Macros for the serial driver. + */ +#define curruart(info) ((struct uart_16c550 *)(info->port)) + +#define ser_DTRon(info) curruart(info)->MCR |= DTR +#define ser_RTSon(info) curruart(info)->MCR |= RTS +#define ser_DTRoff(info) curruart(info)->MCR &= ~DTR +#define ser_RTSoff(info) curruart(info)->MCR &= ~RTS + + +/* + * CNTR defines (copied from the GVP SCSI-driver file gvp11.h + */ +#define GVP_BUSY (1<<0) +#define GVP_IRQ_PEND (1<<1) +#define GVP_IRQ_ENA (1<<3) +#define GVP_DIR_WRITE (1<<4) + + +/* + * CTRL defines + */ +#define PORT0_MIDI (1<<0) /* CLR = DRIVERS SET = MIDI */ +#define PORT1_MIDI (1<<1) /* CLR = DRIVERS SET = MIDI */ +#define PORT0_DRIVER (1<<2) /* CLR = RS232, SET = MIDI */ +#define PORT1_DRIVER (1<<3) /* CLR = RS232, SET = MIDI */ +#define IRQ_SEL (1<<4) /* CLR = INT2, SET = INT6 */ +#define ROM_BANK_SEL (1<<5) /* CLR = LOW 32K, SET = HIGH 32K */ +#define PORT0_CTRL (1<<6) /* CLR = RTSx or RXRDYx, SET = RTSx ONLY */ +#define PORT1_CTRL (1<<7) /* CLR = RTSx or RXRDYx, SET = RTSx ONLY */ + + +/* + * This is the struct describing the registers on the IO-Extender. + * NOTE: The board uses a dual uart (16c552), which should be equal to + * two 16c550 uarts. + */ +typedef struct { + char gap0[0x41]; + volatile unsigned char CNTR; /* GVP DMAC CNTR (status register) */ + char gap1[0x11e]; + struct uart_16c550 uart0; /* The first uart */ + char gap2[0xf0]; + struct uart_16c550 uart1; /* The second uart */ + char gap3[0xf0]; + struct IOEXT_par par; /* The parallel port */ + char gap4[0xfb]; + volatile unsigned char CTRL; /* The control-register on the board */ +} IOEXT_struct; + + +typedef struct { + int num_uarts; + int line[IOEXT_MAX_LINES]; + volatile struct uart_16c550 *uart[IOEXT_MAX_LINES]; + IOEXT_struct *board; + int spurious_count; + unsigned char par_use; /* IOEXT_PAR_xxx */ +#if defined(CONFIG_GVPIOEXT_PLIP) || defined(CONFIG_GVPIOEXT_PLIP_MODULE) + struct nt_device *dev; +#endif +#if defined(CONFIG_GVPIOEXT_LP) || defined(CONFIG_GVPIOEXT_LP_MODULE) + struct lp_struct *lp_table; + int lp_dev; + int lp_interrupt; +#endif +} IOExtInfoType; + +/* Number of detected boards. */ +extern int ioext_num; +extern IOExtInfoType ioext_info[MAX_IOEXT]; + +void ioext_plip_interrupt(struct net_device *dev, int *spurious_count); +void ioext_lp_interrupt(int dev, int *spurious_count); + +extern struct net_device ioext_dev_plip[3]; +extern struct lp_struct ioext_lp_table[1]; + +#endif diff -Naur linux-2.4.26/drivers/char/mc68681.h linux-2.4.26-m68k/drivers/char/mc68681.h --- linux-2.4.26/drivers/char/mc68681.h 1970-01-01 10:00:00.000000000 +1000 +++ linux-2.4.26-m68k/drivers/char/mc68681.h 2001-10-22 19:34:32.000000000 +1000 @@ -0,0 +1,131 @@ +#ifndef _MC68681_H_ +#define _MC68681_H_ + +/* + * This describes an MC68681 DUART. It has almost only overlayed registers, which + * the structure very ugly. + * Note that the ri-register isn't really a register of the duart but a kludge of bsc + * to make the ring indicator available. + * + * The data came from the MFC-31-Developer Kit (from Ralph Seidel, + * zodiac@darkness.gun.de) and the data sheet of Phillip's clone device (SCN68681) + * (from Richard Hirst, srh@gpt.co.uk) + * + * 11.11.95 copyright Joerg Dorchain (dorchain@mpi-sb.mpg.de) + * + */ + +struct duarthalf { +union { +volatile u_char mr1; /* rw */ +volatile u_char mr2; /* rw */ +} mr; +volatile u_char ri; /* special, read */ +union { +volatile u_char sr; /* read */ +volatile u_char csr; /* write */ +} sr_csr; +u_char pad1; +volatile u_char cr; /* write */ +u_char pad2; +union { +volatile u_char rhr; /* read */ +volatile u_char thr; /* write */ +} hr; +u_char pad3; +}; + +struct duart { +struct duarthalf pa; +union { +volatile u_char ipcr; /* read */ +volatile u_char acr; /* write */ +} ipcr_acr; +u_char pad1; +union { +volatile u_char isr; /* read */ +volatile u_char imr; /* write */ +} ir; +u_char pad2; +volatile u_char ctu; +u_char pad3; +volatile u_char ctl; +u_char pad4; +struct duarthalf pb; +volatile u_char ivr; +u_char pad5; +union { +volatile u_char ipr; /* read */ +volatile u_char opcr; /* write */ +} ipr_opcr; +u_char pad6; +union { +volatile u_char start; /* read */ +volatile u_char sopc; /* write */ +} start_sopc; +u_char pad7; +union { +volatile u_char stop; /* read */ +volatile u_char ropc; /* write */ +} stop_ropc; +u_char pad8; +}; + +#define MR1_BITS 3 +#define MR1_5BITS 0 +#define MR1_6BITS 1 +#define MR1_7BITS 2 +#define MR1_8BITS 3 + +#define MR1_PARITY_ODD 4 + +#define MR1_PARITY 24 +#define MR1_PARITY_WITH 0 +#define MR1_PARITY_FORCE 8 +#define MR1_PARITY_NO 16 +#define MR1_PARITY_MULTIDROP 24 + +#define MR1_ERROR_BLOCK 32 +#define MR1_FFULL_IRQ 64 +#define MR1_RxRTS_ON 128 + +#define MR2_STOPS 15 +#define MR2_1STOP 7 +#define MR2_2STOP 15 + +#define MR2_CTS_ON 16 +#define MR2_TxRTS_ON 32 + +#define MR2_MODE 192 +#define MR2_NORMAL 0 +#define MR2_ECHO 64 +#define MR2_LOCALLOOP 128 +#define MR2_REMOTELOOP 192 + +#define CR_RXCOMMAND 3 +#define CR_NONE 0 +#define CR_RX_ON 1 +#define CR_RX_OFF 2 +#define CR_TXCOMMAND 12 +#define CR_TX_ON 4 +#define CR_TX_OFF 8 +#define CR_MISC 112 +#define CR_RESET_MR 16 +#define CR_RESET_RX 32 +#define CR_RESET_TX 48 +#define CR_RESET_ERR 64 +#define CR_RESET_BREAK 80 +#define CR_START_BREAK 96 +#define CR_STOP_BREAK 112 + +#define SR_RXRDY 1 +#define SR_FFULL 2 +#define SR_TXRDY 4 +#define SR_TXEMPT 8 +#define SR_OVERRUN 16 +#define SR_PARITY 32 +#define SR_FRAMING 64 +#define SR_BREAK 128 + + +#endif diff -Naur linux-2.4.26/drivers/char/pc_keyb.c linux-2.4.26-m68k/drivers/char/pc_keyb.c --- linux-2.4.26/drivers/char/pc_keyb.c 2002-11-29 10:53:12.000000000 +1100 +++ linux-2.4.26-m68k/drivers/char/pc_keyb.c 2003-07-22 07:33:07.000000000 +1000 @@ -898,6 +898,8 @@ void __init pckbd_init_hw(void) { + unsigned long flags; + if (!kbd_controller_present()) { kbd_exists = 0; return; @@ -905,6 +907,9 @@ kbd_request_region(); + save_flags(flags); + cli(); + /* Flush any pending input. */ kbd_clear_input(); @@ -922,6 +927,8 @@ /* Ok, finally allocate the IRQ, and off we go.. */ kbd_request_irq(keyboard_interrupt); + + restore_flags(flags); } #if defined CONFIG_PSMOUSE diff -Naur linux-2.4.26/drivers/char/plip_ioext.c linux-2.4.26-m68k/drivers/char/plip_ioext.c --- linux-2.4.26/drivers/char/plip_ioext.c 1970-01-01 10:00:00.000000000 +1000 +++ linux-2.4.26-m68k/drivers/char/plip_ioext.c 2001-11-02 07:04:56.000000000 +1100 @@ -0,0 +1,1065 @@ +/* + * plip_ioext: A parallel port "network" driver for GVP IO-Extender. + * + * Authors: See drivers/net/plip.c + * IO-Extender version by Steve Bennett, + * + * This driver is for use with a 5-bit cable (LapLink (R) cable). + */ + +static const char *version = "NET3 PLIP version 2.2/m68k"; + +#define __NO_VERSION__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +/*#include */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "ioext.h" + +#define DEBUG 0 + +/* Map 'struct device *' to our control structure */ +#define PLIP_DEV(DEV) (&ioext_info[(DEV)->irq]) + +/************************************************************************ +** +** PLIP definitions +** +************************************************************************* +*/ + +/* Use 0 for production, 1 for verification, >2 for debug */ +#ifndef NET_DEBUG +#define NET_DEBUG 2 +#endif +static unsigned int net_debug = NET_DEBUG; + +/* In micro second */ +#define PLIP_DELAY_UNIT 1 + +/* Connection time out = PLIP_TRIGGER_WAIT * PLIP_DELAY_UNIT usec */ +#define PLIP_TRIGGER_WAIT 500 + +/* Nibble time out = PLIP_NIBBLE_WAIT * PLIP_DELAY_UNIT usec */ +#define PLIP_NIBBLE_WAIT 3000 + +#define PAR_DATA(dev) ((dev)->base_addr+0) +#define PAR_STATUS(dev) ((dev)->base_addr+2) +#define PAR_CONTROL(dev) ((dev)->base_addr+4) + +static void enable_par_irq(struct device *dev, int on); +static int plip_init(struct device *dev); + +/* Bottom halfs */ +static void plip_kick_bh(struct device *dev); +static void plip_bh(struct device *dev); + +/* Functions for DEV methods */ +static int plip_rebuild_header(struct sk_buff *skb); +static int plip_tx_packet(struct sk_buff *skb, struct device *dev); +static int plip_open(struct device *dev); +static int plip_close(struct device *dev); +static struct enet_statistics *plip_get_stats(struct device *dev); +static int plip_config(struct device *dev, struct ifmap *map); +static int plip_ioctl(struct device *dev, struct ifreq *ifr, int cmd); + +enum plip_connection_state { + PLIP_CN_NONE=0, + PLIP_CN_RECEIVE, + PLIP_CN_SEND, + PLIP_CN_CLOSING, + PLIP_CN_ERROR +}; + +enum plip_packet_state { + PLIP_PK_DONE=0, + PLIP_PK_TRIGGER, + PLIP_PK_LENGTH_LSB, + PLIP_PK_LENGTH_MSB, + PLIP_PK_DATA, + PLIP_PK_CHECKSUM +}; + +enum plip_nibble_state { + PLIP_NB_BEGIN, + PLIP_NB_1, + PLIP_NB_2, +}; + +struct plip_local { + enum plip_packet_state state; + enum plip_nibble_state nibble; + union { + struct { +#if defined(__LITTLE_ENDIAN) + unsigned char lsb; + unsigned char msb; +#elif defined(__BIG_ENDIAN) + unsigned char msb; + unsigned char lsb; +#else +#error "Please fix the endianness defines in " +#endif + } b; + unsigned short h; + } length; + unsigned short byte; + unsigned char checksum; + unsigned char data; + struct sk_buff *skb; +}; + +struct net_local { + struct enet_statistics enet_stats; + struct tq_struct immediate; + struct tq_struct deferred; + struct plip_local snd_data; + struct plip_local rcv_data; + unsigned long trigger; + unsigned long nibble; + enum plip_connection_state connection; + unsigned short timeout_count; + char is_deferred; + int (*orig_rebuild_header)(struct sk_buff *skb); +}; + +struct device ioext_dev_plip[] = { + { + "plip0", + 0, 0, 0, 0, /* memory */ + 0, 0, /* base, irq */ + 0, 0, 0, NULL, plip_init + }, + { + "plip1", + 0, 0, 0, 0, /* memory */ + 0, 0, /* base, irq */ + 0, 0, 0, NULL, plip_init + }, + { + "plip2", + 0, 0, 0, 0, /* memory */ + 0, 0, /* base, irq */ + 0, 0, 0, NULL, plip_init + } +}; + +/* + * Check for and handle an interrupt for this PLIP device. + * + */ +void ioext_plip_interrupt(struct device *dev, int *spurious_count) +{ + struct net_local *nl; + struct plip_local *rcv; + unsigned char c0; + unsigned long flags; + + nl = (struct net_local *)dev->priv; + rcv = &nl->rcv_data; + + c0 = z_readb(PAR_STATUS(dev)); + + if (dev->interrupt) { + return; + } + + if ((c0 & 0xf8) != 0xc0) { + /* Not for us */ + ++*spurious_count; + return; + } + + *spurious_count = 0; + dev->interrupt = 1; + + save_flags(flags); + cli(); + + switch (nl->connection) { + case PLIP_CN_CLOSING: + dev->tbusy = 0; + case PLIP_CN_NONE: + case PLIP_CN_SEND: + dev->last_rx = jiffies; + rcv->state = PLIP_PK_TRIGGER; + nl->connection = PLIP_CN_RECEIVE; + nl->timeout_count = 0; + queue_task(&nl->immediate, &tq_immediate); + mark_bh(IMMEDIATE_BH); + restore_flags(flags); +#if 0 + printk("%s: receive irq in SEND/NONE/CLOSING (%d) ok\n", + dev->name, nl->connection); +#endif + break; + + case PLIP_CN_RECEIVE: + restore_flags(flags); + printk("%s: receive interrupt when receiving packet\n", + dev->name); + break; + + case PLIP_CN_ERROR: + restore_flags(flags); + printk("%s: receive interrupt in error state\n", dev->name); + break; + } +} + + +/* Bottom half handler for the delayed request. + This routine is kicked by do_timer(). + Request `plip_bh' to be invoked. */ +static void +plip_kick_bh(struct device *dev) +{ + struct net_local *nl = (struct net_local *)dev->priv; + + if (nl->is_deferred) { + queue_task(&nl->immediate, &tq_immediate); + mark_bh(IMMEDIATE_BH); + } +} + +/* Forward declarations of internal routines */ +static int plip_none(struct device *, struct net_local *, + struct plip_local *, struct plip_local *); +static int plip_receive_packet(struct device *, struct net_local *, + struct plip_local *, struct plip_local *); +static int plip_send_packet(struct device *, struct net_local *, + struct plip_local *, struct plip_local *); +static int plip_connection_close(struct device *, struct net_local *, + struct plip_local *, struct plip_local *); +static int plip_error(struct device *, struct net_local *, + struct plip_local *, struct plip_local *); +static int plip_bh_timeout_error(struct device *dev, struct net_local *nl, + struct plip_local *snd, + struct plip_local *rcv, + int error); + +#define OK 0 +#define TIMEOUT 1 +#define ERROR 2 + +typedef int (*plip_func)(struct device *dev, struct net_local *nl, + struct plip_local *snd, struct plip_local *rcv); + +static plip_func connection_state_table[] = +{ + plip_none, + plip_receive_packet, + plip_send_packet, + plip_connection_close, + plip_error +}; + +/* +** enable_par_irq() +** +** Enable or disable parallel irq for 'dev' according to 'on'. +** +** It is NOT possible to disable only the parallel irq. +** So we disable the board interrupt instead. This means that +** during reception of a PLIP packet, no serial interrupts can +** happen. Sorry. +*/ +static void enable_par_irq(struct device *dev, int on) +{ + if (on) { + PLIP_DEV(dev)->board->CNTR |= GVP_IRQ_ENA; + } + else { + PLIP_DEV(dev)->board->CNTR &= ~GVP_IRQ_ENA; + } +} + +/* Bottom half handler of PLIP. */ +static void +plip_bh(struct device *dev) +{ + struct net_local *nl = (struct net_local *)dev->priv; + struct plip_local *snd = &nl->snd_data; + struct plip_local *rcv = &nl->rcv_data; + plip_func f; + int r; + + nl->is_deferred = 0; + f = connection_state_table[nl->connection]; + if ((r = (*f)(dev, nl, snd, rcv)) != OK + && (r = plip_bh_timeout_error(dev, nl, snd, rcv, r)) != OK) { + nl->is_deferred = 1; + queue_task(&nl->deferred, &tq_timer); + } +} + +static int +plip_bh_timeout_error(struct device *dev, struct net_local *nl, + struct plip_local *snd, struct plip_local *rcv, + int error) +{ + unsigned char c0; + unsigned long flags; + + save_flags(flags); + cli(); + if (nl->connection == PLIP_CN_SEND) { + + if (error != ERROR) { /* Timeout */ + nl->timeout_count++; + if ((snd->state == PLIP_PK_TRIGGER + && nl->timeout_count <= 10) + || nl->timeout_count <= 3) { + restore_flags(flags); + /* Try again later */ + return TIMEOUT; + } + c0 = z_readb(PAR_STATUS(dev)); + printk(KERN_INFO "%s: transmit timeout(%d,%02x)\n", + dev->name, snd->state, c0); + } + nl->enet_stats.tx_errors++; + nl->enet_stats.tx_aborted_errors++; + } else if (nl->connection == PLIP_CN_RECEIVE) { + if (rcv->state == PLIP_PK_TRIGGER) { + /* Transmission was interrupted. */ + restore_flags(flags); + return OK; + } + if (error != ERROR) { /* Timeout */ + if (++nl->timeout_count <= 3) { + restore_flags(flags); + /* Try again later */ + return TIMEOUT; + } + c0 = z_readb(PAR_STATUS(dev)); + printk(KERN_INFO "%s: receive timeout(%d,%02x)\n", + dev->name, rcv->state, c0); + } + nl->enet_stats.rx_dropped++; + } + rcv->state = PLIP_PK_DONE; + if (rcv->skb) { + kfree_skb(rcv->skb); + rcv->skb = NULL; + } + snd->state = PLIP_PK_DONE; + if (snd->skb) { + dev_kfree_skb(snd->skb); + snd->skb = NULL; + } + enable_par_irq(dev, 0); + dev->tbusy = 1; + nl->connection = PLIP_CN_ERROR; + z_writeb(0x00, PAR_DATA(dev)); + restore_flags(flags); + + return TIMEOUT; +} + +static int +plip_none(struct device *dev, struct net_local *nl, + struct plip_local *snd, struct plip_local *rcv) +{ + return OK; +} + +/* PLIP_RECEIVE --- receive a byte(two nibbles) + Returns OK on success, TIMEOUT on timeout */ +inline static int +plip_receive(struct device *dev, unsigned short nibble_timeout, + enum plip_nibble_state *ns_p, unsigned char *data_p) +{ + unsigned char c0, c1; + unsigned int cx; + + switch (*ns_p) { + case PLIP_NB_BEGIN: + cx = nibble_timeout; + while (1) { + c0 = z_readb(PAR_STATUS(dev)); + udelay(PLIP_DELAY_UNIT); + if ((c0 & 0x80) == 0) { + c1 = z_readb(PAR_STATUS(dev)); + if (c0 == c1) + break; + } + if (--cx == 0) + return TIMEOUT; + } +#if 0 + printk("received first nybble: %02X -> %02X\n", + c0, (c0 >> 3) & 0x0F); +#endif + *data_p = (c0 >> 3) & 0x0f; + z_writeb(0x10, PAR_DATA(dev)); /* send ACK */ + *ns_p = PLIP_NB_1; + + case PLIP_NB_1: + cx = nibble_timeout; + while (1) { + c0 = z_readb(PAR_STATUS(dev)); + udelay(PLIP_DELAY_UNIT); + if (c0 & 0x80) { + c1 = z_readb(PAR_STATUS(dev)); + if (c0 == c1) + break; + } + if (--cx == 0) + return TIMEOUT; + } +#if 0 + printk("received second nybble: %02X -> %02X\n", + c0, (c0 << 1) & 0xF0); +#endif + *data_p |= (c0 << 1) & 0xf0; + z_writeb(0x00, PAR_DATA(dev)); /* send ACK */ + *ns_p = PLIP_NB_BEGIN; + case PLIP_NB_2: + break; + } + return OK; +} + +/* PLIP_RECEIVE_PACKET --- receive a packet */ +static int +plip_receive_packet(struct device *dev, struct net_local *nl, + struct plip_local *snd, struct plip_local *rcv) +{ + unsigned short nibble_timeout = nl->nibble; + unsigned char *lbuf; + unsigned long flags; + + switch (rcv->state) { + case PLIP_PK_TRIGGER: + enable_par_irq(dev, 0); + dev->interrupt = 0; + z_writeb(0x01, PAR_DATA(dev)); /* send ACK */ + if (net_debug > 2) + printk(KERN_DEBUG "%s: receive start\n", dev->name); + rcv->state = PLIP_PK_LENGTH_LSB; + rcv->nibble = PLIP_NB_BEGIN; + + case PLIP_PK_LENGTH_LSB: + if (snd->state != PLIP_PK_DONE) { + if (plip_receive(dev, nl->trigger, + &rcv->nibble, &rcv->length.b.lsb)) { + /* collision, here dev->tbusy == 1 */ + rcv->state = PLIP_PK_DONE; + nl->is_deferred = 1; + nl->connection = PLIP_CN_SEND; + queue_task(&nl->deferred, &tq_timer); + enable_par_irq(dev, 1); + return OK; + } + } else { + if (plip_receive(dev, nibble_timeout, + &rcv->nibble, &rcv->length.b.lsb)) + return TIMEOUT; + } + rcv->state = PLIP_PK_LENGTH_MSB; + + case PLIP_PK_LENGTH_MSB: + if (plip_receive(dev, nibble_timeout, + &rcv->nibble, &rcv->length.b.msb)) + return TIMEOUT; + if (rcv->length.h > dev->mtu + dev->hard_header_len + || rcv->length.h < 8) { + printk(KERN_INFO "%s: bogus packet size %d.\n", + dev->name, rcv->length.h); + return ERROR; + } + /* Malloc up new buffer. */ + rcv->skb = dev_alloc_skb(rcv->length.h); + if (rcv->skb == NULL) { + printk(KERN_INFO "%s: Memory squeeze.\n", dev->name); + return ERROR; + } + skb_put(rcv->skb,rcv->length.h); + rcv->skb->dev = dev; + rcv->state = PLIP_PK_DATA; + rcv->byte = 0; + rcv->checksum = 0; + + case PLIP_PK_DATA: + lbuf = rcv->skb->data; + do + if (plip_receive(dev, nibble_timeout, + &rcv->nibble, &lbuf[rcv->byte])) + return TIMEOUT; + while (++rcv->byte < rcv->length.h); + do + rcv->checksum += lbuf[--rcv->byte]; + while (rcv->byte); + rcv->state = PLIP_PK_CHECKSUM; + + case PLIP_PK_CHECKSUM: + if (plip_receive(dev, nibble_timeout, + &rcv->nibble, &rcv->data)) + return TIMEOUT; + if (rcv->data != rcv->checksum) { + nl->enet_stats.rx_crc_errors++; + if (net_debug) + printk(KERN_INFO "%s: checksum error\n", + dev->name); + return ERROR; + } + rcv->state = PLIP_PK_DONE; + + case PLIP_PK_DONE: + /* Inform the upper layer for the arrival of a packet. */ + rcv->skb->protocol=eth_type_trans(rcv->skb, dev); + netif_rx(rcv->skb); + nl->enet_stats.rx_packets++; + rcv->skb = NULL; + if (net_debug > 2) + printk(KERN_DEBUG "%s: receive end\n", dev->name); + + /* Close the connection. */ + z_writeb (0x00, PAR_DATA(dev)); + + save_flags(flags); + cli(); + if (snd->state != PLIP_PK_DONE) { + nl->connection = PLIP_CN_SEND; + restore_flags(flags); + queue_task(&nl->immediate, &tq_immediate); + mark_bh(IMMEDIATE_BH); + enable_par_irq(dev, 1); + return OK; + } else { + nl->connection = PLIP_CN_NONE; + restore_flags(flags); + enable_par_irq(dev, 1); + return OK; + } + } + return OK; +} + +/* PLIP_SEND --- send a byte (two nibbles) + Returns OK on success, TIMEOUT when timeout */ +inline static int +plip_send(struct device *dev, unsigned short nibble_timeout, + enum plip_nibble_state *ns_p, unsigned char data) +{ + unsigned char c0; + unsigned int cx; + + switch (*ns_p) { + case PLIP_NB_BEGIN: + z_writeb((data & 0x0f), PAR_DATA(dev)); + *ns_p = PLIP_NB_1; + + case PLIP_NB_1: + z_writeb(0x10 | (data & 0x0f), PAR_DATA(dev)); + cx = nibble_timeout; + while (1) { + c0 = z_readb(PAR_STATUS(dev)); + if ((c0 & 0x80) == 0) + break; + if (--cx == 0) + return TIMEOUT; + udelay(PLIP_DELAY_UNIT); + } + z_writeb(0x10 | (data >> 4), PAR_DATA(dev)); + *ns_p = PLIP_NB_2; + + case PLIP_NB_2: + z_writeb((data >> 4), PAR_DATA(dev)); + cx = nibble_timeout; + while (1) { + c0 = z_readb(PAR_STATUS(dev)); + if (c0 & 0x80) + break; + if (--cx == 0) + return TIMEOUT; + udelay(PLIP_DELAY_UNIT); + } + *ns_p = PLIP_NB_BEGIN; + return OK; + } + return OK; +} + +/* PLIP_SEND_PACKET --- send a packet */ +static int +plip_send_packet(struct device *dev, struct net_local *nl, + struct plip_local *snd, struct plip_local *rcv) +{ + unsigned short nibble_timeout = nl->nibble; + unsigned char *lbuf; + unsigned char c0; + unsigned int cx; + unsigned long flags; + + if (snd->skb == NULL || (lbuf = snd->skb->data) == NULL) { + printk(KERN_INFO "%s: send skb lost\n", dev->name); + snd->state = PLIP_PK_DONE; + snd->skb = NULL; + return ERROR; + } + + if (snd->length.h == 0) { + return OK; + } + + switch (snd->state) { + case PLIP_PK_TRIGGER: + if ((z_readb(PAR_STATUS(dev)) & 0xf8) != 0x80) + return TIMEOUT; + + /* Trigger remote rx interrupt. */ + z_writeb(0x08, PAR_DATA(dev)); + cx = nl->trigger; + while (1) { + udelay(PLIP_DELAY_UNIT); + save_flags(flags); + cli(); + if (nl->connection == PLIP_CN_RECEIVE) { + restore_flags(flags); + /* interrupted */ + nl->enet_stats.collisions++; + if (net_debug > 1) + printk(KERN_INFO "%s: collision.\n", + dev->name); + return OK; + } + c0 = z_readb(PAR_STATUS(dev)); + if (c0 & 0x08) { + enable_par_irq(dev, 0); + if (net_debug > 2) + printk(KERN_DEBUG "%s: send start\n", + dev->name); + snd->state = PLIP_PK_LENGTH_LSB; + snd->nibble = PLIP_NB_BEGIN; + nl->timeout_count = 0; + restore_flags(flags); + break; + } + restore_flags(flags); + if (--cx == 0) { + z_writeb(0x00, PAR_DATA(dev)); + return TIMEOUT; + } + } + + case PLIP_PK_LENGTH_LSB: + if (plip_send(dev, nibble_timeout, + &snd->nibble, snd->length.b.lsb)) + return TIMEOUT; + snd->state = PLIP_PK_LENGTH_MSB; + + case PLIP_PK_LENGTH_MSB: + if (plip_send(dev, nibble_timeout, + &snd->nibble, snd->length.b.msb)) + return TIMEOUT; + snd->state = PLIP_PK_DATA; + snd->byte = 0; + snd->checksum = 0; + + case PLIP_PK_DATA: + do + if (plip_send(dev, nibble_timeout, + &snd->nibble, lbuf[snd->byte])) + return TIMEOUT; + while (++snd->byte < snd->length.h); + do + snd->checksum += lbuf[--snd->byte]; + while (snd->byte); + snd->state = PLIP_PK_CHECKSUM; + + case PLIP_PK_CHECKSUM: + if (plip_send(dev, nibble_timeout, + &snd->nibble, snd->checksum)) + return TIMEOUT; + + dev_kfree_skb(snd->skb); + nl->enet_stats.tx_packets++; + snd->state = PLIP_PK_DONE; + + case PLIP_PK_DONE: + /* Close the connection */ + z_writeb (0x00, PAR_DATA(dev)); + snd->skb = NULL; + if (net_debug > 2) + printk(KERN_DEBUG "%s: send end\n", dev->name); + nl->connection = PLIP_CN_CLOSING; + nl->is_deferred = 1; + queue_task(&nl->deferred, &tq_timer); + enable_par_irq(dev, 1); + return OK; + } + return OK; +} + +static int +plip_connection_close(struct device *dev, struct net_local *nl, + struct plip_local *snd, struct plip_local *rcv) +{ + unsigned long flags; + + save_flags(flags); + cli(); + if (nl->connection == PLIP_CN_CLOSING) { + nl->connection = PLIP_CN_NONE; + dev->tbusy = 0; + mark_bh(NET_BH); + } + restore_flags(flags); + return OK; +} + +/* PLIP_ERROR --- wait till other end settled */ +static int +plip_error(struct device *dev, struct net_local *nl, + struct plip_local *snd, struct plip_local *rcv) +{ + unsigned char status; + + status = z_readb(PAR_STATUS(dev)); + if ((status & 0xf8) == 0x80) { + if (net_debug > 2) + printk(KERN_DEBUG "%s: reset interface.\n", dev->name); + nl->connection = PLIP_CN_NONE; + dev->tbusy = 0; + dev->interrupt = 0; + enable_par_irq(dev, 1); + mark_bh(NET_BH); + } else { + nl->is_deferred = 1; + queue_task(&nl->deferred, &tq_timer); + } + + return OK; +} + +/* We don't need to send arp, for plip is point-to-point. */ +static int +plip_rebuild_header(struct sk_buff *skb) +{ + struct device *dev = skb->dev; + struct net_local *nl = (struct net_local *)dev->priv; + struct ethhdr *eth = (struct ethhdr *)skb->data; + int i; + + if ((dev->flags & IFF_NOARP)==0) + return nl->orig_rebuild_header(skb); + + if (eth->h_proto != __constant_htons(ETH_P_IP) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) + && eth->h_proto != __constant_htons(ETH_P_IPV6) +#endif + ) { + printk(KERN_ERR "plip_rebuild_header: Don't know how to resolve type %d addresses?\n", (int)eth->h_proto); + memcpy(eth->h_source, dev->dev_addr, dev->addr_len); + return 0; + } + + for (i=0; i < ETH_ALEN - sizeof(u32); i++) + eth->h_dest[i] = 0xfc; +#if 0 + *(u32 *)(eth->h_dest+i) = dst; +#else + /* Do not want to include net/route.h here. + * In any case, it is TOP of silliness to emulate + * hardware addresses on PtP link. --ANK + */ + *(u32 *)(eth->h_dest+i) = 0; +#endif + return 0; +} + +static int +plip_tx_packet(struct sk_buff *skb, struct device *dev) +{ + struct net_local *nl = (struct net_local *)dev->priv; + struct plip_local *snd = &nl->snd_data; + unsigned long flags; + + if (dev->tbusy) + return 1; + + if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) { + printk(KERN_ERR "%s: Transmitter access conflict.\n", + dev->name); + return 1; + } + + if (skb->len > dev->mtu + dev->hard_header_len) { + printk(KERN_ERR "%s: packet too big, %d.\n", + dev->name, (int)skb->len); + dev->tbusy = 0; + return 0; + } + + if (net_debug > 2) + printk(KERN_DEBUG "%s: send request\n", dev->name); + + save_flags(flags); + cli(); + dev->trans_start = jiffies; + snd->skb = skb; + snd->length.h = skb->len; + snd->state = PLIP_PK_TRIGGER; + if (nl->connection == PLIP_CN_NONE) { + nl->connection = PLIP_CN_SEND; + nl->timeout_count = 0; + } + queue_task(&nl->immediate, &tq_immediate); + mark_bh(IMMEDIATE_BH); + restore_flags(flags); + + return 0; +} + +/* Open/initialize the board. This is called (in the current kernel) + sometime after booting when the 'ifconfig' program is run. + + */ +static int +plip_open(struct device *dev) +{ + struct net_local *nl = (struct net_local *)dev->priv; + struct in_device *in_dev; + +#if defined(CONFIG_GVPIOEXT_LP) || defined(CONFIG_GVPIOEXT_LP_MODULE) + /* Yes, there is a race condition here. Fix it later */ + if (PLIP_DEV(dev)->par_use & IOEXT_PAR_LP) { + /* Can't open if lp is in use */ +#if DEBUG + printk("par is in use by lp\n"); +#endif + return(-EBUSY); + } +#endif + PLIP_DEV(dev)->par_use |= IOEXT_PAR_PLIP; + +#if DEBUG + printk("plip_open(): sending 00 to data port\n"); +#endif + + /* Clear the data port. */ + z_writeb (0x00, PAR_DATA(dev)); + +#if DEBUG + printk("plip_open(): sent\n"); +#endif + + /* Initialize the state machine. */ + nl->rcv_data.state = nl->snd_data.state = PLIP_PK_DONE; + nl->rcv_data.skb = nl->snd_data.skb = NULL; + nl->connection = PLIP_CN_NONE; + nl->is_deferred = 0; + + /* Fill in the MAC-level header. + (ab)Use "dev->broadcast" to store point-to-point MAC address. + + PLIP doesn't have a real mac address, but we need to create one + to be DOS compatible. */ + memset(dev->dev_addr, 0xfc, ETH_ALEN); + memset(dev->broadcast, 0xfc, ETH_ALEN); + + if ((in_dev=dev->ip_ptr) != NULL) { + /* + * Any address will do - we take the first + */ + struct in_ifaddr *ifa=in_dev->ifa_list; + if (ifa != NULL) { + memcpy(dev->dev_addr+2, &ifa->ifa_local, 4); + memcpy(dev->broadcast+2, &ifa->ifa_address, 4); + } + } + + dev->interrupt = 0; + dev->start = 1; + dev->tbusy = 0; + + MOD_INC_USE_COUNT; + + /* Enable rx interrupt. */ + enable_par_irq(dev, 1); + + return 0; +} + +/* The inverse routine to plip_open (). */ +static int +plip_close(struct device *dev) +{ + struct net_local *nl = (struct net_local *)dev->priv; + struct plip_local *snd = &nl->snd_data; + struct plip_local *rcv = &nl->rcv_data; + unsigned long flags; + + dev->tbusy = 1; + dev->start = 0; + save_flags(flags); + cli(); + nl->is_deferred = 0; + nl->connection = PLIP_CN_NONE; + restore_flags(flags); + z_writeb(0x00, PAR_DATA(dev)); + + snd->state = PLIP_PK_DONE; + if (snd->skb) { + dev_kfree_skb(snd->skb); + snd->skb = NULL; + } + rcv->state = PLIP_PK_DONE; + if (rcv->skb) { + kfree_skb(rcv->skb); + rcv->skb = NULL; + } + + PLIP_DEV(dev)->par_use &= ~IOEXT_PAR_PLIP; + + MOD_DEC_USE_COUNT; + return 0; +} + +static struct enet_statistics * +plip_get_stats(struct device *dev) +{ + struct net_local *nl = (struct net_local *)dev->priv; + struct enet_statistics *r = &nl->enet_stats; + + return r; +} + +static int +plip_config(struct device *dev, struct ifmap *map) +{ + if (dev->flags & IFF_UP) + return -EBUSY; + + printk(KERN_INFO "%s: This interface is autodetected (ignored).\n", + dev->name); + + return 0; +} + +static int +plip_ioctl(struct device *dev, struct ifreq *rq, int cmd) +{ + struct net_local *nl = (struct net_local *) dev->priv; + struct plipconf *pc = (struct plipconf *) &rq->ifr_data; + + switch(pc->pcmd) { + case PLIP_GET_TIMEOUT: + pc->trigger = nl->trigger; + pc->nibble = nl->nibble; + break; + case PLIP_SET_TIMEOUT: + nl->trigger = pc->trigger; + nl->nibble = pc->nibble; + break; + default: + return -EOPNOTSUPP; + } + return 0; +} + +/* + * Detect and initialize all IO-Extenders in this system. + * + * Both PLIP and serial devices are configured. + */ +int plip_init(struct device *dev) +{ + IOEXT_struct *board; + struct net_local *nl; + + if (ioext_num == 0) { + printk(KERN_INFO "%s\n", version); + } + + board = PLIP_DEV(dev)->board; + dev->base_addr = (unsigned long)&board->par.DATA; + + /* Cheat and use irq to index into our table */ + dev->irq = ioext_num; + + printk(KERN_INFO "%s: IO-Extender parallel port at 0x%08lX\n", dev->name, dev->base_addr); + + /* Fill in the generic fields of the device structure. */ + ether_setup(dev); + + /* Then, override parts of it */ + dev->hard_start_xmit = plip_tx_packet; + dev->open = plip_open; + dev->stop = plip_close; + dev->get_stats = plip_get_stats; + dev->set_config = plip_config; + dev->do_ioctl = plip_ioctl; + dev->tx_queue_len = 10; + dev->flags = IFF_POINTOPOINT|IFF_NOARP; + + /* Set the private structure */ + dev->priv = kmalloc(sizeof (struct net_local), GFP_KERNEL); + if (dev->priv == NULL) { + printk(KERN_ERR "%s: out of memory\n", dev->name); + return -ENOMEM; + } + memset(dev->priv, 0, sizeof(struct net_local)); + nl = (struct net_local *) dev->priv; + + nl->orig_rebuild_header = dev->rebuild_header; + dev->rebuild_header = plip_rebuild_header; + + /* Initialize constants */ + nl->trigger = PLIP_TRIGGER_WAIT; + nl->nibble = PLIP_NIBBLE_WAIT; + + /* Initialize task queue structures */ + nl->immediate.next = NULL; + nl->immediate.sync = 0; + nl->immediate.routine = (void *)(void *)plip_bh; + nl->immediate.data = dev; + + nl->deferred.next = NULL; + nl->deferred.sync = 0; + nl->deferred.routine = (void *)(void *)plip_kick_bh; + nl->deferred.data = dev; + + /* Don't enable interrupts yet */ + + return 0; +} diff -Naur linux-2.4.26/drivers/char/scc2692.c linux-2.4.26-m68k/drivers/char/scc2692.c --- linux-2.4.26/drivers/char/scc2692.c 1970-01-01 10:00:00.000000000 +1000 +++ linux-2.4.26-m68k/drivers/char/scc2692.c 2003-07-22 07:31:02.000000000 +1000 @@ -0,0 +1,617 @@ +#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 + +#define NR_PORTS 2 + +static struct scc_port +{ + struct gs_port gs; + unsigned long base; + int irq_rx, irq_tx; + unsigned char channel; + unsigned long scale; +} scc_ports[NR_PORTS]; + +#define STATUS(scc) ((scc)->base + (((scc)->channel * 8 + 1) * (scc)->scale)) +#define CSR(scc) STATUS(scc) + +#define RECEIVE(scc) ((scc)->base + (((scc)->channel * 8 + 3) * (scc)->scale)) +#define TRANSMIT(scc) RECEIVE(scc) + +#define COMMAND(scc) ((scc)->base + (((scc)->channel * 8 + 2) * (scc)->scale)) + +#define MR(scc) ((scc)->base + (((scc)->channel * 8 + 0) * (scc)->scale)) + + +static struct tty_driver scc_driver, scc_callout_driver; +static struct tty_struct *scc_table[NR_PORTS] = { NULL, NULL }; +static struct termios *scc_termios[NR_PORTS]; +static struct termios *scc_termios_locked[NR_PORTS]; + +int scc_refcount; + +#define SCC_MINOR_BASE 64 +#define SCC_MAGIC 0x52696368 + +static inline void scc_disable_tx_interrupts(void *ptr) +{ + struct scc_port *port = ptr; + disable_irq(port->irq_tx); + port->gs.flags &= ~GS_TX_INTEN; +} + +static inline void scc_enable_tx_interrupts(void *ptr) +{ + struct scc_port *port = ptr; + enable_irq(port->irq_tx); +} + +static inline void scc_disable_rx_interrupts(void *ptr) +{ + struct scc_port *port = ptr; + disable_irq(port->irq_rx); +} + +static inline void scc_enable_rx_interrupts(void *ptr) +{ + struct scc_port *port = ptr; + enable_irq(port->irq_rx); +} + + +/* + * Receiver Interrupt + */ +static void scc_rx_int(int irq, void *data, struct pt_regs *fp) +{ + struct scc_port *port = data; + struct tty_struct *tty = port->gs.tty; + unsigned long flags; + volatile unsigned char ch; + + spin_lock_irqsave(tek_uart_lock, flags); + while ( *(volatile unsigned char *)STATUS(port) & 0x1 ) + { + ch = *(volatile unsigned char *)RECEIVE(port); + + if (!tty) + /* + * FIXME: It might be a bad idea to call printk + * with the lock held. + */ + printk(KERN_WARNING "scc_rx_int with NULL tty!\n"); + else if (tty->flip.count < TTY_FLIPBUF_SIZE) { + *tty->flip.char_buf_ptr = ch; + *tty->flip.flag_buf_ptr = 0; + tty->flip.flag_buf_ptr++; + tty->flip.char_buf_ptr++; + tty->flip.count++; + } + } + spin_unlock_irqrestore(tek_uart_lock, flags); + + tty_flip_buffer_push(tty); +} + +/* + * Transmitter interrupt + */ +static void scc_tx_int(int irq, void *data, struct pt_regs *fp) +{ + struct scc_port *port = data; + struct tty_struct *tty = port->gs.tty; + unsigned long flags; + + if ( !tty ) + { + scc_disable_tx_interrupts(port); + return; + } + + spin_lock_irqsave(tek_uart_lock, flags); + while ( *(volatile unsigned char *)STATUS(port) & 0x4 ) + { + *(volatile unsigned char *)TRANSMIT(port) = + port->gs.xmit_buf[port->gs.xmit_tail++]; + port->gs.xmit_tail = port->gs.xmit_tail & (SERIAL_XMIT_SIZE-1); + if (--port->gs.xmit_cnt <= 0) + break; + } + spin_unlock_irqrestore(tek_uart_lock, flags); + + if ((port->gs.xmit_cnt <= 0) || (tty && (tty->stopped || tty->hw_stopped)) ) + { + scc_disable_tx_interrupts(port); + } + + if (tty && port->gs.xmit_cnt <= port->gs.wakeup_chars) { + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) + (tty->ldisc.write_wakeup)(port->gs.tty); + wake_up_interruptible(&tty->write_wait); + } +} + +/*--------------------------------------------------------------------------- + * generic_serial.c callback funtions + *--------------------------------------------------------------------------*/ + +static int scc_get_CD(void *ptr) +{ + return 1; +} + +static void scc_shutdown_port(void *ptr) +{ + struct scc_port *port = ptr; + + port->gs.flags &= ~ GS_ACTIVE; +} + +static const int baudrates[B38400] = { + [B19200] 13, + [B9600] 12, + [B4800] 10, + [B2400] 9, + [B1200] 7, + [B600] 6, + [B300] 5, + [B134] 3, + [B110] 2, + [B75] 1 +}; + +static int scc_set_real_termios(void *ptr) +{ + struct scc_port *port = ptr; + unsigned long flags; + unsigned int cflag; + unsigned char baudrate = 0; + unsigned char mr1 = 0x80, mr2 = 0; + int baud; + + if (!port->gs.tty || !port->gs.tty->termios) + return 0; + + cflag = port->gs.tty->termios->c_cflag; + baud = cflag & (CBAUD | CBAUDEX); + + if (baud == B0) + { + // TODO: hangup + return 0; + } + + if ((baud >= sizeof baudrates/sizeof baudrates[0]) || !baudrates[baud]) + return -EINVAL; + baudrate = baudrates[baud] - 1; + + if ( cflag & CSTOPB ) + mr2 |= 0x7; /* 1 stop bit */ + + if ( !(cflag & PARENB) ) + mr1 |= 0x10; /* no parity */ + else if ( cflag & PARODD ) + mr1 |= 0x04; + + switch (cflag & CSIZE) + { + case CS5: + break; + case CS6: + mr1 |= 0x01; + break; + case CS7: + mr1 |= 0x02; + break; + case CS8: + mr1 |= 0x03; + break; + default: + return -EINVAL; + } + +/* + printk("scc2692: real_termios line=%d baudrate=%02x mr1=%02x mr2=%02x\n", port->channel, baudrate, mr1, mr2); +*/ + + spin_lock_irqsave(tek_uart_lock, flags); + + // Set baudrate into register CSRA + *(volatile unsigned char *)CSR(port) = (baudrate << 4) | (baudrate & 0xf); + // Reset MR pointer + *(volatile unsigned char *)COMMAND(port) = 1 << 4; + // Set MR1 + *(volatile unsigned char *)MR(port) = mr1; + // Set MR2 + *(volatile unsigned char *)MR(port) = mr2; + + spin_unlock_irqrestore(tek_uart_lock, flags); + + return 0; +} + +static int scc_chars_in_buffer(void *ptr) +{ + struct scc_port *port = ptr; + int res; + unsigned long flags; + + spin_lock_irqsave(tek_uart_lock, flags); + res = !(*(volatile unsigned char *)STATUS(port) & 4); + spin_unlock_irqrestore(tek_uart_lock, flags); + + return res; +} + +static void scc_hungup(void *ptr) +{ + scc_disable_tx_interrupts(ptr); + scc_disable_rx_interrupts(ptr); + MOD_DEC_USE_COUNT; +} + +static void scc_close(void *ptr) +{ + scc_disable_tx_interrupts(ptr); + scc_disable_rx_interrupts(ptr); + MOD_DEC_USE_COUNT; +} + +/*--------------------------------------------------------------------------- + * Driver entrypoints referenced from above + *--------------------------------------------------------------------------*/ + +static int scc_open (struct tty_struct * tty, struct file * filp) +{ + int line = MINOR(tty->device) - SCC_MINOR_BASE; + int retval; + struct scc_port *port = &scc_ports[line]; + + if ( line >= 2 ) + return -ENXIO; + + tty->driver_data = port; + port->gs.tty = tty; + port->gs.count++; + retval = gs_init_port(&port->gs); + if (retval) { + port->gs.count--; + return retval; + } + port->gs.flags |= GS_ACTIVE; + if (port->gs.count == 1) { + MOD_INC_USE_COUNT; + } + retval = gs_block_til_ready(port, filp); + + if (retval) { + MOD_DEC_USE_COUNT; + port->gs.count--; + return retval; + } + + if ((port->gs.count == 1) && (port->gs.flags & ASYNC_SPLIT_TERMIOS)) { + if (tty->driver.subtype == SERIAL_TYPE_NORMAL) + *tty->termios = port->gs.normal_termios; + else + *tty->termios = port->gs.callout_termios; + scc_set_real_termios (port); +// scc_disable_tx_interrupts(ptr); + } + + port->gs.session = current->session; + port->gs.pgrp = current->pgrp; + + scc_enable_rx_interrupts(port); + + return 0; +} + +static void scc_throttle (struct tty_struct * tty) +{ +/* + struct scc_port *port = (struct scc_port *)tty->driver_data; + unsigned long flags; + SCC_ACCESS_INIT(port); + + if (tty->termios->c_cflag & CRTSCTS) { + save_flags(flags); + cli(); + SCCmod(TX_CTRL_REG, ~TCR_RTS, 0); + restore_flags(flags); + } + if (I_IXOFF(tty)) + scc_send_xchar(tty, STOP_CHAR(tty)); +*/ +} + +static void scc_unthrottle (struct tty_struct * tty) +{ +} + +static int scc_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg) +{ + return -ENOIOCTLCMD; +} + +static void scc_break_ctl(struct tty_struct *tty, int break_state) +{ +} + +/*--------------------------------------------------------------------------- + * Interface from generic_serial.c back here + *--------------------------------------------------------------------------*/ + +static struct real_driver scc_real_driver = { + scc_disable_tx_interrupts, + scc_enable_tx_interrupts, + scc_disable_rx_interrupts, + scc_enable_rx_interrupts, + scc_get_CD, + scc_shutdown_port, + scc_set_real_termios, + scc_chars_in_buffer, + scc_close, + scc_hungup, + NULL +}; + + +int __devinit scc_register_chip(struct scc_port *port) +{ + port->gs.callout_termios = tty_std_termios; + port->gs.normal_termios = tty_std_termios; + port->gs.magic = SCC_MAGIC; + port->gs.close_delay = HZ/2; + port->gs.closing_wait = 30 * HZ; + port->gs.rd = &scc_real_driver; +#ifdef NEW_WRITE_LOCKING + port->gs.port_write_sem = MUTEX; +#endif + + init_waitqueue_head(&port->gs.open_wait); + init_waitqueue_head(&port->gs.close_wait); + + return 0; +} + +static int __devinit scc_chip_init(unsigned long base, int irq_rxa, int irq_txa, + int irq_rxb, int irq_txb) +{ + int err = 0; + unsigned long flags; + + scc_ports[0].base = base; + scc_ports[0].scale = 4; + scc_ports[0].irq_rx = irq_rxa; + scc_ports[0].irq_tx = irq_txa; + scc_ports[0].channel = 0; + + scc_ports[1].base = base; + scc_ports[1].scale = 4; + scc_ports[1].irq_rx = irq_rxb; + scc_ports[1].irq_tx = irq_txb; + scc_ports[1].channel = 1; + + save_flags(flags); + cli(); + + err = request_irq(irq_rxa, scc_rx_int, SA_INTERRUPT, "SCC-A RX", &scc_ports[0]); + if ( err < 0 ) + return err; + + err = request_irq(irq_txa, scc_tx_int, SA_INTERRUPT, "SCC-A TX", &scc_ports[0]); + if ( err < 0 ) + { + free_irq(irq_rxa, &scc_ports[0]); + return err; + } + + err = request_irq(irq_rxb, scc_rx_int, SA_INTERRUPT, "SCC-B RX", &scc_ports[1]); + if ( err < 0 ) + { + free_irq(irq_rxa, &scc_ports[0]); + free_irq(irq_txa, &scc_ports[0]); + return err; + } + + err = request_irq(irq_txb, scc_tx_int, SA_INTERRUPT, "SCC-B TX", &scc_ports[1]); + if ( err < 0 ) + { + free_irq(irq_rxa, &scc_ports[0]); + free_irq(irq_txa, &scc_ports[0]); + free_irq(irq_rxb, &scc_ports[1]); + return err; + } + + disable_irq(irq_rxa); + disable_irq(irq_txa); + disable_irq(irq_rxb); + disable_irq(irq_txb); + + restore_flags(flags); + + scc_register_chip(&scc_ports[0]); + scc_register_chip(&scc_ports[1]); + + return 0; +} + +int __devinit tekscc_init(void) +{ + int err = -ENXIO; + +#ifdef CONFIG_TEKXP + err = scc_chip_init(TEK_UART_BASE, TEK_IRQ_RXRDY_A, TEK_IRQ_TXRDY_A, + TEK_IRQ_RXRDY_B, TEK_IRQ_TXRDY_B); +#endif + if ( err < 0 ) + return err; + + memset(&scc_driver, 0, sizeof(scc_driver)); + scc_driver.magic = TTY_DRIVER_MAGIC; + scc_driver.driver_name = "scc2692"; +#ifdef CONFIG_DEVFS_FS + scc_driver.name = "tts/%d"; +#else + scc_driver.name = "ttyS"; +#endif + scc_driver.major = TTY_MAJOR; + scc_driver.minor_start = SCC_MINOR_BASE; + scc_driver.num = 2; + scc_driver.type = TTY_DRIVER_TYPE_SERIAL; + scc_driver.subtype = SERIAL_TYPE_NORMAL; + scc_driver.init_termios = tty_std_termios; + scc_driver.init_termios.c_cflag = B9600 | PARENB | CSTOPB | CS7 | CREAD | HUPCL | CLOCAL; + scc_driver.flags = TTY_DRIVER_REAL_RAW; + scc_driver.refcount = &scc_refcount; + scc_driver.table = scc_table; + scc_driver.termios = scc_termios; + scc_driver.termios_locked = scc_termios_locked; + scc_driver.open = scc_open; + scc_driver.close = gs_close; + scc_driver.write = gs_write; + scc_driver.put_char = gs_put_char; + scc_driver.flush_chars = gs_flush_chars; + scc_driver.write_room = gs_write_room; + scc_driver.chars_in_buffer = gs_chars_in_buffer; + scc_driver.flush_buffer = gs_flush_buffer; + scc_driver.ioctl = scc_ioctl; + scc_driver.throttle = scc_throttle; + scc_driver.unthrottle = scc_unthrottle; + scc_driver.set_termios = gs_set_termios; + scc_driver.stop = gs_stop; + scc_driver.start = gs_start; + scc_driver.hangup = gs_hangup; + scc_driver.break_ctl = scc_break_ctl; + + scc_callout_driver = scc_driver; +#ifdef CONFIG_DEVFS_FS + scc_callout_driver.driver_name = "cua/%d"; +#else + scc_callout_driver.driver_name = "cua"; +#endif + scc_callout_driver.major = TTYAUX_MAJOR; + scc_callout_driver.subtype = SERIAL_TYPE_CALLOUT; + + if ((err = tty_register_driver(&scc_driver))) { + printk(KERN_ERR "scc2692: Couldn't register scc driver, error = %d\n", err); + return -EBUSY; + } + if ((err = tty_register_driver(&scc_callout_driver))) { + printk(KERN_ERR "scc2692: Couldn't register scc callout driver, error = %d\n", err); + return -EBUSY; + } + + return 0; +} + +static void __devexit tekscc_exit(void) +{ + struct scc_port *port = &scc_ports[0]; + scc_disable_tx_interrupts(port); + scc_disable_rx_interrupts(port); + free_irq(port->irq_rx, port); + free_irq(port->irq_tx, port); + + port = &scc_ports[1]; + scc_disable_tx_interrupts(port); + scc_disable_rx_interrupts(port); + free_irq(port->irq_rx, port); + free_irq(port->irq_tx, port); + + if ( tty_unregister_driver(&scc_driver) ) + printk(KERN_ERR "Could not unregister SCC2692 serial driver\n"); + if ( tty_unregister_driver(&scc_callout_driver) ) + printk(KERN_ERR "Could not unregister SCC2692 callout driver\n"); +} + +module_init(tekscc_init); +module_exit(tekscc_exit); +MODULE_LICENSE("GPL"); + +#ifdef CONFIG_SERIAL_CONSOLE + +/*--------------------------------------------------------------------------- + * Serial console stuff... + *--------------------------------------------------------------------------*/ + +#define scc_delay() do { __asm__ __volatile__ (" nop; nop"); } while (0) + +static void scc_ch_write (char ch) +{ + tek_uart_putchar(0, ch, 1); +} + +static void scc_console_write (struct console *co, const char *str, unsigned count) +{ + unsigned long flags; + + save_flags(flags); + cli(); + + while (count--) + { + if (*str == '\n') + scc_ch_write ('\r'); + scc_ch_write (*str++); + } + restore_flags(flags); +} + +static kdev_t scc_console_device(struct console *c) +{ + return MKDEV(TTY_MAJOR, SCC_MINOR_BASE + c->index); +} + + +static int __devinit scc_console_setup(struct console *co, char *options) +{ + return 0; +} + +static struct console sercons = { + name: "ttyS", + write: scc_console_write, + device: scc_console_device, + setup: scc_console_setup, + flags: CON_PRINTBUFFER, + index: -1, +}; + + +void __init tekscc_console_init(void) +{ + register_console(&sercons); +} + +#endif + diff -Naur linux-2.4.26/drivers/char/tty_io.c linux-2.4.26-m68k/drivers/char/tty_io.c --- linux-2.4.26/drivers/char/tty_io.c 2004-04-14 23:05:29.000000000 +1000 +++ linux-2.4.26-m68k/drivers/char/tty_io.c 2004-04-15 06:42:20.000000000 +1000 @@ -138,7 +138,9 @@ unsigned int cmd, unsigned long arg); static int tty_fasync(int fd, struct file * filp, int on); extern int vme_scc_init (void); +extern int tekscc_init (void); extern long vme_scc_console_init(void); +extern long tekscc_console_init(void); extern int serial167_init(void); extern long serial167_console_init(void); extern void console_8xx_init(void); @@ -2269,6 +2271,9 @@ #if defined(CONFIG_SERIAL167) serial167_console_init(); #endif +#if defined(CONFIG_SCC2692) + tekscc_console_init(); +#endif #if defined(CONFIG_SH_SCI) sci_console_init(); #endif @@ -2408,6 +2413,9 @@ #if defined(CONFIG_MVME162_SCC) || defined(CONFIG_BVME6000_SCC) || defined(CONFIG_MVME147_SCC) vme_scc_init(); #endif +#ifdef CONFIG_SCC2692 + tekscc_init(); +#endif #ifdef CONFIG_SERIAL_TX3912 tx3912_rs_init(); #endif diff -Naur linux-2.4.26/drivers/ide/ide-probe.c linux-2.4.26-m68k/drivers/ide/ide-probe.c --- linux-2.4.26/drivers/ide/ide-probe.c 2004-04-14 23:05:29.000000000 +1000 +++ linux-2.4.26-m68k/drivers/ide/ide-probe.c 2004-04-15 06:42:24.000000000 +1000 @@ -350,6 +350,7 @@ rc = 0; /* clear drive IRQ */ (void) hwif->INB(IDE_STATUS_REG); + (void) ide_ack_intr(hwif); local_irq_restore(flags); } else { /* drive refused ID */ @@ -503,6 +504,7 @@ drive->name, hwif->INB(IDE_STATUS_REG)); /* ensure drive irq is clear */ (void) hwif->INB(IDE_STATUS_REG); + (void) ide_ack_intr(hwif); } else { /* not present or maybe ATAPI */ rc = 3; @@ -513,6 +515,7 @@ ide_delay_50ms(); /* ensure drive irq is clear */ (void) hwif->INB(IDE_STATUS_REG); + (void) ide_ack_intr(hwif); } return rc; } diff -Naur linux-2.4.26/drivers/macintosh/adb.c linux-2.4.26-m68k/drivers/macintosh/adb.c --- linux-2.4.26/drivers/macintosh/adb.c 2003-08-25 21:44:42.000000000 +1000 +++ linux-2.4.26-m68k/drivers/macintosh/adb.c 2003-10-21 07:14:22.000000000 +1000 @@ -35,6 +35,7 @@ #include #include #include + #include #ifdef CONFIG_PPC #include @@ -380,14 +381,14 @@ if (adb_controller == NULL) return -ENXIO; - + if (adb_controller->autopoll) adb_controller->autopoll(0); nret = notifier_call_chain(&adb_client_list, ADB_MSG_PRE_RESET, NULL); if (nret & NOTIFY_STOP_MASK) { if (adb_controller->autopoll) - adb_controller->autopoll(devs); + adb_controller->autopoll(0); return -EBUSY; } @@ -467,13 +468,15 @@ use_sreq = 1; } else use_sreq = 0; - req->nbytes = nbytes+1; + i = (flags & ADBREQ_RAW) ? 0 : 1; + req->nbytes = nbytes+i; req->done = done; req->reply_expected = flags & ADBREQ_REPLY; req->data[0] = ADB_PACKET; va_start(list, nbytes); - for (i = 0; i < nbytes; ++i) - req->data[i+1] = va_arg(list, int); + while (i < req->nbytes) { + req->data[i++] = va_arg(list, int); + } va_end(list); if (flags & ADBREQ_NOSEND) diff -Naur linux-2.4.26/drivers/mtd/maps/Config.in linux-2.4.26-m68k/drivers/mtd/maps/Config.in --- linux-2.4.26/drivers/mtd/maps/Config.in 2003-06-14 00:51:34.000000000 +1000 +++ linux-2.4.26-m68k/drivers/mtd/maps/Config.in 2003-07-22 07:32:35.000000000 +1000 @@ -96,6 +96,10 @@ dep_tristate ' Generic uClinux RAM/ROM filesystem support' CONFIG_MTD_UCLINUX $CONFIG_MTD_PARTITIONS fi +if [ "$CONFIG_TEKXP" = "y" ]; then + dep_tristate ' TekXpress optional ROM support' CONFIG_MTD_TEKXP_OPTROM $CONFIG_MTD_ROM +fi + # This needs CFI or JEDEC, depending on the cards found. dep_tristate ' PCI MTD driver' CONFIG_MTD_PCI $CONFIG_MTD $CONFIG_PCI dep_tristate ' PCMCIA MTD driver' CONFIG_MTD_PCMCIA $CONFIG_MTD $CONFIG_PCMCIA diff -Naur linux-2.4.26/drivers/mtd/maps/Makefile linux-2.4.26-m68k/drivers/mtd/maps/Makefile --- linux-2.4.26/drivers/mtd/maps/Makefile 2003-06-14 00:51:34.000000000 +1000 +++ linux-2.4.26-m68k/drivers/mtd/maps/Makefile 2003-07-22 07:32:35.000000000 +1000 @@ -22,6 +22,7 @@ obj-$(CONFIG_MTD_L440GX) += l440gx.o obj-$(CONFIG_MTD_AMD76XROM) += amd76xrom.o obj-$(CONFIG_MTD_ICH2ROM) += ich2rom.o +obj-$(CONFIG_MTD_TEKXP_OPTROM) += tekxp_optrom.o obj-$(CONFIG_MTD_TSUNAMI) += tsunami_flash.o obj-$(CONFIG_MTD_MBX860) += mbx860.o obj-$(CONFIG_MTD_NORA) += nora.o diff -Naur linux-2.4.26/drivers/mtd/maps/tekxp_optrom.c linux-2.4.26-m68k/drivers/mtd/maps/tekxp_optrom.c --- linux-2.4.26/drivers/mtd/maps/tekxp_optrom.c 1970-01-01 10:00:00.000000000 +1000 +++ linux-2.4.26-m68k/drivers/mtd/maps/tekxp_optrom.c 2003-07-22 07:32:35.000000000 +1000 @@ -0,0 +1,177 @@ +#include +#include +#include +#include +#include +#include +#include + +/* + * Maximum number of ROMS supported by this drivers. + * + * There will be definitely be no more, since the address space for them + * is restricted to what those 16 may span. + */ +#define MAX_NUM_OPTROM 16 + +/* + * Virtual address of the address space potentially used by the ROMs. + */ +static unsigned long possible_rom_memory; + +/* + * Structure holding just the information needed for the MTD framework. + * The driver itself needs no further information about a single ROM. + */ +typedef struct { + struct map_info map; + struct mtd_info *mtd; +} optrom_desc_t; + +static int num_optrom; +static optrom_desc_t optrom_desc[MAX_NUM_OPTROM]; + +/* + * Check if a ROM is present and determinate its size. + */ +static unsigned int __init detect_optrom_size(unsigned long start_address) +{ + unsigned long original = *(unsigned long *)start_address; + + /* + * We try to write into the ROM. It will not fault on us. + */ + *(volatile unsigned long *)start_address = ~original; + + /* + * If the write did not change there is a ROM or nothing. + */ + if ( *(volatile unsigned long *)start_address == original ) + { + /* + * But the Nothing will fail to report a correct size. + * + * Yes, the size is stored at a given position within the + * ROM. So if someone did create ROMs on his own behalf + * not following the "specification" this driver will + * fail to detect them. + * + * Do NOT fix this! It is intended behaviour since the + * future goal of this driver is to present the filesystem + * stored in the original ROMs. + */ + unsigned short size = *(unsigned short *)(start_address + 6); + if ( size == 0x80 || size == 0x100 || size == 0x200 || size == 0x400 ) + return size * 1024; + } + + /* + * If we hit something else try to restore the original content. + */ + *(unsigned long *)start_address = original; + + return 0; +} + +/* + * Just the obvious way to copy memory around. + */ +static void optrom_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) +{ + memcpy(to, (char *)map->map_priv_1 + from, len); +} + +/* + * We can not write into the ROMs. + */ +static void optrom_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) +{ +} + +/* + * Initialization + */ +static int __init init_optrom(void) +{ + int i; + + /* + * Get all memory mapped that may hold a ROM. This might have to + * be switched to a less gready sheme if causing any problems. + */ + possible_rom_memory = (unsigned long)ioremap_nocache(0x1000000, MAX_NUM_OPTROM * 0x100000); + if ( !possible_rom_memory ) + { + printk(KERN_WARNING "Could not map optroms into the virtual memory space\n"); + return -ENXIO; + } + + /* + * Search through the complete address space for any ROM. + * If any ROM is found register it with the MTD framework. + */ + for ( i=0; i 0 ) + { + optrom_desc_t *desc = &optrom_desc[num_optrom]; + + printk(KERN_INFO "Found optional ROM of size %u at %08x\n", size, 0x1000000 + i * 0x100000); + + desc->map.name = "TekXpress optional ROM"; + desc->map.size = size; + desc->map.map_priv_1 = possible_rom_memory + i * 0x100000; + desc->map.copy_from = optrom_copy_from; + desc->map.copy_to = optrom_copy_to; + + desc->mtd = do_map_probe("map_rom", &desc->map); + if ( !desc->mtd ) + { + printk(KERN_ERR "Could not allocate MTD structure\n"); + continue; + } + + desc->mtd->module = THIS_MODULE; + add_mtd_device(desc->mtd); + + num_optrom++; + } + + } + + if ( num_optrom <= 0 ) + { + iounmap((void *)possible_rom_memory); + printk(KERN_WARNING "No optional rom found\n"); + return -ENXIO; + } + + return 0; +} + +/* + * Unregister all ROMs found from the MTD framework. + */ +void __exit cleanup_optrom(void) +{ + while ( num_optrom-- ) + { + optrom_desc_t *desc = &optrom_desc[num_optrom]; + + del_mtd_device(desc->mtd); + map_destroy(desc->mtd); + } + + iounmap((void*)possible_rom_memory); +} + + + +module_init(init_optrom); +module_exit(cleanup_optrom); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Michael Mueller "); +MODULE_DESCRIPTION("MTD map driver for optional ROM of the TekXpress XP2x X-Terminals"); + diff -Naur linux-2.4.26/drivers/net/Makefile linux-2.4.26-m68k/drivers/net/Makefile --- linux-2.4.26/drivers/net/Makefile 2004-04-14 23:05:30.000000000 +1000 +++ linux-2.4.26-m68k/drivers/net/Makefile 2004-04-15 06:42:31.000000000 +1000 @@ -95,6 +95,7 @@ obj-$(CONFIG_FEALNX) += fealnx.o mii.o obj-$(CONFIG_TC35815) += tc35815.o obj-$(CONFIG_TIGON3) += tg3.o +obj-$(CONFIG_TEKSONIC) += teksonic.o ifeq ($(CONFIG_E100),y) obj-y += e100/e100.o diff -Naur linux-2.4.26/drivers/net/Space.c linux-2.4.26-m68k/drivers/net/Space.c --- linux-2.4.26/drivers/net/Space.c 2004-02-19 00:36:31.000000000 +1100 +++ linux-2.4.26-m68k/drivers/net/Space.c 2004-02-19 09:16:53.000000000 +1100 @@ -101,6 +101,7 @@ extern int mac8390_probe(struct net_device *dev); extern int mac89x0_probe(struct net_device *dev); extern int mc32_probe(struct net_device *dev); +extern int teksonic_probe(struct net_device *dev); /* Detachable devices ("pocket adaptors") */ extern int de600_probe(struct net_device *); @@ -326,6 +327,9 @@ }; static struct devprobe m68k_probes[] __initdata = { +#ifdef CONFIG_TEKSONIC + {teksonic_probe, 0}, +#endif #ifdef CONFIG_ATARILANCE /* Lance-based Atari ethernet boards */ {atarilance_probe, 0}, #endif diff -Naur linux-2.4.26/drivers/net/a2065.c linux-2.4.26-m68k/drivers/net/a2065.c --- linux-2.4.26/drivers/net/a2065.c 2003-06-14 00:51:34.000000000 +1000 +++ linux-2.4.26-m68k/drivers/net/a2065.c 2004-04-16 21:37:49.000000000 +1000 @@ -284,6 +284,7 @@ struct sk_buff *skb = 0; /* XXX shut up gcc warnings */ #ifdef TEST_HITS + int i; printk ("["); for (i = 0; i < RX_RING_SIZE; i++) { if (i == lp->rx_new) diff -Naur linux-2.4.26/drivers/net/macsonic.c linux-2.4.26-m68k/drivers/net/macsonic.c --- linux-2.4.26/drivers/net/macsonic.c 2003-08-25 21:44:42.000000000 +1000 +++ linux-2.4.26-m68k/drivers/net/macsonic.c 2004-06-20 21:17:28.000000000 +1000 @@ -199,6 +199,7 @@ if ((lp->rba = (char *) kmalloc(SONIC_NUM_RRS * SONIC_RBSIZE, GFP_KERNEL | GFP_DMA)) == NULL) { printk(KERN_ERR "%s: couldn't allocate receive buffers\n", dev->name); + kfree(lp); return -ENOMEM; } @@ -635,19 +636,14 @@ } #ifdef MODULE -static char namespace[16] = ""; static struct net_device dev_macsonic; MODULE_PARM(sonic_debug, "i"); MODULE_PARM_DESC(sonic_debug, "macsonic debug level (1-4)"); -MODULE_LICENSE("GPL"); - -EXPORT_NO_SYMBOLS; int init_module(void) { - dev_macsonic.name = namespace; dev_macsonic.init = macsonic_probe; if (register_netdev(&dev_macsonic) != 0) { diff -Naur linux-2.4.26/drivers/net/teksonic.c linux-2.4.26-m68k/drivers/net/teksonic.c --- linux-2.4.26/drivers/net/teksonic.c 1970-01-01 10:00:00.000000000 +1000 +++ linux-2.4.26-m68k/drivers/net/teksonic.c 2003-07-22 07:28:08.000000000 +1000 @@ -0,0 +1,310 @@ +/* + * linux/drivers/net/teksonic.c + * + * (C) 2003 Michael Mueller + * + * based on the macsonic driver: + * + * (C) 1998 Alan Cox + * + * Debugging Andreas Ehliar, Michael Schmitz + * + * Based on code + * (C) 1996 by Thomas Bogendoerfer (tsbogend@bigbug.franken.de) + * + * This driver is based on work from Andreas Busse, but most of + * the code is rewritten. + * + * (C) 1995 by Andreas Busse (andy@waldorf-gmbh.de) + * + */ + +#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 + +/* + * All registers are located at addresses dividable by 4. + */ + +#define SREGS_PAD(n) u16 n; + +/* + * This is a hack to get the endianness stuff done correctly. + */ + +#define CONFIG_MACSONIC + +/* + * Generic Sonic definitions + */ +#include "sonic.h" + +#ifdef DEBUG + +#define SONIC_READ(reg) _SONIC_READ(base_addr, reg) +#define SONIC_WRITE(reg,val) do { _SONIC_WRITE(base_addr, reg, val); } while(0) + +static inline unsigned short _SONIC_READ(unsigned long base_addr, int reg) +{ + unsigned short val = *((volatile unsigned long*)(base_addr + 4*(reg))) & 0xffff; + printk("sonic_read(%08x) = %02x\n", base_addr + 4*(reg), val); + return val; +} + +static inline void _SONIC_WRITE(unsigned long base_addr, int reg, unsigned short val) +{ + printk("sonic_write(%08x,%04x)\n", base_addr + 4*(reg), val); + *((volatile unsigned long*)(base_addr + 4*(reg))) = (val) & 0xffff; +} + +static inline unsigned short sonic_read(struct net_device *dev, int reg) +{ + unsigned short val = *((volatile unsigned long*)(dev->base_addr + 4*(reg))) & 0xffff; + printk("sonic_read(%08x) = %02x\n", dev->base_addr + 4*(reg), val); + return val; +} + +static inline void sonic_write(struct net_device *dev, int reg, unsigned short val) +{ + printk("sonic_write(%08x,%04x)\n", dev->base_addr + 4*(reg), val); + *((volatile unsigned long*)(dev->base_addr + 4*(reg))) = (val) & 0xffff; +} + +#else + +#define SONIC_READ(reg) ((unsigned short)(*(volatile unsigned long *)((base_addr) + 4*(reg))) & 0xffff) + +#define SONIC_WRITE(reg, val) do { *(volatile unsigned long*)((base_addr) + 4*(reg)) = (val)& 0xffff; } while (0) + +#define sonic_read(dev,reg) ((unsigned short)(*(volatile unsigned long *)((dev)->base_addr + 4*(reg))) & 0xffff) + +#define sonic_write(dev, reg, val) do { *(volatile unsigned long*)((dev)->base_addr + 4*(reg)) = (val)& 0xffff; } while (0) + +#endif + +static int sonic_debug = 0; +static int sonic_version_printed; + +static int reg_offset; + +int teksonic_init(struct net_device* dev) +{ + int i,j; + struct sonic_local* lp_alloc[20]; + struct sonic_local* lp; + + /* Allocate the entire chunk of memory for the descriptors. + Note that this cannot cross a 64K boundary. */ + for (i = 0; i < 20; i++) { + unsigned long desc_base, desc_top, desc_top2; + if((lp_alloc[i] = kmalloc(sizeof(struct sonic_local), GFP_KERNEL)) == NULL) { + printk(KERN_ERR "%s: couldn't allocate descriptor buffers\n", dev->name); + return -ENOMEM; + } + desc_base = (unsigned long)virt_to_phys(lp_alloc[i]); + desc_top = desc_base + sizeof(struct sonic_local); + desc_top2 = (unsigned long)virt_to_phys(lp_alloc[i] + 1); + + if ( (desc_top == desc_top2) && (desc_top & 0xffff) >= (desc_base & 0xffff)) + break; + + /* Hmm. try again (FIXME: does this actually work?) */ + /* Note: It did not work when freeing the memory allocated + previously since it got the same memory again. */ +/* kfree(lp); */ + printk(KERN_DEBUG + "%s: didn't get continguous chunk [%08lx - %08lx], trying again\n", + dev->name, desc_base, desc_top); + + } + + /* Deallocate what was allocated just to get the alignment done. */ + for ( j = i-1; j >= 0; j-- ) + kfree(lp_alloc[j]); + + if (i==20) { + /* Note: Do not free dev->priv, it is deallocated later! */ + printk(KERN_ERR "%s: tried 20 times to allocate descriptor buffers, giving up.\n", + dev->name); + return -ENOMEM; + } + + dev->priv = lp = lp_alloc[i]; + + memset(lp, 0, sizeof(struct sonic_local)); + + lp->cda_laddr = virt_to_phys(&(lp->cda)); + lp->tda_laddr = virt_to_phys(lp->tda); + lp->rra_laddr = virt_to_phys(lp->rra); + lp->rda_laddr = virt_to_phys(lp->rda); + + /* FIXME, maybe we should use skbs */ + if ((lp->rba = (char *)kmalloc(SONIC_NUM_RRS * SONIC_RBSIZE, GFP_KERNEL)) == NULL) { + printk(KERN_ERR "%s: couldn't allocate receive buffers\n", dev->name); + return -ENOMEM; + } + lp->rba_laddr = virt_to_phys(lp->rba); + +#if 0 + { + int rs, ds; + + /* almost always 12*4096, but let's not take chances */ + rs = ((SONIC_NUM_RRS * SONIC_RBSIZE + 4095) / 4096) * 4096; + /* almost always under a page, but let's not take chances */ + ds = ((sizeof(struct sonic_local) + 4095) / 4096) * 4096; + kernel_set_cachemode(lp->rba, rs, IOMAP_NOCACHE_SER); + kernel_set_cachemode(lp, ds, IOMAP_NOCACHE_SER); + } +#endif + + +#if 0 + flush_cache_all(); +#endif + + dev->open = sonic_open; + dev->stop = sonic_close; + dev->hard_start_xmit = sonic_send_packet; + dev->get_stats = sonic_get_stats; + dev->set_multicast_list = &sonic_multicast_list; + + /* + * clear tally counter + */ + sonic_write(dev, SONIC_CRCT, 0xffff); + sonic_write(dev, SONIC_FAET, 0xffff); + sonic_write(dev, SONIC_MPT, 0xffff); + + /* Fill in the fields of the device structure with ethernet values. */ + ether_setup(dev); + return 0; +} + +int teksonic_ethernet_addr(struct net_device* dev) +{ + int i; + + /* On NuBus boards we can sometimes look in the ROM resources. + No such luck for comm-slot/onboard. */ + for(i = 0; i < 6; i++) + dev->dev_addr[i] = nvram_readb(NVRAM_SONIC_MAC+i); + + return 0; +} + +int teksonic_probe(struct net_device* dev) +{ + /* Bwahahaha */ + static int once_is_more_than_enough; + int i; + int dma_bitmode; + + if (once_is_more_than_enough) + return -ENODEV; + once_is_more_than_enough = 1; + + if (dev) { + dev = init_etherdev(dev, sizeof(struct sonic_local)); + if (!dev) + return -ENOMEM; + } else { + dev = init_etherdev(NULL, sizeof(struct sonic_local)); + } + if (dev->priv != NULL) { + kfree(dev->priv); + dev->priv = NULL; + } + + if (dev == NULL) + return -ENOMEM; + + /* Danger! My arms are flailing wildly! You *must* set this + before using sonic_read() */ + + dev->base_addr = 0xFFC00000; // FIXME: This does rely on transparent translation + dev->irq = IRQ6; + + if (!sonic_version_printed) { + printk(KERN_INFO "%s", version); + sonic_version_printed = 1; + } + printk(KERN_INFO "%s: SONIC at 0x%08lx\n", + dev->name, dev->base_addr); + + reg_offset = 0; + dma_bitmode = 1; + + /* Software reset, then initialize control registers. */ + sonic_write(dev, SONIC_CMD, SONIC_CR_RST); + + sonic_write(dev, SONIC_DCR, SONIC_DCR_BMS | + SONIC_DCR_RFT1 | SONIC_DCR_TFT0 | SONIC_DCR_EXBUS | + (dma_bitmode ? SONIC_DCR_DW : 0)); +#if 0 + sonic_write(dev, SONIC_DCR, 0x3F); +#endif + + /* This *must* be written back to in order to restore the + extended programmable output bits */ + sonic_write(dev, SONIC_DCR2, 0); + + sonic_write(dev, SONIC_CMD, 0); + + /* Clear *and* disable interrupts to be on the safe side */ + sonic_write(dev, SONIC_ISR,0x7fff); + sonic_write(dev, SONIC_IMR,0); + + /* Now look for the MAC address. */ + if (teksonic_ethernet_addr(dev) != 0) + return -ENODEV; + + printk(KERN_INFO "MAC "); + for (i = 0; i < 6; i++) { + printk("%2.2x", dev->dev_addr[i]); + if (i < 5) + printk(":"); + } + + printk(" IRQ %d\n", dev->irq); + + /* Shared init code */ + return teksonic_init(dev); +} + + +#define vdma_alloc(foo, bar) ((u32)(foo)) +#define vdma_free(baz) +#define sonic_chiptomem(bat) (phys_to_virt(bat)) +#define PHYSADDR(quux) (virt_to_phys((void*)(quux))) + +#define sonic_request_irq request_irq +#define sonic_free_irq free_irq + +#include "sonic.c" + diff -Naur linux-2.4.26/drivers/sbus/char/sunkbd.c linux-2.4.26-m68k/drivers/sbus/char/sunkbd.c --- linux-2.4.26/drivers/sbus/char/sunkbd.c 2002-08-03 10:39:44.000000000 +1000 +++ linux-2.4.26-m68k/drivers/sbus/char/sunkbd.c 2002-08-06 00:37:03.000000000 +1000 @@ -761,6 +761,7 @@ static void boot_it(void) { +#if !defined(CONFIG_SUN3) && !defined(CONFIG_SUN3X) extern int obp_system_intr(void); if (!obp_system_intr()) @@ -768,6 +769,7 @@ /* sigh.. attempt to prevent multiple entry */ last_keycode=1; rep = 0; +#endif } static void compose(void) @@ -1232,7 +1234,7 @@ int __init sun_kbd_init(void) { - int i, opt_node; + int i; struct kbd_struct kbd0; extern struct tty_driver console_driver; @@ -1250,18 +1252,22 @@ kd_mksound = sunkbd_kd_mksound; +#ifndef CONFIG_SUN3X_ZS /* XXX Check keyboard-click? property in 'options' PROM node XXX */ if(sparc_cpu_model != sun4) { - opt_node = prom_getchild(prom_root_node); + int opt_node = prom_getchild(prom_root_node); opt_node = prom_searchsiblings(opt_node, "options"); i = prom_getintdefault(opt_node, "keyboard-click?", -1); if(i != -1) sunkbd_clickp = 1; else sunkbd_clickp = 0; - } else { + } else +#else + { sunkbd_clickp = 0; } +#endif keyboard_tasklet.func = sun_kbd_bh; diff -Naur linux-2.4.26/drivers/sbus/char/sunserial.c linux-2.4.26-m68k/drivers/sbus/char/sunserial.c --- linux-2.4.26/drivers/sbus/char/sunserial.c 2002-08-03 10:39:44.000000000 +1000 +++ linux-2.4.26-m68k/drivers/sbus/char/sunserial.c 2002-08-03 22:45:22.000000000 +1000 @@ -10,6 +10,13 @@ #include #include #include + +#ifdef CONFIG_SUN3 +#include +#include +#include +#endif + #include #include #include @@ -228,6 +235,7 @@ void sunserial_console_termios(struct console *con) { +#ifndef CONFIG_SUN3X_ZS char mode[16], buf[16], *s; char *mode_prop = "ttyX-mode"; char *cd_prop = "ttyX-ignore-cd"; @@ -331,6 +339,9 @@ } con->cflag = cflag; +#else /* CONFIG_SUN3 */ + con->cflag = CREAD | HUPCL | CLOCAL | B9600 | CS8; +#endif /* CONFIG_SUN3 */ } void @@ -452,6 +463,9 @@ } #endif +#ifndef CONFIG_SUN3X_ZS prom_printf("No serial devices found, bailing out.\n"); prom_halt(); +#endif + } diff -Naur linux-2.4.26/drivers/sbus/char/zs.c linux-2.4.26-m68k/drivers/sbus/char/zs.c --- linux-2.4.26/drivers/sbus/char/zs.c 2002-08-03 10:39:44.000000000 +1000 +++ linux-2.4.26-m68k/drivers/sbus/char/zs.c 2002-08-06 00:37:04.000000000 +1000 @@ -11,6 +11,8 @@ * /proc/tty/driver/serial now exists and is readable. * Alex Buell , 2001-12-23 * + * Tweaks for sun3x by Oliver Jowett + * */ #include @@ -39,23 +41,39 @@ #include #include #include + +#include +#ifndef CONFIG_SUN3X_ZS #include #include #include -#include #ifdef __sparc_v9__ #include #endif #ifdef CONFIG_PCI #include #endif +#else /* CONFIG_SUN3X_ZS */ +#include +#ifndef CONFIG_SUN3X +#include +#else +#include +#endif +#endif /* CONFIG_SUN3X_ZS */ #include "sunserial.h" #include "zs.h" #include "sunkbd.h" #include "sunmouse.h" +/* some sun3 boxen always use vectors */ +#ifdef CONFIG_SUN3 +#undef NV +#define NV 0 +#endif + static int num_serial = 2; /* sun4/sun4c/sun4m - Two chips on board. */ #define NUM_SERIAL num_serial #define NUM_CHANNELS (NUM_SERIAL * 2) @@ -425,6 +443,7 @@ */ void batten_down_hatches(void) { +#ifndef CONFIG_SUN3X_ZS if (!stop_a_enabled) return; /* If we are doing kadb, we call the debugger @@ -448,6 +467,13 @@ */ return; +#else /* CONFIG_SUN3X_ZS */ +#ifndef CONFIG_SUN3X + prom_reboot(""); +#else + sun3x_reboot(); +#endif +#endif /* CONFIG_SUN3X_ZS */ } @@ -550,7 +576,9 @@ * arch/sparc/kernel/sparc-stub.c to see how all this works. */ if (info->kgdb_channel && (ch =='\003')) { +#ifndef CONFIG_SUN3X_ZS breakpoint(); +#endif return; } #endif @@ -683,6 +711,23 @@ for (i = 0; i < NUM_SERIAL; i++) { unsigned char r3 = read_zsreg(info->zs_channel, 3); + /* some sun3's need the pending flags cleared */ +#ifdef CONFIG_SUN3 + unsigned char r2 = read_zsreg(info->zs_next->zs_channel, 2); + r2 &= STATUS_MASK; + if(r2 & 0x8) { + sbus_writeb(RES_H_IUS, &info->zs_channel->control); + ZSDELAY(); + ZS_WSYNC(info->zs_channel); + ZSLOG(REGCTRL, RES_H_IUS, 1); + } else { + sbus_writeb(RES_H_IUS, &info->zs_next->zs_channel->control); + ZSDELAY(); + ZS_WSYNC(info->zs_next->zs_channel); + ZSLOG(REGCTRL, RES_H_IUS, 1); + } +#endif + /* Channel A -- /dev/ttya or /dev/kbd, could be the console */ if (r3 & (CHAEXT | CHATxIP | CHARxIP)) { sbus_writeb(RES_H_IUS, &info->zs_channel->control); @@ -1964,6 +2009,88 @@ /* Finally, routines used to initialize the serial driver. */ + +#ifdef CONFIG_SUN3X_ZS + +static void show_serial_version(void) +{ + char *revision = "$Revision: 1.5 $"; + char *version, *p; + + version = strchr(revision, ' '); + p = strchr(++version, ' '); + *p = '\0'; + printk("sun3/3x Zilog8530 serial driver version %s\n", version); + *p = ' '; +} + +static struct sun_zslayout * __init + get_zs(int chip) +{ + unsigned int vaddr = 0; + unsigned long iopte; + static int irq = 0; + + if(chip < 0 || chip >= NUM_SERIAL) + panic("get_zs bogon zs chip number"); + +#ifndef CONFIG_SUN3X + /* sun3 OBIO version */ + /* Grrr, these have to be hardcoded aieee */ + switch(chip) { + case 0: + for(vaddr = 0xfe00000; vaddr < (0xfe00000 + + SUN3_PMEG_SIZE); vaddr += SUN3_PTE_SIZE) { + + iopte = sun3_get_pte(vaddr); + if(!(iopte & SUN3_PAGE_TYPE_IO)) /* this an io page? */ + continue; + + if(((iopte & SUN3_PAGE_PGNUM_MASK) << PAGE_SHIFT) == + 0x20000) { + break; + } + } + break; + case 1: + for(vaddr = 0xfe00000; vaddr < (0xfe00000 + + SUN3_PMEG_SIZE); vaddr += SUN3_PTE_SIZE) { + + iopte = sun3_get_pte(vaddr); + if(!(iopte & SUN3_PAGE_TYPE_IO)) /* this an io page? */ + continue; + + if(((iopte & SUN3_PAGE_PGNUM_MASK) << PAGE_SHIFT) == + 0) { + break; + } + } + break; + }; +#else + /* sun3x is a wee bit cleaner. :) */ + switch(chip) { + case 0: + vaddr = SUN3X_ZS2; + break; + + case 1: + vaddr = SUN3X_ZS1; + break; + } +#endif + + zs_nodes[chip] = 0; + zilog_irq = irq = 6; + + if(!vaddr) + panic("get_zs whee no serial chip mappable"); + + return (struct sun_zslayout *)(unsigned long) vaddr; +} + +#else /* !CONFIG_SUN3X_ZS */ + static void show_serial_version(void) { char *revision = "$Revision: 1.68.2.2 $"; @@ -2224,6 +2351,9 @@ return (struct sun_zslayout *)(unsigned long) vaddr[0]; } #endif + +#endif /* !CONFIG_SUN3X_ZS */ + /* This is for the auto baud rate detection in the mouse driver. */ void zs_change_mouse_baud(int newbaud) { @@ -2292,6 +2422,8 @@ int __init zs_probe(void) { +#ifndef CONFIG_SUN3X_ZS + int node; if(sparc_cpu_model == sun4) @@ -2344,6 +2476,8 @@ NUM_SERIAL = 2; no_probe: +#endif /* !CONFIG_SUN3X_ZS */ + zs_alloc_tables(); /* Fill in rs_ops struct... */ @@ -2501,6 +2635,7 @@ /* Initialize Softinfo */ zs_prepare(); +#ifndef CONFIG_SUN3X_ZS /* Grab IRQ line before poking the chips so we do * not lose any interrupts. */ @@ -2509,6 +2644,7 @@ prom_printf("Unable to attach zs intr\n"); prom_halt(); } +#endif /* !CONFIG_SUN3X_ZS */ /* Initialize Hardware */ for(channel = 0; channel < NUM_CHANNELS; channel++) { @@ -2517,6 +2653,10 @@ write_zsreg(zs_soft[channel].zs_channel, R9, FHWRES); ZSDELAY_LONG(); dummy = read_zsreg(zs_soft[channel].zs_channel, R0); +#ifdef CONFIG_SUN3 + /* program the int vector */ + write_zsreg(zs_soft[channel].zs_channel, R2, 0x18+zilog_irq); +#endif } if(channel == KEYBOARD_LINE) { @@ -2676,11 +2816,23 @@ info->normal_termios = serial_driver.init_termios; init_waitqueue_head(&info->open_wait); init_waitqueue_head(&info->close_wait); +#ifdef CONFIG_SUN3X_ZS + printk("tty%02d at 0x%04x (irq = %d)", info->line, + info->port, info->irq); +#else /* !CONFIG_SUN3X_ZS */ printk("tty%02d at 0x%04x (irq = %s)", info->line, info->port, __irq_itoa(info->irq)); +#endif /* !CONFIG_SUN3X_ZS */ printk(" is a Zilog8530\n"); } +#ifdef CONFIG_SUN3X_ZS + if (request_irq(zilog_irq, zs_interrupt, + (SA_INTERRUPT), + "Zilog8530", zs_chain)) + panic("Unable to attach zs intr\n"); +#endif /* CONFIG_SUN3X_ZS */ + restore_flags(flags); keyboard_zsinit(kbd_put_char); @@ -2881,10 +3033,15 @@ { extern int con_is_present(void); +#ifndef CONFIG_SUN3X_ZS if (con_is_present()) return 0; zs_console.index = serial_console - 1; +#else /* CONFIG_SUN3X_ZS */ + zs_console.index = 0; +#endif /* CONFIG_SUN3X_ZS */ + register_console(&zs_console); return 0; } diff -Naur linux-2.4.26/drivers/scsi/NCR53C9x.c linux-2.4.26-m68k/drivers/scsi/NCR53C9x.c --- linux-2.4.26/drivers/scsi/NCR53C9x.c 2002-11-29 10:53:14.000000000 +1100 +++ linux-2.4.26-m68k/drivers/scsi/NCR53C9x.c 2003-06-14 21:46:22.000000000 +1000 @@ -917,7 +917,7 @@ if (esp->dma_mmu_get_scsi_one) esp->dma_mmu_get_scsi_one(esp, sp); else - sp->SCp.have_data_in = (int) sp->SCp.ptr = + sp->SCp.ptr = (char *) virt_to_phys(sp->request_buffer); } else { sp->SCp.buffer = (struct scatterlist *) sp->buffer; diff -Naur linux-2.4.26/drivers/scsi/oktagon_esp.c linux-2.4.26-m68k/drivers/scsi/oktagon_esp.c --- linux-2.4.26/drivers/scsi/oktagon_esp.c 2002-08-03 10:39:44.000000000 +1000 +++ linux-2.4.26-m68k/drivers/scsi/oktagon_esp.c 2003-06-14 21:46:22.000000000 +1000 @@ -548,7 +548,7 @@ void dma_mmu_get_scsi_one(struct NCR_ESP *esp, Scsi_Cmnd *sp) { - sp->SCp.have_data_in = (int) sp->SCp.ptr = + sp->SCp.ptr = sp->request_buffer; } diff -Naur linux-2.4.26/drivers/video/Config.in linux-2.4.26-m68k/drivers/video/Config.in --- linux-2.4.26/drivers/video/Config.in 2004-02-19 00:36:31.000000000 +1100 +++ linux-2.4.26-m68k/drivers/video/Config.in 2004-02-19 09:17:54.000000000 +1100 @@ -43,6 +43,9 @@ if [ "$CONFIG_Q40" = "y" ]; then define_bool CONFIG_FB_Q40 y fi + if [ "$CONFIG_TEKXP" = "y" ]; then + define_bool CONFIG_FB_TEKXP y + fi if [ "$CONFIG_AMIGA" = "y" ]; then tristate ' Amiga native chipset support' CONFIG_FB_AMIGA if [ "$CONFIG_FB_AMIGA" != "n" ]; then @@ -107,6 +110,7 @@ bool ' Sun3 framebuffer support' CONFIG_FB_SUN3 if [ "$CONFIG_FB_SUN3" != "n" ]; then bool ' BWtwo support' CONFIG_FB_BWTWO + bool ' CGthree support' CONFIG_FB_CGTHREE bool ' CGsix (GX,TurboGX) support' CONFIG_FB_CGSIX fi fi @@ -265,7 +269,7 @@ "$CONFIG_FB_MAC" = "y" -o "$CONFIG_FB_RETINAZ3" = "y" -o \ "$CONFIG_FB_VIRGE" = "y" -o "$CONFIG_FB_VIRTUAL" = "y" -o \ "$CONFIG_FB_BWTWO" = "y" -o "$CONFIG_FB_CLGEN" = "y" -o \ - "$CONFIG_FB_TX3912" = "y" ]; then + "$CONFIG_FB_TX3912" = "y" -o "$CONFIG_FB_TEKXP" = "y" ]; then define_tristate CONFIG_FBCON_MFB y else if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_AMIGA" = "m" -o \ @@ -281,12 +285,21 @@ "$CONFIG_FB_SA1100" = "y" -o "$CONFIG_FB_VIRTUAL" = "y" -o \ "$CONFIG_FB_TX3912" = "y" ]; then define_tristate CONFIG_FBCON_CFB2 y - define_tristate CONFIG_FBCON_CFB4 y else - if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_MAC" = "m" -o \ + if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_MAC" = "m" -o \ "$CONFIG_FB_SA1100" = "m" -o "$CONFIG_FB_VIRTUAL" = "m" -o \ "$CONFIG_FB_TX3912" = "m" ]; then define_tristate CONFIG_FBCON_CFB2 m + fi + fi + if [ "$CONFIG_FB_ACORN" = "y" -o "$CONFIG_FB_MAC" = "y" -o \ + "$CONFIG_FB_SA1100" = "y" -o "$CONFIG_FB_VIRTUAL" = "y" -o \ + "$CONFIG_FB_TX3912" = "y" -o "$CONFIG_FB_TEKXP" = "y" ]; then + define_tristate CONFIG_FBCON_CFB4 y + else + if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_MAC" = "m" -o \ + "$CONFIG_FB_SA1100" = "m" -o "$CONFIG_FB_VIRTUAL" = "m" -o \ + "$CONFIG_FB_TX3912" = "m" ]; then define_tristate CONFIG_FBCON_CFB4 m fi fi @@ -312,7 +325,7 @@ "$CONFIG_FB_TX3912" = "y" -o \ "$CONFIG_FB_SIS" = "y" -o "$CONFIG_FB_NEOMAGIC" = "y" -o \ "$CONFIG_FB_STI" = "y" -o "$CONFIG_FB_HP300" = "y" -o \ - "$CONFIG_FB_INTEL" = "y" ]; then + "$CONFIG_FB_INTEL" = "y" -o "$CONFIG_FB_TEKXP" = "y" ]; then define_tristate CONFIG_FBCON_CFB8 y else if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_ATARI" = "m" -o \ diff -Naur linux-2.4.26/drivers/video/Makefile linux-2.4.26-m68k/drivers/video/Makefile --- linux-2.4.26/drivers/video/Makefile 2004-02-19 00:36:31.000000000 +1100 +++ linux-2.4.26-m68k/drivers/video/Makefile 2004-02-19 09:17:54.000000000 +1100 @@ -73,14 +73,22 @@ obj-$(CONFIG_FB_VIRGE) += virgefb.o obj-$(CONFIG_FB_G364) += g364fb.o obj-$(CONFIG_FB_FM2) += fm2fb.o -obj-$(CONFIG_FB_CREATOR) += creatorfb.o sbusfb.o -obj-$(CONFIG_FB_CGSIX) += cgsixfb.o sbusfb.o -obj-$(CONFIG_FB_BWTWO) += bwtwofb.o sbusfb.o -obj-$(CONFIG_FB_CGTHREE) += cgthreefb.o sbusfb.o -obj-$(CONFIG_FB_TCX) += tcxfb.o sbusfb.o -obj-$(CONFIG_FB_CGFOURTEEN) += cgfourteenfb.o sbusfb.o -obj-$(CONFIG_FB_P9100) += p9100fb.o sbusfb.o -obj-$(CONFIG_FB_LEO) += leofb.o sbusfb.o + +SBUSFB = +ifneq ($(CONFIG_SUN3),y) +ifneq ($(CONFIG_SUN3X),y) + SBUSFB = sbusfb.o +endif +endif + +obj-$(CONFIG_FB_CREATOR) += creatorfb.o $(SBUSFB) +obj-$(CONFIG_FB_CGSIX) += cgsixfb.o $(SBUSFB) +obj-$(CONFIG_FB_BWTWO) += bwtwofb.o $(SBUSFB) +obj-$(CONFIG_FB_CGTHREE) += cgthreefb.o $(SBUSFB) +obj-$(CONFIG_FB_TCX) += tcxfb.o $(SBUSFB) +obj-$(CONFIG_FB_CGFOURTEEN) += cgfourteenfb.o $(SBUSFB) +obj-$(CONFIG_FB_P9100) += p9100fb.o $(SBUSFB) +obj-$(CONFIG_FB_LEO) += leofb.o $(SBUSFB) obj-$(CONFIG_FB_PMAG_AA) += pmag-aa-fb.o obj-$(CONFIG_FB_PMAG_BA) += pmag-ba-fb.o obj-$(CONFIG_FB_PMAGB_B) += pmagb-b-fb.o @@ -125,7 +133,6 @@ endif obj-$(CONFIG_FB_SUN3) += sun3fb.o -obj-$(CONFIG_FB_BWTWO) += bwtwofb.o obj-$(CONFIG_FB_HGA) += hgafb.o obj-$(CONFIG_FB_SA1100) += sa1100fb.o obj-$(CONFIG_FB_VIRTUAL) += vfb.o @@ -134,6 +141,7 @@ obj-$(CONFIG_FB_E1356) += epson1356fb.o obj-$(CONFIG_FB_PVR2) += pvr2fb.o obj-$(CONFIG_FB_VOODOO1) += sstfb.o +obj-$(CONFIG_FB_TEKXP) += tek_fb.o # Generic Low Level Drivers diff -Naur linux-2.4.26/drivers/video/cgthreefb.c linux-2.4.26-m68k/drivers/video/cgthreefb.c --- linux-2.4.26/drivers/video/cgthreefb.c 2001-09-21 07:11:58.000000000 +1000 +++ linux-2.4.26-m68k/drivers/video/cgthreefb.c 2001-10-22 19:34:33.000000000 +1000 @@ -178,13 +178,16 @@ struct display *disp = &fb->disp; struct fbtype *type = &fb->type; struct sbus_dev *sdev = fb->sbdp; +#ifndef CONFIG_SUN3 unsigned long phys = sdev->reg_addrs[0].phys_addr; int cgRDI = strstr(fb->sbdp->prom_name, "cgRDI") != NULL; +#endif #ifndef FBCON_HAS_CFB8 return NULL; #endif +#ifndef CONFIG_SUN3 if (!fb->s.cg3.regs) { fb->s.cg3.regs = (struct cg3_regs *) sbus_ioremap(&sdev->resource[0], CG3_REGS_OFFSET, @@ -211,6 +214,9 @@ } } } +#else + fb->s.cg3.regs = (struct cg3_regs *)0x0fe0e000; +#endif strcpy(fb->info.modename, "CGthree"); strcpy(fix->id, "CGthree"); @@ -218,12 +224,19 @@ fix->accel = FB_ACCEL_SUN_CGTHREE; disp->scrollmode = SCROLL_YREDRAW; +#ifndef CONFIG_SUN3 if (!disp->screen_base) { disp->screen_base = (char *) sbus_ioremap(&sdev->resource[0], CG3_RAM_OFFSET, type->fb_size, "cg3 ram"); } - disp->screen_base += fix->line_length * fb->y_margin + fb->x_margin; + fb->physbase = phys; +#else + disp->screen_base = (char *)0x0fd00000; + fb->physbase = (unsigned long)0x0fd00000; +#endif + +// disp->screen_base += fix->line_length * fb->y_margin + fb->x_margin; fb->dispsw = fbcon_cfb8; fb->margins = cg3_margins; @@ -231,9 +244,9 @@ fb->blank = cg3_blank; fb->unblank = cg3_unblank; - fb->physbase = phys; fb->mmap_map = cg3_mmap_map; - + +#ifndef CONFIG_SUN3 #ifdef __sparc_v9__ sprintf(idstring, "%s at %016lx", cgRDI ? "cgRDI" : "cgthree", phys); #else @@ -279,6 +292,22 @@ sbus_writeb(p[1], regp); } } +#else + sprintf(idstring, "%s: mem %x regs %x", "cgthree", fb->physbase, fb->s.cg3.regs); + + /* kick up the sun3 -- 66hz prom mode only */ + /* this also turns off the overlay in case it's really a cg4 */ + + fb->s.cg3.regs->cmap.addr = 4; + fb->s.cg3.regs->cmap.control = 0xff; + fb->s.cg3.regs->cmap.addr = 5; + fb->s.cg3.regs->cmap.control = 0; + fb->s.cg3.regs->cmap.addr = 6; + fb->s.cg3.regs->cmap.control = 0x40; + fb->s.cg3.regs->cmap.addr = 7; + fb->s.cg3.regs->cmap.control = 0; + +#endif return idstring; } diff -Naur linux-2.4.26/drivers/video/fbcon.c linux-2.4.26-m68k/drivers/video/fbcon.c --- linux-2.4.26/drivers/video/fbcon.c 2003-08-25 21:44:42.000000000 +1000 +++ linux-2.4.26-m68k/drivers/video/fbcon.c 2003-08-26 13:13:09.000000000 +1000 @@ -2340,6 +2340,27 @@ done = 1; } #endif +#ifdef CONFIG_HP300 + if (depth == 6 && p->type == FB_TYPE_PACKED_PIXELS) { + /* depth 6 or more, packed, with color registers */ + + src = logo; + for( y1 = 0; y1 < LOGO_H; y1++ ) { + int c; + dst = fb + y1*line; + for( x1 = 0; x1 < LOGO_W / 2; x1++ ) { + fb_writeb((*src >> 4) + 16, dst++); + fb_writeb(((*src++) & 0xf) + 16, dst++); + } + dst += 8; + for (c = 0; c < 32; c++) + for (x1 = 0; x1 < 24; x1++) + *dst++ = c; + } + + done = 1; + } +#endif /* CONFIG_HP300 */ #if defined(CONFIG_FBCON_AFB) || defined(CONFIG_FBCON_ILBM) || \ defined(CONFIG_FBCON_IPLAN2P2) || defined(CONFIG_FBCON_IPLAN2P4) || \ defined(CONFIG_FBCON_IPLAN2P8) @@ -2412,8 +2433,22 @@ dst = fb + (y1%4)*8192 + (y1>>2)*line + x/8; else dst = fb + y1*line + x/8; - for( x1 = 0; x1 < LOGO_LINE; ++x1 ) + for( x1 = 0; x1 < LOGO_LINE; ++x1 ) { +#ifndef CONFIG_HP300 fb_writeb(*src++ ^ inverse, dst++); +#else /* CONFIG_HP300 */ + /* hack hack -- make it work with topcat in pseudomono mode */ + char c = *src++ ^ inverse; + fb_writeb((c >> 7) & 1, dst++); + fb_writeb((c >> 6) & 1, dst++); + fb_writeb((c >> 5) & 1, dst++); + fb_writeb((c >> 4) & 1, dst++); + fb_writeb((c >> 3) & 1, dst++); + fb_writeb((c >> 2) & 1, dst++); + fb_writeb((c >> 1) & 1, dst++); + fb_writeb((c >> 0) & 1, dst++); +#endif /* CONFIG_HP300 */ + } } done = 1; } diff -Naur linux-2.4.26/drivers/video/fbmem.c linux-2.4.26-m68k/drivers/video/fbmem.c --- linux-2.4.26/drivers/video/fbmem.c 2004-02-19 00:36:31.000000000 +1100 +++ linux-2.4.26-m68k/drivers/video/fbmem.c 2004-02-19 09:17:54.000000000 +1100 @@ -53,6 +53,7 @@ extern int amifb_setup(char*); extern int atafb_init(void); extern int atafb_setup(char*); +extern int tekfb_init(void); extern int macfb_init(void); extern int macfb_setup(char*); extern int cyberfb_init(void); @@ -271,6 +272,9 @@ #ifdef CONFIG_FB_ATARI { "atafb", atafb_init, atafb_setup }, #endif +#ifdef CONFIG_FB_TEKXP + { "tekfb", tekfb_init, NULL }, +#endif #ifdef CONFIG_FB_MAC { "macfb", macfb_init, macfb_setup }, #endif @@ -964,9 +968,9 @@ fb_drivers[i].init; fb_drivers[i].init = NULL; } - if (fb_drivers[i].setup) - fb_drivers[i].setup(options+j+1); } + if (fb_drivers[i].setup) + fb_drivers[i].setup(options+j+1); return 0; } } diff -Naur linux-2.4.26/drivers/video/sun3fb.c linux-2.4.26-m68k/drivers/video/sun3fb.c --- linux-2.4.26/drivers/video/sun3fb.c 2001-10-01 05:26:08.000000000 +1000 +++ linux-2.4.26-m68k/drivers/video/sun3fb.c 2003-06-14 21:44:17.000000000 +1000 @@ -48,6 +48,8 @@ #ifdef CONFIG_SUN3 #include +#include +#include #endif #ifdef CONFIG_SUN3X #include @@ -59,12 +61,14 @@ #define CURSOR_SHAPE 1 #define CURSOR_BLINK 2 +#define mymemset(x,y) memset(x,0,y) + /* * Interface used by the world */ int sun3fb_init(void); -int sun3fb_setup(char *options); +void sun3fb_setup(char *options); static int currcon; static char fontname[40] __initdata = { 0 }; @@ -115,6 +119,8 @@ static void sun3fb_clear_margin(struct display *p, int s) { struct fb_info_sbusfb *fb = sbusfbinfod(p); + + return; if (fb->switch_from_graph) (*fb->switch_from_graph)(fb); @@ -354,7 +360,7 @@ p++; } - return 0; + return; } static int sun3fbcon_switch(int con, struct fb_info *info) @@ -523,7 +529,7 @@ */ static int __init sun3fb_init_fb(int fbtype, unsigned long addr) { - static struct linux_sbus_device sdb; + static struct sbus_dev sdb; struct fb_fix_screeninfo *fix; struct fb_var_screeninfo *var; struct display *disp; @@ -531,7 +537,7 @@ struct fbtype *type; int linebytes, w, h, depth; char *p = NULL; - + fb = kmalloc(sizeof(struct fb_info_sbusfb), GFP_ATOMIC); if (!fb) return -ENOMEM; @@ -600,8 +606,13 @@ case FBTYPE_SUN2BW: p = bwtwofb_init(fb); break; #endif +#ifdef CONFIG_FB_CGTHREE + case FBTYPE_SUN4COLOR: + case FBTYPE_SUN3COLOR: + p = cgthreefb_init(fb); break; +#endif } - fix->smem_start = fb->disp.screen_base; + fix->smem_start = (unsigned long)fb->disp.screen_base; if (!p) { kfree(fb); @@ -656,17 +667,25 @@ unsigned long addr; char p4id; - if (!con_is_present()) return; - printk("sun3fb_init()\n"); + if (!con_is_present()) return -ENXIO; #ifdef CONFIG_SUN3 - addr = 0xfe20000; switch(*(romvec->pv_fbtype)) { - case FBTYPE_SUN2BW: - return sun3fb_init_fb(FBTYPE_SUN2BW, addr); - case FBTYPE_SUN3COLOR: - printk("cg3 detected but not supported\n"); - return -EINVAL; + case FBTYPE_SUN2BW: + addr = 0xfe20000; + return sun3fb_init_fb(FBTYPE_SUN2BW, addr); + case FBTYPE_SUN3COLOR: + case FBTYPE_SUN4COLOR: + if(idprom->id_machtype != (SM_SUN3|SM_3_60)) { + printk("sun3fb: cgthree/four only supported on 3/60\n"); + return -ENODEV; + } + + addr = 0xfd00000; + return sun3fb_init_fb(*(romvec->pv_fbtype), addr); + default: + printk("sun3fb: unsupported framebuffer\n"); + return -ENODEV; } #else addr = SUN3X_VIDEO_BASE; diff -Naur linux-2.4.26/drivers/video/tek_fb.c linux-2.4.26-m68k/drivers/video/tek_fb.c --- linux-2.4.26/drivers/video/tek_fb.c 1970-01-01 10:00:00.000000000 +1000 +++ linux-2.4.26-m68k/drivers/video/tek_fb.c 2003-07-22 07:31:52.000000000 +1000 @@ -0,0 +1,442 @@ +/* + * linux/drivers/video/tek_fb.c + * + * Copyright (C) 2002,2003 Michael Mueller + * + * 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. + * + * + * It is basicly a hack to get the console working. So if someone feels + * familiar with the framebuffer API a rework would be welcome. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include