Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Linux Kernel Patch v2.2, patch-2.2.8 (05/33)

21 views
Skip to first unread message

Thomas...@ciw.uni-karlsruhe.de

unread,
May 12, 1999, 3:00:00 AM5/12/99
to
Archive-name: v2.2/patch-2.2.8/part05

#!/bin/sh
# this is part 05 of a 33 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.8 continued
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck
if test "$Scheck" != 05; then
echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.8'
else
echo 'x - continuing with patch-2.2.8'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.8' &&
X .word _arm6_7_flush_tlb_all @ 44
X .word _arm6_7_flush_tlb_area @ 48
X .word _arm7_set_pmd @ 52
- .word _arm6_7_reset @ 56
- .word _arm6_7_flush_cache @ 60
-
+ .word _arm6_7_set_pte @ 56
+ .word _arm6_7_reset @ 60
X .word _arm6_7_flush_cache @ 64
+
X .word _arm6_7_flush_cache @ 68
+ .word _arm6_7_flush_cache @ 72
diff -u --recursive --new-file v2.2.7/linux/arch/arm/mm/proc-sa110.S linux/arch/arm/mm/proc-sa110.S
--- v2.2.7/linux/arch/arm/mm/proc-sa110.S Tue Dec 22 14:16:53 1998
+++ linux/arch/arm/mm/proc-sa110.S Sat May 8 11:07:16 1999
@@ -8,6 +8,7 @@
X */
X #include <linux/linkage.h>
X #include <asm/assembler.h>
+#include <asm/hardware.h>
X #include "../lib/constants.h"
X
X /* This is the maximum size of an area which will be flushed. If the area
@@ -21,7 +22,6 @@
X
X /*
X * Function: sa110_flush_cache_all (void)
- *
X * Purpose : Flush all cache lines
X */
X .align 5
@@ -33,7 +33,7 @@
X ands r1, r1, #1
X eor r1, r1, #1
X str r1, [r3]
- ldr ip, =0xdf000000
+ ldr ip, =FLUSH_BASE
X addne ip, ip, #32768
X add r1, ip, #16384 @ only necessary for 16k
X 1: ldr r3, [ip], #32
@@ -47,11 +47,9 @@
X
X /*
X * Function: sa110_flush_cache_area (unsigned long address, int end, int flags)
- *
X * Params : address Area start address
X * : end Area end address
X * : flags b0 = I cache as well
- *
X * Purpose : clean & flush all cache lines associated with this area of memory
X */
X .align 5
@@ -74,10 +72,8 @@
X
X /*
X * Function: sa110_cache_wback_area(unsigned long address, unsigned long end)
- *
X * Params : address Area start address
X * : end Area end address
- *
X * Purpose : ensure all dirty cachelines in the specified area have been
X * written out to memory (for DMA)
X */
@@ -99,13 +95,10 @@
X
X /*
X * Function: sa110_cache_purge_area(unsigned long address, unsigned long end)
- *
X * Params : address Area start address
X * : end Area end address
- *
X * Purpose : throw away all D-cached data in specified region without
- * an obligation to write it ack.
- *
+ * an obligation to write it back.
X * Note : Must clean the D-cached entries around the boundaries if the
X * start and/or end address are not cache aligned.
X */
@@ -124,9 +117,7 @@
X
X /*
X * Function: sa110_flush_cache_entry (unsigned long address)
- *
X * Params : address Address of cache line to flush
- *
X * Purpose : clean & flush an entry
X */
X .align 5
@@ -138,24 +129,23 @@
X mov pc, lr
X
X /*
- * Function: sa110_flush_cache_pte (unsigned long address)
- *
+ * Function: sa110_clean_cache_area(unsigned long start, unsigned long size)
X * Params : address Address of cache line to clean
- *
X * Purpose : Ensure that physical memory reflects cache at this location
X * for page table purposes.
X */
-_sa110_flush_cache_pte:
- mcr p15, 0, r0, c7, c10, 1 @ clean D entry (drain is done by TLB fns)
+_sa110_clean_cache_area:
+1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry (drain is done by TLB fns)
+ add r0, r0, #32
+ subs r1, r1, #32
+ bhi 1b
X mov pc, lr
X
X /*
X * Function: sa110_flush_ram_page (unsigned long page)
- *
X * Params : address Area start address
X * : size size of area
X * : flags b0 = I cache as well
- *
X * Purpose : clean & flush all cache lines associated with this area of memory
X */
X .align 5
@@ -176,7 +166,6 @@
X
X /*
X * Function: sa110_flush_tlb_all (void)
- *
X * Purpose : flush all TLB entries in all caches
X */
X .align 5
@@ -188,11 +177,9 @@
X
X /*
X * Function: sa110_flush_tlb_area (unsigned long address, unsigned long end, int flags)
- *
X * Params : address Area start address
X * : end Area end address
X * : flags b0 = I cache as well
- *
X * Purpose : flush a TLB entry
X */
X .align 5
@@ -212,22 +199,21 @@
X
X .align 5
X _sa110_flush_icache_area:
- mov r3, #0
X 1: mcr p15, 0, r0, c7, c10, 1 @ Clean D entry
X add r0, r0, #32
- cmp r0, r1
- blt 1b
+ subs r1, r1, #32
+ bhi 1b
+ mov r0, #0
+ mcr p15, 0, r0, c7, c10, 4 @ drain WB
X mcr p15, 0, r0, c7, c5, 0 @ flush I cache
X mov pc, lr
X /*
X * Function: sa110_switch_to (struct task_struct *prev, struct task_struct *next)
- *
X * Params : prev Old task structure
X * : next New task structure for process to run
- *
+ * Returns : prev
X * Purpose : Perform a task switch, saving the old processes state, and restoring
X * the new.
- *
X * Notes : We don't fiddle with the FP registers here - we postpone this until
X * the new task actually uses FP. This way, we don't swap FP for tasks
X * that do not require it.
@@ -237,20 +223,30 @@
X stmfd sp!, {r4 - r9, fp, lr} @ Store most regs on stack
X mrs ip, cpsr
X stmfd sp!, {ip} @ Save cpsr_SVC
+ ldr r2, [r0, #TSS_MEMMAP] @ Get old page tables
X str sp, [r0, #TSS_SAVE] @ Save sp_SVC
X ldr sp, [r1, #TSS_SAVE] @ Get saved sp_SVC
- ldr r0, [r1, #TSK_ADDR_LIMIT]
- teq r0, #0
- moveq r0, #DOM_KERNELDOMAIN
- movne r0, #DOM_USERDOMAIN
- mcr p15, 0, r0, c3, c0 @ Set segment
- ldr r0, [r1, #TSS_MEMMAP] @ Page table pointer
+ ldr r4, [r1, #TSK_ADDR_LIMIT]
+ teq r4, #0
+ moveq r4, #DOM_KERNELDOMAIN
+ movne r4, #DOM_USERDOMAIN
+ mcr p15, 0, r4, c3, c0 @ Set segment
+ ldr r4, [r1, #TSS_MEMMAP] @ Page table pointer
+/*
+ * Flushing the cache is nightmarishly slow, so we take any excuse
+ * to get out of it. If the old page table is the same as the new,
+ * this is a CLONE_VM relative of the old task and there is no need
+ * to flush. The overhead of the tests isn't even on the radar
+ * compared to the cost of the flush itself.
+ */
+ teq r4, r2
+ beq 2f
X ldr r3, =Lclean_switch
X ldr r2, [r3]
X ands r2, r2, #1
X eor r2, r2, #1
X str r2, [r3]
- ldr r2, =0xdf000000
+ ldr r2, =FLUSH_BASE
X addne r2, r2, #32768
X add r1, r2, #16384 @ only necessary for 16k
X 1: ldr r3, [r2], #32
@@ -259,19 +255,16 @@
X mov r1, #0
X mcr p15, 0, r1, c7, c5, 0 @ flush I cache
X mcr p15, 0, r1, c7, c10, 4 @ drain WB
- mcr p15, 0, r0, c2, c0, 0 @ load page table pointer
+ mcr p15, 0, r4, c2, c0, 0 @ load page table pointer
X mcr p15, 0, r1, c8, c7, 0 @ flush TLBs
- ldmfd sp!, {ip}
+2: ldmfd sp!, {ip}
X msr spsr, ip @ Save tasks CPSR into SPSR for this return
X ldmfd sp!, {r4 - r9, fp, pc}^ @ Load all regs saved previously
X
X /*
X * Function: sa110_data_abort ()
- *
X * Params : r0 = address of aborted instruction
- *
X * Purpose : obtain information about current aborted instruction
- *
X * Returns : r0 = address of abort
X * : r1 = FSR
X * : r2 != 0 if writing
@@ -288,12 +281,10 @@
X mov pc, lr
X
X /*
- * Function: sa110_set_pmd ()
- *
+ * Function: sa110_set_pmd(pmd_t *pmdp, pmd_t pmd)
X * Params : r0 = Address to set
X * : r1 = value to set
- *
- * Purpose : Set a PMD and flush it out of any WB cache
+ * Purpose : Set a PMD and flush it out
X */
X .align 5
X _sa110_set_pmd: str r1, [r0]
@@ -301,23 +292,51 @@
X mov pc, lr
X
X /*
+ * Function: sa110_set_pte(pte_t *ptep, pte_t pte)
+ * Params : r0 = Address to set
+ * : r1 = value to set
+ * Purpose : Set a PTE and flush it out
+ */
+ .align 5
+_sa110_set_pte: str r1, [r0], #-1024 @ linux version
+
+ eor r1, r1, #LPTE_PRESENT | LPTE_YOUNG | LPTE_WRITE | LPTE_DIRTY
+
+ bic r2, r1, #0xff0
+ bic r2, r2, #3
+ orr r2, r2, #HPTE_TYPE_SMALL
+
+ tst r1, #LPTE_USER | LPTE_EXEC @ User or Exec?
+ orrne r2, r2, #HPTE_AP_READ
+
+ tst r1, #LPTE_WRITE | LPTE_DIRTY @ Write and Dirty?
+ orreq r2, r2, #HPTE_AP_WRITE
+
+ tst r1, #LPTE_PRESENT | LPTE_YOUNG @ Present and Young?
+ movne r2, #0
+
+ str r2, [r0] @ hardware version
+ mov r0, r0
+ mcr p15, 0, r0, c7, c10, 1 @ clean D entry (drain is done by TLB fns)
+ mov pc, lr
+
+/*
X * Function: sa110_check_bugs (void)
X * : sa110_proc_init (void)
X * : sa110_proc_fin (void)
- *
X * Notes : This processor does not require these
X */
X _sa110_check_bugs:
X mrs ip, cpsr
X bic ip, ip, #F_BIT
X msr cpsr, ip
+
X _sa110_proc_init:
X _sa110_proc_fin:
X mov pc, lr
X
X /*
X * Function: sa110_reset
- *
X * Notes : This sets up everything for a reset
X */
X _sa110_reset: mrs r1, cpsr
@@ -350,14 +369,15 @@
X .word _sa110_flush_cache_all @ 24
X .word _sa110_flush_cache_area @ 28
X .word _sa110_flush_cache_entry @ 32
- .word _sa110_flush_cache_pte @ 36
+ .word _sa110_clean_cache_area @ 36
X .word _sa110_flush_ram_page @ 40
X .word _sa110_flush_tlb_all @ 44
X .word _sa110_flush_tlb_area @ 48
X
X .word _sa110_set_pmd @ 52
- .word _sa110_reset @ 56
- .word _sa110_flush_icache_area @ 60
+ .word _sa110_set_pte @ 56
+ .word _sa110_reset @ 60
+ .word _sa110_flush_icache_area @ 64
X
- .word _sa110_cache_wback_area @ 64
- .word _sa110_cache_purge_area @ 68
+ .word _sa110_cache_wback_area @ 68
+ .word _sa110_cache_purge_area @ 72
diff -u --recursive --new-file v2.2.7/linux/arch/arm/mm/small_page.c linux/arch/arm/mm/small_page.c
--- v2.2.7/linux/arch/arm/mm/small_page.c Wed Sep 9 14:51:05 1998
+++ linux/arch/arm/mm/small_page.c Sat May 8 11:06:57 1999
@@ -5,6 +5,8 @@
X *
X * Changelog:
X * 26/01/1996 RMK Cleaned up various areas to make little more generic
+ * 07/02/1999 RMK Support added for 16K and 32K page sizes
+ * containing 8K blocks
X */
X
X #include <linux/signal.h>
@@ -19,21 +21,32 @@
X #include <linux/swap.h>
X #include <linux/smp.h>
X
-#define SMALL_ALLOC_SHIFT (10)
+#if PAGE_SIZE == 4096
+/* 2K blocks */
+#define SMALL_ALLOC_SHIFT (11)
+#define NAME(x) x##_2k
+#elif PAGE_SIZE == 32768 || PAGE_SIZE == 16384
+/* 8K blocks */
+#define SMALL_ALLOC_SHIFT (13)
+#define NAME(x) x##_8k
+#endif
+
X #define SMALL_ALLOC_SIZE (1 << SMALL_ALLOC_SHIFT)
X #define NR_BLOCKS (PAGE_SIZE / SMALL_ALLOC_SIZE)
+#define BLOCK_MASK ((1 << NR_BLOCKS) - 1)
X
-#if NR_BLOCKS != 4
-#error I only support 4 blocks per page!
-#endif
-
-#define USED(pg) ((atomic_read(&(pg)->count) >> 8) & 15)
+#define USED(pg) ((atomic_read(&(pg)->count) >> 8) & BLOCK_MASK)
X #define SET_USED(pg,off) (atomic_read(&(pg)->count) |= 256 << off)
X #define CLEAR_USED(pg,off) (atomic_read(&(pg)->count) &= ~(256 << off))
+#define ALL_USED BLOCK_MASK
X #define IS_FREE(pg,off) (!(atomic_read(&(pg)->count) & (256 << off)))
-#define PAGE_PTR(page,block) ((struct free_small_page *)((page) + \
+#define SM_PAGE_PTR(page,block) ((struct free_small_page *)((page) + \
X ((block) << SMALL_ALLOC_SHIFT)))
X
+#if NR_BLOCKS != 2 && NR_BLOCKS != 4
+#error I only support 2 or 4 blocks per page
+#endif
+
X struct free_small_page {
X unsigned long next;
X unsigned long prev;
@@ -52,6 +65,7 @@
X 1, /* 0001 */
X 0, /* 0010 */
X 2, /* 0011 */
+#if NR_BLOCKS == 4
X 0, /* 0100 */
X 1, /* 0101 */
X 0, /* 0110 */
@@ -64,6 +78,7 @@
X 1, /* 1101 */
X 0, /* 1110 */
X 4 /* 1111 */
+#endif
X };
X
X static inline void clear_page_links(unsigned long page)
@@ -72,7 +87,7 @@
X int i;
X
X for (i = 0; i < NR_BLOCKS; i++) {
- fsp = PAGE_PTR(page, i);
+ fsp = SM_PAGE_PTR(page, i);
X fsp->next = fsp->prev = 0;
X }
X }
@@ -90,7 +105,7 @@
X for (i = 0; i < NR_BLOCKS; i++) {
X if (mask & (1 << i))
X continue;
- fsp = PAGE_PTR(page, i);
+ fsp = SM_PAGE_PTR(page, i);
X fsp->prev = prev;
X }
X }
@@ -108,12 +123,12 @@
X for (i = 0; i < NR_BLOCKS; i++) {
X if (mask & (1 << i))
X continue;
- fsp = PAGE_PTR(page, i);
+ fsp = SM_PAGE_PTR(page, i);
X fsp->next = next;
X }
X }
X
-unsigned long get_small_page(int priority)
+unsigned long NAME(get_page)(int priority)
X {
X struct free_small_page *fsp;
X unsigned long new_page;
@@ -129,8 +144,8 @@
X page = mem_map + MAP_NR(small_page_ptr);
X offset = offsets[USED(page)];
X SET_USED(page, offset);
- new_page = (unsigned long)PAGE_PTR(small_page_ptr, offset);
- if (USED(page) == 15) {
+ new_page = (unsigned long)SM_PAGE_PTR(small_page_ptr, offset);
+ if (USED(page) == ALL_USED) {
X fsp = (struct free_small_page *)new_page;
X set_page_links_prev (fsp->next, 0);
X small_page_ptr = fsp->next;
@@ -156,30 +171,31 @@
X goto again;
X }
X
-void free_small_page(unsigned long spage)
+void NAME(free_page)(unsigned long spage)
X {
X struct free_small_page *ofsp, *cfsp;
X unsigned long flags;
X struct page *page;
X int offset, oldoffset;
X
+ if (!spage)
+ goto none;
+
X offset = (spage >> SMALL_ALLOC_SHIFT) & (NR_BLOCKS - 1);
X spage -= offset << SMALL_ALLOC_SHIFT;
X
X page = mem_map + MAP_NR(spage);
- if (!PageReserved(page) || !USED(page)) {
- printk ("Trying to free non-small page from %p\n", __builtin_return_address(0));
- return;
- }
- if (IS_FREE(page, offset)) {
- printk ("Trying to free free small page from %p\n", __builtin_return_address(0));
- return;
- }
+ if (!PageReserved(page) || !USED(page))
+ goto non_small;
+
+ if (IS_FREE(page, offset))
+ goto free;
+
X save_flags_cli (flags);
X oldoffset = offsets[USED(page)];
X CLEAR_USED(page, offset);
- ofsp = PAGE_PTR(spage, oldoffset);
- cfsp = PAGE_PTR(spage, offset);
+ ofsp = SM_PAGE_PTR(spage, oldoffset);
+ cfsp = SM_PAGE_PTR(spage, offset);
X
X if (oldoffset == NR_BLOCKS) { /* going from totally used to mostly used */
X cfsp->prev = 0;
@@ -197,4 +213,13 @@
X } else
X *cfsp = *ofsp;
X restore_flags(flags);
+ return;
+
+non_small:
+ printk ("Trying to free non-small page from %p\n", __builtin_return_address(0));
+ return;
+free:
+ printk ("Trying to free free small page from %p\n", __builtin_return_address(0));
+none:
+ return;
X }
diff -u --recursive --new-file v2.2.7/linux/arch/i386/kernel/entry.S linux/arch/i386/kernel/entry.S
--- v2.2.7/linux/arch/i386/kernel/entry.S Wed Jan 20 23:14:04 1999
+++ linux/arch/i386/kernel/entry.S Fri Apr 30 08:13:37 1999
@@ -154,7 +154,9 @@
X .globl ret_from_fork
X ret_from_fork:
X #ifdef __SMP__
+ pushl %ebx
X call SYMBOL_NAME(schedule_tail)
+ addl $4, %esp
X #endif /* __SMP__ */
X GET_CURRENT(%ebx)
X jmp ret_from_sys_call
diff -u --recursive --new-file v2.2.7/linux/arch/i386/kernel/i386_ksyms.c linux/arch/i386/kernel/i386_ksyms.c
--- v2.2.7/linux/arch/i386/kernel/i386_ksyms.c Tue Mar 23 14:35:46 1999
+++ linux/arch/i386/kernel/i386_ksyms.c Mon May 10 10:32:45 1999
@@ -39,6 +39,7 @@
X EXPORT_SYMBOL(local_irq_count);
X EXPORT_SYMBOL(enable_irq);
X EXPORT_SYMBOL(disable_irq);
+EXPORT_SYMBOL(disable_irq_nosync);
X EXPORT_SYMBOL(kernel_thread);
X
X EXPORT_SYMBOL_NOVERS(__down_failed);
@@ -91,7 +92,7 @@
X EXPORT_SYMBOL(__global_sti);
X EXPORT_SYMBOL(__global_save_flags);
X EXPORT_SYMBOL(__global_restore_flags);
-EXPORT_SYMBOL(mtrr_hook);
+EXPORT_SYMBOL(smp_call_function);
X #endif
X
X #ifdef CONFIG_MCA
diff -u --recursive --new-file v2.2.7/linux/arch/i386/kernel/io_apic.c linux/arch/i386/kernel/io_apic.c
--- v2.2.7/linux/arch/i386/kernel/io_apic.c Fri Apr 16 14:47:30 1999
+++ linux/arch/i386/kernel/io_apic.c Thu May 6 16:07:03 1999
@@ -1049,7 +1049,7 @@
X * and do not need to be masked.
X */
X ack_APIC_irq();
- status = desc->status & ~IRQ_REPLAY;
+ status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING);
X status |= IRQ_PENDING;
X
X /*
@@ -1060,8 +1060,9 @@
X if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
X action = desc->action;
X status &= ~IRQ_PENDING;
+ status |= IRQ_INPROGRESS;
X }
- desc->status = status | IRQ_INPROGRESS;
+ desc->status = status;
X spin_unlock(&irq_controller_lock);
X
X /*
@@ -1103,7 +1104,7 @@
X * So this all has to be within the spinlock.
X */
X mask_IO_APIC_irq(irq);
- status = desc->status & ~IRQ_REPLAY;
+ status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING);
X
X /*
X * If the IRQ is disabled for whatever reason, we must
@@ -1112,8 +1113,9 @@
X action = NULL;
X if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
X action = desc->action;
+ status |= IRQ_INPROGRESS;
X }
- desc->status = status | IRQ_INPROGRESS;
+ desc->status = status;
X
X ack_APIC_irq();
X spin_unlock(&irq_controller_lock);
diff -u --recursive --new-file v2.2.7/linux/arch/i386/kernel/irq.c linux/arch/i386/kernel/irq.c
--- v2.2.7/linux/arch/i386/kernel/irq.c Fri Apr 16 14:47:30 1999
+++ linux/arch/i386/kernel/irq.c Mon May 10 10:32:45 1999
@@ -203,7 +203,7 @@
X
X void make_8259A_irq(unsigned int irq)
X {
- disable_irq(irq);
+ disable_irq_nosync(irq);
X io_apic_irqs &= ~(1<<irq);
X irq_desc[irq].handler = &i8259A_irq_type;
X enable_irq(irq);
@@ -239,11 +239,13 @@
X {
X unsigned int status;
X mask_and_ack_8259A(irq);
- status = desc->status & ~IRQ_REPLAY;
+ status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING);
X action = NULL;
- if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+ if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
X action = desc->action;
- desc->status = status | IRQ_INPROGRESS;
+ status |= IRQ_INPROGRESS;
+ }
+ desc->status = status;
X }
X spin_unlock(&irq_controller_lock);
X
@@ -320,7 +322,7 @@
X BUILD_SMP_INTERRUPT(reschedule_interrupt)
X BUILD_SMP_INTERRUPT(invalidate_interrupt)
X BUILD_SMP_INTERRUPT(stop_cpu_interrupt)
-BUILD_SMP_INTERRUPT(mtrr_interrupt)
+BUILD_SMP_INTERRUPT(call_function_interrupt)
X BUILD_SMP_INTERRUPT(spurious_interrupt)
X
X /*
@@ -747,7 +749,7 @@
X * hardware disable after having gotten the irq
X * controller lock.
X */
-void disable_irq(unsigned int irq)
+void disable_irq_nosync(unsigned int irq)
X {
X unsigned long flags;
X
@@ -757,9 +759,21 @@
X irq_desc[irq].handler->disable(irq);
X }
X spin_unlock_irqrestore(&irq_controller_lock, flags);
+}
+
+/*
+ * Synchronous version of the above, making sure the IRQ is
+ * no longer running on any other IRQ..
+ */
+void disable_irq(unsigned int irq)
+{
+ disable_irq_nosync(irq);
X
- if (irq_desc[irq].status & IRQ_INPROGRESS)
- synchronize_irq();
+ if (!local_irq_count[smp_processor_id()]) {
+ do {
+ barrier();
+ } while (irq_desc[irq].status & IRQ_INPROGRESS);
+ }
X }
X
X void enable_irq(unsigned int irq)
@@ -769,7 +783,7 @@
X spin_lock_irqsave(&irq_controller_lock, flags);
X switch (irq_desc[irq].depth) {
X case 1:
- irq_desc[irq].status &= ~(IRQ_DISABLED | IRQ_INPROGRESS);
+ irq_desc[irq].status &= ~IRQ_DISABLED;
X irq_desc[irq].handler->enable(irq);
X /* fall throught */
X default:
@@ -864,7 +878,7 @@
X
X if (!shared) {
X irq_desc[irq].depth = 0;
- irq_desc[irq].status &= ~(IRQ_DISABLED | IRQ_INPROGRESS);
+ irq_desc[irq].status &= ~IRQ_DISABLED;
X irq_desc[irq].handler->startup(irq);
X }
X spin_unlock_irqrestore(&irq_controller_lock,flags);
@@ -936,7 +950,7 @@
X *
X * This depends on the fact that any interrupt that
X * comes in on to an unassigned handler will get stuck
- * with "IRQ_INPROGRESS" asserted and the interrupt
+ * with "IRQ_WAITING" cleared and the interrupt
X * disabled.
X */
X unsigned long probe_irq_on(void)
@@ -950,8 +964,7 @@
X spin_lock_irq(&irq_controller_lock);
X for (i = NR_IRQS-1; i > 0; i--) {
X if (!irq_desc[i].action) {
- unsigned int status = irq_desc[i].status | IRQ_AUTODETECT;
- irq_desc[i].status = status & ~IRQ_INPROGRESS;
+ irq_desc[i].status |= IRQ_AUTODETECT | IRQ_WAITING;
X irq_desc[i].handler->startup(i);
X }
X }
@@ -974,7 +987,7 @@
X continue;
X
X /* It triggered already - consider it spurious. */
- if (status & IRQ_INPROGRESS) {
+ if (!(status & IRQ_WAITING)) {
X irq_desc[i].status = status & ~IRQ_AUTODETECT;
X irq_desc[i].handler->shutdown(i);
X }
@@ -1000,7 +1013,7 @@
X if (!(status & IRQ_AUTODETECT))
X continue;
X
- if (status & IRQ_INPROGRESS) {
+ if (!(status & IRQ_WAITING)) {
X if (!nr_irqs)
X irq_found = i;
X nr_irqs++;
@@ -1081,8 +1094,8 @@
X /* self generated IPI for local APIC timer */
X set_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt);
X
- /* IPI for MTRR control */
- set_intr_gate(MTRR_CHANGE_VECTOR, mtrr_interrupt);
+ /* IPI for generic function call */
+ set_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt);
X
X /* IPI vector for APIC spurious interrupts */
X set_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt);
diff -u --recursive --new-file v2.2.7/linux/arch/i386/kernel/irq.h linux/arch/i386/kernel/irq.h
--- v2.2.7/linux/arch/i386/kernel/irq.h Fri Apr 16 14:47:30 1999
+++ linux/arch/i386/kernel/irq.h Tue May 11 10:37:06 1999
@@ -26,6 +26,7 @@
X #define IRQ_PENDING 4 /* IRQ pending - replay on enable */
X #define IRQ_REPLAY 8 /* IRQ has been replayed but not acked yet */
X #define IRQ_AUTODETECT 16 /* IRQ is being autodetected */
+#define IRQ_WAITING 32 /* IRQ not yet seen - for autodetection */
X
X /*
X * This is the "IRQ descriptor", which contains various information
@@ -64,7 +65,7 @@
X #define INVALIDATE_TLB_VECTOR 0x31
X #define STOP_CPU_VECTOR 0x40
X #define LOCAL_TIMER_VECTOR 0x41
-#define MTRR_CHANGE_VECTOR 0x50
+#define CALL_FUNCTION_VECTOR 0x50
X
X /*
X * First APIC vector available to drivers: (vectors 0x51-0xfe)
@@ -98,7 +99,6 @@
X extern int i8259A_irq_pending(unsigned int irq);
X extern void ack_APIC_irq(void);
X extern void FASTCALL(send_IPI_self(int vector));
-extern void smp_send_mtrr(void);
X extern void init_VISWS_APIC_irqs(void);
X extern void setup_IO_APIC(void);
X extern int IO_APIC_get_PCI_irq_vector(int bus, int slot, int fn);
diff -u --recursive --new-file v2.2.7/linux/arch/i386/kernel/mca.c linux/arch/i386/kernel/mca.c
--- v2.2.7/linux/arch/i386/kernel/mca.c Fri Apr 16 14:47:30 1999
+++ linux/arch/i386/kernel/mca.c Mon May 10 13:00:10 1999
@@ -92,7 +92,7 @@
X * is set to zero.
X */
X
-static struct MCA_info* mca_info = 0;
+static struct MCA_info* mca_info = NULL;
X
X /* MCA registers */
X
@@ -160,7 +160,10 @@
X
X /* id = 0x0000 usually indicates hardware failure,
X * however, ZP Gu (z...@castle.net> reports that his 9556
- * has 0x0000 as id and everything still works.
+ * has 0x0000 as id and everything still works. There
+ * also seem to be an adapter with id = 0x0000; the
+ * NCR Parallel Bus Memory Card. Until this is confirmed,
+ * however, this code will stay.
X */
X
X mca_info->slot[slot].status = MCA_ADAPTER_ERROR;
@@ -222,7 +225,13 @@
X
X /* Allocate MCA_info structure (at address divisible by 8) */
X
- mca_info = kmalloc(sizeof(struct MCA_info), GFP_ATOMIC);
+ mca_info = kmalloc(sizeof(struct MCA_info), GFP_KERNEL);
+
+ if(mca_info == NULL) {
+ printk("Failed to allocate memory for mca_info!");
+ restore_flags(flags);
+ return;
+ }
X
X /* Make sure adapter setup is off */
X
@@ -382,7 +391,7 @@
X
X int mca_find_adapter(int id, int start)
X {
- if(mca_info == 0 || id == 0 || id == 0xffff) {
+ if(mca_info == NULL || id == 0xffff) {
X return MCA_NOTFOUND;
X }
X
@@ -412,7 +421,7 @@
X
X int mca_find_unused_adapter(int id, int start)
X {
- if(mca_info == 0 || id == 0 || id == 0xffff) {
+ if(mca_info == NULL || id == 0xffff) {
X return MCA_NOTFOUND;
X }
X
@@ -443,7 +452,7 @@
X
X unsigned char mca_read_stored_pos(int slot, int reg)
X {
- if(slot < 0 || slot >= MCA_NUMADAPTERS || mca_info == 0) return 0;
+ if(slot < 0 || slot >= MCA_NUMADAPTERS || mca_info == NULL) return 0;
X if(reg < 0 || reg >= 8) return 0;
X return mca_info->slot[slot].pos[reg];
X } /* mca_read_stored_pos() */
@@ -455,7 +464,7 @@
X unsigned int byte = 0;
X unsigned long flags;
X
- if(slot < 0 || slot >= MCA_NUMADAPTERS || mca_info == 0) return 0;
+ if(slot < 0 || slot >= MCA_NUMADAPTERS || mca_info == NULL) return 0;
X if(reg < 0 || reg >= 8) return 0;
X
X save_flags(flags);
@@ -527,7 +536,7 @@
X return;
X if(reg < 0 || reg >= 8)
X return;
- if(mca_info == 0)
+ if(mca_info == NULL)
X return;
X
X save_flags(flags);
@@ -554,7 +563,7 @@
X
X void mca_set_adapter_name(int slot, char* name)
X {
- if(mca_info == 0) return;
+ if(mca_info == NULL) return;
X
X if(slot >= 0 && slot < MCA_NUMADAPTERS) {
X if(name != NULL) {
@@ -570,7 +579,7 @@
X
X void mca_set_adapter_procfn(int slot, MCA_ProcFn procfn, void* dev)
X {
- if(mca_info == 0) return;
+ if(mca_info == NULL) return;
X
X if(slot >= 0 && slot < MCA_NUMADAPTERS) {
X mca_info->slot[slot].procfn = procfn;
@@ -597,7 +606,7 @@
X
X char *mca_get_adapter_name(int slot)
X {
- if(mca_info == 0) return 0;
+ if(mca_info == NULL) return 0;
X
X if(slot >= 0 && slot < MCA_NUMADAPTERS) {
X return mca_info->slot[slot].name;
@@ -608,7 +617,7 @@
X
X int mca_isadapter(int slot)
X {
- if(mca_info == 0) return 0;
+ if(mca_info == NULL) return 0;
X
X if(slot >= 0 && slot < MCA_NUMADAPTERS) {
X return ((mca_info->slot[slot].status == MCA_ADAPTER_NORMAL)
@@ -620,7 +629,7 @@
X
X int mca_isenabled(int slot)
X {
- if(mca_info == 0) return 0;
+ if(mca_info == NULL) return 0;
X
X if(slot >= 0 && slot < MCA_NUMADAPTERS) {
X return (mca_info->slot[slot].status == MCA_ADAPTER_NORMAL);
@@ -637,7 +646,7 @@
X {
X int i, j, len = 0;
X
- if(MCA_bus && mca_info != 0)
+ if(MCA_bus && mca_info != NULL)
X {
X /* Format POS registers of eight MCA slots */
X
@@ -676,10 +685,10 @@
X
X __initfunc(void mca_do_proc_init(void))
X {
- int i = 0;
- struct proc_dir_entry* node = 0;
+ int i;
+ struct proc_dir_entry* node = NULL;
X
- if(mca_info == 0) return; /* Should never happen */
+ if(mca_info == NULL) return; /* Should never happen */
X
X proc_register(&proc_mca, &(struct proc_dir_entry) {
X PROC_MCA_REGISTERS, 3, "pos", S_IFREG|S_IRUGO,
@@ -696,8 +705,12 @@
X mca_info->slot[i].dev = 0;
X
X if(!mca_isadapter(i)) continue;
- node = kmalloc(sizeof(struct proc_dir_entry), GFP_ATOMIC);
+ node = kmalloc(sizeof(struct proc_dir_entry), GFP_KERNEL);
X
+ if(node == NULL) {
+ printk("Failed to allocate memory for MCA proc-entries!");
+ return;
+ }
X if(i < MCA_MAX_SLOT_NR) {
X node->low_ino = PROC_MCA_SLOT + i;
X node->namelen = sprintf(mca_info->slot[i].procname,
@@ -727,7 +740,7 @@
X
X /* This really shouldn't happen... */
X
- if(mca_info == 0) {
+ if(mca_info == NULL) {
X *buf = 0;
X return 0;
X }
diff -u --recursive --new-file v2.2.7/linux/arch/i386/kernel/mtrr.c linux/arch/i386/kernel/mtrr.c
--- v2.2.7/linux/arch/i386/kernel/mtrr.c Mon Dec 28 15:00:52 1998
+++ linux/arch/i386/kernel/mtrr.c Mon May 10 10:32:45 1999
@@ -132,6 +132,70 @@
X Fixed harmless compiler warning in include/asm-i386/mtrr.h
X Fixed version numbering and history for v1.23 -> v1.24.
X v1.26
+ 19990118 Richard Gooch <rgo...@atnf.csiro.au>
+ PLACEHOLDER.
+ v1.27
+ 19990123 Richard Gooch <rgo...@atnf.csiro.au>
+ Changed locking to spin with reschedule.
+ Made use of new <smp_call_function>.
+ v1.28
+ 19990201 Zoltan Boszormenyi <zbo...@mol.hu>
+ Extended the driver to be able to use Cyrix style ARRs.
+ 19990204 Richard Gooch <rgo...@atnf.csiro.au>
+ Restructured Cyrix support.
+ v1.29
+ 19990204 Zoltan Boszormenyi <zbo...@mol.hu>
+ Refined ARR support: enable MAPEN in set_mtrr_prepare()
+ and disable MAPEN in set_mtrr_done().
+ 19990205 Richard Gooch <rgo...@atnf.csiro.au>
+ Minor cleanups.
+ v1.30
+ 19990208 Zoltan Boszormenyi <zbo...@mol.hu>
+ Protect plain 6x86s (and other processors without the
+ Page Global Enable feature) against accessing CR4 in
+ set_mtrr_prepare() and set_mtrr_done().
+ 19990210 Richard Gooch <rgo...@atnf.csiro.au>
+ Turned <set_mtrr_up> and <get_mtrr> into function pointers.
+ v1.31
+ 19990212 Zoltan Boszormenyi <zbo...@mol.hu>
+ Major rewrite of cyrix_arr_init(): do not touch ARRs,
+ leave them as the BIOS have set them up.
+ Enable usage of all 8 ARRs.
+ Avoid multiplications by 3 everywhere and other
+ code clean ups/speed ups.
+ 19990213 Zoltan Boszormenyi <zbo...@mol.hu>
+ Set up other Cyrix processors identical to the boot cpu.
+ Since Cyrix don't support Intel APIC, this is l'art pour l'art.
+ Weigh ARRs by size:
+ If size <= 32M is given, set up ARR# we were given.
+ If size > 32M is given, set up ARR7 only if it is free,
+ fail otherwise.
+ 19990214 Zoltan Boszormenyi <zbo...@mol.hu>
+ Also check for size >= 256K if we are to set up ARR7,
+ mtrr_add() returns the value it gets from set_mtrr()
+ 19990218 Zoltan Boszormenyi <zbo...@mol.hu>
+ Remove Cyrix "coma bug" workaround from here.
+ Moved to linux/arch/i386/kernel/setup.c and
+ linux/include/asm-i386/bugs.h
+ 19990228 Richard Gooch <rgo...@atnf.csiro.au>
+ Added #ifdef CONFIG_DEVFS_FS
+ Added MTRRIOC_KILL_ENTRY ioctl(2)
+ Trap for counter underflow in <mtrr_file_del>.
+ Trap for 4 MiB aligned regions for PPro, stepping <= 7.
+ 19990301 Richard Gooch <rgo...@atnf.csiro.au>
+ Created <get_free_region> hook.
+ 19990305 Richard Gooch <rgo...@atnf.csiro.au>
+ Temporarily disable AMD support now MTRR capability flag is set.
+ v1.32
+ 19990308 Zoltan Boszormenyi <zbo...@mol.hu>
+ Adjust my changes (19990212-19990218) to Richard Gooch's
+ latest changes. (19990228-19990305)
+ v1.33
+ 19990309 Richard Gooch <rgo...@atnf.csiro.au>
+ Fixed typo in <printk> message.
+ 19990310 Richard Gooch <rgo...@atnf.csiro.au>
+ Support K6-II/III based on Alan Cox's <al...@redhat.com> patches.
+ v1.34
X */
X #include <linux/types.h>
X #include <linux/errno.h>
@@ -163,11 +227,12 @@
X #include <asm/segment.h>
X #include <asm/bitops.h>
X #include <asm/atomic.h>
+#include <asm/msr.h>
X
X #include <asm/hardirq.h>
X #include "irq.h"
X
-#define MTRR_VERSION "1.26 (19981001)"
+#define MTRR_VERSION "1.34 (19990310)"
X
X #define TRUE 1
X #define FALSE 0
@@ -197,7 +262,7 @@
X # define MTRR_CHANGE_MASK_DEFTYPE 0x04
X #endif
X
-/* In the processor's MTRR interface, the MTRR type is always held in
+/* In the Intel processor's MTRR interface, the MTRR type is always held in
X an 8 bit field: */
X typedef u8 mtrr_type;
X
@@ -207,9 +272,12 @@
X #ifdef __SMP__
X # define set_mtrr(reg,base,size,type) set_mtrr_smp (reg, base, size, type)
X #else
-# define set_mtrr(reg,base,size,type) set_mtrr_up (reg, base, size, type,TRUE)
+# define set_mtrr(reg,base,size,type) (*set_mtrr_up) (reg, base, size, type, \
+ TRUE)
X #endif
X
+#define spin_lock_reschedule(lock) while (!spin_trylock(lock)) schedule ();
+
X #ifndef CONFIG_PROC_FS
X # define compute_ascii() while (0)
X #endif
@@ -233,49 +301,30 @@
X unsigned long deftype_lo;
X unsigned long deftype_hi;
X unsigned long cr4val;
+ unsigned long ccr3;
X };
X
-/*
- * Access to machine-specific registers (available on 586 and better only)
- * Note: the rd* operations modify the parameters directly (without using
- * pointer indirection), this allows gcc to optimize better
- */
-#define rdmsr(msr,val1,val2) \
- __asm__ __volatile__("rdmsr" \
- : "=a" (val1), "=d" (val2) \
- : "c" (msr))
-
-#define wrmsr(msr,val1,val2) \
- __asm__ __volatile__("wrmsr" \
- : /* no outputs */ \
- : "c" (msr), "a" (val1), "d" (val2))
-
-#define rdtsc(low,high) \
- __asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high))
-
-#define rdpmc(counter,low,high) \
- __asm__ __volatile__("rdpmc" \
- : "=a" (low), "=d" (high) \
- : "c" (counter))
-
X
-/* Put the processor into a state where MTRRs can be safely set. */
-static void set_mtrr_prepare(struct set_mtrr_context *ctxt)
+/* Put the processor into a state where MTRRs can be safely set */
+static void set_mtrr_prepare (struct set_mtrr_context *ctxt)
X {
X unsigned long tmp;
X
- /* disable interrupts locally */
+ /* Disable interrupts locally */
X __save_flags (ctxt->flags); __cli ();
X
- /* save value of CR4 and clear Page Global Enable (bit 7) */
- asm volatile ("movl %%cr4, %0\n\t"
- "movl %0, %1\n\t"
- "andb $0x7f, %b1\n\t"
- "movl %1, %%cr4\n\t"
- : "=r" (ctxt->cr4val), "=q" (tmp) : : "memory");
+ if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) return;
X
- /* disable and flush caches. Note that wbinvd flushes the TLBs as
- a side-effect. */
+ /* Save value of CR4 and clear Page Global Enable (bit 7) */
+ if (boot_cpu_data.x86_capability & X86_FEATURE_PGE)
+ asm volatile ("movl %%cr4, %0\n\t"
+ "movl %0, %1\n\t"
+ "andb $0x7f, %b1\n\t"
+ "movl %1, %%cr4\n\t"
+ : "=r" (ctxt->cr4val), "=q" (tmp) : : "memory");
+
+ /* Disable and flush caches. Note that wbinvd flushes the TLBs as
+ a side-effect */
X asm volatile ("movl %%cr0, %0\n\t"
X "orl $0x40000000, %0\n\t"
X "wbinvd\n\t"
@@ -283,64 +332,108 @@
X "wbinvd\n\t"
X : "=r" (tmp) : : "memory");
X
- /* disable MTRRs, and set the default type to uncached. */
- rdmsr(MTRRdefType_MSR, ctxt->deftype_lo, ctxt->deftype_hi);
- wrmsr(MTRRdefType_MSR, ctxt->deftype_lo & 0xf300UL, ctxt->deftype_hi);
+ switch (boot_cpu_data.x86_vendor)
+ {
+ case X86_VENDOR_INTEL:
+ /* Disable MTRRs, and set the default type to uncached */
+ rdmsr (MTRRdefType_MSR, ctxt->deftype_lo, ctxt->deftype_hi);
+ wrmsr (MTRRdefType_MSR, ctxt->deftype_lo & 0xf300UL, ctxt->deftype_hi);
+ break;
+ case X86_VENDOR_CYRIX:
+ tmp = getCx86 (CX86_CCR3);
+ setCx86 (CX86_CCR3, (tmp & 0x0f) | 0x10);
+ ctxt->ccr3 = tmp;
+ break;
+ }
X } /* End Function set_mtrr_prepare */
X
-
-/* Restore the processor after a set_mtrr_prepare */
-static void set_mtrr_done(struct set_mtrr_context *ctxt)
+/* Restore the processor after a set_mtrr_prepare */
+static void set_mtrr_done (struct set_mtrr_context *ctxt)
X {
X unsigned long tmp;
X
- /* flush caches and TLBs */
+ if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD)
+ {
+ __restore_flags (ctxt->flags);
+ return;
+ }
+
+ /* Flush caches and TLBs */
X asm volatile ("wbinvd" : : : "memory" );
X
- /* restore MTRRdefType */
- wrmsr(MTRRdefType_MSR, ctxt->deftype_lo, ctxt->deftype_hi);
+ /* Restore MTRRdefType */
+ switch (boot_cpu_data.x86_vendor)
+ {
+ case X86_VENDOR_INTEL:
+ wrmsr (MTRRdefType_MSR, ctxt->deftype_lo, ctxt->deftype_hi);
+ break;
+ case X86_VENDOR_CYRIX:
+ setCx86 (CX86_CCR3, ctxt->ccr3);
+ break;
+ }
X
- /* enable caches */
+ /* Enable caches */
X asm volatile ("movl %%cr0, %0\n\t"
X "andl $0xbfffffff, %0\n\t"
X "movl %0, %%cr0\n\t"
X : "=r" (tmp) : : "memory");
X
- /* restore value of CR4 */
- asm volatile ("movl %0, %%cr4"
- : : "r" (ctxt->cr4val) : "memory");
+ /* Restore value of CR4 */
+ if (boot_cpu_data.x86_capability & X86_FEATURE_PGE)
+ asm volatile ("movl %0, %%cr4"
+ : : "r" (ctxt->cr4val) : "memory");
X
- /* re-enable interrupts locally (if enabled previously) */
+ /* Re-enable interrupts locally (if enabled previously) */
X __restore_flags (ctxt->flags);
X } /* End Function set_mtrr_done */
X
-
-/* this function returns the number of variable MTRRs */
+/* This function returns the number of variable MTRRs */
X static unsigned int get_num_var_ranges (void)
X {
X unsigned long config, dummy;
X
- rdmsr(MTRRcap_MSR, config, dummy);
- return (config & 0xff);
+ switch (boot_cpu_data.x86_vendor)
+ {
+ case X86_VENDOR_INTEL:
+ rdmsr (MTRRcap_MSR, config, dummy);
+ return (config & 0xff);
+ /*break;*/
+ case X86_VENDOR_CYRIX:
+ /* Cyrix have 8 ARRs */
+ return 8;
+ /*break;*/
+ case X86_VENDOR_AMD:
+ return 2;
+ /*break;*/
+ }
+ return 0;
X } /* End Function get_num_var_ranges */
X
-
-/* non-zero if we have the write-combining memory type. */
+/* Returns non-zero if we have the write-combining memory type */
X static int have_wrcomb (void)
X {
X unsigned long config, dummy;
X
- rdmsr(MTRRcap_MSR, config, dummy);
- return (config & (1<<10));
-}
-
+ switch (boot_cpu_data.x86_vendor)
+ {
+ case X86_VENDOR_INTEL:
+ rdmsr (MTRRcap_MSR, config, dummy);
+ return (config & (1<<10));
+ /*break;*/
+ case X86_VENDOR_CYRIX:
+ case X86_VENDOR_AMD:
+ return 1;
+ /*break;*/
+ }
+ return 0;
+} /* End Function have_wrcomb */
X
-static void get_mtrr (unsigned int reg, unsigned long *base,
- unsigned long *size, mtrr_type *type)
+static void intel_get_mtrr (unsigned int reg, unsigned long *base,
+ unsigned long *size, mtrr_type *type)
X {
X unsigned long dummy, mask_lo, base_lo;
X
- rdmsr(MTRRphysMask_MSR(reg), mask_lo, dummy);
+ rdmsr (MTRRphysMask_MSR(reg), mask_lo, dummy);
X if ((mask_lo & 0x800) == 0) {
X /* Invalid (i.e. free) range. */
X *base = 0;
@@ -364,11 +457,104 @@
X
X *base = (base_lo & 0xfffff000UL);
X *type = (base_lo & 0xff);
-} /* End Function get_mtrr */
+} /* End Function intel_get_mtrr */
+
+static void cyrix_get_arr (unsigned int reg, unsigned long *base,
+ unsigned long *size, mtrr_type *type)
+{
+ unsigned long flags;
+ unsigned char arr, ccr3, rcr, shift;
+
+ arr = CX86_ARR_BASE + (reg << 1) + reg; /* avoid multiplication by 3 */
X
+ /* Save flags and disable interrupts */
+ __save_flags (flags); __cli ();
X
-static void set_mtrr_up (unsigned int reg, unsigned long base,
- unsigned long size, mtrr_type type, int do_safe)
+ ccr3 = getCx86 (CX86_CCR3);
+ setCx86 (CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* enable MAPEN */
+ ((unsigned char *) base)[3] = getCx86 (arr);
+ ((unsigned char *) base)[2] = getCx86 (arr+1);
+ ((unsigned char *) base)[1] = getCx86 (arr+2);
+ rcr = getCx86(CX86_RCR_BASE + reg);
+ setCx86 (CX86_CCR3, ccr3); /* disable MAPEN */
+
+ /* Enable interrupts if it was enabled previously */
+ __restore_flags (flags);
+
+ shift = ((unsigned char *) base)[1] & 0x0f;
+ *base &= 0xfffff000UL;
+
+ /* Power of two, at least 4K on ARR0-ARR6, 256K on ARR7
+ * Note: shift==0xf means 4G, this is unsupported.
+ */
+ if (shift)
+ *size = (reg < 7 ? 0x800UL : 0x20000UL) << shift;
+ else
+ *size = 0;
+
+ /* Bit 0 is Cache Enable on ARR7, Cache Disable on ARR0-ARR6 */
+ if (reg < 7) {
+ switch (rcr) {
+ case 1: *type = MTRR_TYPE_UNCACHABLE; break;
+ case 8: *type = MTRR_TYPE_WRBACK; break;
+ case 9: *type = MTRR_TYPE_WRCOMB; break;
+ case 24:
+ default: *type = MTRR_TYPE_WRTHROUGH; break;
+ }
+ } else {
+ switch (rcr) {
+ case 0: *type = MTRR_TYPE_UNCACHABLE; break;
+ case 8: *type = MTRR_TYPE_WRCOMB; break;
+ case 9: *type = MTRR_TYPE_WRBACK; break;
+ case 25:
+ default: *type = MTRR_TYPE_WRTHROUGH; break;
+ }
+ }
+} /* End Function cyrix_get_arr */
+
+static void amd_get_mtrr (unsigned int reg, unsigned long *base,
+ unsigned long *size, mtrr_type *type)
+{
+ unsigned long low, high;
+
+ rdmsr (0xC0000085, low, high);
+ /* Upper dword is region 1, lower is region 0 */
+ if (reg == 1) low = high;
+ /* The base masks off on the right alignment */
+ *base = low & 0xFFFE0000;
+ *type = 0;
+ if (low & 1) *type = MTRR_TYPE_UNCACHABLE;
+ if (low & 2) *type = MTRR_TYPE_WRCOMB;
+ if ( !(low & 3) )
+ {
+ *size = 0;
+ return;
+ }
+ /*
+ * This needs a little explaining. The size is stored as an
+ * inverted mask of bits of 128K granularity 15 bits long offset
+ * 2 bits
+ *
+ * So to get a size we do invert the mask and add 1 to the lowest
+ * mask bit (4 as its 2 bits in). This gives us a size we then shift
+ * to turn into 128K blocks
+ *
+ * eg 111 1111 1111 1100 is 512K
+ *
+ * invert 000 0000 0000 0011
+ * +1 000 0000 0000 0100
+ * *128K ...
+ */
+ low = (~low) & 0x1FFFC;
+ *size = (low + 4) << 15;
+ return;
+} /* End Function amd_get_mtrr */
+
+static void (*get_mtrr) (unsigned int reg, unsigned long *base,
+ unsigned long *size, mtrr_type *type) = NULL;
+
+static void intel_set_mtrr_up (unsigned int reg, unsigned long base,
+ unsigned long size, mtrr_type type, int do_safe)
X /* [SUMMARY] Set variable MTRR register on the local CPU.
X <reg> The register to set.
X <base> The base address of the region.
@@ -376,6 +562,7 @@
X <type> The type of the region.
X <do_safe> If TRUE, do the change safely. If FALSE, safety measures should
X be done externally.
+ [RETURNS] Nothing.
X */
X {
X struct set_mtrr_context ctxt;
@@ -393,8 +580,92 @@
X wrmsr (MTRRphysMask_MSR (reg), ~(size - 1) | 0x800, 0);
X }
X if (do_safe) set_mtrr_done (&ctxt);
-} /* End Function set_mtrr_up */
+} /* End Function intel_set_mtrr_up */
+
+static void cyrix_set_arr_up (unsigned int reg, unsigned long base,
+ unsigned long size, mtrr_type type, int do_safe)
+{
+ struct set_mtrr_context ctxt;
+ unsigned char arr, arr_type, arr_size;
+
+ arr = CX86_ARR_BASE + (reg << 1) + reg; /* avoid multiplication by 3 */
+
+ /* count down from 32M (ARR0-ARR6) or from 2G (ARR7) */
+ size >>= (reg < 7 ? 12 : 18);
+ size &= 0x7fff; /* make sure arr_size <= 14 */
+ for(arr_size = 0; size; arr_size++, size >>= 1);
+
+ if (reg<7) {
+ switch (type) {
+ case MTRR_TYPE_UNCACHABLE: arr_type = 1; break;
+ case MTRR_TYPE_WRCOMB: arr_type = 9; break;
+ case MTRR_TYPE_WRTHROUGH: arr_type = 24; break;
+ default: arr_type = 8; break;
+ }
+ } else {
+ switch (type) {
+ case MTRR_TYPE_UNCACHABLE: arr_type = 0; break;
+ case MTRR_TYPE_WRCOMB: arr_type = 8; break;
+ case MTRR_TYPE_WRTHROUGH: arr_type = 25; break;
+ default: arr_type = 9; break;
+ }
+ }
+
+ if (do_safe) set_mtrr_prepare (&ctxt);
+ setCx86(arr, ((unsigned char *) &base)[3]);
+ setCx86(arr+1, ((unsigned char *) &base)[2]);
+ setCx86(arr+2, (((unsigned char *) &base)[1]) | arr_size);
+ setCx86(CX86_RCR_BASE + reg, arr_type);
+ if (do_safe) set_mtrr_done (&ctxt);
+} /* End Function cyrix_set_arr_up */
+
+static void amd_set_mtrr_up (unsigned int reg, unsigned long base,
+ unsigned long size, mtrr_type type, int do_safe)
+/* [SUMMARY] Set variable MTRR register on the local CPU.
+ <reg> The register to set.
+ <base> The base address of the region.
+ <size> The size of the region. If this is 0 the region is disabled.
+ <type> The type of the region.
+ <do_safe> If TRUE, do the change safely. If FALSE, safety measures should
+ be done externally.
+ [RETURNS] Nothing.
+*/
+{
+ u32 low, high;
+ struct set_mtrr_context ctxt;
+
+ if (do_safe) set_mtrr_prepare (&ctxt);
+ /*
+ * Low is MTRR0 , High MTRR 1
+ */
+ rdmsr (0xC0000085, low, high);
+ /*
+ * Blank to disable
+ */
+ if (size == 0)
+ *(reg ? &high : &low) = 0;
+ else
+ /* Set the register to the base (already shifted for us), the
+ type (off by one) and an inverted bitmask of the size
+
+ The size is the only odd bit. We are fed say 512K
+ We invert this and we get 111 1111 1111 1011 but
+ if you subtract one and invert you get the desired
+ 111 1111 1111 1100 mask
+ */
+ *(reg ? &high : &low)=(((~(size-1))>>15)&0x0001FFFC)|base|(type+1);
+ /*
+ * The writeback rule is quite specific. See the manual. Its
+ * disable local interrupts, write back the cache, set the mtrr
+ */
+ __asm__ __volatile__ ("wbinvd" : : : "memory");
+ wrmsr (0xC0000085, low, high);
+ if (do_safe) set_mtrr_done (&ctxt);
+} /* End Function amd_set_mtrr_up */
X
+static void (*set_mtrr_up) (unsigned int reg, unsigned long base,
+ unsigned long size, mtrr_type type,
+ int do_safe) = NULL;
X
X #ifdef __SMP__
X
@@ -407,7 +678,7 @@
X };
X
X
-/* Get the MSR pair relating to a var range. */
+/* Get the MSR pair relating to a var range */
X __initfunc(static void get_mtrr_var_range (unsigned int index,
X struct mtrr_var_range *vr))
X {
@@ -416,8 +687,8 @@
X } /* End Function get_mtrr_var_range */
X
X
-/* Set the MSR pair relating to a var range. Returns TRUE if
- changes are made. */
+/* Set the MSR pair relating to a var range. Returns TRUE if
+ changes are made */
X __initfunc(static int set_mtrr_var_range_testing (unsigned int index,
X struct mtrr_var_range *vr))
X {
@@ -441,8 +712,7 @@
X }
X
X return changed;
-}
-
+} /* End Function set_mtrr_var_range_testing */
X
X __initfunc(static void get_fixed_ranges(mtrr_type *frs))
X {
@@ -456,8 +726,7 @@
X
X for (i = 0; i < 8; i++)
X rdmsr(MTRRfix4K_C0000_MSR + i, p[6 + i*2], p[7 + i*2]);
-}
-
+} /* End Function get_fixed_ranges */
X
X __initfunc(static int set_fixed_ranges_testing(mtrr_type *frs))
X {
@@ -487,10 +756,8 @@
X changed = TRUE;
X }
X }
-
X return changed;
-}
-
+} /* End Function set_fixed_ranges_testing */
X
X struct mtrr_state
X {
@@ -502,7 +769,7 @@
X };
X
X
-/* Grab all of the MTRR state for this CPU into *state. */
+/* Grab all of the MTRR state for this CPU into *state */
X __initfunc(static void get_mtrr_state(struct mtrr_state *state))
X {
X unsigned int nvrs, i;
@@ -511,22 +778,22 @@
X
X nvrs = state->num_var_ranges = get_num_var_ranges();
X vrs = state->var_ranges
- = kmalloc(nvrs * sizeof(struct mtrr_var_range), GFP_KERNEL);
+ = kmalloc (nvrs * sizeof (struct mtrr_var_range), GFP_KERNEL);
X if (vrs == NULL)
X nvrs = state->num_var_ranges = 0;
X
X for (i = 0; i < nvrs; i++)
- get_mtrr_var_range(i, &vrs[i]);
+ get_mtrr_var_range (i, &vrs[i]);
X
- get_fixed_ranges(state->fixed_ranges);
+ get_fixed_ranges (state->fixed_ranges);
X
- rdmsr(MTRRdefType_MSR, lo, dummy);
+ rdmsr (MTRRdefType_MSR, lo, dummy);
X state->def_type = (lo & 0xff);
X state->enabled = (lo & 0xc00) >> 10;
X } /* End Function get_mtrr_state */
X
X
-/* Free resources associated with a struct mtrr_state */
+/* Free resources associated with a struct mtrr_state */
X __initfunc(static void finalize_mtrr_state(struct mtrr_state *state))
X {
X if (state->var_ranges) kfree (state->var_ranges);
@@ -546,14 +813,14 @@
X unsigned long change_mask = 0;
X
X for (i = 0; i < state->num_var_ranges; i++)
- if (set_mtrr_var_range_testing(i, &state->var_ranges[i]))
+ if ( set_mtrr_var_range_testing (i, &state->var_ranges[i]) )
X change_mask |= MTRR_CHANGE_MASK_VARIABLE;
X
- if (set_fixed_ranges_testing(state->fixed_ranges))
+ if ( set_fixed_ranges_testing(state->fixed_ranges) )
X change_mask |= MTRR_CHANGE_MASK_FIXED;
X
- /* set_mtrr_restore restores the old value of MTRRdefType,
- so to set it we fiddle with the saved value. */
+ /* Set_mtrr_restore restores the old value of MTRRdefType,
+ so to set it we fiddle with the saved value */
X if ((ctxt->deftype_lo & 0xff) != state->def_type
X || ((ctxt->deftype_lo & 0xc00) >> 10) != state->enabled)
X {
@@ -566,76 +833,63 @@
X
X
X static atomic_t undone_count;
-static void (*handler_func) (struct set_mtrr_context *ctxt, void *info);
-static void *handler_info;
X static volatile int wait_barrier_execute = FALSE;
X static volatile int wait_barrier_cache_enable = FALSE;
X
-static void sync_handler (void)
+struct set_mtrr_data
+{
+ unsigned long smp_base;
+ unsigned long smp_size;
+ unsigned int smp_reg;
+ mtrr_type smp_type;
+};
+
+static void ipi_handler (void *info)
X /* [SUMMARY] Synchronisation handler. Executed by "other" CPUs.
X [RETURNS] Nothing.
X */
X {
+ struct set_mtrr_data *data = info;
X struct set_mtrr_context ctxt;
X
X set_mtrr_prepare (&ctxt);
- /* Notify master CPU that I'm at the barrier and then wait */
+ /* Notify master that I've flushed and disabled my cache */
X atomic_dec (&undone_count);
X while (wait_barrier_execute) barrier ();
X /* The master has cleared me to execute */
- (*handler_func) (&ctxt, handler_info);
+ (*set_mtrr_up) (data->smp_reg, data->smp_base, data->smp_size,
+ data->smp_type, FALSE);
X /* Notify master CPU that I've executed the function */
X atomic_dec (&undone_count);
X /* Wait for master to clear me to enable cache and return */
X while (wait_barrier_cache_enable) barrier ();
X set_mtrr_done (&ctxt);
-} /* End Function sync_handler */
+} /* End Function ipi_handler */
X
-static void do_all_cpus (void (*handler) (struct set_mtrr_context *ctxt,
- void *info),
- void *info, int local)
-/* [SUMMARY] Execute a function on all CPUs, with caches flushed and disabled.
- [PURPOSE] This function will synchronise all CPUs, flush and disable caches
- on all CPUs, then call a specified function. When the specified function
- finishes on all CPUs, caches are enabled on all CPUs.
- <handler> The function to execute.
- <info> An arbitrary information pointer which is passed to <<handler>>.
- <local> If TRUE <<handler>> is executed locally.
- [RETURNS] Nothing.
-*/
+static void set_mtrr_smp (unsigned int reg, unsigned long base,
+ unsigned long size, mtrr_type type)
X {
- unsigned long timeout;
+ struct set_mtrr_data data;
X struct set_mtrr_context ctxt;
X
- mtrr_hook = sync_handler;
- handler_func = handler;
- handler_info = info;
+ data.smp_reg = reg;
+ data.smp_base = base;
+ data.smp_size = size;
+ data.smp_type = type;
X wait_barrier_execute = TRUE;
X wait_barrier_cache_enable = TRUE;
- /* Send a message to all other CPUs and wait for them to enter the
- barrier */
X atomic_set (&undone_count, smp_num_cpus - 1);
- smp_send_mtrr();
- /* Wait for it to be done */
- timeout = jiffies + JIFFIE_TIMEOUT;
- while ( (atomic_read (&undone_count) > 0) &&
- time_before(jiffies, timeout) )
- barrier ();
- if (atomic_read (&undone_count) > 0)
- {
+ /* Flush and disable the local CPU's cache and start the ball rolling on
+ other CPUs */
+ set_mtrr_prepare (&ctxt);
+ if (smp_call_function (ipi_handler, &data, 1, 0) != 0)
X panic ("mtrr: timed out waiting for other CPUs\n");
- }
- mtrr_hook = NULL;
- /* All other CPUs should be waiting for the barrier, with their caches
- already flushed and disabled. Prepare for function completion
- notification */
+ /* Wait for all other CPUs to flush and disable their caches */
+ while (atomic_read (&undone_count) > 0) barrier ();
+ /* Set up for completion wait and then release other CPUs to change MTRRs*/
X atomic_set (&undone_count, smp_num_cpus - 1);
- /* Flush and disable the local CPU's cache and release the barier, which
- should cause the other CPUs to execute the function. Also execute it
- locally if required */
- set_mtrr_prepare (&ctxt);
X wait_barrier_execute = FALSE;
- if (local) (*handler) (&ctxt, info);
+ (*set_mtrr_up) (reg, base, size, type, FALSE);
X /* Now wait for other CPUs to complete the function */
X while (atomic_read (&undone_count) > 0) barrier ();
X /* Now all CPUs should have finished the function. Release the barrier to
@@ -643,41 +897,10 @@
X then enable the local cache and return */
X wait_barrier_cache_enable = FALSE;
X set_mtrr_done (&ctxt);
- handler_func = NULL;
- handler_info = NULL;
-} /* End Function do_all_cpus */
-
-
-struct set_mtrr_data
-{
- unsigned long smp_base;
- unsigned long smp_size;
- unsigned int smp_reg;
- mtrr_type smp_type;
-};
-
-static void set_mtrr_handler (struct set_mtrr_context *ctxt, void *info)
-{
- struct set_mtrr_data *data = info;
-
- set_mtrr_up (data->smp_reg, data->smp_base, data->smp_size, data->smp_type,
- FALSE);
-} /* End Function set_mtrr_handler */
-
-static void set_mtrr_smp (unsigned int reg, unsigned long base,
- unsigned long size, mtrr_type type)
-{
- struct set_mtrr_data data;
-
- data.smp_reg = reg;
- data.smp_base = base;
- data.smp_size = size;
- data.smp_type = type;
- do_all_cpus (set_mtrr_handler, &data, TRUE);
X } /* End Function set_mtrr_smp */
X
X
-/* Some BIOS's are fucked and don't set all MTRRs the same! */
+/* Some BIOS's are fucked and don't set all MTRRs the same! */
X __initfunc(static void mtrr_state_warn (unsigned long mask))
X {
X if (!mask) return;
@@ -720,6 +943,58 @@
X #endif
X } /* End Function init_table */
X
+static int generic_get_free_region (unsigned long base, unsigned long size)
+/* [SUMMARY] Get a free MTRR.
+ <base> The starting (base) address of the region.
+ <size> The size (in bytes) of the region.
+ [RETURNS] The index of the region on success, else -1 on error.
+*/
+{
+ int i, max;
+ mtrr_type ltype;
+ unsigned long lbase, lsize;
+
+ max = get_num_var_ranges ();
+ for (i = 0; i < max; ++i)
+ {
+ (*get_mtrr) (i, &lbase, &lsize, &ltype);
+ if (lsize < 1) return i;
+ }
+ return -ENOSPC;
+} /* End Function generic_get_free_region */
+
+static int cyrix_get_free_region (unsigned long base, unsigned long size)
+/* [SUMMARY] Get a free ARR.
+ <base> The starting (base) address of the region.
+ <size> The size (in bytes) of the region.
+ [RETURNS] The index of the region on success, else -1 on error.
+*/
+{
+ int i;
+ mtrr_type ltype;
+ unsigned long lbase, lsize;
+
+ /* If we are to set up a region >32M then look at ARR7 immediately */
+ if (size > 0x2000000UL) {
+ cyrix_get_arr (7, &lbase, &lsize, &ltype);
+ if (lsize < 1) return 7;
+ /* else try ARR0-ARR6 first */
+ } else {
+ for (i = 0; i < 7; i++)
+ {
+ cyrix_get_arr (i, &lbase, &lsize, &ltype);
+ if (lsize < 1) return i;
+ }
+ /* ARR0-ARR6 isn't free, try ARR7 but its size must be at least 256K */
+ cyrix_get_arr (i, &lbase, &lsize, &ltype);
+ if ((lsize < 1) && (size >= 0x40000)) return i;
+ }
+ return -ENOSPC;
+} /* End Function cyrix_get_free_region */
+
+static int (*get_free_region) (unsigned long base,
+ unsigned long size) = generic_get_free_region;
+
X int mtrr_add (unsigned long base, unsigned long size, unsigned int type,
X char increment)
X /* [SUMMARY] Add an MTRR entry.
@@ -738,28 +1013,57 @@
X unsigned long lbase, lsize, last;
X
X if ( !(boot_cpu_data.x86_capability & X86_FEATURE_MTRR) ) return -ENODEV;
- if ( (base & 0xfff) || (size & 0xfff) )
- {
- printk ("mtrr: size and base must be multiples of 4kB\n");
- printk ("mtrr: size: %lx base: %lx\n", size, base);
- return -EINVAL;
- }
- if (base + size < 0x100000)
- {
- printk ("mtrr: cannot set region below 1 MByte (0x%lx,0x%lx)\n",
- base, size);
- return -EINVAL;
- }
- /* Check upper bits of base and last are equal and lower bits are 0 for
- base and 1 for last */
- last = base + size - 1;
- for (lbase = base; !(lbase & 1) && (last & 1);
- lbase = lbase >> 1, last = last >> 1);
- if (lbase != last)
+ switch (boot_cpu_data.x86_vendor)
X {
- printk ("mtrr: base(0x%lx) is not aligned on a size(0x%lx) boundary\n",
- base, size);
+ case X86_VENDOR_INTEL:
+ /* For Intel PPro stepping <= 7, must be 4 MiB aligned */
+ if ( (boot_cpu_data.x86 == 6) && (boot_cpu_data.x86_model == 1) &&
+ (boot_cpu_data.x86_mask <= 7) && ( base & ( (1 << 22) - 1 ) ) )
+ {
+ printk ("mtrr: base(0x%lx) is not 4 MiB aligned\n", base);
+ return -EINVAL;
+ }
+ /* Fall through */
+ case X86_VENDOR_CYRIX:
+ if ( (base & 0xfff) || (size & 0xfff) )
+ {
+ printk ("mtrr: size and base must be multiples of 4 kiB\n");
+ printk ("mtrr: size: %lx base: %lx\n", size, base);
+ return -EINVAL;
+ }
+ if (base + size < 0x100000)
+ {
+ printk ("mtrr: cannot set region below 1 MiB (0x%lx,0x%lx)\n",
+ base, size);
+ return -EINVAL;
+ }
+ /* Check upper bits of base and last are equal and lower bits are 0
+ for base and 1 for last */
+ last = base + size - 1;
+ for (lbase = base; !(lbase & 1) && (last & 1);
+ lbase = lbase >> 1, last = last >> 1);
+ if (lbase != last)
+ {
+ printk ("mtrr: base(0x%lx) is not aligned on a size(0x%lx) boundary\n",
+ base, size);
+ return -EINVAL;
+ }
+ break;
+ case X86_VENDOR_AMD:
+ /* Apply the K6 block alignment and size rules
+ In order
+ o Uncached or gathering only
+ o 128K or bigger block
+ o Power of 2 block
+ o base suitably aligned to the power
+ */
+ if (type > MTRR_TYPE_WRCOMB || size < (1 << 17) ||
+ (size & ~(size-1))-size || (base & (size-1)))
+ return -EINVAL;
+ break;
+ default:
X return -EINVAL;
+ /*break;*/
X }
X if (type >= MTRR_NUM_TYPES)
X {
@@ -775,10 +1079,10 @@
X increment = increment ? 1 : 0;
X max = get_num_var_ranges ();
X /* Search for existing MTRR */
- spin_lock (&main_lock);
+ spin_lock_reschedule (&main_lock);
X for (i = 0; i < max; ++i)
X {
- get_mtrr (i, &lbase, &lsize, &ltype);
+ (*get_mtrr) (i, &lbase, &lsize, &ltype);
X if (base >= lbase + lsize) continue;
X if ( (base < lbase) && (base + size <= lbase) ) continue;
X /* At this point we know there is some kind of overlap/enclosure */
@@ -804,19 +1108,18 @@
X return i;
X }
X /* Search for an empty MTRR */
- for (i = 0; i < max; ++i)
+ i = (*get_free_region) (base, size);
+ if (i < 0)
X {
- get_mtrr (i, &lbase, &lsize, &ltype);
- if (lsize > 0) continue;
- set_mtrr (i, base, size, type);
- usage_table[i] = 1;
- compute_ascii ();
X spin_unlock (&main_lock);
+ printk ("mtrr: no more MTRRs available\n");
X return i;
X }
+ set_mtrr (i, base, size, type);
+ usage_table[i] = 1;
+ compute_ascii ();
X spin_unlock (&main_lock);
- printk ("mtrr: no more MTRRs available\n");
- return -ENOSPC;
+ return i;
X } /* End Function mtrr_add */
X
X int mtrr_del (int reg, unsigned long base, unsigned long size)
@@ -836,13 +1139,13 @@
X
X if ( !(boot_cpu_data.x86_capability & X86_FEATURE_MTRR) ) return -ENODEV;
X max = get_num_var_ranges ();
- spin_lock (&main_lock);
+ spin_lock_reschedule (&main_lock);
X if (reg < 0)
X {
X /* Search for existing MTRR */
SHAR_EOF
true || echo 'restore of patch-2.2.8 failed'
fi
echo 'End of part 05'
echo 'File patch-2.2.8 is continued in part 06'
echo 06 > _shar_seq_.tmp
exit 0
--
Thomas Koenig, Thomas...@ciw.uni-karlsruhe.de, ig...@dkauni2.bitnet.
The joy of engineering is to find a straight line on a double
logarithmic diagram.

Thomas...@ciw.uni-karlsruhe.de

unread,
May 12, 1999, 3:00:00 AM5/12/99
to
Archive-name: v2.2/patch-2.2.8/part06

#!/bin/sh
# this is part 06 of a 33 - part archive


# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.8 continued
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 06; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.8'
else
echo 'x - continuing with patch-2.2.8'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.8' &&

X for (i = 0; i < max; ++i)
X {
- get_mtrr (i, &lbase, &lsize, &ltype);
+ (*get_mtrr) (i, &lbase, &lsize, &ltype);

X if ( (lbase == base) && (lsize == size) )
X {
X reg = i;
@@ -862,7 +1165,7 @@
X printk ("mtrr: register: %d too big\n", reg);
X return -EINVAL;
X }
- get_mtrr (reg, &lbase, &lsize, &ltype);
+ (*get_mtrr) (reg, &lbase, &lsize, &ltype);
X if (lsize < 1)
X {
X spin_unlock (&main_lock);
@@ -913,7 +1216,9 @@
X
X reg = mtrr_del (-1, base, size);
X if (reg < 0) return reg;
- if (fcount != NULL) --fcount[reg];
+ if (fcount == NULL) return reg;
+ if (fcount[reg] < 1) return -EINVAL;
+ --fcount[reg];
X return reg;
X } /* End Function mtrr_file_del */
X
@@ -1019,11 +1324,18 @@
X err = mtrr_file_del (sentry.base, sentry.size, file);
X if (err < 0) return err;
X break;
+ case MTRRIOC_KILL_ENTRY:
+ if ( !suser () ) return -EPERM;
+ if ( copy_from_user (&sentry, (void *) arg, sizeof sentry) )
+ return -EFAULT;
+ err = mtrr_del (-1, sentry.base, sentry.size);
+ if (err < 0) return err;
+ break;
X case MTRRIOC_GET_ENTRY:
X if ( copy_from_user (&gentry, (void *) arg, sizeof gentry) )
X return -EFAULT;
X if ( gentry.regnum >= get_num_var_ranges () ) return -EINVAL;
- get_mtrr (gentry.regnum, &gentry.base, &gentry.size, &type);
+ (*get_mtrr) (gentry.regnum, &gentry.base, &gentry.size, &type);
X gentry.type = type;
X if ( copy_to_user ( (void *) arg, &gentry, sizeof gentry) )
X return -EFAULT;
@@ -1115,7 +1427,7 @@


X max = get_num_var_ranges ();

X for (i = 0; i < max; i++)
X {
- get_mtrr (i, &base, &size, &type);
+ (*get_mtrr) (i, &base, &size, &type);
X if (size < 1) usage_table[i] = 0;
X else
X {
@@ -1148,23 +1460,165 @@


X
X #ifdef __SMP__
X

+typedef struct {
+ unsigned long base;
+ unsigned long size;
+ mtrr_type type;
+} arr_state_t;
+
+arr_state_t arr_state[8] __initdata = {
+ {0UL,0UL,0UL}, {0UL,0UL,0UL}, {0UL,0UL,0UL}, {0UL,0UL,0UL},
+ {0UL,0UL,0UL}, {0UL,0UL,0UL}, {0UL,0UL,0UL}, {0UL,0UL,0UL}
+};
+
+unsigned char ccr_state[7] __initdata = { 0, 0, 0, 0, 0, 0, 0 };
+
+__initfunc(static void cyrix_arr_init_secondary(void))


+{
+ struct set_mtrr_context ctxt;

+ int i;
+
+ set_mtrr_prepare (&ctxt); /* flush cache and enable MAPEN */
+
+ /* the CCRs are not contiguous */
+ for(i=0; i<4; i++) setCx86(CX86_CCR0 + i, ccr_state[i]);
+ for( ; i<7; i++) setCx86(CX86_CCR4 + i, ccr_state[i]);
+ for(i=0; i<8; i++)
+ cyrix_set_arr_up(i,
+ arr_state[i].base, arr_state[i].size, arr_state[i].type, FALSE);
+
+ set_mtrr_done (&ctxt); /* flush cache and disable MAPEN */
+} /* End Function cyrix_arr_init_secondary */
+
+#endif
+
+/*
+ * On Cyrix 6x86(MX) and M II the ARR3 is special: it has connection
+ * with the SMM (System Management Mode) mode. So we need the following:
+ * Check whether SMI_LOCK (CCR3 bit 0) is set
+ * if it is set, write a warning message: ARR3 cannot be changed!
+ * (it cannot be changed until the next processor reset)
+ * if it is reset, then we can change it, set all the needed bits:
+ * - disable access to SMM memory through ARR3 range (CCR1 bit 7 reset)
+ * - disable access to SMM memory (CCR1 bit 2 reset)
+ * - disable SMM mode (CCR1 bit 1 reset)
+ * - disable write protection of ARR3 (CCR6 bit 1 reset)
+ * - (maybe) disable ARR3
+ * Just to be sure, we enable ARR usage by the processor (CCR5 bit 5 set)
+ */
+__initfunc(static void cyrix_arr_init(void))


+{
+ struct set_mtrr_context ctxt;

+ unsigned char ccr[7];
+ int ccrc[7] = { 0, 0, 0, 0, 0, 0, 0 };
+#ifdef __SMP__
+ int i;
+#endif
+
+ set_mtrr_prepare (&ctxt); /* flush cache and enable MAPEN */
+
+ /* Save all CCRs locally */
+ ccr[0] = getCx86 (CX86_CCR0);
+ ccr[1] = getCx86 (CX86_CCR1);
+ ccr[2] = getCx86 (CX86_CCR2);
+ ccr[3] = ctxt.ccr3;
+ ccr[4] = getCx86 (CX86_CCR4);
+ ccr[5] = getCx86 (CX86_CCR5);
+ ccr[6] = getCx86 (CX86_CCR6);
+
+ if (ccr[3] & 1)
+ ccrc[3] = 1;
+ else {
+ /* Disable SMM mode (bit 1), access to SMM memory (bit 2) and
+ * access to SMM memory through ARR3 (bit 7).
+ */
+/*
+ if (ccr[1] & 0x80) { ccr[1] &= 0x7f; ccrc[1] |= 0x80; }
+ if (ccr[1] & 0x04) { ccr[1] &= 0xfb; ccrc[1] |= 0x04; }
+ if (ccr[1] & 0x02) { ccr[1] &= 0xfd; ccrc[1] |= 0x02; }
+*/
+ if (ccr[6] & 0x02) {
+ ccr[6] &= 0xfd; ccrc[6] = 1; /* Disable write protection of ARR3. */
+ setCx86 (CX86_CCR6, ccr[6]);
+ }
+ /* Disable ARR3. */
+ /* cyrix_set_arr_up (3, 0, 0, 0, FALSE); */
+ }
+ /* If we changed CCR1 in memory, change it in the processor, too. */
+ if (ccrc[1]) setCx86 (CX86_CCR1, ccr[1]);
+
+ /* Enable ARR usage by the processor */
+ if (!(ccr[5] & 0x20)) {
+ ccr[5] |= 0x20; ccrc[5] = 1;
+ setCx86 (CX86_CCR5, ccr[5]);
+ }
+
+#ifdef __SMP__
+ for(i=0; i<7; i++) ccr_state[i] = ccr[i];
+ for(i=0; i<8; i++)
+ cyrix_get_arr(i,
+ &arr_state[i].base, &arr_state[i].size, &arr_state[i].type);
+#endif
+
+ set_mtrr_done (&ctxt); /* flush cache and disable MAPEN */
+
+ if ( ccrc[5] ) printk ("mtrr: ARR usage was not enabled, enabled manually\n");
+ if ( ccrc[3] ) printk ("mtrr: ARR3 cannot be changed\n");
+/*
+ if ( ccrc[1] & 0x80) printk ("mtrr: SMM memory access through ARR3 disabled\n");
+ if ( ccrc[1] & 0x04) printk ("mtrr: SMM memory access disabled\n");
+ if ( ccrc[1] & 0x02) printk ("mtrr: SMM mode disabled\n");
+*/
+ if ( ccrc[6] ) printk ("mtrr: ARR3 was write protected, unprotected\n");
+} /* End Function cyrix_arr_init */
+
+__initfunc(static void mtrr_setup (void))
+{
+ printk ("mtrr: v%s Richard Gooch (rgo...@atnf.csiro.au)\n", MTRR_VERSION);


+ switch (boot_cpu_data.x86_vendor)
+ {
+ case X86_VENDOR_INTEL:

+ get_mtrr = intel_get_mtrr;
+ set_mtrr_up = intel_set_mtrr_up;


+ break;
+ case X86_VENDOR_CYRIX:

+ printk ("mtrr: Using Cyrix style ARRs\n");
+ get_mtrr = cyrix_get_arr;
+ set_mtrr_up = cyrix_set_arr_up;
+ get_free_region = cyrix_get_free_region;


+ break;
+ case X86_VENDOR_AMD:

+ get_mtrr = amd_get_mtrr;
+ set_mtrr_up = amd_set_mtrr_up;
+ break;
+ }
+} /* End Function mtrr_setup */
+
+#ifdef __SMP__
+
X static volatile unsigned long smp_changes_mask __initdata = 0;
X static struct mtrr_state smp_mtrr_state __initdata = {0, 0};
X
X __initfunc(void mtrr_init_boot_cpu (void))
X {
X if ( !(boot_cpu_data.x86_capability & X86_FEATURE_MTRR) ) return;
- printk("mtrr: v%s Richard Gooch (rgo...@atnf.csiro.au)\n", MTRR_VERSION);
-
- get_mtrr_state (&smp_mtrr_state);
+ mtrr_setup ();


+ switch (boot_cpu_data.x86_vendor)
+ {
+ case X86_VENDOR_INTEL:

+ get_mtrr_state (&smp_mtrr_state);


+ break;
+ case X86_VENDOR_CYRIX:

+ cyrix_arr_init ();
+ break;
+ }
X } /* End Function mtrr_init_boot_cpu */
X
-__initfunc(void mtrr_init_secondary_cpu (void))
+__initfunc(static void intel_mtrr_init_secondary_cpu (void))
X {
X unsigned long mask, count;


X struct set_mtrr_context ctxt;
X

- if ( !(boot_cpu_data.x86_capability & X86_FEATURE_MTRR) ) return;
X /* Note that this is not ideal, since the cache is only flushed/disabled
X for this CPU while the MTRRs are changed, but changing this requires
X more invasive changes to the way the kernel boots */
@@ -1177,21 +1631,52 @@
X if (mask & 0x01) set_bit (count, &smp_changes_mask);
X mask >>= 1;
X }
-} /* End Function mtrr_init_secondary_cpu */
+} /* End Function intel_mtrr_init_secondary_cpu */
X
+__initfunc(void mtrr_init_secondary_cpu (void))
+{
+ if ( !(boot_cpu_data.x86_capability & X86_FEATURE_MTRR) ) return;


+ switch (boot_cpu_data.x86_vendor)
+ {
+ case X86_VENDOR_INTEL:

+ intel_mtrr_init_secondary_cpu ();


+ break;
+ case X86_VENDOR_CYRIX:

+ /* This is _completely theoretical_!
+ * I assume here that one day Cyrix will support Intel APIC.
+ * In reality on non-Intel CPUs we won't even get to this routine.
+ * Hopefully no one will plug two Cyrix processors in a dual P5 board.
+ * :-)
+ */
+ cyrix_arr_init_secondary ();
+ break;
+ default:
+ printk ("mtrr: SMP support incomplete for this vendor\n");
+ break;
+ }
+} /* End Function mtrr_init_secondary_cpu */


X #endif /* __SMP__ */
X

X __initfunc(int mtrr_init(void))
X {
X if ( !(boot_cpu_data.x86_capability & X86_FEATURE_MTRR) ) return 0;
-# ifndef __SMP__
- printk("mtrr: v%s Richard Gooch (rgo...@atnf.csiro.au)\n", MTRR_VERSION);
-# endif
-
X # ifdef __SMP__
- finalize_mtrr_state (&smp_mtrr_state);
- mtrr_state_warn (smp_changes_mask);
-# endif /* __SMP__ */


+ switch (boot_cpu_data.x86_vendor)
+ {
+ case X86_VENDOR_INTEL:

+ finalize_mtrr_state (&smp_mtrr_state);
+ mtrr_state_warn (smp_changes_mask);
+ break;
+ }
+# else /* __SMP__ */
+ mtrr_setup ();
+ switch (boot_cpu_data.x86_vendor)
+ {
+ case X86_VENDOR_CYRIX:
+ cyrix_arr_init ();
+ break;
+ }
+# endif /* !__SMP__ */
X
X # ifdef CONFIG_PROC_FS
X proc_register (&proc_root, &proc_root_mtrr);
diff -u --recursive --new-file v2.2.7/linux/arch/i386/kernel/process.c linux/arch/i386/kernel/process.c
--- v2.2.7/linux/arch/i386/kernel/process.c Tue Mar 23 14:35:46 1999
+++ linux/arch/i386/kernel/process.c Fri Apr 30 08:13:37 1999
@@ -111,6 +111,8 @@
X /* endless idle loop with no priority at all */
X current->priority = 0;
X current->counter = -100;
+ init_idle();
+
X for (;;) {
X if (work)
X start_idle = jiffies;
@@ -139,6 +141,8 @@
X /* endless idle loop with no priority at all */
X current->priority = 0;
X current->counter = -100;
+ init_idle();
+
X while(1) {
X if (current_cpu_data.hlt_works_ok && !hlt_counter &&
X !current->need_resched)
diff -u --recursive --new-file v2.2.7/linux/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c
--- v2.2.7/linux/arch/i386/kernel/setup.c Tue Mar 23 14:35:46 1999
+++ linux/arch/i386/kernel/setup.c Mon May 10 10:32:45 1999
@@ -5,6 +5,10 @@
X *
X * Enhanced CPU type detection by Mike Jagdis, Patrick St. Jean
X * and Martin Mares, November 1997.
+ *
+ * Force Cyrix 6x86(MX) and M II processors to report MTRR capability
+ * and fix against Cyrix "coma bug" by
+ * Zoltan Boszormenyi <zbo...@mol.hu> February 1999.
X */
X
X /*
@@ -39,6 +43,7 @@
X #include <asm/io.h>
X #include <asm/smp.h>
X #include <asm/cobalt.h>
+#include <asm/msr.h>
X
X /*
X * Machine setup..
@@ -57,6 +62,7 @@
X unsigned int machine_id = 0;
X unsigned int machine_submodel_id = 0;
X unsigned int BIOS_revision = 0;
+unsigned int mca_pentium_flag = 0;
X
X /*
X * Setup options
@@ -244,11 +250,6 @@
X unsigned long memory_start, memory_end;
X char c = ' ', *to = command_line, *from = COMMAND_LINE;
X int len = 0;
- static unsigned char smptrap=0;
-
- if (smptrap)
- return;
- smptrap=1;
X
X #ifdef CONFIG_VISWS
X visws_get_board_type_and_rev();
@@ -381,16 +382,6 @@
X
X }
X

-#define rdmsr(msr,val1,val2) \
- __asm__ __volatile__("rdmsr" \
- : "=a" (val1), "=d" (val2) \
- : "c" (msr))
-
-#define wrmsr(msr,val1,val2) \
- __asm__ __volatile__("wrmsr" \
- : /* no outputs */ \
- : "c" (msr), "a" (val1), "d" (val2))
-

X __initfunc(static int get_model_name(struct cpuinfo_x86 *c))
X {
X unsigned int n, dummy, *v;
@@ -408,6 +399,14 @@
X cpuid(0x80000003, &v[4], &v[5], &v[6], &v[7]);
X cpuid(0x80000004, &v[8], &v[9], &v[10], &v[11]);
X c->x86_model_id[48] = 0;
+ /* Set MTRR capability flag if appropriate */
+ if(boot_cpu_data.x86 !=5)
+ return 1;
+ if((boot_cpu_data.x86_model == 9) ||
+ ((boot_cpu_data.x86_model == 8) &&
+ (boot_cpu_data.x86_mask >= 8)))
+ c->x86_capability |= X86_FEATURE_MTRR;
+
X return 1;
X }
X
@@ -587,6 +586,10 @@
X (c->x86_model)++;
X } else /* 686 */
X p = Cx86_cb+1;
+ /* Emulate MTRRs using Cyrix's ARRs. */
+ c->x86_capability |= X86_FEATURE_MTRR;
+ /* 6x86's contain this bug */
+ c->coma_bug = 1;
X break;
X
X case 4: /* MediaGX/GXm */
@@ -611,11 +614,14 @@
X
X case 5: /* 6x86MX/M II */
X if (dir1 > 7) dir0_msn++; /* M II */
+ else c->coma_bug = 1; /* 6x86MX, it has the bug. */
X tmp = (!(dir0_lsn & 7) || dir0_lsn & 1) ? 2 : 0;
X Cx86_cb[tmp] = cyrix_model_mult2[dir0_lsn & 7];
X p = Cx86_cb+tmp;
X if (((dir1 & 0x0f) > 4) || ((dir1 & 0xf0) == 0x20))
X (c->x86_model)++;
+ /* Emulate MTRRs using Cyrix's ARRs. */
+ c->x86_capability |= X86_FEATURE_MTRR;
X break;
X
X case 0xf: /* Cyrix 486 without DEVID registers */
@@ -869,7 +875,7 @@
X int sep_bug;
X static char *x86_cap_flags[] = {
X "fpu", "vme", "de", "pse", "tsc", "msr", "6", "mce",
- "cx8", "9", "10", "sep", "12", "pge", "14", "cmov",
+ "cx8", "9", "10", "sep", "mtrr", "pge", "14", "cmov",
X "16", "17", "psn", "19", "20", "21", "22", "mmx",
X "24", "kni", "26", "27", "28", "29", "30", "31"
X };
@@ -917,7 +923,6 @@
X } else if (c->x86_vendor == X86_VENDOR_INTEL) {
X x86_cap_flags[6] = "pae";
X x86_cap_flags[9] = "apic";
- x86_cap_flags[12] = "mtrr";
X x86_cap_flags[14] = "mca";
X x86_cap_flags[16] = "pat";
X x86_cap_flags[17] = "pse36";
@@ -936,6 +941,7 @@
X "hlt_bug\t\t: %s\n"
X "sep_bug\t\t: %s\n"
X "f00f_bug\t: %s\n"
+ "coma_bug\t: %s\n"
X "fpu\t\t: %s\n"
X "fpu_exception\t: %s\n"
X "cpuid level\t: %d\n"
@@ -945,6 +951,7 @@
X c->hlt_works_ok ? "no" : "yes",
X sep_bug ? "yes" : "no",
X c->f00f_bug ? "yes" : "no",
+ c->coma_bug ? "yes" : "no",
X c->hard_math ? "yes" : "no",
X (c->hard_math && ignore_irq13) ? "yes" : "no",
X c->cpuid_level,
diff -u --recursive --new-file v2.2.7/linux/arch/i386/kernel/smp.c linux/arch/i386/kernel/smp.c
--- v2.2.7/linux/arch/i386/kernel/smp.c Wed Apr 28 11:37:29 1999
+++ linux/arch/i386/kernel/smp.c Mon May 10 10:32:45 1999
@@ -40,10 +40,12 @@
X #include <linux/smp_lock.h>
X #include <linux/init.h>
X #include <asm/mtrr.h>
+#include <asm/msr.h>
X
X #include "irq.h"
X
-extern unsigned long start_kernel;
+#define JIFFIE_TIMEOUT 100
+
X extern void update_one_process( struct task_struct *p,
X unsigned long ticks, unsigned long user,
X unsigned long system, int cpu);
@@ -147,16 +149,7 @@
X */
X #define APIC_DEFAULT_PHYS_BASE 0xfee00000
X
-/*
- * Reads and clears the Pentium Timestamp-Counter
- */
-#define READ_TSC(x) __asm__ __volatile__ ( "rdtsc" \
- :"=a" (((unsigned long*)&(x))[0]), \
- "=d" (((unsigned long*)&(x))[1]))
-
-#define CLEAR_TSC \
- __asm__ __volatile__ ("\t.byte 0x0f, 0x30;\n"::\
- "a"(0x00001000), "d"(0x00001000), "c"(0x10):"memory")
+#define CLEAR_TSC wrmsr(0x10, 0x00001000, 0x00001000)
X
X /*
X * Setup routine for controlling SMP activation
@@ -899,6 +892,7 @@
X * Everything has been set up for the secondary
X * CPUs - they just need to reload everything
X * from the task structure
+ * This function must not return.
X */
X void __init initialize_secondary(void)
X {
@@ -940,7 +934,6 @@
X /*
X * We need an idle process for each processor.
X */
-
X kernel_thread(start_secondary, NULL, CLONE_PID);
X cpucount++;
X
@@ -951,6 +944,8 @@
X idle->processor = i;
X __cpu_logical_map[cpucount] = i;
X cpu_number_map[i] = cpucount;
+ idle->has_cpu = 1; /* we schedule the first task manually */
+ idle->tss.eip = (unsigned long) start_secondary;
X
X /* start_eip had better be page-aligned! */
X start_eip = setup_trampoline();
@@ -1183,6 +1178,7 @@
X /* Must be done before other processors booted */
X mtrr_init_boot_cpu ();
X #endif
+ init_idle();
X /*
X * Initialize the logical to physical CPU number mapping
X * and the per-CPU profiling counter/multiplier
@@ -1657,15 +1653,84 @@
X send_IPI_allbutself(STOP_CPU_VECTOR);
X }
X
-/*
- * this function sends an 'reload MTRR state' IPI to all other CPUs
- * in the system. it goes straight through, completion processing
- * is done on the mttr.c level.
+/* Structure and data for smp_call_function(). This is designed to minimise
+ * static memory requirements. It also looks cleaner.
X */
-
-void smp_send_mtrr(void)
+struct smp_call_function_struct {
+ void (*func) (void *info);
+ void *info;
+ atomic_t unstarted_count;
+ atomic_t unfinished_count;
+ int wait;
+};
+static volatile struct smp_call_function_struct *smp_call_function_data = NULL;
+
+/*
+ * this function sends a 'generic call function' IPI to all other CPUs
+ * in the system.
+ */
+
+int smp_call_function (void (*func) (void *info), void *info, int retry,
+ int wait)
+/* [SUMMARY] Run a function on all other CPUs.
+ <func> The function to run. This must be fast and non-blocking.
+ <info> An arbitrary pointer to pass to the function.
+ <retry> If true, keep retrying until ready.
+ <wait> If true, wait until function has completed on other CPUs.
+ [RETURNS] 0 on success, else a negative status code. Does not return until
+ remote CPUs are nearly ready to execute <<func>> or are or have executed.
+*/
X {
- send_IPI_allbutself(MTRR_CHANGE_VECTOR);
+ unsigned long timeout;
+ struct smp_call_function_struct data;
+ static spinlock_t lock = SPIN_LOCK_UNLOCKED;
+
+ if (retry) {
+ while (1) {
+ if (smp_call_function_data) {
+ schedule (); /* Give a mate a go */
+ continue;
+ }
+ spin_lock (&lock);
+ if (smp_call_function_data) {
+ spin_unlock (&lock); /* Bad luck */
+ continue;
+ }
+ /* Mine, all mine! */
+ break;
+ }
+ }
+ else {
+ if (smp_call_function_data) return -EBUSY;
+ spin_lock (&lock);
+ if (smp_call_function_data) {
+ spin_unlock (&lock);
+ return -EBUSY;
+ }
+ }
+ smp_call_function_data = &data;
+ spin_unlock (&lock);
+ data.func = func;
+ data.info = info;
+ atomic_set (&data.unstarted_count, smp_num_cpus - 1);
+ data.wait = wait;
+ if (wait) atomic_set (&data.unfinished_count, smp_num_cpus - 1);
+ /* Send a message to all other CPUs and wait for them to respond */
+ send_IPI_allbutself (CALL_FUNCTION_VECTOR);
+ /* Wait for response */
+ timeout = jiffies + JIFFIE_TIMEOUT;
+ while ( (atomic_read (&data.unstarted_count) > 0) &&
+ time_before (jiffies, timeout) )
+ barrier ();
+ if (atomic_read (&data.unstarted_count) > 0) {
+ smp_call_function_data = NULL;
+ return -ETIMEDOUT;
+ }
+ if (wait)
+ while (atomic_read (&data.unfinished_count) > 0)
+ barrier ();
+ smp_call_function_data = NULL;
+ return 0;
X }
X
X /*
@@ -1781,6 +1846,7 @@
X local_flush_tlb();
X
X ack_APIC_irq();
+
X }
X
X static void stop_this_cpu (void)
@@ -1803,12 +1869,19 @@
X stop_this_cpu();
X }
X
-void (*mtrr_hook) (void) = NULL;
-
-asmlinkage void smp_mtrr_interrupt(void)
+asmlinkage void smp_call_function_interrupt(void)
X {
- ack_APIC_irq();
- if (mtrr_hook) (*mtrr_hook)();
+ void (*func) (void *info) = smp_call_function_data->func;
+ void *info = smp_call_function_data->info;
+ int wait = smp_call_function_data->wait;
+
+ ack_APIC_irq ();
+ /* Notify initiating CPU that I've grabbed the data and am about to
+ execute the function */
+ atomic_dec (&smp_call_function_data->unstarted_count);
+ /* At this point the structure may be out of scope unless wait==1 */
+ (*func) (info);
+ if (wait) atomic_dec (&smp_call_function_data->unfinished_count);
X }
X
X /*
@@ -1949,7 +2022,7 @@
X /*
X * We wrapped around just now. Let's start:
X */
- READ_TSC(t1);
+ rdtscll(t1);
X tt1=apic_read(APIC_TMCCT);
X
X #define LOOPS (HZ/10)
@@ -1960,7 +2033,7 @@
X wait_8254_wraparound ();
X
X tt2=apic_read(APIC_TMCCT);
- READ_TSC(t2);
+ rdtscll(t2);
X
X /*
X * The APIC bus clock counter is 32 bits only, it
diff -u --recursive --new-file v2.2.7/linux/arch/i386/kernel/time.c linux/arch/i386/kernel/time.c
--- v2.2.7/linux/arch/i386/kernel/time.c Tue Mar 23 14:35:46 1999
+++ linux/arch/i386/kernel/time.c Thu Apr 29 11:53:41 1999
@@ -47,6 +47,7 @@
X #include <asm/io.h>
X #include <asm/irq.h>
X #include <asm/delay.h>
+#include <asm/msr.h>
X
X #include <linux/mc146818rtc.h>
X #include <linux/timex.h>
@@ -83,8 +84,8 @@
X register unsigned long edx asm("dx");
X
X /* Read the Time Stamp Counter */
- __asm__("rdtsc"
- :"=a" (eax), "=d" (edx));
+
+ rdtsc(eax,edx);
X
X /* .. relative to previous jiffy (32 bits is enough) */
X eax -= last_tsc_low; /* tsc_low delta */
@@ -443,7 +444,8 @@
X */
X
X /* read Pentium cycle counter */
- __asm__("rdtsc" : "=a" (last_tsc_low) : : "edx");
+
+ rdtscl(last_tsc_low);
X
X outb_p(0x00, 0x43); /* latch the count ASAP */
X
@@ -566,12 +568,12 @@
X unsigned long endlow, endhigh;
X unsigned long count;
X
- __asm__ __volatile__("rdtsc":"=a" (startlow),"=d" (starthigh));
+ rdtsc(startlow,starthigh);
X count = 0;
X do {
X count++;
X } while ((inb(0x61) & 0x20) == 0);
- __asm__ __volatile__("rdtsc":"=a" (endlow),"=d" (endhigh));
+ rdtsc(endlow,endhigh);
X
X last_tsc_low = endlow;
X
diff -u --recursive --new-file v2.2.7/linux/arch/i386/kernel/visws_apic.c linux/arch/i386/kernel/visws_apic.c
--- v2.2.7/linux/arch/i386/kernel/visws_apic.c Wed Jan 20 23:14:04 1999
+++ linux/arch/i386/kernel/visws_apic.c Thu May 6 16:12:23 1999
@@ -201,11 +201,13 @@


X {
X unsigned int status;

X /* XXX APIC EOI? */


- status = desc->status & ~IRQ_REPLAY;
+ status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING);
X action = NULL;
- if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+ if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
X action = desc->action;
- desc->status = status | IRQ_INPROGRESS;
+ status |= IRQ_INPROGRESS;
+ }
+ desc->status = status;
X }
X spin_unlock(&irq_controller_lock);
X

diff -u --recursive --new-file v2.2.7/linux/arch/m68k/Makefile linux/arch/m68k/Makefile
--- v2.2.7/linux/arch/m68k/Makefile Wed Jan 20 23:14:04 1999
+++ linux/arch/m68k/Makefile Tue May 11 09:57:14 1999
@@ -56,6 +56,11 @@
X CORE_FILES := arch/m68k/kernel/kernel.o arch/m68k/mm/mm.o $(CORE_FILES)
X LIBS += arch/m68k/lib/lib.a
X
+ifdef CONFIG_Q40
+CORE_FILES := $(CORE_FILES) arch/m68k/q40/q40.o
+SUBDIRS := $(SUBDIRS) arch/m68k/q40
+endif
+
X ifdef CONFIG_AMIGA
X CORE_FILES := $(CORE_FILES) arch/m68k/amiga/amiga.o
X SUBDIRS := $(SUBDIRS) arch/m68k/amiga
@@ -81,6 +86,11 @@
X SUBDIRS := $(SUBDIRS) arch/m68k/apollo
X endif
X
+ifdef CONFIG_MVME147
+CORE_FILES := $(CORE_FILES) arch/m68k/mvme147/mvme147.o
+SUBDIRS := $(SUBDIRS) arch/m68k/mvme147
+endif
+
X ifdef CONFIG_MVME16x
X CORE_FILES := $(CORE_FILES) arch/m68k/mvme16x/mvme16x.o
X SUBDIRS := $(SUBDIRS) arch/m68k/mvme16x
@@ -89,6 +99,11 @@
X ifdef CONFIG_BVME6000
X CORE_FILES := $(CORE_FILES) arch/m68k/bvme6000/bvme6000.o
X SUBDIRS := $(SUBDIRS) arch/m68k/bvme6000
+endif
+
+ifdef CONFIG_SUN3X
+CORE_FILES := $(CORE_FILES) arch/m68k/sun3x/sun3x.o
+SUBDIRS := $(SUBDIRS) arch/m68k/sun3x
X endif
X
X ifdef CONFIG_M68040
diff -u --recursive --new-file v2.2.7/linux/arch/m68k/bvme6000/config.c linux/arch/m68k/bvme6000/config.c
--- v2.2.7/linux/arch/m68k/bvme6000/config.c Tue Dec 22 14:16:54 1998
+++ linux/arch/m68k/bvme6000/config.c Tue May 11 09:57:14 1999
@@ -417,10 +417,10 @@
X static void scc_delay (void)
X {
X int n;
- char i;
+ volatile int trash;
X
X for (n = 0; n < 20; n++)
- i = *(volatile char *)0;
+ trash = n;
X }
X
X static void scc_write (char ch)
diff -u --recursive --new-file v2.2.7/linux/arch/m68k/config.in linux/arch/m68k/config.in
--- v2.2.7/linux/arch/m68k/config.in Tue Feb 23 15:21:32 1999
+++ linux/arch/m68k/config.in Tue May 11 09:57:14 1999
@@ -37,6 +37,7 @@
X bool 'Apollo support' CONFIG_APOLLO
X bool 'VME (Motorola and BVM) support' CONFIG_VME
X if [ "$CONFIG_VME" = "y" ]; then
+ bool 'MVME147 support' CONFIG_MVME147
X bool 'MVME162, 166 and 167 support' CONFIG_MVME16x
X bool 'BVME4000 and BVME6000 support' CONFIG_BVME6000
X fi
@@ -44,10 +45,13 @@
X if [ "$CONFIG_HP300" = "y" ]; then
X bool 'DIO bus support' CONFIG_DIO
X fi
+bool 'Sun3x support' CONFIG_SUN3X
+
X define_bool CONFIG_SUN3 n
X if [ "$CONFIG_PCI" = "y" ]; then
X bool 'Backward-compatible /proc/pci' CONFIG_PCI_OLD_PROC
X fi
+bool 'Q40/Q60 support' CONFIG_Q40
X
X comment 'Processor type'
X bool '68020 support' CONFIG_M68020
@@ -94,6 +98,29 @@
X fi
X fi
X bool '/proc/hardware support' CONFIG_PROC_HARDWARE
+
+if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ tristate 'Parallel port support (EXPERIMENTAL, disables old lp driver!)' CONFIG_PARPORT
+ if [ "$CONFIG_PARPORT" != "n" ]; then
+ if [ "$CONFIG_AMIGA" != "n" ]; then
+ dep_tristate ' Amiga builtin port' CONFIG_PARPORT_AMIGA $CONFIG_PARPORT
+ if [ "$CONFIG_ZORRO" != "n" ]; then
+ dep_tristate ' Multiface III parallel port' CONFIG_PARPORT_MFC3 $CONFIG_PARPORT
+ fi
+ fi
+ if [ "$CONFIG_Q40" != "n" ]; then
+ tristate ' Q40 Parallel port' CONFIG_PARPORT
+ if [ "$CONFIG_PARPORT" != "n" ]; then
+ define_bool CONFIG_PARPORT_PC y
+ fi
+ fi
+ fi
+ if [ "$CONFIG_ATARI" == "y" ]; then
+ dep_tristate ' Atari builtin port' CONFIG_PARPORT_ATARI $CONFIG_PARPORT
+ fi
+fi
+
+
X endmenu
X
X source drivers/block/Config.in
@@ -147,6 +174,7 @@
X bool 'A4091 SCSI support' CONFIG_A4091_SCSI
X bool 'WarpEngine SCSI support' CONFIG_WARPENGINE_SCSI
X bool 'Blizzard PowerUP 603e+ SCSI' CONFIG_BLZ603EPLUS_SCSI
+ dep_tristate 'BSC Oktagon SCSI support' CONFIG_OKTAGON_SCSI $CONFIG_SCSI
X bool 'Cyberstorm Mk III SCSI support' CONFIG_CYBERSTORMIII_SCSI
X # bool 'GVP Turbo 040/060 SCSI support' CONFIG_GVP_TURBO_SCSI
X fi
@@ -167,6 +195,10 @@
X fi
X #dep_tristate 'SCSI debugging host adapter' CONFIG_SCSI_DEBUG $CONFIG_SCSI
X
+if [ "$CONFIG_VME" = "y" -a "$CONFIG_MVME147" = "y" ]; then
+ bool 'WD33C93 SCSI driver for MVME147' CONFIG_MVME147_SCSI
+fi
+
X if [ "$CONFIG_VME" = "y" -a "$CONFIG_MVME16x" = "y" ]; then
X bool 'NCR53C710 SCSI driver for MVME16x' CONFIG_MVME16x_SCSI
X fi
@@ -175,6 +207,10 @@
X bool 'NCR53C710 SCSI driver for BVME6000' CONFIG_BVME6000_SCSI
X fi
X
+if [ "$CONFIG_SUN3X" = "y" ]; then
+ bool 'ESP SCSI driver' CONFIG_SUN3X_ESP
+fi
+
X endmenu
X
X fi
@@ -219,6 +255,9 @@
X # bool 'Macintosh (AV) onboard MACE ethernet' CONFIG_MACMACE
X bool 'Macintosh (Quadra) onboard SONIC ethernet' CONFIG_MACSONIC
X fi
+if [ "$CONFIG_VME" = "y" -a "$CONFIG_MVME147" = "y" ]; then
+ tristate 'MVME147 (Lance) Ethernet support' CONFIG_MVME147_NET
+fi
X if [ "$CONFIG_VME" = "y" -a "$CONFIG_MVME16x" = "y" ]; then
X tristate 'MVME16x Ethernet support' CONFIG_MVME16x_NET
X fi
@@ -232,9 +271,17 @@
X tristate 'PAMsNet support' CONFIG_ATARI_PAMSNET
X fi
X fi
+if [ "$CONFIG_SUN3X" = "y" ]; then
+ bool 'Sun3x Lance support' CONFIG_SUNLANCE
+fi
X if [ "$CONFIG_HP300" = "y" ]; then
X bool 'HP on-board LANCE support' CONFIG_HPLANCE
X fi
+if [ "$CONFIG_Q40" = "y" ]; then
+ if [ ! "$CONFIG_PARPORT" = "n" ]; then
+ dep_tristate 'PLIP (parallel port) support' CONFIG_PLIP $CONFIG_PARPORT
+ fi
+fi
X fi
X endmenu
X
@@ -243,6 +290,23 @@
X mainmenu_option next_comment
X comment 'Character devices'
X
+if [ "$CONFIG_Q40" = "y" ]; then
+ tristate 'Q40 Standard/generic serial support' CONFIG_SERIAL
+fi
+
+if [ "$CONFIG_SERIAL" = "y" ]; then
+ bool ' Support for console on serial port' CONFIG_SERIAL_CONSOLE
+ bool 'Extended dumb serial driver options' CONFIG_SERIAL_EXTENDED
+fi
+
+if [ "$CONFIG_SERIAL_EXTENDED" = "y" ]; then
+ bool ' Support more than 4 serial ports' CONFIG_SERIAL_MANY_PORTS
+ bool ' Support for sharing serial interrupts' CONFIG_SERIAL_SHARE_IRQ
+# bool ' Autodetect IRQ - do not yet enable !!' CONFIG_SERIAL_DETECT_IRQ
+ bool ' Support special multiport boards' CONFIG_SERIAL_MULTIPORT
+ bool ' Support the Bell Technologies HUB6 card' CONFIG_HUB6
+fi
+
X if [ "$CONFIG_VME" = "n" ]; then
X define_bool CONFIG_VT y
X if [ "$CONFIG_VT" = "y" ]; then
@@ -254,10 +318,17 @@
X define_bool CONFIG_NVRAM y
X fi
X
-tristate 'Parallel printer support' CONFIG_M68K_PRINTER
-if [ "$CONFIG_ZORRO" = "y" ]; then
- dep_tristate 'Multiface Card III parallel support' CONFIG_MULTIFACE_III_LP $CONFIG_M68K_PRINTER
-fi
+if [ "$CONFIG_PARPORT" = "n" ]; then
+ tristate 'Parallel printer support' CONFIG_M68K_PRINTER
+ if [ "$CONFIG_ZORRO" = "y" ]; then
+ dep_tristate 'Multiface Card III parallel support' CONFIG_MULTIFACE_III_LP $CONFIG_M68K_PRINTER
+ fi
+else
+ dep_tristate 'Parallel printer support' CONFIG_PRINTER $CONFIG_PARPORT
+ if [ "$CONFIG_PRINTER" != "n" ]; then
+ bool ' Support IEEE1284 status readback' CONFIG_PRINTER_READBACK
+ fi
+fi
X if [ "$CONFIG_AMIGA" = "y" ]; then
X tristate 'Amiga mouse support' CONFIG_AMIGAMOUSE
X fi
@@ -280,13 +351,17 @@
X fi
X if [ "$CONFIG_AMIGA" = "y" ]; then
X tristate 'Amiga builtin serial support' CONFIG_AMIGA_BUILTIN_SERIAL
- bool 'Hisoft Whippet PCMCIA serial support' CONFIG_WHIPPET
+ if [ "$CONFIG_AMIGA_PCMCIA" = "y" ]; then
+ tristate 'Hisoft Whippet PCMCIA serial support' CONFIG_WHIPPET_SERIAL
+ fi
X fi
-if [ "$CONFIG_ZORRO" = "y" ]; then
- tristate 'GVP IO-Extender support' CONFIG_GVPIOEXT
- dep_tristate 'GVP IO-Extender parallel printer support' CONFIG_GVPIOEXT_LP $CONFIG_GVPIOEXT
- dep_tristate 'GVP IO-Extender PLIP support' CONFIG_GVPIOEXT_PLIP $CONFIG_GVPIOEXT
- tristate 'Multiface Card III serial support' CONFIG_MULTIFACE_III_TTY
+if [ "$CONFIG_PARPORT" = "n" ]; then
+ if [ "$CONFIG_ZORRO" = "y" ]; then
+ tristate 'GVP IO-Extender support' CONFIG_GVPIOEXT
+ dep_tristate 'GVP IO-Extender parallel printer support' CONFIG_GVPIOEXT_LP $CONFIG_GVPIOEXT
+ dep_tristate 'GVP IO-Extender PLIP support' CONFIG_GVPIOEXT_PLIP $CONFIG_GVPIOEXT
+ tristate 'Multiface Card III serial support' CONFIG_MULTIFACE_III_TTY
+ fi
X fi
X if [ "$CONFIG_MAC" = "y" ]; then
X bool 'Mac SCC serial support' CONFIG_MAC_SCC
@@ -294,18 +369,32 @@
X if [ "$CONFIG_HP300" = "y" -a "$CONFIG_DIO" = "y" ]; then
X tristate 'HP DCA serial support' CONFIG_HPDCA
X fi
+if [ "$CONFIG_SUN3X" = "y" ]; then
+ bool 'Sun3x builtin serial support' CONFIG_SUN3X_ZS
+ if [ "$CONFIG_SUN3X_ZS" = "y" ]; then
+ bool 'Sun keyboard support' CONFIG_SUN_KEYBOARD
+ bool 'Sun mouse support' CONFIG_SUN_MOUSE
+ define_bool CONFIG_SBUS y
+ define_bool CONFIG_SBUSCHAR y
+ define_bool CONFIG_SUN_SERIAL y
+ fi
+fi
X if [ "$CONFIG_AMIGA" = "y" -o "$CONFIG_ATARI" = "y" -o \
- "$CONFIG_MAC" = "y" -o "$CONFIG_HP300" = "y" ]; then
+ "$CONFIG_MAC" = "y" -o "$CONFIG_HP300" = "y" -o \
+ "$CONFIG_SUN3X" = "y" ]; then
X if [ "$CONFIG_ATARI_MFPSER" = "y" -o "$CONFIG_ATARI_SCC" = "y" -o \
X "$CONFIG_ATARI_MIDI" = "y" -o "$CONFIG_MAC_SCC" = "y" -o \
X "$CONFIG_AMIGA_BUILTIN_SERIAL" = "y" -o \
X "$CONFIG_GVPIOEXT" = "y" -o "$CONFIG_MULTIFACE_III_TTY" = "y" -o \
- "$CONFIG_HPDCA" = "y" ]; then
+ "$CONFIG_HPDCA" = "y" -o "$CONFIG_SUN3X_ZS" = "y" ]; then
X bool 'Support for serial port console' CONFIG_SERIAL_CONSOLE
X fi
X fi
X if [ "$CONFIG_VME" = "y" ]; then
X define_bool CONFIG_SERIAL_CONSOLE y
+ if [ "$CONFIG_MVME147" = "y" ]; then
+ bool 'SCC support for MVME147 serial ports' CONFIG_MVME147_SCC
+ fi
X if [ "$CONFIG_MVME16x" = "y" ]; then
X bool 'CD2401 support for MVME166/7 serial ports' CONFIG_SERIAL167
X bool 'SCC support for MVME162 serial ports' CONFIG_MVME162_SCC
diff -u --recursive --new-file v2.2.7/linux/arch/m68k/kernel/entry.S linux/arch/m68k/kernel/entry.S
--- v2.2.7/linux/arch/m68k/kernel/entry.S Wed Jan 20 23:14:04 1999
+++ linux/arch/m68k/kernel/entry.S Tue May 11 09:57:14 1999
@@ -164,8 +164,17 @@
X
X movel %sp,%sp@-
X movel %d0,%sp@- | put vector # on stack
+#if defined(MACH_Q40_ONLY) && defined(CONFIG_BLK_DEV_FD)
+ btstb #4,0xff000000 | Q40 floppy needs very special treatment ...
+ jbeq 1f
+ btstb #3,0xff000004
+ jbeq 1f
+ jbsr SYMBOL_NAME(floppy_hardint)
+ jbra 3f
+1:
+#endif
X jbsr SYMBOL_NAME(process_int)| process the IRQ
- addql #8,%sp | pop parameters off stack
+3: addql #8,%sp | pop parameters off stack
X
X SYMBOL_NAME_LABEL(ret_from_interrupt)
X subql #1,SYMBOL_NAME(local_irq_count)
@@ -295,6 +304,8 @@
X 2: fmovemx %fp0-%fp7,%a0@(TASK_TSS+TSS_FPREG)
X fmoveml %fpcr/%fpsr/%fpiar,%a0@(TASK_TSS+TSS_FPCNTL)
X 3:
+ /* Return previous task in %d1 */
+ movel %curptr,%d1
X
X /* switch to new task (a1 contains new task) */
X movel %a1,%curptr
@@ -320,7 +331,14 @@
X movec %d0,%cacr
X
X /* switch the root pointer */
+#ifdef CPU_M68030_ONLY
+ .chip 68030
+ pmovefd %a1@(TASK_TSS+TSS_CRP),%crp
+ .chip 68k
+ pflush #0,#4
+#else
X pmove %a1@(TASK_TSS+TSS_CRP),%crp
+#endif
X #endif
X
X #if defined(CPU_M68020_OR_M68030) && defined(CPU_M68040_OR_M68060)
diff -u --recursive --new-file v2.2.7/linux/arch/m68k/kernel/head.S linux/arch/m68k/kernel/head.S
--- v2.2.7/linux/arch/m68k/kernel/head.S Wed Jan 20 23:14:04 1999
+++ linux/arch/m68k/kernel/head.S Tue May 11 09:57:14 1999
@@ -23,6 +23,7 @@
X ** 98/04/25 Phil Blundell: added HP300 support
X ** 1998/08/30 David Kilzer: Added support for fbcon_font_desc structures
X ** for linux-2.1.115
+** 9/02/11 Richard Zidlicky: added Q40 support (initial vesion 99/01/01)
X **
X ** This file is subject to the terms and conditions of the GNU General Public
X ** License. See the file README.legal in the main directory of this archive
@@ -303,6 +304,12 @@
X .globl SYMBOL_NAME(availmem)
X .globl SYMBOL_NAME(m68k_pgtable_cachemode)
X .globl SYMBOL_NAME(m68k_supervisor_cachemode)
+#ifdef CONFIG_MVME16x
+.globl SYMBOL_NAME(mvme_bdid_ptr)
+#endif
+#ifdef CONFIG_Q40
+.globl SYMBOL_NAME(q40_mem_cptr)
+#endif
X
X CPUTYPE_040 = 1 /* indicates an 040 */
X CPUTYPE_060 = 2 /* indicates an 060 */
@@ -512,13 +519,15 @@
X #endif
X .endm
X
-
X #define is_not_amiga(lab) cmpl &MACH_AMIGA,%pc@(m68k_machtype); jne lab
X #define is_not_atari(lab) cmpl &MACH_ATARI,%pc@(m68k_machtype); jne lab
X #define is_not_mac(lab) cmpl &MACH_MAC,%pc@(m68k_machtype); jne lab
+#define is_not_mvme147(lab) cmpl &MACH_MVME147,%pc@(m68k_machtype); jne lab
X #define is_not_mvme16x(lab) cmpl &MACH_MVME16x,%pc@(m68k_machtype); jne lab
X #define is_not_bvme6000(lab) cmpl &MACH_BVME6000,%pc@(m68k_machtype); jne lab
X #define is_not_hp300(lab) cmpl &MACH_HP300,%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
X
X #define is_040_or_060(lab) btst &CPUTYPE_0460,%pc@(L(cputype)+3); jne lab
X #define is_not_040_or_060(lab) btst &CPUTYPE_0460,%pc@(L(cputype)+3); jeq lab
@@ -552,9 +561,11 @@
X .long BOOTINFOV_MAGIC
X .long MACH_AMIGA, AMIGA_BOOTI_VERSION
X .long MACH_ATARI, ATARI_BOOTI_VERSION
+ .long MACH_MVME147, MVME147_BOOTI_VERSION
X .long MACH_MVME16x, MVME16x_BOOTI_VERSION
X .long MACH_BVME6000, BVME6000_BOOTI_VERSION
X .long MACH_MAC, MAC_BOOTI_VERSION
+ .long MACH_Q40, Q40_BOOTI_VERSION
X .long 0
X 1: jra SYMBOL_NAME(__start)
X
@@ -859,7 +870,12 @@
X /*
X * 040: Map the 16Meg range physical 0x0 upto logical 0x8000.0000
X */
- mmu_map #0x80000000,#0,#0x01000000,#_PAGE_NOCACHE_S
+ mmu_map #0x80000000,#0,#0x01000000,#_PAGE_NOCACHE_S
+ /*
+ * Map the Zorro III I/O space with transparent translation
+ * for frame buffer memory etc.
+ */
+ mmu_map_tt #1,#0x40000000,#0x20000000,#_PAGE_NOCACHE_S
X
X jbra L(mmu_init_done)
X
@@ -867,7 +883,8 @@
X /*
X * 030: Map the 32Meg range physical 0x0 upto logical 0x8000.0000
X */
- mmu_map #0x80000000,#0,#0x02000000,#_PAGE_NOCACHE030
+ mmu_map #0x80000000,#0,#0x02000000,#_PAGE_NOCACHE030
+ mmu_map_tt #1,#0x40000000,#0x20000000,#_PAGE_NOCACHE030
X
X jbra L(mmu_init_done)
X
@@ -926,6 +943,25 @@
X L(mmu_init_not_atari):
X #endif
X
+#ifdef CONFIG_Q40
+ is_not_q40(L(notq40))
+ /*
+ * add transparent mapping for 0xff00 0000 - 0xffff ffff
+ * non-cached serialized etc..
+ * this includes master chip, DAC, RTC and ISA ports
+ * 0xfe000000-0xfeffffff is for screen and ROM
+ */
+
+ putc 'Q'
+
+ mmu_map_tt #0,#0xfe000000,#0x01000000,#_PAGE_CACHE040W
+ mmu_map_tt #1,#0xff000000,#0x01000000,#_PAGE_NOCACHE_S
+
+ jbra L(mmu_init_done)
+
+L(notq40):
+#endif
+
X #ifdef CONFIG_HP300
X is_not_hp300(L(nothp300))
X
@@ -940,6 +976,24 @@
X
X #endif
X
+#ifdef CONFIG_MVME147
+
+ is_not_mvme147(L(not147))
+
+ /*
+ * On MVME147 we have already created kernel page tables for
+ * 4MB of RAM at address 0, so now need to do a transparent
+ * mapping of the top of memory space. Make it 0.5GByte for now,
+ * so we can access on-board i/o areas.
+ */
+
+ mmu_map_tt #1,#0xe0000000,#0x20000000,#_PAGE_NOCACHE030
+
+ jbra L(mmu_init_done)
+
+L(not147):
+#endif /* CONFIG_MVME147 */
+
X #ifdef CONFIG_MVME16x
X
X is_not_mvme16x(L(not16x))
@@ -965,7 +1019,7 @@
X * 0xffe00000->0xffe1ffff.
X */
X
- mmu_map_tt 1,#0xe0000000,#0x20000000,#_PAGE_NOCACHE_S
+ mmu_map_tt #1,#0xe0000000,#0x20000000,#_PAGE_NOCACHE_S
X
X jbra L(mmu_init_done)
X
@@ -985,7 +1039,7 @@
X * clash with User code virtual address space.
X */
X
- mmu_map_tt 1,#0xe0000000,#0x20000000,#_PAGE_NOCACHE_S
+ mmu_map_tt #1,#0xe0000000,#0x20000000,#_PAGE_NOCACHE_S
X
X jbra L(mmu_init_done)
X
@@ -1052,13 +1106,23 @@
X mmu_map_eq #0x50000000,#0x02000000,%d3
X mmu_map_eq #0x60000000,#0x00400000,%d3
X mmu_map_eq #0x9c000000,#0x00400000,%d3
- mmu_map_tt 1,#0xf8000000,#0x08000000,%d3
+ mmu_map_tt #1,#0xf8000000,#0x08000000,%d3
X
X jbra L(mmu_init_done)
X
X L(mmu_init_not_mac):
X #endif
X
+#ifdef CONFIG_SUN3X
+ is_not_sun3x(L(notsun3x))
+
+ /* setup tt1 for I/O */
+ mmu_map_tt #1,#0x40000000,#0x40000000,#_PAGE_NOCACHE_S
+
+L(notsun3x):
+ jbra L(mmu_init_done)
+#endif
+
X L(mmu_init_done):
X
X putc 'G'
@@ -1214,6 +1278,14 @@
X 1:
X #endif
X
+#ifdef CONFIG_SUN3X
+ is_not_sun3x(1f)
+
+ /* enable copro */
+ oriw #0x4000,0x61000000
+1:
+#endif
+
X /*
X * Fixup the addresses for the kernel pointer table and availmem.
X * Convert them from physical addresses to virtual addresses.
@@ -1780,7 +1852,7 @@
X /* Extract the highest bit set
X */
X bfffo ARG3{#0,#32},%d1
- cmpw #8,%d0
+ cmpw #8,%d1
X jcc L(do_map)
X
X /* And get the mask
@@ -2155,7 +2227,9 @@
X /* Temporary allocate a page table and insert it into the ptr table
X */
X movel %a1@,%d0
- addl #PTR_TABLE_SIZE*4,%a1@
+ /* The 512 should be PAGE_TABLE_SIZE*4, but that violates the
+ alignment restriction for pointer tables on the '0[46]0. */
+ addl #512,%a1@
X orw #_PAGE_TABLE+_PAGE_ACCESSED,%d0
X movel %d0,%a0@
X dputs " (new)"
@@ -2703,6 +2777,31 @@
X L(serial_init_not_mac):
X #endif /* CONFIG_MAC */
X
+#ifdef CONFIG_Q40
+ is_not_q40(2f)
+/* debug output goes into SRAM, so we don't do it unless requested
+ - check for '%LX$' signature in SRAM */
+ lea %pc@(SYMBOL_NAME(q40_mem_cptr)),%a1
+ move.l #0xff020010,%a1@ /* must be inited - also used by debug=mem */
+ move.l #0xff020000,%a1
+ cmp.b #'%',%a1@
+ bne 2f /*nodbg*/
+ addq.w #4,%a1
+ cmp.b #'L',%a1@
+ bne 2f /*nodbg*/
+ addq.w #4,%a1
+ cmp.b #'X',%a1@
+ bne 2f /*nodbg*/
+ addq.w #4,%a1
+ cmp.b #'$',%a1@
+ bne 2f /*nodbg*/
+ /* signature OK */
+ lea %pc@(L(q40_do_debug)),%a1
+ tas %a1@
+/*nodbg: q40_do_debug is 0 by default*/
+2:
+#endif
+
X L(serial_init_done):
X func_return serial_init
X
@@ -2792,6 +2891,15 @@
X 4:
X #endif /* CONFIG_ATARI */
X
+#ifdef CONFIG_MVME147
+ is_not_mvme147(2f)
+1: btst #2,M147_SCC_CTRL_A
+ jeq 1b
+ moveb %d0,M147_SCC_DATA_A
+ jbra L(serial_putc_done)
+2:
+#endif
+
X #ifdef CONFIG_MVME16x
X is_not_mvme16x(2f)
X /*
@@ -2805,7 +2913,7 @@
X moveml %sp@+,%d0-%d7/%a2-%a6
X jbra L(serial_putc_done)
X 2:
-#endif CONFIG_MVME162 | CONFIG_MVME167
+#endif CONFIG_MVME16x
X
X #ifdef CONFIG_BVME6000
X is_not_bvme6000(2f)
@@ -2819,6 +2927,18 @@
X 2:
X #endif
X
+#ifdef CONFIG_Q40
+ is_not_q40(2f)
+ tst.l %pc@(L(q40_do_debug)) /* only debug if requested */
+ beq 2f
+ lea %pc@(SYMBOL_NAME(q40_mem_cptr)),%a1
+ move.l %a1@,%a0
+ move.b %d0,%a0@
+ addq.l #4,%a0
+ move.l %a0,%a1@
+2:
+#endif
+
X L(serial_putc_done):
X func_return serial_putc
X
@@ -3472,6 +3592,10 @@
X L(temp_mmap_mem):
X .long 0
X
+#if defined (CONFIG_MVME147)
+M147_SCC_CTRL_A = 0xfffe3002
+M147_SCC_DATA_A = 0xfffe3003
+#endif
X
X #if defined (CONFIG_BVME6000)
X BVME_SCC_CTRL_A = 0xffb0000b
@@ -3508,4 +3632,10 @@
X #if defined(CONFIG_MVME16x)
X SYMBOL_NAME_LABEL(mvme_bdid_ptr)
X .long 0
+#endif
+#if defined(CONFIG_Q40)
+SYMBOL_NAME_LABEL(q40_mem_cptr)
+ .long 0
+L(q40_do_debug):
+ .long 0
X #endif
diff -u --recursive --new-file v2.2.7/linux/arch/m68k/kernel/ints.c linux/arch/m68k/kernel/ints.c
--- v2.2.7/linux/arch/m68k/kernel/ints.c Tue Jun 23 10:01:21 1998
+++ linux/arch/m68k/kernel/ints.c Tue May 11 09:57:14 1999
@@ -38,6 +38,10 @@
X #include <asm/page.h>
X #include <asm/machdep.h>
X
+#ifdef CONFIG_Q40
+#include <asm/q40ints.h>
+#endif
+
X /* table for system interrupt handlers */
X static irq_handler_t irq_list[SYS_IRQS];
X
@@ -177,14 +181,24 @@
X
X /*
X * Do we need these probe functions on the m68k?
+ *
+ * ... may be usefull with ISA devices


X */
X unsigned long probe_irq_on (void)

X {
+#ifdef CONFIG_Q40
+ if (MACH_IS_Q40)
+ return q40_probe_irq_on();
+#endif
X return 0;
X }
X
X int probe_irq_off (unsigned long irqs)
X {
+#ifdef CONFIG_Q40
+ if (MACH_IS_Q40)
+ return q40_probe_irq_off(irqs);
+#endif
X return 0;
X }
X
diff -u --recursive --new-file v2.2.7/linux/arch/m68k/kernel/m68k_defs.h linux/arch/m68k/kernel/m68k_defs.h
--- v2.2.7/linux/arch/m68k/kernel/m68k_defs.h Thu Jan 7 15:11:36 1999
+++ linux/arch/m68k/kernel/m68k_defs.h Tue May 11 09:57:14 1999
@@ -3,6 +3,47 @@
X */
X
X #define TS_MAGICKEY 0x5a5a5a5a
-#define TS_TSS 482
-#define TS_ESP0 502
-#define TS_FPU 506
+#define TASK_STATE 0
+#define TASK_FLAGS 4
+#define TASK_SIGPENDING 8
+#define TASK_NEEDRESCHED 20
+#define TASK_TSS 470
+#define TASK_MM 622
+#define TSS_KSP 0
+#define TSS_USP 4
+#define TSS_SR 8
+#define TSS_FS 10
+#define TSS_CRP 12
+#define TSS_ESP0 20
+#define TSS_FPREG 24
+#define TSS_FPCNTL 120
+#define TSS_FPSTATE 132
+#define PT_D0 32
+#define PT_ORIG_D0 36
+#define PT_SR 44
+#define PT_VECTOR 50
+#define IRQ_HANDLER 0
+#define IRQ_DEVID 8
+#define IRQ_NEXT 16
+#define STAT_IRQ 120
+#define BIR_TAG 0
+#define BIR_SIZE 2
+#define BIR_DATA 4
+#define FBCON_FONT_DESC_IDX 0
+#define FBCON_FONT_DESC_NAME 4
+#define FBCON_FONT_DESC_WIDTH 8
+#define FBCON_FONT_DESC_HEIGHT 12
+#define FBCON_FONT_DESC_DATA 16
+#define FBCON_FONT_DESC_PREF 20
+#define CUSTOMBASE -2132807680
+#define C_INTENAR 28
+#define C_INTREQR 30
+#define C_INTENA 154
+#define C_INTREQ 156
+#define C_SERDATR 24
+#define C_SERDAT 48
+#define C_SERPER 50
+#define CIAABASE -2134908927
+#define CIABBASE -2134913024
+#define C_PRA 0
+#define ZTWOBASE -2147483648
diff -u --recursive --new-file v2.2.7/linux/arch/m68k/kernel/m68k_ksyms.c linux/arch/m68k/kernel/m68k_ksyms.c
--- v2.2.7/linux/arch/m68k/kernel/m68k_ksyms.c Wed Jan 20 23:14:04 1999
+++ linux/arch/m68k/kernel/m68k_ksyms.c Tue May 11 09:57:14 1999
@@ -18,6 +18,7 @@
X #include <asm/checksum.h>
X #include <asm/hardirq.h>
X #include <asm/softirq.h>
+#include <asm/m68kserial.h>
X
X asmlinkage long long __ashrdi3 (long long, int);
X extern char m68k_debug_device[];
@@ -54,6 +55,8 @@
X EXPORT_SYMBOL(disable_irq);
X EXPORT_SYMBOL(kernel_set_cachemode);
X EXPORT_SYMBOL(kernel_thread);
+EXPORT_SYMBOL(register_serial);
+EXPORT_SYMBOL(unregister_serial);
X
X /* Networking helper routines. */
X EXPORT_SYMBOL(csum_partial_copy);
@@ -69,4 +72,5 @@
X
X EXPORT_SYMBOL_NOVERS(__down_failed);
X EXPORT_SYMBOL_NOVERS(__down_failed_interruptible);
+EXPORT_SYMBOL_NOVERS(__down_failed_trylock);
X EXPORT_SYMBOL_NOVERS(__up_wakeup);
diff -u --recursive --new-file v2.2.7/linux/arch/m68k/kernel/process.c linux/arch/m68k/kernel/process.c
--- v2.2.7/linux/arch/m68k/kernel/process.c Wed Jan 20 23:14:04 1999
+++ linux/arch/m68k/kernel/process.c Tue May 11 09:57:14 1999
@@ -169,15 +169,7 @@
X
X asmlinkage int m68k_vfork(struct pt_regs *regs)
X {
- int child;
- struct semaphore sem = MUTEX_LOCKED;
-
- child = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs);
-
- if (child > 0)
- down(&sem);
-
- return child;
+ return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs);
X }
X
X asmlinkage int m68k_clone(struct pt_regs *regs)
@@ -190,7 +182,7 @@
X newsp = regs->d2;
X if (!newsp)
X newsp = rdusp();
- return do_fork(clone_flags & ~CLONE_VFORK, newsp, regs);
+ return do_fork(clone_flags, newsp, regs);
X }
X
X int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
diff -u --recursive --new-file v2.2.7/linux/arch/m68k/kernel/ptrace.c linux/arch/m68k/kernel/ptrace.c
--- v2.2.7/linux/arch/m68k/kernel/ptrace.c Wed Jan 20 23:14:04 1999
+++ linux/arch/m68k/kernel/ptrace.c Tue May 11 09:57:14 1999
@@ -312,6 +312,7 @@
X asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
X {
X struct task_struct *child;
+ unsigned long flags;
X int ret;
X
X lock_kernel();
@@ -343,21 +344,22 @@
X (current->uid != child->uid) ||
X (current->gid != child->egid) ||
X (current->gid != child->sgid) ||
+ (!cap_issubset(child->cap_permitted, current->cap_permitted)) ||
X (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
X goto out;
X /* the same process cannot be attached many times */
X if (child->flags & PF_PTRACED)
X goto out;
X child->flags |= PF_PTRACED;
- if (child->p_pptr != current) {
- unsigned long flags;
X
- write_lock_irqsave(&tasklist_lock, flags);
+ write_lock_irqsave(&tasklist_lock, flags);
+ if (child->p_pptr != current) {
X REMOVE_LINKS(child);
X child->p_pptr = current;
X SET_LINKS(child);
- write_unlock_irqrestore(&tasklist_lock, flags);
X }
+ write_unlock_irqrestore(&tasklist_lock, flags);
+
X send_sig(SIGSTOP, child, 1);
X ret = 0;
X goto out;
@@ -502,7 +504,6 @@
X }
X
X case PTRACE_DETACH: { /* detach a process that was attached. */
- unsigned long flags;
X long tmp;
X
X ret = -EIO;
diff -u --recursive --new-file v2.2.7/linux/arch/m68k/kernel/setup.c linux/arch/m68k/kernel/setup.c
--- v2.2.7/linux/arch/m68k/kernel/setup.c Wed Jan 20 23:14:04 1999
+++ linux/arch/m68k/kernel/setup.c Tue May 11 09:57:14 1999
@@ -77,10 +77,26 @@
X int (*mach_set_clock_mmss) (unsigned long) = NULL;
X void (*mach_reset)( void );
X long mach_max_dma_address = 0x00ffffff; /* default set to the lower 16MB */
-#if defined(CONFIG_AMIGA_FLOPPY) || defined(CONFIG_ATARI_FLOPPY)
+#if defined(CONFIG_AMIGA_FLOPPY) || defined(CONFIG_ATARI_FLOPPY) || defined(CONFIG_BLK_DEV_FD)
X void (*mach_floppy_setup) (char *, int *) __initdata = NULL;
X void (*mach_floppy_eject) (void) = NULL;
X #endif
+struct serial_struct;
+#ifdef CONFIG_SERIAL
+long serial_rs_init(void);
+int serial_register_serial(struct serial_struct *);
+void serial_unregister_serial(int);
+long ser_console_init(long, long );
+#endif
+#if defined(CONFIG_USERIAL)||defined(CONFIG_BVME6000_SCC)||defined(CONFIG_MVME162_SCC)||defined(CONFIG_HPDCA)||defined(CONFIG_WHIPPET_SERIAL)||defined(CONFIG_MULTIFACE_III_TTY)||defined(CONFIG_GVPIOEXT)||defined(CONFIG_AMIGA_BUILTIN_SERIAL)||defined(CONFIG_MAC_SCC)||defined(CONFIG_ATARI_MIDI)||defined(CONFIG_ATARI_SCC)||defined(CONFIG_ATARI_MFPSER)
+#define M68K_SERIAL
+#endif
+#ifdef M68K_SERIAL
+long m68k_rs_init(void);
+int m68k_register_serial(struct serial_struct *);
+void m68k_unregister_serial(int);
+long m68k_serial_console_init(long, long );
+#endif
X #ifdef CONFIG_HEARTBEAT
X void (*mach_heartbeat) (int) = NULL;
X #endif
@@ -97,15 +113,19 @@
X extern int amiga_parse_bootinfo(const struct bi_record *);
X extern int atari_parse_bootinfo(const struct bi_record *);
X extern int mac_parse_bootinfo(const struct bi_record *);
+extern int q40_parse_bootinfo(const struct bi_record *);
X
X extern void config_amiga(void);
X extern void config_atari(void);
X extern void config_mac(void);
X extern void config_sun3(void);
X extern void config_apollo(void);
+extern void config_mvme147(void);
X extern void config_mvme16x(void);
X extern void config_bvme6000(void);
X extern void config_hp300(void);
+extern void config_q40(void);
+extern void config_sun3x(void);
X
X #define MASK_256K 0xfffc0000
X
@@ -149,6 +169,8 @@
X unknown = atari_parse_bootinfo(record);
X else if (MACH_IS_MAC)
X unknown = mac_parse_bootinfo(record);
+ else if (MACH_IS_Q40)
+ unknown = q40_parse_bootinfo(record);
X else
X unknown = 1;
X }
@@ -258,6 +280,11 @@
X config_apollo();
X break;
X #endif
+#ifdef CONFIG_MVME147
+ case MACH_MVME147:
+ config_mvme147();
+ break;
+#endif
X #ifdef CONFIG_MVME16x
X case MACH_MVME16x:
X config_mvme16x();
@@ -273,6 +300,16 @@
X config_hp300();
X break;
X #endif
+#ifdef CONFIG_Q40
+ case MACH_Q40:
+ config_q40();
+ break;
+#endif
+#ifdef CONFIG_SUN3X
+ case MACH_SUN3X:
+ config_sun3x();
+ break;
+#endif
X default:
X panic ("No configuration setup");
X }
@@ -384,7 +421,52 @@
X return(len);
X }
X
-#if defined(CONFIG_AMIGA_FLOPPY) || defined(CONFIG_ATARI_FLOPPY)
+#if defined(CONFIG_SERIAL) || defined(M68K_SERIAL)
+int rs_init(void)
+{
+#ifdef CONFIG_SERIAL
+ if (MACH_IS_Q40)
+ return serial_rs_init();
+#endif
+#ifdef M68K_SERIAL
+ return m68k_rs_init();
+#endif
+}
+int register_serial(struct serial_struct *p)
+{
+#ifdef CONFIG_SERIAL
+ if (MACH_IS_Q40)
+ return serial_register_serial(p);
+#endif
+#ifdef M68K_SERIAL
+ return m68k_register_serial(p);
+#endif
+}
+void unregister_serial(int i)
+{
+#ifdef CONFIG_SERIAL
+ if (MACH_IS_Q40)
+ serial_unregister_serial(i);
+#endif
+#ifdef M68K_SERIAL
+ m68k_unregister_serial(i);
+#endif
+}
+#ifdef CONFIG_SERIAL_CONSOLE
+long serial_console_init(long kmem_start, long kmem_end)
+{
+#ifdef CONFIG_SERIAL
+ if (MACH_IS_Q40)
+ return ser_console_init(kmem_start, kmem_end);
+#endif
+#if defined(M68K_SERIAL) && defined(CONFIG_SERIAL_CONSOLE)
+ return m68k_serial_console_init(kmem_start, kmem_end);
+#endif
+}
+#endif
+#endif
+
+#if defined(CONFIG_AMIGA_FLOPPY) || defined(CONFIG_ATARI_FLOPPY) || defined(CONFIG_BLK_DEV_FD)
X __initfunc(void floppy_setup(char *str, int *ints))
X {
X if (mach_floppy_setup)
@@ -399,7 +481,7 @@
X #endif
X
X /* for "kbd-reset" cmdline param */
-void __init kbd_reset_setup(char *str, int *ints)
+__initfunc(void kbd_reset_setup(char *str, int *ints))
X {
X }
X
diff -u --recursive --new-file v2.2.7/linux/arch/m68k/kernel/time.c linux/arch/m68k/kernel/time.c
--- v2.2.7/linux/arch/m68k/kernel/time.c Tue Mar 23 14:35:46 1999
+++ linux/arch/m68k/kernel/time.c Tue May 11 09:57:14 1999
@@ -200,5 +200,5 @@
X time_status |= STA_UNSYNC;
X time_maxerror = NTP_PHASE_LIMIT;
X time_esterror = NTP_PHASE_LIMIT;
- sti();
+ write_unlock_irq(&xtime_lock);
X }
diff -u --recursive --new-file v2.2.7/linux/arch/m68k/lib/semaphore.S linux/arch/m68k/lib/semaphore.S
--- v2.2.7/linux/arch/m68k/lib/semaphore.S Sat May 24 09:10:22 1997
+++ linux/arch/m68k/lib/semaphore.S Tue May 11 09:57:14 1999
@@ -32,6 +32,16 @@
X movel (%sp)+,%a0
X rts
X
+ENTRY(__down_failed_trylock)
+ movel %a0,-(%sp)
+ movel %d1,-(%sp)
+ movel %a1,-(%sp)
+ jbsr SYMBOL_NAME(__down_trylock)
+ movel (%sp)+,%a1
+ movel (%sp)+,%d1
+ movel (%sp)+,%a0
+ rts
+
X ENTRY(__up_wakeup)
X moveml %a0/%d0/%d1,-(%sp)
X movel %a1,-(%sp)
diff -u --recursive --new-file v2.2.7/linux/arch/m68k/mm/init.c linux/arch/m68k/mm/init.c
--- v2.2.7/linux/arch/m68k/mm/init.c Wed Jan 20 23:14:04 1999
+++ linux/arch/m68k/mm/init.c Tue May 11 09:57:14 1999
@@ -123,7 +123,7 @@
X unsigned long mm_cachebits = 0;
X #endif
X
-static pte_t *__init kernel_page_table(unsigned long *memavailp)
+__initfunc(static pte_t * kernel_page_table(unsigned long *memavailp))
X {
X pte_t *ptablep;
X
@@ -140,15 +140,19 @@
X
X static pmd_t *last_pgtable __initdata = NULL;
X
-static pmd_t *__init kernel_ptr_table(unsigned long *memavailp)
+__initfunc(static pmd_t * kernel_ptr_table(unsigned long *memavailp))
X {
X if (!last_pgtable) {
X unsigned long pmd, last;
X int i;
X
+ /* Find the last ptr table that was used in head.S and
+ * reuse the remaining space in that page for further
+ * ptr tables.
+ */
X last = (unsigned long)kernel_pg_dir;
X for (i = 0; i < PTRS_PER_PGD; i++) {
- if (!pgd_val(kernel_pg_dir[i]))
+ if (!pgd_present(kernel_pg_dir[i]))
X continue;
X pmd = pgd_page(kernel_pg_dir[i]);
X if (pmd > last)
@@ -175,8 +179,8 @@
X return last_pgtable;
X }
X
-static unsigned long __init
-map_chunk (unsigned long addr, long size, unsigned long *memavailp)
+__initfunc(static unsigned long
+map_chunk (unsigned long addr, long size, unsigned long *memavailp))
X {
X #define PTRTREESIZE (256*1024)
X #define ROOTTREESIZE (32*1024*1024)
@@ -282,8 +286,8 @@
X * paging_init() continues the virtual memory environment setup which
X * was begun by the code in arch/head.S.
X */
-unsigned long __init paging_init(unsigned long start_mem,
- unsigned long end_mem)
+__initfunc(unsigned long paging_init(unsigned long start_mem,
+ unsigned long end_mem))
X {
X int chunk;
X unsigned long mem_avail = 0;
@@ -392,7 +396,7 @@
X return PAGE_ALIGN(free_area_init(start_mem, end_mem));
X }
X
-void __init mem_init(unsigned long start_mem, unsigned long end_mem)
+__initfunc(void mem_init(unsigned long start_mem, unsigned long end_mem))
X {
X int codepages = 0;
X int datapages = 0;
@@ -443,7 +447,7 @@
X /* insert pointer tables allocated so far into the tablelist */
X init_pointer_table((unsigned long)kernel_pg_dir);
X for (i = 0; i < PTRS_PER_PGD; i++) {
- if (pgd_val(kernel_pg_dir[i]))
+ if (pgd_present(kernel_pg_dir[i]))
X init_pointer_table(pgd_page(kernel_pg_dir[i]));
X }
X
diff -u --recursive --new-file v2.2.7/linux/arch/m68k/mm/kmap.c linux/arch/m68k/mm/kmap.c
--- v2.2.7/linux/arch/m68k/mm/kmap.c Wed Jan 20 23:14:04 1999
+++ linux/arch/m68k/mm/kmap.c Tue May 11 09:57:14 1999
@@ -116,6 +116,14 @@
X if (!size || size > physaddr + size)
X return NULL;
X
+#ifdef CONFIG_AMIGA
+ if (MACH_IS_AMIGA) {
+ if ((physaddr >= 0x40000000) && (physaddr + size < 0x60000000)
+ && (cacheflag == IOMAP_NOCACHE_SER))
+ return (void *)physaddr;
+ }
+#endif
+
X #ifdef DEBUG
X printk("ioremap: 0x%lx,0x%lx(%d) - ", physaddr, size, cacheflag);
X #endif
@@ -174,7 +182,7 @@
X }
X }
X
- while (size > 0) {
+ while ((long)size > 0) {
X #ifdef DEBUG
X if (!(virtaddr & (PTRTREESIZE-1)))
X printk ("\npa=%#lx va=%#lx ", physaddr, virtaddr);
@@ -187,7 +195,7 @@
X }
X
X if (CPU_IS_020_OR_030) {
- pmd_dir->pmd[(virtaddr/PTRTREESIZE)&-16] = physaddr;
+ pmd_dir->pmd[(virtaddr/PTRTREESIZE) & 15] = physaddr;
X physaddr += PTRTREESIZE;
X virtaddr += PTRTREESIZE;
X size -= PTRTREESIZE;
@@ -217,7 +225,14 @@
X */
X void iounmap(void *addr)
X {
+#ifdef CONFIG_AMIGA
+ if ((!MACH_IS_AMIGA) ||
+ (((unsigned long)addr < 0x40000000) ||
+ ((unsigned long)addr > 0x60000000)))
+ free_io_area(addr);
+#else
X free_io_area(addr);
+#endif
X }
X
X /*
@@ -232,7 +247,7 @@
X pmd_t *pmd_dir;
X pte_t *pte_dir;
X
- while (size > 0) {
+ while ((long)size > 0) {
X pgd_dir = pgd_offset_k(virtaddr);
X if (pgd_bad(*pgd_dir)) {
X printk("iounmap: bad pgd(%08lx)\n", pgd_val(*pgd_dir));
@@ -242,7 +257,7 @@
X pmd_dir = pmd_offset(pgd_dir, virtaddr);
X
X if (CPU_IS_020_OR_030) {
- int pmd_off = (virtaddr/PTRTREESIZE) & -16;
+ int pmd_off = (virtaddr/PTRTREESIZE) & 15;
X
X if ((pmd_dir->pmd[pmd_off] & _DESCTYPE_MASK) == _PAGE_PRESENT) {
X pmd_dir->pmd[pmd_off] = 0;
@@ -308,7 +323,7 @@
X }
X }
X
- while (size > 0) {
+ while ((long)size > 0) {
X pgd_dir = pgd_offset_k(virtaddr);
X if (pgd_bad(*pgd_dir)) {
X printk("iocachemode: bad pgd(%08lx)\n", pgd_val(*pgd_dir));
@@ -318,7 +333,7 @@
X pmd_dir = pmd_offset(pgd_dir, virtaddr);
X
X if (CPU_IS_020_OR_030) {
- int pmd_off = (virtaddr/PTRTREESIZE) & -16;
+ int pmd_off = (virtaddr/PTRTREESIZE) & 15;
X
X if ((pmd_dir->pmd[pmd_off] & _DESCTYPE_MASK) == _PAGE_PRESENT) {
X pmd_dir->pmd[pmd_off] = (pmd_dir->pmd[pmd_off] &
diff -u --recursive --new-file v2.2.7/linux/arch/m68k/mm/memory.c linux/arch/m68k/mm/memory.c
--- v2.2.7/linux/arch/m68k/mm/memory.c Wed Jan 20 23:14:04 1999
+++ linux/arch/m68k/mm/memory.c Tue May 11 09:57:14 1999
@@ -11,6 +11,7 @@
X #include <linux/types.h>
X #include <linux/malloc.h>
X #include <linux/init.h>
+#include <linux/pagemap.h>
X
X #include <asm/setup.h>
X #include <asm/segment.h>
@@ -93,12 +94,11 @@
X static ptable_desc ptable_list = { &ptable_list, &ptable_list };
X
X #define PD_MARKBITS(dp) (*(unsigned char *)&(dp)->offset)
-#define PD_PAGE(dp) (PAGE_OFFSET + ((dp)->map_nr << PAGE_SHIFT))
X #define PAGE_PD(page) ((ptable_desc *)&mem_map[MAP_NR(page)])
X
X #define PTABLE_SIZE (PTRS_PER_PMD * sizeof(pmd_t))
X
-void __init init_pointer_table(unsigned long ptable)
+__initfunc(void init_pointer_table(unsigned long ptable))
X {
X ptable_desc *dp;
X unsigned long page = ptable & PAGE_MASK;
@@ -166,7 +166,7 @@
X (dp->next = last->next)->prev = dp;
X (dp->prev = last)->next = dp;
X }
- return (pmd_t *) (PD_PAGE(dp) + off);
+ return (pmd_t *) (page_address(dp) + off);
X }
X
X int free_pointer_table (pmd_t *ptable)
@@ -215,8 +215,8 @@
X /* function code match? */
X base = (regval >> 4) & 7;
X mask = ~(regval & 7);
- if ((SUPER_DATA & mask) != (base & mask))
- return( 0 );
+ if (((SUPER_DATA ^ base) & mask) != 0)
+ return 0;
X }
X else {
X /* must not be user-only */
@@ -226,8 +226,8 @@
X
X /* address match? */
X base = regval & 0xff000000;
- mask = ~((regval << 8) & 0xff000000);
- return( (vaddr & mask) == (base & mask) );
+ mask = ~(regval << 8) & 0xff000000;
+ return ((vaddr ^ base) & mask) == 0;
X }
X
X #ifndef CONFIG_SINGLE_MEMORY_CHUNK
diff -u --recursive --new-file v2.2.7/linux/arch/m68k/mvme147/147ints.c linux/arch/m68k/mvme147/147ints.c
--- v2.2.7/linux/arch/m68k/mvme147/147ints.c Wed Dec 31 16:00:00 1969
+++ linux/arch/m68k/mvme147/147ints.c Tue May 11 09:57:14 1999


SHAR_EOF
true || echo 'restore of patch-2.2.8 failed'
fi

echo 'End of part 06'
echo 'File patch-2.2.8 is continued in part 07'
echo 07 > _shar_seq_.tmp

Thomas...@ciw.uni-karlsruhe.de

unread,
May 12, 1999, 3:00:00 AM5/12/99
to
Archive-name: v2.2/patch-2.2.8/part07

#!/bin/sh
# this is part 07 of a 33 - part archive


# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.8 continued
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 07; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.8'
else
echo 'x - continuing with patch-2.2.8'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.8' &&

@@ -0,0 +1,142 @@
+/*
+ * arch/m68k/mvme147/147ints.c
+ *
+ * Copyright (C) 1997 Richard Hirst [ric...@sleepie.demon.co.uk]
+ *
+ * based on amiints.c -- Amiga Linux interrupt handling code
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file README.legal in the main directory of this archive
+ * for more details.
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/traps.h>
+
+static void mvme147_defhand (int irq, void *dev_id, struct pt_regs *fp);
+
+/*
+ * This should ideally be 4 elements only, for speed.
+ */
+
+static struct {
+ void (*handler)(int, void *, struct pt_regs *);
+ unsigned long flags;
+ void *dev_id;
+ const char *devname;
+ unsigned count;
+} irq_tab[256];
+
+/*
+ * void mvme147_init_IRQ (void)
+ *
+ * Parameters: None
+ *
+ * Returns: Nothing
+ *
+ * This function is called during kernel startup to initialize
+ * the mvme147 IRQ handling routines.
+ */
+
+void mvme147_init_IRQ (void)
+{
+ int i;
+
+ for (i = 0; i < 256; i++) {
+ irq_tab[i].handler = mvme147_defhand;
+ irq_tab[i].flags = IRQ_FLG_STD;
+ irq_tab[i].dev_id = NULL;
+ irq_tab[i].devname = NULL;
+ irq_tab[i].count = 0;
+ }
+}
+
+int mvme147_request_irq(unsigned int irq,
+ void (*handler)(int, void *, struct pt_regs *),
+ unsigned long flags, const char *devname, void *dev_id)
+{
+ if (irq > 255) {
+ printk("%s: Incorrect IRQ %d from %s\n", __FUNCTION__, irq, devname);
+ return -ENXIO;
+ }
+ if (!(irq_tab[irq].flags & IRQ_FLG_STD)) {
+ if (irq_tab[irq].flags & IRQ_FLG_LOCK) {
+ printk("%s: IRQ %d from %s is not replaceable\n",
+ __FUNCTION__, irq, irq_tab[irq].devname);
+ return -EBUSY;
+ }
+ if (flags & IRQ_FLG_REPLACE) {
+ printk("%s: %s can't replace IRQ %d from %s\n",
+ __FUNCTION__, devname, irq, irq_tab[irq].devname);


+ return -EBUSY;
+ }
+ }

+ irq_tab[irq].handler = handler;
+ irq_tab[irq].flags = flags;
+ irq_tab[irq].dev_id = dev_id;
+ irq_tab[irq].devname = devname;
+ return 0;
+}
+
+void mvme147_free_irq(unsigned int irq, void *dev_id)
+{
+ if (irq > 255) {
+ printk("%s: Incorrect IRQ %d\n", __FUNCTION__, irq);
+ return;
+ }
+ if (irq_tab[irq].dev_id != dev_id)
+ printk("%s: Removing probably wrong IRQ %d from %s\n",
+ __FUNCTION__, irq, irq_tab[irq].devname);
+
+ irq_tab[irq].handler = mvme147_defhand;
+ irq_tab[irq].flags = IRQ_FLG_STD;
+ irq_tab[irq].dev_id = NULL;
+ irq_tab[irq].devname = NULL;
+}
+
+void mvme147_process_int (unsigned long vec, struct pt_regs *fp)
+{
+ if (vec > 255)
+ printk ("mvme147_process_int: Illegal vector %ld\n", vec);
+ else
+ {
+ irq_tab[vec].count++;
+ irq_tab[vec].handler(vec, irq_tab[vec].dev_id, fp);
+ }
+}
+
+int mvme147_get_irq_list (char *buf)
+{
+ int i, len = 0;
+
+ for (i = 0; i < 256; i++) {
+ if (irq_tab[i].count)
+ len += sprintf (buf+len, "Vec 0x%02x: %8d %s\n",
+ i, irq_tab[i].count,
+ irq_tab[i].devname ? irq_tab[i].devname : "free");
+ }
+ return len;
+}
+
+
+static void mvme147_defhand (int irq, void *dev_id, struct pt_regs *fp)
+{
+ printk ("Unknown interrupt 0x%02x\n", irq);
+}
+
+void mvme147_enable_irq (unsigned int irq)
+{
+}
+
+
+void mvme147_disable_irq (unsigned int irq)
+{
+}
+
diff -u --recursive --new-file v2.2.7/linux/arch/m68k/mvme147/Makefile linux/arch/m68k/mvme147/Makefile
--- v2.2.7/linux/arch/m68k/mvme147/Makefile Wed Dec 31 16:00:00 1969
+++ linux/arch/m68k/mvme147/Makefile Tue May 11 09:57:14 1999
@@ -0,0 +1,14 @@
+#
+# Makefile for Linux arch/m68k/mvme147 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).
+#
+
+O_TARGET := mvme147.o
+O_OBJS := config.o 147ints.o
+
+
+include $(TOPDIR)/Rules.make
+
diff -u --recursive --new-file v2.2.7/linux/arch/m68k/mvme147/config.c linux/arch/m68k/mvme147/config.c
--- v2.2.7/linux/arch/m68k/mvme147/config.c Wed Dec 31 16:00:00 1969
+++ linux/arch/m68k/mvme147/config.c Tue May 11 09:57:14 1999
@@ -0,0 +1,240 @@
+/*
+ * arch/m68k/mvme147/config.c
+ *
+ * Copyright (C) 1996 Dave Frascone [ch...@mindspring.com]
+ * Cloned from Richard Hirst [ric...@sleepie.demon.co.uk]
+ *
+ * Based on:
+ *
+ * Copyright (C) 1993 Hamish Macdonald
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file README.legal in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/config.h>
+#include <stdarg.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/kd.h>
+#include <linux/tty.h>
+#include <linux/console.h>
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <linux/major.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/setup.h>
+#include <asm/irq.h>
+#include <asm/traps.h>
+#include <asm/machdep.h>
+#include <asm/mvme147hw.h>
+
+
+extern void mvme147_process_int (int level, struct pt_regs *regs);
+extern void mvme147_init_IRQ (void);
+extern void mvme147_free_irq (unsigned int, void *);
+extern int mvme147_get_irq_list (char *);
+extern void mvme147_enable_irq (unsigned int);
+extern void mvme147_disable_irq (unsigned int);
+static void mvme147_get_model(char *model);
+static int mvme147_get_hardware_list(char *buffer);
+extern int mvme147_request_irq (unsigned int irq, void (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id);
+extern void mvme147_sched_init(void (*handler)(int, void *, struct pt_regs *));
+extern int mvme147_keyb_init(void);
+extern int mvme147_kbdrate (struct kbd_repeat *);
+extern unsigned long mvme147_gettimeoffset (void);
+extern void mvme147_gettod (int *year, int *mon, int *day, int *hour,
+ int *min, int *sec);
+extern int mvme147_hwclk (int, struct hwclk_time *);
+extern int mvme147_set_clock_mmss (unsigned long);
+extern void mvme147_check_partition (struct gendisk *hd, unsigned int dev);
+extern void mvme147_reset (void);
+extern void mvme147_waitbut(void);
+
+
+static int bcd2int (unsigned char b);
+
+/* Save tick handler routine pointer, will point to do_timer() in
+ * kernel/sched.c, called via mvme147_process_int() */
+
+void (*tick_handler)(int, void *, struct pt_regs *);
+
+
+int mvme147_kbdrate (struct kbd_repeat *k)


+{
+ return 0;
+}

+
+void mvme147_reset()
+{
+ printk ("\r\n\nCalled mvme147_reset\r\n");
+ m147_pcc->watchdog = 0x0a; /* Clear timer */
+ m147_pcc->watchdog = 0xa5; /* Enable watchdog - 100ms to reset */
+ while (1)
+ ;
+}
+
+static void mvme147_get_model(char *model)
+{
+ sprintf(model, "Motorola MVME147");
+}
+
+
+static int mvme147_get_hardware_list(char *buffer)
+{
+ *buffer = '\0';


+
+ return 0;
+}

+
+
+__initfunc(void config_mvme147(void))
+{
+ mach_sched_init = mvme147_sched_init;
+ mach_keyb_init = mvme147_keyb_init;
+ mach_kbdrate = mvme147_kbdrate;
+ mach_init_IRQ = mvme147_init_IRQ;
+ mach_gettimeoffset = mvme147_gettimeoffset;
+ mach_gettod = mvme147_gettod;
+ mach_hwclk = mvme147_hwclk;
+ mach_set_clock_mmss = mvme147_set_clock_mmss;
+ mach_reset = mvme147_reset;
+ mach_free_irq = mvme147_free_irq;
+ mach_process_int = mvme147_process_int;
+ mach_get_irq_list = mvme147_get_irq_list;
+ mach_request_irq = mvme147_request_irq;
+ enable_irq = mvme147_enable_irq;
+ disable_irq = mvme147_disable_irq;
+ mach_get_model = mvme147_get_model;
+ mach_get_hardware_list = mvme147_get_hardware_list;
+}
+
+
+/* Using pcc tick timer 1 */
+
+static void mvme147_timer_int (int irq, void *dev_id, struct pt_regs *fp)
+{
+ m147_pcc->t1_int_cntrl = PCC_TIMER_INT_CLR;
+ m147_pcc->t1_int_cntrl = PCC_INT_ENAB|PCC_LEVEL_TIMER1;
+ tick_handler(irq, dev_id, fp);
+}
+
+
+void mvme147_sched_init (void (*timer_routine)(int, void *, struct pt_regs *))
+{
+ tick_handler = timer_routine;
+ request_irq (PCC_IRQ_TIMER1, mvme147_timer_int,
+ IRQ_FLG_REPLACE, "timer 1", NULL);
+
+ /* Init the clock with a value */
+ /* our clock goes off every 6.25us */
+ m147_pcc->t1_preload = PCC_TIMER_PRELOAD;
+ m147_pcc->t1_cntrl = 0x0; /* clear timer */
+ m147_pcc->t1_cntrl = 0x3; /* start timer */
+ m147_pcc->t1_int_cntrl = PCC_TIMER_INT_CLR; /* clear pending ints */
+ m147_pcc->t1_int_cntrl = PCC_INT_ENAB|PCC_LEVEL_TIMER1;
+}
+
+/* This is always executed with interrupts disabled. */
+/* XXX There are race hazards in this code XXX */
+unsigned long mvme147_gettimeoffset (void)
+{
+ volatile unsigned short *cp = (volatile unsigned short *)0xfffe1012;
+ unsigned short n;
+
+ n = *cp;
+ while (n != *cp)
+ n = *cp;
+
+ n -= PCC_TIMER_PRELOAD;
+ return (unsigned long)n * 25 / 4;
+}
+
+extern void mvme147_gettod (int *year, int *mon, int *day, int *hour,
+ int *min, int *sec)
+{
+ m147_rtc->ctrl = RTC_READ;
+ *year = bcd2int (m147_rtc->bcd_year);
+ *mon = bcd2int (m147_rtc->bcd_mth);
+ *day = bcd2int (m147_rtc->bcd_dom);
+ *hour = bcd2int (m147_rtc->bcd_hr);
+ *min = bcd2int (m147_rtc->bcd_min);
+ *sec = bcd2int (m147_rtc->bcd_sec);
+ m147_rtc->ctrl = 0;
+}
+
+static int bcd2int (unsigned char b)
+{
+ return ((b>>4)*10 + (b&15));
+}
+
+int mvme147_hwclk(int op, struct hwclk_time *t)


+{
+ return 0;
+}

+
+int mvme147_set_clock_mmss (unsigned long nowtime)


+{
+ return 0;
+}

+
+int mvme147_keyb_init (void)


+{
+ return 0;
+}

+
+/*------------------- Serial console stuff ------------------------*/
+
+void m147_scc_write(struct console *co, const char *str, unsigned cnt);
+
+
+void mvme147_init_console_port (struct console *co, int cflag)
+{
+ co->write = m147_scc_write;
+}
+
+
+static void scc_delay (void)
+{
+ int n;
+ volatile int trash;
+
+ for (n = 0; n < 20; n++)
+ trash = n;
+}
+
+static void scc_write (char ch)
+{
+ volatile char *p = (volatile char *)M147_SCC_A_ADDR;
+
+ do {
+ scc_delay();
+ }
+ while (!(*p & 4));
+ scc_delay();
+ *p = 8;
+ scc_delay();
+ *p = ch;
+}
+
+
+void m147_scc_write (struct console *co, const char *str, unsigned count)


+{
+ unsigned long flags;
+

+ save_flags(flags);
+ cli();
+
+ while (count--)
+ {
+ if (*str == '\n')
+ scc_write ('\r');
+ scc_write (*str++);
+ }
+ restore_flags(flags);
+}
+
diff -u --recursive --new-file v2.2.7/linux/arch/m68k/mvme16x/config.c linux/arch/m68k/mvme16x/config.c
--- v2.2.7/linux/arch/m68k/mvme16x/config.c Tue Jun 23 10:01:21 1998
+++ linux/arch/m68k/mvme16x/config.c Tue May 11 09:57:14 1999
@@ -335,10 +335,10 @@


X static void scc_delay (void)
X {
X int n;
- char i;
+ volatile int trash;
X
X for (n = 0; n < 20; n++)
- i = *(volatile char *)0;
+ trash = n;
X }
X
X static void scc_write (char ch)

diff -u --recursive --new-file v2.2.7/linux/arch/m68k/q40/Makefile linux/arch/m68k/q40/Makefile
--- v2.2.7/linux/arch/m68k/q40/Makefile Wed Dec 31 16:00:00 1969
+++ linux/arch/m68k/q40/Makefile Tue May 11 09:57:14 1999
@@ -0,0 +1,14 @@
+#
+# Makefile for Linux arch/m68k/q40 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 := q40.o
+O_OBJS := config.o q40ints.o
+
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.2.7/linux/arch/m68k/q40/README linux/arch/m68k/q40/README
--- v2.2.7/linux/arch/m68k/q40/README Wed Dec 31 16:00:00 1969
+++ linux/arch/m68k/q40/README Tue May 11 09:57:14 1999
@@ -0,0 +1,121 @@
+Linux for the Q40
+=================
+
+You may try http://www.geocities.com/SiliconValley/Bay/2602/ for
+some up to date information. Booter and other tools will be also
+available from this place and ftp.uni-erlangen.de/linux/680x0/q40/
+and mirrors.
+
+Hints to documentation usually refer to the linux source tree in
+/usr/src/linux unless URL given.
+
+It seems IRQ unmasking can't be safely done on a Q40. Autoprobing is
+not yet implemented - do not try it! (See below)
+
+For a list of kernel commandline options read the documentation for the
+particular device drivers.
+
+The floppy imposes a very high interrupt load on the CPU, approx 30K/s.
+When something blocks interrupts (HD) it will loose some of them, so far
+this is not known to have caused any data loss. On hihgly loaded systems
+it can make the floppy very slow. Other Q40 OS' simply poll the floppy
+for this reason - something that can't be done in Linux.
+Only possible cure is getting a 82072 contoler with fifo instead of
+the 8272A
+
+drivers used by the Q40, appart from the very obvious (console etc.):
+ drivers/char/q40_keyb.c # use PC keymaps for national keyboards
+ serial.c # normal PC driver - any speed
+ lp.c # printer driver
+ char/joystick/* # most of this should work
+ block/q40ide.c # startup for ide
+ ide* # see Documentation/ide.txt
+ floppy.c # normal PC driver, DMA emu in asm/floppy.h
+ # and arch/m68k/kernel/entry.S
+ # see drivers/block/README.fd
+ video/q40fb.c
+ misc/parport_pc.c
+
+Various other PC drivers can be enabled simply by adding them to
+arch/m68k/config.in, especially 8 bit devices should be without any
+problems. For cards using 16bit io/mem more care is required, like
+checking byteorder issues, hacking memcpy_*_io etc.
+
+
+Debugging
+=========
+
+Upon startup the kernel will usually output "ABCQGHIJ" into the SRAM,
+preceded by the booter signature. This is a trace just in case something
+went wrong during earliest setup stages.
+*Changed* to preserve SRAM contents by default, this is only done when
+requested - SRAM must start with '%LX$' signature to do this. '-d' option
+to 'lxx' loader enables this.
+
+SRAM can also be used as additional console device, use debug=mem.
+This will save kernel startup msgs into SRAM, the screen will display
+only the penguin - and shell prompt if it gets that far..
+
+Serial console works and can also be used for debugging, provided serial
+initialisation works.
+
+Most problems seem to be caused by fawlty or badly configured io-cards or
+harddrives anyway..there are so many things that can go wrong here.
+Make sure to configure the parallel port as SPP for first testing..the
+Q40 may have trouble with parallel interrupts.
+
+
+Q40 Hardware Description
+========================
+
+This is just an overview, see asm-m68k/* for details ask if you have any
+questions.
+
+The Q40 consists of a 68040@40 MHz, 1MB video RAM, up to 32MB RAM, AT-style
+keyboard interface, 1 Programmable LED, 2 8bit DACs and up to 1MB ROM, 1MB
+shadow ROM.
+
+Most interfacing like floppy, hd, serial, parallel ports is done via ISA
+slots. The ISA io and mem range is mapped (sparse&byteswapped!) into separate
+regions of the memory.
+The main interrupt register IIRQ_REG will indicate whether an IRQ was internal
+or from some ISA devices, EIRQ_REG can distinguish up to 8 ISA IRQs.
+
+The Q40 custom chip is programmable to provide 2 periodic timers:
+ - 50 or 200 Hz - level 2, !!THIS CANT BE DISABLED!!
+ - 10 or 20 KHz - level 4 (and possibly 6 - hardware decoding..)
+
+Linux uses the 200 Hz interrupt for timer and beep by default.
+
+
+Interrupts
+==========
+
+q40 master chip handles only level triggered interrupts :-((
+further limitation is no disabling etc. Unless someone finds
+some ingenious clue this means autoprobing will never work.
+Parallel port interrupts cause most trouble..
+
+IRQ sharing is not yet implemented.
+
+
+Keyboard
+========
+
+q40 receives AT make/break codes from the keyboard, these are translated to
+the PC scancodes x86 Linux uses. So by theory every national keyboard should
+work just by loading the apropriate x86 keytable - see any national-HOWTO.
+
+Unfortunately the AT->PC translation isn't quite trivial and even worse, my
+documentation of it is absolutely minimal - thus some exotic keys may not
+behave exactly as expected.
+
+There is still hope that it can be fixed completely though. If you encounter
+problems, email me idealy this:
+ - exact keypress/release sequence
+ - 'showkey -s' run on q40, non-X session
+ - 'showkey -s' run on a PC, non-X session
+ - AT codes as displayed by the q40 debuging ROM
+btw if the showkey output from PC and Q40 doesn't differ then you have some
+classic configuration problem - don't send me anything in this case
+
diff -u --recursive --new-file v2.2.7/linux/arch/m68k/q40/config.c linux/arch/m68k/q40/config.c
--- v2.2.7/linux/arch/m68k/q40/config.c Wed Dec 31 16:00:00 1969
+++ linux/arch/m68k/q40/config.c Tue May 11 09:57:14 1999
@@ -0,0 +1,425 @@
+/*
+ * arch/m68k/q40/config.c
+ *
+ * originally based on:
+ *
+ * linux/bvme/config.c
+ *
+ * Copyright (C) 1993 Hamish Macdonald
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file README.legal in the main directory of this archive
+ * for more details.
+ */
+
+#include <stdarg.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/kd.h>
+#include <linux/tty.h>
+#include <linux/console.h>
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <linux/major.h>
+
+#include <asm/bootinfo.h>
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/setup.h>
+#include <asm/irq.h>
+#include <asm/traps.h>
+#include <asm/machdep.h>
+#include <asm/q40_master.h>
+#include <asm/keyboard.h>
+
+extern void fd_floppy_eject(void);
+extern void fd_floppy_setup(char *str, int *ints);
+
+extern void q40_process_int (int level, struct pt_regs *regs);
+extern void (*q40_sys_default_handler[]) (int, void *, struct pt_regs *); /* added just for debugging */
+extern void q40_init_IRQ (void);
+extern void q40_free_irq (unsigned int, void *);
+extern int q40_get_irq_list (char *);
+extern void q40_enable_irq (unsigned int);
+extern void q40_disable_irq (unsigned int);
+static void q40_get_model(char *model);
+static int q40_get_hardware_list(char *buffer);
+extern int q40_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id);
+extern void q40_sched_init(void (*handler)(int, void *, struct pt_regs *));
+extern int q40_keyb_init(void);
+extern int q40_kbdrate (struct kbd_repeat *);
+extern unsigned long q40_gettimeoffset (void);
+extern void q40_gettod (int *year, int *mon, int *day, int *hour,
+ int *min, int *sec);
+extern int q40_hwclk (int, struct hwclk_time *);
+extern int q40_set_clock_mmss (unsigned long);
+extern void q40_reset (void);
+extern void q40_waitbut(void);
+void q40_set_vectors (void);
+extern void (*kd_mksound)(unsigned int, unsigned int);
+void q40_mksound(unsigned int /*freq*/, unsigned int /*ticks*/ );
+
+extern char *saved_command_line;
+extern char m68k_debug_device[];
+static void q40_mem_console_write(struct console *co, const char *b,
+ unsigned int count);
+
+static int ql_ticks=0;
+static int sound_ticks=0;
+
+static unsigned char bcd2bin (unsigned char b);
+static unsigned char bin2bcd (unsigned char b);
+
+static int q40_wait_key(struct console *co){return 0;}
+static struct console q40_console_driver = {
+ "debug",
+ NULL, /* write */
+ NULL, /* read */
+ NULL, /* device */
+ q40_wait_key, /* wait_key */
+ NULL, /* unblank */
+ NULL, /* setup */
+ CON_PRINTBUFFER,
+ -1,
+ 0,
+ NULL
+};
+
+
+/* Save tick handler routine pointer, will point to do_timer() in
+ * kernel/sched.c */
+
+/* static void (*tick_handler)(int, void *, struct pt_regs *); */
+
+
+/* early debugging function:*/
+extern char *q40_mem_cptr; /*=(char *)0xff020000;*/
+static int _cpleft;
+
+static void q40_mem_console_write(struct console *co, const char *s,
+ unsigned int count)
+{
+ char *p=(char *)s;
+
+ if (count<_cpleft)
+ while (count-- >0){
+ *q40_mem_cptr=*p++;
+ q40_mem_cptr+=4;
+ _cpleft--;
+ }
+}
+#if 0
+void printq40(char *str)
+{
+ int l=strlen(str);
+ char *p=q40_mem_cptr;
+
+ while (l-- >0 && _cpleft-- >0)
+ {
+ *p=*str++;
+ p+=4;
+ }
+ q40_mem_cptr=p;
+}
+#endif
+
+#if 0
+int q40_kbdrate (struct kbd_repeat *k)


+{
+ return 0;
+}

+#endif
+
+void q40_reset()
+{
+
+ printk ("\n\n*******************************************\n"
+ "Called q40_reset : press the RESET button!! \n");
+ printk( "*******************************************\n");
+
+ while(1)
+ ;
+}
+
+static void q40_get_model(char *model)
+{
+ sprintf(model, "Q40");
+}
+
+
+/* No hardware options on Q40? */
+
+static int q40_get_hardware_list(char *buffer)
+{
+ *buffer = '\0';
+ return 0;
+}
+
+
+__initfunc(void config_q40(void))
+{
+ mach_sched_init = q40_sched_init; /* ok */
+ /*mach_kbdrate = q40_kbdrate;*/ /* unneeded ?*/
+ mach_keyb_init = q40_keyb_init; /* OK */
+ mach_init_IRQ = q40_init_IRQ;
+ mach_gettimeoffset = q40_gettimeoffset;
+ mach_gettod = q40_gettod;
+ mach_hwclk = q40_hwclk;
+ mach_set_clock_mmss = q40_set_clock_mmss;
+/* mach_mksound = q40_mksound; */
+ mach_reset = q40_reset; /* use reset button instead !*/
+ mach_free_irq = q40_free_irq;
+ mach_process_int = q40_process_int;
+ mach_get_irq_list = q40_get_irq_list;
+ mach_request_irq = q40_request_irq;
+ enable_irq = q40_enable_irq;
+ disable_irq = q40_disable_irq;
+ mach_default_handler = &q40_sys_default_handler;
+ mach_get_model = q40_get_model; /* no use..*/
+ mach_get_hardware_list = q40_get_hardware_list; /* no use */
+ kd_mksound = q40_mksound;
+ /*mach_kbd_leds = q40kbd_leds;*/
+#ifdef CONFIG_MAGIC_SYSRQ
+ mach_sysrq_key = 0x54;
+#endif
+ conswitchp = &dummy_con;
+#ifdef CONFIG_BLK_DEV_FD
+ mach_floppy_setup = fd_floppy_setup;
+ mach_floppy_eject = fd_floppy_eject;
+ /**/
+#endif
+
+ mach_max_dma_address = 0; /* no DMA at all */
+
+
+/* userfull for early debuging stages writes kernel messages into SRAM */
+
+ if (!strncmp( m68k_debug_device,"mem",3 ))
+ {
+ /*printk("using NVRAM debug, q40_mem_cptr=%p\n",q40_mem_cptr);*/
+ _cpleft=2000-((long)q40_mem_cptr-0xff020000)/4;
+ q40_console_driver.write = q40_mem_console_write;
+ register_console(&q40_console_driver);
+ }
+}
+
+
+int q40_parse_bootinfo(const struct bi_record *rec)
+{
+ return 1; /* unknown */
+}
+
+#define DAC_LEFT ((unsigned char *)0xff008000)
+#define DAC_RIGHT ((unsigned char *)0xff008004)
+void q40_mksound(unsigned int hz, unsigned int ticks)
+{
+ /* for now ignore hz, except that hz==0 switches off sound */
+ /* simply alternate the ampl 0-255-0-.. at 200Hz */
+ if (hz==0)
+ {
+ if (sound_ticks)
+ sound_ticks=1; /* atomic - no irq spinlock used */
+
+ *DAC_LEFT=0;
+ *DAC_RIGHT=0;
+
+ return;
+ }
+ /* sound itself is done in q40_timer_int */
+ if (sound_ticks == 0) sound_ticks=1000; /* pretty long beep */
+ sound_ticks=ticks<<1;
+}
+
+static void (*q40_timer_routine)(int, void *, struct pt_regs *);
+
+static void q40_timer_int (int irq, void *dev_id, struct pt_regs *fp)
+{
+#if (HZ==10000)
+ master_outb(-1,SAMPLE_CLEAR_REG);
+#else /* must be 50 or 100 */
+ master_outb(-1,FRAME_CLEAR_REG);
+#endif
+
+#if (HZ==100)
+ ql_ticks = ql_ticks ? 0 : 1;
+ if (sound_ticks)
+ {
+ unsigned char sval=(sound_ticks & 1) ? 0 : 255;
+ sound_ticks--;
+ *DAC_LEFT=sval;
+ *DAC_RIGHT=sval;
+ }
+ if (ql_ticks) return;
+#endif
+ q40_timer_routine(irq, dev_id, fp);
+}
+
+
+void q40_sched_init (void (*timer_routine)(int, void *, struct pt_regs *))
+{
+ int timer_irq;
+
+ q40_timer_routine = timer_routine;
+
+#if (HZ==10000)
+ timer_irq=Q40_IRQ_TIMER;
+#else
+ timer_irq=Q40_IRQ_FRAME;
+#endif
+
+ /*printk("registering sched/timer IRQ %d\n", timer_irq);*/
+
+ if (request_irq(timer_irq, q40_timer_int, 0,
+ "timer", q40_timer_int))
+ panic ("Couldn't register timer int");
+
+#if (HZ==10000)
+ master_outb(SAMPLE_LOW,SAMPLE_RATE_REG);
+ master_outb(-1,SAMPLE_CLEAR_REG);
+ master_outb(1,SAMPLE_ENABLE_REG);
+#else
+ master_outb(-1,FRAME_CLEAR_REG); /* not necessary ? */
+#if (HZ==100)
+ master_outb( 1,FRAME_RATE_REG);
+#endif
+#endif
+}
+
+
+unsigned long q40_gettimeoffset (void)
+{
+#if (HZ==100)
+ return 5000*(ql_ticks!=0);
+#else
+ return 0;
+#endif
+}
+
+extern void q40_gettod (int *year, int *mon, int *day, int *hour,
+ int *min, int *sec)
+{
+ RTC_CTRL |= RTC_READ;
+ *year = bcd2bin (RTC_YEAR);
+ *mon = bcd2bin (RTC_MNTH)-1;
+ *day = bcd2bin (RTC_DATE);
+ *hour = bcd2bin (RTC_HOUR);
+ *min = bcd2bin (RTC_MINS);
+ *sec = bcd2bin (RTC_SECS);
+ RTC_CTRL &= ~(RTC_READ);
+
+}
+
+static unsigned char bcd2bin (unsigned char b)
+{
+ return ((b>>4)*10 + (b&15));
+}
+
+static unsigned char bin2bcd (unsigned char b)
+{
+ return (((b/10)*16) + (b%10));
+}
+
+
+/*
+ * Looks like op is non-zero for setting the clock, and zero for
+ * reading the clock.
+ *
+ * struct hwclk_time {
+ * unsigned sec; 0..59
+ * unsigned min; 0..59
+ * unsigned hour; 0..23
+ * unsigned day; 1..31
+ * unsigned mon; 0..11
+ * unsigned year; 00...
+ * int wday; 0..6, 0 is Sunday, -1 means unknown/don't set
+ * };
+ */
+
+int q40_hwclk(int op, struct hwclk_time *t)
+{
+ if (op)
+ { /* Write.... */
+ RTC_CTRL |= RTC_WRITE;
+
+ RTC_SECS = bin2bcd(t->sec);
+ RTC_MINS = bin2bcd(t->min);
+ RTC_HOUR = bin2bcd(t->hour);
+ RTC_DATE = bin2bcd(t->day);
+ RTC_MNTH = bin2bcd(t->mon + 1);
+ RTC_YEAR = bin2bcd(t->year%100);
+ if (t->wday >= 0)
+ RTC_DOW = bin2bcd(t->wday+1);
+
+ RTC_CTRL &= ~(RTC_WRITE);
+ }
+ else
+ { /* Read.... */
+ RTC_CTRL |= RTC_READ;
+
+ t->year = bcd2bin (RTC_YEAR);
+ t->mon = bcd2bin (RTC_MNTH)-1;
+ t->day = bcd2bin (RTC_DATE);
+ t->hour = bcd2bin (RTC_HOUR);
+ t->min = bcd2bin (RTC_MINS);
+ t->sec = bcd2bin (RTC_SECS);
+
+ RTC_CTRL &= ~(RTC_READ);
+
+ if (t->year < 70)
+ t->year += 100;
+ t->wday = bcd2bin(RTC_DOW)-1;
+
+ }


+
+ return 0;
+}

+
+/*
+ * Set the minutes and seconds from seconds value 'nowtime'. Fail if
+ * clock is out by > 30 minutes. Logic lifted from atari code.
+ * Algorithm is to wait for the 10ms register to change, and then to
+ * wait a short while, and then set it.
+ */
+
+int q40_set_clock_mmss (unsigned long nowtime)
+{
+ int retval = 0;
+ short real_seconds = nowtime % 60, real_minutes = (nowtime / 60) % 60;
+
+ int rtc_minutes;
+
+
+ rtc_minutes = bcd2bin (RTC_MINS);
+
+ if ((rtc_minutes < real_minutes
+ ? real_minutes - rtc_minutes
+ : rtc_minutes - real_minutes) < 30)
+ {
+ RTC_CTRL |= RTC_WRITE;
+ RTC_MINS = bin2bcd(real_minutes);
+ RTC_SECS = bin2bcd(real_seconds);
+ RTC_CTRL &= ~(RTC_WRITE);
+ }
+ else
+ retval = -1;
+
+
+ return retval;
+}
+
+extern void q40kbd_init_hw(void);
+
+int q40_keyb_init (void)
+{
+ q40kbd_init_hw();
+ return 0;
+}
+
+#if 0
+/* dummy to cause */
+void q40_slow_io()
+{
+ return;
+}
+#endif
diff -u --recursive --new-file v2.2.7/linux/arch/m68k/q40/q40ints.c linux/arch/m68k/q40/q40ints.c
--- v2.2.7/linux/arch/m68k/q40/q40ints.c Wed Dec 31 16:00:00 1969
+++ linux/arch/m68k/q40/q40ints.c Tue May 11 09:57:14 1999
@@ -0,0 +1,347 @@
+/*
+ * arch/m68k/q40/q40ints.c
+ *
+ * Copyright (C) 1999 Richard Zidlicky
+ *
+ * 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.
+ *
+ * losely based on bvme6000ints.c
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/traps.h>
+
+#include <asm/q40_master.h>
+#include <asm/q40ints.h>
+
+/*
+ * Q40 IRQs are defined as follows:
+ * 3,4,5,6,7,10,11,14,15 : ISA dev IRQs
+ * 16-31: reserved
+ * 32 : keyboard int
+ * 33 : frame int (50 Hz periodic timer)
+ * 34 : sample int (10/20 KHz periodic timer)
+ *
+*/
+
+extern int ints_inited;
+
+
+void q40_irq2_handler (int, void *, struct pt_regs *fp);
+
+
+extern void (*q40_sys_default_handler[]) (int, void *, struct pt_regs *); /* added just for debugging */
+
+static void q40_defhand (int irq, void *dev_id, struct pt_regs *fp);
+static void sys_default_handler(int lev, void *dev_id, struct pt_regs *regs);
+
+/*
+ * This should ideally be 4 elements only, for speed.
+ */
+
+#define DEVNAME_SIZE 24
+
+static struct {
+ void (*handler)(int, void *, struct pt_regs *);
+ unsigned long flags;
+ void *dev_id;
+ char devname[DEVNAME_SIZE];
+ unsigned count;
+} irq_tab[Q40_IRQ_MAX+1];
+
+/*
+ * void q40_init_IRQ (void)
+ *
+ * Parameters: None
+ *
+ * Returns: Nothing
+ *
+ * This function is called during kernel startup to initialize
+ * the q40 IRQ handling routines.
+ */
+
+void q40_init_IRQ (void)
+{
+ int i;
+
+ for (i = 0; i <= Q40_IRQ_MAX; i++) {
+ irq_tab[i].handler = q40_defhand;
+ irq_tab[i].flags = IRQ_FLG_STD;
+ irq_tab[i].dev_id = NULL;
+ irq_tab[i].devname[0] = 0;
+ irq_tab[i].count = 0;
+ }
+
+ /* setup handler for ISA ints */
+ sys_request_irq(IRQ2,q40_irq2_handler, IRQ_FLG_LOCK, "q40 ISA and master chip", NULL);
+
+ /* now enable some ints.. */
+
+#if 0 /* has been abandoned */
+ master_outb(1,SER_ENABLE_REG);
+#endif
+ master_outb(1,EXT_ENABLE_REG);
+
+ /* would be spurious ints by now, q40kbd_init_hw() does that */
+ master_outb(0,KEY_IRQ_ENABLE_REG);
+}
+
+int q40_request_irq(unsigned int irq,
+ void (*handler)(int, void *, struct pt_regs *),
+ unsigned long flags, const char *devname, void *dev_id)
+{
+ /*printk("q40_request_irq %d, %s\n",irq,devname);*/
+
+ if (irq > Q40_IRQ_MAX || (irq>15 && irq<32)) {
+ printk("%s: Incorrect IRQ %d from %s\n", __FUNCTION__, irq, devname);
+ return -ENXIO;
+ }
+
+ /* test for ISA ints not implemented by HW */
+ if (irq<15)
+ {
+ switch (irq){
+ case 1: case 2: case 8: case 9:
+ case 12: case 13:
+ printk("%s: ISA IRQ %d from %s not implemented by HW\n", __FUNCTION__, irq, devname);
+ return -ENXIO;
+ default:
+ }
+ }
+
+ if (irq<Q40_IRQ_TIMER)
+ {
+ if (irq==11) {
+ printk("warning IRQ 10 and 11 not distinguishable\n");
+ irq=10;
+ }
+ if (!(irq_tab[irq].flags & IRQ_FLG_STD))
+ {
+ if (irq_tab[irq].flags & IRQ_FLG_LOCK)
+ {
+ printk("%s: IRQ %d from %s is not replaceable\n",
+ __FUNCTION__, irq, irq_tab[irq].devname);
+ return -EBUSY;
+ }
+ if (flags & IRQ_FLG_REPLACE)
+ {
+ printk("%s: %s can't replace IRQ %d from %s\n",
+ __FUNCTION__, devname, irq, irq_tab[irq].devname);


+ return -EBUSY;
+ }
+ }

+ /*printk("IRQ %d set to handler %p\n",irq,handler);*/
+ irq_tab[irq].handler = handler;
+ irq_tab[irq].flags = flags;
+ irq_tab[irq].dev_id = dev_id;
+ strncpy(irq_tab[irq].devname,devname,DEVNAME_SIZE);
+ return 0;
+ }
+ else {
+ /* Q40_IRQ_TIMER :somewhat special actions required here ..*/
+ sys_request_irq(4,handler,flags,devname,dev_id);
+ sys_request_irq(6,handler,flags,devname,dev_id);
+ return 0;
+ }
+}
+
+void q40_free_irq(unsigned int irq, void *dev_id)
+{
+ if (irq > Q40_IRQ_MAX || (irq>15 && irq<32)) {
+ printk("%s: Incorrect IRQ %d, dev_id %x \n", __FUNCTION__, irq, (unsigned)dev_id);
+ return;
+ }
+
+ /* test for ISA ints not implemented by HW */
+ if (irq<15) {
+ switch (irq){
+ case 1: case 2: case 8: case 9:
+ case 12: case 13:
+ printk("%s: ISA IRQ %d from %x illegal\n", __FUNCTION__, irq, (unsigned)dev_id);
+ return;
+ default:
+ }
+ }
+
+ if (irq<Q40_IRQ_TIMER){
+ if (irq==11) irq=10;
+ if (irq_tab[irq].dev_id != dev_id)
+ printk("%s: Removing probably wrong IRQ %d from %s\n",
+ __FUNCTION__, irq, irq_tab[irq].devname);
+
+ irq_tab[irq].handler = q40_defhand;
+ irq_tab[irq].flags = IRQ_FLG_STD;
+ irq_tab[irq].dev_id = NULL;
+ /* irq_tab[irq].devname = NULL; */
+ } else { /* == Q40_IRQ_TIMER */
+ sys_free_irq(4,dev_id);
+ sys_free_irq(6,dev_id);
+ }
+}
+
+#if 1
+void q40_process_int (int level, struct pt_regs *fp)
+{
+ printk("unexpected interrupt %x\n",level);
+}
+#endif
+
+/*
+ * tables to translate bits into IRQ numbers
+ * it is a good idea to order the entries by priority
+ *
+*/
+
+struct IRQ_TABLE{ unsigned mask; int irq ;};
+
+static struct IRQ_TABLE iirqs[]={
+ {IRQ_FRAME_MASK,Q40_IRQ_FRAME},
+ {IRQ_KEYB_MASK,Q40_IRQ_KEYBOARD},
+ {0,0}};
+static struct IRQ_TABLE eirqs[]={
+ {IRQ3_MASK,3}, /* ser 1 */
+ {IRQ4_MASK,4}, /* ser 2 */
+ {IRQ14_MASK,14}, /* IDE 1 */
+ {IRQ15_MASK,15}, /* IDE 2 */
+ {IRQ6_MASK,6}, /* floppy */
+ {IRQ7_MASK,7}, /* par */
+
+ {IRQ5_MASK,5},
+ {IRQ10_MASK,10},
+
+
+
+
+ {0,0}};
+
+/* complaiun only this many times about spurious ints : */
+static int ccleirq=60; /* ISA dev IRQ's*/
+static int cclirq=60; /* internal */
+
+/* FIX: add IRQ_INPROGRESS,mask,unmask,probing.... */
+
+void q40_irq2_handler (int vec, void *devname, struct pt_regs *fp)
+{
+ /* got level 2 interrupt, dispatch to ISA or keyboard IRQs */
+
+ unsigned mir=master_inb(IIRQ_REG);
+ unsigned mer;
+ int irq,i;
+
+ /*
+ * more than 1 bit might be set, must handle atmost 1 int source,
+ * - handle only those with explicitly set handler
+ */
+
+ if ((mir&IRQ_SER_MASK) || (mir&IRQ_EXT_MASK))
+ {
+
+ /* some ISA dev caused the int */
+
+ mer=master_inb(EIRQ_REG);
+
+ for (i=0; eirqs[i].mask; i++)
+ {
+ if (mer&(eirqs[i].mask))
+ {
+ irq=eirqs[i].irq;
+ irq_tab[irq].count++;
+ if (irq_tab[irq].handler == q40_defhand )
+ continue; /* ignore uninited INTs :-( */
+
+ irq_tab[irq].handler(irq,irq_tab[irq].dev_id,fp);
+ return;
+ }
+ }
+ if (ccleirq>0)
+ printk("ISA interrupt from unknown source? EIRQ_REG = %x\n",mer),ccleirq--;
+ }
+ else
+ {
+ /* internal */
+
+ for (i=0; iirqs[i].mask; i++)
+ {
+ if (mir&(iirqs[i].mask))
+ {
+ irq=iirqs[i].irq;
+ irq_tab[irq].count++;
+ if (irq_tab[irq].handler == q40_defhand )
+ continue; /* ignore uninited INTs :-( */
+
+ irq_tab[irq].handler(irq,irq_tab[irq].dev_id,fp);
+ return;
+ }
+ }
+ if (cclirq>0)
+ printk("internal level 2 interrupt from unknown source ? IIRQ_REG=%x\n",mir),cclirq--;
+ }
+}
+
+int q40_get_irq_list (char *buf)
+{
+ int i, len = 0;
+
+ for (i = 0; i <= Q40_IRQ_MAX; i++) {
+ if (irq_tab[i].count)
+ len += sprintf (buf+len, "Vec 0x%02x: %8d %s%s\n",
+ i, irq_tab[i].count,
+ irq_tab[i].devname[0] ? irq_tab[i].devname : "?",
+ irq_tab[i].handler == q40_defhand ?
+ " (now unassigned)" : "");
+ }
+ return len;
+}
+
+
+static void q40_defhand (int irq, void *dev_id, struct pt_regs *fp)
+{
+#if 0
+ printk ("Unknown q40 interrupt 0x%02x\n", irq);
+#endif
+}
+static void sys_default_handler(int lev, void *dev_id, struct pt_regs *regs)
+{
+#if 0
+ if (ints_inited)
+#endif
+ printk ("Uninitialised interrupt level %d\n", lev);
+#if 0
+ else
+ printk ("Interrupt before interrupt initialisation\n");
+#endif
+}
+
+ void (*q40_sys_default_handler[SYS_IRQS]) (int, void *, struct pt_regs *) = {
+ sys_default_handler,sys_default_handler,sys_default_handler,sys_default_handler,
+ sys_default_handler,sys_default_handler,sys_default_handler,sys_default_handler
+ };
+
+void q40_enable_irq (unsigned int irq)
+{
+}
+
+
+void q40_disable_irq (unsigned int irq)
+{
+}
+
+unsigned long q40_probe_irq_on (void)
+{
+ printk("sorry, irq probing not yet implemented - reconfigure the driver to avoid this\n");
+ return 0;
+}
+int q40_probe_irq_off (unsigned long irqs)
+{
+ return -1;
+}
diff -u --recursive --new-file v2.2.7/linux/arch/m68k/sun3x/Makefile linux/arch/m68k/sun3x/Makefile
--- v2.2.7/linux/arch/m68k/sun3x/Makefile Wed Dec 31 16:00:00 1969
+++ linux/arch/m68k/sun3x/Makefile Tue May 11 09:57:14 1999
@@ -0,0 +1,14 @@
+#
+# Makefile for Linux arch/m68k/sun3x 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 := sun3x.o
+O_OBJS := config.o time.o dvma.o sbus.o
+OX_OBJS :=
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.2.7/linux/arch/m68k/sun3x/config.c linux/arch/m68k/sun3x/config.c
--- v2.2.7/linux/arch/m68k/sun3x/config.c Wed Dec 31 16:00:00 1969
+++ linux/arch/m68k/sun3x/config.c Tue May 11 09:57:14 1999
@@ -0,0 +1,128 @@
+/*
+ * Setup kernel for a Sun3x machine
+ *
+ * (C) 1999 Thomas Bogendoerfer (tsbo...@alpha.franken.de)
+ *
+ * based on code from Oliver Jowett <oli...@jowett.manawatu.gen.nz>
+ */
+
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/console.h>
+#include <linux/init.h>
+
+#include <asm/system.h>
+#include <asm/machdep.h>
+#include <asm/irq.h>
+#include <asm/sun3x.h>
+
+#include "time.h"
+
+static volatile unsigned char *sun3x_intreg = (unsigned char *)SUN3X_INTREG;
+extern int serial_console;
+
+void sun3x_halt(void)
+{
+ /* Disable interrupts */
+ cli();
+
+ /* we can't drop back to PROM, so we loop here */
+ for (;;);
+}
+
+void sun3x_reboot(void)
+{
+ /* This never returns, don't bother saving things */
+ cli();
+
+ /* no idea, whether this works */
+ asm ("reset");
+}
+
+__initfunc(int sun3x_keyb_init(void))


+{
+ return 0;
+}

+
+int sun3x_kbdrate(struct kbd_repeat *r)


+{
+ return 0;
+}

+
+void sun3x_kbd_leds(unsigned int i)
+{
+
+}
+
+static void sun3x_badint (int irq, void *dev_id, struct pt_regs *fp)
+{
+ printk ("received spurious interrupt %d\n",irq);
+ num_spurious += 1;
+}
+
+void (*sun3x_default_handler[SYS_IRQS])(int, void *, struct pt_regs *) = {
+ sun3x_badint, sun3x_badint, sun3x_badint, sun3x_badint,
+ sun3x_badint, sun3x_badint, sun3x_badint, sun3x_badint
+};
+
+void sun3x_enable_irq(unsigned int irq)
+{
+ *sun3x_intreg |= (1 << irq);
+}
+
+void sun3x_disable_irq(unsigned int irq)
+{
+ *sun3x_intreg &= ~(1 << irq);
+}
+
+__initfunc(void sun3x_init_IRQ(void))
+{
+ /* disable all interrupts initially */
+ *sun3x_intreg = 1; /* master enable only */
+}
+
+int sun3x_get_irq_list(char *buf)


+{
+ return 0;
+}

+
+/*
+ * Setup the sun3x configuration info
+ */
+__initfunc(void config_sun3x(void))
+{
+ mach_get_irq_list = sun3x_get_irq_list;
+ mach_max_dma_address = 0xffffffff; /* we can DMA anywhere, whee */
+
+ mach_keyb_init = sun3x_keyb_init;
+ mach_kbdrate = sun3x_kbdrate;
+ mach_kbd_leds = sun3x_kbd_leds;
+
+ mach_sched_init = sun3x_sched_init;
+ mach_init_IRQ = sun3x_init_IRQ;
+ enable_irq = sun3x_enable_irq;
+ disable_irq = sun3x_disable_irq;
+ mach_request_irq = sys_request_irq;
+ mach_free_irq = sys_free_irq;
+ mach_default_handler = &sun3x_default_handler;
+ mach_gettimeoffset = sun3x_gettimeoffset;
+ mach_reset = sun3x_reboot;
+
+ mach_gettod = sun3x_gettod;
+
+ switch (*(unsigned char *)SUN3X_EEPROM_CONS) {
+ case 0x10:
+ serial_console = 1;
+ conswitchp = NULL;
+ break;
+ case 0x11:
+ serial_console = 2;
+ conswitchp = NULL;
+ break;
+ default:
+ serial_console = 0;
+ conswitchp = &dummy_con;


+ break;
+ }
+
+}

diff -u --recursive --new-file v2.2.7/linux/arch/m68k/sun3x/dvma.c linux/arch/m68k/sun3x/dvma.c
--- v2.2.7/linux/arch/m68k/sun3x/dvma.c Wed Dec 31 16:00:00 1969
+++ linux/arch/m68k/sun3x/dvma.c Tue May 11 09:57:14 1999
@@ -0,0 +1,162 @@
+/*
+ * Virtual DMA allocation
+ *
+ * (C) 1999 Thomas Bogendoerfer (tsbo...@alpha.franken.de)
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/bitops.h>
+#include <linux/mm.h>
+
+#include <asm/sun3x.h>
+#include <asm/dvma.h>
+#include <asm/io.h>
+#include <asm/page.h>
+
+/* IOMMU support */
+
+#define IOMMU_ENTRIES 2048
+#define IOMMU_ADDR_MASK 0x03ffe000
+#define IOMMU_CACHE_INHIBIT 0x00000040
+#define IOMMU_FULL_BLOCK 0x00000020
+#define IOMMU_MODIFIED 0x00000010
+#define IOMMU_USED 0x00000008
+#define IOMMU_WRITE_PROTECT 0x00000004
+#define IOMMU_DT_MASK 0x00000003
+#define IOMMU_DT_INVALID 0x00000000
+#define IOMMU_DT_VALID 0x00000001
+#define IOMMU_DT_BAD 0x00000002
+
+#define DVMA_PAGE_SHIFT 13
+#define DVMA_PAGE_SIZE (1UL << DVMA_PAGE_SHIFT)
+#define DVMA_PAGE_MASK (~(DVMA_PAGE_SIZE-1))
+
+
+static volatile unsigned long *iommu_pte = (unsigned long *)SUN3X_IOMMU;
+static unsigned long iommu_use[IOMMU_ENTRIES];
+static unsigned long iommu_bitmap[IOMMU_ENTRIES/32];
+
+
+#define dvma_entry_paddr(index) (iommu_pte[index] & IOMMU_ADDR_MASK)
+#define dvma_entry_vaddr(index,paddr) ((index << DVMA_PAGE_SHIFT) | \
+ (paddr & (DVMA_PAGE_SIZE-1)))
+#define dvma_entry_set(index,addr) (iommu_pte[index] = \
+ (addr & IOMMU_ADDR_MASK) | \
+ IOMMU_DT_VALID)
+#define dvma_entry_clr(index) (iommu_pte[index] = IOMMU_DT_INVALID)
+#define dvma_entry_use(index) (iommu_use[index])
+#define dvma_entry_inc(index) (iommu_use[index]++)
+#define dvma_entry_dec(index) (iommu_use[index]--)
+#define dvma_entry_hash(addr) ((addr >> DVMA_PAGE_SHIFT) ^ \
+ ((addr & 0x03c00000) >> \
+ (DVMA_PAGE_SHIFT+4)))
+#define dvma_map iommu_bitmap
+#define dvma_map_size (IOMMU_ENTRIES/2)
+#define dvma_slow_offset (IOMMU_ENTRIES/2)
+#define dvma_is_slow(addr) ((addr) & \
+ (dvma_slow_offset << DVMA_PAGE_SHIFT))
+
+static int fixed_dvma;
+
+void __init dvma_init(void)
+{
+ unsigned long tmp;
+
+ if ((unsigned long)high_memory < (IOMMU_ENTRIES << DVMA_PAGE_SHIFT)) {
+ printk ("Sun3x fixed DVMA mapping\n");
+ fixed_dvma = 1;
+ for (tmp = 0; tmp < (unsigned long)high_memory; tmp += DVMA_PAGE_SIZE)
+ dvma_entry_set (tmp >> DVMA_PAGE_SHIFT, virt_to_phys((void *)tmp));
+ fixed_dvma = 1;
+ } else {
+ printk ("Sun3x variable DVMA mapping\n");
+ for (tmp = 0; tmp < IOMMU_ENTRIES; tmp++)
+ dvma_entry_clr (tmp);
+ fixed_dvma = 0;
+ }
+}
+
+unsigned long dvma_slow_alloc (unsigned long paddr, int npages)
+{
+ int scan, base;
+
+ scan = 0;
+ for (;;) {
+ scan = find_next_zero_bit(dvma_map, dvma_map_size, scan);
+ if ((base = scan) + npages > dvma_map_size) {
+ printk ("dvma_slow_alloc failed for %d pages\n",npages);
+ return 0;
+ }
+ for (;;) {
+ if (scan >= base + npages) goto found;
+ if (test_bit(scan, dvma_map)) break;
+ scan++;
+ }
+ }
+
+found:
+ for (scan = base; scan < base+npages; scan++) {
+ dvma_entry_set(scan+dvma_slow_offset, paddr);
+ paddr += DVMA_PAGE_SIZE;
+ set_bit(scan, dvma_map);
+ }
+ return (dvma_entry_vaddr((base+dvma_slow_offset),paddr));
+}
+
+unsigned long dvma_alloc (unsigned long paddr, unsigned long size)
+{
+ int index;
+ int pages = ((paddr & ~DVMA_PAGE_MASK) + size + (DVMA_PAGE_SIZE-1)) >>
+ DVMA_PAGE_SHIFT;
+
+ if (fixed_dvma)
+ return ((unsigned long)phys_to_virt (paddr));
+
+ if (pages > 1) /* multi page, allocate from slow pool */
+ return dvma_slow_alloc (paddr, pages);
+
+ index = dvma_entry_hash (paddr);
+
+ if (dvma_entry_use(index)) {
+ if (dvma_entry_paddr(index) == (paddr & DVMA_PAGE_MASK)) {
+ dvma_entry_inc(index);
+ return dvma_entry_vaddr(index,paddr);
+ }
+ /* collision, allocate from slow pool */
+ return dvma_slow_alloc (paddr, pages);
+ }
+
+ dvma_entry_set(index,paddr);
+ dvma_entry_inc(index);
+ return dvma_entry_vaddr(index,paddr);
+}
+
+void dvma_free (unsigned long dvma_addr, unsigned long size)
+{
+ int npages;
+ int index;
+
+ if (fixed_dvma)
+ return;
+
+ if (!dvma_is_slow(dvma_addr)) {
+ index = (dvma_addr >> DVMA_PAGE_SHIFT);
+ if (dvma_entry_use(index) == 0) {
+ printk ("dvma_free: %lx entry already free\n",dvma_addr);
+ return;
+ }
+ dvma_entry_dec(index);
+ if (dvma_entry_use(index) == 0)
+ dvma_entry_clr(index);
+ return;
+ }
+
+ /* free in slow pool */
+ npages = ((dvma_addr & ~DVMA_PAGE_MASK) + size + (DVMA_PAGE_SIZE-1)) >>
+ DVMA_PAGE_SHIFT;
+ for (index = (dvma_addr >> DVMA_PAGE_SHIFT); npages--; index++) {
+ dvma_entry_clr(index);
+ clear_bit (index,dvma_map);
+ }
+}
diff -u --recursive --new-file v2.2.7/linux/arch/m68k/sun3x/sbus.c linux/arch/m68k/sun3x/sbus.c
--- v2.2.7/linux/arch/m68k/sun3x/sbus.c Wed Dec 31 16:00:00 1969
+++ linux/arch/m68k/sun3x/sbus.c Tue May 11 09:57:14 1999
@@ -0,0 +1,44 @@
+/*
+ * SBus helper functions
+ *
+ * Sun3x don't have a sbus, but many of the used devices are also
+ * used on Sparc machines with sbus. To avoid having a lot of
+ * duplicate code, we provide necessary glue stuff to make using
+ * of the sbus driver code possible.
+ *
+ * (C) 1999 Thomas Bogendoerfer (tsbo...@alpha.franken.de)
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+
+__initfunc(void sbus_init(void))
+{
+
+}
+
+void *sparc_alloc_io (u32 address, void *virtual, int len, char *name,
+ u32 bus_type, int rdonly)
+{
+ return (void *)address;
+}
+
+int prom_getintdefault(int node, char *property, int deflt)
+{
+ return deflt;
+}
+
+int prom_getbool (int node, char *prop)
+{
+ return 1;
+}
+
+void prom_printf(char *fmt, ...)
+{
+
+}
+
+void prom_halt (void)
+{
+
+}
diff -u --recursive --new-file v2.2.7/linux/arch/m68k/sun3x/time.c linux/arch/m68k/sun3x/time.c
--- v2.2.7/linux/arch/m68k/sun3x/time.c Wed Dec 31 16:00:00 1969
+++ linux/arch/m68k/sun3x/time.c Tue May 11 09:57:14 1999
@@ -0,0 +1,83 @@
+/*
+ * linux/arch/m68k/sun3x/time.c
+ *
+ * Sun3x-specific time handling
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/kernel_stat.h>
+#include <linux/interrupt.h>
+
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/traps.h>
+#include <asm/sun3x.h>
+
+#include "time.h"
+
+#define M_CONTROL 0xf8
+#define M_SEC 0xf9
+#define M_MIN 0xfa
+#define M_HOUR 0xfb
+#define M_DAY 0xfc
+#define M_DATE 0xfd
+#define M_MONTH 0xfe
+#define M_YEAR 0xff
+
+#define C_WRITE 0x80
+#define C_READ 0x40
+#define C_SIGN 0x20
+#define C_CALIB 0x1f
+
+#define BCD_TO_BIN(val) (((val)&15) + ((val)>>4)*10)
+
+/* Read the Mostek */
+void sun3x_gettod (int *yearp, int *monp, int *dayp,
+ int *hourp, int *minp, int *secp)
+{
+ volatile unsigned char *eeprom = (unsigned char *)SUN3X_EEPROM;
+
+ /* Stop updates */
+ *(eeprom + M_CONTROL) |= C_READ;
+
+ /* Read values */
+ *yearp = BCD_TO_BIN(*(eeprom + M_YEAR));
+ *monp = BCD_TO_BIN(*(eeprom + M_MONTH));
+ *dayp = BCD_TO_BIN(*(eeprom + M_DATE));
+ *hourp = BCD_TO_BIN(*(eeprom + M_HOUR));
+ *minp = BCD_TO_BIN(*(eeprom + M_MIN));
+ *secp = BCD_TO_BIN(*(eeprom + M_SEC));
+
+ /* Restart updates */
+ *(eeprom + M_CONTROL) &= ~C_READ;
+}
+
+/* Not much we can do here */
+unsigned long sun3x_gettimeoffset (void)
+{
+ return 0L;
+}
+
+static void sun3x_timer_tick(int irq, void *dev_id, struct pt_regs *regs)
+{
+ void (*vector)(int, void *, struct pt_regs *) = dev_id;
+
+ /* Clear the pending interrupt - pulse the enable line low */
+ disable_irq(5);
+ enable_irq(5);
+
+ vector(irq, NULL, regs);
+}
+
+__initfunc(void sun3x_sched_init(void (*vector)(int, void *, struct pt_regs *)))
+{
+ sys_request_irq(5, sun3x_timer_tick, IRQ_FLG_STD, "timer tick", vector);
+
+ /* Pulse enable low to get the clock started */
+ disable_irq(5);
+ enable_irq(5);
+}
diff -u --recursive --new-file v2.2.7/linux/arch/m68k/sun3x/time.h linux/arch/m68k/sun3x/time.h
--- v2.2.7/linux/arch/m68k/sun3x/time.h Wed Dec 31 16:00:00 1969
+++ linux/arch/m68k/sun3x/time.h Tue May 11 09:57:14 1999
@@ -0,0 +1,9 @@
+#ifndef SUN3X_TIME_H
+#define SUN3X_TIME_H
+
+void sun3x_gettod (int *yearp, int *monp, int *dayp,
+ int *hourp, int *minp, int *secp);
+unsigned long sun3x_gettimeoffset (void);
+void sun3x_sched_init(void (*vector)(int, void *, struct pt_regs *));
+
+#endif
diff -u --recursive --new-file v2.2.7/linux/arch/mips/kernel/irixioctl.c linux/arch/mips/kernel/irixioctl.c
--- v2.2.7/linux/arch/mips/kernel/irixioctl.c Fri Oct 23 22:01:19 1998
+++ linux/arch/mips/kernel/irixioctl.c Sat May 8 11:14:01 1999
@@ -33,13 +33,15 @@
X {
X struct file *filp;
X
- if(fd >= NR_OPEN || !(filp = current->files->fd[fd]))
+ file = fcheck(fd);
+ if(!file)
X return ((struct tty_struct *) 0);
X if(filp->private_data) {
X struct tty_struct *ttyp = (struct tty_struct *) filp->private_data;
X
- if(ttyp->magic == TTY_MAGIC)
+ if(ttyp->magic == TTY_MAGIC) {
X return ttyp;
+ }
X }
X return ((struct tty_struct *) 0);
X }
diff -u --recursive --new-file v2.2.7/linux/arch/mips/kernel/sysirix.c linux/arch/mips/kernel/sysirix.c
--- v2.2.7/linux/arch/mips/kernel/sysirix.c Tue Mar 23 14:35:46 1999
+++ linux/arch/mips/kernel/sysirix.c Sat May 8 11:14:01 1999
@@ -23,6 +23,7 @@
X #include <linux/smp.h>
X #include <linux/smp_lock.h>
X #include <linux/utsname.h>
+#include <linux/file.h>
X
X #include <asm/ptrace.h>
X #include <asm/page.h>
@@ -734,6 +735,7 @@
X int error, i;
X
X /* We don't support this feature yet. */
+ lock_kernel();
X if(fs_type) {
X error = -EINVAL;
X goto out;
@@ -776,7 +778,6 @@
X
X asmlinkage int irix_fstatfs(unsigned int fd, struct irix_statfs *buf)
X {
- struct dentry *dentry;
X struct inode *inode;
X struct statfs kbuf;
X mm_segment_t old_fs;
@@ -787,25 +788,22 @@
X error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statfs));
X if (error)
X goto out;
- if (fd >= NR_OPEN || !(file = current->files->fd[fd])) {
+ if (!(file = fget(fd))) {
X error = -EBADF;
X goto out;
X }
- if (!(dentry = file->f_dentry)) {
+
+ if (!(inode = file->f_dentry->d_inode)) {
X error = -ENOENT;
- goto out;
- }
- if (!(inode = dentry->d_inode)) {
- error = -ENOENT;
- goto out;
+ goto out_f;
X }
X if (!inode->i_sb) {
X error = -ENODEV;
- goto out;
+ goto out_f;
X }
X if (!inode->i_sb->s_op->statfs) {
X error = -ENOSYS;
- goto out;
+ goto out_f;
X }
X
X old_fs = get_fs(); set_fs(get_ds());
@@ -813,7 +811,7 @@
X sizeof(struct statfs));
X set_fs(old_fs);
X if (error)
- goto out;
+ goto out_f;
X
X __put_user(kbuf.f_type, &buf->f_type);
X __put_user(kbuf.f_bsize, &buf->f_bsize);
@@ -826,9 +824,9 @@
X __put_user(0, &buf->f_fname[i]);
X __put_user(0, &buf->f_fpack[i]);
X }
- error = 0;
X
- dput(dentry);
+out_f:
+ fput(file);
X out:
X unlock_kernel();
X return error;
@@ -1110,7 +1108,7 @@
X
X lock_kernel();
X if(!(flags & MAP_ANONYMOUS)) {
- if(fd >= NR_OPEN || !(file = current->files->fd[fd])) {
+ if(!(file = fget(fd))) {
X retval = -EBADF;
X goto out;
X }
@@ -1130,6 +1128,8 @@
X flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
X
X retval = do_mmap(file, addr, len, prot, flags, offset);
+ if (file)
+ fput(file);
X
X out:
X unlock_kernel();
@@ -1568,7 +1568,6 @@
X
X asmlinkage int irix_fstatvfs(int fd, struct irix_statvfs *buf)
X {
- struct dentry *dentry;
X struct inode *inode;
X mm_segment_t old_fs;
X struct statfs kbuf;
@@ -1582,21 +1581,21 @@
X error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statvfs));
X if (error)
X goto out;
- if (fd >= NR_OPEN || !(file = current->files->fd[fd])) {
+ if (!(file = fget(fd))) {
X error = -EBADF;
X goto out;
X }
- if (!(dentry = file->f_dentry)) {
+ if (!(inode = file->f_dentry->d_inode)) {
X error = -ENOENT;
- goto out;
+ goto out_f;
X }
- if (!(inode = dentry->d_inode)) {
- error = -ENOENT;
- goto out;
+ if (!inode->i_sb) {
+ error = -ENODEV;
+ goto out_f;
X }
X if (!inode->i_sb->s_op->statfs) {
X error = -ENOSYS;
- goto out;
+ goto out_f;
X }
X
X old_fs = get_fs(); set_fs(get_ds());
@@ -1604,7 +1603,7 @@
X sizeof(struct statfs));
X set_fs(old_fs);
X if (error)
- goto out;
+ goto out_f;
X
X __put_user(kbuf.f_bsize, &buf->f_bsize);
X __put_user(kbuf.f_frsize, &buf->f_frsize);
@@ -1626,9 +1625,8 @@
X for(i = 0; i < 32; i++)
X __put_user(0, &buf->f_fstr[i]);
X
- error = 0;
-
- dput(dentry);
+out_f:
+ fput(file);
X out:
X unlock_kernel();
X return error;
@@ -1726,7 +1724,7 @@
X }
X
X if(!(flags & MAP_ANONYMOUS)) {
- if(fd >= NR_OPEN || !(file = current->files->fd[fd])) {
+ if(!(file = fcheck(fd))) {
X error = -EBADF;
X goto out;
X }
@@ -1812,6 +1810,7 @@
X struct statfs kbuf;
X int error, i;
X
+ lock_kernel();
X printk("[%s:%ld] Wheee.. irix_statvfs(%s,%p)\n",
X current->comm, current->pid, fname, buf);
X error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statvfs));
@@ -1864,7 +1863,6 @@
X
X asmlinkage int irix_fstatvfs64(int fd, struct irix_statvfs *buf)
X {
- struct dentry *dentry;
X struct inode *inode;
X mm_segment_t old_fs;
X struct statfs kbuf;
@@ -1878,21 +1876,21 @@
X error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statvfs));
X if (error)
X goto out;
- if (fd >= NR_OPEN || !(file = current->files->fd[fd])) {
+ if (!(file = fget(fd))) {
X error = -EBADF;
X goto out;
X }
- if (!(dentry = file->f_dentry)) {
+ if (!(inode = file->f_dentry->d_inode)) {
X error = -ENOENT;
- goto out;
+ goto out_f;
X }
- if (!(inode = dentry->d_inode)) {
- error = -ENOENT;
- goto out;
+ if (!inode->i_sb) {
+ error = -ENODEV;
+ goto out_f;
X }
X if (!inode->i_sb->s_op->statfs) {
X error = -ENOSYS;
- goto out;
+ goto out_f;
X }
X
X old_fs = get_fs(); set_fs(get_ds());
@@ -1900,7 +1898,7 @@
X sizeof(struct statfs));
X set_fs(old_fs);
X if (error)
- goto out;
+ goto out_f;
X
X __put_user(kbuf.f_bsize, &buf->f_bsize);
X __put_user(kbuf.f_frsize, &buf->f_frsize);
@@ -1921,10 +1919,8 @@
X __put_user(kbuf.f_namelen, &buf->f_namemax);
X for(i = 0; i < 32; i++)
X __put_user(0, &buf->f_fstr[i]);
-
- error = 0;
-
- dput(dentry);
+out_f:
+ fput(file);
X out:
X unlock_kernel();
X return error;
@@ -1994,7 +1990,6 @@
X unsigned short reclen = ROUND_UP32(NAME_OFFSET32(dirent) + namlen + 1);
X int retval;
X
- lock_kernel();
X #ifdef DEBUG_GETDENTS
X printk("\nirix_filldir32[reclen<%d>namlen<%d>count<%d>]",
X reclen, namlen, buf->count);
@@ -2020,14 +2015,12 @@
X retval = 0;
X
X out:
- unlock_kernel();
X return retval;
X }
X
X asmlinkage int irix_ngetdents(unsigned int fd, void * dirent, unsigned int count, int *eob)
X {
X struct file *file;
- struct dentry *dentry;
X struct inode *inode;
X struct irix_dirent32 *lastdirent;
X struct irix_dirent32_callback buf;
@@ -2039,46 +2032,56 @@
X current->pid, fd, dirent, count, eob);
X #endif
X error = -EBADF;
- if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
+ file = fget(fd);
+ if (!file)
X goto out;
X
- dentry = file->f_dentry;
- if (!dentry)
- goto out;
+ inode = file->f_dentry->d_inode;
+ if (!inode)
+ goto out_putf;
X
X inode = dentry->d_inode;
X if (!inode)
- goto out;
+ goto out_putf;
X
- error = -ENOTDIR;
- if (!file->f_op || !file->f_op->readdir)
- goto out;
-
- error = -EFAULT;
- if(!access_ok(VERIFY_WRITE, dirent, count) ||
- !access_ok(VERIFY_WRITE, eob, sizeof(*eob)))
- goto out;
-
- __put_user(0, eob);
X buf.current_dir = (struct irix_dirent32 *) dirent;
X buf.previous = NULL;
X buf.count = count;
X buf.error = 0;
X
+ error = -ENOTDIR;
+ if (!file->f_op || !file->f_op->readdir)
+ goto out_putf;
+
+ /*
+ * Get the inode's semaphore to prevent changes
+ * to the directory while we read it.
+ */
+ down(&inode->i_sem);
X error = file->f_op->readdir(file, &buf, irix_filldir32);
+ up(&inode->i_sem);
X if (error < 0)
- goto out;
+ goto out_putf;
+ error = buf.error;
X lastdirent = buf.previous;
- if (!lastdirent) {
- error = buf.error;
- goto out;
+ if (lastdirent) {
+ put_user(file->f_pos, &lastdirent->d_off);
+ error = count - buf.count;
X }
- lastdirent->d_off = (u32) file->f_pos;
+
+ if (put_user(0, eob) < 0) {
+ error = EFAULT;
+ goto out_putf;
+ }
+
+
X #ifdef DEBUG_GETDENTS
X printk("eob=%d returning %d\n", *eob, count - buf.count);
X #endif
X error = count - buf.count;
X
+out_putf:
+ fput(file);
X out:
X unlock_kernel();
X return error;
@@ -2110,7 +2113,6 @@
X unsigned short reclen = ROUND_UP64(NAME_OFFSET64(dirent) + namlen + 1);
X int retval;
X
- lock_kernel();
X buf->error = -EINVAL; /* only used if we fail.. */
X if (reclen > buf->count) {
X retval = -EINVAL;
@@ -2131,14 +2133,12 @@
X
X retval = 0;
X out:
- unlock_kernel();
X return retval;
X }
X
X asmlinkage int irix_getdents64(int fd, void *dirent, int cnt)
X {
X struct file *file;
- struct dentry *dentry;
X struct inode *inode;
X struct irix_dirent64 *lastdirent;
X struct irix_dirent64_callback buf;
@@ -2150,40 +2150,38 @@
X current->pid, fd, dirent, cnt);
X #endif
X error = -EBADF;
- if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
- goto out;
-
- dentry = file->f_dentry;
- if (!dentry)
+ if (!(file = fget(fd)))
X goto out;
X
- inode = dentry->d_inode;
+ inode = file->f_dentry->d_inode;
X if (!inode)
- goto out;
+ goto out_f;
X
X error = -ENOTDIR;
X if (!file->f_op || !file->f_op->readdir)


SHAR_EOF
true || echo 'restore of patch-2.2.8 failed'
fi

echo 'End of part 07'
echo 'File patch-2.2.8 is continued in part 08'
echo 08 > _shar_seq_.tmp

Thomas...@ciw.uni-karlsruhe.de

unread,
May 12, 1999, 3:00:00 AM5/12/99
to
Archive-name: v2.2/patch-2.2.8/part08

#!/bin/sh
# this is part 08 of a 33 - part archive


# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.8 continued
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 08; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.8'
else
echo 'x - continuing with patch-2.2.8'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.8' &&

- goto out;
+ goto out_f;
X

X error = -EFAULT;
X if(!access_ok(VERIFY_WRITE, dirent, cnt))


- goto out;
+ goto out_f;
X

X error = -EINVAL;
X if(cnt < (sizeof(struct irix_dirent64) + 255))


- goto out;
+ goto out_f;
X

X buf.curr = (struct irix_dirent64 *) dirent;
X buf.previous = NULL;
X buf.count = cnt;
X buf.error = 0;
+ down(&inode->i_sem);
X error = file->f_op->readdir(file, &buf, irix_filldir64);


+ up(&inode->i_sem);
X if (error < 0)
- goto out;

+ goto out_f;
X lastdirent = buf.previous;
X if (!lastdirent) {
X error = buf.error;
- goto out;
+ goto out_f;
X }
X lastdirent->d_off = (u64) file->f_pos;
X #ifdef DEBUG_GETDENTS
@@ -2191,6 +2189,8 @@
X #endif
X error = cnt - buf.count;
X

+out_f:
+ fput(file);
X out:
X unlock_kernel();
X return error;

@@ -2199,7 +2199,6 @@
X asmlinkage int irix_ngetdents64(int fd, void *dirent, int cnt, int *eob)


X {
X struct file *file;
- struct dentry *dentry;
X struct inode *inode;

X struct irix_dirent64 *lastdirent;
X struct irix_dirent64_callback buf;

@@ -2211,42 +2210,40 @@


X current->pid, fd, dirent, cnt);
X #endif
X error = -EBADF;
- if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
- goto out;
-
- dentry = file->f_dentry;
- if (!dentry)
+ if (!(file = fget(fd)))
X goto out;
X
- inode = dentry->d_inode;
+ inode = file->f_dentry->d_inode;
X if (!inode)
- goto out;
+ goto out_f;
X
X error = -ENOTDIR;
X if (!file->f_op || !file->f_op->readdir)
- goto out;
+ goto out_f;
X

X error = -EFAULT;
X if(!access_ok(VERIFY_WRITE, dirent, cnt) ||
X !access_ok(VERIFY_WRITE, eob, sizeof(*eob)))
- goto out;
+ goto out_f;
X
X error = -EINVAL;
X if(cnt < (sizeof(struct irix_dirent64) + 255))


- goto out;
+ goto out_f;
X

X *eob = 0;
X buf.curr = (struct irix_dirent64 *) dirent;
X buf.previous = NULL;
X buf.count = cnt;
X buf.error = 0;
+ down(&inode->i_sem);
X error = file->f_op->readdir(file, &buf, irix_filldir64);


+ up(&inode->i_sem);
X if (error < 0)
- goto out;

+ goto out_f;
X lastdirent = buf.previous;
X if (!lastdirent) {
X error = buf.error;
- goto out;
+ goto out_f;
X }
X lastdirent->d_off = (u64) file->f_pos;
X #ifdef DEBUG_GETDENTS
@@ -2254,6 +2251,8 @@
X #endif
X error = cnt - buf.count;
X

+out_f:
+ fput(file);
X out:
X unlock_kernel();
X return error;

diff -u --recursive --new-file v2.2.7/linux/arch/ppc/boot/Makefile linux/arch/ppc/boot/Makefile
--- v2.2.7/linux/arch/ppc/boot/Makefile Tue Mar 23 14:35:46 1999
+++ linux/arch/ppc/boot/Makefile Thu Apr 29 12:39:01 1999
@@ -14,7 +14,7 @@
X .s.o:
X $(AS) -o $*.o $<
X .c.o:
- $(CC) $(CFLAGS) -DINITRD_OFFSET=$(IOFF) -DINITRD_SIZE=$(ISZ) -DZIMAGE_OFFSET=$(ZOFF) -DZIMAGE_SIZE=$(ZSZ) -DKERNELBASE=$(KERNELBASE) -c -o $*.o $<
+ $(CC) $(CFLAGS) -DINITRD_OFFSET=$(IOFF) -DINITRD_SIZE=$(ISZ) -DZIMAGE_OFFSET=$(ZOFF) -DZIMAGE_SIZE=$(ZSZ) -c -o $*.o $<
X .S.s:
X $(CC) -D__ASSEMBLY__ -traditional -E -o $*.o $<
X .S.o:
@@ -57,7 +57,7 @@
X -DINITRD_SIZE=`sh size $(OBJDUMP) zvmlinux.initrd initrd` \
X -DZIMAGE_OFFSET=`sh offset $(OBJDUMP) zvmlinux.initrd image` \
X -DZIMAGE_SIZE=`sh size $(OBJDUMP) zvmlinux.initrd image` \
- -DKERNELBASE=$(KERNELBASE) -c -o misc.o misc.c
+ -c -o misc.o misc.c
X $(LD) $(ZLINKFLAGS) -o zvmlinux.initrd.tmp $(OBJECTS)
X $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
X --add-section=initrd=ramdisk.image.gz \
@@ -84,7 +84,7 @@
X #
X $(CC) $(CFLAGS) -DINITRD_OFFSET=0 -DINITRD_SIZE=0 \
X -DZIMAGE_OFFSET=`sh offset $(OBJDUMP) zvmlinux image` \
- -DZIMAGE_SIZE=`sh size $(OBJDUMP) zvmlinux image` -DKERNELBASE=$(KERNELBASE) \
+ -DZIMAGE_SIZE=`sh size $(OBJDUMP) zvmlinux image` \
X -c -o misc.o misc.c
X $(LD) $(ZLINKFLAGS) -o zvmlinux.tmp $(OBJECTS)
X $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment --add-section=image=../coffboot/vmlinux.gz \
@@ -95,7 +95,7 @@
X dd if=zImage of=/dev/fd0H1440 bs=64b
X
X mkprep : mkprep.c
- $(HOSTCC) -DKERNELBASE=$(KERNELBASE) -o mkprep mkprep.c
+ $(HOSTCC) -o mkprep mkprep.c
X
X znetboot : zImage
X cp zImage $(TFTPIMAGE)
diff -u --recursive --new-file v2.2.7/linux/arch/ppc/boot/head.S linux/arch/ppc/boot/head.S
--- v2.2.7/linux/arch/ppc/boot/head.S Fri Apr 16 14:47:30 1999
+++ linux/arch/ppc/boot/head.S Thu Apr 29 12:39:01 1999
@@ -6,7 +6,7 @@
X .text
X
X /*
- * $Id: head.S,v 1.29 1999/03/08 23:41:17 cort Exp $
+ * $Id: head.S,v 1.31 1999/04/22 06:32:00 davem Exp $
X *
X * Boot loader philosophy:
X * ROM loads us to some arbitrary location
@@ -23,11 +23,7 @@
X start_:
X mr r11,r3 /* Save pointer to residual/board data */
X mr r25,r5 /* Save OFW pointer */
-
- mfmsr r3 /* Turn off interrupts */
- li r4,0
- ori r4,r4,MSR_EE
- andc r3,r3,r4
+ li r3,MSR_IP /* Establish default MSR value */
X mtmsr r3
X
X /* check if we need to relocate ourselves to the link addr or were we
@@ -136,6 +132,20 @@
X lis r10,0xdeadc0de@h
X ori r10,r10,0xdeadc0de@l
X stw r10,0(r9)
+/*
+ * The Radstone firmware maps PCI memory at 0xc0000000 using BAT2
+ * so disable BATs before setting this to avoid a clash
+ */
+ li r8,0
+ mtspr DBAT0U,r8
+ mtspr DBAT1U,r8
+ mtspr DBAT2U,r8
+ mtspr DBAT3U,r8
+ mtspr IBAT0U,r8
+ mtspr IBAT1U,r8
+ mtspr IBAT2U,r8
+ mtspr IBAT3U,r8
+
X blr
X hang:
X b hang
diff -u --recursive --new-file v2.2.7/linux/arch/ppc/boot/kbd.c linux/arch/ppc/boot/kbd.c
--- v2.2.7/linux/arch/ppc/boot/kbd.c Tue Mar 23 14:35:46 1999
+++ linux/arch/ppc/boot/kbd.c Thu Apr 29 12:39:01 1999
@@ -127,6 +127,11 @@
X unsigned char c;
X int i;
X
+ /* flush input queue */
+ while ((inb(KBSTATP) & KBINRDY))
+ {
+ (void)inb(KBDATAP);
+ }
X /* Send self-test */
X while (inb(KBSTATP) & KBOUTRDY) ;
X outb(KBSTATP,0xAA);
diff -u --recursive --new-file v2.2.7/linux/arch/ppc/boot/misc.c linux/arch/ppc/boot/misc.c
--- v2.2.7/linux/arch/ppc/boot/misc.c Tue Mar 23 14:35:46 1999
+++ linux/arch/ppc/boot/misc.c Tue May 11 08:24:32 1999
@@ -1,7 +1,7 @@
X /*
X * misc.c
X *
- * $Id: misc.c,v 1.61 1999/03/08 23:51:02 cort Exp $
+ * $Id: misc.c,v 1.64 1999/04/30 05:52:46 cort Exp $
X *
X * Adapted for PowerPC by Gary Thomas
X *
@@ -33,14 +33,16 @@
X char *end_avail;
X extern char _end[];
X
-#if defined(CONFIG_SERIAL_CONSOLE)
-char cmd_preset[] = "console=ttyS0,9600n8";
+#ifdef CONFIG_CMDLINE
+#define CMDLINE CONFIG_CMDLINE
X #else
-char cmd_preset[] = "";
+#define CMDLINE "";
X #endif
-char cmd_buf[256];
-char *cmd_line = cmd_buf;
+char cmd_preset[] = CMDLINE;
+char cmd_buf[256];
+char *cmd_line = cmd_buf;
X
+int keyb_present = 1; /* keyboard controller is present by default */
X RESIDUAL hold_resid_buf;
X RESIDUAL *hold_residual = &hold_resid_buf;
X unsigned long initrd_start = 0, initrd_end = 0;
@@ -58,7 +60,8 @@
X void * memcpy(void * __dest, __const void * __src,
X int __n);
X void gunzip(void *, int, unsigned char *, int *);
-int _cvt(unsigned long val, char *buf, long radix, char *digits);
+static int _cvt(unsigned long val, char *buf, long radix, char *digits);
+unsigned char inb(int);
X
X void pause()
X {
@@ -93,11 +96,14 @@
X
X tstc(void)
X {
- return (
X #if defined(CONFIG_SERIAL_CONSOLE)
- NS16550_tstc(com_port) ||
+ if (keyb_present)
+ return (CRT_tstc() || NS16550_tstc(com_port));
+ else
+ NS16550_tstc(com_port);
+#else
+ return (CRT_tstc() );
X #endif /* CONFIG_SERIAL_CONSOLE */
- CRT_tstc());
X }
X
X getc(void)
@@ -106,7 +112,8 @@
X #if defined(CONFIG_SERIAL_CONSOLE)
X if (NS16550_tstc(com_port)) return (NS16550_getc(com_port));
X #endif /* CONFIG_SERIAL_CONSOLE */
- if (CRT_tstc()) return (CRT_getc());
+ if (keyb_present)
+ if (CRT_tstc()) return (CRT_getc());
X }
X }
X
@@ -188,6 +195,8 @@
X }
X }
X
+ cursor(x, y);
+
X orig_x = x;
X orig_y = y;
X }
@@ -317,6 +326,8 @@
X int dev_handle;
X int mem_info[2];
X int res, size;
+ unsigned char board_type;
+ unsigned char base_mod;
X
X lines = 25;
X cols = 80;
@@ -333,14 +344,31 @@
X flush_instruction_cache();
X _put_HID0(_get_HID0() & ~0x0000C000);
X _put_MSR((orig_MSR = _get_MSR()) & ~0x0030);
- vga_init(0xC0000000);
X
X #if defined(CONFIG_SERIAL_CONSOLE)
- com_port = (struct NS16550 *)NS16550_init(1);
+ com_port = (struct NS16550 *)NS16550_init(0);
X #endif /* CONFIG_SERIAL_CONSOLE */
+ vga_init(0xC0000000);
X
X if (residual)
X {
+ /* Is this Motorola PPCBug? */
+ if ((1 & residual->VitalProductData.FirmwareSupports) &&
+ (1 == residual->VitalProductData.FirmwareSupplier)) {
+ board_type = inb(0x800) & 0xF0;
+
+ /* If this is genesis 2 board then check for no
+ * keyboard controller and more than one processor.
+ */
+ if (board_type == 0xe0) {
+ base_mod = inb(0x803);
+ /* if a MVME2300/2400 or a Sitka then no keyboard */
+ if((base_mod == 0x9) || (base_mod == 0xF9) ||
+ (base_mod == 0xE1)) {
+ keyb_present = 0; /* no keyboard */
+ }
+ }
+ }
X memcpy(hold_residual,residual,sizeof(RESIDUAL));
X } else {
X /* Assume 32M in the absence of more info... */
@@ -429,7 +457,7 @@
X avail_ram = (char *)PAGE_ALIGN((unsigned long)_end);
X puts("zimage at: "); puthex((unsigned long)zimage_start);
X puts(" "); puthex((unsigned long)(zimage_size+zimage_start)); puts("\n");
- if ( (unsigned long)zimage_start <= 0x008000000 )
+ if ( (unsigned long)zimage_start <= 0x00800000 )
X {
X memcpy( (void *)avail_ram, (void *)zimage_start, zimage_size );
X zimage_start = (char *)avail_ram;
@@ -444,6 +472,7 @@
X {
X puts("initrd at: "); puthex(initrd_start);
X puts(" "); puthex(initrd_end); puts("\n");
+#ifdef OMIT
X avail_ram = (char *)PAGE_ALIGN(
X (unsigned long)zimage_size+(unsigned long)zimage_start);
X memcpy ((void *)avail_ram, (void *)initrd_start, INITRD_SIZE );
@@ -451,6 +480,7 @@
X initrd_end = initrd_start + INITRD_SIZE;
X puts("relocated to: "); puthex(initrd_start);
X puts(" "); puthex(initrd_end); puts("\n");
+#endif
X }
X
X avail_ram = (char *)0x00400000;
@@ -458,9 +488,8 @@
X puts("avail ram: "); puthex((unsigned long)avail_ram); puts(" ");
X puthex((unsigned long)end_avail); puts("\n");
X
-#if !defined(CONFIG_SERIAL_CONSOLE)
- CRT_tstc(); /* Forces keyboard to be initialized */
-#endif
+ if (keyb_present)
+ CRT_tstc(); /* Forces keyboard to be initialized */
X
X puts("\nLinux/PPC load: ");
X timer = 0;
diff -u --recursive --new-file v2.2.7/linux/arch/ppc/boot/mkprep.c linux/arch/ppc/boot/mkprep.c
--- v2.2.7/linux/arch/ppc/boot/mkprep.c Mon Oct 5 13:13:36 1998
+++ linux/arch/ppc/boot/mkprep.c Thu Apr 29 12:39:01 1999
@@ -14,15 +14,8 @@
X * Modified for x86 hosted builds by Matt Porter <por...@neta.com>
X */
X
-#ifdef linux
-#include <linux/types.h>
-/*#include <asm/stat.h>*/
-/*#include <asm/byteorder.h>*/ /* the byte swap funcs don't work here -- Cort */
-#else
X #include <unistd.h>
-#endif
X #include <sys/stat.h>
-
X #include <stdio.h>
X #include <errno.h>
X
@@ -168,10 +161,10 @@
X /* set entry point and boot image size skipping over elf header */
X #ifdef __i386__
X *entry = 0x400/*+65536*/;
- *length = info.st_size+0x400;
+ *length = info.st_size-elfhdr_size+0x400;
X #else
X *entry = cpu_to_le32(0x400/*+65536*/);
- *length = cpu_to_le32(info.st_size+0x400);
+ *length = cpu_to_le32(info.st_size-elfhdr_size+0x400);
X #endif /* __i386__ */
X
X /* sets magic number for msdos partition (used by linux) */
diff -u --recursive --new-file v2.2.7/linux/arch/ppc/common_defconfig linux/arch/ppc/common_defconfig
--- v2.2.7/linux/arch/ppc/common_defconfig Tue Mar 23 14:35:46 1999
+++ linux/arch/ppc/common_defconfig Tue May 11 08:24:32 1999
@@ -1,5 +1,5 @@
X #
-# Automatically generated by make menuconfig: don't edit
+# Automatically generated make config: don't edit
X #
X
X #
@@ -42,13 +42,13 @@
X CONFIG_MAC_KEYBOARD=y
X CONFIG_MAC_FLOPPY=y
X CONFIG_MAC_SERIAL=y
+# CONFIG_SERIAL_CONSOLE is not set
X CONFIG_ADBMOUSE=y
-CONFIG_BLK_DEV_IDE_PMAC=y
X CONFIG_PROC_DEVICETREE=y
-# CONFIG_KGDB is not set
-# CONFIG_XMON is not set
X # CONFIG_TOTALMP is not set
X CONFIG_BOOTX_TEXT=y
+# CONFIG_MOTOROLA_HOTSWAP is not set
+# CONFIG_CMDLINE_BOOL is not set
X
X #
X # Plug and Play support
@@ -60,6 +60,10 @@
X #
X # CONFIG_BLK_DEV_FD is not set
X CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
X # CONFIG_BLK_DEV_HD_IDE is not set
X CONFIG_BLK_DEV_IDEDISK=y
X CONFIG_BLK_DEV_IDECD=y
@@ -70,8 +74,14 @@
X # CONFIG_BLK_DEV_RZ1000 is not set
X # CONFIG_BLK_DEV_IDEPCI is not set
X # CONFIG_BLK_DEV_SL82C105 is not set
+CONFIG_BLK_DEV_IDE_PMAC=y
+# CONFIG_BLK_DEV_IDEDMA_PMAC is not set
X # CONFIG_IDE_CHIPSETS is not set
-# CONFIG_BLK_DEV_LOOP is not set
+
+#
+# Additional Block Devices
+#
+CONFIG_BLK_DEV_LOOP=y
X # CONFIG_BLK_DEV_NBD is not set
X # CONFIG_BLK_DEV_MD is not set
X CONFIG_BLK_DEV_RAM=y
@@ -101,10 +111,17 @@
X # CONFIG_IP_MROUTE is not set
X CONFIG_IP_ALIAS=y
X # CONFIG_SYN_COOKIES is not set
+
+#
+# (it is safe to leave these untouched)
+#
X CONFIG_INET_RARP=y
-CONFIG_IP_NOSR=y
X CONFIG_SKB_LARGE=y
X # CONFIG_IPV6 is not set
+
+#
+#
+#
X # CONFIG_IPX is not set
X CONFIG_ATALK=m
X # CONFIG_X25 is not set
@@ -126,12 +143,20 @@
X # SCSI support
X #
X CONFIG_SCSI=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
X CONFIG_BLK_DEV_SD=y
X CONFIG_CHR_DEV_ST=y
X CONFIG_BLK_DEV_SR=y
X CONFIG_BLK_DEV_SR_VENDOR=y
-# CONFIG_CHR_DEV_SG is not set
-# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_CHR_DEV_SG=y
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
X CONFIG_SCSI_CONSTANTS=y
X # CONFIG_SCSI_LOGGING is not set
X
@@ -159,10 +184,15 @@
X # CONFIG_SCSI_FUTURE_DOMAIN is not set
X # CONFIG_SCSI_GDTH is not set
X # CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_G_NCR5380_PORT is not set
+# CONFIG_SCSI_G_NCR5380_MEM is not set
X # CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
X # CONFIG_SCSI_NCR53C406A is not set
+# CONFIG_SCSI_SYM53C416 is not set
X # CONFIG_SCSI_NCR53C7xx is not set
X CONFIG_SCSI_NCR53C8XX=y
+# CONFIG_SCSI_SYM53C8XX is not set
X CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8
X CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32
X CONFIG_SCSI_NCR53C8XX_SYNC=20
@@ -175,6 +205,7 @@
X # CONFIG_SCSI_PSI240I is not set
X # CONFIG_SCSI_QLOGIC_FAS is not set
X # CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
X # CONFIG_SCSI_SEAGATE is not set
X # CONFIG_SCSI_DC390T is not set
X # CONFIG_SCSI_T128 is not set
@@ -205,7 +236,7 @@
X # CONFIG_ACENIC is not set
X # CONFIG_NET_ISA is not set
X CONFIG_NET_EISA=y
-# CONFIG_PCNET32 is not set
+CONFIG_PCNET32=y
X # CONFIG_AC3200 is not set
X # CONFIG_APRICOT is not set
X # CONFIG_CS89x0 is not set
@@ -229,6 +260,10 @@
X # CONFIG_COPS is not set
X # CONFIG_IPDDP is not set
X CONFIG_PPP=y
+
+#
+# CCP compressors for PPP are only built as modules.
+#
X # CONFIG_SLIP is not set
X # CONFIG_NET_RADIO is not set
X # CONFIG_TR is not set
@@ -256,22 +291,37 @@
X # Console drivers
X #
X CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FB_PM2 is not set
X CONFIG_FB_OF=y
X CONFIG_FB_CONTROL=y
X CONFIG_FB_PLATINUM=y
X CONFIG_FB_VALKYRIE=y
-CONFIG_FB_ATY=y
+# CONFIG_FB_ATY is not set
X CONFIG_FB_IMSTT=y
X CONFIG_FB_CT65550=y
X # CONFIG_FB_S3TRIO is not set
-# CONFIG_FB_MATROX is not set
-CONFIG_FB_ATY=y
+CONFIG_FB_MATROX=y
+CONFIG_FB_MATROX_MILLENIUM=y
+CONFIG_FB_MATROX_MYSTIQUE=y
+CONFIG_FB_MATROX_G100=y
+# CONFIG_FB_MATROX_MULTIHEAD is not set
+# CONFIG_FB_ATY is not set
X # CONFIG_FB_VIRTUAL is not set
-# CONFIG_FBCON_ADVANCED is not set
+CONFIG_FBCON_ADVANCED=y
+# CONFIG_FBCON_MFB is not set
+# CONFIG_FBCON_CFB2 is not set
+# CONFIG_FBCON_CFB4 is not set
X CONFIG_FBCON_CFB8=y
X CONFIG_FBCON_CFB16=y
X CONFIG_FBCON_CFB24=y
X CONFIG_FBCON_CFB32=y
+# CONFIG_FBCON_AFB is not set
+# CONFIG_FBCON_ILBM is not set
+# CONFIG_FBCON_IPLAN2P2 is not set
+# CONFIG_FBCON_IPLAN2P4 is not set
+# CONFIG_FBCON_IPLAN2P8 is not set
+# CONFIG_FBCON_MAC is not set
+# CONFIG_FBCON_VGA is not set
X # CONFIG_FBCON_FONTWIDTH8_ONLY is not set
X CONFIG_FBCON_FONTS=y
X # CONFIG_FONT_8x8 is not set
@@ -287,12 +337,22 @@
X #
X CONFIG_VT=y
X CONFIG_VT_CONSOLE=y
-# CONFIG_SERIAL is not set
+CONFIG_SERIAL=m
X # CONFIG_SERIAL_EXTENDED is not set
X # CONFIG_SERIAL_NONSTANDARD is not set
X CONFIG_UNIX98_PTYS=y
X CONFIG_UNIX98_PTY_COUNT=256
-# CONFIG_MOUSE is not set
+CONFIG_MOUSE=y
+
+#
+# Mice
+#
+# CONFIG_ATIXL_BUSMOUSE is not set
+# CONFIG_BUSMOUSE is not set
+# CONFIG_MS_BUSMOUSE is not set
+CONFIG_PSMOUSE=y
+# CONFIG_82C710_MOUSE is not set
+# CONFIG_PC110_PAD is not set
X # CONFIG_QIC02_TAPE is not set
X # CONFIG_WATCHDOG is not set
X # CONFIG_NVRAM is not set
@@ -307,11 +367,20 @@
X # Joystick support
X #
X # CONFIG_JOYSTICK is not set
+# CONFIG_DTLK is not set
X
X #
X # Ftape, the floppy tape device driver
X #
X # CONFIG_FTAPE is not set
+# CONFIG_FT_NORMAL_DEBUG is not set
+# CONFIG_FT_FULL_DEBUG is not set
+# CONFIG_FT_NO_TRACE is not set
+# CONFIG_FT_NO_TRACE_AT_ALL is not set
+# CONFIG_FT_STD_FDC is not set
+# CONFIG_FT_MACH2 is not set
+# CONFIG_FT_PROBE_FC10 is not set
+# CONFIG_FT_ALT_FDC is not set
X
X #
X # Filesystems
@@ -402,3 +471,10 @@
X # CONFIG_SOUND_MSNDCLAS is not set
X # CONFIG_SOUND_MSNDPIN is not set
X # CONFIG_SOUND_OSS is not set
+
+#
+# Kernel hacking
+#
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_KGDB is not set
+# CONFIG_XMON is not set
diff -u --recursive --new-file v2.2.7/linux/arch/ppc/config.in linux/arch/ppc/config.in
--- v2.2.7/linux/arch/ppc/config.in Tue Mar 23 14:35:46 1999
+++ linux/arch/ppc/config.in Tue May 11 08:24:32 1999
@@ -1,4 +1,4 @@
-# $Id: config.in,v 1.84 1999/02/23 08:08:38 davem Exp $
+# $Id: config.in,v 1.92 1999/04/30 05:41:43 cort Exp $
X # For a description of the syntax of this configuration file,
X # see the Configure script.
X #
@@ -19,12 +19,10 @@
X APUS CONFIG_APUS \
X MBX CONFIG_MBX" PowerMac
X
+bool 'Symmetric multi-processing support' CONFIG_SMP
X if [ "$CONFIG_ALL_PPC" != "y" ];then
X define_bool CONFIG_MACH_SPECIFIC y
X fi
-
-bool 'Symmetric multi-processing support' CONFIG_SMP
-
X endmenu
X
X if [ "$CONFIG_MBX" = "y" ];then
@@ -82,13 +80,20 @@
X bool 'Support for PowerMac keyboard' CONFIG_MAC_KEYBOARD
X bool 'Support for PowerMac floppy' CONFIG_MAC_FLOPPY
X bool 'Support for PowerMac serial ports' CONFIG_MAC_SERIAL
+if [ "$CONFIG_MAC_SERIAL" = "y" ]; then


+ bool ' Support for console on serial port' CONFIG_SERIAL_CONSOLE

+fi
X bool 'Support for PowerMac ADB mouse' CONFIG_ADBMOUSE
-bool 'Support for PowerMac IDE devices (must also enable IDE)' CONFIG_BLK_DEV_IDE_PMAC
X bool 'Support for Open Firmware device tree in /proc' CONFIG_PROC_DEVICETREE
-bool 'Include kgdb kernel debugger' CONFIG_KGDB
-bool 'Include xmon kernel debugger' CONFIG_XMON
X bool 'Support for TotalImpact TotalMP' CONFIG_TOTALMP
X bool 'Support for early boot text console (BootX only)' CONFIG_BOOTX_TEXT
+bool 'Support for Motorola Hot Swap' CONFIG_MOTOROLA_HOTSWAP
+if [ "$CONFIG_PREP" = "y" -o "$CONFIG_ALL_PPC" = "y" ]; then
+ bool 'PReP bootloader kernel arguments' CONFIG_CMDLINE_BOOL y
+ if [ "$CONFIG_CMDLINE_BOOL" = "y" ] ; then
+ string 'Initial kernel command string' CONFIG_CMDLINE console=ttyS0,9600 console=tty0 root=/dev/sda2
+ fi
+fi
X
X if [ "$CONFIG_APUS" = "y" ]; then
X define_bool CONFIG_FB_CONSOLE y
@@ -176,4 +181,12 @@
X source drivers/sound/Config.in
X fi
X
+endmenu
+
+mainmenu_option next_comment
+comment 'Kernel hacking'
+
+bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
+bool 'Include kgdb kernel debugger' CONFIG_KGDB
+bool 'Include xmon kernel debugger' CONFIG_XMON
X endmenu
diff -u --recursive --new-file v2.2.7/linux/arch/ppc/defconfig linux/arch/ppc/defconfig
--- v2.2.7/linux/arch/ppc/defconfig Tue Mar 23 14:35:46 1999
+++ linux/arch/ppc/defconfig Tue May 11 08:24:32 1999
@@ -8,13 +8,12 @@
X CONFIG_PPC=y
X CONFIG_6xx=y
X # CONFIG_8xx is not set
-CONFIG_PMAC=y
+# CONFIG_PMAC is not set
X # CONFIG_PREP is not set
X # CONFIG_CHRP is not set
-# CONFIG_ALL_PPC is not set
+CONFIG_ALL_PPC=y
X # CONFIG_APUS is not set
X # CONFIG_MBX is not set
-CONFIG_MACH_SPECIFIC=y
X # CONFIG_SMP is not set
X
X #
@@ -36,20 +35,20 @@
X CONFIG_BINFMT_MISC=m
X # CONFIG_BINFMT_JAVA is not set
X # CONFIG_PARPORT is not set
-# CONFIG_VGA_CONSOLE is not set
+CONFIG_VGA_CONSOLE=y
X CONFIG_FB=y
X CONFIG_FB_COMPAT_XPMAC=y
X CONFIG_PMAC_PBOOK=y
X CONFIG_MAC_KEYBOARD=y
X CONFIG_MAC_FLOPPY=y
X CONFIG_MAC_SERIAL=y
+# CONFIG_SERIAL_CONSOLE is not set
X CONFIG_ADBMOUSE=y
-CONFIG_BLK_DEV_IDE_PMAC=y
X CONFIG_PROC_DEVICETREE=y
-# CONFIG_KGDB is not set
-# CONFIG_XMON is not set
X # CONFIG_TOTALMP is not set
X CONFIG_BOOTX_TEXT=y
+# CONFIG_MOTOROLA_HOTSWAP is not set
+# CONFIG_CMDLINE_BOOL is not set
X
X #
X # Plug and Play support
@@ -76,15 +75,13 @@
X # CONFIG_BLK_DEV_IDEPCI is not set
X # CONFIG_BLK_DEV_SL82C105 is not set
X CONFIG_BLK_DEV_IDE_PMAC=y
-CONFIG_BLK_DEV_IDEDMA_PMAC=y
-CONFIG_BLK_DEV_IDEDMA=y
-CONFIG_PMAC_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_IDEDMA_PMAC is not set
X # CONFIG_IDE_CHIPSETS is not set
X
X #
X # Additional Block Devices
X #
-# CONFIG_BLK_DEV_LOOP is not set
+CONFIG_BLK_DEV_LOOP=y
X # CONFIG_BLK_DEV_NBD is not set
X # CONFIG_BLK_DEV_MD is not set
X CONFIG_BLK_DEV_RAM=y
@@ -119,7 +116,6 @@
X # (it is safe to leave these untouched)
X #
X CONFIG_INET_RARP=y
-CONFIG_IP_NOSR=y
X CONFIG_SKB_LARGE=y
X # CONFIG_IPV6 is not set
X
@@ -155,12 +151,12 @@
X CONFIG_CHR_DEV_ST=y
X CONFIG_BLK_DEV_SR=y
X CONFIG_BLK_DEV_SR_VENDOR=y
-# CONFIG_CHR_DEV_SG is not set
+CONFIG_CHR_DEV_SG=y
X
X #
X # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
X #
-# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_MULTI_LUN=y
X CONFIG_SCSI_CONSTANTS=y
X # CONFIG_SCSI_LOGGING is not set
X
@@ -188,16 +184,28 @@
X # CONFIG_SCSI_FUTURE_DOMAIN is not set
X # CONFIG_SCSI_GDTH is not set
X # CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_G_NCR5380_PORT is not set
+# CONFIG_SCSI_G_NCR5380_MEM is not set
X # CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
X # CONFIG_SCSI_NCR53C406A is not set
+# CONFIG_SCSI_SYM53C416 is not set
X # CONFIG_SCSI_NCR53C7xx is not set
-# CONFIG_SCSI_NCR53C8XX is not set
+CONFIG_SCSI_NCR53C8XX=y
+# CONFIG_SCSI_SYM53C8XX is not set
+CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8
+CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32
+CONFIG_SCSI_NCR53C8XX_SYNC=20
+# CONFIG_SCSI_NCR53C8XX_PROFILE is not set
+# CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set
+# CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set
X # CONFIG_SCSI_PAS16 is not set
X # CONFIG_SCSI_PCI2000 is not set
X # CONFIG_SCSI_PCI2220I is not set
X # CONFIG_SCSI_PSI240I is not set
X # CONFIG_SCSI_QLOGIC_FAS is not set
X # CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
X # CONFIG_SCSI_SEAGATE is not set
X # CONFIG_SCSI_DC390T is not set
X # CONFIG_SCSI_T128 is not set
@@ -228,7 +236,7 @@
X # CONFIG_ACENIC is not set
X # CONFIG_NET_ISA is not set
X CONFIG_NET_EISA=y
-# CONFIG_PCNET32 is not set
+CONFIG_PCNET32=y
X # CONFIG_AC3200 is not set
X # CONFIG_APRICOT is not set
X # CONFIG_CS89x0 is not set
@@ -275,7 +283,7 @@
X # CONFIG_ISDN is not set
X
X #
-# CD-ROM drivers (not for SCSI or IDE/ATAPI drives)
+# Old CD-ROM drivers (not SCSI, not IDE)
X #
X # CONFIG_CD_NO_IDESCSI is not set
X
@@ -283,22 +291,37 @@
X # Console drivers
X #
X CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FB_PM2 is not set
X CONFIG_FB_OF=y
X CONFIG_FB_CONTROL=y
X CONFIG_FB_PLATINUM=y
X CONFIG_FB_VALKYRIE=y
-CONFIG_FB_ATY=y
+# CONFIG_FB_ATY is not set
X CONFIG_FB_IMSTT=y
X CONFIG_FB_CT65550=y
X # CONFIG_FB_S3TRIO is not set
-# CONFIG_FB_MATROX is not set
-CONFIG_FB_ATY=y
+CONFIG_FB_MATROX=y
+CONFIG_FB_MATROX_MILLENIUM=y
+CONFIG_FB_MATROX_MYSTIQUE=y
+CONFIG_FB_MATROX_G100=y
+# CONFIG_FB_MATROX_MULTIHEAD is not set
+# CONFIG_FB_ATY is not set
X # CONFIG_FB_VIRTUAL is not set
-# CONFIG_FBCON_ADVANCED is not set
+CONFIG_FBCON_ADVANCED=y
+# CONFIG_FBCON_MFB is not set
+# CONFIG_FBCON_CFB2 is not set
+# CONFIG_FBCON_CFB4 is not set
X CONFIG_FBCON_CFB8=y
X CONFIG_FBCON_CFB16=y
X CONFIG_FBCON_CFB24=y
X CONFIG_FBCON_CFB32=y
+# CONFIG_FBCON_AFB is not set
+# CONFIG_FBCON_ILBM is not set
+# CONFIG_FBCON_IPLAN2P2 is not set
+# CONFIG_FBCON_IPLAN2P4 is not set
+# CONFIG_FBCON_IPLAN2P8 is not set
+# CONFIG_FBCON_MAC is not set
+# CONFIG_FBCON_VGA is not set
X # CONFIG_FBCON_FONTWIDTH8_ONLY is not set
X CONFIG_FBCON_FONTS=y
X # CONFIG_FONT_8x8 is not set
@@ -314,15 +337,25 @@
X #
X CONFIG_VT=y
X CONFIG_VT_CONSOLE=y
-# CONFIG_SERIAL is not set
+CONFIG_SERIAL=m
X # CONFIG_SERIAL_EXTENDED is not set
X # CONFIG_SERIAL_NONSTANDARD is not set
X CONFIG_UNIX98_PTYS=y
X CONFIG_UNIX98_PTY_COUNT=256
-# CONFIG_MOUSE is not set
+CONFIG_MOUSE=y
+
+#
+# Mice
+#
+# CONFIG_ATIXL_BUSMOUSE is not set
+# CONFIG_BUSMOUSE is not set
+# CONFIG_MS_BUSMOUSE is not set
+CONFIG_PSMOUSE=y
+# CONFIG_82C710_MOUSE is not set
+# CONFIG_PC110_PAD is not set
X # CONFIG_QIC02_TAPE is not set
X # CONFIG_WATCHDOG is not set
-CONFIG_NVRAM=y
+# CONFIG_NVRAM is not set
X # CONFIG_RTC is not set
X
X #
@@ -334,11 +367,20 @@
X # Joystick support
X #
X # CONFIG_JOYSTICK is not set
+# CONFIG_DTLK is not set
X
X #
X # Ftape, the floppy tape device driver
X #
X # CONFIG_FTAPE is not set
+# CONFIG_FT_NORMAL_DEBUG is not set
+# CONFIG_FT_FULL_DEBUG is not set
+# CONFIG_FT_NO_TRACE is not set
+# CONFIG_FT_NO_TRACE_AT_ALL is not set
+# CONFIG_FT_STD_FDC is not set
+# CONFIG_FT_MACH2 is not set
+# CONFIG_FT_PROBE_FC10 is not set
+# CONFIG_FT_ALT_FDC is not set
X
X #
X # Filesystems
@@ -429,3 +471,10 @@
X # CONFIG_SOUND_MSNDCLAS is not set
X # CONFIG_SOUND_MSNDPIN is not set
X # CONFIG_SOUND_OSS is not set
+
+#
+# Kernel hacking
+#
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_KGDB is not set
+# CONFIG_XMON is not set
diff -u --recursive --new-file v2.2.7/linux/arch/ppc/kernel/Makefile linux/arch/ppc/kernel/Makefile
--- v2.2.7/linux/arch/ppc/kernel/Makefile Mon Dec 28 15:00:52 1998
+++ linux/arch/ppc/kernel/Makefile Thu Apr 29 12:39:01 1999
@@ -27,7 +27,7 @@
X endif
X
X ifeq ($(CONFIG_MBX),y)
-O_OBJS += mbx_setup.o mbx_pci.o softemu8xx.o
+O_OBJS += mbx_setup.o mbx_pci.o softemu8xx.o i8259.o ppc8xx_pic.o
X else
X ifeq ($(CONFIG_APUS),y)
X O_OBJS += apus_setup.o prom.o openpic.o
@@ -36,7 +36,8 @@
X O_OBJS += prep_time.o pmac_time.o chrp_time.o \
X pmac_setup.o pmac_support.o \
X prep_pci.o pmac_pci.o chrp_pci.o \
- residual.o prom.o openpic.o feature.o
+ residual.o prom.o openpic.o feature.o \
+ prep_nvram.o open_pic.o i8259.o pmac_pic.o indirect_pci.o
X OX_OBJS += chrp_setup.o prep_setup.o
X endif
X endif
diff -u --recursive --new-file v2.2.7/linux/arch/ppc/kernel/align.c linux/arch/ppc/kernel/align.c
--- v2.2.7/linux/arch/ppc/kernel/align.c Mon Oct 5 13:13:36 1998
+++ linux/arch/ppc/kernel/align.c Thu Apr 29 12:39:01 1999
@@ -194,13 +194,8 @@
X return -EFAULT; /* bad address */
X }
X
-#ifdef __SMP__
- if ((flags & F) && (regs->msr & MSR_FP) )
- smp_giveup_fpu(current);
-#else
- if ((flags & F) && last_task_used_math == current)
- giveup_fpu();
-#endif
+ if ((flags & F) && (regs->msr & MSR_FP))
+ giveup_fpu(current);
X if (flags & M)
X return 0; /* too hard for now */
X
@@ -254,27 +249,16 @@
X data.d = current->tss.fpr[reg];
X break;
X /* these require some floating point conversions... */
- /* note that giveup_fpu enables the FPU for the kernel */
X /* we'd like to use the assignment, but we have to compile
X * the kernel with -msoft-float so it doesn't use the
X * fp regs for copying 8-byte objects. */
X case LD+F+S:
-#ifdef __SMP__
- if (regs->msr & MSR_FP )
- smp_giveup_fpu(current);
-#else
- giveup_fpu();
-#endif
+ enable_kernel_fp();
X cvt_fd(&data.f, &current->tss.fpr[reg], &current->tss.fpscr);
X /* current->tss.fpr[reg] = data.f; */
X break;
X case ST+F+S:
-#ifdef __SMP__
- if (regs->msr & MSR_FP )
- smp_giveup_fpu(current);
-#else
- giveup_fpu();
-#endif
+ enable_kernel_fp();
X cvt_df(&current->tss.fpr[reg], &data.f, &current->tss.fpscr);
X /* data.f = current->tss.fpr[reg]; */
X break;
diff -u --recursive --new-file v2.2.7/linux/arch/ppc/kernel/apus_setup.c linux/arch/ppc/kernel/apus_setup.c
--- v2.2.7/linux/arch/ppc/kernel/apus_setup.c Tue Dec 22 14:16:54 1998
+++ linux/arch/ppc/kernel/apus_setup.c Thu Apr 29 12:39:01 1999
@@ -14,12 +14,50 @@
X #include <linux/sched.h>
X #include <linux/kd.h>
X #include <linux/init.h>
+#include <linux/hdreg.h>
+
+/* Get the IDE stuff from the 68k file */
+#define ide_init_hwif_ports m68k_ide_init_hwif_ports
+#define ide_default_irq m68k_ide_default_irq
+#define ide_default_io_base m68k_ide_default_io_base
+#define ide_check_region m68k_ide_check_region
+#define ide_request_region m68k_ide_request_region
+#define ide_release_region m68k_ide_release_region
+#define ide_fix_driveid m68k_ide_fix_driveid
+#include <asm-m68k/ide.h>
+#undef ide_init_hwif_ports
+#define ide_default_irq
+#define ide_default_io_base
+#define ide_check_region
+#define ide_request_region
+#define ide_release_region
+#define ide_fix_driveid
+
X
X #include <asm/setup.h>
X #include <asm/amigahw.h>
X #include <asm/amigappc.h>
X #include <asm/pgtable.h>
X #include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/ide.h>
+
+#include "time.h"
+#include "local_irq.h"
+
+unsigned long apus_get_rtc_time(void);
+int apus_set_rtc_time(unsigned long nowtime);
+
+/* APUS defs */
+extern int parse_bootinfo(const struct bi_record *);
+extern char _end[];
+#ifdef CONFIG_APUS
+struct mem_info ramdisk;
+unsigned long isa_io_base;
+unsigned long isa_mem_base;
+unsigned long pci_dram_offset;
+#endif
+/* END APUS defs */
X
X unsigned long m68k_machtype;
X char debug_device[6] = "";
@@ -72,6 +110,8 @@
X int i;
X char *p, *q;
X
+ m68k_machtype = MACH_AMIGA;
+
X /* Parse the command line for arch-specific options.
X * For the m68k, this is currently only "debug=xxx" to enable printing
X * certain kernel messages to some machine-specific device. */
@@ -408,4 +448,195 @@
X "icbi 0,%0 \n\t"
X "isync \n\t"
X : : "r" (addr));
+}
+
+void
+apus_restart(char *cmd)
+{
+ cli();
+
+ APUS_WRITE(APUS_REG_LOCK,
+ REGLOCK_BLACKMAGICK1|REGLOCK_BLACKMAGICK2);
+ APUS_WRITE(APUS_REG_LOCK,
+ REGLOCK_BLACKMAGICK1|REGLOCK_BLACKMAGICK3);
+ APUS_WRITE(APUS_REG_LOCK,
+ REGLOCK_BLACKMAGICK2|REGLOCK_BLACKMAGICK3);
+ APUS_WRITE(APUS_REG_SHADOW, REGSHADOW_SELFRESET);
+ APUS_WRITE(APUS_REG_RESET, REGRESET_AMIGARESET);
+ for(;;);
+}
+
+void
+apus_power_off(void)


+{
+ for (;;);
+}

+
+void
+apus_halt(void)
+{
+ apus_restart(NULL);
+}
+
+void
+apus_do_IRQ(struct pt_regs *regs,
+ int cpu,
+ int isfake)
+{
+ int old_level, new_level;
+
+ /* I don't think we need SMP code here - Corey */
+
+ old_level = ~(regs->mq) & IPLEMU_IPLMASK;
+ new_level = (~(regs->mq) >> 3) & IPLEMU_IPLMASK;
+ if (new_level != 0)
+ {
+ APUS_WRITE(APUS_IPL_EMU, IPLEMU_IPLMASK);
+ APUS_WRITE(APUS_IPL_EMU, (IPLEMU_SETRESET
+ | (~(new_level) & IPLEMU_IPLMASK)));
+ APUS_WRITE(APUS_IPL_EMU, IPLEMU_DISABLEINT);
+
+ process_int (VEC_SPUR+new_level, regs);
+ APUS_WRITE(APUS_IPL_EMU, IPLEMU_SETRESET | IPLEMU_DISABLEINT);
+ APUS_WRITE(APUS_IPL_EMU, IPLEMU_IPLMASK);
+ APUS_WRITE(APUS_IPL_EMU, (IPLEMU_SETRESET
+ | (~(old_level) & IPLEMU_IPLMASK)));
+ }
+ APUS_WRITE(APUS_IPL_EMU, IPLEMU_DISABLEINT);
+}
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+/*
+ * IDE stuff.
+ */
+void
+apus_ide_insw(ide_ioreg_t port, void *buf, int ns)
+{
+ ide_insw(port, buf, ns);
+}
+
+void
+apus_ide_outsw(ide_ioreg_t port, void *buf, int ns)
+{
+ ide_outsw(port, buf, ns);
+}
+
+int
+apus_ide_default_irq(ide_ioreg_t base)
+{
+ m68k_ide_default_irq(base);
+}
+
+ide_ioreg_t
+apus_ide_default_io_base(int index)
+{
+ m68k_ide_default_io_base(index);
+}
+
+int
+apus_ide_check_region(ide_ioreg_t from, unsigned int extent)
+{
+ return m68k_ide_check_region(from, extent);
+}
+
+void
+apus_ide_request_region(ide_ioreg_t from,
+ unsigned int extent,
+ const char *name)
+{
+ m68k_ide_request_region(from, extent, name);
+}
+
+void
+apus_ide_release_region(ide_ioreg_t from,
+ unsigned int extent)
+{
+ m68k_ide_release_region(from, extent);
+}
+
+void
+apus_ide_fix_driveid(struct hd_driveid *id)
+{
+ m68k_ide_fix_driveid(id);
+}
+
+__initfunc(void
+apus_ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq))
+{
+ m68k_ide_init_hwif_ports(p, base, irq);
+}
+#endif
+
+__initfunc(void
+apus_local_init_IRQ(void))
+{
+ ppc_md.mask_irq = amiga_disable_irq;
+ ppc_md.unmask_irq = amiga_enable_irq;
+ apus_init_IRQ();
+}
+
+__initfunc(void
+apus_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7))
+{
+ /* Parse bootinfo. The bootinfo is located right after
+ the kernel bss */
+ parse_bootinfo((const struct bi_record *)&_end);
+#ifdef CONFIG_BLK_DEV_INITRD
+ /* Take care of initrd if we have one. Use data from
+ bootinfo to avoid the need to initialize PPC
+ registers when kernel is booted via a PPC reset. */
+ if ( ramdisk.addr ) {
+ initrd_start = (unsigned long) __va(ramdisk.addr);
+ initrd_end = (unsigned long)
+ __va(ramdisk.size + ramdisk.addr);
+ }
+ /* Make sure code below is not executed. */
+ r4 = 0;
+ r6 = 0;
+#endif /* CONFIG_BLK_DEV_INITRD */
+
+ ISA_DMA_THRESHOLD = 0x00ffffff;
+
+ ppc_md.setup_arch = apus_setup_arch;
+ ppc_md.setup_residual = NULL;
+ ppc_md.get_cpuinfo = apus_get_cpuinfo;
+ ppc_md.irq_cannonicalize = NULL;
+ ppc_md.init_IRQ = apus_init_IRQ;
+ ppc_md.do_IRQ = apus_do_IRQ;
+ ppc_md.get_irq_source = NULL;
+ ppc_md.init = NULL;
+
+ ppc_md.restart = apus_restart;
+ ppc_md.power_off = apus_power_off;
+ ppc_md.halt = apus_halt;
+
+ ppc_md.time_init = NULL;
+ ppc_md.set_rtc_time = apus_set_rtc_time;
+ ppc_md.get_rtc_time = apus_get_rtc_time;
+ ppc_md.calibrate_decr = apus_calibrate_decr;
+
+ /* These should not be used for the APUS yet, since it uses
+ the M68K keyboard now. */
+ ppc_md.kbd_setkeycode = NULL;
+ ppc_md.kbd_getkeycode = NULL;
+ ppc_md.kbd_translate = NULL;
+ ppc_md.kbd_unexpected_up = NULL;
+ ppc_md.kbd_leds = NULL;
+ ppc_md.kbd_init_hw = NULL;
+ ppc_md.kbd_sysrq_xlate = NULL;
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+ ppc_ide_md.insw = apus_ide_insw;
+ ppc_ide_md.outsw = apus_ide_outsw;
+ ppc_ide_md.default_irq = apus_ide_default_irq;
+ ppc_ide_md.default_io_base = apus_ide_default_io_base;
+ ppc_ide_md.check_region = apus_ide_check_region;
+ ppc_ide_md.request_region = apus_ide_request_region;
+ ppc_ide_md.release_region = apus_ide_release_region;
+ ppc_ide_md.fix_driveid = apus_ide_fix_driveid;
+ ppc_ide_md.ide_init_hwif = apus_ide_init_hwif_ports;
+
+ ppc_ide_md.io_base = _IO_BASE;
+#endif
X }
diff -u --recursive --new-file v2.2.7/linux/arch/ppc/kernel/chrp_pci.c linux/arch/ppc/kernel/chrp_pci.c
--- v2.2.7/linux/arch/ppc/kernel/chrp_pci.c Tue Mar 23 14:35:46 1999
+++ linux/arch/ppc/kernel/chrp_pci.c Tue May 11 08:24:32 1999
@@ -15,10 +15,14 @@
X #include <asm/hydra.h>
X #include <asm/prom.h>
X #include <asm/gg2.h>
+#include <asm/ide.h>
+#include <asm/machdep.h>
+
+#include "pci.h"
X
X /* LongTrail */
X #define pci_config_addr(bus, dev, offset) \
- (GG2_PCI_CONFIG_BASE | ((bus)<<16) | ((dev)<<8) | (offset))
+(GG2_PCI_CONFIG_BASE | ((bus)<<16) | ((dev)<<8) | (offset))
X
X volatile struct Hydra *Hydra = NULL;
X
@@ -30,159 +34,78 @@
X int gg2_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn,
X unsigned char offset, unsigned char *val)
X {
- if (bus > 7) {
- *val = 0xff;
- return PCIBIOS_DEVICE_NOT_FOUND;
- }
- *val = in_8((unsigned char *)pci_config_addr(bus, dev_fn, offset));
- return PCIBIOS_SUCCESSFUL;
+ if (bus > 7) {
+ *val = 0xff;
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+ *val = in_8((unsigned char *)pci_config_addr(bus, dev_fn, offset));
+ return PCIBIOS_SUCCESSFUL;
X }
X
X int gg2_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn,
X unsigned char offset, unsigned short *val)
X {
- if (bus > 7) {
- *val = 0xffff;
- return PCIBIOS_DEVICE_NOT_FOUND;
- }
- *val = in_le16((unsigned short *)pci_config_addr(bus, dev_fn, offset));
- return PCIBIOS_SUCCESSFUL;
+ if (bus > 7) {
+ *val = 0xffff;
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+ *val = in_le16((unsigned short *)pci_config_addr(bus, dev_fn, offset));
+ return PCIBIOS_SUCCESSFUL;
X }
X
X
X int gg2_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn,
X unsigned char offset, unsigned int *val)
X {
- if (bus > 7) {
- *val = 0xffffffff;
- return PCIBIOS_DEVICE_NOT_FOUND;
- }
- *val = in_le32((unsigned int *)pci_config_addr(bus, dev_fn, offset));
- return PCIBIOS_SUCCESSFUL;
+ if (bus > 7) {
+ *val = 0xffffffff;
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+ *val = in_le32((unsigned int *)pci_config_addr(bus, dev_fn, offset));
+ return PCIBIOS_SUCCESSFUL;
X }
X
X int gg2_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn,
X unsigned char offset, unsigned char val)
X {
- if (bus > 7)
- return PCIBIOS_DEVICE_NOT_FOUND;
- out_8((unsigned char *)pci_config_addr(bus, dev_fn, offset), val);
- return PCIBIOS_SUCCESSFUL;
+ if (bus > 7)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ out_8((unsigned char *)pci_config_addr(bus, dev_fn, offset), val);
+ return PCIBIOS_SUCCESSFUL;
X }
X
X int gg2_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn,
X unsigned char offset, unsigned short val)
X {
- if (bus > 7)
- return PCIBIOS_DEVICE_NOT_FOUND;
- out_le16((unsigned short *)pci_config_addr(bus, dev_fn, offset), val);
- return PCIBIOS_SUCCESSFUL;
+ if (bus > 7)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ out_le16((unsigned short *)pci_config_addr(bus, dev_fn, offset), val);
+ return PCIBIOS_SUCCESSFUL;
X }
X
X int gg2_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,
X unsigned char offset, unsigned int val)
X {
- if (bus > 7)
- return PCIBIOS_DEVICE_NOT_FOUND;
- out_le32((unsigned int *)pci_config_addr(bus, dev_fn, offset), val);
- return PCIBIOS_SUCCESSFUL;
-}
-
-extern volatile unsigned int *pci_config_address;
-extern volatile unsigned char *pci_config_data;
-
-#define DEV_FN_MAX (31<<3)
-
-int raven_pcibios_read_config_byte(unsigned char bus,
- unsigned char dev_fn,
- unsigned char offset,
- unsigned char *val)
-{
- if (dev_fn >= DEV_FN_MAX) return PCIBIOS_DEVICE_NOT_FOUND;
- out_be32(pci_config_address,
- 0x80|(bus<<8)|(dev_fn<<16)|((offset&~3)<<24));
- *val = in_8(pci_config_data+(offset&3));
- return PCIBIOS_SUCCESSFUL;
-}
-
-int raven_pcibios_read_config_word(unsigned char bus,
- unsigned char dev_fn,
- unsigned char offset,
- unsigned short *val)
-{
- if (dev_fn >= DEV_FN_MAX) return PCIBIOS_DEVICE_NOT_FOUND;
- if (offset&1)return PCIBIOS_BAD_REGISTER_NUMBER;
- out_be32(pci_config_address,
- 0x80|(bus<<8)|(dev_fn<<16)|((offset&~3)<<24));
- *val = in_le16((volatile unsigned short *)
- (pci_config_data+(offset&3)));
- return PCIBIOS_SUCCESSFUL;
-}
-
-int raven_pcibios_read_config_dword(unsigned char bus,
- unsigned char dev_fn,
- unsigned char offset,
- unsigned int *val)
-{
- if (dev_fn >= DEV_FN_MAX) return PCIBIOS_DEVICE_NOT_FOUND;
- if (offset&3)return PCIBIOS_BAD_REGISTER_NUMBER;
- out_be32(pci_config_address,
- 0x80|(bus<<8)|(dev_fn<<16)|(offset<<24));
- *val = in_le32((volatile unsigned int *)(pci_config_data));
- return PCIBIOS_SUCCESSFUL;
-}
-
-int raven_pcibios_write_config_byte(unsigned char bus,
- unsigned char dev_fn,
- unsigned char offset,
- unsigned char val)
-{
- if (dev_fn >= DEV_FN_MAX) return PCIBIOS_DEVICE_NOT_FOUND;
- out_be32(pci_config_address,
- 0x80|(bus<<8)|(dev_fn<<16)|((offset&~3)<<24));
- out_8(pci_config_data+(offset&3),val);
- return PCIBIOS_SUCCESSFUL;
-}
-
-int raven_pcibios_write_config_word(unsigned char bus,
- unsigned char dev_fn,
- unsigned char offset,
- unsigned short val)
-{
- if (dev_fn >= DEV_FN_MAX) return PCIBIOS_DEVICE_NOT_FOUND;
- if (offset&1)return PCIBIOS_BAD_REGISTER_NUMBER;
- out_be32(pci_config_address,
- 0x80|(bus<<8)|(dev_fn<<16)|((offset&~3)<<24));
- out_le16((volatile unsigned short *)(pci_config_data+(offset&3)),val);
- return PCIBIOS_SUCCESSFUL;
-}
-
-int raven_pcibios_write_config_dword(unsigned char bus,
- unsigned char dev_fn,
- unsigned char offset,
- unsigned int val)
-{
- if (dev_fn >= DEV_FN_MAX) return PCIBIOS_DEVICE_NOT_FOUND;
- if (offset&3)return PCIBIOS_BAD_REGISTER_NUMBER;
- out_be32(pci_config_address,
- 0x80|(bus<<8)|(dev_fn<<16)|(offset<<24));
- out_le32((volatile unsigned int *)pci_config_data,val);
- return PCIBIOS_SUCCESSFUL;
+ if (bus > 7)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ out_le32((unsigned int *)pci_config_addr(bus, dev_fn, offset), val);
+ return PCIBIOS_SUCCESSFUL;
X }
X
X #define python_config_address(bus) (unsigned *)((0xfef00000+0xf8000)-(bus*0x100000))
X #define python_config_data(bus) ((0xfef00000+0xf8010)-(bus*0x100000))
-#define PYTHON_CFA(b, d, o) (0x80 | ((b) << 8) | ((d) << 16) \
+#define PYTHON_CFA(b, d, o) (0x80 | ((b<<6) << 8) | ((d) << 16) \
X | (((o) & ~3) << 24))
-
+unsigned int python_busnr = 1;
+
X int python_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn,
X unsigned char offset, unsigned char *val)
X {
- if (bus > 2) {
+ if (bus > python_busnr) {
X *val = 0xff;
X return PCIBIOS_DEVICE_NOT_FOUND;
X }
- out_be32( python_config_address( bus ), PYTHON_CFA(bus,dev_fn,offset) );
+ out_be32( python_config_address( bus ), PYTHON_CFA(bus,dev_fn,offset));
X *val = in_8((unsigned char *)python_config_data(bus) + (offset&3));
X return PCIBIOS_SUCCESSFUL;
X }
@@ -190,11 +113,11 @@
X int python_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn,
X unsigned char offset, unsigned short *val)
X {
- if (bus > 2) {
+ if (bus > python_busnr) {
X *val = 0xffff;
X return PCIBIOS_DEVICE_NOT_FOUND;
X }
- out_be32( python_config_address( bus ), PYTHON_CFA(bus,dev_fn,offset) );
+ out_be32( python_config_address( bus ), PYTHON_CFA(bus,dev_fn,offset));
X *val = in_le16((unsigned short *)(python_config_data(bus) + (offset&3)));
X return PCIBIOS_SUCCESSFUL;
X }
@@ -203,11 +126,11 @@
X int python_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn,
X unsigned char offset, unsigned int *val)
X {
- if (bus > 2) {
+ if (bus > python_busnr) {
X *val = 0xffffffff;
X return PCIBIOS_DEVICE_NOT_FOUND;
X }
- out_be32( python_config_address( bus ), PYTHON_CFA(bus,dev_fn,offset) );
+ out_be32( python_config_address( bus ), PYTHON_CFA(bus,dev_fn,offset));
X *val = in_le32((unsigned *)python_config_data(bus));
X return PCIBIOS_SUCCESSFUL;
X }
@@ -215,9 +138,9 @@
X int python_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn,
X unsigned char offset, unsigned char val)
X {
- if (bus > 2)
+ if (bus > python_busnr)
X return PCIBIOS_DEVICE_NOT_FOUND;
- out_be32( python_config_address( bus ), PYTHON_CFA(bus,dev_fn,offset) );
+ out_be32( python_config_address( bus ), PYTHON_CFA(bus,dev_fn,offset));
X out_8((volatile unsigned char *)python_config_data(bus) + (offset&3), val);
X return PCIBIOS_SUCCESSFUL;
X }
@@ -225,9 +148,9 @@
X int python_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn,
X unsigned char offset, unsigned short val)
X {
- if (bus > 2)
+ if (bus > python_busnr)
X return PCIBIOS_DEVICE_NOT_FOUND;
- out_be32( python_config_address( bus ), PYTHON_CFA(bus,dev_fn,offset) );
+ out_be32( python_config_address( bus ), PYTHON_CFA(bus,dev_fn,offset));
X out_le16((volatile unsigned short *)python_config_data(bus) + (offset&3),
X val);
X return PCIBIOS_SUCCESSFUL;
@@ -236,9 +159,9 @@
X int python_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,
X unsigned char offset, unsigned int val)
X {
- if (bus > 2)
+ if (bus > python_busnr)
X return PCIBIOS_DEVICE_NOT_FOUND;
- out_be32( python_config_address( bus ), PYTHON_CFA(bus,dev_fn,offset) );
+ out_be32( python_config_address( bus ), PYTHON_CFA(bus,dev_fn,offset));
X out_le32((unsigned *)python_config_data(bus) + (offset&3), val);
X return PCIBIOS_SUCCESSFUL;
X }
@@ -264,7 +187,8 @@
X /* all others are 1 (= default) */
X };
X
-__initfunc(int hydra_init(void))
+int __init
+hydra_init(void)
X {
X struct device_node *np;
X
@@ -287,4 +211,97 @@
X OpenPIC_InitSenses = hydra_openpic_initsenses;
X OpenPIC_NumInitSenses = sizeof(hydra_openpic_initsenses);
X return 1;
+}
+
+void __init
+chrp_pcibios_fixup(void)
+{
+ struct pci_dev *dev;
+
+ /* some of IBM chrps have > 1 bus */
+ if ( !strncmp("IBM", get_property(find_path_device("/"),
+ "name", NULL),3) )
+ {
+ pci_scan_peer_bridge(1);
+ pci_scan_peer_bridge(2);
+ }
+
+ /* PCI interrupts are controlled by the OpenPIC */
+ for( dev=pci_devices ; dev; dev=dev->next )
+ {
+ if ( dev->irq )
+ dev->irq = openpic_to_irq( dev->irq );
+ /* adjust the io_port for the NCR cards for busses other than 0 -- Cort */
+ if ( (dev->bus->number > 0) && (dev->vendor == PCI_VENDOR_ID_NCR) )
+ dev->base_address[0] += (dev->bus->number*0x08000000);
+ /* these need to be absolute addrs for OF and Matrox FB -- Cort */
+ if ( dev->vendor == PCI_VENDOR_ID_MATROX )
+ {
+ if ( dev->base_address[0] < isa_mem_base )
+ dev->base_address[0] += isa_mem_base;
+ if ( dev->base_address[1] < isa_mem_base )
+ dev->base_address[1] += isa_mem_base;
+ }
+ /* the F50 identifies the amd as a trident */
+ if ( (dev->vendor == PCI_VENDOR_ID_TRIDENT) &&
+ (dev->class == PCI_CLASS_NETWORK_ETHERNET) )
+ {
+ dev->vendor = PCI_VENDOR_ID_AMD;
+ pcibios_write_config_word(dev->bus->number, dev->devfn,
+ PCI_VENDOR_ID, PCI_VENDOR_ID_AMD);
+ }
+ }
+}
+
+decl_config_access_method(grackle);
+decl_config_access_method(indirect);
+
+void __init
+chrp_setup_pci_ptrs(void)
+{
+ struct device_node *py;
+
+ if ( !strncmp("MOT",
+ get_property(find_path_device("/"), "model", NULL),3) )
+ {
+ pci_dram_offset = 0;
+ isa_mem_base = 0xf7000000;
+ isa_io_base = 0xfe000000;
+ set_config_access_method(grackle);
+ }
+ else
+ {
+ if ( (py = find_compatible_devices( "pci", "IBM,python" )) )
+ {
+ /* find out how many pythons */
+ while ( (py = py->next) ) python_busnr++;
+ set_config_access_method(python);
+ /*
+ * We base these values on the machine type but should
+ * try to read them from the python controller itself.
+ * -- Cort
+ */
+ if ( !strncmp("IBM,7025-F50", get_property(find_path_device("/"), "name", NULL),12) )
+ {
+ pci_dram_offset = 0x80000000;
+ isa_mem_base = 0xa0000000;
+ isa_io_base = 0x88000000;
+ } else if ( !strncmp("IBM,7043-260",
+ get_property(find_path_device("/"), "name", NULL),12) )
+ {
+ pci_dram_offset = 0x80000000;
+ isa_mem_base = 0xc0000000;
+ isa_io_base = 0xf8000000;
+ }
+ }
+ else
+ {
+ pci_dram_offset = 0;
+ isa_mem_base = 0xf7000000;
+ isa_io_base = 0xf8000000;
+ set_config_access_method(gg2);
+ }
+ }
+
+ ppc_md.pcibios_fixup = chrp_pcibios_fixup;
X }
diff -u --recursive --new-file v2.2.7/linux/arch/ppc/kernel/chrp_setup.c linux/arch/ppc/kernel/chrp_setup.c
--- v2.2.7/linux/arch/ppc/kernel/chrp_setup.c Tue Mar 23 14:35:46 1999
+++ linux/arch/ppc/kernel/chrp_setup.c Tue May 11 08:24:32 1999
@@ -41,8 +41,50 @@
X #include <asm/prom.h>
X #include <asm/gg2.h>
X #include <asm/pci-bridge.h>
-
-extern void hydra_init(void);
+#include <asm/dma.h>
+#include <asm/machdep.h>
+#include <asm/irq.h>
+#include <asm/adb.h>
+#include <asm/hydra.h>
+
+#include "time.h"
+#include "local_irq.h"
+#include "i8259.h"
+#include "open_pic.h"
+
+/* Fixme - need to move these into their own .c and .h file */
+extern void i8259_mask_and_ack_irq(unsigned int irq_nr);
+extern void i8259_set_irq_mask(unsigned int irq_nr);
+extern void i8259_mask_irq(unsigned int irq_nr);
+extern void i8259_unmask_irq(unsigned int irq_nr);
+extern void i8259_init(void);
+
+/* Fixme - remove this when it is fixed. - Corey */
+extern volatile unsigned char *chrp_int_ack_special;
+
+unsigned long chrp_get_rtc_time(void);
+int chrp_set_rtc_time(unsigned long nowtime);
+void chrp_calibrate_decr(void);
+void chrp_time_init(void);
+
+void chrp_setup_pci_ptrs(void);
+
+extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode);
+extern int pckbd_getkeycode(unsigned int scancode);
+extern int pckbd_translate(unsigned char scancode, unsigned char *keycode,
+ char raw_mode);
+extern char pckbd_unexpected_up(unsigned char keycode);
+extern void pckbd_leds(unsigned char leds);
+extern void pckbd_init_hw(void);
+extern unsigned char pckbd_sysrq_xlate[128];
+extern int mackbd_setkeycode(unsigned int scancode, unsigned int keycode);
+extern int mackbd_getkeycode(unsigned int scancode);
+extern int mackbd_translate(unsigned char scancode, unsigned char *keycode,
+ char raw_mode);
+extern char mackbd_unexpected_up(unsigned char keycode);
+extern void mackbd_leds(unsigned char leds);
+extern void mackbd_init_hw(void);
+extern unsigned char mackbd_sysrq_xlate[128];
X
X /* for the mac fs */
X kdev_t boot_dev;
@@ -61,17 +103,17 @@
X #endif
X
X static const char *gg2_memtypes[4] = {
- "FPM", "SDRAM", "EDO", "BEDO"
+ "FPM", "SDRAM", "EDO", "BEDO"
X };
X static const char *gg2_cachesizes[4] = {
- "256 KB", "512 KB", "1 MB", "Reserved"
+ "256 KB", "512 KB", "1 MB", "Reserved"
X };
X static const char *gg2_cachetypes[4] = {
- "Asynchronous", "Reserved", "Flow-Through Synchronous",
- "Pipelined Synchronous"
+ "Asynchronous", "Reserved", "Flow-Through Synchronous",
+ "Pipelined Synchronous"
X };
X static const char *gg2_cachemodes[4] = {
- "Disabled", "Write-Through", "Copy-Back", "Transparent Mode"
+ "Disabled", "Write-Through", "Copy-Back", "Transparent Mode"
X };
X
X int
@@ -84,7 +126,7 @@
X
X root = find_path_device("/");
X if (root)
- model = get_property(root, "model", NULL);
+ model = get_property(root, "model", NULL);
X len = sprintf(buffer,"machine\t\t: CHRP %s\n", model);
X
X /* longtrail (goldengate) stuff */
@@ -137,7 +179,7 @@
X return len;
X }
X
- /*
+/*
X * Fixes for the National Semiconductor PC78308VUL SuperI/O
X *
X * Some versions of Open Firmware incorrectly initialize the IRQ settings
@@ -146,56 +188,56 @@
X
X __initfunc(static inline void sio_write(u8 val, u8 index))
X {
- outb(index, 0x15c);
- outb(val, 0x15d);
+ outb(index, 0x15c);
+ outb(val, 0x15d);
X }
X
X __initfunc(static inline u8 sio_read(u8 index))
X {
- outb(index, 0x15c);
- return inb(0x15d);
+ outb(index, 0x15c);
+ return inb(0x15d);
X }
X
X __initfunc(static void sio_fixup_irq(const char *name, u8 device, u8 level,
X u8 type))
X {
- u8 level0, type0, active;
+ u8 level0, type0, active;
X
- /* select logical device */
- sio_write(device, 0x07);
- active = sio_read(0x30);
- level0 = sio_read(0x70);
- type0 = sio_read(0x71);
- printk("sio: %s irq level %d, type %d, %sactive: ", name, level0, type0,
- !active ? "in" : "");
- if (level0 == level && type0 == type && active)
- printk("OK\n");
- else {
- printk("remapping to level %d, type %d, active\n", level, type);
- sio_write(0x01, 0x30);
- sio_write(level, 0x70);
- sio_write(type, 0x71);
- }
+ /* select logical device */
+ sio_write(device, 0x07);
+ active = sio_read(0x30);
+ level0 = sio_read(0x70);
+ type0 = sio_read(0x71);
+ printk("sio: %s irq level %d, type %d, %sactive: ", name, level0, type0,
+ !active ? "in" : "");
+ if (level0 == level && type0 == type && active)
+ printk("OK\n");
+ else {
+ printk("remapping to level %d, type %d, active\n", level, type);
+ sio_write(0x01, 0x30);
+ sio_write(level, 0x70);
+ sio_write(type, 0x71);
+ }
X
X }
X
X __initfunc(static void sio_init(void))
X {
- /* logical device 0 (KBC/Keyboard) */
- sio_fixup_irq("keyboard", 0, 1, 2);
- /* select logical device 1 (KBC/Mouse) */
- sio_fixup_irq("mouse", 1, 12, 2);
+ /* logical device 0 (KBC/Keyboard) */
+ sio_fixup_irq("keyboard", 0, 1, 2);
+ /* select logical device 1 (KBC/Mouse) */
+ sio_fixup_irq("mouse", 1, 12, 2);
X }
X
X
X __initfunc(void
-chrp_setup_arch(unsigned long * memory_start_p, unsigned long * memory_end_p))
+ chrp_setup_arch(unsigned long * memory_start_p, unsigned long * memory_end_p))
X {
X extern char cmd_line[];
X
X /* init to some ~sane value until calibrate_delay() runs */
X loops_per_sec = 50000000;
-
+
X #ifdef CONFIG_BLK_DEV_INITRD
X /* this is fine for chrp */
X initrd_below_start_ok = 1;
@@ -243,27 +285,210 @@
X if ( !strncmp("MOT", get_property(find_path_device("/"),
X "model", NULL),3) )
X *memory_start_p = pmac_find_bridges(*memory_start_p, *memory_end_p);
+ /*
+ * The f50 has a lot of IO space - we need to map some in that
+ * isn't covered by the BAT mappings in MMU_init() -- Cort
+ */
+ if ( !strncmp("F5", get_property(find_path_device("/"),
+ "ibm,model-class", NULL),2) )
+ {
+#if 0
+ /*
+ * This ugly hack allows us to force ioremap() to
+ * create a 1-to-1 mapping for us, even though
+ * the address is < ioremap_base. This is necessary
+ * since we want our PCI IO space to have contiguous
+ * virtual addresses and I think it's worse to have
+ * calls to map_page() here.
+ * -- Cort
+ */
+ unsigned long hold = ioremap_base;
+ ioremap_base = 0;
+ __ioremap(0x90000000, 0x10000000, _PAGE_NO_CACHE);
+ ioremap_base = hold;
+#endif
+ }
X }
X
-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+void
+chrp_restart(char *cmd)
+{
+#if 0
+ extern unsigned int rtas_entry, rtas_data, rtas_size;
+ printk("RTAS system-reboot returned %d\n",
+ call_rtas("system-reboot", 0, 1, NULL));
+ printk("rtas_entry: %08lx rtas_data: %08lx rtas_size: %08lx\n",
+ rtas_entry,rtas_data,rtas_size);
+ for (;;);
+#else
+ printk("System Halted\n");
+ while(1);
+#endif
+}
X
-unsigned int chrp_ide_irq = 0;
-int chrp_ide_ports_known = 0;
-ide_ioreg_t chrp_ide_regbase[MAX_HWIFS];
-ide_ioreg_t chrp_idedma_regbase;
+void
+chrp_power_off(void)
+{
+ /* RTAS doesn't seem to work on Longtrail.
+ For now, do it the same way as the PReP. */
+#if 0
+ extern unsigned int rtas_entry, rtas_data, rtas_size;
+ printk("RTAS power-off returned %d\n",
+ call_rtas("power-off", 2, 1, NULL, 0, 0));
+ printk("rtas_entry: %08lx rtas_data: %08lx rtas_size: %08lx\n",
+ rtas_entry,rtas_data,rtas_size);
+ for (;;);
+#else
+ chrp_restart(NULL);
+#endif
+}
X
-void chrp_ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq)
+void
+chrp_halt(void)
X {
- ide_ioreg_t port = base;
- int i = 8;
+ chrp_restart(NULL);
+}
X
- while (i--)
- *p++ = port++;
- *p++ = port;
- if (irq != NULL)
- *irq = chrp_ide_irq;
+u_int
+chrp_irq_cannonicalize(u_int irq)
+{
+ if (irq == 2)
+ {
+ return 9;
+ }
+ else
+ {
+ return irq;
+ }
+}
+
+void
+chrp_do_IRQ(struct pt_regs *regs,
+ int cpu,
+ int isfake)
+{
+ int irq;
+ unsigned long bits = 0;
+ int openpic_eoi_done = 0;
+
+#ifdef __SMP__
+ {
+ unsigned int loops = 1000000;
+ while (test_bit(0, &global_irq_lock)) {
+ if (smp_processor_id() == global_irq_holder) {
+ printk("uh oh, interrupt while we hold global irq lock!\n");
+#ifdef CONFIG_XMON
+ xmon(0);
+#endif
+ break;
+ }
+ if (loops-- == 0) {
+ printk("do_IRQ waiting for irq lock (holder=%d)\n", global_irq_holder);
+#ifdef CONFIG_XMON
+ xmon(0);
+#endif
+ }
+ }
+ }
+#endif /* __SMP__ */
+
+ irq = openpic_irq(0);
+ if (irq == IRQ_8259_CASCADE)
+ {
+ /*
+ * This magic address generates a PCI IACK cycle.
+ *
+ * This should go in the above mask/ack code soon. -- Cort
+ */
+ if ( chrp_int_ack_special )
+ irq = *chrp_int_ack_special;
+ else
+ irq = i8259_irq(0);
+ /*
+ * Acknowledge as soon as possible to allow i8259
+ * interrupt nesting */
+ openpic_eoi(0);
+ openpic_eoi_done = 1;
+ }
+ if (irq == OPENPIC_VEC_SPURIOUS)
+ {
+ /*
+ * Spurious interrupts should never be
+ * acknowledged
+ */
+ ppc_spurious_interrupts++;


SHAR_EOF
true || echo 'restore of patch-2.2.8 failed'
fi

echo 'End of part 08'
echo 'File patch-2.2.8 is continued in part 09'
echo 09 > _shar_seq_.tmp

Thomas...@ciw.uni-karlsruhe.de

unread,
May 12, 1999, 3:00:00 AM5/12/99
to
Archive-name: v2.2/patch-2.2.8/part09

#!/bin/sh
# this is part 09 of a 33 - part archive


# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.8 continued
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 09; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.8'
else
echo 'x - continuing with patch-2.2.8'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.8' &&

+ openpic_eoi_done = 1;
+ goto out;
+ }
+ bits = 1UL << irq;
+
+ if (irq < 0)
+ {
+ printk(KERN_DEBUG "Bogus interrupt %d from PC = %lx\n",
+ irq, regs->nip);
+ ppc_spurious_interrupts++;
+ }
+ else
+ {
+ ppc_irq_dispatch_handler( regs, irq );
+ }
+out:
+ if (!openpic_eoi_done)
+ openpic_eoi(0);
X }
X
+__initfunc(void
+ chrp_init_IRQ(void))
+{
+ struct device_node *np;
+ int i;
+
+ if ( !(np = find_devices("pci") ) )
+ printk("Cannot find pci to get ack address\n");
+ else
+ {
+ chrp_int_ack_special = (volatile unsigned char *)
+ (*(unsigned long *)get_property(np,
+ "8259-interrupt-acknowledge", NULL));
+ }
+ for ( i = 16 ; i < NR_IRQS ; i++ )
+ irq_desc[i].ctl = &open_pic;
+ /* openpic knows that it's at irq 16 offset
+ * so we don't need to set it in the pic structure


+ * -- Cort
+ */

+ openpic_init(1);
+ for ( i = 0 ; i < 16 ; i++ )
+ irq_desc[i].ctl = &i8259_pic;
+ i8259_init();
+#ifdef CONFIG_XMON
+ request_irq(openpic_to_irq(HYDRA_INT_ADB_NMI),
+ xmon_irq, 0, "NMI", 0);
+#endif /* CONFIG_XMON */
+#ifdef __SMP__
+ request_irq(openpic_to_irq(OPENPIC_VEC_IPI),
+ openpic_ipi_action, 0, "IPI0", 0);


+#endif /* __SMP__ */
+}
+

+__initfunc(void
+ chrp_init2(void))
+{
+ adb_init();
+
+ /* Should this be here? - Corey */
+ pmac_nvram_init();


+}
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+/*
+ * IDE stuff.
+ */

+unsigned int chrp_ide_irq = 0;
+int chrp_ide_ports_known = 0;
+ide_ioreg_t chrp_ide_regbase[MAX_HWIFS];
+ide_ioreg_t chrp_idedma_regbase;
+
X void chrp_ide_probe(void) {
X
X struct pci_dev *pdev = pci_find_device(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, NULL);
@@ -281,9 +506,167 @@
X }
X }
X
+void
+chrp_ide_insw(ide_ioreg_t port, void *buf, int ns)
+{
+ ide_insw(port+_IO_BASE, buf, ns);
+}
+
+void
+chrp_ide_outsw(ide_ioreg_t port, void *buf, int ns)
+{
+ ide_outsw(port+_IO_BASE, buf, ns);
+}
+
+int
+chrp_ide_default_irq(ide_ioreg_t base)
+{
+ if (chrp_ide_ports_known == 0)
+ chrp_ide_probe();
+ return chrp_ide_irq;
+}
+
+ide_ioreg_t
+chrp_ide_default_io_base(int index)
+{
+ if (chrp_ide_ports_known == 0)
+ chrp_ide_probe();
+ return chrp_ide_regbase[index];
+}
+
+int
+chrp_ide_check_region(ide_ioreg_t from, unsigned int extent)
+{
+ return check_region(from, extent);
+}
+
+void
+chrp_ide_request_region(ide_ioreg_t from,


+ unsigned int extent,
+ const char *name)
+{

+ request_region(from, extent, name);
+}
+
+void
+chrp_ide_release_region(ide_ioreg_t from,


+ unsigned int extent)
+{

+ release_region(from, extent);
+}
+
+void
+chrp_ide_fix_driveid(struct hd_driveid *id)
+{
+ ppc_generic_ide_fix_driveid(id);
+}
+
+void chrp_ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq)
+{
+ ide_ioreg_t port = base;
+ int i = 8;
+
+ while (i--)
+ *p++ = port++;
+ *p++ = port;
+ if (irq != NULL)
+ *irq = chrp_ide_irq;
+}
+
X EXPORT_SYMBOL(chrp_ide_irq);
X EXPORT_SYMBOL(chrp_ide_ports_known);
X EXPORT_SYMBOL(chrp_ide_regbase);
X EXPORT_SYMBOL(chrp_ide_probe);
X
X #endif
+
+__initfunc(void
+ chrp_init(unsigned long r3, unsigned long r4, unsigned long r5,


+ unsigned long r6, unsigned long r7))
+{

+ chrp_setup_pci_ptrs();
+#ifdef CONFIG_BLK_DEV_INITRD
+ /* take care of initrd if we have one */
+ if ( r3 )
+ {
+ initrd_start = r3 + KERNELBASE;
+ initrd_end = r3 + r4 + KERNELBASE;
+ }


+#endif /* CONFIG_BLK_DEV_INITRD */
+

+ /* pci_dram_offset/isa_io_base/isa_mem_base set by setup_pci_ptrs() */
+ ISA_DMA_THRESHOLD = ~0L;
+ DMA_MODE_READ = 0x44;
+ DMA_MODE_WRITE = 0x48;
+
+ ppc_md.setup_arch = chrp_setup_arch;
+ ppc_md.setup_residual = NULL;
+ ppc_md.get_cpuinfo = chrp_get_cpuinfo;
+ ppc_md.irq_cannonicalize = chrp_irq_cannonicalize;
+ ppc_md.init_IRQ = chrp_init_IRQ;
+ ppc_md.do_IRQ = chrp_do_IRQ;
+
+ ppc_md.init = chrp_init2;
+
+ ppc_md.restart = chrp_restart;
+ ppc_md.power_off = chrp_power_off;
+ ppc_md.halt = chrp_halt;
+
+ ppc_md.time_init = chrp_time_init;
+ ppc_md.set_rtc_time = chrp_set_rtc_time;
+ ppc_md.get_rtc_time = chrp_get_rtc_time;
+ ppc_md.calibrate_decr = chrp_calibrate_decr;
+
+#ifdef CONFIG_VT
+#ifdef CONFIG_MAC_KEYBOAD
+ if ( adb_hardware == ADB_NONE )
+ {
+ ppc_md.kbd_setkeycode = pckbd_setkeycode;
+ ppc_md.kbd_getkeycode = pckbd_getkeycode;
+ ppc_md.kbd_translate = pckbd_translate;
+ ppc_md.kbd_unexpected_up = pckbd_unexpected_up;
+ ppc_md.kbd_leds = pckbd_leds;
+ ppc_md.kbd_init_hw = pckbd_init_hw;
+#ifdef CONFIG_MAGIC_SYSRQ
+ ppc_md.kbd_sysrq_xlate = pckbd_sysrq_xlate;
+#endif
+ }
+ else
+ {
+ ppc_md.kbd_setkeycode = mackbd_setkeycode;
+ ppc_md.kbd_getkeycode = mackbd_getkeycode;
+ ppc_md.kbd_translate = mackbd_translate;
+ ppc_md.kbd_unexpected_up = mackbd_unexpected_up;
+ ppc_md.kbd_leds = mackbd_leds;
+ ppc_md.kbd_init_hw = mackbd_init_hw;
+#ifdef CONFIG_MAGIC_SYSRQ
+ ppc_md.kbd_sysrq_xlate = mackbd_sysrq_xlate;
+#endif
+ }
+#else
+ ppc_md.kbd_setkeycode = pckbd_setkeycode;
+ ppc_md.kbd_getkeycode = pckbd_getkeycode;
+ ppc_md.kbd_translate = pckbd_translate;
+ ppc_md.kbd_unexpected_up = pckbd_unexpected_up;
+ ppc_md.kbd_leds = pckbd_leds;
+ ppc_md.kbd_init_hw = pckbd_init_hw;
+#ifdef CONFIG_MAGIC_SYSRQ
+ ppc_md.kbd_sysrq_xlate = pckbd_sysrq_xlate;
+#endif
+#endif
+#endif
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+ ppc_ide_md.insw = chrp_ide_insw;
+ ppc_ide_md.outsw = chrp_ide_outsw;
+ ppc_ide_md.default_irq = chrp_ide_default_irq;
+ ppc_ide_md.default_io_base = chrp_ide_default_io_base;
+ ppc_ide_md.check_region = chrp_ide_check_region;
+ ppc_ide_md.request_region = chrp_ide_request_region;
+ ppc_ide_md.release_region = chrp_ide_release_region;
+ ppc_ide_md.fix_driveid = chrp_ide_fix_driveid;
+ ppc_ide_md.ide_init_hwif = chrp_ide_init_hwif_ports;


+
+ ppc_ide_md.io_base = _IO_BASE;
+#endif

+}
diff -u --recursive --new-file v2.2.7/linux/arch/ppc/kernel/head.S linux/arch/ppc/kernel/head.S
--- v2.2.7/linux/arch/ppc/kernel/head.S Tue Mar 23 14:35:46 1999
+++ linux/arch/ppc/kernel/head.S Tue May 11 08:24:32 1999


@@ -1,7 +1,7 @@
X /*

X * arch/ppc/kernel/head.S
X *
- * $Id: head.S,v 1.121 1999/03/16 10:40:29 cort Exp $
+ * $Id: head.S,v 1.130 1999/05/09 19:16:43 cort Exp $
X *
X * PowerPC version
X * Copyright (C) 1995-1996 Gary Thomas (g...@linuxppc.org)
@@ -91,7 +91,7 @@
X #define tlbia \
X li r4,128; \
X mtctr r4; \
- lis r4,0xC000; \
+ lis r4,KERNELBASE@h; \
X 0: tlbie r4; \
X addi r4,r4,0x1000; \
X bdnz 0b
@@ -415,7 +415,7 @@
X * this, we leave this much untouched space on the stack on exception
X * entry.
X */
-#define STACK_UNDERHEAD 64
+#define STACK_UNDERHEAD 0
X
X /*
X * Exception entry code. This code runs with address translation
@@ -1495,27 +1495,25 @@
X * On SMP we know the fpu is free, since we give it up every
X * switch. -- Cort
X */
+ mfmsr r5
+ ori r5,r5,MSR_FP
+ SYNC
+ mtmsr r5 /* enable use of fpu now */
+ SYNC
+/*
+ * For SMP, we don't do lazy FPU switching because it just gets too
+ * horrendously complex, especially when a task switches from one CPU
+ * to another. Instead we call giveup_fpu in switch_to.
+ */
+#ifndef __SMP__
X #ifndef CONFIG_APUS
X lis r6,-KERNELBASE@h
X #else
X lis r6,CYBERBASEp@h
X lwz r6,0(r6)
X #endif
-
X addis r3,r6,last_task_used_math@ha
X lwz r4,last_task_used_math@l(r3)
- mfmsr r5
- ori r5,r5,MSR_FP
- SYNC
- mtmsr r5 /* enable use of fpu now */
-/*
- * All the saving of last_task_used_math is handled
- * by a switch_to() call to smp_giveup_fpu() in SMP so
- * last_task_used_math is not used.
- * -- Cort
- */
-#ifndef __SMP__
- SYNC
X cmpi 0,r4,0
X beq 1f
X add r4,r4,r6
@@ -1529,15 +1527,17 @@
X li r20,MSR_FP|MSR_FE0|MSR_FE1
X andc r4,r4,r20 /* disable FP for previous task */
X stw r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+1:


X #endif /* __SMP__ */

-1: ori r23,r23,MSR_FP|MSR_FE0|MSR_FE1 /* enable use of FP after return */
+ /* enable use of FP after return */
+ ori r23,r23,MSR_FP|MSR_FE0|MSR_FE1
X mfspr r5,SPRG3 /* current task's TSS (phys) */
X lfd fr0,TSS_FPSCR-4(r5)
X mtfsf 0xff,fr0
X REST_32FPRS(0, r5)
+#ifndef __SMP__
X subi r4,r5,TSS
X sub r4,r4,r6
-#ifndef __SMP__
X stw r4,last_task_used_math@l(r3)


X #endif /* __SMP__ */

X /* restore registers and return */
@@ -1574,48 +1574,44 @@
X .align 4
X
X /*
- * Disable FP for the task which had the FPU previously,
- * and save its floating-point registers in its thread_struct.
+ * giveup_fpu(tsk)
+ * Disable FP for the task given as the argument,
+ * and save the floating-point registers in its thread_struct.
X * Enables the FPU for use in the kernel on return.
X */
-/* smp_giveup_fpu() takes an arg to tell it where to save the fpu
- * regs since last_task_used_math can't be trusted (many many race
- * conditions). -- Cort
- */
- .globl smp_giveup_fpu
-smp_giveup_fpu:
- mr r4,r3
- b 12f
X .globl giveup_fpu
X giveup_fpu:
- lis r3,last_task_used_math@ha
- lwz r4,last_task_used_math@l(r3)
-12:
X mfmsr r5
X ori r5,r5,MSR_FP
X SYNC
X mtmsr r5 /* enable use of fpu now */
X SYNC
- cmpi 0,r4,0
+ cmpi 0,r3,0
X beqlr- /* if no previous owner, done */
- addi r4,r4,TSS /* want TSS of last_task_used_math */
+ addi r3,r3,TSS /* want TSS of task */
+ lwz r5,PT_REGS(r3)
+ cmpi 0,r5,0
+ SAVE_32FPRS(0, r3)
+ mffs fr0
+ stfd fr0,TSS_FPSCR-4(r3)
+ beq 1f
+ lwz r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+ li r3,MSR_FP|MSR_FE0|MSR_FE1
+ andc r4,r4,r3 /* disable FP for previous task */
+ stw r4,_MSR-STACK_FRAME_OVERHEAD(r5)
+1:
X #ifndef __SMP__
X li r5,0
- stw r5,last_task_used_math@l(r3)
+ lis r4,last_task_used_math@ha
+ stw r5,last_task_used_math@l(r4)


X #endif /* __SMP__ */

- SAVE_32FPRS(0, r4)
- mffs fr0
- stfd fr0,TSS_FPSCR-4(r4)
- lwz r5,PT_REGS(r4)
- lwz r3,_MSR-STACK_FRAME_OVERHEAD(r5)
- li r4,MSR_FP|MSR_FE0|MSR_FE1
- andc r3,r3,r4 /* disable FP for previous task */
- stw r3,_MSR-STACK_FRAME_OVERHEAD(r5)
+ blr
+
X #else /* CONFIG_8xx */
X .globl giveup_fpu
X giveup_fpu:
-#endif /* CONFIG_8xx */
X blr
+#endif /* CONFIG_8xx */
X
X /*
X * This code is jumped to from the startup code to copy
@@ -2049,8 +2045,9 @@
X stw r0,GPR0(r1)
X lwz r0,0(r1)
X stw r0,GPR1(r1)
- SAVE_10GPRS(2, r1)
- SAVE_10GPRS(12, r1)
+ /* r3-r13 are caller saved -- Cort */
+ SAVE_GPR(2, r1)
+ SAVE_8GPRS(14, r1)
X SAVE_10GPRS(22, r1)
X mflr r20 /* Return to switch caller */
X mfmsr r22
@@ -2073,6 +2070,8 @@
X mtspr SPRG3,r0 /* Update current TSS phys addr */
X SYNC
X lwz r1,KSP(r4) /* Load new stack pointer */
+ /* save the old current 'last' for return value */
+ mr r3,r2
X addi r2,r4,-TSS /* Update current */
X #ifndef CONFIG_8xx
X /* Set up segment registers for new task */
@@ -2080,39 +2079,62 @@
X addis r5,r5,0x6000 /* Set Ks, Ku bits */
X li r0,12 /* TASK_SIZE / SEGMENT_SIZE */
X mtctr r0
- li r3,0
-3: mtsrin r5,r3
+ li r9,0
+3: mtsrin r5,r9
X addi r5,r5,1 /* next VSID */
- addis r3,r3,0x1000 /* address of next segment */
+ addis r9,r9,0x1000 /* address of next segment */
X bdnz 3b
X #else
X /* On the MPC8xx, we place the physical address of the new task
X * page directory loaded into the MMU base register, and set the
X * ASID compare register with the new "context".
X */
- lwz r3,MM-TSS(r4) /* Get virtual address of mm */
- lwz r3,PGD(r3) /* get new->mm->pgd */
- addis r3,r3,-KERNELBASE@h /* convert to phys addr */
- mtspr M_TWB, r3 /* Update MMU base address */
+ lwz r9,MM-TSS(r4) /* Get virtual address of mm */
+ lwz r9,PGD(r9) /* get new->mm->pgd */
+ addis r9,r9,-KERNELBASE@h /* convert to phys addr */
+ mtspr M_TWB, r9 /* Update MMU base address */
X mtspr M_CASID, r5 /* Update context */
X tlbia
X #endif
X SYNC
-
-/* FALL THROUGH into int_return */
-#ifdef __SMP__
- /* call schedule_tail if this is the first time for a child process */
- lwz r5,TSS_SMP_FORK_RET(r4)
- cmpi 0,r5,0
- beq+ int_return
- li r3,0
- stw r3,TSS_SMP_FORK_RET(r4)
- bl schedule_tail
-#endif /* __SMP__ */
+2: lwz r9,_MSR(r1) /* Returning to user mode? */
+ andi. r9,r9,MSR_PR
+ beq+ 10f /* if not, don't adjust kernel stack */
+8: addi r4,r1,INT_FRAME_SIZE+STACK_UNDERHEAD /* size of frame */
+ stw r4,TSS+KSP(r2) /* save kernel stack pointer */
+ tophys(r9,r1,r9)
+ mtspr SPRG2,r9 /* phys exception stack pointer */
+10: lwz r2,_CTR(r1)
+ lwz r0,_LINK(r1)
+ mtctr r2
+ mtlr r0
+ lwz r2,_XER(r1)
+ lwz r0,_CCR(r1)
+ mtspr XER,r2
+ mtcrf 0xFF,r0
+ /* r3-r13 are destroyed -- Cort */
+ REST_GPR(14, r1)
+ REST_8GPRS(15, r1)
+ REST_8GPRS(23, r1)
+ REST_GPR(31, r1)
+ lwz r2,_NIP(r1) /* Restore environment */
+ lwz r0,_MSR(r1)
+ mtspr SRR0,r2
+ mtspr SRR1,r0
+ lwz r0,GPR0(r1)
+ lwz r2,GPR2(r1)
+ lwz r1,GPR1(r1)
+ SYNC
+ rfi
X
X /*
X * Trap exit.
X */
+#ifdef __SMP__
+ .globl ret_from_smpfork
+ret_from_smpfork:
+ bl schedule_tail
+#endif
X .globl ret_from_syscall
X ret_from_syscall:
X .globl int_return
@@ -2127,8 +2149,8 @@
X lwz r5,_MSR(r1)
X and. r5,r5,r4
X beq 2f
-3: lis r4,n_lost_interrupts@ha
- lwz r4,n_lost_interrupts@l(r4)
+3: lis r4,ppc_n_lost_interrupts@ha
+ lwz r4,ppc_n_lost_interrupts@l(r4)
X cmpi 0,r4,0
X beq+ 1f
X addi r3,r1,STACK_FRAME_OVERHEAD
diff -u --recursive --new-file v2.2.7/linux/arch/ppc/kernel/i8259.c linux/arch/ppc/kernel/i8259.c
--- v2.2.7/linux/arch/ppc/kernel/i8259.c Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/kernel/i8259.c Tue May 11 08:24:32 1999
@@ -0,0 +1,130 @@
+
+#include <linux/stddef.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <asm/io.h>
+#include "i8259.h"
+
+unsigned char cached_8259[2] = { 0xff, 0xff };
+#define cached_A1 (cached_8259[0])
+#define cached_21 (cached_8259[1])
+
+int i8259_irq(int cpu)
+{
+ int irq;
+
+ /*
+ * Perform an interrupt acknowledge cycle on controller 1
+ */
+ outb(0x0C, 0x20);
+ irq = inb(0x20) & 7;

+ if (irq == 2)
+ {

+ /*
+ * Interrupt is cascaded so perform interrupt
+ * acknowledge on controller 2
+ */
+ outb(0x0C, 0xA0);
+ irq = (inb(0xA0) & 7) + 8;
+ }
+ else if (irq==7)
+ {
+ /*
+ * This may be a spurious interrupt
+ *
+ * Read the interrupt status register. If the most
+ * significant bit is not set then there is no valid
+ * interrupt
+ */
+ outb(0x0b, 0x20);
+ if(~inb(0x20)&0x80)
+ return -1;


+ }
+ return irq;
+}
+

+static void i8259_mask_and_ack_irq(unsigned int irq_nr)
+{
+ if ( irq_nr >= i8259_pic.irq_offset )
+ irq_nr -= i8259_pic.irq_offset;
+
+ if (irq_nr > 7) {
+ cached_A1 |= 1 << (irq_nr-8);
+ inb(0xA1); /* DUMMY */
+ outb(cached_A1,0xA1);
+ outb(0x20,0xA0); /* Non-specific EOI */
+ outb(0x20,0x20); /* Non-specific EOI to cascade */
+ } else {
+ cached_21 |= 1 << irq_nr;
+ inb(0x21); /* DUMMY */
+ outb(cached_21,0x21);
+ outb(0x20,0x20); /* Non-specific EOI */
+ }
+}
+
+static void i8259_set_irq_mask(int irq_nr)
+{
+ outb(cached_A1,0xA1);
+ outb(cached_21,0x21);
+}
+
+static void i8259_mask_irq(unsigned int irq_nr)
+{
+ if ( irq_nr >= i8259_pic.irq_offset )
+ irq_nr -= i8259_pic.irq_offset;
+ if ( irq_nr < 8 )
+ cached_21 |= 1 << irq_nr;
+ else
+ cached_A1 |= 1 << (irq_nr-8);
+ i8259_set_irq_mask(irq_nr);
+}
+
+static void i8259_unmask_irq(unsigned int irq_nr)
+{
+
+ if ( irq_nr >= i8259_pic.irq_offset )
+ irq_nr -= i8259_pic.irq_offset;
+ if ( irq_nr < 8 )
+ cached_21 &= ~(1 << irq_nr);
+ else
+ cached_A1 &= ~(1 << (irq_nr-8));
+ i8259_set_irq_mask(irq_nr);
+}
+
+struct hw_interrupt_type i8259_pic = {
+ " i8259 ",
+ NULL,
+ NULL,
+ NULL,
+ i8259_unmask_irq,
+ i8259_mask_irq,
+ i8259_mask_and_ack_irq,
+ 0
+};
+
+static void
+no_action(int cpl, void *dev_id, struct pt_regs *regs)
+{
+}
+
+void __init i8259_init(void)
+{
+ /* init master interrupt controller */
+ outb(0x11, 0x20); /* Start init sequence */
+ outb(0x00, 0x21); /* Vector base */
+ outb(0x04, 0x21); /* edge tiggered, Cascade (slave) on IRQ2 */
+ outb(0x01, 0x21); /* Select 8086 mode */
+ outb(0xFF, 0x21); /* Mask all */
+ /* init slave interrupt controller */
+ outb(0x11, 0xA0); /* Start init sequence */
+ outb(0x08, 0xA1); /* Vector base */
+ outb(0x02, 0xA1); /* edge triggered, Cascade (slave) on IRQ2 */
+ outb(0x01, 0xA1); /* Select 8086 mode */
+ outb(0xFF, 0xA1); /* Mask all */
+ outb(cached_A1, 0xA1);
+ outb(cached_21, 0x21);
+ request_irq( i8259_pic.irq_offset + 2, no_action, SA_INTERRUPT,
+ "82c59 secondary cascade", NULL );
+ enable_irq(i8259_pic.irq_offset + 2); /* Enable cascade interrupt */
+}
diff -u --recursive --new-file v2.2.7/linux/arch/ppc/kernel/i8259.h linux/arch/ppc/kernel/i8259.h
--- v2.2.7/linux/arch/ppc/kernel/i8259.h Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/kernel/i8259.h Tue May 11 08:24:32 1999
@@ -0,0 +1,12 @@
+
+#ifndef _PPC_KERNEL_i8259_H
+#define _PPC_KERNEL_i8259_H
+
+#include "local_irq.h"
+
+extern struct hw_interrupt_type i8259_pic;
+
+void i8259_init(void);
+int i8259_irq(int);
+
+#endif /* _PPC_KERNEL_i8259_H */
diff -u --recursive --new-file v2.2.7/linux/arch/ppc/kernel/idle.c linux/arch/ppc/kernel/idle.c
--- v2.2.7/linux/arch/ppc/kernel/idle.c Tue Mar 23 14:35:46 1999
+++ linux/arch/ppc/kernel/idle.c Thu Apr 29 12:39:01 1999
@@ -1,5 +1,5 @@
X /*
- * $Id: idle.c,v 1.60 1999/02/12 07:06:26 cort Exp $
+ * $Id: idle.c,v 1.61 1999/03/18 04:15:45 cort Exp $
X *
X * Idle daemon for PowerPC. Idle daemon will handle any action
X * that needs to be taken when the system becomes idle.
@@ -303,7 +303,14 @@
X hid0 &= ~(HID0_NAP | HID0_SLEEP | HID0_DOZE);
X hid0 |= (powersave_nap? HID0_NAP: HID0_DOZE) | HID0_DPM;
X asm("mtspr 1008,%0" : : "r" (hid0));
- msr |= MSR_POW;
+
+ /* set the POW bit in the MSR, and enable interrupts
+ * so we wake up sometime! */
+ _nmask_and_or_msr(0, MSR_POW | MSR_EE);
+
+ /* Disable interrupts again so restore_flags will
+ * work. */
+ _nmask_and_or_msr(MSR_EE, 0);
X }
X restore_flags(msr);
X default:
diff -u --recursive --new-file v2.2.7/linux/arch/ppc/kernel/indirect_pci.c linux/arch/ppc/kernel/indirect_pci.c
--- v2.2.7/linux/arch/ppc/kernel/indirect_pci.c Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/kernel/indirect_pci.c Tue May 11 08:24:32 1999
@@ -0,0 +1,121 @@
+/*
+ * Support for indirect PCI bridges.
+ *
+ * Copyright (C) 1998 Gabriel Paubert.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/pci.h>
+#include <asm/io.h>
+#include <asm/system.h>
+
+unsigned int * pci_config_address;
+unsigned char * pci_config_data;
+
+int indirect_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn,
+ unsigned char offset, unsigned char *val)
+{
+ unsigned flags;
+
+ save_flags(flags); cli();
+
+ out_be32(pci_config_address,
+ ((offset&0xfc)<<24) | (dev_fn<<16) | (bus<<8) | 0x80);
+
+ *val= in_8(pci_config_data + (offset&3));
+
+ restore_flags(flags);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int indirect_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn,
+ unsigned char offset, unsigned short *val)
+{
+ unsigned flags;
+
+ if (offset&1) return PCIBIOS_BAD_REGISTER_NUMBER;
+
+ save_flags(flags); cli();
+
+ out_be32(pci_config_address,
+ ((offset&0xfc)<<24) | (dev_fn<<16) | (bus<<8) | 0x80);
+
+ *val= in_le16((unsigned short *)(pci_config_data + (offset&3)));
+
+ restore_flags(flags);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int indirect_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn,
+ unsigned char offset, unsigned int *val)
+{
+ unsigned flags;
+
+ if (offset&3) return PCIBIOS_BAD_REGISTER_NUMBER;
+
+ save_flags(flags); cli();
+
+ out_be32(pci_config_address,
+ ((offset&0xfc)<<24) | (dev_fn<<16) | (bus<<8) | 0x80);
+
+ *val= in_le32((unsigned *)pci_config_data);
+
+ restore_flags(flags);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int indirect_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn,
+ unsigned char offset, unsigned char val)
+{
+ unsigned flags;
+
+ save_flags(flags); cli();
+
+ out_be32(pci_config_address,
+ ((offset&0xfc)<<24) | (dev_fn<<16) | (bus<<8) | 0x80);
+
+ out_8(pci_config_data + (offset&3), val);
+
+ restore_flags(flags);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int indirect_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn,
+ unsigned char offset, unsigned short val)
+{
+ unsigned flags;
+
+ if (offset&1) return PCIBIOS_BAD_REGISTER_NUMBER;
+
+ save_flags(flags); cli();
+
+ out_be32(pci_config_address,
+ ((offset&0xfc)<<24) | (dev_fn<<16) | (bus<<8) | 0x80);
+
+ out_le16((unsigned short *)(pci_config_data + (offset&3)), val);
+
+ restore_flags(flags);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int indirect_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,
+ unsigned char offset, unsigned int val)
+{
+ unsigned flags;
+
+ if (offset&3) return PCIBIOS_BAD_REGISTER_NUMBER;
+
+ save_flags(flags); cli();
+
+ out_be32(pci_config_address,
+ ((offset&0xfc)<<24) | (dev_fn<<16) | (bus<<8) | 0x80);
+
+ out_le32((unsigned *)pci_config_data, val);
+
+ restore_flags(flags);
+ return PCIBIOS_SUCCESSFUL;
+}
diff -u --recursive --new-file v2.2.7/linux/arch/ppc/kernel/irq.c linux/arch/ppc/kernel/irq.c
--- v2.2.7/linux/arch/ppc/kernel/irq.c Tue Mar 23 14:35:46 1999
+++ linux/arch/ppc/kernel/irq.c Thu Apr 29 12:39:01 1999
@@ -1,5 +1,5 @@
X /*
- * $Id: irq.c,v 1.102 1999/02/03 01:36:59 paulus Exp $
+ * $Id: irq.c,v 1.105 1999/03/25 19:51:51 cort Exp $
X *
X * arch/ppc/kernel/irq.c
X *
@@ -58,44 +58,15 @@


X #include <asm/amigahw.h>
X #include <asm/amigappc.h>

X #include <asm/ptrace.h>
-#ifdef CONFIG_8xx
-#include <asm/8xx_immap.h>
-#include <asm/mbx.h>
-#endif
X
-static void no_action(int cpl, void *dev_id, struct pt_regs *regs) { }
+#include "local_irq.h"
+
X extern volatile unsigned long ipi_count;
-static void dispatch_handler(struct pt_regs *regs, int irq);
X void enable_irq(unsigned int irq_nr);
X void disable_irq(unsigned int irq_nr);
X
-static void i8259_mask_and_ack_irq(unsigned int irq_nr);
-static void i8259_mask_irq(unsigned int irq_nr);
-static void i8259_unmask_irq(unsigned int irq_nr);
-#ifdef CONFIG_8xx
-static void mbx_mask_and_ack(unsigned int irq_nr);
-static void mbx_mask_irq(unsigned int irq_nr);
-static void mbx_unmask_irq(unsigned int irq_nr);
-static void mbx_i8259_action(int cpl, void *dev_id, struct pt_regs *regs);
-#else /* CONFIG_8xx */
-static volatile unsigned char *chrp_int_ack_special;
-extern void process_int(unsigned long vec, struct pt_regs *fp);
-extern void apus_init_IRQ(void);
-extern void amiga_disable_irq(unsigned int irq);
-extern void amiga_enable_irq(unsigned int irq);
-static void pmac_fix_gatwick_interrupts(struct device_node *gw, int irq_base);
-static void gatwick_action(int cpl, void *dev_id, struct pt_regs *regs);
-static void pmac_mask_irq(unsigned int irq_nr);
-static void pmac_unmask_irq(unsigned int irq_nr);
-static void pmac_mask_and_ack_irq(unsigned int irq_nr);
-static void chrp_mask_and_ack_irq(unsigned int irq_nr);
-static void chrp_unmask_irq(unsigned int irq_nr);
-static void chrp_mask_irq(unsigned int irq_nr);
-#ifdef __SMP__
-static void openpic_ipi_action(int cpl, void *dev_id, struct pt_regs *regs);
-extern void smp_message_recv(void);
-#endif /* __SMP__ */
-#endif /* CONFIG_8xx */
+/* Fixme - Need to figure out a way to get rid of this - Corey */
+volatile unsigned char *chrp_int_ack_special;
X
X #ifdef CONFIG_APUS
X /* Rename a few functions. Requires the CONFIG_APUS protection. */
@@ -105,39 +76,19 @@
X #define VEC_SPUR (24)
X #endif
X
+#define MAXCOUNT 10000000
+
X #define NR_MASK_WORDS ((NR_IRQS + 31) / 32)
-unsigned char cached_8259[2] = { 0xff, 0xff };
-#define cached_A1 (cached_8259[0])
-#define cached_21 (cached_8259[1])
-
-unsigned int local_bh_count[NR_CPUS];
-unsigned int local_irq_count[NR_CPUS];
-int max_irqs;
-int max_real_irqs;
-static int spurious_interrupts = 0;
-static unsigned int cached_irq_mask[NR_MASK_WORDS];
-unsigned int lost_interrupts[NR_MASK_WORDS];
-atomic_t n_lost_interrupts;
-
-#ifndef CONFIG_8xx
-#define GATWICK_IRQ_POOL_SIZE 10
-static struct interrupt_info gatwick_int_pool[GATWICK_IRQ_POOL_SIZE];
-/* pmac */
-struct pmac_irq_hw {
- unsigned int flag;
- unsigned int enable;
- unsigned int ack;
- unsigned int level;
-};
-
-/* these addresses are obtained from the device tree now -- Cort */
-volatile struct pmac_irq_hw *pmac_irq_hw[4] __pmac = {
- (struct pmac_irq_hw *) 0xf3000020,
- (struct pmac_irq_hw *) 0xf3000010,
- (struct pmac_irq_hw *) 0xf4000020,
- (struct pmac_irq_hw *) 0xf4000010,
-};
-#endif /* CONFIG_8xx */
+
+int ppc_spurious_interrupts = 0;
+
+unsigned int ppc_local_bh_count[NR_CPUS];
+unsigned int ppc_local_irq_count[NR_CPUS];
+struct irqaction *ppc_irq_action[NR_IRQS];
+unsigned int ppc_cached_irq_mask[NR_MASK_WORDS];
+unsigned int ppc_lost_interrupts[NR_MASK_WORDS];
+atomic_t ppc_n_lost_interrupts;
+
X
X /* nasty hack for shared irq's since we need to do kmalloc calls but
X * can't very early in the boot when we need to do a request irq.
@@ -174,82 +125,7 @@
X kfree(ptr);
X }
X
-struct hw_interrupt_type {
- const char * typename;
- void (*startup)(unsigned int irq);
- void (*shutdown)(unsigned int irq);
- void (*handle)(unsigned int irq, struct pt_regs * regs);
- void (*enable)(unsigned int irq);
- void (*disable)(unsigned int irq);
- void (*mask_and_ack)(unsigned int irq);
- int irq_offset;
-};
-
-#define mask_irq(irq) ({if (irq_desc[irq].ctl && irq_desc[irq].ctl->disable) irq_desc[irq].ctl->disable(irq);})
-#define unmask_irq(irq) ({if (irq_desc[irq].ctl && irq_desc[irq].ctl->enable) irq_desc[irq].ctl->enable(irq);})
-#define mask_and_ack_irq(irq) ({if (irq_desc[irq].ctl && irq_desc[irq].ctl->mask_and_ack) irq_desc[irq].ctl->mask_and_ack(irq);})
-
-struct irqdesc {
- struct irqaction *action;
- struct hw_interrupt_type *ctl;
-};
-static struct irqdesc irq_desc[NR_IRQS] = {{0, 0}, };
-
-static struct hw_interrupt_type i8259_pic = {
- " i8259 ",
- NULL,
- NULL,
- NULL,
- i8259_unmask_irq,
- i8259_mask_irq,
- i8259_mask_and_ack_irq,
- 0
-};
-#ifndef CONFIG_8xx
-static struct hw_interrupt_type pmac_pic = {
- " PMAC-PIC ",
- NULL,
- NULL,
- NULL,
- pmac_unmask_irq,
- pmac_mask_irq,
- pmac_mask_and_ack_irq,
- 0
-};
-
-static struct hw_interrupt_type gatwick_pic = {
- " GATWICK ",
- NULL,
- NULL,
- NULL,
- pmac_unmask_irq,
- pmac_mask_irq,
- pmac_mask_and_ack_irq,
- 0
-};
-
-static struct hw_interrupt_type open_pic = {
- " OpenPIC ",
- NULL,
- NULL,
- NULL,
- chrp_unmask_irq,
- chrp_mask_irq,
- chrp_mask_and_ack_irq,
- 0
-};
-#else
-static struct hw_interrupt_type ppc8xx_pic = {
- " 8xx SIU ",
- NULL,
- NULL,
- NULL,
- mbx_unmask_irq,
- mbx_mask_irq,
- mbx_mask_and_ack,
- 0
-};
-#endif /* CONFIG_8xx */
+struct irqdesc irq_desc[NR_IRQS] = {{0, 0}, };
X
X int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
X unsigned long irqflags, const char * devname, void *dev_id)
@@ -357,19 +233,17 @@
X }
X #ifdef __SMP__
X /* should this be per processor send/receive? */
- len += sprintf(buf+len, "IPI: %10lu", ipi_count);
- for ( i = 0 ; i <= smp_num_cpus-1; i++ )
- len += sprintf(buf+len," ");
- len += sprintf(buf+len, " interprocessor messages received\n");
+ len += sprintf(buf+len, "IPI: %10lu\n", ipi_count);
X #endif
- len += sprintf(buf+len, "BAD: %10u",spurious_interrupts);
- for ( i = 0 ; i <= smp_num_cpus-1; i++ )
- len += sprintf(buf+len," ");
- len += sprintf(buf+len, " spurious or short\n");
+ len += sprintf(buf+len, "BAD: %10u\n", ppc_spurious_interrupts);


X return len;
X }
X

-static void dispatch_handler(struct pt_regs *regs, int irq)
+/*
+ * Eventually, this should take an array of interrupts and an array size
+ * so it can dispatch multiple interrupts.
+ */
+void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq)
X {
X int status;
X struct irqaction *action;
@@ -390,209 +264,18 @@
X __cli();
X unmask_irq(irq);
X } else {
- spurious_interrupts++;
+ ppc_spurious_interrupts++;
X disable_irq( irq );
X }
X }
X
-#define MAXCOUNT 100000000
X asmlinkage void do_IRQ(struct pt_regs *regs, int isfake)
X {
- int irq;
- unsigned long bits = 0;
X int cpu = smp_processor_id();
- int openpic_eoi_done = 0;
-
- hardirq_enter(cpu);
-#ifndef CONFIG_8xx
-#ifdef __SMP__
- /* IPI's are a hack on the powersurge -- Cort */
- if ( (_machine == _MACH_Pmac) && (cpu != 0) )
- {
- if (!isfake)
- {
-#ifdef CONFIG_XMON
- static int xmon_2nd;
- if (xmon_2nd)
- xmon(regs);
-#endif
- smp_message_recv();
- goto out;
- }
- /* could be here due to a do_fake_interrupt call but we don't
- mess with the controller from the second cpu -- Cort */


- goto out;
- }
-

- {
- unsigned int loops = MAXCOUNT;
- while (test_bit(0, &global_irq_lock)) {
- if (smp_processor_id() == global_irq_holder) {
- printk("uh oh, interrupt while we hold global irq lock!\n");
-#ifdef CONFIG_XMON
- xmon(0);
-#endif
- break;
- }
- if (loops-- == 0) {
- printk("do_IRQ waiting for irq lock (holder=%d)\n", global_irq_holder);
-#ifdef CONFIG_XMON
- xmon(0);
-#endif
- }
- }
- }
-#endif /* __SMP__ */
-
- switch ( _machine )
- {
- case _MACH_Pmac:
- for (irq = max_real_irqs - 1; irq > 0; irq -= 32) {
- int i = irq >> 5;
- bits = ld_le32(&pmac_irq_hw[i]->flag)
- | lost_interrupts[i];
- if (bits == 0)
- continue;
- irq -= cntlzw(bits);
- break;
- }
- break;
- case _MACH_chrp:
- irq = openpic_irq(0);
- if (irq == IRQ_8259_CASCADE)
- {
- /*
- * This magic address generates a PCI IACK cycle.
- *
- * This should go in the above mask/ack code soon. -- Cort
- */
- irq = *chrp_int_ack_special;
- /*
- * Acknowledge as soon as possible to allow i8259
- * interrupt nesting
- */
- openpic_eoi(0);
- openpic_eoi_done = 1;
- }
- if (irq == OPENPIC_VEC_SPURIOUS)
- {
- /*
- * Spurious interrupts should never be
- * acknowledged
- */
- spurious_interrupts++;
- openpic_eoi_done = 1;
- }
- bits = 1UL << irq;
- break;
- case _MACH_prep:
- outb(0x0C, 0x20);
- irq = inb(0x20) & 7;
- if (irq == 2)
- {
- outb(0x0C, 0xA0);
- irq = (inb(0xA0) & 7) + 8;
- bits |= 1UL << irq;
-#if 0
- /* It's possible to loose intrs here
- * if we get 2 intrs in the upper 8
- * bits. We eoi irq 2 and handle one of
- * the upper intrs but then ignore it
- * since we've already eoi-d 2. So,
- * we must keep track of lost intrs.
- * -- Cort
- */
- while (1)
- {
- int i;
- outb(0x0C, 0xA0);
- i = inb(0xA0);
- if ( !(i & 128) )
- break;
- irq &= 7;
- irq += 8;
- bits |= 1UL << irq;
- }
-#endif
- }
- else
- bits = 1UL << irq;
-
- break;
-#ifdef CONFIG_APUS
- case _MACH_apus:
- {
- int old_level, new_level;
-
- old_level = ~(regs->mq) & IPLEMU_IPLMASK;
- new_level = (~(regs->mq) >> 3) & IPLEMU_IPLMASK;
-
- if (new_level == 0)
- {
- goto apus_out;
- }
-
- APUS_WRITE(APUS_IPL_EMU, IPLEMU_IPLMASK);
- APUS_WRITE(APUS_IPL_EMU, (IPLEMU_SETRESET
- | (~(new_level) & IPLEMU_IPLMASK)));
- APUS_WRITE(APUS_IPL_EMU, IPLEMU_DISABLEINT);
-
- process_int (VEC_SPUR+new_level, regs);
-
- APUS_WRITE(APUS_IPL_EMU, IPLEMU_SETRESET | IPLEMU_DISABLEINT);
- APUS_WRITE(APUS_IPL_EMU, IPLEMU_IPLMASK);
- APUS_WRITE(APUS_IPL_EMU, (IPLEMU_SETRESET
- | (~(old_level) & IPLEMU_IPLMASK)));
-apus_out:
- hardirq_exit(cpu);
- APUS_WRITE(APUS_IPL_EMU, IPLEMU_DISABLEINT);
- goto out2;
- }
-#endif
- }
X
- if (irq < 0)
- {
- printk(KERN_DEBUG "Bogus interrupt %d from PC = %lx\n",
- irq, regs->nip);
- spurious_interrupts++;


- goto out;
- }
-

-#else /* CONFIG_8xx */
- /* For MPC8xx, read the SIVEC register and shift the bits down
- * to get the irq number.
- */
- bits = ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_sivec;
- irq = bits >> 26;
- irq += ppc8xx_pic.irq_offset;
- bits = 1UL << irq;
-#endif /* CONFIG_8xx */
-#if 0
- /*
- * this allows for > 1 interrupt at a time so we can
- * clear out any 'double' interrupts on prep and
- * finish up the lost interrupts.
- * It doesn't currently work for irqs > 31 so I'm leaving
- * it commented out for now.
- * -- Cort
- */
- for ( i = 0 ; i < sizeof(bits)*8 ; i++ )
- if ( bits & (1UL<<i) )
- dispatch_handler( regs, i );
-#else
- dispatch_handler( regs, irq );
-#endif
-
-#ifndef CONFIG_8xx
-out:
- if (_machine == _MACH_chrp && !openpic_eoi_done)
- openpic_eoi(0);
-#endif /* CONFIG_8xx */
- hardirq_exit(cpu);
-#ifdef CONFIG_APUS
-out2:
-#endif
+ hardirq_enter(cpu);
+ ppc_md.do_IRQ(regs, cpu, isfake);
+ hardirq_exit(cpu);
X }
X

X unsigned long probe_irq_on (void)

@@ -605,461 +288,16 @@


X return 0;
X }
X

-static void i8259_mask_and_ack_irq(unsigned int irq_nr)
-{
- if ( irq_nr >= i8259_pic.irq_offset )
- irq_nr -= i8259_pic.irq_offset;
- if (irq_nr > 7) {
- cached_A1 |= 1 << (irq_nr-8);
- inb(0xA1); /* DUMMY */
- outb(cached_A1,0xA1);
- outb(0x62,0x20); /* Specific EOI to cascade */
- /*outb(0x20,0xA0);*/
- outb(0x60|(irq_nr-8), 0xA0); /* specific eoi */
- } else {
- cached_21 |= 1 << irq_nr;
- inb(0x21); /* DUMMY */
- outb(cached_21,0x21);
- /*outb(0x20,0x20);*/
- outb(0x60|irq_nr,0x20); /* specific eoi */
- }
-}
-
-static void i8259_set_irq_mask(int irq_nr)
-{
- outb(cached_A1,0xA1);
- outb(cached_21,0x21);
-}
-
-static void i8259_mask_irq(unsigned int irq_nr)
-{
- if ( irq_nr >= i8259_pic.irq_offset )
- irq_nr -= i8259_pic.irq_offset;
- if ( irq_nr < 8 )
- cached_21 |= 1 << irq_nr;
- else
- cached_A1 |= 1 << (irq_nr-8);
- i8259_set_irq_mask(irq_nr);
-}
-
-static void i8259_unmask_irq(unsigned int irq_nr)
-{
-
- if ( irq_nr >= i8259_pic.irq_offset )
- irq_nr -= i8259_pic.irq_offset;
- if ( irq_nr < 8 )
- cached_21 &= ~(1 << irq_nr);
- else
- cached_A1 &= ~(1 << (irq_nr-8));
- i8259_set_irq_mask(irq_nr);
-}
-
-#ifndef CONFIG_8xx
-static void gatwick_action(int cpl, void *dev_id, struct pt_regs *regs)
-{
- int irq, bits;
-
- for (irq = max_irqs - 1; irq > max_real_irqs; irq -= 32) {
- int i = irq >> 5;
- bits = ld_le32(&pmac_irq_hw[i]->flag)
- | lost_interrupts[i];
- if (bits == 0)
- continue;
- irq -= cntlzw(bits);
- break;
- }
- /* The previous version of this code allowed for this case, we
- * don't. Put this here to check for it.
- * -- Cort
- */
- if ( irq_desc[irq].ctl != &gatwick_pic )
- printk("gatwick irq not from gatwick pic\n");
- else
- dispatch_handler( regs, irq );
-}
-
-void pmac_mask_and_ack_irq(unsigned int irq_nr)
-{
- unsigned long bit = 1UL << (irq_nr & 0x1f);
- int i = irq_nr >> 5;
-
- if ((unsigned)irq_nr >= max_irqs)
- return;
-
- clear_bit(irq_nr, cached_irq_mask);
- if (test_and_clear_bit(irq_nr, lost_interrupts))
- atomic_dec(&n_lost_interrupts);
- out_le32(&pmac_irq_hw[i]->ack, bit);
- out_le32(&pmac_irq_hw[i]->enable, cached_irq_mask[i]);
- out_le32(&pmac_irq_hw[i]->ack, bit);
- do {
- /* make sure ack gets to controller before we enable interrupts */
- mb();
- } while(in_le32(&pmac_irq_hw[i]->flag) & bit);
-
-}
-
-void __openfirmware chrp_mask_and_ack_irq(unsigned int irq_nr)
-{
- if (is_8259_irq(irq_nr))
- i8259_mask_and_ack_irq(irq_nr);
-}
-
-static void pmac_set_irq_mask(int irq_nr)
-{
- unsigned long bit = 1UL << (irq_nr & 0x1f);
- int i = irq_nr >> 5;
-
- if ((unsigned)irq_nr >= max_irqs)
- return;
-
- /* enable unmasked interrupts */
- out_le32(&pmac_irq_hw[i]->enable, cached_irq_mask[i]);
-
- do {
- /* make sure mask gets to controller before we
- return to user */
- mb();
- } while((in_le32(&pmac_irq_hw[i]->enable) & bit)
- != (cached_irq_mask[i] & bit));
-
- /*
- * Unfortunately, setting the bit in the enable register
- * when the device interrupt is already on *doesn't* set
- * the bit in the flag register or request another interrupt.
- */
- if ((bit & cached_irq_mask[i])
- && (ld_le32(&pmac_irq_hw[i]->level) & bit)
- && !(ld_le32(&pmac_irq_hw[i]->flag) & bit)) {
- if (!test_and_set_bit(irq_nr, lost_interrupts))
- atomic_inc(&n_lost_interrupts);
- }
-}
-
-static void pmac_mask_irq(unsigned int irq_nr)
-{
- clear_bit(irq_nr, cached_irq_mask);
- pmac_set_irq_mask(irq_nr);
- mb();
-}
-
-static void pmac_unmask_irq(unsigned int irq_nr)
-{
- set_bit(irq_nr, cached_irq_mask);
- pmac_set_irq_mask(irq_nr);
-}
-
-static void __openfirmware chrp_mask_irq(unsigned int irq_nr)
-{
- if (is_8259_irq(irq_nr))
- i8259_mask_irq(irq_nr);
- else
- openpic_disable_irq(irq_to_openpic(irq_nr));
-}
-
-static void __openfirmware chrp_unmask_irq(unsigned int irq_nr)
-{
- if (is_8259_irq(irq_nr))
- i8259_unmask_irq(irq_nr);
- else
- openpic_enable_irq(irq_to_openpic(irq_nr));
-}
-
-/* This routine will fix some missing interrupt values in the device tree
- * on the gatwick mac-io controller used by some PowerBooks
- */
-static void __init pmac_fix_gatwick_interrupts(struct device_node *gw, int irq_base)
-{
- struct device_node *node;
- int count;
-
- memset(gatwick_int_pool, 0, sizeof(gatwick_int_pool));
- node = gw->child;
- count = 0;
- while(node)
- {
- /* Fix SCC */
- if (strcasecmp(node->name, "escc") == 0)
- if (node->child) {
- if (node->child->n_intrs < 3) {
- node->child->intrs = &gatwick_int_pool[count];
- count += 3;
- }
- node->child->n_intrs = 3;
- node->child->intrs[0].line = 15+irq_base;
- node->child->intrs[1].line = 4+irq_base;
- node->child->intrs[2].line = 5+irq_base;
- printk(KERN_INFO "irq: fixed SCC on second controller (%d,%d,%d)\n",
- node->child->intrs[0].line,
- node->child->intrs[1].line,
- node->child->intrs[2].line);
- }
- /* Fix media-bay & left SWIM */
- if (strcasecmp(node->name, "media-bay") == 0) {
- struct device_node* ya_node;
-
- if (node->n_intrs == 0)
- node->intrs = &gatwick_int_pool[count++];
- node->n_intrs = 1;
- node->intrs[0].line = 29+irq_base;
- printk(KERN_INFO "irq: fixed media-bay on second controller (%d)\n",
- node->intrs[0].line);
-
- ya_node = node->child;
- while(ya_node)
- {
- if (strcasecmp(ya_node->name, "floppy") == 0) {
- if (ya_node->n_intrs < 2) {
- ya_node->intrs = &gatwick_int_pool[count];
- count += 2;
- }
- ya_node->n_intrs = 2;
- ya_node->intrs[0].line = 19+irq_base;
- ya_node->intrs[1].line = 1+irq_base;
- printk(KERN_INFO "irq: fixed floppy on second controller (%d,%d)\n",
- ya_node->intrs[0].line, ya_node->intrs[1].line);
- }
- if (strcasecmp(ya_node->name, "ata4") == 0) {
- if (ya_node->n_intrs < 2) {
- ya_node->intrs = &gatwick_int_pool[count];
- count += 2;
- }
- ya_node->n_intrs = 2;
- ya_node->intrs[0].line = 14+irq_base;
- ya_node->intrs[1].line = 3+irq_base;
- printk(KERN_INFO "irq: fixed ide on second controller (%d,%d)\n",
- ya_node->intrs[0].line, ya_node->intrs[1].line);
- }
- ya_node = ya_node->sibling;
- }
- }
- node = node->sibling;
- }
- if (count > 10) {
- printk("WARNING !! Gatwick interrupt pool overflow\n");
- printk(" GATWICK_IRQ_POOL_SIZE = %d\n", GATWICK_IRQ_POOL_SIZE);
- printk(" requested = %d\n", count);
- }
-}
-
-#ifdef __SMP__
-static void openpic_ipi_action(int cpl, void *dev_id, struct pt_regs *regs)
-{
- smp_message_recv();
-}
-#endif /* __SMP__ */
-
-
-#else /* CONFIG_8xx */
-
-static void mbx_i8259_action(int cpl, void *dev_id, struct pt_regs *regs)
-{
- int bits, irq;
-
- /* A bug in the QSpan chip causes it to give us 0xff always
- * when doing a character read. So read 32 bits and shift.
- * This doesn't seem to return useful values anyway, but
- * read it to make sure things are acked.
- * -- Cort
- */
- irq = (inl(0x508) >> 24)&0xff;
- if ( irq != 0xff ) printk("iack %d\n", irq);
-
- outb(0x0C, 0x20);
- irq = inb(0x20) & 7;
- if (irq == 2)
- {
- outb(0x0C, 0xA0);
- irq = inb(0xA0);
- irq = (irq&7) + 8;
- }
- bits = 1UL << irq;
- irq += i8259_pic.irq_offset;
- dispatch_handler( regs, irq );
-}
-
-static void mbx_mask_and_ack(unsigned int irq_nr)
-{
- /* this shouldn't be masked, we mask the 8259 if we need to -- Cort */
- if ( irq_nr != ISA_BRIDGE_INT )
- mbx_mask_irq(irq_nr);
- if ( irq_nr >= ppc8xx_pic.irq_offset )
- irq_nr -= ppc8xx_pic.irq_offset;
- /* clear the pending bits */
- ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_sipend = 1 << (31-irq_nr);
-}
-
-static void mbx_mask_irq(unsigned int irq_nr)
-{
- if ( irq_nr == ISA_BRIDGE_INT ) return;
- if ( irq_nr >= ppc8xx_pic.irq_offset )
- irq_nr -= ppc8xx_pic.irq_offset;
- cached_irq_mask[0] &= ~(1 << (31-irq_nr));
- ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask = cached_irq_mask[0];
-}
-
-static void mbx_unmask_irq(unsigned int irq_nr)
-{
- if ( irq_nr >= ppc8xx_pic.irq_offset )
- irq_nr -= ppc8xx_pic.irq_offset;
- cached_irq_mask[0] |= (1 << (31-irq_nr));
- ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask = cached_irq_mask[0];
-}
-#endif /* CONFIG_8xx */
-
-static void __init i8259_init(void)
-{
- /* init master interrupt controller */
- outb(0x11, 0x20); /* Start init sequence */
- outb(0x00, 0x21); /* Vector base */
- outb(0x04, 0x21); /* edge tiggered, Cascade (slave) on IRQ2 */
- outb(0x01, 0x21); /* Select 8086 mode */
- outb(0xFF, 0x21); /* Mask all */
- /* init slave interrupt controller */
- outb(0x11, 0xA0); /* Start init sequence */
- outb(0x08, 0xA1); /* Vector base */
- outb(0x02, 0xA1); /* edge triggered, Cascade (slave) on IRQ2 */
- outb(0x01, 0xA1); /* Select 8086 mode */
- outb(0xFF, 0xA1); /* Mask all */
- outb(cached_A1, 0xA1);
- outb(cached_21, 0x21);
- request_irq( i8259_pic.irq_offset + 2, no_action, SA_INTERRUPT,
- "8259 secondary cascade", NULL );
- enable_irq(i8259_pic.irq_offset + 2); /* Enable cascade interrupt */
-}
-
X void __init init_IRQ(void)
X {
- extern void xmon_irq(int, void *, struct pt_regs *);
- int i;
X static int once = 0;
-#ifndef CONFIG_8xx
- struct device_node *irqctrler;
- unsigned long addr;
- struct device_node *np;
- int second_irq = -999;
-#endif
+
X if ( once )
X return;
X else
X once++;
X
-#ifndef CONFIG_8xx
- switch (_machine)
- {
- case _MACH_Pmac:
- /* G3 powermacs have 64 interrupts, G3 Series PowerBook have 128,
- others have 32 */
- max_irqs = max_real_irqs = 32;
- irqctrler = find_devices("mac-io");
- if (irqctrler)
- {
- max_real_irqs = 64;
- if (irqctrler->next)
- max_irqs = 128;
- else
- max_irqs = 64;
- }
- for ( i = 0; i < max_real_irqs ; i++ )
- irq_desc[i].ctl = &pmac_pic;
-
- /* get addresses of first controller */
- if (irqctrler) {
- if (irqctrler->n_addrs > 0) {
- addr = (unsigned long)
- ioremap(irqctrler->addrs[0].address, 0x40);
- for (i = 0; i < 2; ++i)
- pmac_irq_hw[i] = (volatile struct pmac_irq_hw*)
- (addr + (2 - i) * 0x10);
- }
-
- /* get addresses of second controller */
- irqctrler = (irqctrler->next) ? irqctrler->next : NULL;
- if (irqctrler && irqctrler->n_addrs > 0) {
- addr = (unsigned long)
- ioremap(irqctrler->addrs[0].address, 0x40);
- for (i = 2; i < 4; ++i)
- pmac_irq_hw[i] = (volatile struct pmac_irq_hw*)
- (addr + (4 - i) * 0x10);
- }
- }
-
- /* disable all interrupts in all controllers */
- for (i = 0; i * 32 < max_irqs; ++i)
- out_le32(&pmac_irq_hw[i]->enable, 0);
-
- /* get interrupt line of secondary interrupt controller */
- if (irqctrler) {
- second_irq = irqctrler->intrs[0].line;
- printk(KERN_INFO "irq: secondary controller on irq %d\n",
- (int)second_irq);
- if (device_is_compatible(irqctrler, "gatwick"))
- pmac_fix_gatwick_interrupts(irqctrler, max_real_irqs);
- for ( i = max_real_irqs ; i < max_irqs ; i++ )
- irq_desc[i].ctl = &gatwick_pic;
- request_irq( second_irq, gatwick_action, SA_INTERRUPT,
- "gatwick cascade", 0 );
- }
- printk("System has %d possible interrupts\n", max_irqs);
- if (max_irqs != max_real_irqs)
- printk(KERN_DEBUG "%d interrupts on main controller\n",
- max_real_irqs);
-
-#ifdef CONFIG_XMON
- request_irq(20, xmon_irq, 0, "NMI - XMON", 0);
-#endif /* CONFIG_XMON */
- break;
- case _MACH_chrp:
- if ( !(np = find_devices("pci") ) )
- printk("Cannot find pci to get ack address\n");
- else
- {
- chrp_int_ack_special = (volatile unsigned char *)
- (*(unsigned long *)get_property(np,
- "8259-interrupt-acknowledge", NULL));
- }
- for ( i = 16 ; i < 36 ; i++ )
- irq_desc[i].ctl = &open_pic;
- /* openpic knows that it's at irq 16 offset
- * so we don't need to set it in the pic structure
- * -- Cort
- */
- openpic_init(1);
- for ( i = 0 ; i < 16 ; i++ )
- irq_desc[i].ctl = &i8259_pic;
- i8259_init();
-#ifdef CONFIG_XMON
- request_irq(openpic_to_irq(HYDRA_INT_ADB_NMI),
- xmon_irq, 0, "NMI", 0);
-#endif /* CONFIG_XMON */
-#ifdef __SMP__
- request_irq(openpic_to_irq(OPENPIC_VEC_SPURIOUS),
- openpic_ipi_action, 0, "IPI0", 0);
-#endif /* __SMP__ */
- break;
- case _MACH_prep:
- for ( i = 0 ; i < 16 ; i++ )
- irq_desc[i].ctl = &i8259_pic;
- i8259_init();
- break;
-#ifdef CONFIG_APUS
- case _MACH_apus:
- apus_init_IRQ();
- break;
-#endif
- }
-#else /* CONFIG_8xx */
- ppc8xx_pic.irq_offset = 16;
- for ( i = 16 ; i < 32 ; i++ )
- irq_desc[i].ctl = &ppc8xx_pic;
- unmask_irq(CPM_INTERRUPT);
-
- for ( i = 0 ; i < 16 ; i++ )
- irq_desc[i].ctl = &i8259_pic;
- i8259_init();
- request_irq(ISA_BRIDGE_INT, mbx_i8259_action, 0, "8259 cascade", NULL);
- enable_irq(ISA_BRIDGE_INT);
-#endif /* CONFIG_8xx */
+ ppc_md.init_IRQ();
X }
X
X #ifdef __SMP__
@@ -1078,9 +316,13 @@
X
X printk("\n%s, CPU %d:\n", str, cpu);
X printk("irq: %d [%d %d]\n",
- atomic_read(&global_irq_count), local_irq_count[0], local_irq_count[1]);
+ atomic_read(&global_irq_count),
+ ppc_local_irq_count[0],
+ ppc_local_irq_count[1]);
X printk("bh: %d [%d %d]\n",
- atomic_read(&global_bh_count), local_bh_count[0], local_bh_count[1]);
+ atomic_read(&global_bh_count),
+ ppc_local_bh_count[0],
+ ppc_local_bh_count[1]);
X stack = (unsigned long *) &str;
X for (i = 40; i ; i--) {
X unsigned long x = *++stack;
@@ -1115,7 +357,8 @@
X * already executing in one..
X */
X if (!atomic_read(&global_irq_count)) {
- if (local_bh_count[cpu] || !atomic_read(&global_bh_count))
+ if (ppc_local_bh_count[cpu]
+ || !atomic_read(&global_bh_count))
X break;
X }
X
@@ -1136,7 +379,8 @@
X continue;
X if (global_irq_lock)
X continue;
- if (!local_bh_count[cpu] && atomic_read(&global_bh_count))
+ if (!ppc_local_bh_count[cpu]
+ && atomic_read(&global_bh_count))
X continue;
X if (!test_and_set_bit(0,&global_irq_lock))
X break;
@@ -1226,7 +470,7 @@
X if (flags & (1 << 15)) {
X int cpu = smp_processor_id();
X __cli();
- if (!local_irq_count[cpu])
+ if (!ppc_local_irq_count[cpu])
X get_irqlock(cpu);
X }
X }
@@ -1235,7 +479,7 @@
X {
X int cpu = smp_processor_id();
X
- if (!local_irq_count[cpu])
+ if (!ppc_local_irq_count[cpu])
X release_irqlock(cpu);
X __sti();
X }
@@ -1259,7 +503,7 @@
X retval = 2 + local_enabled;
X
X /* check for global flags if we're not in an interrupt */
- if (!local_irq_count[smp_processor_id()]) {
+ if (!ppc_local_irq_count[smp_processor_id()]) {
X if (local_enabled)
X retval = 1;
X if (global_irq_holder == (unsigned char) smp_processor_id())
@@ -1268,6 +512,31 @@


X return retval;
X }
X

+int
+tb(long vals[],
+ int max_size)
+{
+ register unsigned long *orig_sp __asm__ ("r1");
+ register unsigned long lr __asm__ ("r3");
+ unsigned long *sp;
+ int i;
+
+ asm volatile ("mflr 3");
+ vals[0] = lr;
+ sp = (unsigned long *) *orig_sp;
+ sp = (unsigned long *) *sp;
+ for (i=1; i<max_size; i++) {
+ if (sp == 0) {
+ break;
+ }
+
+ vals[i] = *(sp+1);
+ sp = (unsigned long *) *sp;
+ }
+
+ return i;
+}
+
X void __global_restore_flags(unsigned long flags)
X {
X switch (flags) {
@@ -1284,8 +553,20 @@
X __sti();
X break;
X default:
+ {
+ unsigned long trace[5];
+ int count;
+ int i;
+
X printk("global_restore_flags: %08lx (%08lx)\n",
X flags, (&flags)[-1]);
+ count = tb(trace, 5);
+ printk("tb:");
+ for(i=0; i<count; i++) {
+ printk(" %8.8lx", trace[i]);
+ }
+ printk("\n");
+ }
X }
X }
X #endif /* __SMP__ */
diff -u --recursive --new-file v2.2.7/linux/arch/ppc/kernel/local_irq.h linux/arch/ppc/kernel/local_irq.h
--- v2.2.7/linux/arch/ppc/kernel/local_irq.h Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/kernel/local_irq.h Thu Apr 29 12:39:01 1999
@@ -0,0 +1,45 @@
+
+#ifndef _PPC_KERNEL_LOCAL_IRQ_H
+#define _PPC_KERNEL_LOCAL_IRQ_H
+


+#include <linux/kernel_stat.h>
+#include <linux/interrupt.h>
+

+void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq);
+
+/* Structure describing interrupts */
+struct hw_interrupt_type {
+ const char * typename;
+ void (*startup)(unsigned int irq);
+ void (*shutdown)(unsigned int irq);
+ void (*handle)(unsigned int irq, struct pt_regs * regs);
+ void (*enable)(unsigned int irq);
+ void (*disable)(unsigned int irq);
+ void (*mask_and_ack)(unsigned int irq);
+ int irq_offset;
+};
+
+#define mask_irq(irq) ({if (irq_desc[irq].ctl && irq_desc[irq].ctl->disable) irq_desc[irq].ctl->disable(irq);})
+#define unmask_irq(irq) ({if (irq_desc[irq].ctl && irq_desc[irq].ctl->enable) irq_desc[irq].ctl->enable(irq);})
+#define mask_and_ack_irq(irq) ({if (irq_desc[irq].ctl && irq_desc[irq].ctl->mask_and_ack) irq_desc[irq].ctl->mask_and_ack(irq);})
+
+struct irqdesc {
+ struct irqaction *action;
+ struct hw_interrupt_type *ctl;
+};
+
+extern struct irqdesc irq_desc[NR_IRQS];
+
+
+#define NR_MASK_WORDS ((NR_IRQS + 31) / 32)
+
+extern int ppc_spurious_interrupts;
+extern int ppc_second_irq;
+extern struct irqaction *ppc_irq_action[NR_IRQS];
+extern unsigned int ppc_local_bh_count[NR_CPUS];
+extern unsigned int ppc_local_irq_count[NR_CPUS];
+extern unsigned int ppc_cached_irq_mask[NR_MASK_WORDS];
+extern unsigned int ppc_lost_interrupts[NR_MASK_WORDS];
+extern atomic_t ppc_n_lost_interrupts;
+
+#endif /* _PPC_KERNEL_LOCAL_IRQ_H */
diff -u --recursive --new-file v2.2.7/linux/arch/ppc/kernel/mbx_pci.c linux/arch/ppc/kernel/mbx_pci.c
--- v2.2.7/linux/arch/ppc/kernel/mbx_pci.c Thu Apr 23 20:21:29 1998
+++ linux/arch/ppc/kernel/mbx_pci.c Thu Apr 29 12:39:01 1999
@@ -252,3 +252,20 @@
X }
X return PCIBIOS_DEVICE_NOT_FOUND;
X }
+
+__initfunc(
+void
+mbx_pcibios_fixup(void))
+{
+ /* Nothing to do here? */
+}
+
+__initfunc(
+void
+mbx_setup_pci_ptrs(void))
+{
+ set_config_access_method(mbx);
+
+ ppc_md.pcibios_fixup = mbx_pcibios_fixup;
+}
+
diff -u --recursive --new-file v2.2.7/linux/arch/ppc/kernel/mbx_setup.c linux/arch/ppc/kernel/mbx_setup.c
--- v2.2.7/linux/arch/ppc/kernel/mbx_setup.c Fri Jan 8 22:36:02 1999
+++ linux/arch/ppc/kernel/mbx_setup.c Thu Apr 29 12:39:01 1999
@@ -1,5 +1,5 @@
X /*
- * $Id: mbx_setup.c,v 1.5 1998/12/29 18:55:07 cort Exp $
+ * $Id: mbx_setup.c,v 1.9 1999/04/28 11:54:09 davem Exp $
X *
X * linux/arch/ppc/kernel/setup.c
X *
@@ -39,6 +39,22 @@
X #include <asm/pgtable.h>
X #include <asm/ide.h>
X #include <asm/mbx.h>
+#include <asm/machdep.h>


+
+#include "time.h"
+#include "local_irq.h"
+

+static int mbx_set_rtc_time(unsigned long time);
+unsigned long mbx_get_rtc_time(void);
+void mbx_calibrate_decr(void);
+


+extern int mackbd_setkeycode(unsigned int scancode, unsigned int keycode);
+extern int mackbd_getkeycode(unsigned int scancode);
+extern int mackbd_translate(unsigned char scancode, unsigned char *keycode,
+ char raw_mode);
+extern char mackbd_unexpected_up(unsigned char keycode);
+extern void mackbd_leds(unsigned char leds);
+extern void mackbd_init_hw(void);

X
X extern unsigned long loops_per_sec;
X
@@ -55,35 +71,10 @@
X extern unsigned long find_available_memory(void);
X extern void m8xx_cpm_reset(uint);
X
-/* this really does make things cleaner -- Cort */
-void __init powermac_init(void)
-{
-}
-
X void __init adbdev_init(void)
X {
X }
X
-void __init mbx_ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base, int *irq)
-{


- ide_ioreg_t port = base;
- int i = 8;

-


- while (i--)
- *p++ = port++;

- *p++ = base + 0x206;


- if (irq != NULL)

- *irq = 0;
-#ifdef ATA_FLASH
- base = (unsigned long) ioremap(PCMCIA_MEM_ADDR, 0x200);
- for (i = 0; i < 8; ++i)
- *p++ = base++;
- *p = ++base; /* Does not matter */
- if (irq)
- *irq = 13;
-#endif
-}
-
X __initfunc(void
X mbx_setup_arch(unsigned long * memory_start_p, unsigned long * memory_end_p))
X {
@@ -144,4 +135,338 @@
X xmon(0);
X #endif
X machine_restart(NULL);
+}
+
+/* The decrementer counts at the system (internal) clock frequency divided by
+ * sixteen, or external oscillator divided by four. Currently, we only
+ * support the MBX, which is system clock divided by sixteen.
+ */
+__initfunc(void mbx_calibrate_decr(void))
+{
+ bd_t *binfo = (bd_t *)&res;
+ int freq, fp, divisor;
+
+ if ((((immap_t *)MBX_IMAP_ADDR)->im_clkrst.car_sccr & 0x02000000) == 0)
+ printk("WARNING: Wrong decrementer source clock.\n");
+
+ /* The manual says the frequency is in Hz, but it is really
+ * as MHz. The value 'fp' is the number of decrementer ticks
+ * per second.
+ */
+ fp = (binfo->bi_intfreq * 1000000) / 16;
+ freq = fp*60; /* try to make freq/1e6 an integer */
+ divisor = 60;
+ printk("time_init: decrementer frequency = %d/%d\n", freq, divisor);
+ decrementer_count = freq / HZ / divisor;
+ count_period_num = divisor;
+ count_period_den = freq / 1000000;
+}
+
+/* A place holder for time base interrupts, if they are ever enabled.
+*/
+void timebase_interrupt(int irq, void * dev, struct pt_regs * regs)
+{
+ printk("timebase_interrupt()\n");
+}
+
+/* The RTC on the MPC8xx is an internal register.
+ * We want to protect this during power down, so we need to unlock,
+ * modify, and re-lock.
+ */
+static int
+mbx_set_rtc_time(unsigned long time)
+{
+ ((immap_t *)MBX_IMAP_ADDR)->im_sitk.sitk_rtck = KAPWR_KEY;
+ ((immap_t *)MBX_IMAP_ADDR)->im_sit.sit_rtc = time;
+ ((immap_t *)MBX_IMAP_ADDR)->im_sitk.sitk_rtck = ~KAPWR_KEY;
+ return(0);
+}
+
+initfunc(unsigned long
+mbx_get_rtc_time(void)
+{
+ /* First, unlock all of the registers we are going to modify.
+ * To protect them from corruption during power down, registers
+ * that are maintained by keep alive power are "locked". To
+ * modify these registers we have to write the key value to
+ * the key location associated with the register.
+ */
+ ((immap_t *)MBX_IMAP_ADDR)->im_sitk.sitk_tbscrk = KAPWR_KEY;
+ ((immap_t *)MBX_IMAP_ADDR)->im_sitk.sitk_rtcsck = KAPWR_KEY;
+
+
+ /* Disable the RTC one second and alarm interrupts.
+ */
+ ((immap_t *)MBX_IMAP_ADDR)->im_sit.sit_rtcsc &=
+ ~(RTCSC_SIE | RTCSC_ALE);
+
+ /* Enabling the decrementer also enables the timebase interrupts
+ * (or from the other point of view, to get decrementer interrupts
+ * we have to enable the timebase). The decrementer interrupt
+ * is wired into the vector table, nothing to do here for that.
+ */
+ ((immap_t *)MBX_IMAP_ADDR)->im_sit.sit_tbscr =
+ ((mk_int_int_mask(DEC_INTERRUPT) << 8) |
+ (TBSCR_TBF | TBSCR_TBE));
+ if (request_irq(DEC_INTERRUPT, timebase_interrupt, 0, "tbint", NULL) != 0)
+ panic("Could not allocate timer IRQ!");
+
+ /* Get time from the RTC.
+ */
+ return ((immap_t *)MBX_IMAP_ADDR)->im_sit.sit_rtc;
+}
+
+void
+mbx_restart(char *cmd)
+{
+ extern void MBX_gorom(void);
+
+ MBX_gorom();
+}
+
+void
+mbx_power_off(void)
+{
+ mbx_restart(NULL);
+}
+
+void
+mbx_halt(void)
+{
+ mbx_restart(NULL)
+}
+
+
+int mbx_setup_residual(char *buffer)
+{
+ int len = 0;
+ bd_t *bp;
+ extern RESIDUAL *res;
+
+ bp = (bd_t *)res;
+
+ len += sprintf(len+buffer,"clock\t\t: %dMHz\n"
+ "bus clock\t: %dMHz\n",
+ bp->bi_intfreq /*/ 1000000*/,
+ bp->bi_busfreq /*/ 1000000*/);


SHAR_EOF
true || echo 'restore of patch-2.2.8 failed'
fi

echo 'End of part 09'
echo 'File patch-2.2.8 is continued in part 10'
echo 10 > _shar_seq_.tmp

Thomas...@ciw.uni-karlsruhe.de

unread,
May 12, 1999, 3:00:00 AM5/12/99
to
Archive-name: v2.2/patch-2.2.8/part10

#!/bin/sh
# this is part 10 of a 33 - part archive


# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.8 continued
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 10; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.8'
else
echo 'x - continuing with patch-2.2.8'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.8' &&
+

+ return len;
+}
+

+void
+mbx_do_IRQ(struct pt_regs *regs,


+ int cpu,
+ int isfake)

+{
+ int irq;
+ unsigned long bits = 0;
+
+ /* For MPC8xx, read the SIVEC register and shift the bits down
+ * to get the irq number. */
+ bits = ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_sivec;
+ irq = bits >> 26;
+ irq += ppc8xx_pic.irq_offset;


+ bits = 1UL << irq;
+
+ if (irq < 0) {

+ printk(KERN_DEBUG "Bogus interrupt %d from PC = %lx\n",
+ irq, regs->nip);

+ spurious_interrupts++;
+ }
+ else {


+ ppc_irq_dispatch_handler( regs, irq );
+ }

+
+}
+
+static void mbx_i8259_action(int cpl, void *dev_id, struct pt_regs *regs)
+{
+ int bits, irq;
+
+ /* A bug in the QSpan chip causes it to give us 0xff always
+ * when doing a character read. So read 32 bits and shift.
+ * This doesn't seem to return useful values anyway, but
+ * read it to make sure things are acked.


+ * -- Cort
+ */

+ irq = (inl(0x508) >> 24)&0xff;
+ if ( irq != 0xff ) printk("iack %d\n", irq);
+

+ outb(0x0C, 0x20);
+ irq = inb(0x20) & 7;
+ if (irq == 2)
+ {

+ outb(0x0C, 0xA0);
+ irq = inb(0xA0);
+ irq = (irq&7) + 8;


+ }
+ bits = 1UL << irq;

+ irq += i8259_pic.irq_offset;


+ ppc_irq_dispatch_handler( regs, irq );
+}
+

+
+/* On MBX8xx, the interrupt control (SIEL) was set by EPPC-bug. External
+ * interrupts can be either edge or level triggered, but there is no
+ * reason for us to change the EPPC-bug values (it would not work if we did).
+ */
+__initfunc(void
+mbx_init_IRQ(void))
+{
+ int i;
+
+ ppc8xx_pic.irq_offset = 16;
+ for ( i = 16 ; i < 32 ; i++ )
+ irq_desc[i].ctl = &ppc8xx_pic;
+ unmask_irq(CPM_INTERRUPT);
+


+ for ( i = 0 ; i < 16 ; i++ )
+ irq_desc[i].ctl = &i8259_pic;
+ i8259_init();

+ request_irq(ISA_BRIDGE_INT, mbx_i8259_action, 0, "8259 cascade", NULL);
+ enable_irq(ISA_BRIDGE_INT);


+}
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+/*
+ * IDE stuff.
+ */

+void
+mbx_ide_insw(ide_ioreg_t port, void *buf, int ns)
+{
+ ide_insw(port+_IO_BASE), buf, ns);
+}
+
+void
+mbx_ide_outsw(ide_ioreg_t port, void *buf, int ns)


+{
+ ide_outsw(port+_IO_BASE, buf, ns);
+}
+
+int

+mbx_ide_default_irq(ide_ioreg_t base)
+{
+ return 14;
+}
+
+ide_ioreg_t
+mbx_ide_default_io_base(int index)
+{
+ return index;
+}
+
+int
+mbx_ide_check_region(ide_ioreg_t from, unsigned int extent)
+{
+ return 0
+}
+
+void
+mbx_ide_request_region(ide_ioreg_t from,


+ unsigned int extent,
+ const char *name)
+{
+}

+
+void
+mbx_ide_release_region(ide_ioreg_t from,


+ unsigned int extent)
+{
+}

+
+void
+mbx_ide_fix_driveid(struct hd_driveid *id)


+{
+ ppc_generic_ide_fix_driveid(id);
+}
+

+void __init mbx_ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base, int *irq)


+{
+ ide_ioreg_t port = base;
+ int i = 8;
+
+ while (i--)
+ *p++ = port++;

+ *p++ = base + 0x206;


+ if (irq != NULL)

+ *irq = 0;
+#ifdef ATA_FLASH
+ base = (unsigned long) ioremap(PCMCIA_MEM_ADDR, 0x200);
+ for (i = 0; i < 8; ++i)
+ *p++ = base++;
+ *p = ++base; /* Does not matter */
+ if (irq)
+ *irq = 13;
+#endif
+}
+#endif
+
+__initfunc(void
+mbx_init(unsigned long r3, unsigned long r4, unsigned long r5,


+ unsigned long r6, unsigned long r7))
+{
+

+ if ( r3 )

+ memcpy( (void *)&res,(void *)(r3+KERNELBASE), sizeof(bd_t) );
+
+#ifdef CONFIG_PCI
+ mbx_setup_pci_ptrs();
+#endif
+


+#ifdef CONFIG_BLK_DEV_INITRD
+ /* take care of initrd if we have one */

+ if ( r4 )
+ {
+ initrd_start = r4 + KERNELBASE;
+ initrd_end = r5 + KERNELBASE;


+ }
+#endif /* CONFIG_BLK_DEV_INITRD */

+ /* take care of cmd line */
+ if ( r6 )
+ {
+
+ *(char *)(r7+KERNELBASE) = 0;
+ strcpy(cmd_line, (char *)(r6+KERNELBASE));
+ }
+
+ ppc_md.setup_arch = mbx_setup_arch;
+ ppc_md.setup_residual = mbx_setup_residual;
+ ppc_md.get_cpuinfo = NULL;
+ ppc_md.irq_cannonicalize = NULL;
+ ppc_md.init_IRQ = mbx_init_IRQ;
+ ppc_md.do_IRQ = mbx_do_IRQ;


+ ppc_md.init = NULL;
+

+ ppc_md.restart = mbx_restart;
+ ppc_md.power_off = mbx_power_off;
+ ppc_md.halt = mbx_halt;


+
+ ppc_md.time_init = NULL;

+ ppc_md.set_rtc_time = mbx_set_rtc_time;
+ ppc_md.get_rtc_time = mbx_get_rtc_time;
+ ppc_md.calibrate_decr = mbx_calibrate_decr;


+
+ ppc_md.kbd_setkeycode = pckbd_setkeycode;
+ ppc_md.kbd_getkeycode = pckbd_getkeycode;
+ ppc_md.kbd_translate = pckbd_translate;
+ ppc_md.kbd_unexpected_up = pckbd_unexpected_up;
+ ppc_md.kbd_leds = pckbd_leds;
+ ppc_md.kbd_init_hw = pckbd_init_hw;
+#ifdef CONFIG_MAGIC_SYSRQ
+ ppc_md.kbd_sysrq_xlate = pckbd_sysrq_xlate;
+#endif
+

+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+ ppc_ide_md.insw = mbx_ide_insw;
+ ppc_ide_md.outsw = mbx_ide_outsw;
+ ppc_ide_md.default_irq = mbx_ide_default_irq;
+ ppc_ide_md.default_io_base = mbx_ide_default_io_base;
+ ppc_ide_md.check_region = mbx_ide_check_region;
+ ppc_ide_md.request_region = mbx_ide_request_region;
+ ppc_ide_md.release_region = mbx_ide_release_region;
+ ppc_ide_md.fix_driveid = mbx_ide_fix_driveid;
+ ppc_ide_md.ide_init_hwif = mbx_ide_init_hwif_ports;


+
+ ppc_ide_md.io_base = _IO_BASE;
+#endif

X }
diff -u --recursive --new-file v2.2.7/linux/arch/ppc/kernel/misc.S linux/arch/ppc/kernel/misc.S
--- v2.2.7/linux/arch/ppc/kernel/misc.S Tue Mar 23 14:35:46 1999
+++ linux/arch/ppc/kernel/misc.S Thu Apr 29 12:39:01 1999
@@ -36,6 +36,7 @@
X * Returns (address we're running at) - (address we were linked at)
X * for use before the text and data are mapped to KERNELBASE.
X */
+
X _GLOBAL(reloc_offset)
X mflr r0
X bl 1f
@@ -72,8 +73,8 @@
X beqlr /* nothing to do if state == 0 */
X _GLOBAL(__sti)
X _GLOBAL(_hard_sti)
- lis r4,n_lost_interrupts@ha
- lwz r4,n_lost_interrupts@l(r4)
+ lis r4,ppc_n_lost_interrupts@ha
+ lwz r4,ppc_n_lost_interrupts@l(r4)
X mfmsr r3 /* Get current state */
X ori r3,r3,MSR_EE /* Turn on 'EE' bit */
X cmpi 0,r4,0 /* lost interrupts to process first? */
@@ -93,8 +94,8 @@
X stw r0,20(r1)
X stw r3,8(r1)
X 1: bl fake_interrupt
- lis r4,n_lost_interrupts@ha
- lwz r4,n_lost_interrupts@l(r4)
+ lis r4,ppc_n_lost_interrupts@ha


+ lwz r4,ppc_n_lost_interrupts@l(r4)
X cmpi 0,r4,0

X bne- 1b
X lwz r3,8(r1)
@@ -105,6 +106,20 @@
X addi r1,r1,16
X blr
X
+
+/*
+ * complement mask on the msr then "or" some values on.
+ * _nmask_and_or_msr(nmask, value_to_or)
+ */
+ _GLOBAL(_nmask_and_or_msr)
+ mfmsr r0 /* Get current msr */
+ andc r0,r0,r3 /* And off the bits set in r3 (first parm) */
+ or r0,r0,r4 /* Or on the bits in r4 (second parm) */
+ sync /* Some chip revs have problems here... */
+ mtmsr r0 /* Update machine state */
+ blr /* Done */
+
+
X /*
X * Flush MMU TLB
X */
@@ -613,16 +628,6 @@
X stfd 0,-4(r5)
X blr
X
- .globl __clear_msr_me
-__clear_msr_me:
- mfmsr r0 /* Get current interrupt state */
- lis r3,0
- ori r3,r3,MSR_ME
- andc r0,r0,r3 /* Clears bit in (r4) */
- sync /* Some chip revs have problems here */
- mtmsr r0 /* Update machine state */
- blr
-
X _GLOBAL(cvt_df)
X cvt_df:
X lfd 0,-4(r5) /* load up fpscr value */
@@ -633,6 +638,16 @@
X stfd 0,-4(r5)
X blr
X
+ .globl __clear_msr_me
+__clear_msr_me:
+ mfmsr r0 /* Get current interrupt state */
+ lis r3,0
+ ori r3,r3,MSR_ME
+ andc r0,r0,r3 /* Clears bit in (r4) */
+ sync /* Some chip revs have problems here */
+ mtmsr r0 /* Update machine state */
+ blr
+
X /*
X * Fetch the current SR register
X * get_SR(int index)
@@ -651,6 +666,8 @@
X sc
X cmpi 0,r3,0 /* parent or child? */
X bnelr /* return if parent */
+ li r0,0 /* clear out p->tss.regs */
+ stw r0,TSS+PT_REGS(r2) /* since we don't have user ctx */
X mtlr r4 /* fn addr in lr */
X mr r3,r5 /* load arg and call fn */
X blrl
diff -u --recursive --new-file v2.2.7/linux/arch/ppc/kernel/mk_defs.c linux/arch/ppc/kernel/mk_defs.c
--- v2.2.7/linux/arch/ppc/kernel/mk_defs.c Wed Sep 9 14:51:06 1998
+++ linux/arch/ppc/kernel/mk_defs.c Tue May 11 08:24:32 1999
@@ -29,7 +29,7 @@
X int
X main(void)
X {
- DEFINE(KERNELBASE, KERNELBASE);
+ /*DEFINE(KERNELBASE, KERNELBASE);*/
X DEFINE(STATE, offsetof(struct task_struct, state));
X DEFINE(NEXT_TASK, offsetof(struct task_struct, next_task));
X DEFINE(COUNTER, offsetof(struct task_struct, counter));
@@ -48,7 +48,6 @@
X DEFINE(NEED_RESCHED, offsetof(struct task_struct, need_resched));
X DEFINE(TSS_FPR0, offsetof(struct thread_struct, fpr[0]));
X DEFINE(TSS_FPSCR, offsetof(struct thread_struct, fpscr));
- DEFINE(TSS_SMP_FORK_RET, offsetof(struct thread_struct, smp_fork_ret));
X /* Interrupt register frame */
X DEFINE(TASK_UNION_SIZE, sizeof(union task_union));
X DEFINE(STACK_FRAME_OVERHEAD, STACK_FRAME_OVERHEAD);
diff -u --recursive --new-file v2.2.7/linux/arch/ppc/kernel/open_pic.c linux/arch/ppc/kernel/open_pic.c
--- v2.2.7/linux/arch/ppc/kernel/open_pic.c Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/kernel/open_pic.c Tue May 11 08:24:32 1999
@@ -0,0 +1,48 @@


+#include <linux/stddef.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/signal.h>

+#include <linux/openpic.h>
+#include <asm/irq.h>
+#include "open_pic.h"
+#include "i8259.h"
+
+#ifdef __SMP__
+void openpic_ipi_action(int cpl, void *dev_id, struct pt_regs *regs)
+{
+ smp_message_recv();
+}


+#endif /* __SMP__ */
+

+void chrp_mask_and_ack_irq(unsigned int irq_nr)
+{
+ if (is_8259_irq(irq_nr))
+ i8259_pic.mask_and_ack(irq_nr);
+}
+
+static void chrp_mask_irq(unsigned int irq_nr)
+{
+ if (is_8259_irq(irq_nr))
+ i8259_pic.disable(irq_nr);
+ else
+ openpic_disable_irq(irq_to_openpic(irq_nr));
+}
+
+static void chrp_unmask_irq(unsigned int irq_nr)
+{
+ if (is_8259_irq(irq_nr))
+ i8259_pic.enable(irq_nr);
+ else
+ openpic_enable_irq(irq_to_openpic(irq_nr));
+}
+
+struct hw_interrupt_type open_pic = {
+ " OpenPIC ",


+ NULL,
+ NULL,
+ NULL,

+ chrp_unmask_irq,
+ chrp_mask_irq,
+ chrp_mask_and_ack_irq,
+ 0
+};
diff -u --recursive --new-file v2.2.7/linux/arch/ppc/kernel/open_pic.h linux/arch/ppc/kernel/open_pic.h
--- v2.2.7/linux/arch/ppc/kernel/open_pic.h Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/kernel/open_pic.h Thu Apr 29 12:39:01 1999
@@ -0,0 +1,11 @@
+
+#ifndef _PPC_KERNEL_OPEN_PIC_H
+#define _PPC_KERNEL_OPEN_PIC_H
+
+#include "local_irq.h"
+
+extern struct hw_interrupt_type open_pic;
+
+void openpic_ipi_action(int cpl, void *dev_id, struct pt_regs *regs);
+
+#endif /* _PPC_KERNEL_OPEN_PIC_H */
diff -u --recursive --new-file v2.2.7/linux/arch/ppc/kernel/openpic.c linux/arch/ppc/kernel/openpic.c
--- v2.2.7/linux/arch/ppc/kernel/openpic.c Tue Mar 23 14:35:46 1999
+++ linux/arch/ppc/kernel/openpic.c Thu Apr 29 12:39:01 1999
@@ -190,6 +190,9 @@
X case 2:
X version = "1.2";
X break;
+ case 3:
+ version = "1.3";
+ break;
X default:
X version = "?";
X break;
diff -u --recursive --new-file v2.2.7/linux/arch/ppc/kernel/pci.c linux/arch/ppc/kernel/pci.c
--- v2.2.7/linux/arch/ppc/kernel/pci.c Tue Mar 23 14:35:46 1999
+++ linux/arch/ppc/kernel/pci.c Thu Apr 29 12:39:01 1999


@@ -1,5 +1,5 @@
X /*

- * $Id: pci.c,v 1.53 1999/03/12 23:38:02 cort Exp $
+ * $Id: pci.c,v 1.54 1999/03/18 04:16:04 cort Exp $
X * Common pmac/prep/chrp pci routines. -- Cort
X */
X
@@ -21,97 +21,41 @@
X #include <asm/irq.h>
X #include <asm/gg2.h>
X
-unsigned long isa_io_base;
-unsigned long isa_mem_base;
-unsigned long pci_dram_offset;
-unsigned int * pci_config_address;
-unsigned char * pci_config_data;
-
-static void fix_intr(struct device_node *node, struct pci_dev *dev);
-
-/*
- * It would be nice if we could create a include/asm/pci.h and have just
- * function ptrs for all these in there, but that isn't the case.
- * We have a function, pcibios_*() which calls the function ptr ptr_pcibios_*()
- * which has been setup by pcibios_init(). This is all to avoid a check
- * for pmac/prep every time we call one of these. It should also make the move
- * to a include/asm/pcibios.h easier, we can drop the ptr_ on these functions
- * and create pci.h


- * -- Cort
- */

-int (*ptr_pcibios_read_config_byte)(unsigned char bus, unsigned char dev_fn,
- unsigned char offset, unsigned char *val);
-int (*ptr_pcibios_read_config_word)(unsigned char bus, unsigned char dev_fn,
- unsigned char offset, unsigned short *val);
-int (*ptr_pcibios_read_config_dword)(unsigned char bus, unsigned char dev_fn,
- unsigned char offset, unsigned int *val);
-int (*ptr_pcibios_write_config_byte)(unsigned char bus, unsigned char dev_fn,
- unsigned char offset, unsigned char val);
-int (*ptr_pcibios_write_config_word)(unsigned char bus, unsigned char dev_fn,
- unsigned char offset, unsigned short val);
-int (*ptr_pcibios_write_config_dword)(unsigned char bus, unsigned char dev_fn,
- unsigned char offset, unsigned int val);
-
-#define decl_config_access_method(name) \
-extern int name##_pcibios_read_config_byte(unsigned char bus, \
- unsigned char dev_fn, unsigned char offset, unsigned char *val); \
-extern int name##_pcibios_read_config_word(unsigned char bus, \
- unsigned char dev_fn, unsigned char offset, unsigned short *val); \
-extern int name##_pcibios_read_config_dword(unsigned char bus, \
- unsigned char dev_fn, unsigned char offset, unsigned int *val); \
-extern int name##_pcibios_write_config_byte(unsigned char bus, \
- unsigned char dev_fn, unsigned char offset, unsigned char val); \
-extern int name##_pcibios_write_config_word(unsigned char bus, \
- unsigned char dev_fn, unsigned char offset, unsigned short val); \
-extern int name##_pcibios_write_config_dword(unsigned char bus, \
- unsigned char dev_fn, unsigned char offset, unsigned int val)
-
-#define set_config_access_method(name) \
- ptr_pcibios_read_config_byte = name##_pcibios_read_config_byte; \
- ptr_pcibios_read_config_word = name##_pcibios_read_config_word; \
- ptr_pcibios_read_config_dword = name##_pcibios_read_config_dword; \
- ptr_pcibios_write_config_byte = name##_pcibios_write_config_byte; \
- ptr_pcibios_write_config_word = name##_pcibios_write_config_word; \
- ptr_pcibios_write_config_dword = name##_pcibios_write_config_dword
-
-decl_config_access_method(mech1);
-decl_config_access_method(pmac);
-decl_config_access_method(grackle);
-decl_config_access_method(gg2);
-decl_config_access_method(raven);
-decl_config_access_method(prep);
-decl_config_access_method(mbx);
-decl_config_access_method(python);
+#include "pci.h"
+
+unsigned long isa_io_base = 0;
+unsigned long isa_mem_base = 0;
+unsigned long pci_dram_offset = 0;
X
X int pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn,
X unsigned char offset, unsigned char *val)
X {
- return ptr_pcibios_read_config_byte(bus,dev_fn,offset,val);
+ return ppc_md.pcibios_read_config_byte(bus,dev_fn,offset,val);
X }
X int pcibios_read_config_word(unsigned char bus, unsigned char dev_fn,
X unsigned char offset, unsigned short *val)
X {
- return ptr_pcibios_read_config_word(bus,dev_fn,offset,val);
+ return ppc_md.pcibios_read_config_word(bus,dev_fn,offset,val);
X }
X int pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn,
X unsigned char offset, unsigned int *val)
X {
- return ptr_pcibios_read_config_dword(bus,dev_fn,offset,val);
+ return ppc_md.pcibios_read_config_dword(bus,dev_fn,offset,val);
X }
X int pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn,
X unsigned char offset, unsigned char val)
X {
- return ptr_pcibios_write_config_byte(bus,dev_fn,offset,val);
+ return ppc_md.pcibios_write_config_byte(bus,dev_fn,offset,val);
X }
X int pcibios_write_config_word(unsigned char bus, unsigned char dev_fn,
X unsigned char offset, unsigned short val)
X {
- return ptr_pcibios_write_config_word(bus,dev_fn,offset,val);
+ return ppc_md.pcibios_write_config_word(bus,dev_fn,offset,val);
X }
X int pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,
X unsigned char offset, unsigned int val)
X {
- return ptr_pcibios_write_config_dword(bus,dev_fn,offset,val);
+ return ppc_md.pcibios_write_config_dword(bus,dev_fn,offset,val);
X }
X
X int pcibios_present(void)
@@ -123,175 +67,10 @@
X {
X }
X
-void __init setup_pci_ptrs(void)
-{
-#ifndef CONFIG_MBX
- PPC_DEVICE *hostbridge;
- switch (_machine) {
- case _MACH_prep:
- printk("PReP architecture\n");
- if ( _prep_type == _PREP_Radstone )
- {
- printk("Setting PCI access method to mech1\n");
- set_config_access_method(mech1);
- break;
- }
-
- hostbridge=residual_find_device(PROCESSORDEVICE, NULL,
- BridgeController, PCIBridge,
- -1, 0);
- if (hostbridge &&
- hostbridge->DeviceId.Interface == PCIBridgeIndirect) {
- PnP_TAG_PACKET * pkt;
- set_config_access_method(raven);
- pkt=PnP_find_large_vendor_packet(
- res->DevicePnPHeap+hostbridge->AllocatedOffset,
- 3, 0);
- if(pkt) {
-#define p pkt->L4_Pack.L4_Data.L4_PPCPack
- pci_config_address= (unsigned *)
- ld_le32((unsigned *) p.PPCData);
- pci_config_data= (unsigned char *)
- ld_le32((unsigned *) (p.PPCData+8));
- } else {/* default values */
- pci_config_address= (unsigned *) 0x80000cf8;
- pci_config_data= (unsigned char *) 0x80000cfc;
- }
- } else {
- set_config_access_method(prep);
- }
- break;
- case _MACH_Pmac:
- if (find_devices("pci") != 0) {
- /* looks like a G3 powermac */
- set_config_access_method(grackle);
- } else {
- set_config_access_method(pmac);


- }
- break;
- case _MACH_chrp:

- if ( !strncmp("MOT",
- get_property(find_path_device("/"), "model", NULL),3) )
- {
- pci_dram_offset = 0;
- isa_mem_base = 0xf7000000;
- isa_io_base = 0xfe000000;
- set_config_access_method(grackle);
- }
- else
- {
- if ( !strncmp("F5",
- get_property(find_path_device("/"),
- "ibm,model-class", NULL),2) )
-
- {
- pci_dram_offset = 0x80000000;
- isa_mem_base = 0xa0000000;
- isa_io_base = 0x88000000;
- set_config_access_method(python);
- }
- else
- {
- pci_dram_offset = 0;
- isa_mem_base = 0xf7000000;
- isa_io_base = 0xf8000000;
- set_config_access_method(gg2);
- }
- }
- break;
- default:
- printk("setup_pci_ptrs(): unknown machine type!\n");
- }
-#else /* CONFIG_MBX */
- set_config_access_method(mbx);
-#endif /* CONFIG_MBX */
-#undef set_config_access_method
-}
X
X void __init pcibios_fixup(void)
X {
- extern unsigned long route_pci_interrupts(void);
- struct pci_dev *dev;
- extern struct bridge_data **bridges;
- extern unsigned char *Motherboard_map;
- extern unsigned char *Motherboard_routes;
- unsigned char i;
-#ifndef CONFIG_MBX
- switch (_machine )
- {
- case _MACH_prep:
- if ( _prep_type == _PREP_Radstone )
- {
- printk("Radstone boards require no PCI fixups\n");
- break;
- }
-
- route_pci_interrupts();
- for(dev=pci_devices; dev; dev=dev->next)
- {
- /*
- * Use our old hard-coded kludge to figure out what
- * irq this device uses. This is necessary on things
- * without residual data. -- Cort
- */
- unsigned char d = PCI_SLOT(dev->devfn);
- dev->irq = Motherboard_routes[Motherboard_map[d]];
- for ( i = 0 ; i <= 5 ; i++ )
- {
- if ( dev->base_address[i] > 0x10000000 )
- {
- printk("Relocating PCI address %lx -> %lx\n",
- dev->base_address[i],
- (dev->base_address[i] & 0x00FFFFFF)
- | 0x01000000);
- dev->base_address[i] =
- (dev->base_address[i] & 0x00FFFFFF) | 0x01000000;
- pci_write_config_dword(dev,
- PCI_BASE_ADDRESS_0+(i*0x4),
- dev->base_address[i] );
- }
- }
-#if 0
- /*
- * If we have residual data and if it knows about this
- * device ask it what the irq is.


- * -- Cort
- */

- ppcd = residual_find_device_id( ~0L, dev->device,
- -1,-1,-1, 0);
-#endif

- }
- break;
- case _MACH_chrp:

- /* PCI interrupts are controlled by the OpenPIC */
- for(dev=pci_devices; dev; dev=dev->next)
- if (dev->irq)
- dev->irq = openpic_to_irq(dev->irq);
- break;
- case _MACH_Pmac:
- for(dev=pci_devices; dev; dev=dev->next)
- {
- /*
- * Open Firmware often doesn't initialize the,
- * PCI_INTERRUPT_LINE config register properly, so we
- * should find the device node and se if it has an
- * AAPL,interrupts property.
- */
- struct bridge_data *bp = bridges[dev->bus->number];
- unsigned char pin;
-
- if (pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin) ||
- !pin)
- continue; /* No interrupt generated -> no fixup */
- fix_intr(bp->node->child, dev);
- }
- break;
- }
-#else /* CONFIG_MBX */
- for(dev=pci_devices; dev; dev=dev->next)
- {
- }
-#endif /* CONFIG_MBX */
+ ppc_md.pcibios_fixup();
X }
X
X void __init pcibios_fixup_bus(struct pci_bus *bus)
@@ -309,7 +88,7 @@
X * fix IRQ's for cards located behind P2P bridges.
X * - Ranjit Deshpande, 01/20/99
X */
-static void __init fix_intr(struct device_node *node, struct pci_dev *dev)
+void __init fix_intr(struct device_node *node, struct pci_dev *dev)
X {
X unsigned int *reg, *class_code;
X
diff -u --recursive --new-file v2.2.7/linux/arch/ppc/kernel/pci.h linux/arch/ppc/kernel/pci.h
--- v2.2.7/linux/arch/ppc/kernel/pci.h Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/kernel/pci.h Thu Apr 29 12:39:01 1999
@@ -0,0 +1,36 @@
+
+#ifndef __PPC_KERNEL_PCI_H__
+#define __PPC_KERNEL_PCI_H__
+
+extern unsigned long isa_io_base;
+extern unsigned long isa_mem_base;
+extern unsigned long pci_dram_offset;
+
+extern unsigned int *pci_config_address;
+extern unsigned char *pci_config_data;
+
+void fix_intr(struct device_node *node, struct pci_dev *dev);
+
+#define decl_config_access_method(name) \
+extern int name##_pcibios_read_config_byte(unsigned char bus, \
+ unsigned char dev_fn, unsigned char offset, unsigned char *val); \
+extern int name##_pcibios_read_config_word(unsigned char bus, \
+ unsigned char dev_fn, unsigned char offset, unsigned short *val); \
+extern int name##_pcibios_read_config_dword(unsigned char bus, \
+ unsigned char dev_fn, unsigned char offset, unsigned int *val); \
+extern int name##_pcibios_write_config_byte(unsigned char bus, \
+ unsigned char dev_fn, unsigned char offset, unsigned char val); \
+extern int name##_pcibios_write_config_word(unsigned char bus, \
+ unsigned char dev_fn, unsigned char offset, unsigned short val); \
+extern int name##_pcibios_write_config_dword(unsigned char bus, \
+ unsigned char dev_fn, unsigned char offset, unsigned int val)
+
+#define set_config_access_method(name) \
+ ppc_md.pcibios_read_config_byte = name##_pcibios_read_config_byte; \
+ ppc_md.pcibios_read_config_word = name##_pcibios_read_config_word; \
+ ppc_md.pcibios_read_config_dword = name##_pcibios_read_config_dword; \
+ ppc_md.pcibios_write_config_byte = name##_pcibios_write_config_byte; \
+ ppc_md.pcibios_write_config_word = name##_pcibios_write_config_word; \
+ ppc_md.pcibios_write_config_dword = name##_pcibios_write_config_dword
+
+#endif /* __PPC_KERNEL_PCI_H__ */
diff -u --recursive --new-file v2.2.7/linux/arch/ppc/kernel/pmac_pci.c linux/arch/ppc/kernel/pmac_pci.c
--- v2.2.7/linux/arch/ppc/kernel/pmac_pci.c Tue Mar 23 14:35:46 1999
+++ linux/arch/ppc/kernel/pmac_pci.c Thu Apr 29 12:39:01 1999
@@ -21,6 +21,9 @@
X #include <asm/pgtable.h>
X #include <asm/prom.h>
X #include <asm/pci-bridge.h>


+#include <asm/machdep.h>
+
+#include "pci.h"
X

X struct bridge_data **bridges, *bridge_list;
X static int max_bus;
@@ -437,5 +440,49 @@
X if (strcmp(dev->name, "bandit") == 0)
X init_bandit(bp);
X }
+}
+
+__initfunc(
+void
+pmac_pcibios_fixup(void))


+{
+ struct pci_dev *dev;

+
+ /*
+ * FIXME: This is broken: We should not assign IRQ's to IRQless
+ * devices (look at PCI_INTERRUPT_PIN) and we also should
+ * honor the existence of multi-function devices where
+ * different functions have different interrupt pins. [mj]
+ */
+ for(dev=pci_devices; dev; dev=dev->next)
+ {
+ /*
+ * Open Firmware often doesn't initialize the,
+ * PCI_INTERRUPT_LINE config register properly, so we
+ * should find the device node and se if it has an
+ * AAPL,interrupts property.
+ */
+ struct bridge_data *bp = bridges[dev->bus->number];
+ unsigned char pin;
+
+ if (pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin) ||
+ !pin)
+ continue; /* No interrupt generated -> no fixup */
+ fix_intr(bp->node->child, dev);
+ }
+}
+
+__initfunc(
+void
+pmac_setup_pci_ptrs(void))
+{
+ if (find_devices("pci") != 0) {
+ /* looks like a G3 powermac */
+ set_config_access_method(grackle);
+ } else {
+ set_config_access_method(pmac);
+ }
+
+ ppc_md.pcibios_fixup = pmac_pcibios_fixup;
X }
X
diff -u --recursive --new-file v2.2.7/linux/arch/ppc/kernel/pmac_pic.c linux/arch/ppc/kernel/pmac_pic.c
--- v2.2.7/linux/arch/ppc/kernel/pmac_pic.c Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/kernel/pmac_pic.c Tue May 11 08:24:32 1999
@@ -0,0 +1,362 @@


+
+#include <linux/stddef.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <asm/io.h>

+#include <asm/smp.h>
+#include <asm/prom.h>
+#include "pmac_pic.h"
+
+/* pmac */struct pmac_irq_hw {
+ unsigned int flag;
+ unsigned int enable;
+ unsigned int ack;
+ unsigned int level;
+};
+
+/* XXX these addresses should be obtained from the device tree */
+static volatile struct pmac_irq_hw *pmac_irq_hw[4] = {
+ (struct pmac_irq_hw *) 0xf3000020,
+ (struct pmac_irq_hw *) 0xf3000010,
+ (struct pmac_irq_hw *) 0xf4000020,
+ (struct pmac_irq_hw *) 0xf4000010,
+};
+
+static int max_irqs;
+static int max_real_irqs;
+
+#define MAXCOUNT 10000000
+
+#define GATWICK_IRQ_POOL_SIZE 10
+static struct interrupt_info gatwick_int_pool[GATWICK_IRQ_POOL_SIZE];
+
+static void __pmac pmac_mask_and_ack_irq(unsigned int irq_nr)
+{
+ unsigned long bit = 1UL << (irq_nr & 0x1f);
+ int i = irq_nr >> 5;
+
+ if ((unsigned)irq_nr >= max_irqs)
+ return;
+
+ clear_bit(irq_nr, ppc_cached_irq_mask);
+ if (test_and_clear_bit(irq_nr, ppc_lost_interrupts))
+ atomic_dec(&ppc_n_lost_interrupts);
+ out_le32(&pmac_irq_hw[i]->ack, bit);
+ out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]);
+ out_le32(&pmac_irq_hw[i]->ack, bit);
+ do {
+ /* make sure ack gets to controller before we enable
+ interrupts */
+ mb();
+ } while(in_le32(&pmac_irq_hw[i]->flag) & bit);
+}
+
+static void __pmac pmac_set_irq_mask(unsigned int irq_nr)
+{
+ unsigned long bit = 1UL << (irq_nr & 0x1f);
+ int i = irq_nr >> 5;
+
+ if ((unsigned)irq_nr >= max_irqs)
+ return;
+
+ /* enable unmasked interrupts */
+ out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]);
+
+ do {
+ /* make sure mask gets to controller before we
+ return to user */
+ mb();
+ } while((in_le32(&pmac_irq_hw[i]->enable) & bit)
+ != (ppc_cached_irq_mask[i] & bit));
+
+ /*
+ * Unfortunately, setting the bit in the enable register
+ * when the device interrupt is already on *doesn't* set
+ * the bit in the flag register or request another interrupt.
+ */
+ if ((bit & ppc_cached_irq_mask[i])
+ && (ld_le32(&pmac_irq_hw[i]->level) & bit)
+ && !(ld_le32(&pmac_irq_hw[i]->flag) & bit)) {
+ if (!test_and_set_bit(irq_nr, ppc_lost_interrupts))
+ atomic_inc(&ppc_n_lost_interrupts);
+ }
+}
+
+static void __pmac pmac_mask_irq(unsigned int irq_nr)
+{
+ clear_bit(irq_nr, ppc_cached_irq_mask);
+ pmac_set_irq_mask(irq_nr);
+ mb();
+}
+
+static void __pmac pmac_unmask_irq(unsigned int irq_nr)
+{
+ set_bit(irq_nr, ppc_cached_irq_mask);
+ pmac_set_irq_mask(irq_nr);
+}
+
+struct hw_interrupt_type pmac_pic = {
+ " PMAC-PIC ",


+ NULL,
+ NULL,
+ NULL,

+ pmac_unmask_irq,
+ pmac_mask_irq,
+ pmac_mask_and_ack_irq,
+ 0
+};
+
+struct hw_interrupt_type gatwick_pic = {
+ " GATWICK ",


+ NULL,
+ NULL,
+ NULL,

+ pmac_unmask_irq,
+ pmac_mask_irq,
+ pmac_mask_and_ack_irq,
+ 0
+};
+
+static void gatwick_action(int cpl, void *dev_id, struct pt_regs *regs)
+{
+ int irq, bits;
+
+ for (irq = max_irqs - 1; irq > max_real_irqs; irq -= 32) {
+ int i = irq >> 5;
+ bits = ld_le32(&pmac_irq_hw[i]->flag)
+ | ppc_lost_interrupts[i];
+ if (bits == 0)
+ continue;
+ irq -= cntlzw(bits);
+ break;
+ }
+ /* The previous version of this code allowed for this case, we
+ * don't. Put this here to check for it.


+ * -- Cort
+ */

+ if ( irq_desc[irq].ctl != &gatwick_pic )
+ printk("gatwick irq not from gatwick pic\n");
+ else


+ ppc_irq_dispatch_handler( regs, irq );
+}
+

+void
+pmac_do_IRQ(struct pt_regs *regs,


+ int cpu,
+ int isfake)

+{
+ int irq;
+ unsigned long bits = 0;
+
+#ifdef __SMP__
+ /* IPI's are a hack on the powersurge -- Cort */
+ if ( cpu != 0 )
+ {
+ if (!isfake)
+ {
+#ifdef CONFIG_XMON
+ static int xmon_2nd;
+ if (xmon_2nd)
+ xmon(regs);
+#endif
+ smp_message_recv();
+ goto out;
+ }
+ /* could be here due to a do_fake_interrupt call but we don't
+ mess with the controller from the second cpu -- Cort */


+ goto out;
+ }
+

+ {
+ unsigned int loops = MAXCOUNT;


+ while (test_bit(0, &global_irq_lock)) {
+ if (smp_processor_id() == global_irq_holder) {
+ printk("uh oh, interrupt while we hold global irq lock!\n");
+#ifdef CONFIG_XMON
+ xmon(0);
+#endif
+ break;
+ }
+ if (loops-- == 0) {
+ printk("do_IRQ waiting for irq lock (holder=%d)\n", global_irq_holder);
+#ifdef CONFIG_XMON
+ xmon(0);
+#endif
+ }
+ }
+ }

+#endif /* __SMP__ */
+

+ for (irq = max_real_irqs - 1; irq > 0; irq -= 32) {
+ int i = irq >> 5;
+ bits = ld_le32(&pmac_irq_hw[i]->flag)
+ | ppc_lost_interrupts[i];
+ if (bits == 0)
+ continue;
+ irq -= cntlzw(bits);
+ break;
+ }
+


+ if (irq < 0)
+ {
+ printk(KERN_DEBUG "Bogus interrupt %d from PC = %lx\n",
+ irq, regs->nip);
+ ppc_spurious_interrupts++;
+ }
+ else
+ {
+ ppc_irq_dispatch_handler( regs, irq );
+ }

+#ifdef CONFIG_SMP
+out:
+#endif /* CONFIG_SMP */
+}
+
+/* This routine will fix some missing interrupt values in the device tree
+ * on the gatwick mac-io controller used by some PowerBooks
+ */
+static void __init pmac_fix_gatwick_interrupts(struct device_node *gw, int irq_base)
+{
+ struct device_node *node;
+ int count;
+
+ memset(gatwick_int_pool, 0, sizeof(gatwick_int_pool));
+ node = gw->child;
+ count = 0;
+ while(node)
+ {
+ /* Fix SCC */
+ if (strcasecmp(node->name, "escc") == 0)
+ if (node->child) {
+ if (node->child->n_intrs < 3) {
+ node->child->intrs = &gatwick_int_pool[count];
+ count += 3;
+ }
+ node->child->n_intrs = 3;
+ node->child->intrs[0].line = 15+irq_base;
+ node->child->intrs[1].line = 4+irq_base;
+ node->child->intrs[2].line = 5+irq_base;
+ printk(KERN_INFO "irq: fixed SCC on second controller (%d,%d,%d)\n",
+ node->child->intrs[0].line,
+ node->child->intrs[1].line,
+ node->child->intrs[2].line);
+ }
+ /* Fix media-bay & left SWIM */
+ if (strcasecmp(node->name, "media-bay") == 0) {
+ struct device_node* ya_node;
+
+ if (node->n_intrs == 0)
+ node->intrs = &gatwick_int_pool[count++];
+ node->n_intrs = 1;
+ node->intrs[0].line = 29+irq_base;
+ printk(KERN_INFO "irq: fixed media-bay on second controller (%d)\n",
+ node->intrs[0].line);
+
+ ya_node = node->child;
+ while(ya_node)
+ {
+ if (strcasecmp(ya_node->name, "floppy") == 0) {
+ if (ya_node->n_intrs < 2) {
+ ya_node->intrs = &gatwick_int_pool[count];
+ count += 2;
+ }
+ ya_node->n_intrs = 2;
+ ya_node->intrs[0].line = 19+irq_base;
+ ya_node->intrs[1].line = 1+irq_base;
+ printk(KERN_INFO "irq: fixed floppy on second controller (%d,%d)\n",
+ ya_node->intrs[0].line, ya_node->intrs[1].line);
+ }
+ if (strcasecmp(ya_node->name, "ata4") == 0) {
+ if (ya_node->n_intrs < 2) {
+ ya_node->intrs = &gatwick_int_pool[count];
+ count += 2;
+ }
+ ya_node->n_intrs = 2;
+ ya_node->intrs[0].line = 14+irq_base;
+ ya_node->intrs[1].line = 3+irq_base;
+ printk(KERN_INFO "irq: fixed ide on second controller (%d,%d)\n",
+ ya_node->intrs[0].line, ya_node->intrs[1].line);
+ }
+ ya_node = ya_node->sibling;
+ }
+ }
+ node = node->sibling;
+ }
+ if (count > 10) {
+ printk("WARNING !! Gatwick interrupt pool overflow\n");
+ printk(" GATWICK_IRQ_POOL_SIZE = %d\n", GATWICK_IRQ_POOL_SIZE);
+ printk(" requested = %d\n", count);
+ }
+}
+
+__initfunc(void
+pmac_pic_init(void))
+{
+ int i;
+ struct device_node *irqctrler;
+ unsigned long addr;
+ int second_irq = -999;
+
+
+ /* G3 powermacs have 64 interrupts, G3 Series PowerBook have 128,
+ others have 32 */
+ max_irqs = max_real_irqs = 32;
+ irqctrler = find_devices("mac-io");
+ if (irqctrler)
+ {
+ max_real_irqs = 64;
+ if (irqctrler->next)
+ max_irqs = 128;
+ else
+ max_irqs = 64;
+ }
+ for ( i = 0; i < max_real_irqs ; i++ )
+ irq_desc[i].ctl = &pmac_pic;
+
+ /* get addresses of first controller */
+ if (irqctrler) {
+ if (irqctrler->n_addrs > 0) {
+ addr = (unsigned long)
+ ioremap(irqctrler->addrs[0].address, 0x40);
+ for (i = 0; i < 2; ++i)
+ pmac_irq_hw[i] = (volatile struct pmac_irq_hw*)
+ (addr + (2 - i) * 0x10);
+ }
+
+ /* get addresses of second controller */
+ irqctrler = (irqctrler->next) ? irqctrler->next : NULL;
+ if (irqctrler && irqctrler->n_addrs > 0) {
+ addr = (unsigned long)
+ ioremap(irqctrler->addrs[0].address, 0x40);
+ for (i = 2; i < 4; ++i)
+ pmac_irq_hw[i] = (volatile struct pmac_irq_hw*)
+ (addr + (4 - i) * 0x10);
+ }
+ }
+
+ /* disable all interrupts in all controllers */
+ for (i = 0; i * 32 < max_irqs; ++i)
+ out_le32(&pmac_irq_hw[i]->enable, 0);
+
+ /* get interrupt line of secondary interrupt controller */
+ if (irqctrler) {
+ second_irq = irqctrler->intrs[0].line;
+ printk(KERN_INFO "irq: secondary controller on irq %d\n",
+ (int)second_irq);
+ if (device_is_compatible(irqctrler, "gatwick"))
+ pmac_fix_gatwick_interrupts(irqctrler, max_real_irqs);
+ for ( i = max_real_irqs ; i < max_irqs ; i++ )
+ irq_desc[i].ctl = &gatwick_pic;
+ request_irq( second_irq, gatwick_action, SA_INTERRUPT,
+ "gatwick cascade", 0 );
+ }
+ printk("System has %d possible interrupts\n", max_irqs);
+ if (max_irqs != max_real_irqs)
+ printk(KERN_DEBUG "%d interrupts on main controller\n",
+ max_real_irqs);
+
+#ifdef CONFIG_XMON
+ request_irq(20, xmon_irq, 0, "NMI - XMON", 0);
+#endif /* CONFIG_XMON */
+}
diff -u --recursive --new-file v2.2.7/linux/arch/ppc/kernel/pmac_pic.h linux/arch/ppc/kernel/pmac_pic.h
--- v2.2.7/linux/arch/ppc/kernel/pmac_pic.h Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/kernel/pmac_pic.h Thu Apr 29 12:39:01 1999
@@ -0,0 +1,15 @@
+#ifndef _PPC_KERNEL_PMAC_PIC_H
+#define _PPC_KERNEL_PMAC_PIC_H
+
+#include "local_irq.h"
+
+extern struct hw_interrupt_type pmac_pic;
+
+void pmac_pic_init(void);
+void pmac_do_IRQ(struct pt_regs *regs,


+ int cpu,
+ int isfake);
+
+

+#endif /* _PPC_KERNEL_PMAC_PIC_H */
+
diff -u --recursive --new-file v2.2.7/linux/arch/ppc/kernel/pmac_setup.c linux/arch/ppc/kernel/pmac_setup.c
--- v2.2.7/linux/arch/ppc/kernel/pmac_setup.c Tue Mar 23 14:35:46 1999
+++ linux/arch/ppc/kernel/pmac_setup.c Tue May 11 08:24:32 1999
@@ -44,6 +44,7 @@
X #include <asm/prom.h>
X #include <asm/system.h>
X #include <asm/pgtable.h>
+#include <asm/bitops.h>
X #include <asm/io.h>
X #include <asm/pci-bridge.h>
X #include <asm/adb.h>
@@ -52,7 +53,38 @@
X #include <asm/ohare.h>
X #include <asm/mediabay.h>
X #include <asm/feature.h>


+#include <asm/ide.h>
+#include <asm/machdep.h>
+

X #include "time.h"
+#include "local_irq.h"
+#include "pmac_pic.h"
+
+#undef SHOW_GATWICK_IRQS
+
+unsigned long pmac_get_rtc_time(void);
+int pmac_set_rtc_time(unsigned long nowtime);
+void pmac_read_rtc_time(void);
+void pmac_calibrate_decr(void);
+void pmac_setup_pci_ptrs(void);


+
+extern int mackbd_setkeycode(unsigned int scancode, unsigned int keycode);
+extern int mackbd_getkeycode(unsigned int scancode);
+extern int mackbd_translate(unsigned char scancode, unsigned char *keycode,
+ char raw_mode);
+extern char mackbd_unexpected_up(unsigned char keycode);
+extern void mackbd_leds(unsigned char leds);
+extern void mackbd_init_hw(void);

+#ifdef CONFIG_MAGIC_SYSRQ
+unsigned char mackbd_sysrq_xlate[128];
+#endif /* CONFIG_MAGIC_SYSRQ */


+extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode);
+extern int pckbd_getkeycode(unsigned int scancode);

+extern int pckbd_translate(unsigned char scancode, unsigned char *keycode,
+ char raw_mode);


+extern char pckbd_unexpected_up(unsigned char keycode);
+extern void pckbd_leds(unsigned char leds);
+extern void pckbd_init_hw(void);

X
X unsigned char drive_info;
X
@@ -291,15 +323,12 @@
X int boot_part;
X kdev_t boot_dev;
X
-void __init powermac_init(void)
+__initfunc(void
+pmac_init2(void))
X {
- if ( (_machine != _MACH_chrp) && (_machine != _MACH_Pmac) )
- return;
X adb_init();
X pmac_nvram_init();
- if (_machine == _MACH_Pmac) {
- media_bay_init();
- }
+ media_bay_init();
X }
X
X #ifdef CONFIG_SCSI
@@ -402,5 +431,176 @@
X boot_dev = NODEV;
X printk(" (root)");
X }
+}
+
+void
+pmac_restart(char *cmd)
+{
+ struct adb_request req;
+
+ switch (adb_hardware) {
+ case ADB_VIACUDA:
+ cuda_request(&req, NULL, 2, CUDA_PACKET,
+ CUDA_RESET_SYSTEM);
+ for (;;)
+ cuda_poll();
+ break;
+
+ case ADB_VIAPMU:
+ pmu_restart();


+ break;
+ default:
+ }

+}
+
+void
+pmac_power_off(void)
+{
+ struct adb_request req;
+
+ switch (adb_hardware) {
+ case ADB_VIACUDA:
+ cuda_request(&req, NULL, 2, CUDA_PACKET,
+ CUDA_POWERDOWN);
+ for (;;)
+ cuda_poll();
+ break;
+
+ case ADB_VIAPMU:
+ pmu_shutdown();


+ break;
+ default:
+ }

+}
+
+void
+pmac_halt(void)
+{
+ pmac_power_off();
+}


+
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+/*
+ * IDE stuff.
+ */

+void
+pmac_ide_insw(ide_ioreg_t port, void *buf, int ns)
+{
+ ide_insw(port, buf, ns);
+}
+
+void
+pmac_ide_outsw(ide_ioreg_t port, void *buf, int ns)
+{
+ ide_outsw(port, buf, ns);
+}
+
+int
+pmac_ide_default_irq(ide_ioreg_t base)


+{
+ return 0;
+}
+

+ide_ioreg_t
+pmac_ide_default_io_base(int index)
+{
+#if defined(CONFIG_BLK_DEV_IDE_PMAC)
+ return pmac_ide_regbase[index];


+#else
+ return 0;
+#endif
+}
+

+int
+pmac_ide_check_region(ide_ioreg_t from, unsigned int extent)
+{
+ return 0;
+}
+
+void
+pmac_ide_request_region(ide_ioreg_t from,


+ unsigned int extent,
+ const char *name)
+{
+}

+
+void
+pmac_ide_release_region(ide_ioreg_t from,


+ unsigned int extent)
+{
+}

+
+/* Convert the shorts/longs in hd_driveid from little to big endian;
+ * chars are endian independant, of course, but strings need to be flipped.
+ * (Despite what it says in drivers/block/ide.h, they come up as little
+ * endian...)
+ *
+ * Changes to linux/hdreg.h may require changes here. */
+void
+pmac_ide_fix_driveid(struct hd_driveid *id)


+{
+ ppc_generic_ide_fix_driveid(id);
+}
+

+/* This is declared in drivers/block/ide-pmac.c */
+void pmac_ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq);
+#endif
+
+__initfunc(void
+pmac_init(unsigned long r3, unsigned long r4, unsigned long r5,


+ unsigned long r6, unsigned long r7))
+{

+ pmac_setup_pci_ptrs();
+
+ /* isa_io_base gets set in pmac_find_bridges */
+ isa_mem_base = PMAC_ISA_MEM_BASE;
+ pci_dram_offset = PMAC_PCI_DRAM_OFFSET;
+ ISA_DMA_THRESHOLD = ~0L;
+ DMA_MODE_READ = 1;
+ DMA_MODE_WRITE = 2;
+
+ ppc_md.setup_arch = pmac_setup_arch;
+ ppc_md.setup_residual = NULL;
+ ppc_md.get_cpuinfo = pmac_get_cpuinfo;
+ ppc_md.irq_cannonicalize = NULL;
+ ppc_md.init_IRQ = pmac_pic_init;
+ ppc_md.do_IRQ = pmac_do_IRQ;
+ ppc_md.init = pmac_init2;
+
+ ppc_md.restart = pmac_restart;
+ ppc_md.power_off = pmac_power_off;
+ ppc_md.halt = pmac_halt;


+
+ ppc_md.time_init = NULL;

+ ppc_md.set_rtc_time = pmac_set_rtc_time;
+ ppc_md.get_rtc_time = pmac_get_rtc_time;
+ ppc_md.calibrate_decr = pmac_calibrate_decr;
+
+#if defined(CONFIG_VT) && defined(CONFIG_MAC_KEYBOARD)


+ ppc_md.kbd_setkeycode = mackbd_setkeycode;
+ ppc_md.kbd_getkeycode = mackbd_getkeycode;
+ ppc_md.kbd_translate = mackbd_translate;
+ ppc_md.kbd_unexpected_up = mackbd_unexpected_up;
+ ppc_md.kbd_leds = mackbd_leds;
+ ppc_md.kbd_init_hw = mackbd_init_hw;
+#ifdef CONFIG_MAGIC_SYSRQ
+ ppc_md.kbd_sysrq_xlate = mackbd_sysrq_xlate;
+#endif

+#endif
+
+#if defined(CONFIG_BLK_DEV_IDE_PMAC)
+ ppc_ide_md.insw = pmac_ide_insw;
+ ppc_ide_md.outsw = pmac_ide_outsw;
+ ppc_ide_md.default_irq = pmac_ide_default_irq;
+ ppc_ide_md.default_io_base = pmac_ide_default_io_base;
+ ppc_ide_md.check_region = pmac_ide_check_region;
+ ppc_ide_md.request_region = pmac_ide_request_region;
+ ppc_ide_md.release_region = pmac_ide_release_region;
+ ppc_ide_md.fix_driveid = pmac_ide_fix_driveid;
+ ppc_ide_md.ide_init_hwif = pmac_ide_init_hwif_ports;
+
+ ppc_ide_md.io_base = 0;
+#endif
X }
X
diff -u --recursive --new-file v2.2.7/linux/arch/ppc/kernel/ppc8xx_pic.c linux/arch/ppc/kernel/ppc8xx_pic.c
--- v2.2.7/linux/arch/ppc/kernel/ppc8xx_pic.c Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/kernel/ppc8xx_pic.c Thu Apr 29 12:39:01 1999
@@ -0,0 +1,49 @@


+
+#include <linux/stddef.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/signal.h>

+#include <asm/irq.h>
+#include <asm/8xx_immap.h>
+#include <asm/mbx.h>
+#include "ppc8xx_pic.h"
+
+
+static void mbx_mask_irq(unsigned int irq_nr)
+{
+ if ( irq_nr == ISA_BRIDGE_INT ) return;
+ if ( irq_nr >= ppc8xx_pic.irq_offset )
+ irq_nr -= ppc8xx_pic.irq_offset;
+ ppc_cached_irq_mask[0] &= ~(1 << (31-irq_nr));
+ ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask = ppc_cached_irq_mask[0];
+}
+
+static void mbx_unmask_irq(unsigned int irq_nr)
+{
+ if ( irq_nr >= ppc8xx_pic.irq_offset )
+ irq_nr -= ppc8xx_pic.irq_offset;
+ ppc_cached_irq_mask[0] |= (1 << (31-irq_nr));
+ ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask = ppc_cached_irq_mask[0];
+}
+
+static void mbx_mask_and_ack(unsigned int irq_nr)
+{
+ /* this shouldn't be masked, we mask the 8259 if we need to -- Cort */
+ if ( irq_nr != ISA_BRIDGE_INT )
+ mbx_mask_irq(irq_nr);
+ if ( irq_nr >= ppc8xx_pic.irq_offset )
+ irq_nr -= ppc8xx_pic.irq_offset;
+ /* clear the pending bits */
+ ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_sipend = 1 << (31-irq_nr);
+}
+
+struct hw_interrupt_type ppc8xx_pic = {
+ " 8xx SIU ",


+ NULL,
+ NULL,
+ NULL,

+ mbx_unmask_irq,
+ mbx_mask_irq,
+ mbx_mask_and_ack,
+ 0
+};
diff -u --recursive --new-file v2.2.7/linux/arch/ppc/kernel/ppc8xx_pic.h linux/arch/ppc/kernel/ppc8xx_pic.h
--- v2.2.7/linux/arch/ppc/kernel/ppc8xx_pic.h Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/kernel/ppc8xx_pic.h Thu Apr 29 12:39:01 1999
@@ -0,0 +1,9 @@
+
+#ifndef _PPC_KERNEL_PPC8xx_H
+#define _PPC_KERNEL_PPC8xx_H
+
+#include "local_irq.h"
+
+extern struct hw_interrupt_type ppc8xx_pic;
+
+#endif /* _PPC_KERNEL_PPC8xx_H */
diff -u --recursive --new-file v2.2.7/linux/arch/ppc/kernel/ppc_ksyms.c linux/arch/ppc/kernel/ppc_ksyms.c
--- v2.2.7/linux/arch/ppc/kernel/ppc_ksyms.c Tue Mar 23 14:35:46 1999
+++ linux/arch/ppc/kernel/ppc_ksyms.c Thu Apr 29 12:39:01 1999
@@ -27,6 +27,8 @@
X #include <asm/irq.h>
X #include <asm/feature.h>
X #include <asm/spinlock.h>
+#include <asm/dma.h>
+#include <asm/machdep.h>
X
X #define __KERNEL_SYSCALLS__
X #include <linux/unistd.h>
@@ -40,7 +42,7 @@
X extern void ProgramCheckException(struct pt_regs *regs);
X extern void SingleStepException(struct pt_regs *regs);
X extern int sys_sigreturn(struct pt_regs *regs);
-extern atomic_t n_lost_interrupts;
+extern atomic_t ppc_n_lost_interrupts;
X extern void do_lost_interrupts(unsigned long);
X extern int do_signal(sigset_t *, struct pt_regs *);
X
@@ -59,16 +61,21 @@
X EXPORT_SYMBOL(ProgramCheckException);
X EXPORT_SYMBOL(SingleStepException);
X EXPORT_SYMBOL(sys_sigreturn);
-EXPORT_SYMBOL(n_lost_interrupts);
+EXPORT_SYMBOL(ppc_n_lost_interrupts);
X EXPORT_SYMBOL(do_lost_interrupts);
X EXPORT_SYMBOL(enable_irq);
X EXPORT_SYMBOL(disable_irq);
-EXPORT_SYMBOL(local_irq_count);
-EXPORT_SYMBOL(local_bh_count);
+EXPORT_SYMBOL(ppc_local_irq_count);
+EXPORT_SYMBOL(ppc_local_bh_count);
X
X EXPORT_SYMBOL(isa_io_base);
X EXPORT_SYMBOL(isa_mem_base);
X EXPORT_SYMBOL(pci_dram_offset);
+EXPORT_SYMBOL(ISA_DMA_THRESHOLD);
+EXPORT_SYMBOL(DMA_MODE_READ);
+EXPORT_SYMBOL(DMA_MODE_WRITE);
+EXPORT_SYMBOL(_prep_type);
+EXPORT_SYMBOL(ucSystemType);
X
X EXPORT_SYMBOL(atomic_add);
X EXPORT_SYMBOL(atomic_sub);
@@ -157,6 +164,7 @@
X EXPORT_SYMBOL(flush_instruction_cache);
X EXPORT_SYMBOL(_get_PVR);
X EXPORT_SYMBOL(giveup_fpu);
+EXPORT_SYMBOL(enable_kernel_fp);
X EXPORT_SYMBOL(flush_icache_range);
X EXPORT_SYMBOL(xchg_u32);
X #ifdef __SMP__
@@ -173,18 +181,14 @@
X EXPORT_SYMBOL(_write_unlock);
X #endif
X
-#ifndef CONFIG_MACH_SPECIFIC
X EXPORT_SYMBOL(_machine);
-#endif
+EXPORT_SYMBOL(ppc_md);
X
X EXPORT_SYMBOL(adb_request);
-EXPORT_SYMBOL(adb_autopoll);
X EXPORT_SYMBOL(adb_register);
X EXPORT_SYMBOL(cuda_request);
-EXPORT_SYMBOL(cuda_send_request);
X EXPORT_SYMBOL(cuda_poll);
X EXPORT_SYMBOL(pmu_request);
-EXPORT_SYMBOL(pmu_send_request);
X EXPORT_SYMBOL(pmu_poll);
X #ifdef CONFIG_PMAC_PBOOK
X EXPORT_SYMBOL(sleep_notifier_list);
@@ -196,7 +200,6 @@
X EXPORT_SYMBOL(find_path_device);
X EXPORT_SYMBOL(find_phandle);
X EXPORT_SYMBOL(get_property);
-EXPORT_SYMBOL(device_is_compatible);
X EXPORT_SYMBOL(pci_io_base);
X EXPORT_SYMBOL(pci_device_loc);
X EXPORT_SYMBOL(feature_set);
@@ -211,9 +214,8 @@
X EXPORT_SYMBOL(nvram_write_byte);
X #endif /* CONFIG_PMAC */
X
-#ifdef CONFIG_SOUND_MODULE
X EXPORT_SYMBOL(abs);
-#endif
+EXPORT_SYMBOL(device_is_compatible);
X
X /* The following are special because they're not called
X explicitly (the C compiler generates them). Fortunately,
diff -u --recursive --new-file v2.2.7/linux/arch/ppc/kernel/prep_nvram.c linux/arch/ppc/kernel/prep_nvram.c
--- v2.2.7/linux/arch/ppc/kernel/prep_nvram.c Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/kernel/prep_nvram.c Thu Apr 29 12:39:01 1999
@@ -0,0 +1,173 @@
+/*
+ * linux/arch/ppc/kernel/prep_nvram.c
+ *
+ * Copyright (C) 1998 Corey Minyard
+ *
+ */
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/malloc.h>
+#include <linux/ioport.h>
+
+#include <asm/segment.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <asm/machdep.h>
+#include <asm/prep_nvram.h>
+
+/*
+ * Allow for a maximum of 32K of PReP NvRAM data
+ */
+#define MAX_PREP_NVRAM 0x8000
+static char nvramData[MAX_PREP_NVRAM];
+static NVRAM_MAP *nvram=(NVRAM_MAP *)&nvramData[0];
+
+#define PREP_NVRAM_AS0 0x74
+#define PREP_NVRAM_AS1 0x75
+#define PREP_NVRAM_DATA 0x77
+
+unsigned char *rs_pcNvRAM;
+
+unsigned char prep_nvram_read_val(int addr)
+{
+ outb(addr, PREP_NVRAM_AS0);
+ outb(addr>>8, PREP_NVRAM_AS1);
+ return inb(PREP_NVRAM_DATA);
+}
+
+void prep_nvram_write_val(int addr,
+ unsigned char val)
+{
+ outb(addr, PREP_NVRAM_AS0);
+ outb(addr>>8, PREP_NVRAM_AS1);
+ outb(val, PREP_NVRAM_DATA);
+}
+
+/*
+ * Most Radstone boards have NvRAM memory mapped at offset 8M in ISA space
+ */
+unsigned char rs_nvram_read_val(int addr)
+{
+ return rs_pcNvRAM[addr];
+}
+
+void rs_nvram_write_val(int addr,
+ unsigned char val)
+{
+ rs_pcNvRAM[addr]=val;
+}
+
+__initfunc(void init_prep_nvram(void))
+{
+ unsigned char *nvp;
+ int i;
+ int nvramSize;
+
+ /*
+ * I'm making the assumption that 32k will always cover the
+ * nvramsize. If this isn't the case please let me know and we can
+ * map the header, then get the size from the header, then map
+ * the whole size. -- Cort
+ */
+ if ( _prep_type == _PREP_Radstone )
+ rs_pcNvRAM = (unsigned char *)ioremap(_ISA_MEM_BASE+0x00800000,
+ 32<<10);
+ request_region(PREP_NVRAM_AS0, 0x8, "PReP NVRAM");
+ /*
+ * The following could fail if the NvRAM were corrupt but
+ * we expect the boot firmware to have checked its checksum
+ * before boot
+ */
+ nvp = (char *) &nvram->Header;
+ for (i=0; i<sizeof(HEADER); i++)
+ {
+ *nvp = ppc_md.nvram_read_val(i);
+ nvp++;
+ }
+
+ /*
+ * The PReP NvRAM may be any size so read in the header to
+ * determine how much we must read in order to get the complete
+ * GE area
+ */
+ nvramSize=(int)nvram->Header.GEAddress+nvram->Header.GELength;
+ if(nvramSize>MAX_PREP_NVRAM)
+ {
+ /*
+ * NvRAM is too large
+ */
+ nvram->Header.GELength=0;
+ return;
+ }
+
+ /*
+ * Read the remainder of the PReP NvRAM
+ */
+ nvp = (char *) &nvram->GEArea[0];
+ for (i=sizeof(HEADER); i<nvramSize; i++)
+ {
+ *nvp = ppc_md.nvram_read_val(i);
+ nvp++;
+ }
+}
+
+__prep
+char *prep_nvram_get_var(const char *name)
+{
+ char *cp;
+ int namelen;
+
+ namelen = strlen(name);
+ cp = prep_nvram_first_var();
+ while (cp != NULL) {
+ if ((strncmp(name, cp, namelen) == 0)
+ && (cp[namelen] == '='))
+ {
+ return cp+namelen+1;
+ }
+ cp = prep_nvram_next_var(cp);
+ }
+
+ return NULL;
+}
+
+__prep
+char *prep_nvram_first_var(void)
+{
+ if (nvram->Header.GELength == 0) {
+ return NULL;
+ } else {
+ return (((char *)nvram)
+ + ((unsigned int) nvram->Header.GEAddress));
+ }
+}
+
+__prep
+char *prep_nvram_next_var(char *name)
+{
+ char *cp;
+
+
+ cp = name;
+ while (((cp - ((char *) nvram->GEArea)) < nvram->Header.GELength)
+ && (*cp != '\0'))
+ {
+ cp++;
+ }
+
+ /* Skip over any null characters. */
+ while (((cp - ((char *) nvram->GEArea)) < nvram->Header.GELength)
+ && (*cp == '\0'))
+ {
+ cp++;
+ }
+
+ if ((cp - ((char *) nvram->GEArea)) < nvram->Header.GELength) {
+ return cp;
+ } else {
+ return NULL;
+ }
+}
+
+
+
diff -u --recursive --new-file v2.2.7/linux/arch/ppc/kernel/prep_pci.c linux/arch/ppc/kernel/prep_pci.c
--- v2.2.7/linux/arch/ppc/kernel/prep_pci.c Tue Mar 23 14:35:46 1999
+++ linux/arch/ppc/kernel/prep_pci.c Tue May 11 08:24:32 1999


@@ -1,5 +1,5 @@
X /*

- * $Id: prep_pci.c,v 1.25 1999/03/03 15:09:45 cort Exp $
+ * $Id: prep_pci.c,v 1.33 1999/05/09 20:15:54 cort Exp $
X * PReP pci functions.
X * Originally by Gary Thomas
X * rewritten and updated by Cort Dougan (co...@cs.nmt.edu)
@@ -11,11 +11,19 @@
X #include <linux/pci.h>
X #include <linux/kernel.h>
X #include <linux/init.h>
+#include <linux/openpic.h>
X
X #include <asm/byteorder.h>
X #include <asm/io.h>
X #include <asm/ptrace.h>
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#include <asm/residual.h>
X #include <asm/processor.h>
+#include <asm/irq.h>


+#include <asm/machdep.h>
+
+#include "pci.h"
X

X #define MAX_DEVNR 22
X
@@ -27,6 +35,9 @@
X /* How is the 82378 PIRQ mapping setup? */
X unsigned char *Motherboard_routes;
X
+/* Used for Motorola to store system config register */
+static unsigned long *ProcInfo;
+
X /* Tables for known hardware */
X
X /* Motorola PowerStackII - Utah */
@@ -34,38 +45,39 @@
X {
X 0, /* Slot 0 - unused */
X 0, /* Slot 1 - unused */
- 4, /* Slot 2 - SCSI - NCR825A */
+ 5, /* Slot 2 - SCSI - NCR825A */
X 0, /* Slot 3 - unused */
X 1, /* Slot 4 - Ethernet - DEC2114x */
X 0, /* Slot 5 - unused */
- 2, /* Slot 6 - PCI Card slot #1 */
- 3, /* Slot 7 - PCI Card slot #2 */
- 4, /* Slot 8 - PCI Card slot #3 */
- 4, /* Slot 9 - PCI Bridge */
+ 3, /* Slot 6 - PCI Card slot #1 */
+ 4, /* Slot 7 - PCI Card slot #2 */
+ 5, /* Slot 8 - PCI Card slot #3 */
+ 5, /* Slot 9 - PCI Bridge */
X /* added here in case we ever support PCI bridges */
X /* Secondary PCI bus cards are at slot-9,6 & slot-9,7 */
X 0, /* Slot 10 - unused */
X 0, /* Slot 11 - unused */
- 4, /* Slot 12 - SCSI - NCR825A */
+ 5, /* Slot 12 - SCSI - NCR825A */
X 0, /* Slot 13 - unused */
- 2, /* Slot 14 - enet */
+ 3, /* Slot 14 - enet */
X 0, /* Slot 15 - unused */
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
+ 2, /* Slot 16 - unused */
+ 3, /* Slot 17 - unused */
+ 5, /* Slot 18 - unused */
+ 0, /* Slot 19 - unused */
+ 0, /* Slot 20 - unused */
+ 0, /* Slot 21 - unused */
+ 0, /* Slot 22 - unused */
X };
X
X static char Utah_pci_IRQ_routes[] __prepdata =
X {
X 0, /* Line 0 - Unused */
X 9, /* Line 1 */
- 11, /* Line 2 */
- 14, /* Line 3 */
- 15, /* Line 4 */
+ 10, /* Line 2 */
+ 11, /* Line 3 */
+ 14, /* Line 4 */
+ 15, /* Line 5 */
X };
X
X /* Motorola PowerStackII - Omaha */
@@ -125,9 +137,9 @@
X 0, /* Slot 13 - unused */
X 1, /* Slot 14 - Ethernet */
X 0, /* Slot 15 - unused */
- 1, /* Slot P7 */
- 2, /* Slot P6 */
- 3, /* Slot P5 */
+ 1, /* Slot P7 */
+ 2, /* Slot P6 */
+ 3, /* Slot P5 */
X };
X
X static char Blackhawk_pci_IRQ_routes[] __prepdata =
@@ -139,6 +151,122 @@
X 15 /* Line 4 */
X };
X
+/* Motorola Mesquite */
+static char Mesquite_pci_IRQ_map[23] __prepdata =
+{
+ 0, /* Slot 0 - unused */
+ 0, /* Slot 1 - unused */
+ 0, /* Slot 2 - unused */
+ 0, /* Slot 3 - unused */
+ 0, /* Slot 4 - unused */
+ 0, /* Slot 5 - unused */
+ 0, /* Slot 6 - unused */
+ 0, /* Slot 7 - unused */
+ 0, /* Slot 8 - unused */
+ 0, /* Slot 9 - unused */
+ 0, /* Slot 10 - unxued */
+ 0, /* Slot 11 - unused */
+ 0, /* Slot 12 - unused */
+ 0, /* Slot 13 - unused */
+ 2, /* Slot 14 - Ethernet */
+ 0, /* Slot 15 - unused */
+ 3, /* Slot 16 - PMC */
+ 0, /* Slot 17 - unused */
+ 0, /* Slot 18 - unused */
+ 0, /* Slot 19 - unused */
+ 0, /* Slot 20 - unused */
+ 0, /* Slot 21 - unused */
+ 0, /* Slot 22 - unused */
+};
+
+/* Motorola Sitka */
+static char Sitka_pci_IRQ_map[21] __prepdata =
+{
+ 0, /* Slot 0 - unused */
+ 0, /* Slot 1 - unused */
+ 0, /* Slot 2 - unused */
+ 0, /* Slot 3 - unused */
+ 0, /* Slot 4 - unused */
+ 0, /* Slot 5 - unused */
+ 0, /* Slot 6 - unused */
+ 0, /* Slot 7 - unused */
+ 0, /* Slot 8 - unused */
+ 0, /* Slot 9 - unused */
+ 0, /* Slot 10 - unxued */
+ 0, /* Slot 11 - unused */
+ 0, /* Slot 12 - unused */
+ 0, /* Slot 13 - unused */
+ 2, /* Slot 14 - Ethernet */
+ 0, /* Slot 15 - unused */
+ 9, /* Slot 16 - PMC 1 */
+ 12, /* Slot 17 - PMC 2 */
+ 0, /* Slot 18 - unused */
+ 0, /* Slot 19 - unused */
+ 4, /* Slot 20 - NT P2P bridge */
+};
+
+/* Motorola MTX */
+static char MTX_pci_IRQ_map[23] __prepdata =
+{
+ 0, /* Slot 0 - unused */
+ 0, /* Slot 1 - unused */
+ 0, /* Slot 2 - unused */
+ 0, /* Slot 3 - unused */
+ 0, /* Slot 4 - unused */
+ 0, /* Slot 5 - unused */
+ 0, /* Slot 6 - unused */
+ 0, /* Slot 7 - unused */
+ 0, /* Slot 8 - unused */
+ 0, /* Slot 9 - unused */
+ 0, /* Slot 10 - unused */
+ 0, /* Slot 11 - unused */
+ 3, /* Slot 12 - SCSI */
+ 0, /* Slot 13 - unused */
+ 2, /* Slot 14 - Ethernet */
+ 0, /* Slot 15 - unused */
+ 9, /* Slot 16 - PCI/PMC slot 1 */
+ 10, /* Slot 17 - PCI/PMC slot 2 */
+ 11, /* Slot 18 - PCI slot 3 */
+ 0, /* Slot 19 - unused */
+ 0, /* Slot 20 - unused */
+ 0, /* Slot 21 - unused */
+ 0, /* Slot 22 - unused */
+};
+
+/* Motorola MTX Plus */
+/* Secondary bus interrupt routing is not supported yet */
+static char MTXplus_pci_IRQ_map[23] __prepdata =
+{
+ 0, /* Slot 0 - unused */
+ 0, /* Slot 1 - unused */
+ 0, /* Slot 2 - unused */
+ 0, /* Slot 3 - unused */
+ 0, /* Slot 4 - unused */
+ 0, /* Slot 5 - unused */
+ 0, /* Slot 6 - unused */
+ 0, /* Slot 7 - unused */
+ 0, /* Slot 8 - unused */
+ 0, /* Slot 9 - unused */
+ 0, /* Slot 10 - unused */
+ 0, /* Slot 11 - unused */
+ 3, /* Slot 12 - SCSI */
+ 0, /* Slot 13 - unused */
+ 2, /* Slot 14 - Ethernet 1 */
+ 0, /* Slot 15 - unused */
+ 9, /* Slot 16 - PCI slot 1P */
+ 10, /* Slot 17 - PCI slot 2P */
+ 11, /* Slot 18 - PCI slot 3P */
+ 10, /* Slot 19 - Ethernet 2 */


SHAR_EOF
true || echo 'restore of patch-2.2.8 failed'
fi

echo 'End of part 10'
echo 'File patch-2.2.8 is continued in part 11'
echo 11 > _shar_seq_.tmp

Thomas...@ciw.uni-karlsruhe.de

unread,
May 12, 1999, 3:00:00 AM5/12/99
to
Archive-name: v2.2/patch-2.2.8/part11

#!/bin/sh
# this is part 11 of a 33 - part archive


# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.8 continued
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 11; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.8'
else
echo 'x - continuing with patch-2.2.8'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.8' &&

+ 0, /* Slot 20 - P2P Bridge */


+ 0, /* Slot 21 - unused */
+ 0, /* Slot 22 - unused */
+};
+

+static char Raven_pci_IRQ_routes[] __prepdata =
+{
+ 0, /* This is a dummy structure */
+};
+
X /* Motorola MVME16xx */
X static char Genesis_pci_IRQ_map[16] __prepdata =
X {
@@ -169,8 +297,35 @@


X 15 /* Line 4 */
X };
X

+static char Genesis2_pci_IRQ_map[23] __prepdata =


+{
+ 0, /* Slot 0 - unused */
+ 0, /* Slot 1 - unused */
+ 0, /* Slot 2 - unused */
+ 0, /* Slot 3 - unused */
+ 0, /* Slot 4 - unused */
+ 0, /* Slot 5 - unused */
+ 0, /* Slot 6 - unused */
+ 0, /* Slot 7 - unused */
+ 0, /* Slot 8 - unused */
+ 0, /* Slot 9 - unused */

+ 0, /* Slot 10 - Ethernet */
+ 0, /* Slot 11 - Universe PCI - VME Bridge */
+ 3, /* Slot 12 - unused */


+ 0, /* Slot 13 - unused */

+ 2, /* Slot 14 - SCSI */
+ 0, /* Slot 15 - graphics on 3600 */
+ 9, /* Slot 16 - PMC */
+ 12, /* Slot 17 - pci */
+ 11, /* Slot 18 - pci */
+ 10, /* Slot 19 - pci */
+ 0, /* Slot 20 - pci */


+ 0, /* Slot 21 - unused */
+ 0, /* Slot 22 - unused */
+};
+

X /* Motorola Series-E */
-static char Comet_pci_IRQ_map[16] __prepdata =
+static char Comet_pci_IRQ_map[23] __prepdata =
X {


X 0, /* Slot 0 - unused */
X 0, /* Slot 1 - unused */

@@ -188,6 +343,13 @@


X 0, /* Slot 13 - unused */
X 1, /* Slot 14 - Ethernet */
X 0, /* Slot 15 - unused */

+ 1, /* Slot 16 - PCI slot 1 */
+ 2, /* Slot 17 - PCI slot 2 */
+ 3, /* Slot 18 - PCI slot 3 */
+ 4, /* Slot 19 - PCI bridge */
+ 0,
+ 0,
+ 0,
X };
X
X static char Comet_pci_IRQ_routes[] __prepdata =
@@ -199,6 +361,43 @@


X 15 /* Line 4 */
X };
X

+/* Motorola Series-EX */
+static char Comet2_pci_IRQ_map[23] __prepdata =


+{
+ 0, /* Slot 0 - unused */
+ 0, /* Slot 1 - unused */

+ 3, /* Slot 2 - SCSI - NCR825A */


+ 0, /* Slot 3 - unused */

+ 1, /* Slot 4 - Ethernet - DEC2104X */


+ 0, /* Slot 5 - unused */

+ 1, /* Slot 6 - PCI slot 1 */
+ 2, /* Slot 7 - PCI slot 2 */
+ 3, /* Slot 8 - PCI slot 3 */
+ 4, /* Slot 9 - PCI bridge */


+ 0, /* Slot 10 - unused */
+ 0, /* Slot 11 - unused */

+ 3, /* Slot 12 - SCSI - NCR825A */


+ 0, /* Slot 13 - unused */

+ 1, /* Slot 14 - Ethernet - DEC2104X */


+ 0, /* Slot 15 - unused */

+ 1, /* Slot 16 - PCI slot 1 */
+ 2, /* Slot 17 - PCI slot 2 */
+ 3, /* Slot 18 - PCI slot 3 */
+ 4, /* Slot 19 - PCI bridge */
+ 0,
+ 0,
+ 0,
+};
+
+static char Comet2_pci_IRQ_routes[] __prepdata =
+{
+ 0, /* Line 0 - Unused */
+ 10, /* Line 1 */
+ 11, /* Line 2 */
+ 14, /* Line 3 */
+ 15, /* Line 4 */
+};
+
X /*
X * ibm 830 (and 850?).
X * This is actually based on the Carolina motherboard
@@ -328,106 +527,24 @@
X #define ELCRM_INT7_LVL 0x80
X #define ELCRM_INT5_LVL 0x20
X
-/*
- * Mechanism 1 configuration space access as defined in the PCI spec.
- */
-#define CFG_ADDR (volatile u_int *)0x80000cf8
-#define CFG_DATA 0x80000cfc
-
-#define CFG_DEV_ADDR(b, d, o) (0x80000000 | \
- ((b) << 16) | \
- ((d) << 8) | \
- ((o) & ~3))
-
-unsigned char max_bus=255;
-
-int mech1_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn,


- unsigned char offset, unsigned char *val)

-{
- *val = 0xff;
- if (bus > max_bus)
- return PCIBIOS_DEVICE_NOT_FOUND;
- out_le32(CFG_ADDR, CFG_DEV_ADDR(bus, dev_fn, offset));
- *val = in_8((unsigned char *)CFG_DATA + (offset & 3));


- return PCIBIOS_SUCCESSFUL;
-}
-

-int mech1_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn,


- unsigned char offset, unsigned short *val)

-{
- *val = 0xffff;
- if (bus > max_bus)
- return PCIBIOS_DEVICE_NOT_FOUND;
- if ((offset & 1) != 0)
- return PCIBIOS_BAD_REGISTER_NUMBER;
- out_le32(CFG_ADDR, CFG_DEV_ADDR(bus, dev_fn, offset));
- *val = in_le16((volatile unsigned short *)(CFG_DATA + (offset&3)));


- return PCIBIOS_SUCCESSFUL;
-}
-

-int mech1_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn,


- unsigned char offset, unsigned int *val)

-{
- *val = 0xffffffff;
- if (bus > max_bus)
- return PCIBIOS_DEVICE_NOT_FOUND;
- if ((offset & 3) != 0)
- return PCIBIOS_BAD_REGISTER_NUMBER;
- out_le32(CFG_ADDR, CFG_DEV_ADDR(bus, dev_fn, offset));
- *val = in_le32((volatile unsigned int *)CFG_DATA);


- return PCIBIOS_SUCCESSFUL;
-}
-

-int mech1_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn,


- unsigned char offset, unsigned char val)

-{
- if (bus > max_bus)
- return PCIBIOS_DEVICE_NOT_FOUND;
- out_le32(CFG_ADDR, CFG_DEV_ADDR(bus, dev_fn, offset));
- out_8((unsigned char *)CFG_DATA + (offset & 3), val);


- return PCIBIOS_SUCCESSFUL;
-}
-

-int mech1_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn,


- unsigned char offset, unsigned short val)

-{
- if (bus > max_bus)
- return PCIBIOS_DEVICE_NOT_FOUND;
- if ((offset & 1) != 0)
- return PCIBIOS_BAD_REGISTER_NUMBER;
- out_le32(CFG_ADDR, CFG_DEV_ADDR(bus, dev_fn, offset));
- out_le16((volatile unsigned short *)(CFG_DATA + (offset&3)), val);


- return PCIBIOS_SUCCESSFUL;
-}
-

-int mech1_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,


- unsigned char offset, unsigned int val)

-{
- if (bus > max_bus)
- return PCIBIOS_DEVICE_NOT_FOUND;
- if ((offset & 1) != 0)
- return PCIBIOS_BAD_REGISTER_NUMBER;
- out_le32(CFG_ADDR, CFG_DEV_ADDR(bus, dev_fn, offset));
- out_le32((volatile unsigned int *)CFG_DATA, val);
- return PCIBIOS_SUCCESSFUL;
-}
+#define CFGPTR(dev) (0x80800000 | (1<<(dev>>3)) | ((dev&7)<<8) | offset)
+#define DEVNO(dev) (dev>>3)
X
X __prep
X int
X prep_pcibios_read_config_dword (unsigned char bus,
X unsigned char dev, unsigned char offset, unsigned int *val)
X {
- unsigned long _val;
+ unsigned long _val;
X unsigned long *ptr;
- dev >>= 3;
-
- if ((bus != 0) || (dev > MAX_DEVNR))
- {
+
+ if ((bus != 0) || (DEVNO(dev) > MAX_DEVNR))
+ {
X *val = 0xFFFFFFFF;
- return PCIBIOS_DEVICE_NOT_FOUND;
- } else
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ } else
X {
- ptr = (unsigned long *)(0x80800000 | (1<<dev) | offset);
+ ptr = (unsigned long *)CFGPTR(dev);
X _val = le32_to_cpu(*ptr);
X }
X *val = _val;
@@ -439,16 +556,16 @@
X prep_pcibios_read_config_word (unsigned char bus,
X unsigned char dev, unsigned char offset, unsigned short *val)
X {
- unsigned short _val;
+ unsigned short _val;
X unsigned short *ptr;
- dev >>= 3;
- if ((bus != 0) || (dev > MAX_DEVNR))
- {
- *val = (unsigned short)0xFFFFFFFF;
- return PCIBIOS_DEVICE_NOT_FOUND;
- } else
+
+ if ((bus != 0) || (DEVNO(dev) > MAX_DEVNR))
+ {
+ *val = 0xFFFF;
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ } else
X {
- ptr = (unsigned short *)(0x80800000 | (1<<dev) | offset);
+ ptr = (unsigned short *)CFGPTR(dev);
X _val = le16_to_cpu(*ptr);
X }
X *val = _val;
@@ -460,16 +577,16 @@
X prep_pcibios_read_config_byte (unsigned char bus,
X unsigned char dev, unsigned char offset, unsigned char *val)
X {
- unsigned char _val;
- volatile unsigned char *ptr;
- dev >>= 3;
- if ((bus != 0) || (dev > MAX_DEVNR))
- {
- *(unsigned long *)val = (unsigned long) 0xFFFFFFFF;
- return PCIBIOS_DEVICE_NOT_FOUND;
- } else
+ unsigned char _val;
+ unsigned char *ptr;
+
+ if ((bus != 0) || (DEVNO(dev) > MAX_DEVNR))
+ {
+ *val = 0xFF;
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ } else
X {
- ptr = (unsigned char *)(0x80800000 | (1<<dev) | (offset ^ 1));
+ ptr = (unsigned char *)CFGPTR(dev);
X _val = *ptr;
X }
X *val = _val;
@@ -483,14 +600,14 @@
X {
X unsigned long _val;
X unsigned long *ptr;
- dev >>= 3;
+
X _val = le32_to_cpu(val);
- if ((bus != 0) || (dev > MAX_DEVNR))
+ if ((bus != 0) || (DEVNO(dev) > MAX_DEVNR))
X {
X return PCIBIOS_DEVICE_NOT_FOUND;
X } else
X {
- ptr = (unsigned long *)(0x80800000 | (1<<dev) | offset);
+ ptr = (unsigned long *)CFGPTR(dev);
X *ptr = _val;
X }
X return PCIBIOS_SUCCESSFUL;
@@ -503,14 +620,14 @@
X {
X unsigned short _val;
X unsigned short *ptr;
- dev >>= 3;
+
X _val = le16_to_cpu(val);
- if ((bus != 0) || (dev > MAX_DEVNR))
+ if ((bus != 0) || (DEVNO(dev) > MAX_DEVNR))
X {
X return PCIBIOS_DEVICE_NOT_FOUND;
X } else
X {
- ptr = (unsigned short *)(0x80800000 | (1<<dev) | offset);
+ ptr = (unsigned short *)CFGPTR(dev);
X *ptr = _val;
X }
X return PCIBIOS_SUCCESSFUL;
@@ -523,20 +640,151 @@
X {
X unsigned char _val;
X unsigned char *ptr;
- dev >>= 3;
+
X _val = val;
- if ((bus != 0) || (dev > MAX_DEVNR))
+ if ((bus != 0) || (DEVNO(dev) > MAX_DEVNR))
X {
X return PCIBIOS_DEVICE_NOT_FOUND;
X } else
X {
- ptr = (unsigned char *)(0x80800000 | (1<<dev) | (offset^1));
+ ptr = (unsigned char *)CFGPTR(dev);
X *ptr = _val;
X }
X return PCIBIOS_SUCCESSFUL;
X }
X
-__initfunc(unsigned long route_pci_interrupts(void))
+#define MOTOROLA_CPUTYPE_REG 0x800
+#define MOTOROLA_BASETYPE_REG 0x803
+#define MPIC_RAVEN_ID 0x48010000
+#define MPIC_HAWK_ID 0x48030000
+#define MOT_PROC2_BIT 0x800
+
+static u_char mvme2600_openpic_initsenses[] __initdata = {
+ 1, /* MVME2600_INT_SIO */
+ 0, /* MVME2600_INT_FALCN_ECC_ERR */
+ 1, /* MVME2600_INT_PCI_ETHERNET */
+ 1, /* MVME2600_INT_PCI_SCSI */
+ 1, /* MVME2600_INT_PCI_GRAPHICS */
+ 1, /* MVME2600_INT_PCI_VME0 */
+ 1, /* MVME2600_INT_PCI_VME1 */
+ 1, /* MVME2600_INT_PCI_VME2 */
+ 1, /* MVME2600_INT_PCI_VME3 */
+ 1, /* MVME2600_INT_PCI_INTA */
+ 1, /* MVME2600_INT_PCI_INTB */
+ 1, /* MVME2600_INT_PCI_INTC */
+ 1, /* MVME2600_INT_PCI_INTD */
+ 1, /* MVME2600_INT_LM_SIG0 */
+ 1, /* MVME2600_INT_LM_SIG1 */
+};
+
+#define MOT_RAVEN_PRESENT 0x1
+#define MOT_HAWK_PRESENT 0x2
+
+int prep_keybd_present = 1;
+int MotMPIC = 0;
+
+__initfunc(int raven_init(void))
+{
+ unsigned int devid;
+ unsigned int pci_membase;
+ unsigned char base_mod;
+
+ /* Check to see if the Raven chip exists. */
+ if ( _prep_type != _PREP_Motorola) {
+ OpenPIC = NULL;


+ return 0;
+ }
+

+ /* Check to see if this board is a type that might have a Raven. */
+ if ((inb(MOTOROLA_CPUTYPE_REG) & 0xF0) != 0xE0) {
+ OpenPIC = NULL;


+ return 0;
+ }
+

+ /* Check the first PCI device to see if it is a Raven. */
+ pcibios_read_config_dword(0, 0, PCI_VENDOR_ID, &devid);
+
+ switch (devid & 0xffff0000) {
+ case MPIC_RAVEN_ID:
+ MotMPIC = MOT_RAVEN_PRESENT;
+ break;
+ case MPIC_HAWK_ID:
+ MotMPIC = MOT_HAWK_PRESENT;
+ break;
+ default:
+ OpenPIC = NULL;


+ return 0;
+ }
+
+

+ /* Read the memory base register. */
+ pcibios_read_config_dword(0, 0, PCI_BASE_ADDRESS_1, &pci_membase);
+
+ if (pci_membase == 0) {
+ OpenPIC = NULL;


+ return 0;
+ }
+

+ /* Map the Raven MPIC registers to virtual memory. */
+ OpenPIC = (struct OpenPIC *)ioremap(pci_membase+0xC0000000, 0x22000);
+
+ OpenPIC_InitSenses = mvme2600_openpic_initsenses;
+ OpenPIC_NumInitSenses = sizeof(mvme2600_openpic_initsenses);
+
+ /* If raven is present on Motorola store the system config register
+ * for later use.
+ */
+ ProcInfo = (unsigned long *)ioremap(0xfef80400, 4);
+
+ /* This is a hack. If this is a 2300 or 2400 mot board then there is
+ * no keyboard controller and we have to indicate that.
+ */
+ base_mod = inb(MOTOROLA_BASETYPE_REG);
+ if ((MotMPIC == MOT_HAWK_PRESENT) || (base_mod == 0xF9) ||
+ (base_mod == 0xFA) || (base_mod == 0xE1))
+ prep_keybd_present = 0;
+
+ return 1;
+}
+
+struct mot_info {
+ int cpu_type; /* 0x100 mask assumes for Raven and Hawk boards that the level/edge are set */
+ /* 0x200 if this board has a Hawk chip. */
+ int base_type;
+ int max_cpu; /* ored with 0x80 if this board should be checked for multi CPU */
+ const char *name;
+ unsigned char *map;
+ unsigned char *routes;
+} mot_info[] = {
+ {0x300, 0x00, 0x00, "MVME 2400", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes},
+ {0x010, 0x00, 0x00, "Genesis", Genesis_pci_IRQ_map, Genesis_pci_IRQ_routes},
+ {0x020, 0x00, 0x00, "Powerstack (Series E)", Comet_pci_IRQ_map, Comet_pci_IRQ_routes},
+ {0x040, 0x00, 0x00, "Blackhawk (Powerstack)", Blackhawk_pci_IRQ_map, Blackhawk_pci_IRQ_routes},
+ {0x050, 0x00, 0x00, "Omaha (PowerStack II Pro3000)", Omaha_pci_IRQ_map, Omaha_pci_IRQ_routes},
+ {0x060, 0x00, 0x00, "Utah (Powerstack II Pro4000)", Utah_pci_IRQ_map, Utah_pci_IRQ_routes},
+ {0x0A0, 0x00, 0x00, "Powerstack (Series EX)", Comet2_pci_IRQ_map, Comet2_pci_IRQ_routes},
+ {0x1E0, 0xE0, 0x00, "Mesquite cPCI (MCP750)", Mesquite_pci_IRQ_map, Raven_pci_IRQ_routes},
+ {0x1E0, 0xE1, 0x00, "Sitka cPCI (MCPN750)", Sitka_pci_IRQ_map, Raven_pci_IRQ_routes},
+ {0x1E0, 0xE2, 0x00, "Mesquite cPCI (MCP750) w/ HAC", Mesquite_pci_IRQ_map, Raven_pci_IRQ_routes},
+ {0x1E0, 0xF6, 0x80, "MTX Plus", MTXplus_pci_IRQ_map, Raven_pci_IRQ_routes},
+ {0x1E0, 0xF6, 0x81, "Dual MTX Plus", MTXplus_pci_IRQ_map, Raven_pci_IRQ_routes},
+ {0x1E0, 0xF7, 0x80, "MTX wo/ Parallel Port", MTX_pci_IRQ_map, Raven_pci_IRQ_routes},
+ {0x1E0, 0xF7, 0x81, "Dual MTX wo/ Parallel Port", MTX_pci_IRQ_map, Raven_pci_IRQ_routes},
+ {0x1E0, 0xF8, 0x80, "MTX w/ Parallel Port", MTX_pci_IRQ_map, Raven_pci_IRQ_routes},
+ {0x1E0, 0xF8, 0x81, "Dual MTX w/ Parallel Port", MTX_pci_IRQ_map, Raven_pci_IRQ_routes},
+ {0x1E0, 0xF9, 0x00, "MVME 2300", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes},
+ {0x1E0, 0xFA, 0x00, "MVME 2300SC/2600", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes},
+ {0x1E0, 0xFB, 0x00, "MVME 2600 with MVME712M", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes},
+ {0x1E0, 0xFC, 0x00, "MVME 2600/2700 with MVME761", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes},
+ {0x1E0, 0xFD, 0x80, "MVME 3600 with MVME712M", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes},
+ {0x1E0, 0xFD, 0x81, "MVME 4600 with MVME712M", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes},
+ {0x1E0, 0xFE, 0x80, "MVME 3600 with MVME761", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes},
+ {0x1E0, 0xFE, 0x81, "MVME 4600 with MVME761", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes},
+ {0x1E0, 0xFF, 0x00, "MVME 1600-001 or 1600-011", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes},
+ {0x000, 0x00, 0x00, "", NULL, NULL}
+};
+
+__initfunc(unsigned long prep_route_pci_interrupts(void))
X {
X unsigned char *ibc_pirq = (unsigned char *)0x80800860;
X unsigned char *ibc_pcicon = (unsigned char *)0x80800840;
@@ -545,49 +793,66 @@
X if ( _prep_type == _PREP_Motorola)
X {
X unsigned short irq_mode;
+ unsigned char cpu_type;
+ unsigned char base_mod;
+ int entry;
+ int mot_entry = -1;
+
+ cpu_type = inb(MOTOROLA_CPUTYPE_REG) & 0xF0;
+ base_mod = inb(MOTOROLA_BASETYPE_REG);
+
+ for (entry = 0; mot_info[entry].cpu_type != 0; entry++) {
+ if (mot_info[entry].cpu_type & 0x200) { /* Check for Hawk chip */
+ if (!(MotMPIC & MOT_HAWK_PRESENT))
+ continue;
+ } else { /* Check non hawk boards */
+ if ((mot_info[entry].cpu_type & 0xff) != cpu_type)
+ continue;
+
+ if (mot_info[entry].base_type == 0) {
+ mot_entry = entry;
+ break;
+ }
X
- switch (inb(0x800) & 0xF0)
- {
- case 0x10: /* MVME16xx */
- Motherboard_map_name = "Genesis";
- Motherboard_map = Genesis_pci_IRQ_map;
- Motherboard_routes = Genesis_pci_IRQ_routes;
- break;
- case 0x20: /* Series E */
- Motherboard_map_name = "Powerstack (Series E)";
- Motherboard_map = Comet_pci_IRQ_map;
- Motherboard_routes = Comet_pci_IRQ_routes;
- break;
- case 0x50: /* PowerStackII Pro3000 */
- Motherboard_map_name = "Omaha (PowerStack II Pro3000)";
- Motherboard_map = Omaha_pci_IRQ_map;
- Motherboard_routes = Omaha_pci_IRQ_routes;
- break;
- case 0x60: /* PowerStackII Pro4000 */
- Motherboard_map_name = "Utah (Powerstack II Pro4000)";
- Motherboard_map = Utah_pci_IRQ_map;
- Motherboard_routes = Utah_pci_IRQ_routes;
- break;
- case 0xE0: /* MTX -- close enough?? to Genesis, so reuse it */
- Motherboard_map_name = "Motorola MTX";
- Motherboard_map = Genesis_pci_IRQ_map;
- Motherboard_routes = Genesis_pci_IRQ_routes;
- break;
- case 0x40: /* PowerStack */
- default: /* Can't hurt, can it? */
- Motherboard_map_name = "Blackhawk (Powerstack)";
- Motherboard_map = Blackhawk_pci_IRQ_map;
- Motherboard_routes = Blackhawk_pci_IRQ_routes;
- break;
+ if (mot_info[entry].base_type != base_mod)
+ continue;
+ }
+
+ if (!(mot_info[entry].max_cpu & 0x80)) {
+ mot_entry = entry;
+ break;
+ }
+
+ /* processor 1 not present and max processor zero indicated */
+ if ((*ProcInfo & MOT_PROC2_BIT) && !(mot_info[entry].max_cpu & 0x7f)) {
+ mot_entry = entry;
+ break;
+ }
+
+ /* processor 1 present and max processor zero indicated */
+ if (!(*ProcInfo & MOT_PROC2_BIT) && (mot_info[entry].max_cpu & 0x7f)) {
+ mot_entry = entry;
+ break;
+ }
X }
- /* AJF adjust level/edge control according to routes */
- irq_mode = 0;
- for (i = 1; i <= 4; i++)
- {
- irq_mode |= ( 1 << Motherboard_routes[i] );
+
+ if (mot_entry == -1) /* No particular cpu type found - assume Blackhawk */
+ mot_entry = 3;
+
+ Motherboard_map_name = (unsigned char *)mot_info[mot_entry].name;
+ Motherboard_map = mot_info[mot_entry].map;
+ Motherboard_routes = mot_info[mot_entry].routes;
+
+ if (!(mot_info[entry].cpu_type & 0x100)) {
+ /* AJF adjust level/edge control according to routes */
+ irq_mode = 0;
+ for (i = 1; i <= 4; i++)
+ {
+ irq_mode |= ( 1 << Motherboard_routes[i] );
+ }
+ outb( irq_mode & 0xff, 0x4d0 );
+ outb( (irq_mode >> 8) & 0xff, 0x4d1 );
X }
- outb( irq_mode & 0xff, 0x4d0 );
- outb( (irq_mode >> 8) & 0xff, 0x4d1 );
X } else if ( _prep_type == _PREP_IBM )
X {
X unsigned char pl_id;
@@ -705,5 +970,119 @@
X /* Enable PCI interrupts */
X *ibc_pcicon |= 0x20;
X return 0;
+}
+
+__initfunc(
+void
+prep_pcibios_fixup(void))


+{
+ struct pci_dev *dev;

+ extern unsigned char *Motherboard_map;
+ extern unsigned char *Motherboard_routes;
+ unsigned char i;
+


+ if ( _prep_type == _PREP_Radstone )

+ {
+ printk("Radstone boards require no PCI fixups\n");
+ return;
+ }
+
+ prep_route_pci_interrupts();
+
+ printk("Setting PCI interrupts for a \"%s\"\n", Motherboard_map_name);
+ if (OpenPIC) {
+ /* PCI interrupts are controlled by the OpenPIC */


+ for(dev=pci_devices; dev; dev=dev->next) {

+ if (dev->bus->number == 0) {
+ dev->irq = openpic_to_irq(Motherboard_map[PCI_SLOT(dev->devfn)]);
+ pcibios_write_config_byte(dev->bus->number, dev->devfn, PCI_INTERRUPT_PIN, dev->irq);
+ }
+ }
+ return;
+ }
+


+ for(dev=pci_devices; dev; dev=dev->next)
+ {
+ /*

+ * Use our old hard-coded kludge to figure out what
+ * irq this device uses. This is necessary on things
+ * without residual data. -- Cort
+ */
+ unsigned char d = PCI_SLOT(dev->devfn);
+ dev->irq = Motherboard_routes[Motherboard_map[d]];
+
+ for ( i = 0 ; i <= 5 ; i++ )
+ {
+ if ( dev->base_address[i] > 0x10000000 )
+ {
+ printk("Relocating PCI address %lx -> %lx\n",
+ dev->base_address[i],
+ (dev->base_address[i] & 0x00FFFFFF)
+ | 0x01000000);
+ dev->base_address[i] =
+ (dev->base_address[i] & 0x00FFFFFF) | 0x01000000;
+ pci_write_config_dword(dev,
+ PCI_BASE_ADDRESS_0+(i*0x4),
+ dev->base_address[i] );
+ }


+ }
+#if 0
+ /*

+ * If we have residual data and if it knows about this
+ * device ask it what the irq is.


+ * -- Cort
+ */

+ ppcd = residual_find_device_id( ~0L, dev->device,
+ -1,-1,-1, 0);
+#endif
+ }
+}
+
+decl_config_access_method(indirect);
+
+__initfunc(
+void
+prep_setup_pci_ptrs(void))
+{
+ PPC_DEVICE *hostbridge;
+
+ printk("PReP architecture\n");


+ if ( _prep_type == _PREP_Radstone )

+ {
+ pci_config_address = (unsigned *)0x80000cf8;
+ pci_config_data = (char *)0x80000cfc;
+ set_config_access_method(indirect);
+ }
+ else
+ {
+ hostbridge = residual_find_device(PROCESSORDEVICE, NULL,
+ BridgeController, PCIBridge, -1, 0);
+ if (hostbridge &&
+ hostbridge->DeviceId.Interface == PCIBridgeIndirect) {
+ PnP_TAG_PACKET * pkt;
+ set_config_access_method(indirect);
+ pkt = PnP_find_large_vendor_packet(
+ res->DevicePnPHeap+hostbridge->AllocatedOffset,
+ 3, 0);
+ if(pkt)
+ {
+#define p pkt->L4_Pack.L4_Data.L4_PPCPack
+ pci_config_address= (unsigned *)ld_le32((unsigned *) p.PPCData);
+ pci_config_data= (unsigned char *)ld_le32((unsigned *) (p.PPCData+8));
+ }
+ else
+ {
+ pci_config_address= (unsigned *) 0x80000cf8;
+ pci_config_data= (unsigned char *) 0x80000cfc;
+ }
+ }
+ else
+ {
+ set_config_access_method(prep);
+ }
+
+ }
+
+ ppc_md.pcibios_fixup = prep_pcibios_fixup;
X }
X
diff -u --recursive --new-file v2.2.7/linux/arch/ppc/kernel/prep_setup.c linux/arch/ppc/kernel/prep_setup.c
--- v2.2.7/linux/arch/ppc/kernel/prep_setup.c Tue Mar 23 14:35:46 1999
+++ linux/arch/ppc/kernel/prep_setup.c Tue May 11 08:24:32 1999
@@ -30,6 +30,9 @@
X #include <linux/blk.h>
X #include <linux/ioport.h>
X #include <linux/console.h>
+#include <linux/timex.h>
+#include <linux/pci.h>
+#include <linux/openpic.h>
X
X #include <asm/mmu.h>
X #include <asm/processor.h>
@@ -38,12 +41,57 @@
X #include <asm/pgtable.h>
X #include <asm/ide.h>
X #include <asm/cache.h>
+#include <asm/dma.h>
+#include <asm/machdep.h>
+#include <asm/mk48t59.h>
+#include <asm/prep_nvram.h>
+#include <asm/raven.h>
+


+
+#include "time.h"
+#include "local_irq.h"

+#include "i8259.h"
+#include "open_pic.h"
X
X #if defined(CONFIG_SOUND) || defined(CONFIG_SOUND_MODULE)
X #include <../drivers/sound/sound_config.h>
X #include <../drivers/sound/dev_table.h>
X #endif
X
+unsigned char ucSystemType;
+unsigned char ucBoardRev;
+unsigned char ucBoardRevMaj, ucBoardRevMin;
+
+extern unsigned long mc146818_get_rtc_time(void);
+extern int mc146818_set_rtc_time(unsigned long nowtime);
+extern unsigned long mk48t59_get_rtc_time(void);
+extern int mk48t59_set_rtc_time(unsigned long nowtime);
+
+extern unsigned char prep_nvram_read_val(int addr);
+extern void prep_nvram_write_val(int addr,
+ unsigned char val);
+extern unsigned char rs_nvram_read_val(int addr);
+extern void rs_nvram_write_val(int addr,


+ unsigned char val);
+

+extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode);
+extern int pckbd_getkeycode(unsigned int scancode);
+extern int pckbd_translate(unsigned char scancode, unsigned char *keycode,
+ char raw_mode);
+extern char pckbd_unexpected_up(unsigned char keycode);
+extern void pckbd_leds(unsigned char leds);
+extern void pckbd_init_hw(void);

+extern unsigned char pckbd_sysrq_xlate[128];
+

+extern void prep_setup_pci_ptrs(void);
+extern void chrp_do_IRQ(struct pt_regs *regs, int cpu, int isfake);
+extern char saved_command_line[256];
+
+int _prep_type;
+
+#define cached_21 (((char *)(ppc_cached_irq_mask))[3])
+#define cached_A1 (((char *)(ppc_cached_irq_mask))[2])
+


X /* for the mac fs */
X kdev_t boot_dev;

X /* used in nasty hack for sound - see prep_setup_arch() -- Cort */
@@ -60,6 +108,9 @@
X extern int rd_prompt; /* 1 = prompt for ramdisk, 0 = don't prompt */
X extern int rd_image_start; /* starting block # of image */
X #endif
+#ifdef CONFIG_VGA_CONSOLE
+unsigned long vgacon_remap_base;
+#endif
X
X __prep
X int
@@ -177,6 +228,13 @@
X outb(reg, SIO_CONFIG_RD);
X outb(reg, SIO_CONFIG_RD); /* Have to write twice to change! */
X
+ /*
+ * We need to set up the NvRAM access routines early as prep_init
+ * has yet to be called
+ */
+ ppc_md.nvram_read_val = prep_nvram_read_val;
+ ppc_md.nvram_write_val = prep_nvram_write_val;
+
X /* we should determine this according to what we find! -- Cort */
X switch ( _prep_type )
X {
@@ -210,9 +268,38 @@
X ucBoardRev=inb(0x854);
X ucBoardRevMaj=ucBoardRev>>5;
X ucBoardRevMin=ucBoardRev&0x1f;
+
+ /*
+ * Most Radstone boards have memory mapped NvRAM
+ */
+ if((ucSystemType==RS_SYS_TYPE_PPC1) && (ucBoardRevMaj<5))
+ {
+ ppc_md.nvram_read_val = prep_nvram_read_val;
+ ppc_md.nvram_write_val = prep_nvram_write_val;
+ }
+ else
+ {
+ ppc_md.nvram_read_val = rs_nvram_read_val;
+ ppc_md.nvram_write_val = rs_nvram_write_val;
+ }
X break;
X }
X
+ /* Read in NVRAM data */
+ init_prep_nvram();
+
+ /* if no bootargs, look in NVRAM */
+ if ( cmd_line[0] == '\0' ) {
+ char *bootargs;
+ bootargs = prep_nvram_get_var("bootargs");
+ if (bootargs != NULL) {
+ strcpy(cmd_line, bootargs);
+
+ /* again.. */
+ strcpy(saved_command_line, cmd_line);
+ }
+ }
+
X printk("Boot arguments: %s\n", cmd_line);
X
X #ifdef CONFIG_SOUND_CS4232
@@ -262,12 +349,349 @@
X request_region(0x80,0x10,"dma page reg");
X request_region(0xc0,0x20,"dma2");
X
+ raven_init();
+
X #ifdef CONFIG_VGA_CONSOLE
+ /* remap the VGA memory */
+ vgacon_remap_base = 0xf0000000;
+ /*vgacon_remap_base = ioremap(0xc0000000, 0xba000);*/
X conswitchp = &vga_con;
X #endif
X }
X
-__initfunc(void prep_ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq))
+/*
+ * Determine the decrementer frequency from the residual data
+ * This allows for a faster boot as we do not need to calibrate the
+ * decrementer against another clock. This is important for embedded systems.
+ */
+__initfunc(void prep_res_calibrate_decr(void))
+{
+ int freq, divisor;
+
+ freq = res->VitalProductData.ProcessorBusHz;
+ divisor = 4;


+ printk("time_init: decrementer frequency = %d/%d\n", freq, divisor);
+ decrementer_count = freq / HZ / divisor;
+ count_period_num = divisor;
+ count_period_den = freq / 1000000;

+}
+
+/*
+ * Uses the on-board timer to calibrate the on-chip decrementer register
+ * for prep systems. On the pmac the OF tells us what the frequency is
+ * but on prep we have to figure it out.


+ * -- Cort
+ */

+int calibrate_done = 0;
+volatile int *done_ptr = &calibrate_done;
+
+__initfunc(void
+prep_calibrate_decr_handler(int irq,
+ void *dev,
+ struct pt_regs *regs))
+{
+ unsigned long freq, divisor;
+ static unsigned long t1 = 0, t2 = 0;
+
+ if ( !t1 )
+ t1 = get_dec();
+ else if (!t2)
+ {
+ t2 = get_dec();
+ t2 = t1-t2; /* decr's in 1/HZ */
+ t2 = t2*HZ; /* # decrs in 1s - thus in Hz */
+ freq = t2 * 60; /* try to make freq/1e6 an integer */
+ divisor = 60;
+ printk("time_init: decrementer frequency = %lu/%lu (%luMHz)\n",
+ freq, divisor,t2>>20);


+ decrementer_count = freq / HZ / divisor;
+ count_period_num = divisor;
+ count_period_den = freq / 1000000;

+ *done_ptr = 1;
+ }
+}
+
+__initfunc(void prep_calibrate_decr(void))


+{
+ unsigned long flags;
+
+

+ save_flags(flags);
+
+#define TIMER0_COUNT 0x40
+#define TIMER_CONTROL 0x43
+ /* set timer to periodic mode */
+ outb_p(0x34,TIMER_CONTROL);/* binary, mode 2, LSB/MSB, ch 0 */
+ /* set the clock to ~100 Hz */
+ outb_p(LATCH & 0xff , TIMER0_COUNT); /* LSB */
+ outb(LATCH >> 8 , TIMER0_COUNT); /* MSB */
+
+ if (request_irq(0, prep_calibrate_decr_handler, 0, "timer", NULL) != 0)


+ panic("Could not allocate timer IRQ!");

+ __sti();
+ while ( ! *done_ptr ) /* nothing */; /* wait for calibrate */
+ restore_flags(flags);
+ free_irq( 0, NULL);
+}
+
+
+/* We use the NVRAM RTC to time a second to calibrate the decrementer. */
+__initfunc(void mk48t59_calibrate_decr(void))
+{
+ unsigned long freq, divisor;
+ unsigned long t1, t2;
+ unsigned char save_control;
+ long i;
+ unsigned char sec;
+
+
+ /* Make sure the time is not stopped. */
+ save_control = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLB);
+
+ ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA,
+ (save_control & (~MK48T59_RTC_CB_STOP)));
+
+ /* Now make sure the read bit is off so the value will change. */
+ save_control = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLA);
+ save_control &= ~MK48T59_RTC_CA_READ;
+ ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, save_control);
+
+
+ /* Read the seconds value to see when it changes. */
+ sec = ppc_md.nvram_read_val(MK48T59_RTC_SECONDS);
+ for (i = 0 ; i < 1000000 ; i++) { /* may take up to 1 second... */
+ if (ppc_md.nvram_read_val(MK48T59_RTC_SECONDS) != sec) {
+ break;
+ }
+ }
+ t1 = get_dec();
+
+ sec = ppc_md.nvram_read_val(MK48T59_RTC_SECONDS);
+ for (i = 0 ; i < 1000000 ; i++) { /* Should take up 1 second... */
+ if (ppc_md.nvram_read_val(MK48T59_RTC_SECONDS) != sec) {


+ break;
+ }
+ }
+

+ t2 = t1 - get_dec();
+
+ freq = t2 * 60; /* try to make freq/1e6 an integer */
+ divisor = 60;
+ printk("time_init: decrementer frequency = %lu/%lu (%luMHz)\n",
+ freq, divisor,t2>>20);


+ decrementer_count = freq / HZ / divisor;
+ count_period_num = divisor;
+ count_period_den = freq / 1000000;
+}
+

+void
+prep_restart(char *cmd)
+{
+ unsigned long i = 10000;
+
+
+ _disable_interrupts();
+
+ /* set exception prefix high - to the prom */
+ _nmask_and_or_msr(0, MSR_IP);
+
+ /* make sure bit 0 (reset) is a 0 */
+ outb( inb(0x92) & ~1L , 0x92 );
+ /* signal a reset to system control port A - soft reset */
+ outb( inb(0x92) | 1 , 0x92 );
+
+ while ( i != 0 ) i++;
+ panic("restart failed\n");
+}
+
+/*
+ * This function will restart a board regardless of port 92 functionality
+ */
+void
+prep_direct_restart(char *cmd)
+{
+ u32 jumpaddr=0xfff00100;
+ u32 defaultmsr=MSR_IP;
+
+ /*
+ * This will ALWAYS work regardless of port 92
+ * functionality
+ */
+ _disable_interrupts();
+
+ __asm__ __volatile__("\n\
+ mtspr 26, %1 /* SRR0 */
+ mtspr 27, %0 /* SRR1 */
+ rfi"
+ :
+ : "r" (defaultmsr), "r" (jumpaddr));
+ /*
+ * Not reached
+ */
+}
+
+void
+prep_halt(void)


+{
+ unsigned long flags;

+ _disable_interrupts();
+ /* set exception prefix high - to the prom */
+ save_flags( flags );
+ restore_flags( flags|MSR_IP );
+
+ /* make sure bit 0 (reset) is a 0 */
+ outb( inb(0x92) & ~1L , 0x92 );
+ /* signal a reset to system control port A - soft reset */
+ outb( inb(0x92) | 1 , 0x92 );
+
+ while ( 1 ) ;
+ /*
+ * Not reached
+ */
+}
+
+void
+prep_power_off(void)
+{
+ prep_halt();
+}
+
+int prep_setup_residual(char *buffer)


+{
+ int len = 0;
+

+
+ /* PREP's without residual data will give incorrect values here */
+ len += sprintf(len+buffer, "clock\t\t: ");
+ if ( res->ResidualLength )
+ len += sprintf(len+buffer, "%ldMHz\n",
+ (res->VitalProductData.ProcessorHz > 1024) ?
+ res->VitalProductData.ProcessorHz>>20 :
+ res->VitalProductData.ProcessorHz);
+ else
+ len += sprintf(len+buffer, "???\n");


+
+ return len;
+}
+

+u_int
+prep_irq_cannonicalize(u_int irq)
+{


+ if (irq == 2)
+ {

+ return 9;
+ }
+ else
+ {


+ return irq;
+ }
+}
+
+void

+prep_do_IRQ(struct pt_regs *regs, int cpu, int isfake)


+{
+ int irq;
+

+ if ( (irq = i8259_irq(0)) < 0 )
+ {
+ printk(KERN_DEBUG "Bogus interrupt from PC = %lx\n",
+ regs->nip);
+ ppc_spurious_interrupts++;
+ return;


+ }
+ ppc_irq_dispatch_handler( regs, irq );
+}
+

+__initfunc(void
+prep_init_IRQ(void))


+{
+ int i;
+

+ if (OpenPIC != NULL) {
+ for ( i = 16 ; i < 36 ; i++ )
+ irq_desc[i].ctl = &open_pic;
+ openpic_init(1);
+ }


+
+ for ( i = 0 ; i < 16 ; i++ )
+ irq_desc[i].ctl = &i8259_pic;
+ i8259_init();

+#ifdef __SMP__
+ request_irq(openpic_to_irq(OPENPIC_VEC_SPURIOUS), openpic_ipi_action,
+ 0, "IPI0", 0);


+#endif /* __SMP__ */
+}
+

+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+/*
+ * IDE stuff.
+ */
+void

+prep_ide_insw(ide_ioreg_t port, void *buf, int ns)
+{
+ _insw((unsigned short *)((port)+_IO_BASE), buf, ns);
+}
+
+void
+prep_ide_outsw(ide_ioreg_t port, void *buf, int ns)
+{
+ _outsw((unsigned short *)((port)+_IO_BASE), buf, ns);
+}
+
+int
+prep_ide_default_irq(ide_ioreg_t base)
+{
+ switch (base) {
+ case 0x1f0: return 13;
+ case 0x170: return 13;
+ case 0x1e8: return 11;
+ case 0x168: return 10;
+ default:


+ return 0;
+ }
+}
+

+ide_ioreg_t
+prep_ide_default_io_base(int index)
+{
+ switch (index) {
+ case 0: return 0x1f0;
+ case 1: return 0x170;
+ case 2: return 0x1e8;
+ case 3: return 0x168;
+ default:


+ return 0;
+ }
+}
+

+int
+prep_ide_check_region(ide_ioreg_t from, unsigned int extent)
+{


+ return check_region(from, extent);
+}
+
+void

+prep_ide_request_region(ide_ioreg_t from,


+ unsigned int extent,
+ const char *name)
+{

+ request_region(from, extent, name);
+}
+
+void

+prep_ide_release_region(ide_ioreg_t from,


+ unsigned int extent)
+{

+ release_region(from, extent);
+}
+
+void

+prep_ide_fix_driveid(struct hd_driveid *id)
+{
+}
+
+__initfunc(void
+prep_ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq))
X {
X ide_ioreg_t port = base;
X int i = 8;
@@ -277,6 +701,143 @@
X *p++ = base + 0x206;
X if (irq != NULL)
X *irq = 0;
+}
+#endif
+
+__initfunc(void
+prep_init(unsigned long r3, unsigned long r4, unsigned long r5,


+ unsigned long r6, unsigned long r7))
+{

+ /* make a copy of residual data */


+ if ( r3 )

+ {
+ memcpy((void *)res,(void *)(r3+KERNELBASE),
+ sizeof(RESIDUAL));
+ }
+
+ isa_io_base = PREP_ISA_IO_BASE;
+ isa_mem_base = PREP_ISA_MEM_BASE;
+ pci_dram_offset = PREP_PCI_DRAM_OFFSET;
+ ISA_DMA_THRESHOLD = 0x00ffffff;


+ DMA_MODE_READ = 0x44;
+ DMA_MODE_WRITE = 0x48;
+

+ /* figure out what kind of prep workstation we are */
+ if ( res->ResidualLength != 0 )
+ {
+ if ( !strncmp(res->VitalProductData.PrintableModel,"IBM",3) )
+ _prep_type = _PREP_IBM;
+ else if (!strncmp(res->VitalProductData.PrintableModel,
+ "Radstone",8))
+ {
+ extern char *Motherboard_map_name;
+
+ _prep_type = _PREP_Radstone;
+ Motherboard_map_name=
+ res->VitalProductData.PrintableModel;
+ }
+ else
+ _prep_type = _PREP_Motorola;
+ }
+ else /* assume motorola if no residual (netboot?) */
+ {
+ _prep_type = _PREP_Motorola;
+ }
+
+ prep_setup_pci_ptrs();


+
+#ifdef CONFIG_BLK_DEV_INITRD
+ /* take care of initrd if we have one */
+ if ( r4 )
+ {
+ initrd_start = r4 + KERNELBASE;
+ initrd_end = r5 + KERNELBASE;
+ }
+#endif /* CONFIG_BLK_DEV_INITRD */
+
+ /* take care of cmd line */

+ if ( r6 && (((char *) r6) != '\0'))
+ {


+ *(char *)(r7+KERNELBASE) = 0;
+ strcpy(cmd_line, (char *)(r6+KERNELBASE));
+ }
+

+ ppc_md.setup_arch = prep_setup_arch;
+ ppc_md.setup_residual = prep_setup_residual;
+ ppc_md.get_cpuinfo = prep_get_cpuinfo;
+ ppc_md.irq_cannonicalize = prep_irq_cannonicalize;
+ ppc_md.init_IRQ = prep_init_IRQ;
+ if ( !OpenPIC )
+ ppc_md.do_IRQ = prep_do_IRQ;
+ else
+ ppc_md.do_IRQ = chrp_do_IRQ;


+ ppc_md.init = NULL;
+

+ ppc_md.restart = prep_restart;
+ ppc_md.power_off = prep_power_off;
+ ppc_md.halt = prep_halt;


+
+ ppc_md.time_init = NULL;

+ if (_prep_type == _PREP_Radstone) {
+ /*
+ * We require a direct restart as port 92 does not work on
+ * all Radstone boards
+ */
+ ppc_md.restart = prep_direct_restart;
+ /*
+ * The RTC device used varies according to board type
+ */
+ if(((ucSystemType==RS_SYS_TYPE_PPC1) && (ucBoardRevMaj>=5)) ||
+ (ucSystemType==RS_SYS_TYPE_PPC1a))
+ {
+ ppc_md.set_rtc_time = mk48t59_set_rtc_time;
+ ppc_md.get_rtc_time = mk48t59_get_rtc_time;
+ }
+ else
+ {
+ ppc_md.set_rtc_time = mc146818_set_rtc_time;
+ ppc_md.get_rtc_time = mc146818_get_rtc_time;
+ }
+ /*
+ * Determine the decrementer rate from the residual data
+ */
+ ppc_md.calibrate_decr = prep_res_calibrate_decr;
+ }
+ else if (_prep_type == _PREP_IBM) {
+ ppc_md.set_rtc_time = mc146818_set_rtc_time;
+ ppc_md.get_rtc_time = mc146818_get_rtc_time;
+ ppc_md.calibrate_decr = prep_calibrate_decr;
+ }
+ else {
+ ppc_md.set_rtc_time = mk48t59_set_rtc_time;
+ ppc_md.get_rtc_time = mk48t59_get_rtc_time;
+ ppc_md.calibrate_decr = mk48t59_calibrate_decr;


+ }
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)

+ ppc_ide_md.insw = prep_ide_insw;
+ ppc_ide_md.outsw = prep_ide_outsw;
+ ppc_ide_md.default_irq = prep_ide_default_irq;
+ ppc_ide_md.default_io_base = prep_ide_default_io_base;
+ ppc_ide_md.check_region = prep_ide_check_region;
+ ppc_ide_md.request_region = prep_ide_request_region;
+ ppc_ide_md.release_region = prep_ide_release_region;
+ ppc_ide_md.fix_driveid = prep_ide_fix_driveid;
+ ppc_ide_md.ide_init_hwif = prep_ide_init_hwif_ports;
+#endif
+ ppc_ide_md.io_base = _IO_BASE;
+
+#ifdef CONFIG_VT


+ ppc_md.kbd_setkeycode = pckbd_setkeycode;
+ ppc_md.kbd_getkeycode = pckbd_getkeycode;
+ ppc_md.kbd_translate = pckbd_translate;
+ ppc_md.kbd_unexpected_up = pckbd_unexpected_up;
+ ppc_md.kbd_leds = pckbd_leds;
+ ppc_md.kbd_init_hw = pckbd_init_hw;
+#ifdef CONFIG_MAGIC_SYSRQ
+ ppc_md.kbd_sysrq_xlate = pckbd_sysrq_xlate;
+#endif

+#endif
X }
X
X #ifdef CONFIG_SOUND_MODULE
diff -u --recursive --new-file v2.2.7/linux/arch/ppc/kernel/prep_time.c linux/arch/ppc/kernel/prep_time.c
--- v2.2.7/linux/arch/ppc/kernel/prep_time.c Tue Mar 23 14:35:46 1999
+++ linux/arch/ppc/kernel/prep_time.c Thu Apr 29 12:39:01 1999
@@ -22,7 +22,9 @@
X #include <asm/segment.h>
X #include <asm/io.h>
X #include <asm/processor.h>
-#include <asm/nvram.h>
+#include <asm/machdep.h>
+#include <asm/prep_nvram.h>
+#include <asm/mk48t59.h>
X
X #include "time.h"
X
@@ -41,133 +43,44 @@
X * is setup at boot time to use the correct addresses.
X * -- Cort
X */
-/*
- * translate from mc146818 to m48t18 addresses
- */
-unsigned int clock_transl[] __prepdata = { MOTO_RTC_SECONDS,0 /* alarm */,
- MOTO_RTC_MINUTES,0 /* alarm */,
- MOTO_RTC_HOURS,0 /* alarm */, /* 4,5 */
- MOTO_RTC_DAY_OF_WEEK,
- MOTO_RTC_DAY_OF_MONTH,
- MOTO_RTC_MONTH,
- MOTO_RTC_YEAR, /* 9 */
- MOTO_RTC_CONTROLA, MOTO_RTC_CONTROLB /* 10,11 */
-};
-
-/*
- * The following struture is used to access the MK48T18
- */
-typedef volatile struct _MK48T18 {
- unsigned char ucNvRAM[0x3ff8]; /* NvRAM locations */
- unsigned char ucControl;
- unsigned char ucSecond; /* 0-59 */
- unsigned char ucMinute; /* 0-59 */
- unsigned char ucHour; /* 0-23 */
- unsigned char ucDay; /* 1-7 */
- unsigned char ucDate; /* 1-31 */
- unsigned char ucMonth; /* 1-12 */
- unsigned char ucYear; /* 0-99 */
-} MK48T18, *PMK48T18;
-
-/*
- * The control register contains a 5 bit calibration value plus sign
- * and read/write enable bits
- */
-#define MK48T18_CTRL_CAL_MASK 0x1f
-#define MK48T18_CTRL_CAL_SIGN 0x20
-#define MK48T18_CTRL_READ 0x40
-#define MK48T18_CTRL_WRITE 0x80
-/*
- * The STOP bit is the most significant bit of the seconds location
- */
-#define MK48T18_SEC_MASK 0x7f
-#define MK48T18_SEC_STOP 0x80
-/*
- * The day location also contains the frequency test bit which should
- * be zero for normal operation
- */
-#define MK48T18_DAY_MASK 0x07
-#define MK48T18_DAY_FT 0x40
-
-__prep
-int prep_cmos_clock_read(int addr)
-{
- if ( _prep_type == _PREP_IBM )
- return CMOS_READ(addr);
- else if ( _prep_type == _PREP_Motorola )
- {
- outb(clock_transl[addr]>>8, NVRAM_AS1);
- outb(clock_transl[addr], NVRAM_AS0);
- return (inb(NVRAM_DATA));
- }
- else if ( _prep_type == _PREP_Radstone )
- return CMOS_READ(addr);
-
- printk("Unknown machine in prep_cmos_clock_read()!\n");
- return -1;
-}
-
-__prep
-void prep_cmos_clock_write(unsigned long val, int addr)
-{
- if ( _prep_type == _PREP_IBM )
- {
- CMOS_WRITE(val,addr);
- return;
- }
- else if ( _prep_type == _PREP_Motorola )
- {
- outb(clock_transl[addr]>>8, NVRAM_AS1);
- outb(clock_transl[addr], NVRAM_AS0);
- outb(val,NVRAM_DATA);
- return;
- }
- else if ( _prep_type == _PREP_Radstone )
- {
- CMOS_WRITE(val,addr);
- return;
- }
-
- printk("Unknown machine in prep_cmos_clock_write()!\n");
-}
X
X /*
X * Set the hardware clock. -- Cort
X */
X __prep
-int prep_set_rtc_time(unsigned long nowtime)
+int mc146818_set_rtc_time(unsigned long nowtime)
X {
X unsigned char save_control, save_freq_select;
X struct rtc_time tm;
X
X to_tm(nowtime, &tm);
X
- save_control = prep_cmos_clock_read(RTC_CONTROL); /* tell the clock it's being set */
-
- prep_cmos_clock_write((save_control|RTC_SET), RTC_CONTROL);
-
- save_freq_select = prep_cmos_clock_read(RTC_FREQ_SELECT); /* stop and reset prescaler */
+ /* tell the clock it's being set */
+ save_control = CMOS_READ(RTC_CONTROL);
X
- prep_cmos_clock_write((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
-
- tm.tm_year -= 1900;
+ CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
+
+ /* stop and reset prescaler */
+ save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
+
+ CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
+
+ tm.tm_year = (tm.tm_year - 1900) % 100;
X if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
X BIN_TO_BCD(tm.tm_sec);
X BIN_TO_BCD(tm.tm_min);
X BIN_TO_BCD(tm.tm_hour);
X BIN_TO_BCD(tm.tm_mon);
- BIN_TO_BCD(tm.tm_wday);
X BIN_TO_BCD(tm.tm_mday);
X BIN_TO_BCD(tm.tm_year);
X }
- prep_cmos_clock_write(tm.tm_sec,RTC_SECONDS);
- prep_cmos_clock_write(tm.tm_min,RTC_MINUTES);
- prep_cmos_clock_write(tm.tm_hour,RTC_HOURS);
- prep_cmos_clock_write(tm.tm_mon,RTC_MONTH);
- prep_cmos_clock_write(tm.tm_wday+1,RTC_DAY_OF_WEEK);
- prep_cmos_clock_write(tm.tm_mday,RTC_DAY_OF_MONTH);
- prep_cmos_clock_write(tm.tm_year,RTC_YEAR);
-
+ CMOS_WRITE(tm.tm_sec, RTC_SECONDS);
+ CMOS_WRITE(tm.tm_min, RTC_MINUTES);
+ CMOS_WRITE(tm.tm_hour, RTC_HOURS);
+ CMOS_WRITE(tm.tm_mon, RTC_MONTH);
+ CMOS_WRITE(tm.tm_mday, RTC_DAY_OF_MONTH);
+ CMOS_WRITE(tm.tm_year, RTC_YEAR);
+
X /* The following flags have to be released exactly in this order,
X * otherwise the DS12887 (popular MC146818A clone with integrated
X * battery and quartz) will not reset the oscillator and will not
@@ -175,52 +88,14 @@
X * the Dallas Semiconductor data sheets, but who believes data
X * sheets anyway ... -- Markus Kuhn
X */
- prep_cmos_clock_write(save_control, RTC_CONTROL);
- prep_cmos_clock_write(save_freq_select, RTC_FREQ_SELECT);
+ CMOS_WRITE(save_control, RTC_CONTROL);
+ CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
X
- /*
- * Radstone Technology PPC1a boards use an MK48T18 device
- * as the "master" RTC but also have a DS1287 equivalent incorporated
- * into the PCI-ISA bridge device. The DS1287 is initialised by the boot
- * firmware to reflect the value held in the MK48T18 and thus the
- * time may be read from this device both here and in the rtc driver.
- * Whenever we set the time, however, if it is to be preserved across
- * boots we must also update the "master" RTC.
- */
- if((_prep_type==_PREP_Radstone) && (ucSystemType==RS_SYS_TYPE_PPC1a))
- {
- PMK48T18 pMk48t18=(PMK48T18)(_ISA_MEM_BASE+0x00800000);
-
- /*
- * Set the write enable bit
- */
- pMk48t18->ucControl|=MK48T18_CTRL_WRITE;
- eieio();
- /*
- * Update the clock
- */
- pMk48t18->ucSecond=tm.tm_sec;
- pMk48t18->ucMinute=tm.tm_min;
- pMk48t18->ucHour=tm.tm_hour;
- pMk48t18->ucMonth=tm.tm_mon;
- pMk48t18->ucDay=tm.tm_wday+1;
- pMk48t18->ucDate=tm.tm_mday;
- pMk48t18->ucYear=tm.tm_year;
-
- eieio();
- /*
- * Clear the write enable bit
- */
- pMk48t18->ucControl&=~MK48T18_CTRL_WRITE;
- }
-
- if ( (time_state == TIME_ERROR) || (time_state == TIME_BAD) )
- time_state = TIME_OK;


X return 0;
X }
X

X __prep
-unsigned long prep_get_rtc_time(void)
+unsigned long mc146818_get_rtc_time(void)
X {
X unsigned int year, mon, day, hour, min, sec;
X int i;
@@ -232,29 +107,123 @@
X */
X /* read RTC exactly on falling edge of update flag */
X for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */
- if (prep_cmos_clock_read(RTC_FREQ_SELECT) & RTC_UIP)
+ if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
X break;
X for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */
- if (!(prep_cmos_clock_read(RTC_FREQ_SELECT) & RTC_UIP))
+ if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
X break;
X do { /* Isn't this overkill ? UIP above should guarantee consistency */
- sec = prep_cmos_clock_read(RTC_SECONDS);
- min = prep_cmos_clock_read(RTC_MINUTES);
- hour = prep_cmos_clock_read(RTC_HOURS);
- day = prep_cmos_clock_read(RTC_DAY_OF_MONTH);
- mon = prep_cmos_clock_read(RTC_MONTH);
- year = prep_cmos_clock_read(RTC_YEAR);
- } while (sec != prep_cmos_clock_read(RTC_SECONDS));
- if (!(prep_cmos_clock_read(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
- {
- BCD_TO_BIN(sec);
- BCD_TO_BIN(min);
- BCD_TO_BIN(hour);
- BCD_TO_BIN(day);
- BCD_TO_BIN(mon);
- BCD_TO_BIN(year);
- }
+ sec = CMOS_READ(RTC_SECONDS);
+ min = CMOS_READ(RTC_MINUTES);
+ hour = CMOS_READ(RTC_HOURS);
+ day = CMOS_READ(RTC_DAY_OF_MONTH);
+ mon = CMOS_READ(RTC_MONTH);
+ year = CMOS_READ(RTC_YEAR);
+ } while (sec != CMOS_READ(RTC_SECONDS));
+ if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY)
+ || RTC_ALWAYS_BCD)
+ {
+ BCD_TO_BIN(sec);
+ BCD_TO_BIN(min);
+ BCD_TO_BIN(hour);
+ BCD_TO_BIN(day);
+ BCD_TO_BIN(mon);
+ BCD_TO_BIN(year);
+ }
X if ((year += 1900) < 1970)
X year += 100;
+ return mktime(year, mon, day, hour, min, sec);
+}
+
+__prep
+int mk48t59_set_rtc_time(unsigned long nowtime)
+{
+ unsigned char save_control;
+ struct rtc_time tm;
+
+
+ to_tm(nowtime, &tm);
+
+ /* tell the clock it's being written */
+ save_control = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLA);
+
+ ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA,
+ (save_control | MK48T59_RTC_CA_WRITE));
+
+ tm.tm_year = (tm.tm_year - 1900) % 100;
+ BIN_TO_BCD(tm.tm_sec);
+ BIN_TO_BCD(tm.tm_min);
+ BIN_TO_BCD(tm.tm_hour);
+ BIN_TO_BCD(tm.tm_mon);
+ BIN_TO_BCD(tm.tm_mday);
+ BIN_TO_BCD(tm.tm_year);
+
+ ppc_md.nvram_write_val(MK48T59_RTC_SECONDS, tm.tm_sec);
+ ppc_md.nvram_write_val(MK48T59_RTC_MINUTES, tm.tm_min);
+ ppc_md.nvram_write_val(MK48T59_RTC_HOURS, tm.tm_hour);
+ ppc_md.nvram_write_val(MK48T59_RTC_MONTH, tm.tm_mon);
+ ppc_md.nvram_write_val(MK48T59_RTC_DAY_OF_MONTH, tm.tm_mday);
+ ppc_md.nvram_write_val(MK48T59_RTC_YEAR, tm.tm_year);
+
+ /* Turn off the write bit. */
+ ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, save_control);


+
+ return 0;
+}
+

+__prep
+unsigned long mk48t59_get_rtc_time(void)
+{
+ unsigned char save_control;
+ unsigned int year, mon, day, hour, min, sec;
+ int i;
+
+ /* Make sure the time is not stopped. */
+ save_control = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLB);
+
+ ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA,
+ (save_control & (~MK48T59_RTC_CB_STOP)));
+
+ /* Now make sure the read bit is off so the value will change. */
+ save_control = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLA);
+ save_control &= ~MK48T59_RTC_CA_READ;
+ ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, save_control);
+
+ /* Read the seconds value to see when it changes. */
+ sec = ppc_md.nvram_read_val(MK48T59_RTC_SECONDS);
+
+ /* Wait until the seconds value changes, then read the value. */
+ for (i = 0 ; i < 1000000 ; i++) { /* may take up to 1 second... */
+ if (ppc_md.nvram_read_val(MK48T59_RTC_SECONDS) != sec) {


+ break;
+ }
+ }
+

+ /* Set the register to read the value. */
+ ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA,
+ (save_control | MK48T59_RTC_CA_READ));
+
+ sec = ppc_md.nvram_read_val(MK48T59_RTC_SECONDS);
+ min = ppc_md.nvram_read_val(MK48T59_RTC_MINUTES);
+ hour = ppc_md.nvram_read_val(MK48T59_RTC_HOURS);
+ day = ppc_md.nvram_read_val(MK48T59_RTC_DAY_OF_MONTH);
+ mon = ppc_md.nvram_read_val(MK48T59_RTC_MONTH);
+ year = ppc_md.nvram_read_val(MK48T59_RTC_YEAR);
+
+ /* Let the time values change again. */
+ ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, save_control);
+
+ BCD_TO_BIN(sec);
+ BCD_TO_BIN(min);
+ BCD_TO_BIN(hour);
+ BCD_TO_BIN(day);
+ BCD_TO_BIN(mon);
+ BCD_TO_BIN(year);
+
+ year = year + 1900;
+ if (year < 1970) {
+ year += 100;
+ }
+
X return mktime(year, mon, day, hour, min, sec);
X }
diff -u --recursive --new-file v2.2.7/linux/arch/ppc/kernel/process.c linux/arch/ppc/kernel/process.c
--- v2.2.7/linux/arch/ppc/kernel/process.c Tue Mar 23 14:35:46 1999
+++ linux/arch/ppc/kernel/process.c Tue May 11 08:24:32 1999


@@ -1,5 +1,5 @@
X /*

- * $Id: process.c,v 1.75 1999/02/12 07:06:29 cort Exp $
+ * $Id: process.c,v 1.83 1999/05/10 04:43:43 cort Exp $
X *
X * linux/arch/ppc/kernel/process.c
X *
@@ -43,10 +43,7 @@
X #include <asm/prom.h>
X
X int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpregs);
-void switch_to(struct task_struct *, struct task_struct *);
-
X extern unsigned long _get_SP(void);
-extern spinlock_t scheduler_lock;
X
X struct task_struct *last_task_used_math = NULL;
X static struct vm_area_struct init_mmap = INIT_MMAP;
@@ -77,17 +74,25 @@
X int
X dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpregs)
X {
-#ifdef __SMP__
- if ( regs->msr & MSR_FP )
- smp_giveup_fpu(current);
-#else
- if (last_task_used_math == current)
- giveup_fpu();
-#endif
+ if (regs->msr & MSR_FP)
+ giveup_fpu(current);
X memcpy(fpregs, &current->tss.fpr[0], sizeof(*fpregs));


X return 1;
X }
X

+void
+enable_kernel_fp(void)
+{
+#ifdef __SMP__
+ if (current->tss.regs && (current->tss.regs->msr & MSR_FP))
+ giveup_fpu(current);
+ else
+ giveup_fpu(NULL); /* just enables FP for kernel */
+#else
+ giveup_fpu(last_task_used_math);


+#endif /* __SMP__ */
+}
+

X /* check to make sure the kernel stack is healthy */
X int check_stack(struct task_struct *tsk)
X {
@@ -152,7 +157,8 @@
X }
X
X void
-switch_to(struct task_struct *prev, struct task_struct *new)
+_switch_to(struct task_struct *prev, struct task_struct *new,
+ struct task_struct **last)
X {
X struct thread_struct *new_tss, *old_tss;
X int s = _disable_interrupts();
@@ -162,10 +168,10 @@
X #endif
X
X #ifdef SHOW_TASK_SWITCHES
- printk("%s/%d -> %s/%d NIP %08lx cpu %d lock %x root %x/%x\n",
+ printk("%s/%d -> %s/%d NIP %08lx cpu %d root %x/%x\n",
X prev->comm,prev->pid,
X new->comm,new->pid,new->tss.regs->nip,new->processor,
- scheduler_lock.lock,new->fs->root,prev->fs->root);
+ new->fs->root,prev->fs->root);
X #endif
X #ifdef __SMP__
X /* avoid complexity of lazy save/restore of fpu
@@ -173,18 +179,19 @@
X * this task used the fpu during the last quantum.
X *
X * If it tries to use the fpu again, it'll trap and
- * reload its fp regs.
+ * reload its fp regs. So we don't have to do a restore
+ * every switch, just a save.
X * -- Cort
X */
- if ( prev->tss.regs->msr & MSR_FP )
- smp_giveup_fpu(prev);
+ if (prev->tss.regs && (prev->tss.regs->msr & MSR_FP))
+ giveup_fpu(prev);
X
X prev->last_processor = prev->processor;
X current_set[smp_processor_id()] = new;


X #endif /* __SMP__ */

X new_tss = &new->tss;
X old_tss = &current->tss;
- _switch(old_tss, new_tss, new->mm->context);
+ *last = _switch(old_tss, new_tss, new->mm->context);
X _enable_interrupts(s);
X }
X
@@ -237,7 +244,12 @@
X
X printk("Instruction DUMP:");
X for(i = -3; i < 6; i++)
- printk("%c%08lx%c",i?' ':'<',pc[i],i?' ':'>');
+ {
+ unsigned long p;
+ if (__get_user( p, &pc[i] ))
+ break;
+ printk("%c%08lx%c",i?' ':'<',p,i?' ':'>');
+ }
X printk("\n");
X }
X
@@ -265,8 +277,12 @@
X copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
X struct task_struct * p, struct pt_regs * regs)
X {
- struct pt_regs * childregs;
-
+ struct pt_regs * childregs, *kregs;
+#ifdef __SMP__
+ extern void ret_from_smpfork(void);
+#else
+ extern void ret_from_syscall(void);
+#endif
X /* Copy registers */
X childregs = ((struct pt_regs *)
X ((unsigned long)p + sizeof(union task_union)
@@ -275,8 +291,19 @@
X if ((childregs->msr & MSR_PR) == 0)
X childregs->gpr[2] = (unsigned long) p; /* `current' in new task */
X childregs->gpr[3] = 0; /* Result from fork() */
+ p->tss.regs = childregs;
X p->tss.ksp = (unsigned long) childregs - STACK_FRAME_OVERHEAD;
- p->tss.regs = childregs;
+ p->tss.ksp -= sizeof(struct pt_regs ) + STACK_FRAME_OVERHEAD;
+ kregs = (struct pt_regs *)(p->tss.ksp + STACK_FRAME_OVERHEAD);
+#ifdef __SMP__
+ kregs->nip = (unsigned long)ret_from_smpfork;
+#else
+ kregs->nip = (unsigned long)ret_from_syscall;
+#endif
+ kregs->msr = MSR_KERNEL;
+ kregs->gpr[1] = (unsigned long)childregs - STACK_FRAME_OVERHEAD;
+ kregs->gpr[2] = (unsigned long)p;
+
X if (usp >= (unsigned long) regs) {
X /* Stack is in kernel space - must adjust */
X childregs->gpr[1] = (unsigned long)(childregs + 1);
@@ -290,21 +317,14 @@
X * copy fpu info - assume lazy fpu switch now always
X * -- Cort
X */
-#ifdef __SMP__
- if ( regs->msr & MSR_FP )
- smp_giveup_fpu(current);
-#else
- if ( last_task_used_math == current )
- giveup_fpu();
-#endif
+ if (regs->msr & MSR_FP)
+ giveup_fpu(current);
X
X memcpy(&p->tss.fpr, &current->tss.fpr, sizeof(p->tss.fpr));
X p->tss.fpscr = current->tss.fpscr;
X childregs->msr &= ~MSR_FP;
X
X #ifdef __SMP__
- if ( (p->pid != 0) || !(clone_flags & CLONE_PID) )
- p->tss.smp_fork_ret = 1;
X p->last_processor = NO_PROC_ID;


X #endif /* __SMP__ */

X return 0;
@@ -371,11 +391,6 @@
X int res;
X lock_kernel();
X res = do_fork(clone_flags, regs->gpr[1], regs);
- /*
- * only parent returns here, child returns to either
- * syscall_ret_1() or kernel_thread()


- * -- Cort
- */

X #ifdef __SMP__
X /* When we clone the idle task we keep the same pid but
X * the return value of 0 for both causes problems.
@@ -395,7 +410,6 @@
X int res;
X
X res = do_fork(SIGCHLD, regs->gpr[1], regs);
- /* only parent returns here */
X #ifdef __SMP__
X /* When we clone the idle task we keep the same pid but
X * the return value of 0 for both causes problems.
@@ -424,13 +438,8 @@
X error = PTR_ERR(filename);
X if (IS_ERR(filename))
X goto out;
-#ifdef __SMP__
- if ( regs->msr & MSR_FP )
- smp_giveup_fpu(current);
-#else
- if ( last_task_used_math == current )
- giveup_fpu();
-#endif
+ if (regs->msr & MSR_FP)
+ giveup_fpu(current);
X error = do_execve(filename, (char **) a1, (char **) a2, regs);
X putname(filename);
X out:
diff -u --recursive --new-file v2.2.7/linux/arch/ppc/kernel/prom.c linux/arch/ppc/kernel/prom.c
--- v2.2.7/linux/arch/ppc/kernel/prom.c Tue Mar 23 14:35:46 1999
+++ linux/arch/ppc/kernel/prom.c Tue May 11 08:24:32 1999


@@ -1,5 +1,5 @@
X /*

- * $Id: prom.c,v 1.50 1999/03/16 10:40:34 cort Exp $
+ * $Id: prom.c,v 1.54 1999/05/10 04:43:46 cort Exp $
X *
X * Procedures for interfacing to the Open Firmware PROM on
X * Power Macintosh computers.
@@ -16,6 +16,7 @@
X #include <linux/string.h>
X #include <linux/init.h>
X #include <linux/version.h>
+#include <asm/spinlock.h>
X #include <asm/prom.h>
X #include <asm/page.h>
X #include <asm/processor.h>
@@ -263,9 +264,11 @@
X void
X prom_init(int r3, int r4, prom_entry pp)
X {
+#ifdef CONFIG_SMP
X int cpu = 0, i;
X phandle node;
X char type[16], *path;
+#endif
X unsigned long mem;
X ihandle prom_rtas;
X unsigned long offset = reloc_offset();
@@ -454,7 +457,7 @@
X * a holding pattern controlled by the kernel (not OF) before
X * we destroy the OF.
X *
- * This used a chunk of high memory, puts some holding pattern
+ * This uses a chunk of high memory, puts some holding pattern
X * code there and sends the other processors off to there until
X * smp_boot_cpus tells them to do something. We do that by using
X * physical address 0x0. The holding pattern checks that address
@@ -1141,7 +1144,7 @@
X if (cp == NULL)
X return 0;
X while (cplen > 0) {
- if (strcasecmp(cp, compat) == 0)
+ if (strncasecmp(cp, compat, strlen(compat)) == 0)
X return 1;
X l = strlen(cp) + 1;
X cp += l;
@@ -1277,6 +1280,8 @@
X }
X #endif
X
+spinlock_t rtas_lock = SPIN_LOCK_UNLOCKED;
+
X /* this can be called after setup -- Cort */
X __openfirmware
X int
@@ -1307,7 +1312,9 @@
X for (i = 0; i < nargs; ++i)
X u.words[i+3] = va_arg(list, unsigned long);
X va_end(list);
+ spin_lock(&rtas_lock);
X enter_rtas((void *)__pa(&u));
+ spin_unlock(&rtas_lock);
X if (nret > 1 && outputs != NULL)
X for (i = 0; i < nret-1; ++i)
X outputs[i] = u.words[i+nargs+4];
diff -u --recursive --new-file v2.2.7/linux/arch/ppc/kernel/ptrace.c linux/arch/ppc/kernel/ptrace.c
--- v2.2.7/linux/arch/ppc/kernel/ptrace.c Thu Dec 31 10:28:59 1998
+++ linux/arch/ppc/kernel/ptrace.c Thu Apr 29 12:39:01 1999
@@ -392,14 +392,8 @@
X tmp = get_reg(child, addr);
X }
X else if (addr >= PT_FPR0 && addr <= PT_FPSCR) {
-#ifdef __SMP__
- if (child->tss.regs->msr & MSR_FP )
- smp_giveup_fpu(child);
-#else
- /* only current can be last task to use math on SMP */
- if (last_task_used_math == child)
- giveup_fpu();
-#endif
+ if (child->tss.regs->msr & MSR_FP)
+ giveup_fpu(child);
X tmp = ((long *)child->tss.fpr)[addr - PT_FPR0];
X }
X else
@@ -433,13 +427,8 @@
X goto out;
X }
X if (addr >= PT_FPR0 && addr < PT_FPR0 + 64) {
-#ifndef __SMP__
- if (last_task_used_math == child)


SHAR_EOF
true || echo 'restore of patch-2.2.8 failed'
fi

echo 'End of part 11'
echo 'File patch-2.2.8 is continued in part 12'
echo 12 > _shar_seq_.tmp

Thomas...@ciw.uni-karlsruhe.de

unread,
May 12, 1999, 3:00:00 AM5/12/99
to
Archive-name: v2.2/patch-2.2.8/part12

#!/bin/sh
# this is part 12 of a 33 - part archive


# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.8 continued
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 12; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.8'
else
echo 'x - continuing with patch-2.2.8'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.8' &&

- giveup_fpu();
-#else

- if (child->tss.regs->msr & MSR_FP )
- smp_giveup_fpu(child);

-#endif
+ if (child->tss.regs->msr & MSR_FP)
+ giveup_fpu(child);

X ((long *)child->tss.fpr)[addr - PT_FPR0] = data;
X ret = 0;
X goto out;
diff -u --recursive --new-file v2.2.7/linux/arch/ppc/kernel/setup.c linux/arch/ppc/kernel/setup.c
--- v2.2.7/linux/arch/ppc/kernel/setup.c Tue Mar 23 14:35:46 1999
+++ linux/arch/ppc/kernel/setup.c Thu Apr 29 12:39:01 1999


@@ -1,5 +1,5 @@
X /*

- * $Id: setup.c,v 1.130 1999/03/11 01:45:15 cort Exp $
+ * $Id: setup.c,v 1.132 1999/03/24 00:32:19 cort Exp $
X * Common prep/pmac/chrp boot and setup code.
X */
X
@@ -30,31 +30,62 @@
X #include <asm/8xx_immap.h>
X #endif
X #include <asm/bootx.h>
+#include <asm/machdep.h>
+#include <asm/ide.h>
X
-/* APUS defs */
-extern unsigned long m68k_machtype;
-extern int parse_bootinfo(const struct bi_record *);
-extern char _end[];
-#ifdef CONFIG_APUS
-extern struct mem_info ramdisk;


-unsigned long isa_io_base;
-unsigned long isa_mem_base;
-unsigned long pci_dram_offset;

-#endif
-/* END APUS defs */
+extern void pmac_init(unsigned long r3,
+ unsigned long r4,
+ unsigned long r5,
+ unsigned long r6,
+ unsigned long r7);
+
+extern void chrp_init(unsigned long r3,
+ unsigned long r4,
+ unsigned long r5,
+ unsigned long r6,
+ unsigned long r7);
+
+extern void prep_init(unsigned long r3,
+ unsigned long r4,
+ unsigned long r5,
+ unsigned long r6,
+ unsigned long r7);
+
+extern void mbx_init(unsigned long r3,
+ unsigned long r4,
+ unsigned long r5,
+ unsigned long r6,
+ unsigned long r7);
+
+extern void apus_init(unsigned long r3,
+ unsigned long r4,
+ unsigned long r5,
+ unsigned long r6,
+ unsigned long r7);
X
X extern boot_infos_t *boot_infos;
X extern char cmd_line[512];
X char saved_command_line[256];
X unsigned char aux_device_present;
X
-#if !defined(CONFIG_MACH_SPECIFIC)
+struct ide_machdep_calls ppc_ide_md;
+
X unsigned long ISA_DMA_THRESHOLD;
X unsigned long DMA_MODE_READ, DMA_MODE_WRITE;
-int _machine;
-/* if we have openfirmware */
-unsigned long have_of;
-#endif /* ! CONFIG_MACH_SPECIFIC */
+
+/* Temporary hacks until machdep.h is fully done. */
+int _machine = 0;
+/* do we have OF? */
+int have_of = 0;
+int is_prep = 0;
+int is_chrp = 0;
+/* For MTX/MVME boards.. with Raven/Falcon Chipset
+ Real close to CHRP, but boot like PReP (via PPCbug)
+ There's probably a nicer way to do this.. --Troy */
+int is_powerplus = 0;
+
+struct machdep_calls ppc_md;
+
X
X /* copy of the residual data */
X #ifndef CONFIG_MBX
@@ -65,15 +96,6 @@
X
X RESIDUAL *res = (RESIDUAL *)&__res;
X
-int _prep_type;
-/*
- * This is used to identify the board type from a given PReP board
- * vendor. Board revision is also made available.
- */
-unsigned char ucSystemType;
-unsigned char ucBoardRev;
-unsigned char ucBoardRevMaj, ucBoardRevMin;
-
X /*
X * Perhaps we can put the pmac screen_info[] here
X * on pmac as well so we don't need the ifdef's.
@@ -122,164 +144,28 @@
X };
X #endif /* CONFIG_MBX */
X
-/* cmd is ignored for now... */
X void machine_restart(char *cmd)
X {
-#ifndef CONFIG_MBX
- unsigned long flags;
- struct adb_request req;
-
- switch(_machine)
- {
- case _MACH_Pmac:
- switch (adb_hardware) {
- case ADB_VIACUDA:
- cuda_request(&req, NULL, 2, CUDA_PACKET,
- CUDA_RESET_SYSTEM);
- for (;;)
- cuda_poll();
- break;
- case ADB_VIAPMU:
- pmu_restart();


- break;
- default:
- }

- break;
-
- case _MACH_chrp:
-#if 0 /* RTAS doesn't seem to work on Longtrail.
- For now, do it the same way as the PReP. */
- /*err = call_rtas("system-reboot", 0, 1, NULL);
- printk("RTAS system-reboot returned %d\n", err);
- for (;;);*/
-
- {
- extern unsigned int rtas_entry, rtas_data, rtas_size;
- unsigned long status, value;
- printk("rtas_ent`ry: %08x rtas_data: %08x rtas_size: %08x\n",
- rtas_entry,rtas_data,rtas_size);
- }
-#endif
- case _MACH_prep:
- _disable_interrupts();
- /* set exception prefix high - to the prom */
- save_flags( flags );
- restore_flags( flags|MSR_IP );
-
- /* make sure bit 0 (reset) is a 0 */
- outb( inb(0x92) & ~1L , 0x92 );
- /* signal a reset to system control port A - soft reset */
- outb( inb(0x92) | 1 , 0x92 );
-
- while ( 1 ) ;
- break;
- /*
- * Not reached
- */
- case _MACH_apus:
- cli();
-
- APUS_WRITE(APUS_REG_LOCK,
- REGLOCK_BLACKMAGICK1|REGLOCK_BLACKMAGICK2);
- APUS_WRITE(APUS_REG_LOCK,
- REGLOCK_BLACKMAGICK1|REGLOCK_BLACKMAGICK3);
- APUS_WRITE(APUS_REG_LOCK,
- REGLOCK_BLACKMAGICK2|REGLOCK_BLACKMAGICK3);
- APUS_WRITE(APUS_REG_SHADOW, REGSHADOW_SELFRESET);
- APUS_WRITE(APUS_REG_RESET, REGRESET_AMIGARESET);
- for(;;);


- break;
- }
-#else /* CONFIG_MBX */

- extern void __clear_msr_me(void);
- __volatile__ unsigned char dummy;
-
- cli();
- ((immap_t *)IMAP_ADDR)->im_clkrst.car_plprcr |= 0x00000080;
- __clear_msr_me();
- dummy = ((immap_t *)IMAP_ADDR)->im_clkrst.res[0];
-
- printk("Restart failed\n");
- while(1);
-#endif /* CONFIG_MBX */
+ ppc_md.restart(cmd);
X }
-
+
X void machine_power_off(void)
X {
-#ifndef CONFIG_MBX
- struct adb_request req;
-#if 0
- int err;
-#endif
-
- switch (_machine) {
- case _MACH_Pmac:
- switch (adb_hardware) {
- case ADB_VIACUDA:
- cuda_request(&req, NULL, 2, CUDA_PACKET,
- CUDA_POWERDOWN);
- for (;;)
- cuda_poll();
- break;
- case ADB_VIAPMU:
- pmu_shutdown();


- break;
- default:
- }

- break;
-
- case _MACH_chrp:
-#if 0 /* RTAS doesn't seem to work on Longtrail.
- For now, do it the same way as the PReP. */
- err = call_rtas("power-off", 2, 1, NULL, 0, 0);
- printk("RTAS system-reboot returned %d\n", err);
- for (;;);
-#endif
-
- case _MACH_prep:
- machine_restart(NULL);
- case _MACH_apus:
- for (;;);
- }
- for (;;);
-#else /* CONFIG_MBX */
- machine_halt();
-#endif /* CONFIG_MBX */
+ ppc_md.power_off();
X }
-
+
X void machine_halt(void)
X {
- if ( _machine == _MACH_Pmac )
- {
- machine_power_off();
- }
- else /* prep, chrp or apus */
- machine_restart(NULL);
+ ppc_md.halt();
X }
-
+
X #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
X void ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq)
X {
-#if !defined(CONFIG_MBX) && !defined(CONFIG_APUS)
- switch (_machine) {
-#if defined(CONFIG_BLK_DEV_IDE_PMAC)
- case _MACH_Pmac:
- pmac_ide_init_hwif_ports(p,base,irq);
- break;
-#endif
- case _MACH_chrp:
- chrp_ide_init_hwif_ports(p,base,irq);


- break;
- case _MACH_prep:

- prep_ide_init_hwif_ports(p,base,irq);
- break;
+ if (ppc_ide_md.ide_init_hwif != NULL) {
+ ppc_ide_md.ide_init_hwif(p, base, irq);
X }
-#endif
-#if defined(CONFIG_MBX)
- mbx_ide_init_hwif_ports(p,base,irq);
-#endif
X }
-EXPORT_SYMBOL(ide_init_hwif_ports);
X #endif
X
X unsigned long cpu_temp(void)
@@ -313,10 +199,6 @@
X
X int get_cpuinfo(char *buffer)
X {
- extern int pmac_get_cpuinfo(char *);
- extern int chrp_get_cpuinfo(char *);
- extern int prep_get_cpuinfo(char *);
- extern int apus_get_cpuinfo(char *);
X unsigned long len = 0;
X unsigned long bogosum = 0;
X unsigned long i;
@@ -380,7 +262,6 @@
X break;
X }
X
-#ifndef CONFIG_MBX
X /*
X * Assume here that all clock rates are the same in a
X * smp system. -- Cort
@@ -397,33 +278,11 @@
X len += sprintf(len+buffer, "clock\t\t: %dMHz\n",
X *fp / 1000000);
X }
-
- /* PREP's without residual data for some reason will give
- incorrect values here */
- if ( is_prep )
- {
- len += sprintf(len+buffer, "clock\t\t: ");
- if ( res->ResidualLength )
- len += sprintf(len+buffer, "%ldMHz\n",
- (res->VitalProductData.ProcessorHz > 1024) ?
- res->VitalProductData.ProcessorHz>>20 :
- res->VitalProductData.ProcessorHz);
- else
- len += sprintf(len+buffer, "???\n");


- }
-#else /* CONFIG_MBX */

+
+ if (ppc_md.setup_residual != NULL)
X {
- bd_t *bp;
- extern RESIDUAL *res;
-
- bp = (bd_t *)res;
-
- len += sprintf(len+buffer,"clock\t\t: %dMHz\n"
- "bus clock\t: %dMHz\n",
- bp->bi_intfreq /*/ 1000000*/,
- bp->bi_busfreq /*/ 1000000*/);
+ len += ppc_md.setup_residual(buffer + len);
X }
-#endif /* CONFIG_MBX */
X
X len += sprintf(len+buffer, "revision\t: %ld.%ld\n",
X (GET_PVR & 0xff00) >> 8, GET_PVR & 0xff);
@@ -438,8 +297,8 @@
X if ( i )
X len += sprintf(buffer+len, "\n");
X len += sprintf(buffer+len,"total bogomips\t: %lu.%02lu\n",
- (bogosum+2500)/500000,
- (bogosum+2500)/5000 % 100);
+ (bogosum+2500)/500000,
+ (bogosum+2500)/5000 % 100);


X #endif /* __SMP__ */
X

X /*
@@ -455,27 +314,14 @@
X zero_cache_hits,zero_cache_calls,
X /* : 1 below is so we don't div by zero */
X (zero_cache_hits*100) /
- ((zero_cache_calls)?zero_cache_calls:1));
+ ((zero_cache_calls)?zero_cache_calls:1));
X }
X
-#ifndef CONFIG_MBX
- switch (_machine)
+ if (ppc_md.get_cpuinfo != NULL)
X {
- case _MACH_Pmac:
- len += pmac_get_cpuinfo(buffer+len);


- break;
- case _MACH_prep:

- len += prep_get_cpuinfo(buffer+len);


- break;
- case _MACH_chrp:

- len += chrp_get_cpuinfo(buffer+len);
- break;
- case _MACH_apus:
- /* Not much point in printing m68k info when it is not
- used. */
- break;
+ len += ppc_md.get_cpuinfo(buffer+len);
X }
-#endif /* ndef CONFIG_MBX */
+


X return len;
X }
X

@@ -487,25 +333,22 @@
X identify_machine(unsigned long r3, unsigned long r4, unsigned long r5,
X unsigned long r6, unsigned long r7)
X {
- extern void setup_pci_ptrs(void);
X
X #ifdef __SMP__
X if ( first_cpu_booted ) return 0;


X #endif /* __SMP__ */
X

-#ifndef CONFIG_MBX
X #ifndef CONFIG_MACH_SPECIFIC
X /* boot loader will tell us if we're APUS */
X if ( r3 == 0x61707573 )
X {
X _machine = _MACH_apus;
- have_of = 0;
X r3 = 0;
X }
X /* prep boot loader tells us if we're prep or not */
X else if ( *(unsigned long *)(KERNELBASE) == (0xdeadc0de) ) {
X _machine = _MACH_prep;
- have_of = 0;
+ is_prep = 1;
X } else {
X char *model;
X
@@ -516,19 +359,49 @@
X /* ask the OF info if we're a chrp or pmac */
X model = get_property(find_path_device("/"), "device_type", NULL);
X if ( model && !strncmp("chrp",model,4) )
+ {
X _machine = _MACH_chrp;
+ is_chrp = 1;
+ }
X else
X {
X model = get_property(find_path_device("/"),
X "model", NULL);
X if ( model && !strncmp(model, "IBM", 3))
+ {
X _machine = _MACH_chrp;
+ is_chrp = 1;
+ }
X else
+ {
X _machine = _MACH_Pmac;
+ is_prep = 1;
+ }
X }
X
X }
-#endif /* CONFIG_MACH_SPECIFIC */
+#else /* CONFIG_MACH_SPECIFIC */
+
+#ifdef CONFIG_PREP
+ _machine = _MACH_prep;
+ is_prep = 1;
+#elif defined(CONFIG_CHRP)
+ _machine = _MACH_chrp;
+ is_chrp = 1;
+ have_of = 1;
+#elif defined(CONFIG_PMAC)
+ _machine = _MACH_Pmac;
+ have_of = 1;
+#elif defined(CONFIG_MBX)
+ _machine = _MACH_mbx;
+#elif defined(CONFIG_FADS)
+ _machine = _MACH_fads;
+#elif defined(CONFIG_APUS)
+ _machine = _MACH_apus;
+#else
+#error "Machine not defined correctly"
+#endif /* CONFIG_APUS */
+#endif /* CONFIG_MACH_SPECIFIC */
X
X if ( have_of )
X {
@@ -587,138 +460,31 @@
X cmd_line[sizeof(cmd_line) - 1] = 0;
X }
X
-
X switch (_machine)
X {
X case _MACH_Pmac:
- setup_pci_ptrs();
- /* isa_io_base gets set in pmac_find_bridges */
- isa_mem_base = PMAC_ISA_MEM_BASE;
- pci_dram_offset = PMAC_PCI_DRAM_OFFSET;
-#if !defined(CONFIG_MACH_SPECIFIC)
- ISA_DMA_THRESHOLD = ~0L;
- DMA_MODE_READ = 1;
- DMA_MODE_WRITE = 2;
-#endif /* ! CONFIG_MACH_SPECIFIC */
+ pmac_init(r3, r4, r5, r6, r7);
X break;
X case _MACH_prep:
- /* make a copy of residual data */
- if ( r3 )
- memcpy((void *)res,(void *)(r3+KERNELBASE),
- sizeof(RESIDUAL));
- isa_io_base = PREP_ISA_IO_BASE;
- isa_mem_base = PREP_ISA_MEM_BASE;
- pci_dram_offset = PREP_PCI_DRAM_OFFSET;
-#if !defined(CONFIG_MACH_SPECIFIC)
- ISA_DMA_THRESHOLD = 0x00ffffff;
- DMA_MODE_READ = 0x44;
- DMA_MODE_WRITE = 0x48;
-#endif /* ! CONFIG_MACH_SPECIFIC */
- /* figure out what kind of prep workstation we are */
- if ( res->ResidualLength != 0 )
- {
- if ( !strncmp(res->VitalProductData.PrintableModel,"IBM",3) )
- _prep_type = _PREP_IBM;
- else if (!strncmp(res->VitalProductData.PrintableModel,
- "Radstone",8))
- {
- extern char *Motherboard_map_name;
-
- _prep_type = _PREP_Radstone;
- Motherboard_map_name=
- res->VitalProductData.PrintableModel;
- }
- else
- _prep_type = _PREP_Motorola;
- }
- else /* assume motorola if no residual (netboot?) */
- _prep_type = _PREP_Motorola;
- setup_pci_ptrs();
-#ifdef CONFIG_BLK_DEV_INITRD
- /* take care of initrd if we have one */
- if ( r4 )
- {
- initrd_start = r4 + KERNELBASE;
- initrd_end = r5 + KERNELBASE;
- }
-#endif /* CONFIG_BLK_DEV_INITRD */
- /* take care of cmd line */
- if ( r6 )
- {
- *(char *)(r7+KERNELBASE) = 0;
- strcpy(cmd_line, (char *)(r6+KERNELBASE));
- }
+ prep_init(r3, r4, r5, r6, r7);
X break;
X case _MACH_chrp:
- setup_pci_ptrs();
-#ifdef CONFIG_BLK_DEV_INITRD
- /* take care of initrd if we have one */
- if ( r3 )
- {
- initrd_start = r3 + KERNELBASE;
- initrd_end = r3 + r4 + KERNELBASE;
- }
-#endif /* CONFIG_BLK_DEV_INITRD */
- /* pci_dram_offset/isa_io_base/isa_mem_base set by setup_pci_ptrs() */
-#if !defined(CONFIG_MACH_SPECIFIC)
- ISA_DMA_THRESHOLD = ~0L;
- DMA_MODE_READ = 0x44;
- DMA_MODE_WRITE = 0x48;
-#endif /* ! CONFIG_MACH_SPECIFIC */
+ chrp_init(r3, r4, r5, r6, r7);
X break;
-#ifdef CONFIG_APUS
+#ifdef CONFIG_APUS
X case _MACH_apus:
- /* Parse bootinfo. The bootinfo is located right after
- the kernel bss */
- parse_bootinfo((const struct bi_record *)&_end);
-#ifdef CONFIG_BLK_DEV_INITRD
- /* Take care of initrd if we have one. Use data from
- bootinfo to avoid the need to initialize PPC
- registers when kernel is booted via a PPC reset. */
- if ( ramdisk.addr ) {
- initrd_start = (unsigned long) __va(ramdisk.addr);
- initrd_end = (unsigned long)
- __va(ramdisk.size + ramdisk.addr);
- }
- /* Make sure code below is not executed. */
- r4 = 0;
- r6 = 0;
-#endif /* CONFIG_BLK_DEV_INITRD */
-#if !defined(CONFIG_MACH_SPECIFIC)
- ISA_DMA_THRESHOLD = 0x00ffffff;
-#endif /* ! CONFIG_MACH_SPECIFIC */
+ apus_init(r3, r4, r5, r6, r7);
X break;
X #endif
+#ifdef CONFIG_MBX
+ case _MACH_mbx:
+ mbx_init(r3, r4, r5, r6, r7);


+ break;
+#endif
X default:

X printk("Unknown machine type in identify_machine!\n");
X }
X

-#else /* CONFIG_MBX */
-

- if ( r3 )
- memcpy( (void *)res,(void *)(r3+KERNELBASE), sizeof(bd_t) );
-
-#ifdef CONFIG_PCI
- setup_pci_ptrs();
-#endif
-
-#ifdef CONFIG_BLK_DEV_INITRD
- /* take care of initrd if we have one */
- if ( r4 )
- {
- initrd_start = r4 + KERNELBASE;
- initrd_end = r5 + KERNELBASE;
- }
-#endif /* CONFIG_BLK_DEV_INITRD */
- /* take care of cmd line */
- if ( r6 )
- {
-
- *(char *)(r7+KERNELBASE) = 0;
- strcpy(cmd_line, (char *)(r6+KERNELBASE));


- }
-#endif /* CONFIG_MBX */

-
X /* Check for nobats option (used in mapin_ram). */
X if (strstr(cmd_line, "nobats")) {
X extern int __map_without_bats;
@@ -740,14 +506,17 @@
X }
X }
X
+__initfunc(void
+ ppc_init(void))
+{
+ if (ppc_md.init != NULL) {
+ ppc_md.init();
+ }
+}
+
X __initfunc(void setup_arch(char **cmdline_p,
- unsigned long * memory_start_p, unsigned long * memory_end_p))
+ unsigned long * memory_start_p, unsigned long * memory_end_p))
X {
- extern void pmac_setup_arch(unsigned long *, unsigned long *);
- extern void chrp_setup_arch(unsigned long *, unsigned long *);
- extern void prep_setup_arch(unsigned long *, unsigned long *);
- extern void mbx_setup_arch(unsigned long *, unsigned long *);
- extern void apus_setup_arch(unsigned long *, unsigned long *);
X extern int panic_timeout;
X extern char _etext[], _edata[];
X extern char *klimit;
@@ -776,27 +545,113 @@
X *memory_start_p = find_available_memory();
X *memory_end_p = (unsigned long) end_of_DRAM;
X
-#ifdef CONFIG_MBX
- mbx_setup_arch(memory_start_p,memory_end_p);
-#else /* CONFIG_MBX */
- switch (_machine) {
- case _MACH_Pmac:
- pmac_setup_arch(memory_start_p, memory_end_p);


- break;
- case _MACH_prep:

- prep_setup_arch(memory_start_p, memory_end_p);


- break;
- case _MACH_chrp:

- chrp_setup_arch(memory_start_p, memory_end_p);


- break;
-#ifdef CONFIG_APUS
- case _MACH_apus:

- m68k_machtype = MACH_AMIGA;
- apus_setup_arch(memory_start_p,memory_end_p);
- break;
-#endif
- default:
- printk("Unknown machine %d in setup_arch()\n", _machine);


- }
-#endif /* CONFIG_MBX */

+ ppc_md.setup_arch(memory_start_p, memory_end_p);
+}
+
+void ppc_generic_ide_fix_driveid(struct hd_driveid *id)
+{
+ int i;
+ unsigned short *stringcast;
+
+
+ id->config = __le16_to_cpu(id->config);
+ id->cyls = __le16_to_cpu(id->cyls);
+ id->reserved2 = __le16_to_cpu(id->reserved2);
+ id->heads = __le16_to_cpu(id->heads);
+ id->track_bytes = __le16_to_cpu(id->track_bytes);
+ id->sector_bytes = __le16_to_cpu(id->sector_bytes);
+ id->sectors = __le16_to_cpu(id->sectors);
+ id->vendor0 = __le16_to_cpu(id->vendor0);
+ id->vendor1 = __le16_to_cpu(id->vendor1);
+ id->vendor2 = __le16_to_cpu(id->vendor2);
+ stringcast = (unsigned short *)&id->serial_no[0];
+ for (i=0; i<(20/2); i++)
+ stringcast[i] = __le16_to_cpu(stringcast[i]);
+ id->buf_type = __le16_to_cpu(id->buf_type);
+ id->buf_size = __le16_to_cpu(id->buf_size);
+ id->ecc_bytes = __le16_to_cpu(id->ecc_bytes);
+ stringcast = (unsigned short *)&id->fw_rev[0];
+ for (i=0; i<(8/2); i++)
+ stringcast[i] = __le16_to_cpu(stringcast[i]);
+ stringcast = (unsigned short *)&id->model[0];
+ for (i=0; i<(40/2); i++)
+ stringcast[i] = __le16_to_cpu(stringcast[i]);
+ id->dword_io = __le16_to_cpu(id->dword_io);
+ id->reserved50 = __le16_to_cpu(id->reserved50);
+ id->field_valid = __le16_to_cpu(id->field_valid);
+ id->cur_cyls = __le16_to_cpu(id->cur_cyls);
+ id->cur_heads = __le16_to_cpu(id->cur_heads);
+ id->cur_sectors = __le16_to_cpu(id->cur_sectors);
+ id->cur_capacity0 = __le16_to_cpu(id->cur_capacity0);
+ id->cur_capacity1 = __le16_to_cpu(id->cur_capacity1);
+ id->lba_capacity = __le32_to_cpu(id->lba_capacity);
+ id->dma_1word = __le16_to_cpu(id->dma_1word);
+ id->dma_mword = __le16_to_cpu(id->dma_mword);
+ id->eide_pio_modes = __le16_to_cpu(id->eide_pio_modes);
+ id->eide_dma_min = __le16_to_cpu(id->eide_dma_min);
+ id->eide_dma_time = __le16_to_cpu(id->eide_dma_time);
+ id->eide_pio = __le16_to_cpu(id->eide_pio);
+ id->eide_pio_iordy = __le16_to_cpu(id->eide_pio_iordy);
+ id->word69 = __le16_to_cpu(id->word69);
+ id->word70 = __le16_to_cpu(id->word70);
+ id->word71 = __le16_to_cpu(id->word71);
+ id->word72 = __le16_to_cpu(id->word72);
+ id->word73 = __le16_to_cpu(id->word73);
+ id->word74 = __le16_to_cpu(id->word74);
+ id->word75 = __le16_to_cpu(id->word75);
+ id->word76 = __le16_to_cpu(id->word76);
+ id->word77 = __le16_to_cpu(id->word77);
+ id->word78 = __le16_to_cpu(id->word78);
+ id->word79 = __le16_to_cpu(id->word79);
+ id->word80 = __le16_to_cpu(id->word80);
+ id->word81 = __le16_to_cpu(id->word81);
+ id->command_sets = __le16_to_cpu(id->command_sets);
+ id->word83 = __le16_to_cpu(id->word83);
+ id->word84 = __le16_to_cpu(id->word84);
+ id->word85 = __le16_to_cpu(id->word85);
+ id->word86 = __le16_to_cpu(id->word86);
+ id->word87 = __le16_to_cpu(id->word87);
+ id->dma_ultra = __le16_to_cpu(id->dma_ultra);
+ id->word89 = __le16_to_cpu(id->word89);
+ id->word90 = __le16_to_cpu(id->word90);
+ id->word91 = __le16_to_cpu(id->word91);
+ id->word92 = __le16_to_cpu(id->word92);
+ id->word93 = __le16_to_cpu(id->word93);
+ id->word94 = __le16_to_cpu(id->word94);
+ id->word95 = __le16_to_cpu(id->word95);
+ id->word96 = __le16_to_cpu(id->word96);
+ id->word97 = __le16_to_cpu(id->word97);
+ id->word98 = __le16_to_cpu(id->word98);
+ id->word99 = __le16_to_cpu(id->word99);
+ id->word100 = __le16_to_cpu(id->word100);
+ id->word101 = __le16_to_cpu(id->word101);
+ id->word102 = __le16_to_cpu(id->word102);
+ id->word103 = __le16_to_cpu(id->word103);
+ id->word104 = __le16_to_cpu(id->word104);
+ id->word105 = __le16_to_cpu(id->word105);
+ id->word106 = __le16_to_cpu(id->word106);
+ id->word107 = __le16_to_cpu(id->word107);
+ id->word108 = __le16_to_cpu(id->word108);
+ id->word109 = __le16_to_cpu(id->word109);
+ id->word110 = __le16_to_cpu(id->word110);
+ id->word111 = __le16_to_cpu(id->word111);
+ id->word112 = __le16_to_cpu(id->word112);
+ id->word113 = __le16_to_cpu(id->word113);
+ id->word114 = __le16_to_cpu(id->word114);
+ id->word115 = __le16_to_cpu(id->word115);
+ id->word116 = __le16_to_cpu(id->word116);
+ id->word117 = __le16_to_cpu(id->word117);
+ id->word118 = __le16_to_cpu(id->word118);
+ id->word119 = __le16_to_cpu(id->word119);
+ id->word120 = __le16_to_cpu(id->word120);
+ id->word121 = __le16_to_cpu(id->word121);
+ id->word122 = __le16_to_cpu(id->word122);
+ id->word123 = __le16_to_cpu(id->word123);
+ id->word124 = __le16_to_cpu(id->word124);
+ id->word125 = __le16_to_cpu(id->word125);
+ id->word126 = __le16_to_cpu(id->word126);
+ id->word127 = __le16_to_cpu(id->word127);
+ id->security = __le16_to_cpu(id->security);
+ for (i=0; i<127; i++)
+ id->reserved[i] = __le16_to_cpu(id->reserved[i]);
X }
diff -u --recursive --new-file v2.2.7/linux/arch/ppc/kernel/signal.c linux/arch/ppc/kernel/signal.c
--- v2.2.7/linux/arch/ppc/kernel/signal.c Tue Mar 23 14:35:46 1999
+++ linux/arch/ppc/kernel/signal.c Thu Apr 29 12:39:01 1999


@@ -1,7 +1,7 @@
X /*

X * linux/arch/ppc/kernel/signal.c
X *
- * $Id: signal.c,v 1.23 1999/03/01 16:51:53 cort Exp $
+ * $Id: signal.c,v 1.24 1999/04/03 11:25:16 paulus Exp $
X *


X * PowerPC version
X * Copyright (C) 1995-1996 Gary Thomas (g...@linuxppc.org)

@@ -218,13 +218,8 @@
X if (sc == (struct sigcontext_struct *)(sigctx.regs)) {
X /* Last stacked signal - restore registers */
X sr = (struct sigregs *) sigctx.regs;


-#ifdef __SMP__
- if ( regs->msr & MSR_FP )
- smp_giveup_fpu(current);
-#else
- if (last_task_used_math == current)
- giveup_fpu();
-#endif
+ if (regs->msr & MSR_FP )
+ giveup_fpu(current);

X if (copy_from_user(saved_regs, &sr->gp_regs,
X sizeof(sr->gp_regs)))
X goto badframe;
@@ -271,13 +266,8 @@
X
X if (verify_area(VERIFY_WRITE, frame, sizeof(*frame)))
X goto badframe;


-#ifdef __SMP__
- if ( regs->msr & MSR_FP )
- smp_giveup_fpu(current);
-#else
- if (last_task_used_math == current)
- giveup_fpu();
-#endif
+ if (regs->msr & MSR_FP)
+ giveup_fpu(current);

X if (__copy_to_user(&frame->gp_regs, regs, GP_REGS_SIZE)
X || __copy_to_user(&frame->fp_regs, current->tss.fpr,
X ELF_NFPREG * sizeof(double))
diff -u --recursive --new-file v2.2.7/linux/arch/ppc/kernel/smp.c linux/arch/ppc/kernel/smp.c
--- v2.2.7/linux/arch/ppc/kernel/smp.c Tue Mar 23 14:35:46 1999
+++ linux/arch/ppc/kernel/smp.c Thu Apr 29 12:39:01 1999
@@ -1,10 +1,13 @@
X /*
- * $Id: smp.c,v 1.48 1999/03/16 10:40:32 cort Exp $
+ * $Id: smp.c,v 1.49 1999/03/18 04:16:31 cort Exp $
X *
X * Smp support for ppc.
X *
X * Written by Cort Dougan (co...@cs.nmt.edu) borrowing a great
X * deal of code from the sparc and intel versions.
+ *
+ * Support for PReP (Motorola MTX/MVME) SMP by Troy Benjegerdes
+ * (tr...@microux.com, ho...@drgw.net)
X */
X
X #include <linux/kernel.h>
@@ -253,6 +256,7 @@
X * cpu 0, the master -- Cort
X */
X cpu_callin_map[0] = 1;
+ cpu_callin_map[1] = 0;
X smp_store_cpu_info(0);
X active_kernel_processor = 0;
X current->processor = 0;
diff -u --recursive --new-file v2.2.7/linux/arch/ppc/kernel/syscalls.c linux/arch/ppc/kernel/syscalls.c
--- v2.2.7/linux/arch/ppc/kernel/syscalls.c Mon Oct 5 13:13:36 1998
+++ linux/arch/ppc/kernel/syscalls.c Sat May 8 11:14:01 1999
@@ -205,12 +205,15 @@


X
X lock_kernel();
X if (!(flags & MAP_ANONYMOUS)) {

- if (fd >= NR_OPEN || !(file = current->files->fd[fd]))

+ file = fget(fd);
+ if (!file)

X goto out;
X }
X

X flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);

X ret = do_mmap(file, addr, len, prot, flags, offset);
+ if (file)


+ fput(file);
X out:
X unlock_kernel();

X return ret;
diff -u --recursive --new-file v2.2.7/linux/arch/ppc/kernel/time.c linux/arch/ppc/kernel/time.c
--- v2.2.7/linux/arch/ppc/kernel/time.c Tue Mar 23 14:35:46 1999
+++ linux/arch/ppc/kernel/time.c Thu Apr 29 12:39:01 1999


@@ -1,5 +1,5 @@
X /*

- * $Id: time.c,v 1.45 1999/03/03 15:09:59 cort Exp $
+ * $Id: time.c,v 1.47 1999/03/18 05:11:11 cort Exp $
X * Common time routines among all ppc machines.
X *
X * Written by Cort Dougan (co...@cs.nmt.edu) to merge
@@ -41,18 +41,14 @@
X #include <asm/processor.h>
X #include <asm/nvram.h>
X #include <asm/cache.h>
-#ifdef CONFIG_MBX
-#include <asm/mbx.h>
-#endif
+/* Fixme - Why is this here? - Corey */
X #ifdef CONFIG_8xx
X #include <asm/8xx_immap.h>
X #endif
+#include <asm/machdep.h>


X
X #include "time.h"
X

-/* this is set to the appropriate pmac/prep/chrp func in init_IRQ() */
-int (*set_rtc_time)(unsigned long);
-
X void smp_local_timer_interrupt(struct pt_regs *);
X
X /* keep track of when we need to update the rtc */
@@ -116,16 +112,21 @@
X */
X if ( xtime.tv_sec > last_rtc_update + 660 )
X {
- if (set_rtc_time(xtime.tv_sec) == 0)
+ if (ppc_md.set_rtc_time(xtime.tv_sec) == 0) {
X last_rtc_update = xtime.tv_sec;
- else
- last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
+ }
+ else {
+ /* do it again in 60 s */
+ last_rtc_update = xtime.tv_sec - 60;
+ }
X }


X }
X }
X #ifdef __SMP__

X smp_local_timer_interrupt(regs);
X #endif
+
+ /* Fixme - make this more generic - Corey */
X #ifdef CONFIG_APUS
X {
X extern void apus_heartbeat (void);
@@ -135,28 +136,6 @@
X hardirq_exit(cpu);
X }
X
-#ifdef CONFIG_MBX
-/* A place holder for time base interrupts, if they are ever enabled.
-*/
-void timebase_interrupt(int irq, void * dev, struct pt_regs * regs)
-{
- printk("timebase_interrupt()\n");
-}
-
-/* The RTC on the MPC8xx is an internal register.
- * We want to protect this during power down, so we need to unlock,
- * modify, and re-lock.
- */
-static int
-mbx_set_rtc_time(unsigned long time)
-{
- ((immap_t *)IMAP_ADDR)->im_sitk.sitk_rtck = KAPWR_KEY;
- ((immap_t *)IMAP_ADDR)->im_sit.sit_rtc = time;
- ((immap_t *)IMAP_ADDR)->im_sitk.sitk_rtck = ~KAPWR_KEY;
- return(0);


-}
-#endif /* CONFIG_MBX */

-
X /*
X * This version of gettimeofday has microsecond resolution.
X */
@@ -203,199 +182,29 @@
X
X __initfunc(void time_init(void))
X {
-#ifndef CONFIG_MBX
+ if (ppc_md.time_init != NULL)
+ {
+ ppc_md.time_init();
+ }
+
X if ((_get_PVR() >> 16) == 1) {
X /* 601 processor: dec counts down by 128 every 128ns */
X decrementer_count = DECREMENTER_COUNT_601;
X count_period_num = COUNT_PERIOD_NUM_601;
X count_period_den = COUNT_PERIOD_DEN_601;
+ } else if (!smp_processor_id()) {
+ ppc_md.calibrate_decr();
X }
X
- switch (_machine) {
- case _MACH_Pmac:
- xtime.tv_sec = pmac_get_rtc_time();
- if ( (_get_PVR() >> 16) != 1 && (!smp_processor_id()) )
- pmac_calibrate_decr();
- if ( !smp_processor_id() )
- set_rtc_time = pmac_set_rtc_time;


- break;
- case _MACH_chrp:

- chrp_time_init();
- xtime.tv_sec = chrp_get_rtc_time();
- if ((_get_PVR() >> 16) != 1)
- chrp_calibrate_decr();
- set_rtc_time = chrp_set_rtc_time;


- break;
- case _MACH_prep:

- xtime.tv_sec = prep_get_rtc_time();
- prep_calibrate_decr();
- set_rtc_time = prep_set_rtc_time;


- break;
-#ifdef CONFIG_APUS
- case _MACH_apus:
- {

- xtime.tv_sec = apus_get_rtc_time();
- apus_calibrate_decr();
- set_rtc_time = apus_set_rtc_time;
- break;
- }
-#endif
- }
- xtime.tv_usec = 0;
-#else /* CONFIG_MBX */
- mbx_calibrate_decr();
- set_rtc_time = mbx_set_rtc_time;
-
- /* First, unlock all of the registers we are going to modify.
- * To protect them from corruption during power down, registers
- * that are maintained by keep alive power are "locked". To
- * modify these registers we have to write the key value to
- * the key location associated with the register.
- */
- ((immap_t *)IMAP_ADDR)->im_sitk.sitk_tbscrk = KAPWR_KEY;
- ((immap_t *)IMAP_ADDR)->im_sitk.sitk_rtcsck = KAPWR_KEY;
-
-
- /* Disable the RTC one second and alarm interrupts.
- */
- ((immap_t *)IMAP_ADDR)->im_sit.sit_rtcsc &=
- ~(RTCSC_SIE | RTCSC_ALE);
-
- /* Enabling the decrementer also enables the timebase interrupts
- * (or from the other point of view, to get decrementer interrupts
- * we have to enable the timebase). The decrementer interrupt
- * is wired into the vector table, nothing to do here for that.
- */
- ((immap_t *)IMAP_ADDR)->im_sit.sit_tbscr =
- ((mk_int_int_mask(DEC_INTERRUPT) << 8) |
- (TBSCR_TBF | TBSCR_TBE));
- if (request_irq(DEC_INTERRUPT, timebase_interrupt, 0, "tbint", NULL) != 0)
- panic("Could not allocate timer IRQ!");
-
- /* Get time from the RTC.
- */
- xtime.tv_sec = ((immap_t *)IMAP_ADDR)->im_sit.sit_rtc;
- xtime.tv_usec = 0;
+ xtime.tv_sec = ppc_md.get_rtc_time();
+ xtime.tv_usec = 0;
X
-#endif /* CONFIG_MBX */
X set_dec(decrementer_count);
X /* mark the rtc/on-chip timer as in sync
X * so we don't update right away
X */
X last_rtc_update = xtime.tv_sec;
X }
-
-#ifndef CONFIG_MBX
-/*
- * Uses the on-board timer to calibrate the on-chip decrementer register
- * for prep systems. On the pmac the OF tells us what the frequency is
- * but on prep we have to figure it out.


- * -- Cort
- */

-int calibrate_done = 0;
-volatile int *done_ptr = &calibrate_done;
-__initfunc(void prep_calibrate_decr(void))
-{
- unsigned long flags;
- unsigned long freq, divisor;
-
- /* the Powerstack II's have trouble with the timer so
- * we use a default value -- Cort
- */
- if ( (_prep_type == _PREP_Motorola) &&
- ((inb(0x800) & 0xF0) & 0x40) )
- {
- static unsigned long t2 = 0;
-
- t2 = 998700000/60;
- freq = t2 * 60; /* try to make freq/1e6 an integer */
- divisor = 60;
- printk("time_init: decrementer frequency = %lu/%lu (%luMHz)\n",
- freq, divisor,t2>>20);
- decrementer_count = freq / HZ / divisor;
- count_period_num = divisor;
- count_period_den = freq / 1000000;
- return;
- }
- if ( _prep_type == _PREP_Radstone )
- {
- freq = res->VitalProductData.ProcessorBusHz;
- divisor = 4;
- printk("time_init: decrementer frequency = %d/%d\n", freq, divisor);
- decrementer_count = freq / HZ / divisor;
- count_period_num = divisor;
- count_period_den = freq / 1000000;
- return;
- }
-
- save_flags(flags);
-
-#define TIMER0_COUNT 0x40
-#define TIMER_CONTROL 0x43
- /* set timer to periodic mode */
- outb_p(0x34,TIMER_CONTROL);/* binary, mode 2, LSB/MSB, ch 0 */
- /* set the clock to ~100 Hz */
- outb_p(LATCH & 0xff , TIMER0_COUNT); /* LSB */
- outb(LATCH >> 8 , TIMER0_COUNT); /* MSB */
-
- if (request_irq(0, prep_calibrate_decr_handler, 0, "timer", NULL) != 0)
- panic("Could not allocate timer IRQ!");
- __sti();
- while ( ! *done_ptr ) /* nothing */; /* wait for calibrate */
- restore_flags(flags);
- free_irq( 0, NULL);
-}
-
-__initfunc(void prep_calibrate_decr_handler(int irq, void *dev, struct pt_regs * regs))
-{
- unsigned long freq, divisor;
- static unsigned long t1 = 0, t2 = 0;
-
- if ( !t1 )
- t1 = get_dec();
- else if (!t2)
- {
- t2 = get_dec();
- t2 = t1-t2; /* decr's in 1/HZ */
- t2 = t2*HZ; /* # decrs in 1s - thus in Hz */
- freq = t2 * 60; /* try to make freq/1e6 an integer */
- divisor = 60;
- printk("time_init: decrementer frequency = %lu/%lu (%luMHz)\n",
- freq, divisor,t2>>20);
- decrementer_count = freq / HZ / divisor;
- count_period_num = divisor;
- count_period_den = freq / 1000000;
- *done_ptr = 1;
- }
-}


-
-#else /* CONFIG_MBX */
-

-/* The decrementer counts at the system (internal) clock frequency divided by
- * sixteen, or external oscillator divided by four. Currently, we only
- * support the MBX, which is system clock divided by sixteen.
- */
-__initfunc(void mbx_calibrate_decr(void))
-{
- bd_t *binfo = (bd_t *)res;
- int freq, fp, divisor;
-
- if ((((immap_t *)IMAP_ADDR)->im_clkrst.car_sccr & 0x02000000) == 0)
- printk("WARNING: Wrong decrementer source clock.\n");
-
- /* The manual says the frequency is in Hz, but it is really
- * as MHz. The value 'fp' is the number of decrementer ticks
- * per second.
- */
- fp = (binfo->bi_intfreq * 1000000) / 16;
- freq = fp*60; /* try to make freq/1e6 an integer */
- divisor = 60;
- printk("time_init: decrementer frequency = %d/%d\n", freq, divisor);
- decrementer_count = freq / HZ / divisor;
- count_period_num = divisor;
- count_period_den = freq / 1000000;


-}
-#endif /* CONFIG_MBX */

X
X /* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
X * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
diff -u --recursive --new-file v2.2.7/linux/arch/ppc/kernel/time.h linux/arch/ppc/kernel/time.h
--- v2.2.7/linux/arch/ppc/kernel/time.h Thu Apr 23 20:21:29 1998
+++ linux/arch/ppc/kernel/time.h Thu Apr 29 12:39:01 1999


@@ -1,5 +1,5 @@
X /*

- * $Id: time.h,v 1.10 1998/04/01 07:46:03 geert Exp $
+ * $Id: time.h,v 1.11 1999/03/18 04:16:34 cort Exp $
X * Common time prototypes and such for all ppc machines.
X *
X * Written by Cort Dougan (co...@cs.nmt.edu) to merge
@@ -9,32 +9,15 @@
X #include <linux/mc146818rtc.h>
X
X /* time.c */
-void prep_calibrate_decr_handler(int, void *,struct pt_regs *);
-void prep_calibrate_decr(void);
-void pmac_calibrate_decr(void);
-extern void apus_calibrate_decr(void);
X extern unsigned decrementer_count;
X extern unsigned count_period_num;
X extern unsigned count_period_den;
-extern unsigned long mktime(unsigned int, unsigned int,unsigned int,
+extern unsigned long mktime(unsigned int, unsigned int, unsigned int,
X unsigned int, unsigned int, unsigned int);
X extern void to_tm(int tim, struct rtc_time * tm);
X extern unsigned long last_rtc_update;
X
-/* pmac/prep/chrp_time.c */
-unsigned long prep_get_rtc_time(void);
-unsigned long pmac_get_rtc_time(void);
-unsigned long chrp_get_rtc_time(void);
-unsigned long apus_get_rtc_time(void);
-int prep_set_rtc_time(unsigned long nowtime);
-int pmac_set_rtc_time(unsigned long nowtime);
-int chrp_set_rtc_time(unsigned long nowtime);
-int apus_set_rtc_time(unsigned long nowtime);
-void pmac_read_rtc_time(void);
-void chrp_calibrate_decr(void);
-void chrp_time_init(void);
X int via_calibrate_decr(void);
-void mbx_calibrate_decr(void);
X
X /* Accessor functions for the decrementer register. */
X static __inline__ unsigned int get_dec(void)
diff -u --recursive --new-file v2.2.7/linux/arch/ppc/kernel/traps.c linux/arch/ppc/kernel/traps.c
--- v2.2.7/linux/arch/ppc/kernel/traps.c Thu Jan 7 15:11:36 1999
+++ linux/arch/ppc/kernel/traps.c Thu Apr 29 12:39:01 1999
@@ -191,13 +191,8 @@
X {
X int fixed;
X
-#ifdef __SMP__
- if (regs->msr & MSR_FP )


- smp_giveup_fpu(current);
-#else
- if (last_task_used_math == current)
- giveup_fpu();
-#endif
+ if (regs->msr & MSR_FP)
+ giveup_fpu(current);

X fixed = fix_alignment(regs);
X if (fixed == 1) {
X regs->nip += 4; /* skip over emulated instruction */
diff -u --recursive --new-file v2.2.7/linux/arch/ppc/lib/strcase.c linux/arch/ppc/lib/strcase.c
--- v2.2.7/linux/arch/ppc/lib/strcase.c Sat Aug 16 09:51:08 1997
+++ linux/arch/ppc/lib/strcase.c Thu Apr 29 12:39:01 1999
@@ -10,3 +10,14 @@
X } while (c1 == c2 && c1 != 0);
X return c1 - c2;
X }
+
+int strncasecmp(const char *s1, const char *s2, int n)
+{
+ int c1, c2;
+
+ do {
+ c1 = tolower(*s1++);
+ c2 = tolower(*s2++);
+ } while ((--n > 0) && c1 == c2 && c1 != 0);
+ return c1 - c2;
+}
diff -u --recursive --new-file v2.2.7/linux/arch/ppc/mbxboot/head.S linux/arch/ppc/mbxboot/head.S
--- v2.2.7/linux/arch/ppc/mbxboot/head.S Fri Apr 16 14:47:30 1999
+++ linux/arch/ppc/mbxboot/head.S Thu Apr 29 12:39:01 1999


@@ -6,7 +6,7 @@
X .text
X

X /*
- * $Id: head.S,v 1.2 1999/02/17 06:29:41 cort Exp $
+ * $Id: head.S,v 1.4 1999/04/22 06:32:09 davem Exp $
X *
X * This code is loaded by the ROM loader at some arbitrary location.
X * Move it to high memory so that it can load the kernel at 0x0000.
@@ -67,7 +67,7 @@
X mr r11, r21
X lis r8,start@h
X ori r8,r8,start@l
- li r9,end@h
+ lis r9,end@h
X ori r9,r9,end@l
X sub r7,r8,r9
X srwi r7,r7,2
diff -u --recursive --new-file v2.2.7/linux/arch/ppc/mm/fault.c linux/arch/ppc/mm/fault.c
--- v2.2.7/linux/arch/ppc/mm/fault.c Thu Jan 7 15:11:36 1999
+++ linux/arch/ppc/mm/fault.c Tue May 11 08:24:32 1999
@@ -140,7 +140,8 @@
X if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
X goto bad_area;
X }
- handle_mm_fault(current, vma, address, error_code & 0x02000000);
+ if (!handle_mm_fault(current, vma, address, error_code & 0x02000000))
+ goto bad_area;
X up(&mm->mmap_sem);
X /*
X * keep track of tlb+htab misses that are good addrs but
diff -u --recursive --new-file v2.2.7/linux/arch/ppc/mm/init.c linux/arch/ppc/mm/init.c
--- v2.2.7/linux/arch/ppc/mm/init.c Tue Mar 23 14:35:46 1999
+++ linux/arch/ppc/mm/init.c Tue May 11 08:24:32 1999
@@ -1,5 +1,5 @@
- /*
- * $Id: init.c,v 1.150 1999/03/10 08:16:33 cort Exp $
+/*
+ * $Id: init.c,v 1.164 1999/05/05 17:33:55 cort Exp $
X *


X * PowerPC version
X * Copyright (C) 1995-1996 Gary Thomas (g...@linuxppc.org)

@@ -119,12 +119,19 @@
X PTE *Hash, *Hash_end;
X unsigned long Hash_size, Hash_mask;
X #ifndef CONFIG_8xx
+#ifdef CONFIG_PPC64
+unsigned long long _SDR1;
+#else
X unsigned long _SDR1;
+#endif
X static void hash_init(void);
X union ubat { /* BAT register values to be loaded */
X BAT bat;
- P601_BAT bat_601;
+#ifdef CONFIG_PPC64
+ u64 word[2];
+#else
X u32 word[2];
+#endif
X } BATS[4][2]; /* 4 pairs of IBAT, DBAT */
X
X struct batrange { /* stores address ranges mapped by BATs */
@@ -132,6 +139,8 @@
X unsigned long limit;
X unsigned long phys;
X } bat_addrs[4];
+unsigned long inline v_mapped_by_bats(unsigned long);
+unsigned long inline p_mapped_by_bats(unsigned long);
X #endif /* CONFIG_8xx */
X
X /*
@@ -332,15 +341,40 @@
X * virt == phys; for addresses below this we use
X * space going down from ioremap_base (ioremap_bot
X * records where we're up to).
- *
- * We should also look out for a frame buffer and
- * map it with a free BAT register, if there is one.
X */
X p = addr & PAGE_MASK;
X size = PAGE_ALIGN(addr + size) - p;
+
+ /*
+ * Don't allow anybody to remap normal RAM that we're using.
+ * mem_init() sets high_memory so only do the check after that.
+ */
+ if ( mem_init_done && (p < virt_to_phys(high_memory)) )
+ {
+ printk("__ioremap(): phys addr %0lx is RAM lr %p\n", p,
+ __builtin_return_address(0));


+ return NULL;
+ }
+

X if (size == 0)
X return NULL;
X
+#ifndef CONFIG_8xx
+ /*
+ * Is it already mapped? Perhaps overlapped by a previous
+ * BAT mapping. If the whole area is mapped then we're done,
+ * otherwise remap it since we want to keep the virt addrs for
+ * each request contiguous.
+ *
+ * We make the assumption here that if the bottom and top
+ * of the range we want are mapped then it's mapped to the
+ * same virt address (and this is contiguous).


+ * -- Cort
+ */

+ if ( (v = p_mapped_by_bats(addr)) /*&& p_mapped_by_bats(addr+(size-1))*/ )
+ goto out;
+#endif /* CONFIG_8xx */
+
X if (mem_init_done) {
X struct vm_struct *area;
X area = get_vm_area(size);
@@ -358,10 +392,17 @@
X flags |= pgprot_val(PAGE_KERNEL);
X if (flags & (_PAGE_NO_CACHE | _PAGE_WRITETHRU))
X flags |= _PAGE_GUARDED;
+
+#ifndef CONFIG_8xx
+ /*
+ * Is it a candidate for a BAT mapping?
+ */
+#endif /* CONFIG_8xx */
+
X for (i = 0; i < size; i += PAGE_SIZE)
X map_page(&init_task, v+i, p+i, flags);
-
- return (void *) (v + (addr & ~PAGE_MASK));
+out:
+ return (void *) (v + (p & ~PAGE_MASK));
X }
X
X void iounmap(void *addr)
@@ -412,9 +453,7 @@
X {
X pmd_t *pd;
X pte_t *pg;
-#ifndef CONFIG_8xx
- int b;
-#endif
+
X if (tsk->mm->pgd == NULL) {
X /* Allocate upper level page map */
X tsk->mm->pgd = (pgd_t *) MMU_get_page();
@@ -422,20 +461,8 @@
X /* Use upper 10 bits of VA to index the first level map */
X pd = (pmd_t *) (tsk->mm->pgd + (va >> PGDIR_SHIFT));
X if (pmd_none(*pd)) {
-#ifndef CONFIG_8xx
- /*
- * Need to allocate second-level table, but first
- * check whether this address is already mapped by
- * the BATs; if so, don't bother allocating the page.
- */
- for (b = 0; b < 4; ++b) {
- if (va >= bat_addrs[b].start
- && va <= bat_addrs[b].limit) {
- /* XXX should check the phys address matches */
- return;
- }


- }
-#endif /* CONFIG_8xx */

+ if ( v_mapped_by_bats(va) )
+ return;
X pg = (pte_t *) MMU_get_page();
X pmd_val(*pd) = (unsigned long) pg;
X }
@@ -680,6 +707,33 @@
X static void sort_mem_pieces(struct mem_pieces *);
X static void coalesce_mem_pieces(struct mem_pieces *);
X
+/*
+ * Return 1 if this VA is mapped by BATs
+ */
+unsigned long inline v_mapped_by_bats(unsigned long va)
+{
+ int b;
+ for (b = 0; b < 4; ++b)
+ if (va >= bat_addrs[b].start
+ && va < bat_addrs[b].limit)
+ return 1;


+ return 0;
+}
+
+/*

+ * Return VA for a given PA or 0 if not mapped
+ */
+unsigned long inline p_mapped_by_bats(unsigned long pa)
+{
+ int b;
+ for (b = 0; b < 4; ++b)
+ if (pa >= bat_addrs[b].phys
+ && pa < (bat_addrs[b].limit-bat_addrs[b].start)
+ +bat_addrs[b].phys)
+ return bat_addrs[b].start+(pa-bat_addrs[b].phys);


+ return 0;
+}
+

X __initfunc(static void sort_mem_pieces(struct mem_pieces *mp))
X {
X unsigned long a, s;
@@ -836,7 +890,7 @@
X
X setbat(2, KERNELBASE, mem_base, bl, RAM_PAGE);
X done = (unsigned long)bat_addrs[2].limit - KERNELBASE + 1;
- if (done < tot) {
+ if ((done < tot) && !bat_addrs[3].limit) {
X /* use BAT3 to cover a bit more */
X tot -= done;
X for (bl = 128<<10; bl < max_size; bl <<= 1)
@@ -990,11 +1044,13 @@
X switch (_machine) {
X case _MACH_prep:
X setbat(0, 0x80000000, 0x80000000, 0x10000000, IO_PAGE);
- setbat(1, 0xd0000000, 0xc0000000, 0x10000000, IO_PAGE);
+ setbat(1, 0xf0000000, 0xc0000000, 0x08000000, IO_PAGE);
+ ioremap_base = 0xf0000000;
X break;
X case _MACH_chrp:
X setbat(0, 0xf8000000, 0xf8000000, 0x08000000, IO_PAGE);
X setbat(1, 0x80000000, 0x80000000, 0x10000000, IO_PAGE);
+ setbat(3, 0x90000000, 0x90000000, 0x10000000, IO_PAGE);
X break;
X case _MACH_Pmac:
X {
@@ -1245,7 +1301,7 @@
X int i;
X
X /* max amount of RAM we allow -- Cort */
-#define RAM_LIMIT (768<<20)
+#define RAM_LIMIT (768<<20)
X
X memory_node = find_devices("memory");
X if (memory_node == NULL) {
@@ -1449,10 +1505,18 @@
X * up to a maximum of 2MB.
X */
X ramsize = (ulong)end_of_DRAM - KERNELBASE;
+#ifdef CONFIG_PPC64
+ Hash_mask = 0;
+ for (h = 256<<10; h < ramsize / 256 && h < 4<<20; h *= 2, Hash_mask++)
+ ;
+ Hash_size = h;
+ Hash_mask << 10; /* so setting _SDR1 works the same -- Cort */
+#else
X for (h = 64<<10; h < ramsize / 256 && h < 2<<20; h *= 2)
X ;
X Hash_size = h;
X Hash_mask = (h >> 6) - 1;
+#endif
X
X #ifdef NO_RELOAD_HTAB
X /* shrink the htab since we don't use it on 603's -- Cort */
@@ -1530,4 +1594,3 @@
X }
X }
X #endif /* ndef CONFIG_8xx */
-
diff -u --recursive --new-file v2.2.7/linux/arch/sparc/kernel/entry.S linux/arch/sparc/kernel/entry.S
--- v2.2.7/linux/arch/sparc/kernel/entry.S Wed Apr 28 11:37:30 1999
+++ linux/arch/sparc/kernel/entry.S Tue May 11 08:24:31 1999
@@ -1,4 +1,4 @@
-/* $Id: entry.S,v 1.158 1999/04/27 14:35:07 davem Exp $
+/* $Id: entry.S,v 1.159 1999/05/08 03:00:03 davem Exp $
X * arch/sparc/kernel/entry.S: Sparc trap low-level entry points.
X *
X * Copyright (C) 1995 David S. Miller (da...@caip.rutgers.edu)
@@ -1476,7 +1476,7 @@
X wr %l0, PSR_ET, %psr
X WRITE_PAUSE
X call schedule_tail
- nop
+ mov %g3, %o0
X b C_LABEL(ret_sys_call)
X ld [%sp + REGWIN_SZ + PT_I0], %o0
X #endif
diff -u --recursive --new-file v2.2.7/linux/arch/sparc/kernel/process.c linux/arch/sparc/kernel/process.c
--- v2.2.7/linux/arch/sparc/kernel/process.c Wed Apr 28 11:37:30 1999
+++ linux/arch/sparc/kernel/process.c Tue May 11 08:24:31 1999
@@ -1,4 +1,4 @@
-/* $Id: process.c,v 1.136 1999/04/16 01:20:33 anton Exp $
+/* $Id: process.c,v 1.137 1999/05/08 03:00:10 davem Exp $
X * linux/arch/sparc/kernel/process.c
X *
X * Copyright (C) 1995 David S. Miller (da...@caip.rutgers.edu)
@@ -63,6 +63,8 @@


X /* endless idle loop with no priority at all */
X current->priority = 0;
X current->counter = -100;
+ init_idle();
+
X for (;;) {

X if (ARCH_SUN4C_SUN4) {
X static int count = HZ;
@@ -111,6 +113,8 @@


X /* endless idle loop with no priority at all */
X current->priority = 0;
X current->counter = -100;
+ init_idle();
+
X while(1) {

X if(current->need_resched) {
X schedule();
diff -u --recursive --new-file v2.2.7/linux/arch/sparc/kernel/sun4d_smp.c linux/arch/sparc/kernel/sun4d_smp.c
--- v2.2.7/linux/arch/sparc/kernel/sun4d_smp.c Thu Nov 19 09:56:27 1998
+++ linux/arch/sparc/kernel/sun4d_smp.c Tue May 11 08:24:31 1999
@@ -190,6 +190,7 @@
X current->processor = boot_cpu_id;
X smp_store_cpu_info(boot_cpu_id);
X smp_setup_percpu_timer();
+ init_idle();
X local_flush_cache_all();
X if(linux_num_cpus == 1)
X return; /* Not an MP box. */
@@ -211,6 +212,7 @@
X p = task[++cpucount];
X
X p->processor = i;
+ p->has_cpu = 1; /* we schedule the first task manually */
X current_set[i] = p;
X
X for (no = 0; no < linux_num_cpus; no++)
diff -u --recursive --new-file v2.2.7/linux/arch/sparc/kernel/sun4m_smp.c linux/arch/sparc/kernel/sun4m_smp.c
--- v2.2.7/linux/arch/sparc/kernel/sun4m_smp.c Wed Apr 28 11:37:30 1999
+++ linux/arch/sparc/kernel/sun4m_smp.c Tue May 11 08:24:31 1999
@@ -161,6 +161,7 @@
X smp_store_cpu_info(boot_cpu_id);
X set_irq_udt(mid_xlate[boot_cpu_id]);
X smp_setup_percpu_timer();
+ init_idle();
X local_flush_cache_all();
X if(linux_num_cpus == 1)
X return; /* Not an MP box. */
@@ -180,6 +181,7 @@
X p = task[++cpucount];
X
X p->processor = i;
+ p->has_cpu = 1; /* we schedule the first task manually */
X current_set[i] = p;
X
X /* See trampoline.S for details... */
diff -u --recursive --new-file v2.2.7/linux/arch/sparc/kernel/sys_sparc.c linux/arch/sparc/kernel/sys_sparc.c
--- v2.2.7/linux/arch/sparc/kernel/sys_sparc.c Tue Mar 23 14:35:47 1999
+++ linux/arch/sparc/kernel/sys_sparc.c Tue May 11 08:24:31 1999
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc.c,v 1.51 1999/03/20 22:02:00 davem Exp $
+/* $Id: sys_sparc.c,v 1.52 1999/05/08 08:09:48 anton Exp $
X * linux/arch/sparc/kernel/sys_sparc.c
X *
X * This file contains various random system calls that
@@ -231,7 +231,7 @@
X
X if (count++ > 5) return -ENOSYS;
X lock_kernel();
- printk ("Unimplemented SPARC system call %d\n",(int)regs->u_regs[1]);
+ printk ("%s[%d]: Unimplemented SPARC system call %d\n", current->comm, current->pid, (int)regs->u_regs[1]);
X #ifdef DEBUG_UNIMP_SYSCALL
X show_regs (regs);
X #endif
diff -u --recursive --new-file v2.2.7/linux/arch/sparc/mm/iommu.c linux/arch/sparc/mm/iommu.c
--- v2.2.7/linux/arch/sparc/mm/iommu.c Fri May 8 23:14:46 1998
+++ linux/arch/sparc/mm/iommu.c Tue May 11 08:24:31 1999
@@ -1,4 +1,4 @@
-/* $Id: iommu.c,v 1.9 1998/04/15 14:58:37 jj Exp $
+/* $Id: iommu.c,v 1.10 1999/05/07 17:03:34 jj Exp $
X * iommu.c: IOMMU specific routines for memory management.
X *
X * Copyright (C) 1995 David S. Miller (da...@caip.rutgers.edu)
@@ -51,8 +51,7 @@
X unsigned long tmp;
X struct iommu_struct *iommu;
X struct linux_prom_registers iommu_promregs[PROMREG_MAX];
- int i, j, k, l, m;
- struct iommu_alloc { unsigned long addr; int next; } *ia;
+ int i;
X
X iommu = kmalloc(sizeof(struct iommu_struct), GFP_ATOMIC);
X prom_getproperty(iommund, "reg", (void *) iommu_promregs,
@@ -97,62 +96,18 @@
X ptsize = (ptsize >> PAGE_SHIFT) * sizeof(iopte_t);
X
X /* Stupid alignment constraints give me a headache.
- We want to get very large aligned memory area, larger than
- maximum what get_free_pages gives us (128K): we need
- 256K or 512K or 1M or 2M aligned to its size. */
- ia = (struct iommu_alloc *) kmalloc (sizeof(struct iommu_alloc) * 128, GFP_ATOMIC);
- for (i = 0; i < 128; i++) {
- ia[i].addr = 0;
- ia[i].next = -1;
- }
- k = 0;
- for (i = 0; i < 128; i++) {
- ia[i].addr = __get_free_pages(GFP_DMA, 5);
- if (ia[i].addr <= ia[k].addr) {
- if (i) {
- ia[i].next = k;
- k = i;
- }
- } else {
- for (m = k, l = ia[k].next; l != -1; m = l, l = ia[l].next)
- if (ia[i].addr <= ia[l].addr) {
- ia[i].next = l;
- ia[m].next = i;
- }
- if (l == -1)
- ia[m].next = i;
- }
- for (m = -1, j = 0, l = k; l != -1; l = ia[l].next) {
- if (!(ia[l].addr & (ptsize - 1))) {
- tmp = ia[l].addr;
- m = l;
- j = 128 * 1024;
- } else if (m != -1) {
- if (ia[l].addr != tmp + j)
- m = -1;
- else {
- j += 128 * 1024;
- if (j == ptsize) {


- break;
- }
- }
- }

- }
- if (l != -1)
+ We need 256K or 512K or 1M or 2M area aligned to
+ its size and current gfp will fortunately give
+ it to us. */
+ for (i = 6; i < 9; i++)
+ if ((1 << (i + PAGE_SHIFT)) == ptsize)
X break;
- }
- if (i == 128) {
+ tmp = __get_free_pages(GFP_DMA, i);
+ if (!tmp) {
X prom_printf("Could not allocate iopte of size 0x%08x\n", ptsize);
X prom_halt();
X }
- for (l = m, j = 0; j < ptsize; j += 128 * 1024, l = ia[l].next)
- ia[l].addr = 0;
- for (l = k; l != -1; l = ia[l].next)
- if (ia[l].addr)
- free_pages(ia[l].addr, 5);
- kfree (ia);
X iommu->lowest = iommu->page_table = (iopte_t *)tmp;
-
X
X /* Initialize new table. */
X flush_cache_all();
diff -u --recursive --new-file v2.2.7/linux/arch/sparc64/kernel/cpu.c linux/arch/sparc64/kernel/cpu.c
--- v2.2.7/linux/arch/sparc64/kernel/cpu.c Wed Apr 28 11:37:30 1999
+++ linux/arch/sparc64/kernel/cpu.c Tue May 11 08:24:31 1999
@@ -65,7 +65,7 @@
X long ver, fpu_vers;
X long fprs;
X
- cpuid = smp_processor_id();
+ cpuid = hard_smp_processor_id();
X
X fprs = fprs_read ();
X fprs_write (FPRS_FEF);
diff -u --recursive --new-file v2.2.7/linux/arch/sparc64/kernel/devices.c linux/arch/sparc64/kernel/devices.c
--- v2.2.7/linux/arch/sparc64/kernel/devices.c Tue Mar 23 14:35:47 1999
+++ linux/arch/sparc64/kernel/devices.c Tue May 11 08:24:31 1999
@@ -73,6 +73,9 @@
X
X prom_cpu_nodes[0] = prom_node_cpu;
X
+ mem_start = central_probe(mem_start);
+
X cpu_probe();
- return central_probe(mem_start);
+
+ return mem_start;
X }
diff -u --recursive --new-file v2.2.7/linux/arch/sparc64/kernel/ebus.c linux/arch/sparc64/kernel/ebus.c
--- v2.2.7/linux/arch/sparc64/kernel/ebus.c Tue Mar 23 14:35:47 1999
+++ linux/arch/sparc64/kernel/ebus.c Tue May 11 08:24:31 1999
@@ -1,4 +1,4 @@
-/* $Id: ebus.c,v 1.35 1999/01/26 14:34:11 jj Exp $
+/* $Id: ebus.c,v 1.36 1999/05/04 03:21:42 davem Exp $
X * ebus.c: PCI to EBus bridge device.
X *
X * Copyright (C) 1997 Eddie C. Dost (e...@skynet.be)
@@ -35,9 +35,6 @@
X #ifdef CONFIG_SUN_OPENPROMIO
X extern int openprom_init(void);
X #endif
-#ifdef CONFIG_SPARCAUDIO
-extern int sparcaudio_init(void);
-#endif
X #ifdef CONFIG_SUN_AUXIO
X extern void auxio_probe(void);
X #endif
@@ -398,9 +395,6 @@
X
X #ifdef CONFIG_SUN_OPENPROMIO
X openprom_init();
-#endif
-#ifdef CONFIG_SPARCAUDIO
- sparcaudio_init();
X #endif
X #ifdef CONFIG_SUN_BPP
X bpp_init();
diff -u --recursive --new-file v2.2.7/linux/arch/sparc64/kernel/entry.S linux/arch/sparc64/kernel/entry.S
--- v2.2.7/linux/arch/sparc64/kernel/entry.S Wed Apr 28 11:37:30 1999
+++ linux/arch/sparc64/kernel/entry.S Tue May 11 08:24:31 1999
@@ -1,4 +1,4 @@
-/* $Id: entry.S,v 1.102 1999/03/29 12:38:09 jj Exp $
+/* $Id: entry.S,v 1.103 1999/05/08 03:00:21 davem Exp $
X * arch/sparc64/kernel/entry.S: Sparc64 trap low-level entry points.
X *
X * Copyright (C) 1995,1997 David S. Miller (da...@caip.rutgers.edu)
@@ -766,6 +766,7 @@
X */
X #ifdef __SMP__
X andn %o7, 0x100, %l0
+ mov %g5, %o0 /* 'prev' */
X call schedule_tail
X sth %l0, [%g6 + AOFF_task_tss + AOFF_thread_flags]
X #else
diff -u --recursive --new-file v2.2.7/linux/arch/sparc64/kernel/ioctl32.c linux/arch/sparc64/kernel/ioctl32.c
--- v2.2.7/linux/arch/sparc64/kernel/ioctl32.c Mon Mar 29 11:09:11 1999
+++ linux/arch/sparc64/kernel/ioctl32.c Tue May 11 08:24:31 1999
@@ -1,4 +1,4 @@
-/* $Id: ioctl32.c,v 1.60 1999/03/22 10:40:54 jj Exp $
+/* $Id: ioctl32.c,v 1.62 1999/05/01 09:17:44 davem Exp $
X * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
X *
X * Copyright (C) 1997 Jakub Jelinek (j...@sunsite.mff.cuni.cz)
@@ -26,6 +26,7 @@
X #include <linux/fs.h>
X #include <linux/file.h>
X #include <linux/fd.h>
+#include <linux/ppp_defs.h>
X #include <linux/if_ppp.h>
X #include <linux/mtio.h>
X #include <linux/cdrom.h>
@@ -35,6 +36,7 @@
X #include <linux/vt_kern.h>
X #include <linux/fb.h>
X #include <linux/ext2_fs.h>
+#include <linux/videodev.h>
X
X #include <scsi/scsi.h>
X /* Ugly hack. */
@@ -117,6 +119,247 @@
X return sys_ioctl(fd, cmd, arg);
X }
X
+struct video_tuner32 {
+ s32 tuner;
+ u8 name[32];
+ u32 rangelow, rangehigh;
+ u32 flags;
+ u16 mode, signal;
+};
+
+static int get_video_tuner32(struct video_tuner *kp, struct video_tuner32 *up)


+{
+ int i;
+

+ if(get_user(kp->tuner, &up->tuner))
+ return -EFAULT;
+ for(i = 0; i < 32; i++)
+ __get_user(kp->name[i], &up->name[i]);
+ __get_user(kp->rangelow, &up->rangelow);
+ __get_user(kp->rangehigh, &up->rangehigh);
+ __get_user(kp->flags, &up->flags);
+ __get_user(kp->mode, &up->mode);
+ __get_user(kp->signal, &up->signal);


+ return 0;
+}
+

+static int put_video_tuner32(struct video_tuner *kp, struct video_tuner32 *up)


+{
+ int i;
+

+ if(put_user(kp->tuner, &up->tuner))
+ return -EFAULT;
+ for(i = 0; i < 32; i++)
+ __put_user(kp->name[i], &up->name[i]);
+ __put_user(kp->rangelow, &up->rangelow);
+ __put_user(kp->rangehigh, &up->rangehigh);
+ __put_user(kp->flags, &up->flags);
+ __put_user(kp->mode, &up->mode);
+ __put_user(kp->signal, &up->signal);


+ return 0;
+}
+

+struct video_buffer32 {
+ /* void * */ u32 base;
+ s32 height, width, depth, bytesperline;
+};
+
+static int get_video_buffer32(struct video_buffer *kp, struct video_buffer32 *up)
+{
+ u32 tmp;
+
+ if(get_user(tmp, &up->base))
+ return -EFAULT;
+ kp->base = (void *) ((unsigned long)tmp);
+ __get_user(kp->height, &up->height);
+ __get_user(kp->width, &up->width);
+ __get_user(kp->depth, &up->depth);
+ __get_user(kp->bytesperline, &up->bytesperline);


+ return 0;
+}
+

+static int put_video_buffer32(struct video_buffer *kp, struct video_buffer32 *up)
+{
+ u32 tmp = (u32)((unsigned long)kp->base);
+
+ if(put_user(tmp, &up->base))
+ return -EFAULT;
+ __put_user(kp->height, &up->height);
+ __put_user(kp->width, &up->width);
+ __put_user(kp->depth, &up->depth);
+ __put_user(kp->bytesperline, &up->bytesperline);


+ return 0;
+}
+

+struct video_clip32 {
+ s32 x, y, width, height;
+ /* struct video_clip32 * */ u32 next;
+};
+
+struct video_window32 {
+ u32 x, y, width, height, chromakey, flags;
+ /* struct video_clip32 * */ u32 clips;
+ s32 clipcount;
+};
+
+static void free_kvideo_clips(struct video_window *kp)
+{
+ struct video_clip *cp;
+
+ cp = kp->clips;
+ if(cp != NULL)
+ kfree(cp);
+}
+
+static int get_video_window32(struct video_window *kp, struct video_window32 *up)
+{
+ struct video_clip32 *ucp;
+ struct video_clip *kcp;
+ int nclips, err, i;
+ u32 tmp;
+
+ if(get_user(kp->x, &up->x))
+ return -EFAULT;
+ __get_user(kp->y, &up->y);
+ __get_user(kp->width, &up->width);
+ __get_user(kp->height, &up->height);
+ __get_user(kp->chromakey, &up->chromakey);
+ __get_user(kp->flags, &up->flags);
+ __get_user(kp->clipcount, &up->clipcount);
+ __get_user(tmp, &up->clips);
+ ucp = (struct video_clip32 *)A(tmp);
+ kp->clips = NULL;
+
+ nclips = kp->clipcount;
+ if(nclips == 0)
+ return 0;
+
+ if(ucp == 0)
+ return -EINVAL;
+
+ /* Peculiar interface... */
+ if(nclips < 0)
+ nclips = VIDEO_CLIPMAP_SIZE;
+
+ kcp = kmalloc(nclips * sizeof(struct video_clip), GFP_KERNEL);
+ err = -ENOMEM;
+ if(kcp == NULL)
+ goto cleanup_and_err;
+
+ kp->clips = kcp;
+ for(i = 0; i < nclips; i++) {
+ __get_user(kcp[i].x, &ucp[i].x);
+ __get_user(kcp[i].y, &ucp[i].y);
+ __get_user(kcp[i].width, &ucp[i].width);
+ __get_user(kcp[i].height, &ucp[i].height);
+ kcp[nclips].next = NULL;
+ }


+
+ return 0;
+

+cleanup_and_err:
+ free_kvideo_clips(kp);
+ return err;
+}
+
+/* You get back everything except the clips... */
+static int put_video_window32(struct video_window *kp, struct video_window32 *up)
+{
+ if(put_user(kp->x, &up->x))
+ return -EFAULT;
+ __put_user(kp->y, &up->y);
+ __put_user(kp->width, &up->width);
+ __put_user(kp->height, &up->height);
+ __put_user(kp->chromakey, &up->chromakey);
+ __put_user(kp->flags, &up->flags);
+ __put_user(kp->clipcount, &up->clipcount);


SHAR_EOF
true || echo 'restore of patch-2.2.8 failed'
fi

echo 'End of part 12'
echo 'File patch-2.2.8 is continued in part 13'
echo 13 > _shar_seq_.tmp

Thomas...@ciw.uni-karlsruhe.de

unread,
May 12, 1999, 3:00:00 AM5/12/99
to
Archive-name: v2.2/patch-2.2.8/part13

#!/bin/sh
# this is part 13 of a 33 - part archive


# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.8 continued
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 13; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.8'
else
echo 'x - continuing with patch-2.2.8'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.8' &&

+ return 0;
+}
+

+#define VIDIOCGTUNER32 _IOWR('v',4, struct video_tuner32)
+#define VIDIOCSTUNER32 _IOW('v',5, struct video_tuner32)
+#define VIDIOCGWIN32 _IOR('v',9, struct video_window32)
+#define VIDIOCSWIN32 _IOW('v',10, struct video_window32)
+#define VIDIOCGFBUF32 _IOR('v',11, struct video_buffer32)
+#define VIDIOCSFBUF32 _IOW('v',12, struct video_buffer32)
+#define VIDIOCGFREQ32 _IOR('v',14, u32)
+#define VIDIOCSFREQ32 _IOW('v',15, u32)
+
+static int do_video_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+ union {
+ struct video_tuner vt;
+ struct video_buffer vb;
+ struct video_window vw;
+ unsigned long vx;
+ } karg;
+ mm_segment_t old_fs = get_fs();
+ void *up = (void *)arg;
+ int err = 0;
+
+ /* First, convert the command. */
+ switch(cmd) {
+ case VIDIOCGTUNER32: cmd = VIDIOCGTUNER; break;
+ case VIDIOCSTUNER32: cmd = VIDIOCSTUNER; break;
+ case VIDIOCGWIN32: cmd = VIDIOCGWIN; break;
+ case VIDIOCSWIN32: cmd = VIDIOCSWIN; break;
+ case VIDIOCGFBUF32: cmd = VIDIOCGFBUF; break;
+ case VIDIOCSFBUF32: cmd = VIDIOCSFBUF; break;
+ case VIDIOCGFREQ32: cmd = VIDIOCGFREQ; break;
+ case VIDIOCSFREQ32: cmd = VIDIOCSFREQ; break;
+ };
+
+ switch(cmd) {
+ case VIDIOCSTUNER:
+ case VIDIOCGTUNER:
+ err = get_video_tuner32(&karg.vt, up);
+ break;
+
+ case VIDIOCSWIN:
+ err = get_video_window32(&karg.vw, up);
+ break;
+
+ case VIDIOCSFBUF:
+ err = get_video_buffer32(&karg.vb, up);
+ break;
+
+ case VIDIOCSFREQ:
+ err = get_user(karg.vx, (u32 *)up);
+ break;
+ };
+ if(err)
+ goto out;
+
+ set_fs(KERNEL_DS);
+ err = sys_ioctl(fd, cmd, (unsigned long)&karg);
+ set_fs(old_fs);
+
+ if(cmd == VIDIOCSWIN)
+ free_kvideo_clips(&karg.vw);
+
+ if(err == 0) {
+ switch(cmd) {
+ case VIDIOCGTUNER:
+ err = put_video_tuner32(&karg.vt, up);
+ break;
+
+ case VIDIOCGWIN:
+ err = put_video_window32(&karg.vw, up);
+ break;
+
+ case VIDIOCGFBUF:
+ err = put_video_buffer32(&karg.vb, up);
+ break;
+
+ case VIDIOCGFREQ:
+ err = put_user(((u32)karg.vx), (u32 *)up);
+ break;
+ };
+ }
+out:


+ return err;
+}
+

X struct timeval32 {
X int tv_sec;
X int tv_usec;
@@ -1600,6 +1843,17 @@
X error = do_ext2_ioctl(fd, cmd, arg);
X goto out;
X
+ case VIDIOCGTUNER32:
+ case VIDIOCSTUNER32:
+ case VIDIOCGWIN32:
+ case VIDIOCSWIN32:
+ case VIDIOCGFBUF32:
+ case VIDIOCSFBUF32:
+ case VIDIOCGFREQ32:
+ case VIDIOCSFREQ32:
+ error = do_video_ioctl(fd, cmd, arg);
+ goto out;
+
X /* List here exlicitly which ioctl's are known to have
X * compatable types passed or none at all...
X */
@@ -1792,6 +2046,33 @@
X /* Little v */
X case VUIDSFORMAT:
X case VUIDGFORMAT:
+
+ /* Little v, the video4linux ioctls */
+ case VIDIOCGCAP:
+ case VIDIOCGCHAN:
+ case VIDIOCSCHAN:
+ case VIDIOCGPICT:
+ case VIDIOCSPICT:
+ case VIDIOCCAPTURE:
+ case VIDIOCKEY:
+ case VIDIOCGAUDIO:
+ case VIDIOCSAUDIO:
+ case VIDIOCSYNC:
+ case VIDIOCMCAPTURE:
+ case VIDIOCGMBUF:
+ case VIDIOCGUNIT:
+ case VIDIOCGCAPTURE:
+ case VIDIOCSCAPTURE:
+
+ /* BTTV specific... */
+ case _IOW('v', BASE_VIDIOCPRIVATE+0, char [256]):
+ case _IOR('v', BASE_VIDIOCPRIVATE+1, char [256]):
+ case _IOR('v' , BASE_VIDIOCPRIVATE+2, unsigned int):
+ case _IOW('v' , BASE_VIDIOCPRIVATE+3, char [16]): /* struct bttv_pll_info */
+ case _IOR('v' , BASE_VIDIOCPRIVATE+4, int):
+ case _IOR('v' , BASE_VIDIOCPRIVATE+5, int):
+ case _IOR('v' , BASE_VIDIOCPRIVATE+6, int):
+ case _IOR('v' , BASE_VIDIOCPRIVATE+7, int):
X
X /* Little p (/dev/rtc, /dev/envctrl, etc.) */
X case RTCGET:
diff -u --recursive --new-file v2.2.7/linux/arch/sparc64/kernel/process.c linux/arch/sparc64/kernel/process.c
--- v2.2.7/linux/arch/sparc64/kernel/process.c Tue Mar 23 14:35:47 1999
+++ linux/arch/sparc64/kernel/process.c Tue May 11 08:24:32 1999
@@ -1,4 +1,4 @@
-/* $Id: process.c,v 1.90 1999/03/22 02:12:16 davem Exp $
+/* $Id: process.c,v 1.92 1999/05/08 23:04:48 davem Exp $
X * arch/sparc64/kernel/process.c
X *
X * Copyright (C) 1995, 1996 David S. Miller (da...@caip.rutgers.edu)
@@ -54,6 +54,8 @@


X /* endless idle loop with no priority at all */
X current->priority = 0;
X current->counter = -100;
+ init_idle();
+
X for (;;) {

X /* If current->need_resched is zero we should really
X * setup for a system wakup event and execute a shutdown
@@ -79,6 +81,8 @@
X {


X current->priority = 0;
X current->counter = -100;
+ init_idle();
+
X while(1) {

X if (current->need_resched != 0) {
X unidle_me();
diff -u --recursive --new-file v2.2.7/linux/arch/sparc64/kernel/smp.c linux/arch/sparc64/kernel/smp.c
--- v2.2.7/linux/arch/sparc64/kernel/smp.c Wed Apr 28 11:37:30 1999
+++ linux/arch/sparc64/kernel/smp.c Tue May 11 08:24:32 1999
@@ -97,7 +97,7 @@
X cpu_data[id].pte_cache = NULL;
X cpu_data[id].pgdcache_size = 0;
X cpu_data[id].pgd_cache = NULL;
- cpu_data[id].idle_volume = 0;
+ cpu_data[id].idle_volume = 1;
X
X for(i = 0; i < 16; i++)
X cpu_data[id].irq_worklists[i] = 0;
@@ -196,6 +196,7 @@
X __sti();
X smp_store_cpu_info(boot_cpu_id);
X smp_tune_scheduling();
+ init_idle();
X

X if(linux_num_cpus == 1)
X return;

@@ -217,6 +218,7 @@
X kernel_thread(start_secondary, NULL, CLONE_PID);


X p = task[++cpucount];
X p->processor = i;
+ p->has_cpu = 1; /* we schedule the first task manually */

X callin_flag = 0;


X for (no = 0; no < linux_num_cpus; no++)

X if (linux_cpus[no].mid == i)
@@ -460,8 +462,6 @@
X mm->cpu_vm_mask = (1UL << smp_processor_id());
X goto local_flush_and_out;
X } else {
- spin_lock(&scheduler_lock);
-
X /* Try to handle two special cases to avoid cross calls
X * in common scenerios where we are swapping process
X * pages out.
@@ -471,16 +471,12 @@
X /* A dead context cannot ever become "alive" until
X * a task switch is done to it.
X */
- spin_unlock(&scheduler_lock);
X return; /* It's dead, nothing to do. */
X }
X if(mm->cpu_vm_mask == (1UL << smp_processor_id())) {
- spin_unlock(&scheduler_lock);
X __flush_tlb_page(ctx, page, SECONDARY_CONTEXT);
X return; /* Only local flush is necessary. */
X }
-
- spin_unlock(&scheduler_lock);
X }
X smp_cross_call(&xcall_flush_tlb_page, ctx, page, 0);
X
diff -u --recursive --new-file v2.2.7/linux/arch/sparc64/kernel/sparc64_ksyms.c linux/arch/sparc64/kernel/sparc64_ksyms.c
--- v2.2.7/linux/arch/sparc64/kernel/sparc64_ksyms.c Tue Mar 23 14:35:47 1999
+++ linux/arch/sparc64/kernel/sparc64_ksyms.c Tue May 11 08:24:32 1999
@@ -1,4 +1,4 @@
-/* $Id: sparc64_ksyms.c,v 1.57 1999/03/14 20:51:28 davem Exp $
+/* $Id: sparc64_ksyms.c,v 1.58 1999/05/08 03:00:31 davem Exp $
X * arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support.
X *
X * Copyright (C) 1996 David S. Miller (da...@caip.rutgers.edu)
@@ -90,7 +90,6 @@
X extern void dump_thread(struct pt_regs *, struct user *);
X
X #ifdef __SMP__
-extern spinlock_t scheduler_lock;
X extern spinlock_t kernel_flag;
X extern int smp_num_cpus;
X #ifdef SPIN_LOCK_DEBUG
@@ -120,7 +119,6 @@
X /* used by various drivers */
X #ifdef __SMP__
X /* Kernel wide locking */
-EXPORT_SYMBOL(scheduler_lock);
X EXPORT_SYMBOL(kernel_flag);
X
X /* Software-IRQ BH locking */
diff -u --recursive --new-file v2.2.7/linux/arch/sparc64/mm/init.c linux/arch/sparc64/mm/init.c
--- v2.2.7/linux/arch/sparc64/mm/init.c Wed Apr 28 11:37:30 1999
+++ linux/arch/sparc64/mm/init.c Tue May 11 08:24:32 1999
@@ -1,4 +1,4 @@
-/* $Id: init.c,v 1.126 1999/04/09 16:16:41 jj Exp $
+/* $Id: init.c,v 1.127 1999/05/08 03:00:38 davem Exp $
X * arch/sparc64/mm/init.c
X *
X * Copyright (C) 1996-1999 David S. Miller (da...@caip.rutgers.edu)
@@ -949,8 +949,7 @@
X #define CTX_BMAP_SLOTS (1UL << (CTX_VERSION_SHIFT - 6))
X unsigned long mmu_context_bmap[CTX_BMAP_SLOTS];
X
-/* We are always protected by scheduler_lock under SMP.
- * Caller does TLB context flushing on local CPU if necessary.
+/* Caller does TLB context flushing on local CPU if necessary.
X *
X * We must be careful about boundary cases so that we never
X * let the user have CTX 0 (nucleus) or we ever use a CTX
diff -u --recursive --new-file v2.2.7/linux/drivers/Makefile linux/drivers/Makefile
--- v2.2.7/linux/drivers/Makefile Wed Apr 28 11:37:30 1999
+++ linux/drivers/Makefile Mon May 10 10:18:34 1999
@@ -47,7 +47,11 @@
X ifeq ($(CONFIG_USB),y)
X SUB_DIRS += usb
X MOD_SUB_DIRS += usb
-endif
+else
+ ifeq ($(CONFIG_USB),m)
+ MOD_SUB_DIRS += usb
+ endif
+endif
X
X # If CONFIG_SCSI is set, the core of SCSI support will be added to the kernel,
X # but some of the low-level things may also be modules.
diff -u --recursive --new-file v2.2.7/linux/drivers/block/Config.in linux/drivers/block/Config.in
--- v2.2.7/linux/drivers/block/Config.in Thu Dec 31 10:28:59 1998
+++ linux/drivers/block/Config.in Thu Apr 29 12:53:48 1999
@@ -51,13 +51,15 @@
X bool ' Winbond SL82c105 support' CONFIG_BLK_DEV_SL82C105
X fi
X fi
- if [ "$CONFIG_PMAC" = "y" ]; then
- define_bool CONFIG_BLK_DEV_IDE_PMAC y
- bool ' PowerMac IDE DMA support' CONFIG_BLK_DEV_IDEDMA_PMAC
- if [ "$CONFIG_BLK_DEV_IDEDMA_PMAC" = "y" ]; then
- define_bool CONFIG_BLK_DEV_IDEDMA y
- bool ' Use DMA by default' CONFIG_PMAC_IDEDMA_AUTO
- fi
+ if [ "$CONFIG_PMAC" = "y" -o "$CONFIG_ALL_PPC" = "y" ]; then
+ bool ' Builtin PowerMac IDE support' CONFIG_BLK_DEV_IDE_PMAC
+ if [ "$CONFIG_BLK_DEV_IDE_PMAC" != "n" ]; then
+ bool ' PowerMac IDE DMA support' CONFIG_BLK_DEV_IDEDMA_PMAC
+ if [ "$CONFIG_BLK_DEV_IDEDMA_PMAC" = "y" ]; then
+ define_bool CONFIG_BLK_DEV_IDEDMA y
+ bool ' Use DMA by default' CONFIG_PMAC_IDEDMA_AUTO
+ fi
+ fi
X fi
X bool ' Other IDE chipset support' CONFIG_IDE_CHIPSETS
X if [ "$CONFIG_IDE_CHIPSETS" = "y" ]; then
diff -u --recursive --new-file v2.2.7/linux/drivers/block/ide-cd.h linux/drivers/block/ide-cd.h
--- v2.2.7/linux/drivers/block/ide-cd.h Wed Apr 28 11:37:30 1999
+++ linux/drivers/block/ide-cd.h Tue May 11 10:35:45 1999
@@ -363,7 +363,7 @@
X #endif
X
X #if defined(__BIG_ENDIAN_BITFIELD)
- __u8 reserved4 : 4;
+ __u8 reserved4 : 1;
X /* Drive can read multisession discs. */
X __u8 multisession : 1;
X /* Drive can read mode 2, form 2 data. */
diff -u --recursive --new-file v2.2.7/linux/drivers/block/ide.c linux/drivers/block/ide.c
--- v2.2.7/linux/drivers/block/ide.c Tue Mar 23 14:35:47 1999
+++ linux/drivers/block/ide.c Mon May 3 09:34:51 1999
@@ -813,7 +813,7 @@
X ide_end_drive_cmd(drive, stat, err);
X return;
X }
- if (stat & BUSY_STAT) { /* other bits are useless when BUSY */
+ if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) { /* other bits are useless when BUSY */
X rq->errors |= ERROR_RESET;
X } else {
X if (drive->media == ide_disk && (stat & ERR_STAT)) {
diff -u --recursive --new-file v2.2.7/linux/drivers/block/rd.c linux/drivers/block/rd.c
--- v2.2.7/linux/drivers/block/rd.c Wed Apr 28 11:37:30 1999
+++ linux/drivers/block/rd.c Thu Apr 29 11:53:41 1999
@@ -33,11 +33,13 @@
X *
X * Added initrd: Werner Almesberger & Hans Lermen, Feb '96
X *
-* 4/25/96 : Made RAM disk size a parameter (default is now 4 MB)
+ * 4/25/96 : Made RAM disk size a parameter (default is now 4 MB)
X * - Chad Page
X *
X * Add support for fs images split across >1 disk, Paul Gortmaker, Mar '98
X *
+ * Make block size and block size shift for RAM disks a global macro
+ * and set blk_size for -ENOSPC, Werner Fink <wer...@suse.de>, Apr '99
X */
X
X #include <linux/config.h>
@@ -47,6 +49,7 @@
X #include <linux/romfs_fs.h>
X #include <linux/fs.h>
X #include <linux/kernel.h>
+#include <linux/hdreg.h>
X #include <linux/string.h>
X #include <linux/mm.h>
X #include <linux/mman.h>
@@ -70,6 +73,15 @@
X #define MAJOR_NR RAMDISK_MAJOR
X #include <linux/blk.h>
X
+/*
+ * We use a block size of 512 bytes in comparision to BLOCK_SIZE
+ * defined in include/linux/blk.h. This because of the finer
+ * granularity for filling up a RAM disk.
+ */
+#define RDBLK_SIZE_BITS 9
+#define RDBLK_SIZE (1<<RDBLK_SIZE_BITS)
+
+
X /* The RAM disk size is now a parameter */
X #define NUM_RAMDISKS 16 /* This cannot be overridden (yet) */
X
@@ -89,8 +101,10 @@
X /* Various static variables go here. Most are used only in the RAM disk code.
X */
X
-static int rd_length[NUM_RAMDISKS];
-static int rd_blocksizes[NUM_RAMDISKS];
+static unsigned long rd_length[NUM_RAMDISKS]; /* Size of RAM disks in bytes */
+static int rd_hardsec[NUM_RAMDISKS]; /* Size of real blocks in bytes */
+static int rd_blocksizes[NUM_RAMDISKS]; /* Size of 1024 byte blocks :) */
+static int rd_kbsize[NUM_RAMDISKS]; /* Size in blocks of 1024 bytes */
X
X /*
X * Parameters for the boot-loading of the RAM disk. These are set by
@@ -120,9 +134,12 @@
X static void rd_request(void)
X {
X unsigned int minor;
- int offset, len;
+ unsigned long offset, len;
X
X repeat:
+ if (!CURRENT)
+ return;
+
X INIT_REQUEST;
X
X minor = MINOR(CURRENT->rq_dev);
@@ -132,14 +149,20 @@
X goto repeat;
X }
X
- offset = CURRENT->sector << 9;
- len = CURRENT->current_nr_sectors << 9;
+ offset = CURRENT->sector << RDBLK_SIZE_BITS;
+ len = CURRENT->current_nr_sectors << RDBLK_SIZE_BITS;
X
X if ((offset + len) > rd_length[minor]) {
X end_request(0);
X goto repeat;
X }
X
+ if ((CURRENT->cmd != READ) && (CURRENT->cmd != WRITE)) {
+ printk(KERN_INFO "RAMDISK: bad command: %d\n", CURRENT->cmd);
+ end_request(0);
+ goto repeat;
+ }
+
X /*
X * If we're reading, fill the buffer with 0's. This is okay since
X * we're using protected buffers which should never get freed...
@@ -158,24 +181,31 @@
X
X static int rd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
X {
+ unsigned int minor;
+
X if (!inode || !inode->i_rdev)
X return -EINVAL;
X
+ minor = MINOR(inode->i_rdev);
+
X switch (cmd) {
X case BLKFLSBUF:
X if (!capable(CAP_SYS_ADMIN)) return -EACCES;
X invalidate_buffers(inode->i_rdev);
X break;
+
X case BLKGETSIZE: /* Return device size */
X if (!arg) return -EINVAL;
- return put_user(rd_length[MINOR(inode->i_rdev)] / 512,
- (long *) arg);
- case BLKSSZGET:
- /* Block size of media */
- return put_user(rd_blocksizes[MINOR(inode->i_rdev)],
- (int *)arg);
+ return put_user(rd_length[minor] >> RDBLK_SIZE_BITS, (long *) arg);
+
+ case BLKSSZGET: /* Block size of media */
+ if (!arg) return -EINVAL;
+ return put_user(rd_blocksizes[minor], (int *)arg);
+
+ RO_IOCTLS(inode->i_rdev, arg);
+
X default:
- break;
+ return -EINVAL;
X };
X
X return 0;
@@ -263,7 +293,7 @@
X rd_open, /* open */
X NULL, /* flush */
X rd_release, /* module needs to decrement use count */
- block_fsync /* fsync */
+ block_fsync /* fsync */
X };
X
X /* This is the registration and initialization section of the RAM disk driver */
@@ -279,11 +309,16 @@
X blk_dev[MAJOR_NR].request_fn = &rd_request;
X
X for (i = 0; i < NUM_RAMDISKS; i++) {
- rd_length[i] = (rd_size * 1024);
- rd_blocksizes[i] = 1024;
+ /* rd_size is given in kB */
+ rd_length[i] = (rd_size << BLOCK_SIZE_BITS);
+ rd_hardsec[i] = RDBLK_SIZE;
+ rd_blocksizes[i] = BLOCK_SIZE;
+ rd_kbsize[i] = (rd_length[i] >> BLOCK_SIZE_BITS);
X }
X
- blksize_size[MAJOR_NR] = rd_blocksizes;
+ hardsect_size[MAJOR_NR] = rd_hardsec; /* Size of the RAM disk blocks */
+ blksize_size[MAJOR_NR] = rd_blocksizes; /* Avoid set_blocksize() check */
+ blk_size[MAJOR_NR] = rd_kbsize; /* Size of the RAM disk in kB */
X
X printk("RAM disk driver initialized: %d RAM disks of %dK size\n",
X NUM_RAMDISKS, rd_size);
@@ -295,7 +330,8 @@
X
X #ifdef MODULE
X
-MODULE_PARM (rd_size, "1i");
+MODULE_PARM (rd_size, "1i");
+MODULE_PARM_DESC(rd_size, "Size of each RAM disk.");
X
X int init_module(void)
X {
@@ -427,7 +463,7 @@
X /*
X * This routine loads in the RAM disk image.
X */
-__initfunc(static void rd_load_image(kdev_t device,int offset))
+__initfunc(static void rd_load_image(kdev_t device, int offset, int unit))
X {
X struct inode inode, out_inode;
X struct file infile, outfile;
@@ -440,7 +476,7 @@
X unsigned short devblocks = 0;
X char rotator[4] = { '|' , '/' , '-' , '\\' };
X
- ram_device = MKDEV(MAJOR_NR, 0);
+ ram_device = MKDEV(MAJOR_NR, unit);
X
X memset(&infile, 0, sizeof(infile));
X memset(&inode, 0, sizeof(inode));
@@ -480,9 +516,9 @@
X goto done;
X }
X
- if (nblocks > (rd_length[0] >> BLOCK_SIZE_BITS)) {
+ if (nblocks > (rd_length[unit] >> RDBLK_SIZE_BITS)) {
X printk("RAMDISK: image too big! (%d/%d blocks)\n",
- nblocks, rd_length[0] >> BLOCK_SIZE_BITS);
+ nblocks, rd_length[unit] >> RDBLK_SIZE_BITS);
X goto done;
X }
X
@@ -538,7 +574,7 @@
X
X successful_load:
X invalidate_buffers(device);
- ROOT_DEV = MKDEV(MAJOR_NR,0);
+ ROOT_DEV = MKDEV(MAJOR_NR, unit);
X
X done:
X if (infile.f_op->release)
@@ -547,12 +583,21 @@
X }
X
X
-__initfunc(void rd_load(void))
+__initfunc(static void rd_load_disk(int n))
X {
+#ifdef CONFIG_BLK_DEV_INITRD
+ extern kdev_t real_root_dev;
+#endif
+
X if (rd_doload == 0)
X return;
-
- if (MAJOR(ROOT_DEV) != FLOPPY_MAJOR) return;
+
+ if (MAJOR(ROOT_DEV) != FLOPPY_MAJOR
+#ifdef CONFIG_BLK_DEV_INITRD
+ && MAJOR(real_root_dev) != FLOPPY_MAJOR
+#endif
+ )
+ return;
X
X if (rd_prompt) {
X #ifdef CONFIG_BLK_DEV_FD
@@ -563,15 +608,24 @@
X wait_for_keypress();
X }
X
- rd_load_image(ROOT_DEV,rd_image_start);
+ rd_load_image(ROOT_DEV,rd_image_start, n);
X
X }
X
+__initfunc(void rd_load(void))
+{
+ rd_load_disk(0);
+}
+
+__initfunc(void rd_load_secondary(void))
+{
+ rd_load_disk(1);
+}
X
X #ifdef CONFIG_BLK_DEV_INITRD
X __initfunc(void initrd_load(void))
X {
- rd_load_image(MKDEV(MAJOR_NR, INITRD_MINOR),0);
+ rd_load_image(MKDEV(MAJOR_NR, INITRD_MINOR),0,0);
X }
X #endif
X
@@ -695,7 +749,14 @@
X crd_load(struct file * fp, struct file *outfp))
X {
X int result;
-
+
+ insize = 0; /* valid bytes in inbuf */
+ inptr = 0; /* index of next byte to be processed in inbuf */
+ outcnt = 0; /* bytes in output buffer */
+ exit_code = 0;
+ bytes_out = 0;
+ crc = (ulg)0xffffffffL; /* shift register contents */
+
X crd_infp = fp;
X crd_outfp = outfp;
X inbuf = kmalloc(INBUFSIZ, GFP_KERNEL);
diff -u --recursive --new-file v2.2.7/linux/drivers/cdrom/cdrom.c linux/drivers/cdrom/cdrom.c
--- v2.2.7/linux/drivers/cdrom/cdrom.c Tue Mar 23 14:35:47 1999
+++ linux/drivers/cdrom/cdrom.c Thu Apr 29 11:53:41 1999
@@ -120,11 +120,16 @@
X 2.54 Mar 15, 1999 - Jens Axboe <ax...@image.dk>
X -- Check capability mask from low level driver when counting tracks as
X per suggestion from Corey J. Scotts <cst...@blue.weeg.uiowa.edu>.
+
+ 2.55 Apr 25, 1999 - Jens Axboe <ax...@image.dk>
+ -- autoclose was mistakenly checked against CDC_OPEN_TRAY instead of
+ CDC_CLOSE_TRAY.
+ -- proc info didn't mask against capabilities mask.
X
X -------------------------------------------------------------------------*/
X
-#define REVISION "Revision: 2.54"
-#define VERSION "Id: cdrom.c 2.54 1999/03/15"
+#define REVISION "Revision: 2.55"
+#define VERSION "Id: cdrom.c 2.55 1999/04/25"
X
X /* I use an error-log mask to give fine grain control over the type of
X messages dumped to the system logs. The available masks include: */
@@ -268,7 +273,7 @@
X cdo->n_minors = 0;
X cdi->options = CDO_USE_FFLAGS;
X
- if (autoclose==1 && cdo->capability & ~cdi->mask & CDC_OPEN_TRAY)
+ if (autoclose==1 && cdo->capability & ~cdi->mask & CDC_CLOSE_TRAY)
X cdi->options |= (int) CDO_AUTO_CLOSE;
X if (autoeject==1 && cdo->capability & ~cdi->mask & CDC_OPEN_TRAY)
X cdi->options |= (int) CDO_AUTO_EJECT;
@@ -1097,27 +1102,27 @@
X pos += sprintf(cdrom_drive_info+pos, "\nCan close tray:\t");
X for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
X pos += sprintf(cdrom_drive_info+pos, "\t%d",
- ((cdi->ops->capability & CDC_CLOSE_TRAY)!=0));
+ ((cdi->ops->capability & ~cdi->mask & CDC_CLOSE_TRAY)!=0));
X
X pos += sprintf(cdrom_drive_info+pos, "\nCan open tray:\t");
X for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
X pos += sprintf(cdrom_drive_info+pos, "\t%d",
- ((cdi->ops->capability & CDC_OPEN_TRAY)!=0));
+ ((cdi->ops->capability & ~cdi->mask & CDC_OPEN_TRAY)!=0));
X
X pos += sprintf(cdrom_drive_info+pos, "\nCan lock tray:\t");
X for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
X pos += sprintf(cdrom_drive_info+pos, "\t%d",
- ((cdi->ops->capability & CDC_LOCK)!=0));
+ ((cdi->ops->capability & ~cdi->mask & CDC_LOCK)!=0));
X
X pos += sprintf(cdrom_drive_info+pos, "\nCan change speed:");
X for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
X pos += sprintf(cdrom_drive_info+pos, "\t%d",
- ((cdi->ops->capability & CDC_SELECT_SPEED)!=0));
+ ((cdi->ops->capability & ~cdi->mask & CDC_SELECT_SPEED)!=0));
X
X pos += sprintf(cdrom_drive_info+pos, "\nCan select disk:");
X for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
X pos += sprintf(cdrom_drive_info+pos, "\t%d",
- ((cdi->ops->capability & CDC_SELECT_DISC)!=0));
+ ((cdi->ops->capability & ~cdi->mask & CDC_SELECT_DISC)!=0));
X
X pos += sprintf(cdrom_drive_info+pos, "\nCan read multisession:");
X for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
@@ -1137,7 +1142,7 @@
X pos += sprintf(cdrom_drive_info+pos, "\nCan play audio:\t");
X for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
X pos += sprintf(cdrom_drive_info+pos, "\t%d",
- ((cdi->ops->capability & CDC_PLAY_AUDIO)!=0));
+ ((cdi->ops->capability & ~cdi->mask & CDC_PLAY_AUDIO)!=0));
X
X strcpy(cdrom_drive_info+pos,"\n\n");
X *lenp=pos+3;
diff -u --recursive --new-file v2.2.7/linux/drivers/cdrom/mcdx.h linux/drivers/cdrom/mcdx.h
--- v2.2.7/linux/drivers/cdrom/mcdx.h Wed Jan 20 23:14:05 1999
+++ linux/drivers/cdrom/mcdx.h Thu Apr 29 11:53:41 1999
@@ -176,8 +176,10 @@
X #define MCDX_ST_DRV 0x00ff /* mask to query the drive status */
X
X #ifndef I_WAS_HERE
+#ifndef MODULE
X #warning You have not edited mcdx.h
X #warning Perhaps irq and i/o settings are wrong.
+#endif
X #endif
X
X /* ex:set ts=4 sw=4: */
diff -u --recursive --new-file v2.2.7/linux/drivers/char/Config.in linux/drivers/char/Config.in
--- v2.2.7/linux/drivers/char/Config.in Fri Apr 16 14:47:30 1999
+++ linux/drivers/char/Config.in Fri May 7 11:05:30 1999
@@ -137,6 +137,9 @@
X dep_tristate 'Colour QuickCam Video For Linux (EXPERIMENTAL)' CONFIG_VIDEO_CQCAM $CONFIG_VIDEO_DEV $CONFIG_PARPORT
X fi
X dep_tristate 'Mediavision Pro Movie Studio Video For Linux' CONFIG_VIDEO_PMS $CONFIG_VIDEO_DEV
+ if [ "$CONFIG_PMAC" = "y" ]; then
+ dep_tristate 'PlanB Video-In on PowerMac' CONFIG_VIDEO_PLANB $CONFIG_VIDEO_DEV
+ fi
X dep_tristate 'SAA5249 Teletext processor' CONFIG_VIDEO_SAA5249 $CONFIG_VIDEO_DEV
X dep_tristate 'SF16FMI Radio' CONFIG_RADIO_SF16FMI $CONFIG_VIDEO_DEV
X if [ "$CONFIG_RADIO_SF16FMI" = "y" ]; then
diff -u --recursive --new-file v2.2.7/linux/drivers/char/Makefile linux/drivers/char/Makefile
--- v2.2.7/linux/drivers/char/Makefile Wed Apr 28 11:37:30 1999
+++ linux/drivers/char/Makefile Fri May 7 11:05:30 1999
@@ -283,12 +283,12 @@
X endif
X
X ifeq ($(CONFIG_NVRAM),y)
- ifeq ($(CONFIG_PMAC)$(CONFIG_CHRP),)
+ ifeq ($(CONFIG_PPC),)
X L_OBJS += nvram.o
X endif
X else
X ifeq ($(CONFIG_NVRAM),m)
- ifeq ($(CONFIG_PMAC)$(CONFIG_CHRP),)
+ ifeq ($(CONFIG_PPC),)
X M_OBJS += nvram.o
X endif
X endif
@@ -351,6 +351,14 @@
X else
X ifeq ($(CONFIG_VIDEO_PMS),m)
X M_OBJS += pms.o
+ endif
+endif
+
+ifeq ($(CONFIG_VIDEO_PLANB),y)
+L_OBJS += planb.o
+else
+ ifeq ($(CONFIG_VIDEO_PLANB),m)
+ M_OBJS += planb.o
X endif
X endif
X
diff -u --recursive --new-file v2.2.7/linux/drivers/char/adbmouse.c linux/drivers/char/adbmouse.c
--- v2.2.7/linux/drivers/char/adbmouse.c Thu Nov 19 09:56:28 1998
+++ linux/drivers/char/adbmouse.c Thu Apr 29 12:53:48 1999
@@ -113,7 +113,7 @@
X * on a logitech mouseman, the right and mid buttons sometimes behave
X * strangely until they both have been pressed after booting. */
X /* data valid only if extended mouse format ! */
- if (nb == 4)
+ if (nb >= 4)
X buttons = (buttons&6) | (buf[3] & 0x80 ? 1 : 0); /* 1+3 unchanged */
X
X add_mouse_randomness(((~buttons&7) << 16) + ((buf[2]&0x7f) << 8) + (buf[1]&0x7f));
diff -u --recursive --new-file v2.2.7/linux/drivers/char/isicom.c linux/drivers/char/isicom.c
--- v2.2.7/linux/drivers/char/isicom.c Fri Apr 16 14:47:30 1999
+++ linux/drivers/char/isicom.c Fri May 7 11:05:30 1999
@@ -13,6 +13,23 @@
X * (fixed range check bug as a side effect)
X * Printk clean up
X * 9/12/98 al...@redhat.com Rough port to 2.1.x
+ *
+ *
+ * ***********************************************************
+ *
+ * To use this driver you also need the support package. You
+ * can find this in RPM format on
+ * ftp://ftp.linux.org.uk/pub/linux/alan
+ *
+ * You can find the original tools for this direct from Multitech
+ * ftp://ftp.multitech.com/ISI-Cards/
+ *
+ * Having installed the cards the module options (/etc/conf.modules)
+ *
+ * options isicom io=card1,card2,card3,card4 irq=card1,card2,card3,card4
+ *
+ * Omit those entries for boards you don't have installed.
+ *
X */
X
X #include <linux/module.h>
diff -u --recursive --new-file v2.2.7/linux/drivers/char/lp.c linux/drivers/char/lp.c
--- v2.2.7/linux/drivers/char/lp.c Tue Mar 23 14:35:47 1999
+++ linux/drivers/char/lp.c Mon May 10 10:26:31 1999
@@ -202,9 +202,7 @@
X /* Test if the printer is not acking the strobe */
X #define LP_NO_ACKING(status) ((status) & LP_PACK)
X /* Test if the printer has error conditions */
-#define LP_NO_ERROR(status) \
- (((status) & (LP_POUTPA|LP_PSELECD|LP_PERRORP)) == \
- (LP_PSELECD|LP_PERRORP))
+#define LP_NO_ERROR(status) ((status) & LP_PERRORP)
X
X #undef LP_DEBUG
X #undef LP_READ_DEBUG
@@ -424,7 +422,10 @@
X {
X unsigned int last = lp_table[minor].last_error;
X unsigned char status = r_str(minor);
- if ((status & LP_POUTPA)) {
+ if (status & LP_PERRORP)
+ /* No error. */
+ last = 0;
+ else if ((status & LP_POUTPA)) {
X if (last != LP_POUTPA) {
X last = LP_POUTPA;
X printk(KERN_INFO "lp%d out of paper\n", minor);
@@ -434,13 +435,12 @@
X last = LP_PSELECD;
X printk(KERN_INFO "lp%d off-line\n", minor);
X }
- } else if (!(status & LP_PERRORP)) {
+ } else {
X if (last != LP_PERRORP) {
X last = LP_PERRORP;
- printk(KERN_INFO "lp%d on fire!\n", minor);
+ printk(KERN_INFO "lp%d on fire\n", minor);
X }
X }
- else last = 0;
X
X lp_table[minor].last_error = last;
X
diff -u --recursive --new-file v2.2.7/linux/drivers/char/mem.c linux/drivers/char/mem.c
--- v2.2.7/linux/drivers/char/mem.c Wed Apr 28 11:37:30 1999
+++ linux/drivers/char/mem.c Mon May 10 10:18:34 1999
@@ -57,7 +57,10 @@
X #ifdef CONFIG_USB_OHCI
X int ohci_init(void);
X #endif
-
+#ifdef CONFIG_USB_OHCI_HCD
+int ohci_hcd_init(void);
+#endif
+
X static ssize_t do_write_mem(struct file * file, void *p, unsigned long realp,
X const char * buf, size_t count, loff_t *ppos)
X {
@@ -605,11 +608,16 @@
X if (register_chrdev(MEM_MAJOR,"mem",&memory_fops))
X printk("unable to get major %d for memory devs\n", MEM_MAJOR);
X rand_initialize();
+#ifdef CONFIG_USB
X #ifdef CONFIG_USB_UHCI
X uhci_init();
X #endif
X #ifdef CONFIG_USB_OHCI
X ohci_init();
+#endif
+#ifdef CONFIG_USB_OHCI_HCD
+ ohci_hcd_init();
+#endif
X #endif
X #if defined (CONFIG_FB)
X fbmem_init();
diff -u --recursive --new-file v2.2.7/linux/drivers/char/planb.c linux/drivers/char/planb.c
--- v2.2.7/linux/drivers/char/planb.c Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/planb.c Mon May 10 10:17:28 1999
@@ -0,0 +1,2389 @@
+/*
+ planb - PlanB frame grabber driver
+
+ PlanB is used in the 7x00/8x00 series of PowerMacintosh
+ Computers as video input DMA controller.
+
+ Copyright (C) 1998 Michel Lanners (ml...@cpu.lu)
+
+ Based largely on the bttv driver by Ralph Metzler (rj...@thp.uni-koeln.de)
+
+ Additional debugging and coding by Takashi Oe (t...@unlinfo.unl.edu)
+ (Some codes are stolen from proposed v4l2 videodev.c
+ of Bill Dirks <di...@rendition.com>)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/* $Id: planb.c,v 1.18 1999/05/02 17:36:34 mlan Exp $ */
+
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/malloc.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/vmalloc.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/wrapper.h>
+#include <linux/tqueue.h>
+#include <linux/videodev.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/dbdma.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/irq.h>
+
+#include "planb.h"
+#include "saa7196.h"
+
+
+/* Would you mind for some ugly debugging? */
+//#define DEBUG(x...) printk(KERN_DEBUG ## x) /* Debug driver */
+#define DEBUG(x...) /* Don't debug driver */
+//#define IDEBUG(x...) printk(KERN_DEBUG ## x) /* Debug interrupt part */
+#define IDEBUG(x...) /* Don't debug interrupt part */
+
+/* Ever seen a Mac with more than 1 of these? */
+#define PLANB_MAX 1
+
+static int planb_num;
+static struct planb planbs[PLANB_MAX];
+static volatile struct planb_registers *planb_regs;
+
+static int def_norm = PLANB_DEF_NORM; /* default norm */
+
+MODULE_PARM(def_norm, "i");
+MODULE_PARM_DESC(def_norm, "Default startup norm (0=PAL, 1=NTSC, 2=SECAM)");
+
+/* ------------------ PlanB Exported Functions ------------------ */
+static long planb_write(struct video_device *, const char *, unsigned long, int);
+static long planb_read(struct video_device *, char *, unsigned long, int);
+static int planb_open(struct video_device *, int);
+static void planb_close(struct video_device *);
+static int planb_ioctl(struct video_device *, unsigned int, void *);
+static int planb_init_done(struct video_device *);
+static int planb_mmap(struct video_device *, const char *, unsigned long);
+static void planb_irq(int, void *, struct pt_regs *);
+static void release_planb(void);
+int init_planbs(struct video_init *);
+
+/* ------------------ PlanB Internal Functions ------------------ */
+static int planb_prepare_open(struct planb *);
+static void planb_prepare_close(struct planb *);
+static void saa_write_reg(unsigned char, unsigned char);
+static unsigned char saa_status(int, struct planb *);
+static void saa_set(unsigned char, unsigned char, struct planb *);
+static void saa_init_regs(struct planb *);
+static void * rvmalloc(unsigned long);
+static void rvfree(void *, unsigned long);
+static unsigned long vmalloc_to_bus(void *);
+static unsigned long vmalloc_to_phys(void *);
+static int fbuffer_alloc(struct planb *);
+static int vgrab(struct planb *, struct video_mmap *);
+static void add_clip(struct planb *, struct video_clip *);
+static void fill_cmd_buff(struct planb *);
+static void cmd_buff(struct planb *);
+static volatile struct dbdma_cmd *setup_grab_cmd(int, struct planb *);
+static void overlay_start(struct planb *);
+static void overlay_stop(struct planb *);
+static inline void tab_cmd_dbdma(volatile struct dbdma_cmd *, unsigned short,
+ unsigned int);
+static inline void tab_cmd_store(volatile struct dbdma_cmd *, unsigned int,
+ unsigned int);
+static inline void tab_cmd_gen(volatile struct dbdma_cmd *, unsigned short,
+ unsigned short, unsigned int, unsigned int);
+static int init_planb(struct planb *);
+static int find_planb(void);
+static void planb_pre_capture(int, int, struct planb *);
+static volatile struct dbdma_cmd *cmd_geo_setup(volatile struct dbdma_cmd *,
+ int, int, int, int, int, struct planb *);
+static inline void planb_dbdma_stop(volatile struct dbdma_regs *);
+static unsigned int saa_geo_setup(int, int, int, int, struct planb *);
+static inline int overlay_is_active(struct planb *);
+
+/*******************************/
+/* Memory management functions */
+/*******************************/
+
+static void * rvmalloc(unsigned long size)
+{
+ void *mem, *memptr;
+ unsigned long page;
+
+ mem=vmalloc(size);
+ if (mem)
+ {
+ memset(mem, 0, size); /* Clear the ram out, leave no junk */
+ memptr = mem;
+ while (size > 0)
+ {
+ page = vmalloc_to_phys(memptr);
+ mem_map_reserve(MAP_NR(phys_to_virt(page)));
+ memptr+=PAGE_SIZE;
+ size-=PAGE_SIZE;
+ }
+ }
+ return mem;
+}
+
+static void rvfree(void * mem, unsigned long size)
+{
+ void *memptr;
+ unsigned long page;
+
+ if (mem)
+ {
+ memptr = mem;
+ while (size > 0)
+ {
+ page = vmalloc_to_phys(memptr);
+ mem_map_unreserve(MAP_NR(phys_to_virt(page)));
+ memptr += PAGE_SIZE;
+ size-=PAGE_SIZE;
+ }
+ vfree(mem);
+ }
+}
+
+/* Useful for using vmalloc()ed memory as DMA target */
+static unsigned long vmalloc_to_bus(void *virt)
+{
+ pgd_t *pgd;
+ pmd_t *pmd;
+ pte_t *pte;
+ unsigned long a = (unsigned long)virt;
+
+ if (pgd_none(*(pgd = pgd_offset(current->mm, a))) ||
+ pmd_none(*(pmd = pmd_offset(pgd, a))) ||
+ pte_none(*(pte = pte_offset(pmd, a))))
+ return 0;
+ return virt_to_bus((void *)pte_page(*pte))
+ + (a & (PAGE_SIZE - 1));
+}
+
+static unsigned long vmalloc_to_phys(void *virt) {
+ return virt_to_phys(bus_to_virt(vmalloc_to_bus(virt)));
+}
+
+/*
+ * Create the giant waste of buffer space we need for now
+ * until we get DMA to user space sorted out (probably 2.3.x)
+ *
+ * We only create this as and when someone uses mmap
+ */
+
+static int fbuffer_alloc(struct planb *pb)
+{
+ if(!pb->fbuffer)
+ pb->fbuffer=(unsigned char *) rvmalloc(MAX_GBUFFERS
+ * PLANB_MAX_FBUF);
+ else
+ printk(KERN_ERR "PlanB: Double alloc of fbuffer!\n");
+ if(!pb->fbuffer)
+ return -ENOBUFS;


+ return 0;
+}
+

+/*****************************/
+/* Hardware access functions */
+/*****************************/
+
+static void saa_write_reg(unsigned char addr, unsigned char val)
+{
+ planb_regs->saa_addr = addr; eieio();
+ planb_regs->saa_regval = val; eieio();
+ return;
+}
+
+/* return status byte 0 or 1: */
+static unsigned char saa_status(int byte, struct planb *pb)
+{
+ saa_regs[pb->win.norm][SAA7196_STDC] =
+ (saa_regs[pb->win.norm][SAA7196_STDC] & ~2) | ((byte & 1) << 1);
+ saa_write_reg (SAA7196_STDC, saa_regs[pb->win.norm][SAA7196_STDC]);
+
+ /* Let's wait 30msec for this one */
+ current->state = TASK_INTERRUPTIBLE;
+#if LINUX_VERSION_CODE >= 0x02017F
+ schedule_timeout(30 * HZ / 1000);
+#else
+ current->timeout = jiffies + 30 * HZ / 1000; /* 30 ms */;
+ schedule();
+#endif
+
+ return (unsigned char)in_8 (&planb_regs->saa_status);
+}
+
+static void saa_set(unsigned char addr, unsigned char val, struct planb *pb)
+{
+ if(saa_regs[pb->win.norm][addr] != val) {
+ saa_regs[pb->win.norm][addr] = val;
+ saa_write_reg (addr, val);


+ }
+ return;
+}
+

+static void saa_init_regs(struct planb *pb)


+{
+ int i;
+

+ for (i = 0; i < SAA7196_NUMREGS; i++)
+ saa_write_reg (i, saa_regs[pb->win.norm][i]);
+}
+
+static unsigned int saa_geo_setup(int width, int height, int interlace, int bpp,
+ struct planb *pb)
+{
+ int ht, norm = pb->win.norm;
+
+ switch(bpp) {
+ case 2:
+ /* RGB555+a 1x16-bit + 16-bit transparent */
+ saa_regs[norm][SAA7196_FMTS] &= ~0x3;
+ break;
+ case 1:
+ case 4:
+ /* RGB888 1x24-bit + 8-bit transparent */
+ saa_regs[norm][SAA7196_FMTS] &= ~0x1;
+ saa_regs[norm][SAA7196_FMTS] |= 0x2;
+ break;
+ default:
+ return -EINVAL;
+ }
+ ht = (interlace ? height / 2 : height);
+ saa_regs[norm][SAA7196_OUTPIX] = (unsigned char) (width & 0x00ff);
+ saa_regs[norm][SAA7196_HFILT] = (saa_regs[norm][SAA7196_HFILT] & ~0x3)
+ | (width >> 8 & 0x3);
+ saa_regs[norm][SAA7196_OUTLINE] = (unsigned char) (ht & 0xff);
+ saa_regs[norm][SAA7196_VYP] = (saa_regs[norm][SAA7196_VYP] & ~0x3)
+ | (ht >> 8 & 0x3);
+ /* feed both fields if interlaced, or else feed only even fields */
+ saa_regs[norm][SAA7196_FMTS] = (interlace) ?
+ (saa_regs[norm][SAA7196_FMTS] & ~0x60)
+ : (saa_regs[norm][SAA7196_FMTS] | 0x60);
+ /* transparent mode; extended format enabled */
+ saa_regs[norm][SAA7196_DPATH] |= 0x3;


+
+ return 0;
+}
+

+/***************************/
+/* DBDMA support functions */
+/***************************/
+
+static inline void planb_dbdma_restart(volatile struct dbdma_regs *ch)
+{
+ out_le32(&ch->control, PLANB_CLR(RUN));
+ out_le32(&ch->control, PLANB_SET(RUN|WAKE) | PLANB_CLR(PAUSE));
+}
+
+static inline void planb_dbdma_stop(volatile struct dbdma_regs *ch)
+{
+ int i = 0;
+
+ out_le32(&ch->control, PLANB_CLR(RUN) | PLANB_SET(FLUSH));
+ while((in_le32(&ch->status) == (ACTIVE | FLUSH)) && (i < 999)) {
+ IDEBUG("PlanB: waiting for DMA to stop\n");
+ i++;
+ }
+}
+
+static inline void tab_cmd_dbdma(volatile struct dbdma_cmd *ch,
+ unsigned short command, unsigned int cmd_dep)
+{
+ st_le16(&ch->command, command);
+ st_le32(&ch->cmd_dep, cmd_dep);
+}
+
+static inline void tab_cmd_store(volatile struct dbdma_cmd *ch,
+ unsigned int phy_addr, unsigned int cmd_dep)
+{
+ st_le16(&ch->command, STORE_WORD | KEY_SYSTEM);
+ st_le16(&ch->req_count, 4);
+ st_le32(&ch->phy_addr, phy_addr);
+ st_le32(&ch->cmd_dep, cmd_dep);
+}
+
+static inline void tab_cmd_gen(volatile struct dbdma_cmd *ch,
+ unsigned short command, unsigned short req_count,
+ unsigned int phy_addr, unsigned int cmd_dep)
+{
+ st_le16(&ch->command, command);
+ st_le16(&ch->req_count, req_count);
+ st_le32(&ch->phy_addr, phy_addr);
+ st_le32(&ch->cmd_dep, cmd_dep);
+}
+
+static volatile struct dbdma_cmd *cmd_geo_setup(
+ volatile struct dbdma_cmd *c1, int width, int height, int interlace,
+ int bpp, int clip, struct planb *pb)
+{
+ int norm = pb->win.norm;
+
+ if((saa_geo_setup(width, height, interlace, bpp, pb)) != 0)
+ return (volatile struct dbdma_cmd *)NULL;
+ tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->saa_addr),
+ SAA7196_FMTS);
+ tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->saa_regval),
+ saa_regs[norm][SAA7196_FMTS]);
+ tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->saa_addr),
+ SAA7196_DPATH);
+ tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->saa_regval),
+ saa_regs[norm][SAA7196_DPATH]);
+ tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->even),
+ bpp | ((clip)? PLANB_CLIPMASK: 0));
+ tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->odd),
+ bpp | ((clip)? PLANB_CLIPMASK: 0));
+ tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->saa_addr),
+ SAA7196_OUTPIX);
+ tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->saa_regval),
+ saa_regs[norm][SAA7196_OUTPIX]);
+ tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->saa_addr),
+ SAA7196_HFILT);
+ tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->saa_regval),
+ saa_regs[norm][SAA7196_HFILT]);
+ tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->saa_addr),
+ SAA7196_OUTLINE);
+ tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->saa_regval),
+ saa_regs[norm][SAA7196_OUTLINE]);
+ tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->saa_addr),
+ SAA7196_VYP);
+ tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->saa_regval),
+ saa_regs[norm][SAA7196_VYP]);
+ return c1;
+}
+
+/******************************/
+/* misc. supporting functions */
+/******************************/
+
+static void __planb_wait(struct planb *pb)
+{
+ struct wait_queue wait = { current, NULL };
+
+ add_wait_queue(&pb->lockq, &wait);
+repeat:
+ current->state = TASK_UNINTERRUPTIBLE;
+ if (pb->lock) {
+ schedule();
+ goto repeat;
+ }
+ remove_wait_queue(&pb->lockq, &wait);
+ current->state = TASK_RUNNING;
+}
+
+static inline void planb_wait(struct planb *pb)
+{
+ DEBUG("PlanB: planb_wait\n");
+ if(pb->lock)
+ __planb_wait(pb);
+}
+
+static inline void planb_lock(struct planb *pb)
+{
+ DEBUG("PlanB: planb_lock\n");
+ if(pb->lock)
+ __planb_wait(pb);
+ pb->lock = 1;
+}
+
+static inline void planb_unlock(struct planb *pb)
+{
+ DEBUG("PlanB: planb_unlock\n");
+ pb->lock = 0;
+ wake_up(&pb->lockq);
+}
+
+/***************/
+/* Driver Core */
+/***************/
+
+static int planb_prepare_open(struct planb *pb)
+{
+ int i, size;
+
+ /* allocate memory for two plus alpha command buffers (size: max lines,
+ plus 40 commands handling, plus 1 alignment), plus dummy command buf,
+ plus clipmask buffer, plus frame grabbing status */
+ size = (pb->tab_size*(2+MAX_GBUFFERS*TAB_FACTOR)+1+MAX_GBUFFERS
+ * PLANB_DUMMY)*sizeof(struct dbdma_cmd)
+ +(PLANB_MAXLINES*((PLANB_MAXPIXELS+7)& ~7))/8
+ +MAX_GBUFFERS*sizeof(unsigned int);
+ if ((pb->priv_space = kmalloc (size, GFP_KERNEL)) == 0)
+ return -ENOMEM;
+ memset ((void *) pb->priv_space, 0, size);
+ pb->overlay_last1 = pb->ch1_cmd = (volatile struct dbdma_cmd *)
+ DBDMA_ALIGN (pb->priv_space);
+ pb->overlay_last2 = pb->ch2_cmd = pb->ch1_cmd + pb->tab_size;
+ pb->ch1_cmd_phys = virt_to_bus(pb->ch1_cmd);
+ pb->cap_cmd[0] = pb->ch2_cmd + pb->tab_size;
+ pb->pre_cmd[0] = pb->cap_cmd[0] + pb->tab_size * TAB_FACTOR;
+ for (i = 1; i < MAX_GBUFFERS; i++) {
+ pb->cap_cmd[i] = pb->pre_cmd[i-1] + PLANB_DUMMY;
+ pb->pre_cmd[i] = pb->cap_cmd[i] + pb->tab_size * TAB_FACTOR;
+ }
+ pb->frame_stat=(volatile unsigned int *)(pb->pre_cmd[MAX_GBUFFERS-1]
+ + PLANB_DUMMY);
+ pb->mask = (unsigned char *)(pb->frame_stat+MAX_GBUFFERS);
+
+ pb->fbuffer = (unsigned char *)rvmalloc(MAX_GBUFFERS * PLANB_MAX_FBUF);
+ if (!pb->fbuffer) {
+ kfree(pb->priv_space);
+ return -ENOMEM;
+ }
+ pb->grabbing = 0;
+ for (i = 0; i < MAX_GBUFFERS; i++) {
+ pb->frame_stat[i] = GBUFFER_UNUSED;
+ pb->gwidth[i] = 0;
+ pb->gheight[i] = 0;
+ pb->gfmt[i] = 0;
+ pb->gnorm_switch[i] = 0;
+#ifndef PLANB_GSCANLINE
+ pb->lsize[i] = 0;
+ pb->lnum[i] = 0;
+ pb->l_fr_addr[i]=(unsigned char *)rvmalloc(PAGE_SIZE*MAX_LNUM);
+ if (!pb->l_fr_addr[i]) {
+ int j;
+ kfree(pb->priv_space);
+ rvfree((void *)pb->fbuffer, MAX_GBUFFERS
+ * PLANB_MAX_FBUF);
+ for(j = 0; j < i; j++)
+ rvfree((void *)pb->l_fr_addr[j], PAGE_SIZE
+ * MAX_LNUM);
+ return -ENOMEM;
+ }
+#endif /* PLANB_GSCANLINE */
+ }
+ pb->gcount = 0;
+ pb->suspend = 0;
+ pb->last_fr = -999;
+ pb->prev_last_fr = -999;


+ return 0;
+}
+

+static void planb_prepare_close(struct planb *pb)
+{
+#ifndef PLANB_GSCANLINE
+ int i;
+#endif
+
+ /* make sure the dma's are idle */
+ planb_dbdma_stop(&pb->planb_base->ch2);
+ planb_dbdma_stop(&pb->planb_base->ch1);
+ /* free kernel memory of command buffers */
+ if(pb->priv_space != 0) {
+ kfree (pb->priv_space);
+ pb->priv_space = 0;
+ pb->cmd_buff_inited = 0;
+ }
+ if(pb->fbuffer)
+ rvfree((void *)pb->fbuffer, MAX_GBUFFERS*PLANB_MAX_FBUF);
+ pb->fbuffer = NULL;
+#ifndef PLANB_GSCANLINE
+ for(i = 0; i < MAX_GBUFFERS; i++) {
+ if(pb->l_fr_addr[i])
+ rvfree((void *)pb->l_fr_addr[i], PAGE_SIZE * MAX_LNUM);
+ pb->l_fr_addr[i] = NULL;
+ }
+#endif /* PLANB_GSCANLINE */
+}
+
+/*****************************/
+/* overlay support functions */
+/*****************************/
+
+static void overlay_start(struct planb *pb)
+{
+
+ DEBUG("PlanB: overlay_start()\n");
+
+ if(ACTIVE & in_le32(&pb->planb_base->ch1.status)) {
+
+ DEBUG("PlanB: presumably, grabbing is in progress...\n");
+
+ planb_dbdma_stop(&pb->planb_base->ch2);
+ out_le32 (&pb->planb_base->ch2.cmdptr,
+ virt_to_bus(pb->ch2_cmd));
+ planb_dbdma_restart(&pb->planb_base->ch2);
+ st_le16 (&pb->ch1_cmd->command, DBDMA_NOP);
+ tab_cmd_dbdma(pb->last_cmd[pb->last_fr],
+ DBDMA_NOP | BR_ALWAYS,
+ virt_to_bus(pb->ch1_cmd));
+ eieio();
+ pb->prev_last_fr = pb->last_fr;
+ pb->last_fr = -2;
+ if(!(ACTIVE & in_le32(&pb->planb_base->ch1.status))) {
+ IDEBUG("PlanB: became inactive "
+ "in the mean time... reactivating\n");
+ planb_dbdma_stop(&pb->planb_base->ch1);
+ out_le32 (&pb->planb_base->ch1.cmdptr,
+ virt_to_bus(pb->ch1_cmd));
+ planb_dbdma_restart(&pb->planb_base->ch1);
+ }
+ } else {
+
+ DEBUG("PlanB: currently idle, so can do whatever\n");
+
+ planb_dbdma_stop(&pb->planb_base->ch2);
+ planb_dbdma_stop(&pb->planb_base->ch1);
+ st_le32 (&pb->planb_base->ch2.cmdptr,
+ virt_to_bus(pb->ch2_cmd));
+ st_le32 (&pb->planb_base->ch1.cmdptr,
+ virt_to_bus(pb->ch1_cmd));
+ out_le16 (&pb->ch1_cmd->command, DBDMA_NOP);
+ planb_dbdma_restart(&pb->planb_base->ch2);
+ planb_dbdma_restart(&pb->planb_base->ch1);
+ pb->last_fr = -1;


+ }
+ return;
+}
+

+static void overlay_stop(struct planb *pb)
+{
+ DEBUG("PlanB: overlay_stop()\n");
+
+ if(pb->last_fr == -1) {
+
+ DEBUG("PlanB: no grabbing, it seems...\n");
+
+ planb_dbdma_stop(&pb->planb_base->ch2);
+ planb_dbdma_stop(&pb->planb_base->ch1);
+ pb->last_fr = -999;
+ } else if(pb->last_fr == -2) {
+ unsigned int cmd_dep;
+ tab_cmd_dbdma(pb->cap_cmd[pb->prev_last_fr], DBDMA_STOP, 0);
+ eieio();
+ cmd_dep = (unsigned int)in_le32(&pb->overlay_last1->cmd_dep);
+ if(overlay_is_active(pb)) {
+
+ DEBUG("PlanB: overlay is currently active\n");
+
+ planb_dbdma_stop(&pb->planb_base->ch2);
+ planb_dbdma_stop(&pb->planb_base->ch1);
+ if(cmd_dep != pb->ch1_cmd_phys) {
+ out_le32(&pb->planb_base->ch1.cmdptr,
+ virt_to_bus(pb->overlay_last1));
+ planb_dbdma_restart(&pb->planb_base->ch1);
+ }
+ }
+ pb->last_fr = pb->prev_last_fr;
+ pb->prev_last_fr = -999;


+ }
+ return;
+}
+

+static void suspend_overlay(struct planb *pb)
+{
+ int fr = -1;
+ struct dbdma_cmd last;
+
+ DEBUG("PlanB: suspend_overlay: %d\n", pb->suspend);
+
+ if(pb->suspend++)
+ return;
+ if(ACTIVE & in_le32(&pb->planb_base->ch1.status)) {
+ if(pb->last_fr == -2) {
+ fr = pb->prev_last_fr;
+ memcpy(&last, (void*)pb->last_cmd[fr], sizeof(last));
+ tab_cmd_dbdma(pb->last_cmd[fr], DBDMA_STOP, 0);
+ }
+ if(overlay_is_active(pb)) {
+ planb_dbdma_stop(&pb->planb_base->ch2);
+ planb_dbdma_stop(&pb->planb_base->ch1);
+ pb->suspended.overlay = 1;
+ pb->suspended.frame = fr;
+ memcpy(&pb->suspended.cmd, &last, sizeof(last));
+ return;
+ }
+ }
+ pb->suspended.overlay = 0;
+ pb->suspended.frame = fr;
+ memcpy(&pb->suspended.cmd, &last, sizeof(last));
+ return;
+}
+
+static void resume_overlay(struct planb *pb)
+{
+
+ DEBUG("PlanB: resume_overlay: %d\n", pb->suspend);
+
+ if(pb->suspend > 1)
+ return;
+ if(pb->suspended.frame != -1) {
+ memcpy((void*)pb->last_cmd[pb->suspended.frame],
+ &pb->suspended.cmd, sizeof(pb->suspended.cmd));
+ }
+ if(ACTIVE & in_le32(&pb->planb_base->ch1.status)) {
+ goto finish;
+ }
+ if(pb->suspended.overlay) {
+
+ DEBUG("PlanB: overlay being resumed\n");
+
+ st_le16 (&pb->ch1_cmd->command, DBDMA_NOP);
+ st_le16 (&pb->ch2_cmd->command, DBDMA_NOP);
+ /* Set command buffer addresses */
+ st_le32(&pb->planb_base->ch1.cmdptr,
+ virt_to_bus(pb->overlay_last1));
+ out_le32(&pb->planb_base->ch2.cmdptr,
+ virt_to_bus(pb->overlay_last2));
+ /* Start the DMA controller */
+ out_le32 (&pb->planb_base->ch2.control,
+ PLANB_CLR(PAUSE) | PLANB_SET(RUN|WAKE));
+ out_le32 (&pb->planb_base->ch1.control,
+ PLANB_CLR(PAUSE) | PLANB_SET(RUN|WAKE));
+ } else if(pb->suspended.frame != -1) {
+ out_le32(&pb->planb_base->ch1.cmdptr,
+ virt_to_bus(pb->last_cmd[pb->suspended.frame]));
+ out_le32 (&pb->planb_base->ch1.control,
+ PLANB_CLR(PAUSE) | PLANB_SET(RUN|WAKE));
+ }
+
+finish:
+ pb->suspend--;
+ wake_up_interruptible(&pb->suspendq);
+}
+
+static void add_clip(struct planb *pb, struct video_clip *clip)
+{
+ volatile unsigned char *base;
+ int xc = clip->x, yc = clip->y;
+ int wc = clip->width, hc = clip->height;
+ int ww = pb->win.width, hw = pb->win.height;
+ int x, y, xtmp1, xtmp2;
+
+ DEBUG("PlanB: clip %dx%d+%d+%d\n", wc, hc, xc, yc);
+
+ if(xc < 0) {
+ wc += xc;
+ xc = 0;
+ }
+ if(yc < 0) {
+ hc += yc;
+ yc = 0;
+ }
+ if(xc + wc > ww)
+ wc = ww - xc;
+ if(wc <= 0) /* Nothing to do */
+ return;
+ if(yc + hc > hw)
+ hc = hw - yc;
+
+ for (y = yc; y < yc+hc; y++) {
+ xtmp1=xc>>3;
+ xtmp2=(xc+wc)>>3;
+ base = pb->mask + y*96;
+ if(xc != 0 || wc >= 8)
+ *(base + xtmp1) &= (unsigned char)(0x00ff &
+ (0xff00 >> (xc&7)));
+ for (x = xtmp1 + 1; x < xtmp2; x++) {
+ *(base + x) = 0;
+ }
+ if(xc < (ww & ~0x7))
+ *(base + xtmp2) &= (unsigned char)(0x00ff >>
+ ((xc+wc) & 7));


+ }
+
+ return;
+}
+

+static void fill_cmd_buff(struct planb *pb)
+{
+ int restore = 0;
+ volatile struct dbdma_cmd last;
+
+ DEBUG("PlanB: fill_cmd_buff()\n");
+
+ if(pb->overlay_last1 != pb->ch1_cmd) {
+ restore = 1;
+ last = *(pb->overlay_last1);
+ }
+ memset ((void *) pb->ch1_cmd, 0, 2 * pb->tab_size
+ * sizeof(struct dbdma_cmd));
+ cmd_buff (pb);
+ if(restore)
+ *(pb->overlay_last1) = last;
+ if(pb->suspended.overlay) {
+ unsigned long jump_addr = in_le32(&pb->overlay_last1->cmd_dep);
+ if(jump_addr != pb->ch1_cmd_phys) {
+ int i;
+
+ DEBUG("PlanB: adjusting ch1's jump address\n");
+
+ for(i = 0; i < MAX_GBUFFERS; i++) {
+ if(pb->need_pre_capture[i]) {
+ if(jump_addr == virt_to_bus(pb->pre_cmd[i]))
+ goto found;
+ } else {
+ if(jump_addr == virt_to_bus(pb->cap_cmd[i]))
+ goto found;
+ }
+ }
+
+ DEBUG("PlanB: not found...\n");
+
+ goto out;
+found:
+ if(pb->need_pre_capture[i])
+ out_le32(&pb->pre_cmd[i]->phy_addr,
+ virt_to_bus(pb->overlay_last1));
+ else
+ out_le32(&pb->cap_cmd[i]->phy_addr,
+ virt_to_bus(pb->overlay_last1));
+ }
+ }
+out:
+ pb->cmd_buff_inited = 1;


+
+ return;
+}
+

+static void cmd_buff(struct planb *pb)
+{
+ int i, bpp, count, nlines, stepsize, interlace;
+ unsigned long base, jump, addr_com, addr_dep;
+ volatile struct dbdma_cmd *c1 = pb->ch1_cmd;
+ volatile struct dbdma_cmd *c2 = pb->ch2_cmd;
+
+ interlace = pb->win.interlace;
+ bpp = pb->win.bpp;
+ count = (bpp * ((pb->win.x + pb->win.width > pb->win.swidth) ?
+ (pb->win.swidth - pb->win.x) : pb->win.width));
+ nlines = ((pb->win.y + pb->win.height > pb->win.sheight) ?
+ (pb->win.sheight - pb->win.y) : pb->win.height);
+
+ /* Do video in: */
+
+ /* Preamble commands: */
+ addr_com = virt_to_bus(c1);
+ addr_dep = virt_to_bus(&c1->cmd_dep);
+ tab_cmd_dbdma(c1++, DBDMA_NOP, 0);
+ jump = virt_to_bus(c1+16); /* 14 by cmd_geo_setup() and 2 for padding */
+ if((c1 = cmd_geo_setup(c1, pb->win.width, pb->win.height, interlace,
+ bpp, 1, pb)) == NULL) {
+ printk(KERN_WARNING "PlanB: encountered serious problems\n");
+ tab_cmd_dbdma(pb->ch1_cmd + 1, DBDMA_STOP, 0);
+ tab_cmd_dbdma(pb->ch2_cmd + 1, DBDMA_STOP, 0);
+ return;
+ }
+ tab_cmd_store(c1++, addr_com, (unsigned)(DBDMA_NOP | BR_ALWAYS) << 16);
+ tab_cmd_store(c1++, addr_dep, jump);
+ tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.wait_sel),
+ PLANB_SET(FIELD_SYNC));
+ /* (1) wait for field sync to be set */
+ tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFCLR, 0);
+ tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel),
+ PLANB_SET(ODD_FIELD));
+ /* wait for field sync to be cleared */
+ tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFSET, 0);
+ /* if not odd field, wait until field sync is set again */
+ tab_cmd_dbdma(c1, DBDMA_NOP | BR_IFSET, virt_to_bus(c1-3)); c1++;
+ /* assert ch_sync to ch2 */
+ tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch2.control),
+ PLANB_SET(CH_SYNC));
+ tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel),
+ PLANB_SET(DMA_ABORT));
+
+ base = (pb->frame_buffer_phys + pb->offset + pb->win.y * (pb->win.bpl
+ + pb->win.pad) + pb->win.x * bpp);
+
+ if (interlace) {
+ stepsize = 2;
+ jump = virt_to_bus(c1 + (nlines + 1) / 2);
+ } else {
+ stepsize = 1;
+ jump = virt_to_bus(c1 + nlines);
+ }
+
+ /* even field data: */
+ for (i=0; i < nlines; i += stepsize, c1++)
+ tab_cmd_gen(c1, INPUT_MORE | KEY_STREAM0 | BR_IFSET,
+ count, base + i * (pb->win.bpl + pb->win.pad), jump);
+
+ /* For non-interlaced, we use even fields only */
+ if (!interlace)
+ goto cmd_tab_data_end;
+
+ /* Resync to odd field */
+ /* (2) wait for field sync to be set */
+ tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFCLR, 0);
+ tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel),
+ PLANB_SET(ODD_FIELD));
+ /* wait for field sync to be cleared */
+ tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFSET, 0);
+ /* if not odd field, wait until field sync is set again */
+ tab_cmd_dbdma(c1, DBDMA_NOP | BR_IFCLR, virt_to_bus(c1-3)); c1++;
+ /* assert ch_sync to ch2 */
+ tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch2.control),
+ PLANB_SET(CH_SYNC));
+ tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel),
+ PLANB_SET(DMA_ABORT));
+
+ /* odd field data: */
+ jump = virt_to_bus(c1 + nlines / 2);
+ for (i=1; i < nlines; i += stepsize, c1++)
+ tab_cmd_gen(c1, INPUT_MORE | KEY_STREAM0 | BR_IFSET, count,
+ base + i * (pb->win.bpl + pb->win.pad), jump);
+
+ /* And jump back to the start */
+cmd_tab_data_end:
+ pb->overlay_last1 = c1; /* keep a pointer to the last command */
+ tab_cmd_dbdma(c1, DBDMA_NOP | BR_ALWAYS, virt_to_bus(pb->ch1_cmd));
+
+ /* Clipmask command buffer */
+
+ /* Preamble commands: */
+ tab_cmd_dbdma(c2++, DBDMA_NOP, 0);
+ tab_cmd_store(c2++, (unsigned)(&pb->planb_base_phys->ch2.wait_sel),
+ PLANB_SET(CH_SYNC));
+ /* wait until ch1 asserts ch_sync */
+ tab_cmd_dbdma(c2++, DBDMA_NOP | WAIT_IFCLR, 0);
+ /* clear ch_sync asserted by ch1 */
+ tab_cmd_store(c2++, (unsigned)(&pb->planb_base_phys->ch2.control),
+ PLANB_CLR(CH_SYNC));
+ tab_cmd_store(c2++, (unsigned)(&pb->planb_base_phys->ch2.wait_sel),
+ PLANB_SET(FIELD_SYNC));
+ tab_cmd_store(c2++, (unsigned)(&pb->planb_base_phys->ch2.br_sel),
+ PLANB_SET(ODD_FIELD));
+
+ /* jump to end of even field if appropriate */
+ /* this points to (interlace)? pos. C: pos. B */
+ jump = (interlace) ? virt_to_bus(c2 + (nlines + 1) / 2 + 2):
+ virt_to_bus(c2 + nlines + 2);
+ /* if odd field, skip over to odd field clipmasking */
+ tab_cmd_dbdma(c2++, DBDMA_NOP | BR_IFSET, jump);
+
+ /* even field mask: */
+ tab_cmd_store(c2++, (unsigned)(&pb->planb_base_phys->ch2.br_sel),
+ PLANB_SET(DMA_ABORT));
+ /* this points to pos. B */
+ jump = (interlace) ? virt_to_bus(c2 + nlines + 1):
+ virt_to_bus(c2 + nlines);
+ base = virt_to_bus(pb->mask);
+ for (i=0; i < nlines; i += stepsize, c2++)
+ tab_cmd_gen(c2, OUTPUT_MORE | KEY_STREAM0 | BR_IFSET, 96,
+ base + i * 96, jump);
+
+ /* For non-interlaced, we use only even fields */
+ if(!interlace)
+ goto cmd_tab_mask_end;
+
+ /* odd field mask: */
+/* C */ tab_cmd_store(c2++, (unsigned)(&pb->planb_base_phys->ch2.br_sel),
+ PLANB_SET(DMA_ABORT));
+ /* this points to pos. B */
+ jump = virt_to_bus(c2 + nlines / 2);
+ base = virt_to_bus(pb->mask);
+ for (i=1; i < nlines; i += 2, c2++) /* abort if set */
+ tab_cmd_gen(c2, OUTPUT_MORE | KEY_STREAM0 | BR_IFSET, 96,
+ base + i * 96, jump);
+
+ /* Inform channel 1 and jump back to start */
+cmd_tab_mask_end:
+ /* ok, I just realized this is kind of flawed. */
+ /* this part is reached only after odd field clipmasking. */
+ /* wanna clean up? */
+ /* wait for field sync to be set */
+ /* corresponds to fsync (1) of ch1 */
+/* B */ tab_cmd_dbdma(c2++, DBDMA_NOP | WAIT_IFCLR, 0);
+ /* restart ch1, meant to clear any dead bit or something */
+ tab_cmd_store(c2++, (unsigned)(&pb->planb_base_phys->ch1.control),
+ PLANB_CLR(RUN));
+ tab_cmd_store(c2++, (unsigned)(&pb->planb_base_phys->ch1.control),
+ PLANB_SET(RUN));
+ pb->overlay_last2 = c2; /* keep a pointer to the last command */
+ /* start over even field clipmasking */
+ tab_cmd_dbdma(c2, DBDMA_NOP | BR_ALWAYS, virt_to_bus(pb->ch2_cmd));
+
+ eieio();
+ return;
+}
+
+/*********************************/
+/* grabdisplay support functions */
+/*********************************/
+
+static int palette2fmt[] = {
+ 0,
+ PLANB_GRAY,


+ 0,
+ 0,
+ 0,

+ PLANB_COLOUR32,
+ PLANB_COLOUR15,


+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,

+ 0,
+ 0,
+};
+#define PLANB_PALETTE_MAX 15
+
+#define SWAP4(x) (((x>>24) & 0x000000ff) |\
+ ((x>>8) & 0x0000ff00) |\
+ ((x<<8) & 0x00ff0000) |\
+ ((x<<24) & 0xff000000))
+
+static inline int overlay_is_active(struct planb *pb)
+{
+ unsigned int size = pb->tab_size * sizeof(struct dbdma_cmd);
+ unsigned int caddr = (unsigned)in_le32(&pb->planb_base->ch1.cmdptr);
+
+ return (in_le32(&pb->overlay_last1->cmd_dep) == pb->ch1_cmd_phys)
+ && (caddr < (pb->ch1_cmd_phys + size))
+ && (caddr >= (unsigned)pb->ch1_cmd_phys);
+}
+
+static int vgrab(struct planb *pb, struct video_mmap *mp)
+{
+ unsigned int fr = mp->frame;
+ unsigned int format;
+
+ if(pb->fbuffer==NULL) {
+ if(fbuffer_alloc(pb))
+ return -ENOBUFS;
+ }
+
+ IDEBUG("PlanB: grab %d: %dx%d(%u)\n", pb->grabbing,
+ mp->width, mp->height, fr);
+
+ if(pb->grabbing >= MAX_GBUFFERS)
+ return -ENOBUFS;
+ if(fr > (MAX_GBUFFERS - 1) || fr < 0)
+ return -EINVAL;
+ if(mp->height <= 0 || mp->width <= 0)
+ return -EINVAL;
+ if(mp->format < 0 || mp->format >= PLANB_PALETTE_MAX)
+ return -EINVAL;
+ if((format = palette2fmt[mp->format]) == 0)
+ return -EINVAL;
+ if (mp->height * mp->width * format > PLANB_MAX_FBUF) /* format = bpp */
+ return -EINVAL;
+
+ planb_lock(pb);
+ pb->gbuffer[fr] = (unsigned char *)(pb->fbuffer + PLANB_MAX_FBUF * fr);
+ if(mp->width != pb->gwidth[fr] || mp->height != pb->gheight[fr] ||
+ format != pb->gfmt[fr] || (pb->gnorm_switch[fr])) {
+#ifdef PLANB_GSCANLINE


SHAR_EOF
true || echo 'restore of patch-2.2.8 failed'
fi

echo 'End of part 13'
echo 'File patch-2.2.8 is continued in part 14'
echo 14 > _shar_seq_.tmp

Thomas...@ciw.uni-karlsruhe.de

unread,
May 12, 1999, 3:00:00 AM5/12/99
to
Archive-name: v2.2/patch-2.2.8/part14

#!/bin/sh
# this is part 14 of a 33 - part archive


# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.8 continued
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 14; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.8'
else
echo 'x - continuing with patch-2.2.8'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.8' &&

+ int i;
+#else
+ unsigned int osize = pb->gwidth[fr] * pb->gheight[fr]
+ * pb->gfmt[fr];
+ unsigned int nsize = mp->width * mp->height * format;
+#endif
+
+ IDEBUG("PlanB: gwidth = %d, gheight = %d, mp->format = %u\n",
+ mp->width, mp->height, mp->format);
+
+#ifndef PLANB_GSCANLINE
+ if(pb->gnorm_switch[fr])
+ nsize = 0;
+ if(nsize < osize)
+ memset((void *)(pb->gbuffer[fr] + nsize), 0,
+ osize - nsize);
+ memset((void *)pb->l_fr_addr[fr], 0, PAGE_SIZE * pb->lnum[fr]);
+#else
+/* XXX TODO */
+/*
+ if(pb->gnorm_switch[fr])
+ memset((void *)pb->gbuffer[fr], 0,
+ pb->gbytes_per_line * pb->gheight[fr]);
+ else {
+ if(mp->
+ for(i = 0; i < pb->gheight[fr]; i++) {
+ memset((void *)(pb->gbuffer[fr]
+ + pb->gbytes_per_line * i
+ }
+ }
+*/
+#endif
+ pb->gwidth[fr] = mp->width;
+ pb->gheight[fr] = mp->height;
+ pb->gfmt[fr] = format;
+ pb->last_cmd[fr] = setup_grab_cmd(fr, pb);
+ planb_pre_capture(fr, pb->gfmt[fr], pb); /* gfmt = bpp */
+ pb->need_pre_capture[fr] = 1;
+ pb->gnorm_switch[fr] = 0;
+ } else
+ pb->need_pre_capture[fr] = 0;
+ pb->frame_stat[fr] = GBUFFER_GRABBING;


+ if(!(ACTIVE & in_le32(&pb->planb_base->ch1.status))) {
+

+ IDEBUG("PlanB: ch1 inactive, initiating grabbing\n");
+
+ planb_dbdma_stop(&pb->planb_base->ch1);
+ if(pb->need_pre_capture[fr]) {
+
+ IDEBUG("PlanB: padding pre-capture sequence\n");
+


+ out_le32 (&pb->planb_base->ch1.cmdptr,

+ virt_to_bus(pb->pre_cmd[fr]));
+ } else {


+ tab_cmd_dbdma(pb->last_cmd[fr], DBDMA_STOP, 0);

+ tab_cmd_dbdma(pb->cap_cmd[fr], DBDMA_NOP, 0);
+ /* let's be on the safe side. here is not timing critical. */
+ tab_cmd_dbdma((pb->cap_cmd[fr] + 1), DBDMA_NOP, 0);


+ out_le32 (&pb->planb_base->ch1.cmdptr,

+ virt_to_bus(pb->cap_cmd[fr]));
+ }
+ planb_dbdma_restart(&pb->planb_base->ch1);
+ pb->last_fr = fr;
+ } else {
+ int i;
+
+ IDEBUG("PlanB: ch1 active, grabbing being queued\n");
+
+ if((pb->last_fr == -1) || ((pb->last_fr == -2) &&
+ overlay_is_active(pb))) {
+
+ IDEBUG("PlanB: overlay is active, grabbing defered\n");
+


+ tab_cmd_dbdma(pb->last_cmd[fr],

+ DBDMA_NOP | BR_ALWAYS,
+ virt_to_bus(pb->ch1_cmd));

+ if(pb->need_pre_capture[fr]) {
+
+ IDEBUG("PlanB: padding pre-capture sequence\n");
+
+ tab_cmd_store(pb->pre_cmd[fr],
+ virt_to_bus(&pb->overlay_last1->cmd_dep),


+ virt_to_bus(pb->ch1_cmd));
+ eieio();

+ out_le32 (&pb->overlay_last1->cmd_dep,
+ virt_to_bus(pb->pre_cmd[fr]));
+ } else {
+ tab_cmd_store(pb->cap_cmd[fr],
+ virt_to_bus(&pb->overlay_last1->cmd_dep),
+ virt_to_bus(pb->ch1_cmd));
+ tab_cmd_dbdma((pb->cap_cmd[fr] + 1),
+ DBDMA_NOP, 0);
+ eieio();
+ out_le32 (&pb->overlay_last1->cmd_dep,
+ virt_to_bus(pb->cap_cmd[fr]));
+ }
+ for(i = 0; overlay_is_active(pb) && i < 999; i++)
+ IDEBUG("PlanB: waiting for overlay done\n");
+ tab_cmd_dbdma(pb->ch1_cmd, DBDMA_NOP, 0);
+ pb->prev_last_fr = fr;


+ pb->last_fr = -2;

+ } else if(pb->last_fr == -2) {
+

+ IDEBUG("PlanB: mixed mode detected, grabbing"
+ " will be done before activating overlay\n");
+
+ tab_cmd_dbdma(pb->ch1_cmd, DBDMA_NOP, 0);
+ if(pb->need_pre_capture[fr]) {
+
+ IDEBUG("PlanB: padding pre-capture sequence\n");
+
+ tab_cmd_dbdma(pb->last_cmd[pb->prev_last_fr],
+ DBDMA_NOP | BR_ALWAYS,
+ virt_to_bus(pb->pre_cmd[fr]));
+ eieio();
+ } else {
+ tab_cmd_dbdma(pb->cap_cmd[fr], DBDMA_NOP, 0);
+ if(pb->gwidth[pb->prev_last_fr] !=
+ pb->gwidth[fr]
+ || pb->gheight[pb->prev_last_fr] !=
+ pb->gheight[fr]
+ || pb->gfmt[pb->prev_last_fr] !=
+ pb->gfmt[fr])
+ tab_cmd_dbdma((pb->cap_cmd[fr] + 1),
+ DBDMA_NOP, 0);
+ else
+ tab_cmd_dbdma((pb->cap_cmd[fr] + 1),
+ DBDMA_NOP | BR_ALWAYS,
+ virt_to_bus(pb->cap_cmd[fr] + 16));
+ tab_cmd_dbdma(pb->last_cmd[pb->prev_last_fr],
+ DBDMA_NOP | BR_ALWAYS,
+ virt_to_bus(pb->cap_cmd[fr]));
+ eieio();
+ }


+ tab_cmd_dbdma(pb->last_cmd[fr],

+ DBDMA_NOP | BR_ALWAYS,
+ virt_to_bus(pb->ch1_cmd));
+ eieio();

+ pb->prev_last_fr = fr;


+ pb->last_fr = -2;

+ } else {
+
+ IDEBUG("PlanB: active grabbing session detected\n");
+
+ if(pb->need_pre_capture[fr]) {
+
+ IDEBUG("PlanB: padding pre-capture sequence\n");
+


+ tab_cmd_dbdma(pb->last_cmd[pb->last_fr],
+ DBDMA_NOP | BR_ALWAYS,

+ virt_to_bus(pb->pre_cmd[fr]));
+ eieio();
+ } else {


+ tab_cmd_dbdma(pb->last_cmd[fr], DBDMA_STOP, 0);

+ tab_cmd_dbdma(pb->cap_cmd[fr], DBDMA_NOP, 0);
+ if(pb->gwidth[pb->last_fr] != pb->gwidth[fr]
+ || pb->gheight[pb->last_fr] !=
+ pb->gheight[fr]
+ || pb->gfmt[pb->last_fr] !=
+ pb->gfmt[fr])
+ tab_cmd_dbdma((pb->cap_cmd[fr] + 1),
+ DBDMA_NOP, 0);
+ else
+ tab_cmd_dbdma((pb->cap_cmd[fr] + 1),
+ DBDMA_NOP | BR_ALWAYS,
+ virt_to_bus(pb->cap_cmd[fr] + 16));


+ tab_cmd_dbdma(pb->last_cmd[pb->last_fr],
+ DBDMA_NOP | BR_ALWAYS,

+ virt_to_bus(pb->cap_cmd[fr]));
+ eieio();
+ }
+ pb->last_fr = fr;
+ }


+ if(!(ACTIVE & in_le32(&pb->planb_base->ch1.status))) {
+

+ IDEBUG("PlanB: became inactive in the mean time..."
+ "reactivating\n");
+


+ planb_dbdma_stop(&pb->planb_base->ch1);
+ out_le32 (&pb->planb_base->ch1.cmdptr,

+ virt_to_bus(pb->cap_cmd[fr]));


+ planb_dbdma_restart(&pb->planb_base->ch1);
+ }
+ }

+ pb->grabbing++;
+ planb_unlock(pb);


+
+ return 0;
+}
+

+static void planb_pre_capture(int fr, int bpp, struct planb *pb)
+{
+ volatile struct dbdma_cmd *c1 = pb->pre_cmd[fr];
+ int interlace = (pb->gheight[fr] > pb->maxlines/2)? 1: 0;
+
+ tab_cmd_dbdma(c1++, DBDMA_NOP, 0);
+ if((c1 = cmd_geo_setup(c1, pb->gwidth[fr], pb->gheight[fr], interlace,
+ bpp, 0, pb)) == NULL) {
+ printk(KERN_WARNING "PlanB: encountered some problems\n");
+ tab_cmd_dbdma(pb->pre_cmd[fr] + 1, DBDMA_STOP, 0);
+ return;
+ }
+ /* Sync to even field */
+ tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.wait_sel),
+ PLANB_SET(FIELD_SYNC));


+ tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFCLR, 0);
+ tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel),
+ PLANB_SET(ODD_FIELD));

+ tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFSET, 0);

+ tab_cmd_dbdma(c1, DBDMA_NOP | BR_IFSET, virt_to_bus(c1-3)); c1++;

+ tab_cmd_dbdma(c1++, DBDMA_NOP | INTR_ALWAYS, 0);


+ tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel),

+ PLANB_SET(DMA_ABORT));


+ /* For non-interlaced, we use even fields only */

+ if (pb->gheight[fr] <= pb->maxlines/2)
+ goto cmd_tab_data_end;
+ /* Sync to odd field */


+ tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFCLR, 0);
+ tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel),
+ PLANB_SET(ODD_FIELD));

+ tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFSET, 0);

+ tab_cmd_dbdma(c1, DBDMA_NOP | BR_IFCLR, virt_to_bus(c1-3)); c1++;

+ tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel),
+ PLANB_SET(DMA_ABORT));

+cmd_tab_data_end:
+ tab_cmd_dbdma(c1, DBDMA_NOP | BR_ALWAYS, virt_to_bus(pb->cap_cmd[fr]));
+
+ eieio();
+}
+
+static volatile struct dbdma_cmd *setup_grab_cmd(int fr, struct planb *pb)
+{


+ int i, bpp, count, nlines, stepsize, interlace;

+#ifdef PLANB_GSCANLINE
+ int scanline;
+#else
+ int nlpp, leftover1;
+ unsigned long base;
+#endif
+ unsigned long jump;
+ unsigned char *vaddr;
+ volatile struct dbdma_cmd *c1;
+ volatile struct dbdma_cmd *jump_addr;
+
+ c1 = pb->cap_cmd[fr];
+ interlace = (pb->gheight[fr] > pb->maxlines/2)? 1: 0;
+ bpp = pb->gfmt[fr]; /* gfmt = bpp */
+ count = bpp * pb->gwidth[fr];
+ nlines = pb->gheight[fr];
+#ifdef PLANB_GSCANLINE
+ scanline = pb->gbytes_per_line;
+#else
+ pb->lsize[fr] = count;
+ pb->lnum[fr] = 0;
+#endif


+
+ /* Do video in: */
+
+ /* Preamble commands: */

+ tab_cmd_dbdma(c1++, DBDMA_NOP, 0);
+ tab_cmd_dbdma(c1, DBDMA_NOP | BR_ALWAYS, virt_to_bus(c1 + 16)); c1++;
+ if((c1 = cmd_geo_setup(c1, pb->gwidth[fr], pb->gheight[fr], interlace,
+ bpp, 0, pb)) == NULL) {


+ printk(KERN_WARNING "PlanB: encountered serious problems\n");

+ tab_cmd_dbdma(pb->cap_cmd[fr] + 1, DBDMA_STOP, 0);
+ return (pb->cap_cmd[fr] + 2);
+ }


+ tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.wait_sel),
+ PLANB_SET(FIELD_SYNC));

+ tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFCLR, 0);
+ tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel),
+ PLANB_SET(ODD_FIELD));

+ tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFSET, 0);

+ tab_cmd_dbdma(c1, DBDMA_NOP | BR_IFSET, virt_to_bus(c1-3)); c1++;

+ tab_cmd_dbdma(c1++, DBDMA_NOP | INTR_ALWAYS, 0);


+ tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel),

+ PLANB_SET(DMA_ABORT));


+
+ if (interlace) {
+ stepsize = 2;

+ jump_addr = c1 + TAB_FACTOR * (nlines + 1) / 2;


+ } else {
+ stepsize = 1;

+ jump_addr = c1 + TAB_FACTOR * nlines;
+ }
+ jump = virt_to_bus(jump_addr);


+
+ /* even field data: */
+

+ vaddr = pb->gbuffer[fr];
+#ifdef PLANB_GSCANLINE
+ for (i = 0; i < nlines; i += stepsize) {
+ tab_cmd_gen(c1++, INPUT_MORE | BR_IFSET, count,
+ vmalloc_to_bus(vaddr + i * scanline), jump);
+ }
+#else
+ i = 0;
+ leftover1 = 0;
+ do {
+ int j;
+
+ base = vmalloc_to_bus((void*)vaddr);
+ nlpp = (PAGE_SIZE - leftover1) / count / stepsize;
+ for(j = 0; j < nlpp && i < nlines; j++, i += stepsize, c1++)


+ tab_cmd_gen(c1, INPUT_MORE | KEY_STREAM0 | BR_IFSET,

+ count, base + count * j * stepsize + leftover1, jump);
+ if(i < nlines) {
+ int lov0 = PAGE_SIZE - count * nlpp * stepsize - leftover1;
+
+ if(lov0 == 0)
+ leftover1 = 0;
+ else {
+ if(lov0 >= count) {
+ tab_cmd_gen(c1++, INPUT_MORE | BR_IFSET, count, base
+ + count * nlpp * stepsize + leftover1, jump);
+ } else {
+ pb->l_to_addr[fr][pb->lnum[fr]] = vaddr + count * nlpp
+ * stepsize + leftover1;
+ tab_cmd_gen(c1++, INPUT_MORE | BR_IFSET, count,
+ vmalloc_to_bus(pb->l_fr_addr[fr] + PAGE_SIZE
+ * pb->lnum[fr]), jump);
+ if(++pb->lnum[fr] > MAX_LNUM)
+ pb->lnum[fr]--;
+ }
+ leftover1 = count * stepsize - lov0;
+ i += stepsize;
+ }
+ }
+ vaddr += PAGE_SIZE;
+ } while(i < nlines);
+ tab_cmd_dbdma(c1, DBDMA_NOP | BR_ALWAYS, jump);
+ c1 = jump_addr;


+#endif /* PLANB_GSCANLINE */
+

+ /* For non-interlaced, we use even fields only */
+ if (!interlace)
+ goto cmd_tab_data_end;
+

+ /* Sync to odd field */


+ tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFCLR, 0);
+ tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel),
+ PLANB_SET(ODD_FIELD));

+ tab_cmd_dbdma(c1++, DBDMA_NOP | WAIT_IFSET, 0);

+ tab_cmd_dbdma(c1, DBDMA_NOP | BR_IFCLR, virt_to_bus(c1-3)); c1++;

+ tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->ch1.br_sel),
+ PLANB_SET(DMA_ABORT));
+
+ /* odd field data: */

+ jump_addr = c1 + TAB_FACTOR * nlines / 2;
+ jump = virt_to_bus(jump_addr);
+#ifdef PLANB_GSCANLINE
+ for (i = 1; i < nlines; i += stepsize) {
+ tab_cmd_gen(c1++, INPUT_MORE | BR_IFSET, count,
+ vmalloc_to_bus(vaddr + i * scanline), jump);
+ }
+#else
+ i = 1;
+ leftover1 = 0;
+ vaddr = pb->gbuffer[fr];
+ if(nlines <= 1)
+ goto skip;
+ do {
+ int j;
+
+ base = vmalloc_to_bus((void*)vaddr);
+ nlpp = (PAGE_SIZE - leftover1) / count / stepsize;
+ if(leftover1 >= count) {
+ tab_cmd_gen(c1++, INPUT_MORE | KEY_STREAM0 | BR_IFSET, count,
+ base + leftover1 - count, jump);
+ i += stepsize;
+ }
+ for(j = 0; j < nlpp && i < nlines; j++, i += stepsize, c1++)


+ tab_cmd_gen(c1, INPUT_MORE | KEY_STREAM0 | BR_IFSET, count,

+ base + count * (j * stepsize + 1) + leftover1, jump);
+ if(i < nlines) {
+ int lov0 = PAGE_SIZE - count * nlpp * stepsize - leftover1;
+
+ if(lov0 == 0)
+ leftover1 = 0;
+ else {
+ if(lov0 > count) {
+ pb->l_to_addr[fr][pb->lnum[fr]] = vaddr + count
+ * (nlpp * stepsize + 1) + leftover1;
+ tab_cmd_gen(c1++, INPUT_MORE | BR_IFSET, count,
+ vmalloc_to_bus(pb->l_fr_addr[fr] + PAGE_SIZE
+ * pb->lnum[fr]), jump);
+ if(++pb->lnum[fr] > MAX_LNUM)
+ pb->lnum[fr]--;
+ i += stepsize;
+ }
+ leftover1 = count * stepsize - lov0;
+ }
+ }
+ vaddr += PAGE_SIZE;
+ } while(i < nlines);
+skip:
+ tab_cmd_dbdma(c1, DBDMA_NOP | BR_ALWAYS, jump);
+ c1 = jump_addr;


+#endif /* PLANB_GSCANLINE */
+

+cmd_tab_data_end:
+ tab_cmd_store(c1++, (unsigned)(&pb->planb_base_phys->intr_stat),
+ (fr << 2) | PLANB_FRM_IRQ | PLANB_GEN_IRQ);
+ /* stop it */
+ tab_cmd_dbdma(c1, DBDMA_STOP, 0);
+
+ eieio();
+ return c1;
+}
+
+static void planb_irq(int irq, void *dev_id, struct pt_regs * regs)
+{
+ unsigned int stat, astat;
+ struct planb *pb = (struct planb *)dev_id;
+
+ IDEBUG("PlanB: planb_irq()\n");
+
+ /* get/clear interrupt status bits */
+ stat = in_le32(&pb->planb_base->intr_stat);
+ astat = stat & pb->intr_mask;
+ out_le32(&pb->planb_base->intr_stat, PLANB_IRQ_CMD_MASK
+ & ~astat & stat & ~PLANB_GEN_IRQ);
+
+ if(astat & PLANB_FRM_IRQ) {
+ unsigned int fr = stat >> 2;


+#ifndef PLANB_GSCANLINE
+ int i;
+#endif

+ IDEBUG("PlanB: PLANB_FRM_IRQ\n");
+
+ pb->gcount++;
+
+ IDEBUG("PlanB: grab %d: fr = %d, gcount = %d\n",
+ pb->grabbing, fr, pb->gcount);
+#ifndef PLANB_GSCANLINE
+ IDEBUG("PlanB: %d * %d bytes are being copied over\n",
+ pb->lnum[fr], pb->lsize[fr]);
+ for(i = 0; i < pb->lnum[fr]; i++)
+ memcpy(pb->l_to_addr[fr][i], pb->l_fr_addr[fr]
+ + PAGE_SIZE * i, pb->lsize[fr]);
+#endif
+ pb->frame_stat[fr] = GBUFFER_DONE;
+ pb->grabbing--;
+ wake_up_interruptible(&pb->capq);
+ return;
+ }
+ /* incorrect interrupts? */
+ pb->intr_mask = PLANB_CLR_IRQ;
+ out_le32(&pb->planb_base->intr_stat, PLANB_CLR_IRQ);
+ printk(KERN_ERR "PlanB: IRQ lockup, cleared intrrupts"
+ " unconditionally\n");
+}
+
+/*******************************
+ * Device Operations functions *
+ *******************************/
+
+static int planb_open(struct video_device *dev, int mode)
+{
+ struct planb *pb = (struct planb *)dev;
+
+ if (pb->user == 0) {
+ int err;
+ if((err = planb_prepare_open(pb)) != 0)
+ return err;
+ }
+ pb->user++;
+
+ DEBUG("PlanB: device opened\n");
+
+ MOD_INC_USE_COUNT;


+ return 0;
+}
+

+static void planb_close(struct video_device *dev)
+{
+ struct planb *pb = (struct planb *)dev;
+
+ if(pb->user < 1) /* ??? */
+ return;
+ planb_lock(pb);
+ if (pb->user == 1) {
+ if (pb->overlay) {


+ planb_dbdma_stop(&pb->planb_base->ch2);
+ planb_dbdma_stop(&pb->planb_base->ch1);

+ pb->overlay = 0;
+ }
+ planb_prepare_close(pb);
+ }
+ pb->user--;
+ planb_unlock(pb);
+
+ DEBUG("PlanB: device closed\n");
+
+ MOD_DEC_USE_COUNT;
+}
+
+static long planb_read(struct video_device *v, char *buf, unsigned long count,
+ int nonblock)
+{
+ DEBUG("planb: read request\n");


+ return -EINVAL;
+}
+

+static long planb_write(struct video_device *v, const char *buf,
+ unsigned long count, int nonblock)
+{
+ DEBUG("planb: write request\n");


+ return -EINVAL;
+}
+

+static int planb_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
+{
+ struct planb *pb=(struct planb *)dev;
+
+ switch (cmd)
+ {
+ case VIDIOCGCAP:
+ {
+ struct video_capability b;
+
+ DEBUG("PlanB: IOCTL VIDIOCGCAP\n");
+
+ strcpy (b.name, pb->video_dev.name);
+ b.type = VID_TYPE_OVERLAY | VID_TYPE_CLIPPING |
+ VID_TYPE_FRAMERAM | VID_TYPE_SCALES |
+ VID_TYPE_CAPTURE;
+ b.channels = 2; /* composite & svhs */
+ b.audios = 0;
+ b.maxwidth = PLANB_MAXPIXELS;
+ b.maxheight = PLANB_MAXLINES;
+ b.minwidth = 32; /* wild guess */
+ b.minheight = 32;
+ if (copy_to_user(arg,&b,sizeof(b)))
+ return -EFAULT;
+ return 0;
+ }
+ case VIDIOCSFBUF:
+ {
+ struct video_buffer v;
+ unsigned short bpp;
+ unsigned int fmt;
+
+ DEBUG("PlanB: IOCTL VIDIOCSFBUF\n");
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ if (copy_from_user(&v, arg,sizeof(v)))
+ return -EFAULT;
+ planb_lock(pb);
+ switch(v.depth) {
+ case 8:
+ bpp = 1;
+ fmt = PLANB_GRAY;
+ break;
+ case 15:
+ case 16:
+ bpp = 2;
+ fmt = PLANB_COLOUR15;
+ break;
+ case 24:
+ case 32:
+ bpp = 4;
+ fmt = PLANB_COLOUR32;
+ break;
+ default:
+ planb_unlock(pb);
+ return -EINVAL;
+ }
+ if (bpp * v.width > v.bytesperline) {
+ planb_unlock(pb);
+ return -EINVAL;
+ }
+ pb->win.bpp = bpp;
+ pb->win.color_fmt = fmt;
+ pb->frame_buffer_phys = (unsigned long) v.base;
+ pb->win.sheight = v.height;
+ pb->win.swidth = v.width;
+ pb->picture.depth = pb->win.depth = v.depth;
+ pb->win.bpl = pb->win.bpp * pb->win.swidth;
+ pb->win.pad = v.bytesperline - pb->win.bpl;
+
+ DEBUG("PlanB: Display at %p is %d by %d, bytedepth %d,"
+ " bpl %d (+ %d)\n", v.base, v.width,v.height,
+ pb->win.bpp, pb->win.bpl, pb->win.pad);
+


+ pb->cmd_buff_inited = 0;

+ if(pb->overlay) {
+ suspend_overlay(pb);
+ fill_cmd_buff(pb);
+ resume_overlay(pb);
+ }
+ planb_unlock(pb);
+ return 0;
+ }
+ case VIDIOCGFBUF:
+ {
+ struct video_buffer v;
+
+ DEBUG("PlanB: IOCTL VIDIOCGFBUF\n");
+
+ v.base = (void *)pb->frame_buffer_phys;
+ v.height = pb->win.sheight;
+ v.width = pb->win.swidth;
+ v.depth = pb->win.depth;
+ v.bytesperline = pb->win.bpl + pb->win.pad;
+ if (copy_to_user(arg, &v, sizeof(v)))
+ return -EFAULT;
+ return 0;
+ }
+ case VIDIOCCAPTURE:


+ {
+ int i;
+

+ if(copy_from_user(&i, arg, sizeof(i)))
+ return -EFAULT;
+ if(i==0) {
+ DEBUG("PlanB: IOCTL VIDIOCCAPTURE Stop\n");
+
+ if (!(pb->overlay))
+ return 0;
+ planb_lock(pb);
+ pb->overlay = 0;
+ overlay_stop(pb);
+ planb_unlock(pb);
+ } else {
+ DEBUG("PlanB: IOCTL VIDIOCCAPTURE Start\n");
+
+ if (pb->frame_buffer_phys == 0 ||
+ pb->win.width == 0 ||
+ pb->win.height == 0)
+ return -EINVAL;
+ if (pb->overlay)
+ return 0;
+ planb_lock(pb);
+ pb->overlay = 1;
+ if(!(pb->cmd_buff_inited))
+ fill_cmd_buff(pb);
+ overlay_start(pb);
+ planb_unlock(pb);


+ }
+ return 0;
+ }

+ case VIDIOCGCHAN:
+ {
+ struct video_channel v;
+
+ DEBUG("PlanB: IOCTL VIDIOCGCHAN\n");
+
+ if(copy_from_user(&v, arg,sizeof(v)))
+ return -EFAULT;
+ v.flags = 0;
+ v.tuners = 0;
+ v.type = VIDEO_TYPE_CAMERA;
+ v.norm = pb->win.norm;
+ switch(v.channel)
+ {
+ case 0:
+ strcpy(v.name,"Composite");


+ break;
+ case 1:

+ strcpy(v.name,"SVHS");


+ break;
+ default:
+ return -EINVAL;

+ break;
+ }
+ if(copy_to_user(arg,&v,sizeof(v)))
+ return -EFAULT;


+
+ return 0;
+ }

+ case VIDIOCSCHAN:
+ {
+ struct video_channel v;
+
+ DEBUG("PlanB: IOCTL VIDIOCSCHAN\n");
+
+ if(copy_from_user(&v, arg, sizeof(v)))
+ return -EFAULT;
+
+ if (v.norm != pb->win.norm) {
+ int i, maxlines;
+
+ switch (v.norm)
+ {
+ case VIDEO_MODE_PAL:
+ case VIDEO_MODE_SECAM:
+ maxlines = PLANB_MAXLINES;
+ break;
+ case VIDEO_MODE_NTSC:
+ maxlines = PLANB_NTSC_MAXLINES;


+ break;
+ default:
+ return -EINVAL;

+ break;
+ }
+ planb_lock(pb);
+ /* empty the grabbing queue */
+ while(pb->grabbing)
+ interruptible_sleep_on(&pb->capq);
+ pb->maxlines = maxlines;
+ pb->win.norm = v.norm;
+ /* Stop overlay if running */
+ suspend_overlay(pb);


+ for(i = 0; i < MAX_GBUFFERS; i++)

+ pb->gnorm_switch[i] = 1;
+ /* I know it's an overkill, but.... */
+ fill_cmd_buff(pb);
+ /* ok, now init it accordingly */
+ saa_init_regs (pb);
+ /* restart overlay if it was running */
+ resume_overlay(pb);
+ planb_unlock(pb);
+ }
+
+ switch(v.channel)
+ {
+ case 0: /* Composite */
+ saa_set (SAA7196_IOCC,
+ ((saa_regs[pb->win.norm][SAA7196_IOCC] &
+ ~7) | 3), pb);
+ break;
+ case 1: /* SVHS */
+ saa_set (SAA7196_IOCC,
+ ((saa_regs[pb->win.norm][SAA7196_IOCC] &
+ ~7) | 4), pb);


+ break;
+ default:
+ return -EINVAL;

+ break;
+ }


+
+ return 0;
+ }

+ case VIDIOCGPICT:
+ {
+ struct video_picture vp = pb->picture;
+
+ DEBUG("PlanB: IOCTL VIDIOCGPICT\n");
+
+ switch(pb->win.color_fmt) {
+ case PLANB_GRAY:
+ vp.palette = VIDEO_PALETTE_GREY;
+ case PLANB_COLOUR15:
+ vp.palette = VIDEO_PALETTE_RGB555;
+ break;
+ case PLANB_COLOUR32:
+ vp.palette = VIDEO_PALETTE_RGB32;
+ break;
+ default:
+ vp.palette = 0;
+ break;
+ }
+
+ if(copy_to_user(arg,&vp,sizeof(vp)))
+ return -EFAULT;
+ return 0;
+ }
+ case VIDIOCSPICT:
+ {
+ struct video_picture vp;
+
+ DEBUG("PlanB: IOCTL VIDIOCSPICT\n");
+
+ if(copy_from_user(&vp,arg,sizeof(vp)))
+ return -EFAULT;
+ pb->picture = vp;
+ /* Should we do sanity checks here? */
+ saa_set (SAA7196_BRIG, (unsigned char)
+ ((pb->picture.brightness) >> 8), pb);
+ saa_set (SAA7196_HUEC, (unsigned char)
+ ((pb->picture.hue) >> 8) ^ 0x80, pb);
+ saa_set (SAA7196_CSAT, (unsigned char)
+ ((pb->picture.colour) >> 9), pb);
+ saa_set (SAA7196_CONT, (unsigned char)
+ ((pb->picture.contrast) >> 9), pb);
+
+ return 0;
+ }
+ case VIDIOCSWIN:
+ {
+ struct video_window vw;
+ struct video_clip clip;
+ int i;
+
+ DEBUG("PlanB: IOCTL VIDIOCSWIN\n");
+
+ if(copy_from_user(&vw,arg,sizeof(vw)))
+ return -EFAULT;
+
+ planb_lock(pb);
+ /* Stop overlay if running */
+ suspend_overlay(pb);
+ pb->win.interlace = (vw.height > pb->maxlines/2)? 1: 0;
+ if (pb->win.x != vw.x ||
+ pb->win.y != vw.y ||
+ pb->win.width != vw.width ||
+ pb->win.height != vw.height ||
+ !pb->cmd_buff_inited) {
+ pb->win.x = vw.x;
+ pb->win.y = vw.y;
+ pb->win.width = vw.width;
+ pb->win.height = vw.height;
+ fill_cmd_buff(pb);
+ }
+ /* Reset clip mask */
+ memset ((void *) pb->mask, 0xff, (pb->maxlines
+ * ((PLANB_MAXPIXELS + 7) & ~7)) / 8);
+ /* Add any clip rects */
+ for (i = 0; i < vw.clipcount; i++) {
+ if (copy_from_user(&clip, vw.clips + i,
+ sizeof(struct video_clip)))
+ return -EFAULT;
+ add_clip(pb, &clip);
+ }
+ /* restart overlay if it was running */
+ resume_overlay(pb);
+ planb_unlock(pb);
+ return 0;
+ }
+ case VIDIOCGWIN:
+ {


+ struct video_window vw;
+

+ DEBUG("PlanB: IOCTL VIDIOCGWIN\n");
+
+ vw.x=pb->win.x;
+ vw.y=pb->win.y;
+ vw.width=pb->win.width;
+ vw.height=pb->win.height;
+ vw.chromakey=0;
+ vw.flags=0;
+ if(pb->win.interlace)
+ vw.flags|=VIDEO_WINDOW_INTERLACE;
+ if(copy_to_user(arg,&vw,sizeof(vw)))
+ return -EFAULT;
+ return 0;
+ }
+ case VIDIOCSYNC: {
+ int i;
+
+ IDEBUG("PlanB: IOCTL VIDIOCSYNC\n");
+
+ if(copy_from_user((void *)&i,arg,sizeof(int)))
+ return -EFAULT;
+
+ IDEBUG("PlanB: sync to frame %d\n", i);
+
+ if(i > (MAX_GBUFFERS - 1) || i < 0)
+ return -EINVAL;
+chk_grab:
+ switch (pb->frame_stat[i]) {
+ case GBUFFER_UNUSED:
+ return -EINVAL;
+ case GBUFFER_GRABBING:
+ IDEBUG("PlanB: waiting for grab"
+ " done (%d)\n", i);
+ interruptible_sleep_on(&pb->capq);
+ goto chk_grab;
+ case GBUFFER_DONE:


+ pb->frame_stat[i] = GBUFFER_UNUSED;

+ break;


+ }
+ return 0;
+ }
+

+ case VIDIOCMCAPTURE:
+ {
+ struct video_mmap vm;
+ volatile unsigned int status;
+
+ IDEBUG("PlanB: IOCTL VIDIOCMCAPTURE\n");
+
+ if(copy_from_user((void *) &vm,(void *)arg,sizeof(vm)))
+ return -EFAULT;
+ status = pb->frame_stat[vm.frame];
+ if (status != GBUFFER_UNUSED)
+ return -EBUSY;
+
+ return vgrab(pb, &vm);
+ }
+
+ case VIDIOCGMBUF:
+ {
+ int i;
+ struct video_mbuf vm;
+
+ DEBUG("PlanB: IOCTL VIDIOCGMBUF\n");
+
+ memset(&vm, 0 , sizeof(vm));
+ vm.size = PLANB_MAX_FBUF * MAX_GBUFFERS;
+ vm.frames = MAX_GBUFFERS;


+ for(i = 0; i<MAX_GBUFFERS; i++)

+ vm.offsets[i] = PLANB_MAX_FBUF * i;
+ if(copy_to_user((void *)arg, (void *)&vm, sizeof(vm)))
+ return -EFAULT;


+ return 0;
+ }
+

+ case PLANBIOCGSAAREGS:
+ {
+ struct planb_saa_regs preg;
+
+ DEBUG("PlanB: IOCTL PLANBIOCGSAAREGS\n");
+
+ if(copy_from_user(&preg, arg, sizeof(preg)))
+ return -EFAULT;
+ if(preg.addr >= SAA7196_NUMREGS)
+ return -EINVAL;
+ preg.val = saa_regs[pb->win.norm][preg.addr];
+ if(copy_to_user((void *)arg, (void *)&preg,
+ sizeof(preg)))
+ return -EFAULT;


+ return 0;
+ }
+

+ case PLANBIOCSSAAREGS:
+ {
+ struct planb_saa_regs preg;
+
+ DEBUG("PlanB: IOCTL PLANBIOCSSAAREGS\n");
+
+ if(copy_from_user(&preg, arg, sizeof(preg)))
+ return -EFAULT;
+ if(preg.addr >= SAA7196_NUMREGS)
+ return -EINVAL;
+ saa_set (preg.addr, preg.val, pb);


+ return 0;
+ }
+

+ case PLANBIOCGSTAT:
+ {
+ struct planb_stat_regs pstat;
+
+ DEBUG("PlanB: IOCTL PLANBIOCGSTAT\n");
+
+ pstat.ch1_stat = in_le32(&pb->planb_base->ch1.status);
+ pstat.ch2_stat = in_le32(&pb->planb_base->ch2.status);
+ pstat.saa_stat0 = saa_status(0, pb);
+ pstat.saa_stat1 = saa_status(1, pb);
+
+ if(copy_to_user((void *)arg, (void *)&pstat,
+ sizeof(pstat)))
+ return -EFAULT;


+ return 0;
+ }
+

+ case PLANBIOCSMODE: {
+ int v;
+
+ DEBUG("PlanB: IOCTL PLANBIOCSMODE\n");
+
+ if(copy_from_user(&v, arg, sizeof(v)))
+ return -EFAULT;
+
+ switch(v)
+ {
+ case PLANB_TV_MODE:
+ saa_set (SAA7196_STDC,


+ (saa_regs[pb->win.norm][SAA7196_STDC] &

+ 0x7f), pb);
+ break;
+ case PLANB_VTR_MODE:
+ saa_set (SAA7196_STDC,


+ (saa_regs[pb->win.norm][SAA7196_STDC] |

+ 0x80), pb);


+ break;
+ default:
+ return -EINVAL;

+ break;
+ }
+ pb->win.mode = v;
+ return 0;
+ }
+ case PLANBIOCGMODE: {
+ int v=pb->win.mode;
+
+ DEBUG("PlanB: IOCTL PLANBIOCGMODE\n");
+
+ if(copy_to_user(arg,&v,sizeof(v)))
+ return -EFAULT;
+ return 0;
+ }
+#ifdef PLANB_GSCANLINE
+ case PLANBG_GRAB_BPL: {
+ int v=pb->gbytes_per_line;
+
+ DEBUG("PlanB: IOCTL PLANBG_GRAB_BPL\n");
+
+ if(copy_to_user(arg,&v,sizeof(v)))
+ return -EFAULT;
+ return 0;


+ }
+#endif /* PLANB_GSCANLINE */

+ case PLANB_INTR_DEBUG: {
+ int i;
+
+ DEBUG("PlanB: IOCTL PLANB_INTR_DEBUG\n");
+
+ if(copy_from_user(&i, arg, sizeof(i)))
+ return -EFAULT;
+
+ /* avoid hang ups all together */


+ for (i = 0; i < MAX_GBUFFERS; i++) {

+ if(pb->frame_stat[i] == GBUFFER_GRABBING) {
+ pb->frame_stat[i] = GBUFFER_DONE;
+ }
+ }
+ if(pb->grabbing)
+ pb->grabbing--;
+ wake_up_interruptible(&pb->capq);
+ return 0;
+ }
+ case PLANB_INV_REGS: {
+ int i;
+ struct planb_any_regs any;
+
+ DEBUG("PlanB: IOCTL PLANB_INV_REGS\n");
+
+ if(copy_from_user(&any, arg, sizeof(any)))
+ return -EFAULT;
+ if(any.offset < 0 || any.offset + any.bytes > 0x400)
+ return -EINVAL;
+ if(any.bytes > 128)
+ return -EINVAL;
+ for (i = 0; i < any.bytes; i++) {
+ any.data[i] =
+ in_8((unsigned char *)pb->planb_base
+ + any.offset + i);
+ }
+ if(copy_to_user(arg,&any,sizeof(any)))
+ return -EFAULT;
+ return 0;
+ }
+ default:
+ {
+ DEBUG("PlanB: Unimplemented IOCTL\n");
+ return -ENOIOCTLCMD;
+ }
+ /* Some IOCTLs are currently unsupported on PlanB */
+ case VIDIOCGTUNER: {
+ DEBUG("PlanB: IOCTL VIDIOCGTUNER\n");
+ goto unimplemented; }
+ case VIDIOCSTUNER: {
+ DEBUG("PlanB: IOCTL VIDIOCSTUNER\n");
+ goto unimplemented; }
+ case VIDIOCSFREQ: {
+ DEBUG("PlanB: IOCTL VIDIOCSFREQ\n");
+ goto unimplemented; }
+ case VIDIOCGFREQ: {
+ DEBUG("PlanB: IOCTL VIDIOCGFREQ\n");
+ goto unimplemented; }
+ case VIDIOCKEY: {
+ DEBUG("PlanB: IOCTL VIDIOCKEY\n");
+ goto unimplemented; }
+ case VIDIOCSAUDIO: {
+ DEBUG("PlanB: IOCTL VIDIOCSAUDIO\n");
+ goto unimplemented; }
+ case VIDIOCGAUDIO: {
+ DEBUG("PlanB: IOCTL VIDIOCGAUDIO\n");
+ goto unimplemented; }
+unimplemented:
+ DEBUG(" Unimplemented\n");
+ return -ENOIOCTLCMD;


+ }
+ return 0;
+}
+
+/*

+ * This maps the vmalloced and reserved fbuffer to user space.
+ *
+ * FIXME:
+ * - PAGE_READONLY should suffice!?
+ * - remap_page_range is kind of inefficient for page by page remapping.
+ * But e.g. pte_alloc() does not work in modules ... :-(
+ */
+
+static int planb_mmap(struct video_device *dev, const char *adr, unsigned long size)
+{
+ struct planb *pb=(struct planb *)dev;
+ unsigned long start=(unsigned long) adr;
+ unsigned long page;
+ void *pos;
+
+ if (size>MAX_GBUFFERS*PLANB_MAX_FBUF)
+ return -EINVAL;
+ if (!pb->fbuffer)
+ {
+ if(fbuffer_alloc(pb))
+ return -EINVAL;
+ }
+ pos = (void *)pb->fbuffer;


+ while (size > 0)
+ {

+ page = vmalloc_to_phys(pos);
+ if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED))
+ return -EAGAIN;
+ start+=PAGE_SIZE;
+ pos+=PAGE_SIZE;
+ size-=PAGE_SIZE;

+ }
+ return 0;
+}
+

+/* This gets called upon device registration */
+/* we could do some init here */
+static int planb_init_done(struct video_device *dev)


+{
+ return 0;
+}
+

+static struct video_device planb_template=
+{
+ PLANB_DEVICE_NAME,
+ VID_TYPE_OVERLAY,
+ VID_HARDWARE_PLANB,
+ planb_open,
+ planb_close,
+ planb_read,
+ planb_write,
+#if LINUX_VERSION_CODE >= 0x020100
+ NULL, /* poll */
+#endif
+ planb_ioctl,
+ planb_mmap, /* mmap? */
+ planb_init_done,
+ NULL, /* pointer to private data */
+ 0,
+ 0
+};
+
+static int init_planb(struct planb *pb)
+{
+ unsigned char saa_rev;
+ int i, result;
+
+ memset ((void *) &pb->win, 0, sizeof (struct planb_window));
+ /* Simple sanity check */
+ if(def_norm >= NUM_SUPPORTED_NORM || def_norm < 0) {
+ printk(KERN_ERR "PlanB: Option(s) invalid\n");
+ return -2;
+ }
+ pb->win.norm = def_norm;
+ pb->win.mode = PLANB_TV_MODE; /* TV mode */
+ pb->win.interlace=1;
+ pb->win.x=0;
+ pb->win.y=0;
+ pb->win.width=768; /* 640 */
+ pb->win.height=576; /* 480 */
+ pb->maxlines=576;
+#if 0
+ btv->win.cropwidth=768; /* 640 */
+ btv->win.cropheight=576; /* 480 */
+ btv->win.cropx=0;
+ btv->win.cropy=0;
+#endif
+ pb->win.pad=0;
+ pb->win.bpp=4;
+ pb->win.depth=32;
+ pb->win.color_fmt=PLANB_COLOUR32;
+ pb->win.bpl=1024*pb->win.bpp;
+ pb->win.swidth=1024;
+ pb->win.sheight=768;
+#ifdef PLANB_GSCANLINE
+ if((pb->gbytes_per_line = PLANB_MAXPIXELS * 4) > PAGE_SIZE
+ || (pb->gbytes_per_line <= 0))
+ return -3;
+ else {
+ /* page align pb->gbytes_per_line for DMA purpose */
+ for(i = PAGE_SIZE; pb->gbytes_per_line < (i>>1);)
+ i>>=1;
+ pb->gbytes_per_line = i;
+ }
+#endif
+ pb->tab_size = PLANB_MAXLINES + 40;


+ pb->suspend = 0;

+ pb->lock = 0;
+ pb->lockq = NULL;
+ pb->ch1_cmd = 0;
+ pb->ch2_cmd = 0;
+ pb->mask = 0;


+ pb->priv_space = 0;

+ pb->offset = 0;
+ pb->user = 0;
+ pb->overlay = 0;
+ pb->suspendq = NULL;


+ pb->cmd_buff_inited = 0;

+ pb->frame_buffer_phys = 0;
+
+ /* Reset DMA controllers */


+ planb_dbdma_stop(&pb->planb_base->ch2);
+ planb_dbdma_stop(&pb->planb_base->ch1);
+

+ saa_rev = (saa_status(0, pb) & 0xf0) >> 4;
+ printk(KERN_INFO "PlanB: SAA7196 video processor rev. %d\n", saa_rev);
+ /* Initialize the SAA registers in memory and on chip */
+ saa_init_regs (pb);
+
+ /* clear interrupt mask */
+ pb->intr_mask = PLANB_CLR_IRQ;
+
+ result = request_irq(pb->irq, planb_irq, 0, "PlanB", (void *)pb);
+ if (result==-EINVAL) {
+ printk(KERN_ERR "PlanB: Bad irq number (%d) or handler\n",
+ (int)pb->irq);
+ return result;
+ }
+ if (result==-EBUSY) {
+ printk(KERN_ERR "PlanB: I don't know why, but IRQ %d busy\n",
+ (int)pb->irq);
+ return result;
+ }
+ if (result < 0)
+ return result;
+
+ /* Now add the template and register the device unit. */
+ memcpy(&pb->video_dev,&planb_template,sizeof(planb_template));
+
+ pb->picture.brightness=0x90<<8;
+ pb->picture.contrast = 0x70 << 8;
+ pb->picture.colour = 0x70<<8;
+ pb->picture.hue = 0x8000;
+ pb->picture.whiteness = 0;
+ pb->picture.depth = pb->win.depth;
+
+ pb->frame_stat=NULL;
+ pb->capq=NULL;
+ for(i=0; i<MAX_GBUFFERS; i++) {
+ pb->gbuffer[i]=NULL;
+ pb->gwidth[i]=0;
+ pb->gheight[i]=0;
+ pb->gfmt[i]=0;
+ pb->cap_cmd[i]=NULL;
+#ifndef PLANB_GSCANLINE
+ pb->l_fr_addr[i]=NULL;


+ pb->lsize[i] = 0;
+ pb->lnum[i] = 0;

+#endif
+ }
+ pb->fbuffer=NULL;
+ pb->grabbing=0;
+
+ /* clear interrupts */
+ out_le32(&pb->planb_base->intr_stat, PLANB_CLR_IRQ);
+ /* set interrupt mask */
+ pb->intr_mask = PLANB_FRM_IRQ;
+
+ if(video_register_device(&pb->video_dev, VFL_TYPE_GRABBER)<0)
+ return -1;


+
+ return 0;
+}
+
+/*

+ * Scan for a PlanB controller, request the irq and map the io memory
+ */
+
+static int find_planb(void)
+{
+ struct planb *pb;
+ struct device_node *planb_devices;
+ unsigned char dev_fn, confreg, bus;
+ unsigned int old_base, new_base;
+ unsigned int irq;
+
+ if (_machine != _MACH_Pmac)
+ return 0;
+
+ planb_devices = find_devices("planb");
+ if (planb_devices == 0) {
+ planb_num=0;
+ printk(KERN_WARNING "PlanB: no device found!\n");
+ return planb_num;
+ }
+
+ if (planb_devices->next != NULL)
+ printk(KERN_ERR "Warning: only using first PlanB device!\n");
+ pb = &planbs[0];
+ planb_num = 1;
+
+ if (planb_devices->n_addrs != 1) {
+ printk (KERN_WARNING "PlanB: expecting 1 address for planb "
+ "(got %d)", planb_devices->n_addrs);


+ return 0;
+ }
+

+ if (planb_devices->n_intrs == 0) {
+ printk(KERN_WARNING "PlanB: no intrs for device %s\n",
+ planb_devices->full_name);
+ return 0;
+ } else {
+ irq = planb_devices->intrs[0].line;
+ }
+
+ /* Initialize PlanB's PCI registers */
+
+ /* There is a bug with the way OF assigns addresses
+ to the devices behind the chaos bridge.
+ control needs only 0x1000 of space, but decodes only
+ the upper 16 bits. It therefore occupies a full 64K.
+ OF assigns the planb controller memory within this space;
+ so we need to change that here in order to access planb. */
+
+ /* We remap to 0xf1000000 in hope that nobody uses it ! */
+
+ bus = (planb_devices->addrs[0].space >> 16) & 0xff;
+ dev_fn = (planb_devices->addrs[0].space >> 8) & 0xff;
+ confreg = planb_devices->addrs[0].space & 0xff;
+ old_base = planb_devices->addrs[0].address;
+ new_base = 0xf1000000;
+
+ DEBUG("PlanB: Found on bus %d, dev %d, func %d, "
+ "membase 0x%x (base reg. 0x%x)\n",
+ bus, PCI_SLOT(dev_fn), PCI_FUNC(dev_fn), old_base, confreg);
+
+ /* Enable response in memory space, bus mastering,
+ use memory write and invalidate */
+ pcibios_write_config_word (bus, dev_fn, PCI_COMMAND,
+ PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
+ PCI_COMMAND_INVALIDATE);
+ /* Set PCI Cache line size & latency timer */
+ pcibios_write_config_byte (bus, dev_fn, PCI_CACHE_LINE_SIZE, 0x8);
+ pcibios_write_config_byte (bus, dev_fn, PCI_LATENCY_TIMER, 0x40);
+
+ /* Set the new base address */
+ pcibios_write_config_dword (bus, dev_fn, confreg, new_base);
+
+ planb_regs = (volatile struct planb_registers *)
+ ioremap (new_base, 0x400);
+ pb->planb_base = planb_regs;
+ pb->planb_base_phys = (struct planb_registers *)new_base;
+ pb->irq = irq;
+
+ return planb_num;
+}
+
+static void release_planb(void)
+{
+ int i;
+ struct planb *pb;
+
+ for (i=0;i<planb_num; i++)
+ {
+ pb=&planbs[i];
+
+ /* stop and flash DMAs unconditionally */


+ planb_dbdma_stop(&pb->planb_base->ch2);
+ planb_dbdma_stop(&pb->planb_base->ch1);
+

+ /* clear and free interrupts */
+ pb->intr_mask = PLANB_CLR_IRQ;
+ out_le32 (&pb->planb_base->intr_stat, PLANB_CLR_IRQ);
+ free_irq(pb->irq, pb);
+
+ /* make sure all allocated memory are freed */
+ planb_prepare_close(pb);
+
+ printk(KERN_INFO "PlanB: unregistering with v4l\n");
+ video_unregister_device(&pb->video_dev);
+
+ /* note that iounmap() does nothing on the PPC right now */
+ iounmap ((void *)pb->planb_base);
+ }
+}
+
+#ifdef MODULE
+
+int init_module(void)
+{
+#else
+__initfunc(int init_planbs(struct video_init *unused))
+{
+#endif
+ int i;
+
+ if (find_planb()<=0)
+ return -EIO;
+
+ for (i=0; i<planb_num; i++) {
+ if (init_planb(&planbs[i])<0) {
+ printk(KERN_ERR "PlanB: error registering device %d"
+ " with v4l\n", i);
+ release_planb();
+ return -EIO;
+ }
+ printk(KERN_INFO "PlanB: registered device %d with v4l\n", i);


+ }
+ return 0;
+}
+

+#ifdef MODULE
+
+void cleanup_module(void)
+{
+ release_planb();
+}
+
+#endif
diff -u --recursive --new-file v2.2.7/linux/drivers/char/planb.h linux/drivers/char/planb.h
--- v2.2.7/linux/drivers/char/planb.h Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/planb.h Fri May 7 11:05:30 1999
@@ -0,0 +1,229 @@


+/*
+ planb - PlanB frame grabber driver
+
+ PlanB is used in the 7x00/8x00 series of PowerMacintosh
+ Computers as video input DMA controller.
+
+ Copyright (C) 1998 Michel Lanners (ml...@cpu.lu)
+
+ Based largely on the bttv driver by Ralph Metzler (rj...@thp.uni-koeln.de)
+
+ Additional debugging and coding by Takashi Oe (t...@unlinfo.unl.edu)
+

+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+

+/* $Id: planb.h,v 1.13 1999/05/03 19:28:56 mlan Exp $ */
+
+#ifndef _PLANB_H_
+#define _PLANB_H_
+
+#ifdef __KERNEL__
+#include <asm/dbdma.h>
+#include "saa7196.h"
+#endif /* __KERNEL__ */
+
+#define PLANB_DEVICE_NAME "Apple PlanB Video-In"
+#define PLANB_REV "1.0"
+
+#ifdef __KERNEL__
+//#define PLANB_GSCANLINE /* use this if apps have the notion of */
+ /* grab buffer scanline */
+/* This should be safe for both PAL and NTSC */
+#define PLANB_MAXPIXELS 768
+#define PLANB_MAXLINES 576
+#define PLANB_NTSC_MAXLINES 480
+
+/* Uncomment your preferred norm ;-) */
+#define PLANB_DEF_NORM VIDEO_MODE_PAL
+//#define PLANB_DEF_NORM VIDEO_MODE_NTSC
+//#define PLANB_DEF_NORM VIDEO_MODE_SECAM
+
+/* fields settings */
+#define PLANB_GRAY 0x1 /* 8-bit mono? */
+#define PLANB_COLOUR15 0x2 /* 16-bit mode */
+#define PLANB_COLOUR32 0x4 /* 32-bit mode */
+#define PLANB_CLIPMASK 0x8 /* hardware clipmasking */
+
+/* misc. flags for PlanB DMA operation */
+#define CH_SYNC 0x1 /* synchronize channels (set by ch1;
+ cleared by ch2) */
+#define FIELD_SYNC 0x2 /* used for the start of each field
+ (0 -> 1 -> 0 for ch1; 0 -> 1 for ch2) */
+#define EVEN_FIELD 0x0 /* even field is detected if unset */
+#define DMA_ABORT 0x2 /* error or just out of sync if set */
+#define ODD_FIELD 0x4 /* odd field is detected if set */
+
+/* for capture operations */
+#define MAX_GBUFFERS 2
+#ifdef PLANB_GSCANLINE
+#define PLANB_MAX_FBUF 0x240000 /* 576 * 1024 * 4 */
+#define TAB_FACTOR (1)
+#else
+#define PLANB_MAX_FBUF 0x1b0000 /* 576 * 768 * 4 */
+#define TAB_FACTOR (2)
+#endif
+#endif /* __KERNEL__ */
+
+struct planb_saa_regs {
+ unsigned char addr;
+ unsigned char val;
+};
+
+struct planb_stat_regs {
+ unsigned int ch1_stat;
+ unsigned int ch2_stat;
+ unsigned char saa_stat0;
+ unsigned char saa_stat1;
+};
+
+struct planb_any_regs {
+ unsigned int offset;
+ unsigned int bytes;
+ unsigned char data[128];
+};
+
+/* planb private ioctls */
+#define PLANBIOCGSAAREGS _IOWR('v', BASE_VIDIOCPRIVATE, struct planb_saa_regs) /* Read a saa7196 reg value */
+#define PLANBIOCSSAAREGS _IOW('v', BASE_VIDIOCPRIVATE + 1, struct planb_saa_regs) /* Set a saa7196 reg value */
+#define PLANBIOCGSTAT _IOR('v', BASE_VIDIOCPRIVATE + 2, struct planb_stat_regs) /* Read planb status */
+#define PLANB_TV_MODE 1
+#define PLANB_VTR_MODE 2
+#define PLANBIOCGMODE _IOR('v', BASE_VIDIOCPRIVATE + 3, int) /* Get TV/VTR mode */
+#define PLANBIOCSMODE _IOW('v', BASE_VIDIOCPRIVATE + 4, int) /* Set TV/VTR mode */
+
+#ifdef PLANB_GSCANLINE
+#define PLANBG_GRAB_BPL _IOR('v', BASE_VIDIOCPRIVATE + 5, int) /* # of bytes per scanline in grab buffer */
+#endif
+
+/* call wake_up_interruptible() with appropriate actions */
+#define PLANB_INTR_DEBUG _IOW('v', BASE_VIDIOCPRIVATE + 20, int)
+/* investigate which reg does what */
+#define PLANB_INV_REGS _IOWR('v', BASE_VIDIOCPRIVATE + 21, struct planb_any_regs)
+
+#ifdef __KERNEL__
+
+/* Potentially useful macros */
+#define PLANB_SET(x) ((x) << 16 | (x))
+#define PLANB_CLR(x) ((x) << 16)
+
+/* This represents the physical register layout */
+struct planb_registers {
+ volatile struct dbdma_regs ch1; /* 0x00: video in */
+ volatile unsigned int even; /* 0x40: even field setting */
+ volatile unsigned int odd; /* 0x44; odd field setting */
+ unsigned int pad1[14]; /* empty? */
+ volatile struct dbdma_regs ch2; /* 0x80: clipmask out */
+ unsigned int pad2[16]; /* 0xc0: empty? */
+ volatile unsigned int reg3; /* 0x100: ???? */
+ volatile unsigned int intr_stat; /* 0x104: irq status */
+#define PLANB_CLR_IRQ 0x00 /* clear Plan B interrupt */
+#define PLANB_GEN_IRQ 0x01 /* assert Plan B interrupt */
+#define PLANB_FRM_IRQ 0x02 /* end of frame */
+#define PLANB_IRQ_CMD_MASK 0x00000003U /* reserve 2 lsbs for command */
+ unsigned int pad3[1]; /* empty? */
+ volatile unsigned int reg5; /* 0x10c: ??? */
+ unsigned int pad4[60]; /* empty? */
+ volatile unsigned char saa_addr; /* 0x200: SAA subadr */
+ char pad5[3];
+ volatile unsigned char saa_regval; /* SAA7196 write reg. val */
+ char pad6[3];
+ volatile unsigned char saa_status; /* SAA7196 status byte */
+ /* There is more unused stuff here */
+};
+
+struct planb_window {
+ int x, y;
+ ushort width, height;
+ ushort bpp, bpl, depth, pad;
+ ushort swidth, sheight;
+ int norm;
+ int interlace;
+ u32 color_fmt;
+ int chromakey;
+ int mode; /* used to switch between TV/VTR modes */
+};
+
+struct planb_suspend {
+ int overlay;
+ int frame;
+ struct dbdma_cmd cmd;
+};
+
+struct planb {
+ struct video_device video_dev;
+ struct video_picture picture; /* Current picture params */
+ struct video_audio audio_dev; /* Current audio params */
+
+ volatile struct planb_registers *planb_base; /* virt base of planb */
+ struct planb_registers *planb_base_phys; /* phys base of planb */
+ void *priv_space; /* Org. alloc. mem for kfree */
+ int user;
+ unsigned int tab_size;
+ int maxlines;
+ int lock;
+ struct wait_queue *lockq;
+ unsigned int irq; /* interrupt number */
+ volatile unsigned int intr_mask;
+
+ int overlay; /* overlay running? */
+ struct planb_window win;
+ unsigned long frame_buffer_phys; /* We need phys for DMA */
+ int offset; /* offset of pixel 1 */
+ volatile struct dbdma_cmd *ch1_cmd; /* Video In DMA cmd buffer */
+ volatile struct dbdma_cmd *ch2_cmd; /* Clip Out DMA cmd buffer */
+ volatile struct dbdma_cmd *overlay_last1;
+ volatile struct dbdma_cmd *overlay_last2;
+ unsigned long ch1_cmd_phys;
+ volatile unsigned char *mask; /* Clipmask buffer */
+ int suspend;
+ struct wait_queue *suspendq;
+ struct planb_suspend suspended;
+ int cmd_buff_inited; /* cmd buffer inited? */
+
+ int grabbing;
+ unsigned int gcount;
+ struct wait_queue *capq;
+ int last_fr;
+ int prev_last_fr;
+ unsigned char *fbuffer;
+ unsigned char *gbuffer[MAX_GBUFFERS];
+ volatile struct dbdma_cmd *cap_cmd[MAX_GBUFFERS];
+ volatile struct dbdma_cmd *last_cmd[MAX_GBUFFERS];
+ volatile struct dbdma_cmd *pre_cmd[MAX_GBUFFERS];
+ int need_pre_capture[MAX_GBUFFERS];
+#define PLANB_DUMMY 40 /* # of command buf's allocated for pre-capture seq. */
+ int gwidth[MAX_GBUFFERS], gheight[MAX_GBUFFERS];
+ unsigned int gfmt[MAX_GBUFFERS];
+ int gnorm_switch[MAX_GBUFFERS];
+ volatile unsigned int *frame_stat;
+#define GBUFFER_UNUSED 0x00U
+#define GBUFFER_GRABBING 0x01U
+#define GBUFFER_DONE 0x02U
+#ifdef PLANB_GSCANLINE
+ int gbytes_per_line;
+#else
+#define MAX_LNUM 431 /* change this if PLANB_MAXLINES or */
+ /* PLANB_MAXPIXELS changes */
+ unsigned char *l_fr_addr[MAX_GBUFFERS];
+ unsigned char *l_to_addr[MAX_GBUFFERS][MAX_LNUM];
+ int lsize[MAX_GBUFFERS], lnum[MAX_GBUFFERS];
+#endif
+};
+
+#endif /* __KERNEL__ */
+
+#endif /* _PLANB_H_ */
diff -u --recursive --new-file v2.2.7/linux/drivers/char/radio-cadet.c linux/drivers/char/radio-cadet.c
--- v2.2.7/linux/drivers/char/radio-cadet.c Fri Apr 16 14:47:30 1999
+++ linux/drivers/char/radio-cadet.c Mon May 10 13:00:10 1999
@@ -1,7 +1,7 @@
X /* cadet.c - A video4linux driver for the ADS Cadet AM/FM Radio Card
X *
X * by Fred Gleason <fr...@wava.com>
- * Version 0.1.2
+ * Version 0.3.1
X *
X * (Loosely) based on code for the Aztech radio card by
X *
@@ -22,42 +22,110 @@
X #include <asm/uaccess.h> /* copy to/from user */
X #include <linux/videodev.h> /* kernel radio structs */
X #include <linux/config.h> /* CONFIG_RADIO_CADET_PORT */
+#include <linux/param.h>
X
X #ifndef CONFIG_RADIO_CADET_PORT
X #define CONFIG_RADIO_CADET_PORT 0x330
X #endif
+#define RDS_BUFFER 256
X
X static int io=CONFIG_RADIO_CADET_PORT;
X static int users=0;
X static int curtuner=0;
+static int tunestat=0;
+static int sigstrength=0;
+struct wait_queue *tunerq,*rdsq,*readq;
+struct timer_list tunertimer,rdstimer,readtimer;
+static __u8 rdsin=0,rdsout=0,rdsstat=0;
+static unsigned char rdsbuf[RDS_BUFFER];
+static int cadet_lock=0;
+
+/*
+ * Signal Strength Threshold Values
+ * The V4L API spec does not define any particular unit for the signal
+ * strength value. These values are in microvolts of RF at the tuner's input.
+ */
+static __u16 sigtable[2][4]={{5,10,30,150},{28,40,63,1000}};
+
+
+
+void cadet_wake(unsigned long qnum)
+{
+ switch(qnum) {
+ case 0: /* cadet_setfreq */
+ wake_up(&tunerq);
+ break;
+ case 1: /* cadet_getrds */
+ wake_up(&rdsq);


+ break;
+ }
+}
+
+

+
+static int cadet_getrds(void)
+{
+ int rdsstat=0;
+
+ cadet_lock++;
+ outb(3,io); /* Select Decoder Control/Status */
+ outb(inb(io+1)&0x7f,io+1); /* Reset RDS detection */
+ cadet_lock--;
+ init_timer(&rdstimer);
+ rdstimer.function=cadet_wake;
+ rdstimer.data=(unsigned long)1;
+ rdstimer.expires=jiffies+(HZ/10);
+ rdsq=NULL;
+ add_timer(&rdstimer);
+ sleep_on(&rdsq);
+
+ cadet_lock++;
+ outb(3,io); /* Select Decoder Control/Status */
+ if((inb(io+1)&0x80)!=0) {
+ rdsstat|=VIDEO_TUNER_RDS_ON;
+ }
+ if((inb(io+1)&0x10)!=0) {
+ rdsstat|=VIDEO_TUNER_MBS_ON;
+ }
+ cadet_lock--;
+ return rdsstat;
+}
+
+
+
X
X static int cadet_getstereo(void)
X {
- if(curtuner!=0) { /* Only FM has stereo capability! */
+ if(curtuner!=0) { /* Only FM has stereo capability! */
X return 0;
X }
+ cadet_lock++;
X outb(7,io); /* Select tuner control */
X if((inb(io+1)&0x40)==0) {
+ cadet_lock--;
X return 1; /* Stereo pilot detected */
X }
X else {
+ cadet_lock--;
X return 0; /* Mono */
X }
X }
X
X
-static unsigned cadet_getfreq(void)
+
+static unsigned cadet_gettune(void)
X {
X int curvol,i;
- unsigned freq=0,test,fifo=0;
-
+ unsigned fifo=0;
X
X /*
X * Prepare for read
X */
+ cadet_lock++;
X outb(7,io); /* Select tuner control */
X curvol=inb(io+1); /* Save current volume/mute setting */
X outb(0x00,io+1); /* Ensure WRITE-ENABLE is LOW */
+ tunestat=0xffff;
X
X /*
X * Read the shift register
@@ -66,6 +134,7 @@
X fifo=(fifo<<1)|((inb(io+1)>>7)&0x01);
X if(i<24) {
X outb(0x01,io+1);
+ tunestat&=inb(io+1);
X outb(0x00,io+1);
X }
X }
@@ -74,6 +143,22 @@
X * Restore volume/mute setting
X */
X outb(curvol,io+1);
+ cadet_lock--;
+
+ return fifo;
+}
+
+
+
+static unsigned cadet_getfreq(void)
+{
+ int i;
+ unsigned freq=0,test,fifo=0;
+
+ /*
+ * Read current tuning
+ */
+ fifo=cadet_gettune();
X
X /*
X * Convert to actual frequency
@@ -98,10 +183,40 @@
X }
X
X
+
+static void cadet_settune(unsigned fifo)
+{
+ int i;
+ unsigned test;
+
+ cadet_lock++;
+ outb(7,io); /* Select tuner control */
+ /*
+ * Write the shift register
+ */
+ test=0;
+ test=(fifo>>23)&0x02; /* Align data for SDO */
+ test|=0x1c; /* SDM=1, SWE=1, SEN=1, SCK=0 */
+ outb(7,io); /* Select tuner control */
+ outb(test,io+1); /* Initialize for write */
+ for(i=0;i<25;i++) {
+ test|=0x01; /* Toggle SCK High */
+ outb(test,io+1);
+ test&=0xfe; /* Toggle SCK Low */
+ outb(test,io+1);
+ fifo=fifo<<1; /* Prepare the next bit */
+ test=0x1c|((fifo>>23)&0x02);
+ outb(test,io+1);
+ }
+ cadet_lock--;
+}
+
+
+
X static void cadet_setfreq(unsigned freq)
X {
X unsigned fifo;
- int i,test;
+ int i,j,test;
X int curvol;
X
X /*
@@ -129,39 +244,47 @@
X /*
X * Save current volume/mute setting
X */
+ cadet_lock++;
+ outb(7,io); /* Select tuner control */
X curvol=inb(io+1);
X
- /*
- * Write the shift register
- */
- test=0;
- test=(fifo>>23)&0x02; /* Align data for SDO */
- test|=0x1c; /* SDM=1, SWE=1, SEN=1, SCK=0 */
- outb(7,io); /* Select tuner control */
- outb(test,io+1); /* Initialize for write */
- for(i=0;i<25;i++) {
- test|=0x01; /* Toggle SCK High */
- outb(test,io+1);
- test&=0xfe; /* Toggle SCK Low */
- outb(test,io+1);
- fifo=fifo<<1; /* Prepare the next bit */
- test=0x1c|((fifo>>23)&0x02);
- outb(test,io+1);
- }
- /*
- * Restore volume/mute setting
- */
- outb(curvol,io+1);
+ /*
+ * Tune the card
+ */
+ for(j=3;j>-1;j--) {
+ cadet_settune(fifo|(j<<16));
+ outb(7,io); /* Select tuner control */
+ outb(curvol,io+1);
+ cadet_lock--;
+ init_timer(&tunertimer);
+ tunertimer.function=cadet_wake;
+ tunertimer.data=(unsigned long)0;
+ tunertimer.expires=jiffies+(HZ/10);
+ tunerq=NULL;
+ add_timer(&tunertimer);
+ sleep_on(&tunerq);
+ cadet_gettune();
+ if((tunestat&0x40)==0) { /* Tuned */
+ sigstrength=sigtable[curtuner][j];
+ return;
+ }
+ cadet_lock++;
+ }
+ cadet_lock--;
+ sigstrength=0;
X }
X
X
X static int cadet_getvol(void)
X {
+ cadet_lock++;
X outb(7,io); /* Select tuner control */
X if((inb(io+1)&0x20)!=0) {
+ cadet_lock--;
X return 0xffff;
X }
X else {
+ cadet_lock--;


X return 0;
X }
X }

@@ -169,6 +292,7 @@
X
X static void cadet_setvol(int vol)
X {
+ cadet_lock++;
X outb(7,io); /* Select tuner control */
X if(vol>0) {
X outb(0x20,io+1);
@@ -176,9 +300,88 @@
X else {
X outb(0x00,io+1);
X }
+ cadet_lock--;
X }
X
X
+
+void cadet_handler(unsigned long data)
+{
+ /*
+ * Service the RDS fifo
+ */
+ if(cadet_lock==0) {
+ outb(0x3,io); /* Select RDS Decoder Control */
+ if((inb(io+1)&0x20)!=0) {
+ printk(KERN_CRIT "cadet: RDS fifo overflow\n");
+ }
+ outb(0x80,io); /* Select RDS fifo */
+ while((inb(io)&0x80)!=0) {
+ rdsbuf[rdsin++]=inb(io+1);
+ if(rdsin==rdsout) {
+ printk(KERN_CRIT "cadet: RDS buffer overflow\n");
+ }
+ }
+ }
+
+ /*
+ * Service pending read
+ */
+ if((rdsin!=rdsout)&&(readq!=NULL)) {
+ wake_up_interruptible(&readq);
+ }
+
+ /*
+ * Clean up and exit
+ */
+ init_timer(&readtimer);
+ readtimer.function=cadet_handler;
+ readtimer.data=(unsigned long)0;
+ readtimer.expires=jiffies+(HZ/20);
+ add_timer(&readtimer);
+}
+
+
+
+static long cadet_read(struct video_device *v,char *buf,unsigned long count,
+ int nonblock)
+{
+ int i=0,c;
+ unsigned char readbuf[RDS_BUFFER];
+
+ if(rdsstat==0) {
+ cadet_lock++;
+ rdsstat=1;
+ outb(0x80,io); /* Select RDS fifo */
+ c=3*(inb(io)&0x03);
+ for(i=0;i<c;i++) { /* Flush the fifo */
+ inb(io+1);
+ }
+ cadet_lock--;
+ init_timer(&readtimer);
+ readtimer.function=cadet_handler;
+ readtimer.data=(unsigned long)0;
+ readtimer.expires=jiffies+(HZ/20);
+ add_timer(&readtimer);
+ }
+ if(rdsin==rdsout) {
+ if(nonblock) {
+ return -EWOULDBLOCK;
+ }
+ interruptible_sleep_on(&readq);
+ readq=NULL;
+ }
+ while((i<count)&&(rdsin!=rdsout)) {
+ readbuf[i++]=rdsbuf[rdsout++];
+ }
+ if(copy_to_user(buf,readbuf,i)) {
+ return -EFAULT;


+ }
+ return i;
+}
+

+
+
X static int cadet_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
X {
X unsigned freq;
@@ -217,10 +420,11 @@
X v.flags=0;
X v.mode=0;
X v.mode|=VIDEO_MODE_AUTO;
- v.signal=0xFFFF;
+ v.signal=sigstrength;
X if(cadet_getstereo()==1) {
X v.flags|=VIDEO_TUNER_STEREO_ON;
X }
+ v.flags|=cadet_getrds();
X if(copy_to_user(arg,&v, sizeof(v))) {
X return -EFAULT;
X }
@@ -233,7 +437,7 @@
X v.flags|=VIDEO_TUNER_LOW;
X v.mode=0;
X v.mode|=VIDEO_MODE_AUTO;
- v.signal=0xFFFF;
+ v.signal=sigstrength;
X if(copy_to_user(arg,&v, sizeof(v))) {
X return -EFAULT;
X }
@@ -313,11 +517,16 @@
X return -EBUSY;
X users++;
X MOD_INC_USE_COUNT;
+ readq=NULL;


X return 0;
X }
X

X static void cadet_close(struct video_device *dev)
X {
+ if(rdsstat==1) {
+ del_timer(&readtimer);
+ rdsstat=0;
+ }
X users--;
X MOD_DEC_USE_COUNT;
X }
@@ -330,7 +539,7 @@
X VID_HARDWARE_CADET,
X cadet_open,
X cadet_close,
- NULL, /* Can't read (no capture ability) */
+ cadet_read,
X NULL, /* Can't write */
X NULL, /* No poll */
X cadet_ioctl,
@@ -354,6 +563,7 @@
X }
X
X
+#ifndef MODULE
X static int cadet_probe(void)
X {
X static int iovals[8]={0x330,0x332,0x334,0x336,0x338,0x33a,0x33c,0x33e};
@@ -371,6 +581,7 @@
X }
X return -1;
X }
+#endif
X
X
X
diff -u --recursive --new-file v2.2.7/linux/drivers/char/radio-typhoon.c linux/drivers/char/radio-typhoon.c
--- v2.2.7/linux/drivers/char/radio-typhoon.c Wed Apr 28 11:37:30 1999
+++ linux/drivers/char/radio-typhoon.c Mon May 10 13:00:10 1999
@@ -48,6 +48,10 @@
X #define CONFIG_RADIO_TYPHOON_MUTEFREQ 0
X #endif
X
+#ifndef CONFIG_PROC_FS
+#undef CONFIG_RADIO_TYPHOON_PROC_FS
+#endif
+
X struct typhoon_device {
X int users;
X int iobase;
diff -u --recursive --new-file v2.2.7/linux/drivers/char/radio-zoltrix.c linux/drivers/char/radio-zoltrix.c
--- v2.2.7/linux/drivers/char/radio-zoltrix.c Fri Apr 16 14:47:30 1999
+++ linux/drivers/char/radio-zoltrix.c Mon May 10 13:00:10 1999
@@ -5,15 +5,16 @@
X * Due to the inconsistancy in reading from the signal flags
X * it is difficult to get an accurate tuned signal.
X *
- * There seems to be a problem with the volume setting that I must still
- * figure out.
- * It seems that the card has is not linear to 0 volume. It cuts off
- * at a low frequency, and it is not possible (at least I have not found)
+ * It seems that the card is not linear to 0 volume. It cuts off
+ * at a low volume, and it is not possible (at least I have not found)
X * to get fine volume control over the low volume range.
X *
X * Some code derived from code by Romolo Manfredini
X * rom...@bicnet.it
X *
+ * 1999-05-06 - (C. van Schaik)
+ * - Make signal strength and stereo scans
+ * kinder to cpu while in delay
X * 1999-01-05 - (C. van Schaik)
X * - Changed tuning to 1/160Mhz accuracy
X * - Added stereo support
@@ -51,18 +52,10 @@
X
X /* local things */
X
-static void sleep_delay(long n)
+static void sleep_delay(void)
X {
- /* Sleep nicely for 'n' uS */
- int d = n / (1000000 / HZ);
- if (!d)
- udelay(n);
- else {
- /* Yield CPU time */
- unsigned long x = jiffies;
- while ((jiffies - x) <= d)
- schedule();
- }
+ /* Sleep nicely for +/- 10 mS */
+ schedule();
X }
X
X static int zol_setvol(struct zol_device *dev, int vol)
@@ -79,7 +72,7 @@
X }
X
X outb(dev->curvol-1, io);
- sleep_delay(10000);
+ sleep_delay();
X inb(io + 2);
X
X return 0;
@@ -125,18 +118,18 @@
X while (i--) {
X if ((bitmask & 0x8000000000000000ull) != 0) {
X outb(0x80, io);
- sleep_delay(50);
+ udelay(50);
X outb(0x00, io);
- sleep_delay(50);
+ udelay(50);
X outb(0x80, io);
- sleep_delay(50);
+ udelay(50);
X } else {
X outb(0xc0, io);
- sleep_delay(50);
+ udelay(50);
X outb(0x40, io);
- sleep_delay(50);
+ udelay(50);
X outb(0xc0, io);
- sleep_delay(50);
+ udelay(50);
X }
X bitmask *= 2;
X }
@@ -144,16 +137,16 @@
X outb(0x80, io);
X outb(0xc0, io);
X outb(0x40, io);
- sleep_delay(1000);
+ udelay(1000);
X inb(io+2);
X
- sleep_delay(1000);
+ udelay(1000);
X if (dev->muted)
X {
X outb(0, io);
X outb(0, io);


SHAR_EOF
true || echo 'restore of patch-2.2.8 failed'
fi

echo 'End of part 14'
echo 'File patch-2.2.8 is continued in part 15'
echo 15 > _shar_seq_.tmp

Thomas...@ciw.uni-karlsruhe.de

unread,
May 12, 1999, 3:00:00 AM5/12/99
to
Archive-name: v2.2/patch-2.2.8/part15

#!/bin/sh
# this is part 15 of a 33 - part archive


# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.8 continued
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 15; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.8'
else
echo 'x - continuing with patch-2.2.8'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.8' &&

X inb(io + 3);
- sleep_delay(1000);
+ udelay(1000);
X } else
X zol_setvol(dev, dev->curvol);
X return 0;
@@ -167,10 +160,11 @@
X
X outb(0x00, io); /* This stuff I found to do nothing */
X outb(dev->curvol, io);
- sleep_delay(20000);
+ sleep_delay();
+ sleep_delay();
X
X a = inb(io);
- sleep_delay(1000);
+ sleep_delay();
X b = inb(io);
X
X if (a != b)
@@ -188,10 +182,11 @@
X
X outb(0x00, io);
X outb(dev->curvol, io);
- sleep_delay(20000);
+ sleep_delay();
+ sleep_delay();
X
X x1 = inb(io);
- sleep_delay(1000);
+ sleep_delay();
X x2 = inb(io);
X
X if ((x1 == x2) && (x1 == 0xcf))
@@ -362,7 +357,8 @@


X
X outb(0, io);
X outb(0, io);

- sleep_delay(20000);
+ sleep_delay();
+ sleep_delay();
X inb(io + 3);
X
X zoltrix_unit.curvol = 0;
diff -u --recursive --new-file v2.2.7/linux/drivers/char/saa7196.h linux/drivers/char/saa7196.h
--- v2.2.7/linux/drivers/char/saa7196.h Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/saa7196.h Fri May 7 11:05:30 1999
@@ -0,0 +1,117 @@
+/*
+ Definitions for the Philips SAA7196 digital video decoder,
+ scaler, and clock generator circuit (DESCpro), as used in
+ the PlanB video input of the Powermac 7x00/8x00 series.


+
+ Copyright (C) 1998 Michel Lanners (ml...@cpu.lu)
+

+ The register defines are shamelessly copied from the meteor
+ driver out of NetBSD (with permission),
+ and are copyrighted (c) 1995 Mark Tinguely and Jim Lowe
+ (Thanks !)


+
+ Additional debugging and coding by Takashi Oe (t...@unlinfo.unl.edu)
+

+ The default values used for PlanB are my mistakes.
+*/
+
+/* $Id: saa7196.h,v 1.5 1999/03/26 23:28:47 mlan Exp $ */
+
+#ifndef _SAA7196_H_
+#define _SAA7196_H_
+
+#define SAA7196_NUMREGS 0x31 /* Number of registers (used)*/
+#define NUM_SUPPORTED_NORM 3 /* Number of supported norms by PlanB */
+
+/* Decoder part: */
+#define SAA7196_IDEL 0x00 /* Increment delay */
+#define SAA7196_HSB5 0x01 /* H-sync begin; 50 hz */
+#define SAA7196_HSS5 0x02 /* H-sync stop; 50 hz */
+#define SAA7196_HCB5 0x03 /* H-clamp begin; 50 hz */
+#define SAA7196_HCS5 0x04 /* H-clamp stop; 50 hz */
+#define SAA7196_HSP5 0x05 /* H-sync after PHI1; 50 hz */
+#define SAA7196_LUMC 0x06 /* Luminance control */
+#define SAA7196_HUEC 0x07 /* Hue control */
+#define SAA7196_CKTQ 0x08 /* Colour Killer Threshold QAM (PAL, NTSC) */
+#define SAA7196_CKTS 0x09 /* Colour Killer Threshold SECAM */
+#define SAA7196_PALS 0x0a /* PAL switch sensitivity */
+#define SAA7196_SECAMS 0x0b /* SECAM switch sensitivity */
+#define SAA7196_CGAINC 0x0c /* Chroma gain control */
+#define SAA7196_STDC 0x0d /* Standard/Mode control */
+#define SAA7196_IOCC 0x0e /* I/O and Clock Control */
+#define SAA7196_CTRL1 0x0f /* Control #1 */
+#define SAA7196_CTRL2 0x10 /* Control #2 */
+#define SAA7196_CGAINR 0x11 /* Chroma Gain Reference */
+#define SAA7196_CSAT 0x12 /* Chroma Saturation */
+#define SAA7196_CONT 0x13 /* Luminance Contrast */
+#define SAA7196_HSB6 0x14 /* H-sync begin; 60 hz */
+#define SAA7196_HSS6 0x15 /* H-sync stop; 60 hz */
+#define SAA7196_HCB6 0x16 /* H-clamp begin; 60 hz */
+#define SAA7196_HCS6 0x17 /* H-clamp stop; 60 hz */
+#define SAA7196_HSP6 0x18 /* H-sync after PHI1; 60 hz */
+#define SAA7196_BRIG 0x19 /* Luminance Brightness */
+
+/* Scaler part: */
+#define SAA7196_FMTS 0x20 /* Formats and sequence */
+#define SAA7196_OUTPIX 0x21 /* Output data pixel/line */
+#define SAA7196_INPIX 0x22 /* Input data pixel/line */
+#define SAA7196_HWS 0x23 /* Horiz. window start */
+#define SAA7196_HFILT 0x24 /* Horiz. filter */
+#define SAA7196_OUTLINE 0x25 /* Output data lines/field */
+#define SAA7196_INLINE 0x26 /* Input data lines/field */
+#define SAA7196_VWS 0x27 /* Vertical window start */
+#define SAA7196_VYP 0x28 /* AFS/vertical Y processing */
+#define SAA7196_VBS 0x29 /* Vertical Bypass start */
+#define SAA7196_VBCNT 0x2a /* Vertical Bypass count */
+#define SAA7196_VBP 0x2b /* veritcal Bypass Polarity */
+#define SAA7196_VLOW 0x2c /* Colour-keying lower V limit */
+#define SAA7196_VHIGH 0x2d /* Colour-keying upper V limit */
+#define SAA7196_ULOW 0x2e /* Colour-keying lower U limit */
+#define SAA7196_UHIGH 0x2f /* Colour-keying upper U limit */
+#define SAA7196_DPATH 0x30 /* Data path setting */
+
+/* Initialization default values: */
+
+unsigned char saa_regs[NUM_SUPPORTED_NORM][SAA7196_NUMREGS] = {
+
+/* PAL, 768x576 (no scaling), composite video-in */
+/* Decoder: */
+ { 0x50, 0x30, 0x00, 0xe8, 0xb6, 0xe5, 0x63, 0xff,
+ 0xfe, 0xf0, 0xfe, 0xe0, 0x20, 0x06, 0x3b, 0x98,
+ 0x00, 0x59, 0x41, 0x45, 0x34, 0x0a, 0xf4, 0xd2,
+ 0xe9, 0xa2,
+/* Padding */
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+/* Scaler: */
+ 0x72, 0x80, 0x00, 0x03, 0x8d, 0x20, 0x20, 0x12,
+ 0xa5, 0x12, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00,
+ 0x87 },
+
+/* NTSC, 640x480? (no scaling), composite video-in */
+/* Decoder: */
+ { 0x50, 0x30, 0x00, 0xe8, 0xb6, 0xe5, 0x50, 0x00,
+ 0xf8, 0xf0, 0xfe, 0xe0, 0x00, 0x06, 0x3b, 0x98,
+ 0x00, 0x2c, 0x3d, 0x40, 0x34, 0x0a, 0xf4, 0xd2,
+ 0xe9, 0x98,
+/* Padding */
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+/* Scaler: */
+ 0x72, 0x80, 0x80, 0x03, 0x89, 0xf0, 0xf0, 0x0d,
+ 0xa0, 0x0d, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00,
+ 0x87 },
+
+/* SECAM, 768x576 (no scaling), composite video-in */
+/* Decoder: */
+ { 0x50, 0x30, 0x00, 0xe8, 0xb6, 0xe5, 0x63, 0xff,
+ 0xfe, 0xf0, 0xfe, 0xe0, 0x20, 0x07, 0x3b, 0x98,
+ 0x00, 0x59, 0x41, 0x45, 0x34, 0x0a, 0xf4, 0xd2,
+ 0xe9, 0xa2,
+/* Padding */
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+/* Scaler: */
+ 0x72, 0x80, 0x00, 0x03, 0x8d, 0x20, 0x20, 0x12,
+ 0xa5, 0x12, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00,
+ 0x87 }
+ };
+
+#endif /* _SAA7196_H_ */
diff -u --recursive --new-file v2.2.7/linux/drivers/char/specialix.c linux/drivers/char/specialix.c
--- v2.2.7/linux/drivers/char/specialix.c Thu Dec 31 10:29:00 1998
+++ linux/drivers/char/specialix.c Sun May 2 09:51:09 1999
@@ -2355,6 +2355,9 @@
X
X int irq [SX_NBOARD] = {0,};
X
+MODULE_PARM(iobase,"1-" __MODULE_STRING(SX_NBOARD) "i");
+MODULE_PARM(irq,"1-" __MODULE_STRING(SX_NBOARD) "i");
+
X /*
X * You can setup up to 4 boards.
X * by specifying "iobase=0xXXX,0xXXX ..." as insmod parameter.
diff -u --recursive --new-file v2.2.7/linux/drivers/isdn/act2000/act2000.h linux/drivers/isdn/act2000/act2000.h
--- v2.2.7/linux/drivers/isdn/act2000/act2000.h Wed Apr 1 20:11:49 1998
+++ linux/drivers/isdn/act2000/act2000.h Mon May 10 13:00:10 1999
@@ -213,7 +213,7 @@
X char regname[35]; /* Name used for request_region */
X } act2000_card;
X
-extern act2000_card *cards;
+extern act2000_card *actcards;
X
X extern __inline__ void act2000_schedule_tx(act2000_card *card)
X {
diff -u --recursive --new-file v2.2.7/linux/drivers/isdn/act2000/module.c linux/drivers/isdn/act2000/module.c
--- v2.2.7/linux/drivers/isdn/act2000/module.c Wed Apr 1 20:11:49 1998
+++ linux/drivers/isdn/act2000/module.c Mon May 10 13:00:10 1999
@@ -57,7 +57,7 @@
X };
X #define ISA_NRPORTS (sizeof(isa_ports)/sizeof(unsigned short))
X
-act2000_card *cards = (act2000_card *) NULL;
+act2000_card *actcards = (act2000_card *) NULL;
X
X /* Parameters to be set by insmod */
X static int act_bus = 0;
@@ -589,7 +589,7 @@
X static inline act2000_card *
X act2000_findcard(int driverid)
X {
- act2000_card *p = cards;
+ act2000_card *p = actcards;
X
X while (p) {
X if (p->myid == driverid)
@@ -714,8 +714,8 @@
X card->bus = bus;
X card->port = port;
X card->irq = irq;
- card->next = cards;
- cards = card;
+ card->next = actcards;
+ actcards = card;
X }
X
X /*
@@ -805,9 +805,9 @@
X bus);
X }
X }
- if (!cards)
+ if (!actcards)
X return 1;
- p = cards;
+ p = actcards;
X while (p) {
X initialized = 0;
X if (!p->interface.statcallb) {
@@ -870,9 +870,9 @@
X kfree(p);
X p = q->next;
X } else {
- cards = p->next;
+ actcards = p->next;
X kfree(p);
- p = cards;
+ p = actcards;
X }
X failed++;
X }
@@ -890,9 +890,9 @@
X act2000_init(void)
X {
X printk(KERN_INFO "%s\n", DRIVERNAME);
- if (!cards)
+ if (!actcards)
X act2000_addcard(act_bus, act_port, act_irq, act_id);
- if (!cards)
+ if (!actcards)
X printk(KERN_INFO "act2000: No cards defined yet\n");
X /* No symbols to export, hide all symbols */
X EXPORT_NO_SYMBOLS;
@@ -903,14 +903,14 @@
X void
X cleanup_module(void)
X {
- act2000_card *card = cards;
+ act2000_card *card = actcards;
X act2000_card *last;
X while (card) {
X unregister_card(card);
X del_timer(&card->ptimer);
X card = card->next;
X }
- card = cards;
+ card = actcards;
X while (card) {
X last = card;
X card = card->next;
diff -u --recursive --new-file v2.2.7/linux/drivers/macintosh/Makefile linux/drivers/macintosh/Makefile
--- v2.2.7/linux/drivers/macintosh/Makefile Thu Nov 19 09:56:28 1998
+++ linux/drivers/macintosh/Makefile Thu Apr 29 12:53:48 1999
@@ -16,7 +16,7 @@
X M_OBJS :=
X
X ifndef CONFIG_MBX
-L_OBJS := via-cuda.o nvram.o macio-adb.o via-pmu.o mediabay.o
+L_OBJS := via-cuda.o macio-adb.o via-pmu.o mediabay.o
X LX_OBJS := adb.o
X endif
X
@@ -25,6 +25,14 @@
X else
X ifeq ($(CONFIG_MAC_SERIAL),m)
X M_OBJS += macserial.o
+ endif
+endif
+
+ifeq ($(CONFIG_NVRAM),y)
+ L_OBJS += nvram.o
+else
+ ifeq ($(CONFIG_NVRAM),m)
+ M_OBJS += nvram.o
X endif
X endif
X
diff -u --recursive --new-file v2.2.7/linux/drivers/macintosh/adb.c linux/drivers/macintosh/adb.c
--- v2.2.7/linux/drivers/macintosh/adb.c Fri Apr 16 14:47:30 1999
+++ linux/drivers/macintosh/adb.c Thu Apr 29 12:53:48 1999
@@ -3,8 +3,19 @@
X * and the /dev/adb device on macintoshes.
X *
X * Copyright (C) 1996 Paul Mackerras.
+ *
+ * Modified to declare controllers as structures, added
+ * client notification of bus reset and handles PowerBook
+ * sleep, by Benjamin Herrenschmidt.
+ *
+ * To do:
+ *
+ * - /proc/adb to list the devices and infos
+ * - more /dev/adb to allow userland to receive the
+ * flow of auto-polling datas from a given device.
X */
X
+#include <linux/config.h>
X #include <linux/types.h>
X #include <linux/errno.h>
X #include <linux/kernel.h>
@@ -21,12 +32,23 @@
X #include <asm/hydra.h>
X #include <asm/init.h>
X
+EXPORT_SYMBOL(adb_controller);
+EXPORT_SYMBOL(adb_client_list);
X EXPORT_SYMBOL(adb_hardware);
X
+struct adb_controller *adb_controller = NULL;
+struct notifier_block *adb_client_list = NULL;
X enum adb_hw adb_hardware = ADB_NONE;
-int (*adb_send_request)(struct adb_request *req, int sync);
-int (*adb_autopoll)(int devs);
-int (*adb_reset_bus)(void);
+
+#ifdef CONFIG_PMAC_PBOOK
+static int adb_notify_sleep(struct notifier_block *, unsigned long, void *);
+static struct notifier_block adb_sleep_notifier = {
+ adb_notify_sleep,
+ NULL,
+ 0
+};
+#endif
+
X static int adb_scan_bus(void);
X
X static struct adb_handler {
@@ -35,13 +57,6 @@
X int handler_id;
X } adb_handler[16];
X
-__openfirmware
-
-static int adb_nodev(void)
-{


- return -1;
-}
-

X #if 0
X static void printADBreply(struct adb_request *req)
X {
@@ -61,8 +76,6 @@
X int devmask = 0;
X struct adb_request req;
X
- adb_reset_bus(); /* reset ADB bus */
-
X /* assumes adb_handler[] is all zeroes at this point */
X for (i = 1; i < 16; i++) {
X /* see if there is anything at address i */
@@ -147,22 +160,96 @@
X
X void adb_init(void)
X {
- adb_send_request = (void *) adb_nodev;
- adb_autopoll = (void *) adb_nodev;
- adb_reset_bus = adb_nodev;
X if ( (_machine != _MACH_chrp) && (_machine != _MACH_Pmac) )
X return;
+
X via_cuda_init();
X via_pmu_init();
X macio_adb_init();
- if (adb_hardware == ADB_NONE)
+
+ if (adb_controller == NULL)
X printk(KERN_WARNING "Warning: no ADB interface detected\n");
- else {
- int devs = adb_scan_bus();
- adb_autopoll(devs);
+ else
+ {
+ adb_hardware = adb_controller->kind;
+#ifdef CONFIG_PMAC_PBOOK
+ notifier_chain_register(&sleep_notifier_list,
+ &adb_sleep_notifier);
+#endif /* CONFIG_PMAC_PBOOK */
+
+ adb_reset_bus();
+ }
+}
+
+
+#ifdef CONFIG_PMAC_PBOOK
+/*
+ * notify clients before sleep and reset bus afterwards
+ */
+int
+adb_notify_sleep(struct notifier_block *this, unsigned long code, void *x)
+{
+ int ret;
+
+ switch (code) {
+ case PBOOK_SLEEP:
+ ret = notifier_call_chain(&adb_client_list, ADB_MSG_POWERDOWN, NULL);
+ if (ret & NOTIFY_STOP_MASK)
+ return -EBUSY;
+ case PBOOK_WAKE:
+ adb_reset_bus();
+ break;
+ }
+ return NOTIFY_DONE;
+}
+#endif /* CONFIG_PMAC_PBOOK */
+
+int
+adb_reset_bus(void)
+{
+ int ret, devs;


+ unsigned long flags;
+

+ if (adb_controller == NULL)
+ return -ENXIO;
+
+ ret = notifier_call_chain(&adb_client_list, ADB_MSG_PRE_RESET, NULL);
+ if (ret & NOTIFY_STOP_MASK)
+ return -EBUSY;
+
+ save_flags(flags);
+ cli();
+ memset(adb_handler, 0, sizeof(adb_handler));
+ restore_flags(flags);
+
+ if (adb_controller->reset_bus)
+ ret = adb_controller->reset_bus();
+ else
+ ret = 0;
+
+ if (!ret)
+ {
+ devs = adb_scan_bus();
+ if (adb_controller->autopoll)
+ adb_controller->autopoll(devs);
X }
+
+ ret = notifier_call_chain(&adb_client_list, ADB_MSG_POST_RESET, NULL);
+ if (ret & NOTIFY_STOP_MASK)
+ return -EBUSY;
+
+ return 1;
+}
+
+void
+adb_poll(void)
+{
+ if ((adb_controller == NULL)||(adb_controller->poll == NULL))
+ return;
+ adb_controller->poll();
X }
X
+
X int
X adb_request(struct adb_request *req, void (*done)(struct adb_request *),
X int flags, int nbytes, ...)
@@ -171,18 +258,25 @@
X int i;
X struct adb_request sreq;
X
+ if ((adb_controller == NULL) || (adb_controller->send_request == NULL))
+ return -ENXIO;
+ if (nbytes < 1)
+ return -EINVAL;
+
X if (req == NULL) {
X req = &sreq;
X flags |= ADBREQ_SYNC;
X }
- req->nbytes = nbytes;
+ req->nbytes = nbytes+1;
X req->done = done;
X req->reply_expected = flags & ADBREQ_REPLY;
+ req->data[0] = ADB_PACKET;
X va_start(list, nbytes);
X for (i = 0; i < nbytes; ++i)
- req->data[i] = va_arg(list, int);
+ req->data[i+1] = va_arg(list, int);
X va_end(list);
- return adb_send_request(req, flags & ADBREQ_SYNC);
+
+ return adb_controller->send_request(req, flags & ADBREQ_SYNC);
X }
X
X /* Ultimately this should return the number of devices with
@@ -247,7 +341,7 @@
X if (req.reply_len < 2)
X return 0;
X adb_request(&req, NULL, ADBREQ_SYNC, 3,
- ADB_WRITEREG(address, 3), req.reply[1], new_id);
+ ADB_WRITEREG(address, 3), req.reply[1] & 0xF0, new_id);
X adb_request(&req, NULL, ADBREQ_SYNC | ADBREQ_REPLY, 1,
X ADB_READREG(address, 3));
X if (req.reply_len < 2)
@@ -318,7 +412,7 @@
X {
X struct adbdev_state *state;
X
- if (MINOR(inode->i_rdev) > 0 || adb_hardware == ADB_NONE)
+ if (MINOR(inode->i_rdev) > 0 || (adb_controller == NULL)/*adb_hardware == ADB_NONE*/)
X return -ENXIO;
X state = kmalloc(sizeof(struct adbdev_state), GFP_KERNEL);
X if (state == 0)
@@ -420,7 +514,7 @@
X static ssize_t adb_write(struct file *file, const char *buf,
X size_t count, loff_t *ppos)
X {
- int ret, i;
+ int ret/*, i*/;
X struct adbdev_state *state = file->private_data;
X struct adb_request *req;
X
@@ -439,36 +533,26 @@
X req->done = adb_write_done;
X req->arg = (void *) state;
X req->complete = 0;
-
+
X ret = -EFAULT;
X if (copy_from_user(req->data, buf, count))
X goto out;
X
X atomic_inc(&state->n_pending);
- switch (adb_hardware) {
- case ADB_NONE:
- ret = -ENXIO;
- break;
- case ADB_VIACUDA:
- req->reply_expected = 1;
- ret = cuda_send_request(req);


- break;
- case ADB_VIAPMU:

- if (req->data[0] != ADB_PACKET) {
- ret = pmu_send_request(req);
- break;
- }
- /* else fall through */
- default:
- ret = -EINVAL;
- if (req->data[0] != ADB_PACKET)
- break;
- for (i = 0; i < req->nbytes-1; ++i)
- req->data[i] = req->data[i+1];
- req->nbytes--;
- req->reply_expected = ((req->data[0] & 0xc) == 0xc);
- ret = adb_send_request(req, 0);
- break;
+
+ /* Special case for ADB_BUSRESET request, all others are sent to
+ the controller */
+ if ((req->data[0] == ADB_PACKET)&&(count > 1)
+ &&(req->data[1] == ADB_BUSRESET))
+ ret = adb_reset_bus();
+ else
+ {
+ req->reply_expected = ((req->data[1] & 0xc) == 0xc);
+
+ if (adb_controller && adb_controller->send_request)
+ ret = adb_controller->send_request(req, 0);
+ else
+ ret = -ENXIO;
X }
X
X if (ret != 0) {
diff -u --recursive --new-file v2.2.7/linux/drivers/macintosh/mac_keyb.c linux/drivers/macintosh/mac_keyb.c
--- v2.2.7/linux/drivers/macintosh/mac_keyb.c Wed Apr 28 11:37:30 1999
+++ linux/drivers/macintosh/mac_keyb.c Thu Apr 29 12:53:48 1999
@@ -7,6 +7,27 @@
X * (see that file for its authors and contributors).
X *
X * Copyright (C) 1996 Paul Mackerras.
+ *
+ * Adapted to ADB changes and support for more devices by
+ * Benjamin Herrenschmidt. Adapted from code in MkLinux
+ * and reworked.
+ *
+ * Supported devices:
+ *
+ * - Standard 1 button mouse
+ * - All standard Apple Extended protocol (handler ID 4)
+ * mice & trackballs
+ * - PowerBook Trackpad (default setup: enable tapping)
+ * - MicroSpeed mouse & trackball (needs testing)
+ * - CH Products Trackball Pro (needs testing)
+ * - Contour Design (Contour Mouse)
+ * - Hunter digital (NoHandsMouse)
+ * - Kensignton TurboMouse 5 (needs testing)
+ *
+ * To do:
+ *
+ * Improve Kensignton support, add MacX support as a dynamic
+ * option (not a compile-time option).
X */
X
X #include <linux/sched.h>
@@ -32,6 +53,41 @@
X #define KEYB_LEDREG 2 /* register # for leds on ADB keyboard */
X #define MOUSE_DATAREG 0 /* reg# for movement/button codes from mouse */
X
+static int adb_message_handler(struct notifier_block *, unsigned long, void *);
+static struct notifier_block mackeyb_adb_notifier = {
+ adb_message_handler,
+ NULL,
+ 0
+};
+
+/* this map indicates which keys shouldn't autorepeat. */
+static unsigned char dont_repeat[128] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* esc...option */
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, /* fn, num lock */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, /* scroll lock */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+/* Simple translation table for the SysRq keys */
+
+#ifdef CONFIG_MAGIC_SYSRQ
+unsigned char mackbd_sysrq_xlate[128] =
+ "asdfhgzxcv\000bqwer" /* 0x00 - 0x0f */
+ "yt123465=97-80o]" /* 0x10 - 0x1f */
+ "u[ip\rlj'k;\\,/nm." /* 0x20 - 0x2f */
+ "\t `\177\000\033\000\000\000\000\000\000\000\000\000\000"
+ /* 0x30 - 0x3f */
+ "\000\000\000*\000+\000\000\000\000\000/\r\000-\000"
+ /* 0x40 - 0x4f */
+ "\000\0000123456789\000\000\000" /* 0x50 - 0x5f */
+ "\205\206\207\203\210\211\000\213\000\215\000\000\000\000\000\212\000\214";
+ /* 0x60 - 0x6f */
+#endif
+
X static u_short macplain_map[NR_KEYS] __initdata = {
X 0xfb61, 0xfb73, 0xfb64, 0xfb66, 0xfb68, 0xfb67, 0xfb7a, 0xfb78,
X 0xfb63, 0xfb76, 0xf200, 0xfb62, 0xfb71, 0xfb77, 0xfb65, 0xfb72,
@@ -170,6 +226,8 @@
X static struct timer_list repeat_timer = { NULL, NULL, 0, 0, kbd_repeat };
X static int last_keycode;
X
+static void mackeyb_probe(void);
+
X static void keyboard_input(unsigned char *, int, struct pt_regs *, int);
X static void input_keycode(int, int);
X static void leds_done(struct adb_request *);
@@ -180,6 +238,7 @@
X static void init_trackpad(int id);
X static void init_trackball(int id);
X static void init_turbomouse(int id);
+static void init_microspeed(int id);
X
X #ifdef CONFIG_ADBMOUSE
X /* XXX: Hook for mouse driver */
@@ -207,21 +266,11 @@
X #define ADBMOUSE_TRACKBALL 3 /* TrackBall (handler 4) */
X #define ADBMOUSE_TRACKPAD 4 /* Apple's PowerBook trackpad (handler 4) */
X #define ADBMOUSE_TURBOMOUSE5 5 /* Turbomouse 5 (previously req. mousehack) */
+#define ADBMOUSE_MICROSPEED 6 /* Microspeed mouse (&trackball ?), MacPoint */
+#define ADBMOUSE_TRACKBALLPRO 7 /* Trackball Pro (special buttons) */
X
X static int adb_mouse_kinds[16];
X
-/* this map indicates which keys shouldn't autorepeat. */
-static unsigned char dont_repeat[128] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* esc...option */
- 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, /* fn, num lock */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, /* scroll lock */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-};
-
X __openfirmware
X
X int mackbd_setkeycode(unsigned int scancode, unsigned int keycode)
@@ -281,6 +330,10 @@
X /* on the powerbook 3400, the power key gives code 0x7e */
X if (keycode == 0x7e)
X keycode = 0x7f;
+ /* remap the "Fn" key of the PowerBook G3 Series to 0x48
+ to avoid conflict with button emulation */
+ if (keycode == 0x3f)
+ keycode = 0x48;
X
X if (!repeat)
X del_timer(&repeat_timer);
@@ -441,9 +494,24 @@
X the first (the real) button is released. We could do
X this here using async flush requests.
X */
- if (adb_mouse_kinds[(data[0]>>4) & 0xf] == ADBMOUSE_TRACKPAD) {
+ switch (adb_mouse_kinds[(data[0]>>4) & 0xf])
+ {
+ case ADBMOUSE_TRACKPAD:
X data[1] = (data[1] & 0x7f) | ((data[1] & data[2]) & 0x80);
- data[2] = (data[2] & 0x7f) | 0x80;
+ data[2] = data[2] | 0x80;
+ break;
+ case ADBMOUSE_MICROSPEED:
+ data[1] = (data[1] & 0x7f) | ((data[3] & 0x01) << 7);
+ data[2] = (data[2] & 0x7f) | ((data[3] & 0x02) << 6);
+ data[3] = (data[3] & 0x77) | ((data[3] & 0x04) << 5)
+ | (data[3] & 0x08);
+ break;
+ case ADBMOUSE_TRACKBALLPRO:
+ data[1] = (data[1] & 0x7f) | (((data[3] & 0x04) << 5)
+ & ((data[3] & 0x08) << 4));
+ data[2] = (data[2] & 0x7f) | ((data[3] & 0x01) << 7);
+ data[3] = (data[3] & 0x77) | ((data[3] & 0x02) << 6);
+ break;
X }
X
X if (adb_mouse_interrupt_hook)
@@ -473,7 +541,7 @@
X }
X
X /* Macintosh 3-button mouse (handler 4). */


- if (nb == 4) {
+ if (nb >= 4) {

X static unsigned char uch_ButtonStateThird = 0x80;
X unsigned char uchButtonThird;
X
@@ -608,9 +676,6 @@
X
X __initfunc(void mackbd_init_hw(void))
X {
- struct adb_request req;
- int i;
-
X if ( (_machine != _MACH_chrp) && (_machine != _MACH_Pmac) )
X return;
X
@@ -626,71 +691,127 @@
X #ifdef CONFIG_ADBMOUSE
X /* initialize mouse interrupt hook */
X adb_mouse_interrupt_hook = NULL;
+#endif
+
+ led_request.complete = 1;
+
+ mackeyb_probe();
+
+ notifier_chain_register(&adb_client_list, &mackeyb_adb_notifier);
+}
+
+static int
+adb_message_handler(struct notifier_block *this, unsigned long code, void *x)
+{
+ switch (code) {
+ case ADB_MSG_PRE_RESET:
+ case ADB_MSG_POWERDOWN:
+ /* Add unregister_keyboard when merging with Paul Mackerras */
+ while(!led_request.complete)
+ adb_poll();
+ break;
+
+ case ADB_MSG_POST_RESET:
+ mackeyb_probe();
+ break;
+ }
+ return NOTIFY_DONE;
+}
X
+static void
+mackeyb_probe(void)


+{
+ struct adb_request req;

+ int i;
+
+#ifdef CONFIG_ADBMOUSE
X adb_register(ADB_MOUSE, 0, &mouse_ids, mouse_input);
X #endif /* CONFIG_ADBMOUSE */
X
X adb_register(ADB_KEYBOARD, 0, &keyboard_ids, keyboard_input);
X adb_register(0x07, 0x1F, &buttons_ids, buttons_input);
X
- for(i = 0; i < keyboard_ids.nids; i++) {
- /* turn off all leds */
- adb_request(&req, NULL, ADBREQ_SYNC, 3,
- ADB_WRITEREG(keyboard_ids.id[i], KEYB_LEDREG), 0xff, 0xff);
- }
+ for (i = 0; i < keyboard_ids.nids; i++) {
+ int id = keyboard_ids.id[i];
X
- /* Enable full feature set of the keyboard
- ->get it to send separate codes for left and right shift,
- control, option keys */
- for(i = 0;i < keyboard_ids.nids; i++) {
- if (adb_try_handler_change(keyboard_ids.id[i], 5))
- printk("ADB keyboard at %d, handler set to 5\n", keyboard_ids.id[i]);
- else if (adb_try_handler_change(keyboard_ids.id[i], 3))
- printk("ADB keyboard at %d, handler set to 3\n", keyboard_ids.id[i]);
- else
- printk("ADB keyboard at %d, handler 1\n", keyboard_ids.id[i]);
+ /* turn off all leds */
+ adb_request(&req, NULL, ADBREQ_SYNC, 3,
+ ADB_WRITEREG(id, KEYB_LEDREG), 0xff, 0xff);
+
+ /* Enable full feature set of the keyboard
+ ->get it to send separate codes for left and right shift,
+ control, option keys */
+ if (adb_try_handler_change(id, 5))
+ printk("ADB keyboard at %d, handler set to 5\n", id);
+ else if (adb_try_handler_change(id, 3))
+ printk("ADB keyboard at %d, handler set to 3\n", id);
+ else
+ printk("ADB keyboard at %d, handler 1\n", id);
X }
X
- led_request.complete = 1;
-
X /* Try to switch all mice to handler 4, or 2 for three-button
X mode and full resolution. */
- for(i = 0; i < mouse_ids.nids; i++) {
- if (adb_try_handler_change(mouse_ids.id[i], 4)) {
- printk("ADB mouse at %d, handler set to 4", mouse_ids.id[i]);
- adb_mouse_kinds[mouse_ids.id[i]] = ADBMOUSE_EXTENDED;
- }
- else if (adb_try_handler_change(mouse_ids.id[i], 2)) {
- printk("ADB mouse at %d, handler set to 2", mouse_ids.id[i]);
- adb_mouse_kinds[mouse_ids.id[i]] = ADBMOUSE_STANDARD_200;
- }
- else {
- printk("ADB mouse at %d, handler 1", mouse_ids.id[i]);
- adb_mouse_kinds[mouse_ids.id[i]] = ADBMOUSE_STANDARD_100;
- }
-
- /* Register 1 is usually used for device identification.
- Here, we try to identify a known device and call the
- appropriate init function */
- adb_request(&req, NULL, ADBREQ_SYNC | ADBREQ_REPLY, 1,
- ADB_READREG(mouse_ids.id[i], 1));
-
- if ((req.reply_len) &&
- (req.reply[1] == 0x9a) && (req.reply[2] == 0x21))
- init_trackball(mouse_ids.id[i]);
- else if ((req.reply_len >= 4) &&
- (req.reply[1] == 0x74) && (req.reply[2] == 0x70) &&
- (req.reply[3] == 0x61) && (req.reply[4] == 0x64))
- init_trackpad(mouse_ids.id[i]);
- else if ((req.reply_len >= 4) &&
- (req.reply[1] == 0x4b) && (req.reply[2] == 0x4d) &&
- (req.reply[3] == 0x4c) && (req.reply[4] == 0x31))
- init_turbomouse(mouse_ids.id[i]);
- printk("\n");
+ for (i = 0; i < mouse_ids.nids; i++) {
+ int id = mouse_ids.id[i];
+ if (adb_try_handler_change(id, 4)) {
+ printk("ADB mouse at %d, handler set to 4", id);
+ adb_mouse_kinds[id] = ADBMOUSE_EXTENDED;
+ }
+ else if (adb_try_handler_change(id, 2)) {
+ printk("ADB mouse at %d, handler set to 2", id);
+ adb_mouse_kinds[id] = ADBMOUSE_STANDARD_200;
+ }
+ else if (adb_try_handler_change(id, 0x2F)) {
+ printk("ADB mouse at %d, handler set to 0x2F", id);
+ adb_mouse_kinds[id] = ADBMOUSE_MICROSPEED;
+ }
+ else if (adb_try_handler_change(id, 0x42)) {
+ printk("ADB mouse at %d, handler set to 0x42", id);
+ adb_mouse_kinds[id] = ADBMOUSE_TRACKBALLPRO;
+ }
+ else if (adb_try_handler_change(id, 0x66)) {
+ printk("ADB mouse at %d, handler set to 0x66", id);
+ adb_mouse_kinds[id] = ADBMOUSE_MICROSPEED;
+ }
+ else if (adb_try_handler_change(id, 0x5F)) {
+ printk("ADB mouse at %d, handler set to 0x5F", id);
+ adb_mouse_kinds[id] = ADBMOUSE_MICROSPEED;
+ }
+ else {
+ printk("ADB mouse at %d, handler 1", id);
+ adb_mouse_kinds[id] = ADBMOUSE_STANDARD_100;
+ }
+
+ if ((adb_mouse_kinds[id] == ADBMOUSE_TRACKBALLPRO)
+ || (adb_mouse_kinds[id] == ADBMOUSE_MICROSPEED)) {
+ init_microspeed(id);
+ } else if (adb_mouse_kinds[id] == ADBMOUSE_EXTENDED) {
+ /*
+ * Register 1 is usually used for device
+ * identification. Here, we try to identify
+ * a known device and call the appropriate
+ * init function.
+ */
+ adb_request(&req, NULL, ADBREQ_SYNC | ADBREQ_REPLY, 1,
+ ADB_READREG(id, 1));
+
+ if ((req.reply_len) &&
+ (req.reply[1] == 0x9a) && (req.reply[2] == 0x21))
+ init_trackball(id);
+ else if ((req.reply_len >= 4) &&
+ (req.reply[1] == 0x74) && (req.reply[2] == 0x70) &&
+ (req.reply[3] == 0x61) && (req.reply[4] == 0x64))
+ init_trackpad(id);
+ else if ((req.reply_len >= 4) &&
+ (req.reply[1] == 0x4b) && (req.reply[2] == 0x4d) &&
+ (req.reply[3] == 0x4c) && (req.reply[4] == 0x31))
+ init_turbomouse(id);
+ }
+ printk("\n");
X }
X }
X
-__init static void
+static void
X init_trackpad(int id)
X {
X struct adb_request req;
@@ -716,7 +837,7 @@
X r1_buffer[4],
X r1_buffer[5],
X 0x0d, /*r1_buffer[6],*/
- r1_buffer[7]);
+ r1_buffer[7]);
X
X adb_request(&req, NULL, ADBREQ_SYNC, 9,
X ADB_WRITEREG(id,2),
@@ -742,7 +863,7 @@
X }
X }
X
-__init static void
+static void
X init_trackball(int id)
X {
X struct adb_request req;
@@ -776,7 +897,7 @@
X ADB_WRITEREG(id,1), 03,0x38);
X }
X
-__init static void
+static void
X init_turbomouse(int id)
X {
X struct adb_request req;
@@ -785,6 +906,13 @@
X
X adb_mouse_kinds[id] = ADBMOUSE_TURBOMOUSE5;
X
+ adb_request(&req, NULL, ADBREQ_SYNC, 1, ADB_FLUSH(id));
+
+ adb_request(&req, NULL, ADBREQ_SYNC, 3,
+ ADB_WRITEREG(id,3), 0x20 | id, 4);
+
+ adb_request(&req, NULL, ADBREQ_SYNC, 1, ADB_FLUSH(id));
+
X adb_request(&req, NULL, ADBREQ_SYNC, 9,
X ADB_WRITEREG(id,2),
X 0xe7,
@@ -809,3 +937,44 @@
X 0xff,
X 0x27);
X }
+
+static void
+init_microspeed(int id)


+{
+ struct adb_request req;
+

+ printk(" (Microspeed/MacPoint or compatible)");
+
+ adb_request(&req, NULL, ADBREQ_SYNC, 1, ADB_FLUSH(id));
+
+ /* This will initialize mice using the Microspeed, MacPoint and
+ other compatible firmware. Bit 12 enables extended protocol.
+
+ Register 1 Listen (4 Bytes)
+ 0 - 3 Button is mouse (set also for double clicking!!!)
+ 4 - 7 Button is locking (affects change speed also)
+ 8 - 11 Button changes speed
+ 12 1 = Extended mouse mode, 0 = normal mouse mode
+ 13 - 15 unused 0
+ 16 - 23 normal speed
+ 24 - 31 changed speed
+
+ Register 1 talk holds version and product identification information.
+ Register 1 Talk (4 Bytes):
+ 0 - 7 Product code
+ 8 - 23 undefined, reserved
+ 24 - 31 Version number
+
+ Speed 0 is max. 1 to 255 set speed in increments of 1/256 of max.
+ */
+ adb_request(&req, NULL, ADBREQ_SYNC, 5,
+ ADB_WRITEREG(id,1),
+ 0x20, /* alt speed = 0x20 (rather slow) */
+ 0x00, /* norm speed = 0x00 (fastest) */
+ 0x10, /* extended protocol, no speed change */
+ 0x07); /* all buttons enabled as mouse buttons, no locking */
+
+
+ adb_request(&req, NULL, ADBREQ_SYNC, 1, ADB_FLUSH(id));
+}
+
diff -u --recursive --new-file v2.2.7/linux/drivers/macintosh/macio-adb.c linux/drivers/macintosh/macio-adb.c
--- v2.2.7/linux/drivers/macintosh/macio-adb.c Thu Nov 19 09:56:28 1998
+++ linux/drivers/macintosh/macio-adb.c Thu Apr 29 12:53:48 1999
@@ -63,9 +63,17 @@
X static int macio_adb_send_request(struct adb_request *req, int sync);
X static int macio_adb_autopoll(int devs);
X static void macio_adb_poll(void);
-static int macio_reset_bus(void);
+static int macio_adb_reset_bus(void);
X static void completed(void);
X
+static struct adb_controller macio_controller = {
+ ADB_MACIO,
+ macio_adb_send_request,
+ macio_adb_autopoll,
+ macio_adb_reset_bus,
+ macio_adb_poll
+};
+
X __openfirmware
X
X void macio_adb_init(void)
@@ -106,10 +114,12 @@
X out_8(&adb->autopoll.r, APE);
X out_8(&adb->intr_enb.r, DFB | TAG);
X
- adb_hardware = ADB_MACIO;
- adb_send_request = macio_adb_send_request;
- adb_autopoll = macio_adb_autopoll;
- adb_reset_bus = macio_reset_bus;
+ adb_controller = &macio_controller;
+// adb_hardware = ADB_MACIO;
+
+// adb_send_request = macio_adb_send_request;
+// adb_autopoll = macio_adb_autopoll;
+// adb_reset_bus = macio_reset_bus;
X }
X
X static int macio_adb_autopoll(int devs)
@@ -120,7 +130,7 @@
X return 0;
X }
X
-static int macio_reset_bus(void)
+static int macio_adb_reset_bus(void)
X {
X int timeout = 1000000;
X
@@ -138,7 +148,15 @@
X static int macio_adb_send_request(struct adb_request *req, int sync)
X {
X unsigned long mflags;
-
+ int i;
+
+ if (req->data[0] != ADB_PACKET)
+ return -EINVAL;
+
+ for (i = 0; i < req->nbytes - 1; ++i)
+ req->data[i] = req->data[i+1];
+ --req->nbytes;
+
X req->next = 0;
X req->sent = 0;
X req->complete = 0;
diff -u --recursive --new-file v2.2.7/linux/drivers/macintosh/macserial.c linux/drivers/macintosh/macserial.c
--- v2.2.7/linux/drivers/macintosh/macserial.c Tue Mar 23 14:35:47 1999
+++ linux/drivers/macintosh/macserial.c Thu Apr 29 12:53:48 1999
@@ -1986,6 +1986,7 @@
X info->line = i;
X info->tty = 0;
X info->custom_divisor = 16;
+ info->timeout = 0;
X info->close_delay = 50;
X info->closing_wait = 3000;
X info->x_char = 0;
@@ -2058,6 +2059,32 @@
X static void serial_console_write(struct console *co, const char *s,
X unsigned count)
X {
+ struct mac_serial *info = zs_soft + co->index;
+ int i;
+
+ /* Turn of interrupts and enable the transmitter. */
+ write_zsreg(info->zs_channel, R1, info->curregs[1] & ~TxINT_ENAB);
+ write_zsreg(info->zs_channel, R5, info->curregs[5] | TxENAB | RTS | DTR);
+
+ for (i=0; i<count; i++) {
+ /* Wait for the transmit buffer to empty. */
+ while ((read_zsreg(info->zs_channel, 0) & Tx_BUF_EMP) == 0) {
+ eieio();
+ }
+
+ write_zsdata(info->zs_channel, s[i]);
+ if (s[i] == 10) {
+ while ((read_zsreg(info->zs_channel, 0) & Tx_BUF_EMP)
+ == 0)
+ eieio();
+
+ write_zsdata(info->zs_channel, 13);
+ }
+ }
+
+ /* Restore the values in the registers. */
+ write_zsreg(info->zs_channel, R1, info->curregs[1]);
+ /* Don't disable the transmitter. */
X }
X
X /*
@@ -2065,7 +2092,23 @@
X */
X static int serial_console_wait_key(struct console *co)
X {
- return 0;
+ struct mac_serial *info = zs_soft + co->index;
+ int val;
+
+ /* Turn of interrupts and enable the transmitter. */
+ write_zsreg(info->zs_channel, R1, info->curregs[1] & ~INT_ALL_Rx);
+ write_zsreg(info->zs_channel, R3, info->curregs[3] | RxENABLE);
+
+ /* Wait for something in the receive buffer. */
+ while((read_zsreg(info->zs_channel, 0) & Rx_CH_AV) == 0)
+ eieio();
+ val = read_zsdata(info->zs_channel);
+
+ /* Restore the values in the registers. */
+ write_zsreg(info->zs_channel, R1, info->curregs[1]);
+ write_zsreg(info->zs_channel, R3, info->curregs[3]);
+
+ return val;
X }
X
X static kdev_t serial_console_device(struct console *c)
@@ -2081,14 +2124,24 @@
X */
X __initfunc(static int serial_console_setup(struct console *co, char *options))
X {
- struct serial_state *ser;
- unsigned cval;
- int baud = 9600;
+ struct mac_serial *info = zs_soft + co->index;
+ int baud = 38400;
X int bits = 8;
X int parity = 'n';
X int cflag = CREAD | HUPCL | CLOCAL;
- int quot = 0;
+ int brg;
X char *s;
+ long flags;
+
+ /* Find out how many Z8530 SCCs we have */
+ if (zs_chain == 0)
+ probe_sccs();
+
+ if (zs_chain == 0)
+ return -1;
+
+ /* Reset the channel */
+ write_zsreg(info->zs_channel, R9, CHRA);
X
X if (options) {
X baud = simple_strtoul(options, NULL, 10);
@@ -2114,21 +2167,21 @@
X case 4800:
X cflag |= B4800;
X break;
+ case 9600:
+ cflag |= B9600;
+ break;
X case 19200:
X cflag |= B19200;
X break;
- case 38400:
- cflag |= B38400;
- break;
X case 57600:
X cflag |= B57600;
X break;
X case 115200:
X cflag |= B115200;
X break;
- case 9600:
+ case 38400:
X default:
- cflag |= B9600;
+ cflag |= B38400;
X break;
X }
X switch(bits) {
@@ -2142,7 +2195,7 @@
X }
X switch(parity) {
X case 'o': case 'O':
- cflag |= PARODD;
+ cflag |= PARENB | PARODD;
X break;
X case 'e': case 'E':
X cflag |= PARENB;
@@ -2150,6 +2203,90 @@
X }
X co->cflag = cflag;
X
+ save_flags(flags); cli();
+ memset(info->curregs, 0, sizeof(info->curregs));
+
+ info->zs_baud = baud;
+ info->clk_divisor = 16;
+ switch (info->zs_baud) {
+ case ZS_CLOCK/16: /* 230400 */
+ info->curregs[4] = X16CLK;
+ info->curregs[11] = 0;
+ break;
+ case ZS_CLOCK/32: /* 115200 */
+ info->curregs[4] = X32CLK;
+ info->curregs[11] = 0;
+ break;
+ default:
+ info->curregs[4] = X16CLK;
+ info->curregs[11] = TCBR | RCBR;
+ brg = BPS_TO_BRG(info->zs_baud, ZS_CLOCK/info->clk_divisor);
+ info->curregs[12] = (brg & 255);
+ info->curregs[13] = ((brg >> 8) & 255);
+ info->curregs[14] = BRENABL;
+ }
+
+ /* byte size and parity */
+ info->curregs[3] &= ~RxNBITS_MASK;
+ info->curregs[5] &= ~TxNBITS_MASK;
+ switch (cflag & CSIZE) {
+ case CS5:
+ info->curregs[3] |= Rx5;
+ info->curregs[5] |= Tx5;
+ break;
+ case CS6:
+ info->curregs[3] |= Rx6;
+ info->curregs[5] |= Tx6;
+ break;
+ case CS7:
+ info->curregs[3] |= Rx7;
+ info->curregs[5] |= Tx7;
+ break;
+ case CS8:
+ default: /* defaults to 8 bits */
+ info->curregs[3] |= Rx8;
+ info->curregs[5] |= Tx8;
+ break;
+ }
+ info->curregs[5] |= TxENAB | RTS | DTR;
+ info->pendregs[3] = info->curregs[3];
+ info->pendregs[5] = info->curregs[5];
+
+ info->curregs[4] &= ~(SB_MASK | PAR_ENA | PAR_EVEN);
+ if (cflag & CSTOPB) {
+ info->curregs[4] |= SB2;
+ } else {
+ info->curregs[4] |= SB1;
+ }
+ if (cflag & PARENB) {
+ info->curregs[4] |= PAR_ENA;
+ if (!(cflag & PARODD)) {
+ info->curregs[4] |= PAR_EVEN;
+ }
+ }
+ info->pendregs[4] = info->curregs[4];
+
+ if (!(cflag & CLOCAL)) {
+ if (!(info->curregs[15] & DCDIE))
+ info->read_reg_zero = read_zsreg(info->zs_channel, 0);
+ info->curregs[15] |= DCDIE;
+ } else
+ info->curregs[15] &= ~DCDIE;
+ if (cflag & CRTSCTS) {
+ info->curregs[15] |= CTSIE;
+ if ((read_zsreg(info->zs_channel, 0) & CTS) != 0)
+ info->tx_stopped = 1;
+ } else {
+ info->curregs[15] &= ~CTSIE;
+ info->tx_stopped = 0;
+ }
+ info->pendregs[15] = info->curregs[15];
+
+ /* Load up the new values */
+ load_zsregs(info->zs_channel, info->curregs);
+
+ restore_flags(flags);
+


X return 0;
X }
X

@@ -2170,9 +2307,10 @@
X /*
X * Register console.
X */
-__initfunc (void serial_console_init(void))
+__initfunc (long serial_console_init(long kmem_start, long kmem_end))
X {
X register_console(&sercons);
+ return kmem_start;
X }
X #endif /* ifdef CONFIG_SERIAL_CONSOLE */
X
diff -u --recursive --new-file v2.2.7/linux/drivers/macintosh/nvram.c linux/drivers/macintosh/nvram.c
--- v2.2.7/linux/drivers/macintosh/nvram.c Wed Aug 26 11:37:38 1998
+++ linux/drivers/macintosh/nvram.c Thu Apr 29 12:53:48 1999
@@ -1,6 +1,11 @@
X /*
X * /dev/nvram driver for Power Macintosh.
X */
+
+#define NVRAM_VERSION "1.0"
+
+#include <linux/module.h>
+
X #include <linux/types.h>
X #include <linux/errno.h>
X #include <linux/fs.h>
@@ -9,11 +14,14 @@
X #include <linux/nvram.h>
X #include <linux/init.h>
X #include <asm/uaccess.h>
-#include <asm/init.h>
X
X #define NVRAM_SIZE 8192
X
+/* when building as a module, __openfirmware is both unavailable
+ * and unnecessary. */
+#ifndef MODULE
X __openfirmware
+#endif
X
X static long long nvram_llseek(struct file *file, loff_t offset, int origin)
X {
@@ -70,6 +78,13 @@
X
X static int nvram_open(struct inode *inode, struct file *file)
X {


+ MOD_INC_USE_COUNT;
+ return 0;
+}
+

+static int nvram_release(struct inode *inode, struct file *file)
+{
+ MOD_DEC_USE_COUNT;


X return 0;
X }
X

@@ -83,7 +98,7 @@
X NULL, /* nvram_mmap */
X nvram_open,


X NULL, /* flush */

- NULL, /* no special release code */
+ nvram_release,
X NULL /* fsync */
X };
X
@@ -95,6 +110,19 @@
X
X __initfunc(int nvram_init(void))
X {
+ printk(KERN_INFO "Macintosh non-volatile memory driver v%s\n",
+ NVRAM_VERSION);
X misc_register(&nvram_dev);
X return 0;
X }
+#ifdef MODULE
+int init_module (void)
+{
+ return( nvram_init() );
+}
+
+void cleanup_module (void)
+{
+ misc_deregister( &nvram_dev );
+}
+#endif
diff -u --recursive --new-file v2.2.7/linux/drivers/macintosh/via-cuda.c linux/drivers/macintosh/via-cuda.c
--- v2.2.7/linux/drivers/macintosh/via-cuda.c Thu Nov 19 09:56:28 1998
+++ linux/drivers/macintosh/via-cuda.c Thu Apr 29 12:53:48 1999
@@ -74,6 +74,7 @@
X static int reading_reply;
X static int data_index;
X static struct device_node *vias;
+static int cuda_fully_inited = 0;
X
X static int init_via(void);
X static void cuda_start(void);
@@ -81,7 +82,17 @@
X static void cuda_input(unsigned char *buf, int nb, struct pt_regs *regs);
X static int cuda_adb_send_request(struct adb_request *req, int sync);
X static int cuda_adb_autopoll(int devs);
-static int cuda_reset_bus(void);
+static int cuda_adb_reset_bus(void);
+static int cuda_send_request(struct adb_request *req);
+
+
+static struct adb_controller cuda_controller = {
+ ADB_VIACUDA,
+ cuda_adb_send_request,
+ cuda_adb_autopoll,
+ cuda_adb_reset_bus,
+ cuda_poll
+};
X
X __openfirmware
X
@@ -121,7 +132,7 @@
X via = NULL;
X }
X
- adb_hardware = ADB_VIACUDA;
+ adb_controller = &cuda_controller;
X }
X
X void
@@ -139,10 +150,7 @@
X via[IFR] = 0x7f; eieio(); /* clear interrupts by writing 1s */
X via[IER] = IER_SET|SR_INT; eieio(); /* enable interrupt from SR */
X
- /* Set function pointers */
- adb_send_request = cuda_adb_send_request;
- adb_autopoll = cuda_adb_autopoll;
- adb_reset_bus = cuda_reset_bus;
+ cuda_fully_inited = 1;
X }
X
X #define WAIT_FOR(cond, what) \
@@ -201,14 +209,17 @@
X {
X int i;
X
- for (i = req->nbytes; i > 0; --i)
- req->data[i] = req->data[i-1];
- req->data[0] = ADB_PACKET;
- ++req->nbytes;
+ if ((via == NULL) || !cuda_fully_inited) {
+ req->complete = 1;


+ return -ENXIO;
+ }
+

X req->reply_expected = 1;
+
X i = cuda_send_request(req);
X if (i)
X return i;
+
X if (sync) {
X while (!req->complete)
X cuda_poll();
@@ -216,12 +227,16 @@


X return 0;
X }
X

+
X /* Enable/disable autopolling */
X static int
X cuda_adb_autopoll(int devs)
X {
X struct adb_request req;
X
+ if ((via == NULL) || !cuda_fully_inited)
+ return -ENXIO;
+
X cuda_request(&req, NULL, 3, CUDA_PACKET, CUDA_AUTOPOLL, (devs? 1: 0));
X while (!req.complete)
X cuda_poll();
@@ -230,10 +245,13 @@
X
X /* Reset adb bus - how do we do this?? */
X static int
-cuda_reset_bus(void)
+cuda_adb_reset_bus(void)
X {
X struct adb_request req;
X
+ if ((via == NULL) || !cuda_fully_inited)
+ return -ENXIO;
+
X cuda_request(&req, NULL, 2, ADB_PACKET, 0); /* maybe? */
X while (!req.complete)
X cuda_poll();
@@ -248,6 +266,11 @@
X va_list list;
X int i;
X
+ if (via == NULL) {
+ req->complete = 1;


+ return -ENXIO;
+ }
+

X req->nbytes = nbytes;
X req->done = done;
X va_start(list, nbytes);
@@ -258,15 +281,11 @@
X return cuda_send_request(req);
X }
X
-int
+static int
X cuda_send_request(struct adb_request *req)
X {
X unsigned long flags;
X
- if (via == NULL) {
- req->complete = 1;
- return -ENXIO;
- }
X if (req->nbytes < 2 || req->data[0] > CUDA_PACKET) {
X req->complete = 1;
X return -EINVAL;
@@ -472,3 +491,9 @@


X printk("\n");
X }
X }

+
+int
+cuda_present(void)
+{
+ return (adb_controller && (adb_controller->kind == ADB_VIACUDA) && via);
+}
\ No newline at end of file
diff -u --recursive --new-file v2.2.7/linux/drivers/macintosh/via-pmu.c linux/drivers/macintosh/via-pmu.c
--- v2.2.7/linux/drivers/macintosh/via-pmu.c Tue Mar 23 14:35:47 1999
+++ linux/drivers/macintosh/via-pmu.c Thu Apr 29 12:53:48 1999
@@ -93,6 +93,7 @@
X static struct adb_request bright_req_1, bright_req_2, bright_req_3;
X static struct device_node *vias;
X static int pmu_kind = PMU_UNKNOWN;
+static int pmu_fully_inited = 0;
X
X int asleep;
X struct notifier_block *sleep_notifier_list;
@@ -103,7 +104,7 @@
X static void via_pmu_interrupt(int irq, void *arg, struct pt_regs *regs);
X static int pmu_adb_send_request(struct adb_request *req, int sync);
X static int pmu_adb_autopoll(int devs);
-static int pmu_reset_bus(void);
+static int pmu_adb_reset_bus(void);
X static void send_byte(int x);
X static void recv_byte(void);
X static void pmu_sr_intr(struct pt_regs *regs);
@@ -112,6 +113,14 @@
X struct pt_regs *regs);
X static void set_volume(int level);
X
+static struct adb_controller pmu_controller = {
+ ADB_VIAPMU,
+ pmu_adb_send_request,
+ pmu_adb_autopoll,
+ pmu_adb_reset_bus,
+ pmu_poll
+};
+
X /*
X * This table indicates for each PMU opcode:
X * - the number of data bytes to be sent with the command, or -1
@@ -126,17 +135,17 @@
X /*10*/ { 1, 0},{ 1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},
X /*18*/ { 0, 1},{ 0, 1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{ 0, 0},
X /*20*/ {-1, 0},{ 0, 0},{ 2, 0},{ 1, 0},{ 1, 0},{-1, 0},{-1, 0},{-1, 0},
-/*28*/ { 0,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},
-/*30*/ { 4, 0},{20, 0},{ 2, 0},{ 3, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},
-/*38*/ { 0, 4},{ 0,20},{ 1, 1},{ 2, 1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},
+/*28*/ { 0,-1},{ 0,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{ 0,-1},
+/*30*/ { 4, 0},{20, 0},{-1, 0},{ 3, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},
+/*38*/ { 0, 4},{ 0,20},{ 2,-1},{ 2, 1},{ 3,-1},{-1,-1},{-1,-1},{ 4, 0},
X /*40*/ { 1, 0},{ 1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},
-/*48*/ { 0, 1},{ 0, 1},{-1,-1},{-1,-1},{ 1, 0},{-1,-1},{-1,-1},{-1,-1},
+/*48*/ { 0, 1},{ 0, 1},{-1,-1},{ 1, 0},{ 1, 0},{-1,-1},{-1,-1},{-1,-1},
X /*50*/ { 1, 0},{ 0, 0},{ 2, 0},{ 2, 0},{-1, 0},{ 1, 0},{ 3, 0},{ 1, 0},
X /*58*/ { 0, 1},{ 1, 0},{ 0, 2},{ 0, 2},{ 0,-1},{-1,-1},{-1,-1},{-1,-1},
-/*60*/ { 2, 0},{-1, 0},{ 2, 0},{ 0, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},
+/*60*/ { 2, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},
X /*68*/ { 0, 3},{ 0, 3},{ 0, 2},{ 0, 8},{ 0,-1},{ 0,-1},{-1,-1},{-1,-1},
X /*70*/ { 1, 0},{ 1, 0},{ 1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},
-/*78*/ { 0,-1},{ 0,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{ 4, 1},{ 4, 1},
+/*78*/ { 0,-1},{ 0,-1},{-1,-1},{-1,-1},{-1,-1},{ 5, 1},{ 4, 1},{ 4, 1},
X /*80*/ { 4, 0},{-1, 0},{ 0, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},
X /*88*/ { 0, 5},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},
X /*90*/ { 1, 0},{ 2, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},
@@ -149,7 +158,7 @@
X /*c8*/ {-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},
X /*d0*/ { 0, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},
X /*d8*/ { 1, 1},{ 1, 1},{-1,-1},{-1,-1},{ 0, 1},{ 0,-1},{-1,-1},{-1,-1},
-/*e0*/ {-1, 0},{ 4, 0},{ 0, 1},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},
+/*e0*/ {-1, 0},{ 4, 0},{ 0, 1},{-1, 0},{-1, 0},{ 4, 0},{-1, 0},{-1, 0},
X /*e8*/ { 3,-1},{-1,-1},{ 0, 1},{-1,-1},{ 0,-1},{-1,-1},{-1,-1},{ 0, 0},
X /*f0*/ {-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},
X /*f8*/ {-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},
@@ -186,8 +195,8 @@
X return;
X }
X
- if (vias->parent->name && strcmp(vias->parent->name, "ohare") == 0
- || device_is_compatible(vias->parent, "ohare"))
+ if (vias->parent->name && ((strcmp(vias->parent->name, "ohare") == 0)
+ || device_is_compatible(vias->parent, "ohare")))
X pmu_kind = PMU_OHARE_BASED;
X else if (device_is_compatible(vias->parent, "heathrow"))
X pmu_kind = PMU_HEATHROW_BASED;
@@ -203,13 +212,13 @@
X if (!init_pmu())
X via = NULL;
X
- adb_hardware = ADB_VIAPMU;
-
+ adb_controller = &pmu_controller;
+
X if (via)
X printk(KERN_INFO "PMU driver initialized for %s\n",
- (pmu_kind == PMU_OHARE_BASED) ? "PowerBook 2400/3400/3500(G3)" :
- ((pmu_kind == PMU_HEATHROW_BASED) ? "PowerBook G3 Series" :
- "Unknown PowerBook"));
+ (pmu_kind == PMU_OHARE_BASED) ? "PowerBook 2400/3400/3500(G3)" :
+ ((pmu_kind == PMU_HEATHROW_BASED) ? "PowerBook G3 Series" :
+ "Unknown PowerBook"));
X }
X
X void __openfirmware
@@ -232,11 +241,8 @@
X /* Enable interrupts */
X out_8(&via[IER], IER_SET | SR_INT | CB1_INT);
X
- /* Set function pointers */
- adb_send_request = pmu_adb_send_request;
- adb_autopoll = pmu_adb_autopoll;
- adb_reset_bus = pmu_reset_bus;
-
+ pmu_fully_inited = 1;
+
X /* Enable backlight */
X pmu_enable_backlight(1);
X }
@@ -288,25 +294,81 @@
X static int __openfirmware
X pmu_adb_send_request(struct adb_request *req, int sync)
X {
- int i;
+ int i, ret;
X
- for (i = req->nbytes - 1; i > 0; --i)
- req->data[i+3] = req->data[i];
- req->data[3] = req->nbytes - 1;
- req->data[2] = pmu_adb_flags;
- req->data[1] = req->data[0];
- req->data[0] = PMU_ADB_CMD;
- req->nbytes += 3;
- req->reply_expected = 1;
- req->reply_len = 0;
- i = pmu_queue_request(req);
- if (i)
- return i;
- if (sync) {
- while (!req->complete)
- pmu_poll();
- }
- return 0;
+ if ((vias == NULL) || (!pmu_fully_inited))
+ {
+ req->complete = 1;


+ return -ENXIO;
+ }
+

+ ret = -EINVAL;
+
+ switch (req->data[0]) {
+ case PMU_PACKET:
+ for (i = 0; i < req->nbytes - 1; ++i)
+ req->data[i] = req->data[i+1];
+ --req->nbytes;
+ if (pmu_data_len[req->data[0]][1] != 0) {
+ req->reply[0] = ADB_RET_OK;
+ req->reply_len = 1;
+ } else
+ req->reply_len = 0;
+ ret = pmu_queue_request(req);
+ break;
+ case CUDA_PACKET:
+ switch (req->data[1]) {
+ case CUDA_GET_TIME:
+ if (req->nbytes != 2)
+ break;
+ req->data[0] = PMU_READ_RTC;
+ req->nbytes = 1;
+ req->reply_len = 3;
+ req->reply[0] = CUDA_PACKET;
+ req->reply[1] = 0;
+ req->reply[2] = CUDA_GET_TIME;
+ ret = pmu_queue_request(req);
+ break;
+ case CUDA_SET_TIME:
+ if (req->nbytes != 6)
+ break;
+ req->data[0] = PMU_SET_RTC;
+ req->nbytes = 5;
+ for (i = 1; i <= 4; ++i)
+ req->data[i] = req->data[i+1];
+ req->reply_len = 3;
+ req->reply[0] = CUDA_PACKET;
+ req->reply[1] = 0;
+ req->reply[2] = CUDA_SET_TIME;
+ ret = pmu_queue_request(req);
+ break;
+ }
+ break;
+ case ADB_PACKET:
+ for (i = req->nbytes - 1; i > 1; --i)
+ req->data[i+2] = req->data[i];
+ req->data[3] = req->nbytes - 2;
+ req->data[2] = pmu_adb_flags;
+ /*req->data[1] = req->data[1];*/
+ req->data[0] = PMU_ADB_CMD;
+ req->nbytes += 2;
+ req->reply_expected = 1;
+ req->reply_len = 0;
+ ret = pmu_queue_request(req);
+ break;
+ }
+ if (ret)
+ {
+ req->complete = 1;
+ return ret;
+ }
+
+ if (sync) {
+ while (!req->complete)
+ pmu_poll();
+ }
+


+ return 0;
X }
X

X /* Enable/disable autopolling */
@@ -315,6 +377,9 @@
X {
X struct adb_request req;
X
+ if ((vias == NULL) || (!pmu_fully_inited))
+ return -ENXIO;
+
X if (devs) {
X adb_dev_map = devs;
X pmu_request(&req, NULL, 5, PMU_ADB_CMD, 0, 0x86,
@@ -331,12 +396,15 @@
X
X /* Reset the ADB bus */
X static int __openfirmware
-pmu_reset_bus(void)
+pmu_adb_reset_bus(void)
X {
X struct adb_request req;
X long timeout;
X int save_autopoll = adb_dev_map;
X
+ if ((vias == NULL) || (!pmu_fully_inited))
+ return -ENXIO;
+
X /* anyone got a better idea?? */
X pmu_adb_autopoll(0);
X
@@ -344,23 +412,23 @@
X req.done = NULL;
X req.data[0] = PMU_ADB_CMD;
X req.data[1] = 0;
- req.data[2] = 3;
+ req.data[2] = 3; /* ADB_BUSRESET ??? */
X req.data[3] = 0;
X req.data[4] = 0;
X req.reply_len = 0;
X req.reply_expected = 1;
X if (pmu_queue_request(&req) != 0)
X {
- printk(KERN_ERR "pmu_reset_bus: pmu_queue_request failed\n");
- return 0;
+ printk(KERN_ERR "pmu_adb_reset_bus: pmu_queue_request failed\n");
+ return -EIO;
X }
X while (!req.complete)
X pmu_poll();
X timeout = 100000;
X while (!req.complete) {
X if (--timeout < 0) {
- printk(KERN_ERR "pmu_reset_bus (reset): no response from PMU\n");
- return 0;
+ printk(KERN_ERR "pmu_adb_reset_bus (reset): no response from PMU\n");
+ return -EIO;
X }
X udelay(10);
X pmu_poll();
@@ -369,7 +437,7 @@
X if (save_autopoll != 0)
X pmu_adb_autopoll(save_autopoll);
X
- return 1;
+ return 0;
X }
X
X /* Construct and send a pmu request */
@@ -380,6 +448,9 @@
X va_list list;
X int i;
X
+ if (vias == NULL)
+ return -ENXIO;
+
X if (nbytes < 0 || nbytes > 32) {
X printk(KERN_ERR "pmu_request: bad nbytes (%d)\n", nbytes);
X req->complete = 1;
@@ -400,57 +471,6 @@
X return pmu_queue_request(req);
X }
X
-/*
- * This procedure handles requests written to /dev/adb where the
- * first byte is CUDA_PACKET or PMU_PACKET. For CUDA_PACKET, we
- * emulate a few CUDA requests.
- */
-int __openfirmware
-pmu_send_request(struct adb_request *req)


-{
- int i;
-

- switch (req->data[0]) {
- case PMU_PACKET:
- for (i = 0; i < req->nbytes - 1; ++i)
- req->data[i] = req->data[i+1];
- --req->nbytes;
- if (pmu_data_len[req->data[0]][1] != 0) {
- req->reply[0] = ADB_RET_OK;
- req->reply_len = 1;
- } else
- req->reply_len = 0;
- return pmu_queue_request(req);
- case CUDA_PACKET:
- switch (req->data[1]) {
- case CUDA_GET_TIME:
- if (req->nbytes != 2)
- break;
- req->data[0] = PMU_READ_RTC;
- req->nbytes = 1;
- req->reply_len = 3;
- req->reply[0] = CUDA_PACKET;
- req->reply[1] = 0;
- req->reply[2] = CUDA_GET_TIME;
- return pmu_queue_request(req);
- case CUDA_SET_TIME:
- if (req->nbytes != 6)
- break;
- req->data[0] = PMU_SET_RTC;
- req->nbytes = 5;
- for (i = 1; i <= 4; ++i)
- req->data[i] = req->data[i+1];
- req->reply_len = 3;
- req->reply[0] = CUDA_PACKET;
- req->reply[1] = 0;
- req->reply[2] = CUDA_SET_TIME;
- return pmu_queue_request(req);
- }
- break;
- }
- return -EINVAL;
-}
-
X int __openfirmware
X pmu_queue_request(struct adb_request *req)
X {
@@ -737,7 +757,7 @@
X {
X struct adb_request req;
X
- if (adb_hardware != ADB_VIAPMU)
+ if (vias == NULL)
X return ;
X
X if (on) {
@@ -780,7 +800,7 @@
X {
X int bright;
X
- if (adb_hardware != ADB_VIAPMU)
+ if (vias == NULL)
X return ;
X
X backlight_level = level;
@@ -807,7 +827,7 @@
X {
X struct adb_request req;
X
- if (adb_hardware != ADB_VIAPMU)
+ if (vias == NULL)
X return ;
X
X pmu_request(&req, NULL, 2, PMU_POWER_CTRL, PMU_POW_IRLED |
@@ -860,6 +880,11 @@
X ;
X }
X
+int
+pmu_present(void)
+{
+ return (adb_controller && (adb_controller->kind == ADB_VIAPMU) && vias);
+}
X
X #ifdef CONFIG_PMAC_PBOOK


X
@@ -1104,3 +1129,4 @@

X misc_register(&pmu_device);
X }
X #endif /* CONFIG_PMAC_PBOOK */
+
diff -u --recursive --new-file v2.2.7/linux/drivers/misc/Makefile linux/drivers/misc/Makefile
--- v2.2.7/linux/drivers/misc/Makefile Fri Jan 8 22:36:06 1999
+++ linux/drivers/misc/Makefile Tue May 11 09:55:49 1999
@@ -34,6 +34,27 @@
X M_OBJS += parport_ax.o
X endif
X endif
+ ifeq ($(CONFIG_PARPORT_AMIGA),y)
+ LX_OBJS += parport_amiga.o
+ else
+ ifeq ($(CONFIG_PARPORT_AMIGA),m)
+ M_OBJS += parport_amiga.o
+ endif
+ endif
+ ifeq ($(CONFIG_PARPORT_MFC3),y)
+ LX_OBJS += parport_mfc3.o
+ else
+ ifeq ($(CONFIG_PARPORT_MFC3),m)
+ M_OBJS += parport_mfc3.o
+ endif
+ endif
+ ifeq ($(CONFIG_PARPORT_ATARI),y)
+ LX_OBJS += parport_atari.o
+ else
+ ifeq ($(CONFIG_PARPORT_ATARI),m)
+ M_OBJS += parport_atari.o
+ endif
+ endif
X LX_OBJS += parport_init.o
X else
X ifeq ($(CONFIG_PARPORT),m)
@@ -49,6 +70,15 @@
X endif
X ifeq ($(CONFIG_PARPORT_AX),m)
X M_OBJS += parport_ax.o
+ endif
+ ifeq ($(CONFIG_PARPORT_AMIGA),m)
+ M_OBJS += parport_amiga.o
+ endif
+ ifeq ($(CONFIG_PARPORT_MFC3),m)
+ M_OBJS += parport_mfc3.o
+ endif
+ ifeq ($(CONFIG_PARPORT_ATARI),m)
+ M_OBJS += parport_atari.o
X endif
X endif
X
diff -u --recursive --new-file v2.2.7/linux/drivers/misc/multiface.h linux/drivers/misc/multiface.h
--- v2.2.7/linux/drivers/misc/multiface.h Wed Dec 31 16:00:00 1969
+++ linux/drivers/misc/multiface.h Tue May 11 09:55:49 1999
@@ -0,0 +1,20 @@
+#ifndef _MULTIFACE_H_
+#define _MULTIFACE_H_
+
+/*
+ * Defines for SerialMaster, Multiface Card II and Multiface Card III
+ * The addresses given below are offsets to the board base address
+ *
+ * 6.11.95 Joerg Dorchain (dorc...@mpi-sb.mpg.de)


+ *
+ */
+

+#define PIA_REG_PADWIDTH 255
+
+#define DUARTBASE 0x0000
+#define PITBASE 0x0100
+#define ROMBASE 0x0200
+#define PIABASE 0x4000
+
+#endif
+
diff -u --recursive --new-file v2.2.7/linux/drivers/misc/parport_amiga.c linux/drivers/misc/parport_amiga.c
--- v2.2.7/linux/drivers/misc/parport_amiga.c Wed Dec 31 16:00:00 1969
+++ linux/drivers/misc/parport_amiga.c Tue May 11 09:55:49 1999
@@ -0,0 +1,322 @@
+/* Low-level parallel port routines for the Amiga buildin port
+ *
+ * Author: Joerg Dorchain <dorc...@wirbel.com>
+ *
+ * This is a complete rewrite of the code, but based heaviy upon the old
+ * lp_intern. code.
+ *
+ * The built-in Amiga parallel port provides one port at a fixed address
+ * with 8 bisdirecttional data lines (D0 - D7) and 3 bidirectional status
+ * lines (BUSY, POUT, SEL), 1 output control line /STROBE (raised automatically in
+ * hardware when the data register is accessed), and 1 input control line
+ * /ACK, able to cause an interrupt, but both not directly settable by
+ * software.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/parport.h>
+#include <asm/setup.h>
+#include <asm/amigahw.h>
+#include <asm/irq.h>
+#include <asm/amigaints.h>
+
+#undef DEBUG
+#ifdef DEBUG
+#define DPRINTK printk
+#else
+static inline int DPRINTK() {return 0;}
+#endif
+
+static struct parport *this_port = NULL;
+
+static void amiga_write_data(struct parport *p, unsigned char data)
+{
+DPRINTK("write_data %c\n",data);
+ /* Triggers also /STROBE. This behavior cannot be changed */
+ ciaa.prb = data;
+}
+
+static unsigned char amiga_read_data(struct parport *p)


SHAR_EOF
true || echo 'restore of patch-2.2.8 failed'
fi

echo 'End of part 15'
echo 'File patch-2.2.8 is continued in part 16'
echo 16 > _shar_seq_.tmp

Thomas...@ciw.uni-karlsruhe.de

unread,
May 12, 1999, 3:00:00 AM5/12/99
to
Archive-name: v2.2/patch-2.2.8/part16

#!/bin/sh
# this is part 16 of a 33 - part archive


# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.8 continued
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 16; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.8'
else
echo 'x - continuing with patch-2.2.8'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.8' &&

+{


+ /* Triggers also /STROBE. This behavior cannot be changed */

+ return ciaa.prb;
+}
+
+#if 0
+static unsigned char control_pc_to_amiga(unsigned char control)
+{
+ unsigned char ret = 0;
+
+ if (control & PARPORT_CONTROL_DIRECTION) /* XXX: What is this? */
+ ;
+ if (control & PARPORT_CONTROL_INTEN) /* XXX: What is INTEN? */
+ ;
+ if (control & PARPORT_CONTROL_SELECT) /* XXX: What is SELECP? */
+ ;
+ if (control & PARPORT_CONTROL_INIT) /* INITP */
+ /* reset connected to cpu reset pin */;
+ if (control & PARPORT_CONTROL_AUTOFD) /* AUTOLF */
+ /* Not connected */;
+ if (control & PARPORT_CONTROL_STROBE) /* Strobe */
+ /* Handled only directly by hardware */;
+ return ret;
+}
+#endif
+
+static unsigned char control_amiga_to_pc(unsigned char control)
+{
+ return PARPORT_CONTROL_INTEN | PARPORT_CONTROL_SELECT |
+ PARPORT_CONTROL_AUTOFD | PARPORT_CONTROL_STROBE;
+ /* fake value: interrupt enable, select in, no reset,
+ no autolf, no strobe - seems to be closest the wiring diagram */
+}
+
+static void amiga_write_control(struct parport *p, unsigned char control)
+{
+DPRINTK("write_control %02x\n",control);
+ /* No implementation possible */
+}
+
+static unsigned char amiga_read_control( struct parport *p)
+{
+DPRINTK("read_control \n");
+ return control_amiga_to_pc(0);
+}
+
+static unsigned char amiga_frob_control( struct parport *p, unsigned char mask, unsigned char val)
+{
+ unsigned char old;
+
+DPRINTK("frob_control mask %02x, value %02x\n",mask,val);
+ old = amiga_read_control(p);
+ amiga_write_control(p, (old & ~mask) ^ val);
+ return old;
+}
+
+
+static unsigned char status_pc_to_amiga(unsigned char status)
+{
+ unsigned char ret = 1;
+
+ if (status & PARPORT_STATUS_BUSY) /* Busy */
+ ret &= ~1;
+ if (status & PARPORT_STATUS_ACK) /* Ack */
+ /* handled in hardware */;
+ if (status & PARPORT_STATUS_PAPEROUT) /* PaperOut */
+ ret |= 2;
+ if (status & PARPORT_STATUS_SELECT) /* select */
+ ret |= 4;
+ if (status & PARPORT_STATUS_ERROR) /* error */
+ /* not connected */;


+ return ret;
+}
+

+static unsigned char status_amiga_to_pc(unsigned char status)
+{
+ unsigned char ret = PARPORT_STATUS_BUSY | PARPORT_STATUS_ACK | PARPORT_STATUS_ERROR;
+
+ if (status & 1) /* Busy */
+ ret &= ~PARPORT_STATUS_BUSY;
+ if (status & 2) /* PaperOut */
+ ret |= PARPORT_STATUS_PAPEROUT;
+ if (status & 4) /* Selected */
+ ret |= PARPORT_STATUS_SELECT;
+ /* the rest is not connected or handled autonomously in hardware */
+


+ return ret;
+}
+

+static void amiga_write_status( struct parport *p, unsigned char status)
+{
+DPRINTK("write_status %02x\n",status);
+ ciab.pra |= (ciab.pra & 0xf8) | status_pc_to_amiga(status);
+}
+
+static unsigned char amiga_read_status(struct parport *p)
+{
+ unsigned char status;
+
+ status = status_amiga_to_pc(ciab.pra & 7);
+DPRINTK("read_status %02x\n", status);
+ return status;
+}
+
+static void amiga_change_mode( struct parport *p, int m)
+{
+ /* XXX: This port only has one mode, and I am
+ not sure about the corresponding PC-style mode*/
+}
+
+/* as this ports irq handling is already done, we use a generic funktion */
+static void amiga_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ parport_generic_irq(irq, (struct parport *) dev_id, regs);
+}
+
+
+static void amiga_release_resources(struct parport *p)
+{
+DPRINTK("realease_resources\n");
+ if (p->irq != PARPORT_IRQ_NONE)
+ free_irq(IRQ_AMIGA_CIAA_FLG, p);
+}
+
+static int amiga_claim_resources(struct parport *p)
+{
+DPRINTK("claim_resources\n");
+ return request_irq(IRQ_AMIGA_CIAA_FLG, amiga_interrupt, 0, p->name, p);
+}
+
+static void amiga_init_state(struct parport_state *s)
+{
+ s->u.amiga.data = 0;
+ s->u.amiga.datadir = 255;
+ s->u.amiga.status = 0;
+ s->u.amiga.statusdir = 0;
+}
+
+static void amiga_save_state(struct parport *p, struct parport_state *s)
+{
+ s->u.amiga.data = ciaa.prb;
+ s->u.amiga.datadir = ciaa.ddrb;
+ s->u.amiga.status = ciab.pra & 7;
+ s->u.amiga.statusdir = ciab.ddra & 7;
+}
+
+static void amiga_restore_state(struct parport *p, struct parport_state *s)
+{
+ ciaa.prb = s->u.amiga.data;
+ ciaa.ddrb = s->u.amiga.datadir;
+ ciab.pra |= (ciab.pra & 0xf8) | s->u.amiga.status;
+ ciab.ddra |= (ciab.ddra & 0xf8) | s->u.amiga.statusdir;
+}
+
+static void amiga_enable_irq(struct parport *p)
+{
+ enable_irq(IRQ_AMIGA_CIAA_FLG);
+}
+
+static void amiga_disable_irq(struct parport *p)
+{
+ disable_irq(IRQ_AMIGA_CIAA_FLG);
+}
+
+static void amiga_inc_use_count(void)
+{
+ MOD_INC_USE_COUNT;
+}
+
+static void amiga_dec_use_count(void)


+{
+ MOD_DEC_USE_COUNT;
+}
+

+static void amiga_fill_inode(struct inode *inode, int fill)
+{
+#ifdef MODULE
+ if (fill)
+ MOD_INC_USE_COUNT;
+ else
+ MOD_DEC_USE_COUNT;
+#endif
+}
+
+static struct parport_operations pp_amiga_ops = {
+ amiga_write_data,
+ amiga_read_data,
+
+ amiga_write_control,
+ amiga_read_control,
+ amiga_frob_control,
+
+ NULL, /* write_econtrol */
+ NULL, /* read_econtrol */
+ NULL, /* frob_econtrol */
+
+ amiga_write_status,
+ amiga_read_status,
+
+ NULL, /* write fifo */
+ NULL, /* read fifo */
+
+ amiga_change_mode,
+
+
+ amiga_release_resources,
+ amiga_claim_resources,
+
+
+ NULL, /* epp_write_data */
+ NULL, /* epp_read_data */
+ NULL, /* epp_write_addr */
+ NULL, /* epp_read_addr */
+ NULL, /* epp_check_timeout */
+
+ NULL, /* epp_write_block */
+ NULL, /* epp_read_block */
+
+ NULL, /* ecp_write_block */
+ NULL, /* ecp_read_block */
+
+ amiga_init_state,
+ amiga_save_state,
+ amiga_restore_state,
+
+ amiga_enable_irq,
+ amiga_disable_irq,
+ amiga_interrupt,
+
+ amiga_inc_use_count,
+ amiga_dec_use_count,
+ amiga_fill_inode
+};
+
+/* ----------- Initialisation code --------------------------------- */
+
+__initfunc(int parport_amiga_init(void))
+{
+ struct parport *p;
+
+ if (MACH_IS_AMIGA && AMIGAHW_PRESENT(AMI_PARALLEL)) {
+ ciaa.ddrb = 0xff;
+ ciab.ddra &= 0xf8;
+ if (!(p = parport_register_port((unsigned long)&ciaa.prb,
+ IRQ_AMIGA_CIAA_FLG, PARPORT_DMA_NONE,
+ &pp_amiga_ops)))
+ return 0;
+ this_port = p;
+ printk(KERN_INFO "%s: Amiga built-in port using irq\n", p->name);
+ /* XXX: set operating mode */
+ parport_proc_register(p);
+ p->flags |= PARPORT_FLAG_COMA;
+
+ if (parport_probe_hook)
+ (*parport_probe_hook)(p);


+ return 1;
+
+ }

+ return 0;
+}
+

+#ifdef MODULE
+
+MODULE_AUTHOR("Joerg Dorchain");
+MODULE_DESCRIPTION("Parport Driver for Amiga builtin Port");
+MODULE_SUPPORTED_DEVICE("Amiga builtin Parallel Port");
+
+int init_module(void)
+{
+ return ! parport_amiga_init();
+}
+
+void cleanup_module(void)
+{
+ if (!(this_port->flags & PARPORT_FLAG_COMA))
+ parport_quiesce(this_port);
+ parport_proc_unregister(this_port);
+ parport_unregister_port(this_port);
+}
+#endif
+
+
diff -u --recursive --new-file v2.2.7/linux/drivers/misc/parport_atari.c linux/drivers/misc/parport_atari.c
--- v2.2.7/linux/drivers/misc/parport_atari.c Wed Dec 31 16:00:00 1969
+++ linux/drivers/misc/parport_atari.c Tue May 11 09:55:49 1999
@@ -0,0 +1,263 @@
+/* Low-level parallel port routines for the Atari builtin port
+ *
+ * Author: Andreas Schwab <sch...@issan.informatik.uni-dortmund.de>
+ *
+ * Based on parport_amiga.c.
+ *
+ * The built-in Atari parallel port provides one port at a fixed address
+ * with 8 output data lines (D0 - D7), 1 output control line (STROBE)
+ * and 1 input status line (BUSY) able to cause an interrupt.


+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/parport.h>
+#include <asm/setup.h>

+#include <asm/atarihw.h>
+#include <asm/irq.h>
+#include <asm/atariints.h>


+
+static struct parport *this_port = NULL;
+

+static unsigned char
+parport_atari_read_data(struct parport *p)
+{
+ unsigned long flags;
+ unsigned char data;


+
+ save_flags(flags);
+ cli();

+ sound_ym.rd_data_reg_sel = 15;
+ data = sound_ym.rd_data_reg_sel;
+ restore_flags(flags);
+ return data;
+}
+
+static void
+parport_atari_write_data(struct parport *p, unsigned char data)
+{


+ unsigned long flags;
+

+ save_flags(flags);
+ cli();
+ sound_ym.rd_data_reg_sel = 15;
+ sound_ym.wd_data = data;
+ restore_flags(flags);


+}
+
+static unsigned char

+parport_atari_read_control(struct parport *p)
+{
+ unsigned long flags;
+ unsigned char control = 0;


+
+ save_flags(flags);
+ cli();

+ sound_ym.rd_data_reg_sel = 14;
+ if (!(sound_ym.rd_data_reg_sel & (1 << 5)))
+ control = PARPORT_CONTROL_STROBE;
+ restore_flags(flags);
+ return control;
+}
+
+static void
+parport_atari_write_control(struct parport *p, unsigned char control)
+{


+ unsigned long flags;
+

+ save_flags(flags);
+ cli();
+ sound_ym.rd_data_reg_sel = 14;
+ if (control & PARPORT_CONTROL_STROBE)
+ sound_ym.wd_data = sound_ym.rd_data_reg_sel & ~(1 << 5);
+ else
+ sound_ym.wd_data = sound_ym.rd_data_reg_sel | (1 << 5);
+ restore_flags(flags);


+}
+
+static unsigned char

+parport_atari_frob_control(struct parport *p, unsigned char mask,
+ unsigned char val)
+{
+ unsigned char old = parport_atari_read_control(p);
+ parport_atari_write_control(p, (old & ~mask) ^ val);
+ return old;


+}
+
+static unsigned char

+parport_atari_read_status(struct parport *p)
+{
+ return ((mfp.par_dt_reg & 1 ? 0 : PARPORT_STATUS_BUSY) |
+ PARPORT_STATUS_SELECT | PARPORT_STATUS_ERROR);
+}
+
+static void
+parport_atari_write_status(struct parport *p, unsigned char status)


+{
+}
+
+static void

+parport_atari_init_state(struct parport_state *s)


+{
+}
+
+static void

+parport_atari_save_state(struct parport *p, struct parport_state *s)


+{
+}
+
+static void

+parport_atari_restore_state(struct parport *p, struct parport_state *s)


+{
+}
+
+static void

+parport_atari_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ parport_generic_irq(irq, (struct parport *) dev_id, regs);
+}
+
+static void
+parport_atari_release_resources(struct parport *p)
+{
+ if (p->irq != PARPORT_IRQ_NONE)
+ free_irq(IRQ_MFP_BUSY, p);
+}
+
+static int
+parport_atari_claim_resources(struct parport *p)
+{
+ return request_irq(IRQ_MFP_BUSY, parport_atari_interrupt,
+ IRQ_TYPE_SLOW, p->name, p);
+}
+
+static void
+parport_atari_inc_use_count(void)
+{
+ MOD_INC_USE_COUNT;
+}
+
+static void
+parport_atari_dec_use_count(void)


+{
+ MOD_DEC_USE_COUNT;
+}
+

+static void
+parport_atari_fill_inode(struct inode *inode, int fill)
+{
+#ifdef MODULE
+ if (fill)
+ MOD_INC_USE_COUNT;
+ else
+ MOD_DEC_USE_COUNT;
+#endif
+}
+
+static struct parport_operations parport_atari_ops = {
+ parport_atari_write_data,
+ parport_atari_read_data,
+
+ parport_atari_write_control,
+ parport_atari_read_control,
+ parport_atari_frob_control,
+
+ NULL, /* write_econtrol */
+ NULL, /* read_econtrol */
+ NULL, /* frob_econtrol */
+
+ parport_atari_write_status,
+ parport_atari_read_status,
+
+ NULL, /* write fifo */
+ NULL, /* read fifo */
+
+ NULL, /* change_mode */
+
+ parport_atari_release_resources,
+ parport_atari_claim_resources,
+
+ NULL, /* epp_write_data */
+ NULL, /* epp_read_data */
+ NULL, /* epp_write_addr */
+ NULL, /* epp_read_addr */
+ NULL, /* epp_check_timeout */
+
+ NULL, /* epp_write_block */
+ NULL, /* epp_read_block */
+
+ NULL, /* ecp_write_block */
+ NULL, /* ecp_read_block */
+
+ parport_atari_init_state,
+ parport_atari_save_state,
+ parport_atari_restore_state,
+
+ NULL, /* enable_irq */
+ NULL, /* disable_irq */
+ parport_atari_interrupt,
+
+ parport_atari_inc_use_count,
+ parport_atari_dec_use_count,
+ parport_atari_fill_inode
+};
+
+
+int __init
+parport_atari_init(void)
+{
+ struct parport *p;


+ unsigned long flags;
+

+ if (MACH_IS_ATARI) {
+ save_flags(flags);
+ cli();
+ /* Soundchip port A/B as output. */
+ sound_ym.rd_data_reg_sel = 7;
+ sound_ym.wd_data = (sound_ym.rd_data_reg_sel & 0x3f) | 0xc0;
+ /* STROBE high. */
+ sound_ym.rd_data_reg_sel = 14;
+ sound_ym.wd_data = sound_ym.rd_data_reg_sel | (1 << 5);
+ restore_flags(flags);
+ /* MFP port I0 as input. */
+ mfp.data_dir &= ~1;
+ /* MFP port I0 interrupt on high->low edge. */
+ mfp.active_edge &= ~1;
+ p = parport_register_port((unsigned long)&sound_ym.wd_data,
+ IRQ_MFP_BUSY, PARPORT_DMA_NONE,
+ &parport_atari_ops);
+ if (!p)
+ return 0;
+ this_port = p;
+ printk(KERN_INFO "%s: Atari built-in port using irq\n", p->name);
+ parport_proc_register(p);
+ p->flags |= PARPORT_FLAG_COMA;
+
+ if (parport_probe_hook)
+ (*parport_probe_hook)(p);
+ return 1;
+ }


+ return 0;
+}
+
+#ifdef MODULE
+

+MODULE_AUTHOR("Andreas Schwab");
+MODULE_DESCRIPTION("Parport Driver for Atari builtin Port");
+MODULE_SUPPORTED_DEVICE("Atari builtin Parallel Port");
+
+int
+init_module(void)
+{
+ return parport_atari_init() ? 0 : -ENODEV;
+}
+
+void
+cleanup_module(void)
+{
+ if (!(this_port->flags & PARPORT_FLAG_COMA))
+ parport_quiesce(this_port);
+ parport_proc_unregister(this_port);
+ parport_unregister_port(this_port);
+}
+#endif
diff -u --recursive --new-file v2.2.7/linux/drivers/misc/parport_ieee1284.c linux/drivers/misc/parport_ieee1284.c
--- v2.2.7/linux/drivers/misc/parport_ieee1284.c Tue Mar 23 14:35:47 1999
+++ linux/drivers/misc/parport_ieee1284.c Mon May 10 10:26:31 1999
@@ -48,25 +48,22 @@
X int parport_ieee1284_nibble_mode_ok(struct parport *port, unsigned char mode)
X {
X /* make sure it's a valid state, set nStrobe & nAutoFeed high */
- parport_write_control(port, (parport_read_control(port) \
- & ~1 ) & ~2);
+ parport_frob_control (port, (1|2), 0);
X udelay(1);
X parport_write_data(port, mode);
X udelay(400);
X /* nSelectIn high, nAutoFd low */
- parport_write_control(port, (parport_read_control(port) & ~8) | 2);
+ parport_frob_control(port, (2|8), 2);
X if (parport_wait_peripheral(port, 0x78, 0x38)) {
- parport_write_control(port,
- (parport_read_control(port) & ~2) | 8);
+ parport_frob_control(port, (2|8), 8);
X return 0;
X }
X /* nStrobe low */
- parport_write_control(port, parport_read_control(port) | 1);
+ parport_frob_control (port, 1, 1);
X udelay(1); /* Strobe wait */
X /* nStrobe high, nAutoFeed low, last step before transferring
X * reverse data */
- parport_write_control(port, (parport_read_control(port) \
- & ~1) & ~2);
+ parport_frob_control (port, (1|2), 0);
X udelay(1);
X /* Data available? */
X parport_wait_peripheral (port, PARPORT_STATUS_ACK, PARPORT_STATUS_ACK);
diff -u --recursive --new-file v2.2.7/linux/drivers/misc/parport_init.c linux/drivers/misc/parport_init.c
--- v2.2.7/linux/drivers/misc/parport_init.c Mon Jan 4 15:08:17 1999
+++ linux/drivers/misc/parport_init.c Tue May 11 09:55:49 1999
@@ -126,6 +126,15 @@
X #ifdef CONFIG_PARPORT_AX
X parport_ax_init();
X #endif
+#ifdef CONFIG_PARPORT_AMIGA
+ parport_amiga_init();
+#endif
+#ifdef CONFIG_PARPORT_MFC3
+ parport_mfc3_init();
+#endif
+#ifdef CONFIG_PARPORT_ATARI
+ parport_atari_init();
+#endif
X return 0;
X }
X #endif
diff -u --recursive --new-file v2.2.7/linux/drivers/misc/parport_mfc3.c linux/drivers/misc/parport_mfc3.c
--- v2.2.7/linux/drivers/misc/parport_mfc3.c Wed Dec 31 16:00:00 1969
+++ linux/drivers/misc/parport_mfc3.c Tue May 11 09:55:49 1999
@@ -0,0 +1,420 @@
+/* Low-level parallel port routines for the Multiface 3 card


+ *
+ * Author: Joerg Dorchain <dorc...@wirbel.com>
+ *

+ * (C) The elitist m68k Users(TM)
+ *
+ * based on the existing parport_amiga and lp_mfc
+ *
+ *
+ * From the MFC3 documentation:
+ *
+ * Miscellaneous PIA Details
+ * -------------------------
+ *
+ * The two open-drain interrupt outputs /IRQA and /IRQB are routed to
+ * /INT2 of the Z2 bus.
+ *
+ * The CPU data bus of the PIA (D0-D7) is connected to D8-D15 on the Z2
+ * bus. This means that any PIA registers are accessed at even addresses.
+ *
+ * Centronics Pin Connections for the PIA
+ * --------------------------------------
+ *
+ * The following table shows the connections between the PIA and the
+ * Centronics interface connector. These connections implement a single, but
+ * very complete, Centronics type interface. The Pin column gives the pin
+ * numbers of the PIA. The Centronics pin numbers can be found in the section
+ * "Parallel Connectors".
+ *
+ *
+ * Pin | PIA | Dir | Centronics Names
+ * -------+-----+-----+---------------------------------------------------------
+ * 19 | CB2 | --> | /STROBE (aka /DRDY)
+ * 10-17 | PBx | <-> | DATA0 - DATA7
+ * 18 | CB1 | <-- | /ACK
+ * 40 | CA1 | <-- | BUSY
+ * 3 | PA1 | <-- | PAPER-OUT (aka POUT)
+ * 4 | PA2 | <-- | SELECTED (aka SEL)
+ * 9 | PA7 | --> | /INIT (aka /RESET or /INPUT-PRIME)
+ * 6 | PA4 | <-- | /ERROR (aka /FAULT)
+ * 7 | PA5 | --> | DIR (aka /SELECT-IN)
+ * 8 | PA6 | --> | /AUTO-FEED-XT
+ * 39 | CA2 | --> | open
+ * 5 | PA3 | <-- | /ACK (same as CB1!)
+ * 2 | PA0 | <-- | BUSY (same as CA1!)
+ * -------+-----+-----+---------------------------------------------------------
+ *
+ * Should be enough to understand some of the driver.
+ */
+
+#include "multiface.h"


+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/parport.h>

+#include <linux/delay.h>
+#include <linux/mc6821.h>
+#include <linux/zorro.h>


+#include <asm/setup.h>
+#include <asm/amigahw.h>
+#include <asm/irq.h>
+#include <asm/amigaints.h>
+

+/* Maximum Number of Cards supported */
+#define MAX_MFC 5


+
+#undef DEBUG
+#ifdef DEBUG
+#define DPRINTK printk
+#else
+static inline int DPRINTK() {return 0;}
+#endif
+

+static struct parport *this_port[MAX_MFC] = {NULL, };
+static volatile int dummy; /* for trigger readds */
+
+#define pia(dev) ((struct pia *)(dev->base))
+static struct parport_operations pp_mfc3_ops;
+
+static void mfc3_write_data(struct parport *p, unsigned char data)


+{
+DPRINTK("write_data %c\n",data);
+

+ dummy = pia(p)->pprb; /* clears irq bit */
+ /* Triggers also /STROBE.*/
+ pia(p)->pprb = data;
+}
+
+static unsigned char mfc3_read_data(struct parport *p)
+{
+ /* clears interupt bit. Triggers also /STROBE. */
+ return pia(p)->pprb;
+}
+
+static unsigned char control_pc_to_mfc3(unsigned char control)
+{
+ unsigned char ret = 32|64;
+
+ if (control & PARPORT_CONTROL_DIRECTION) /* XXX: What is this? */
+ ;
+ if (control & PARPORT_CONTROL_INTEN) /* XXX: What is INTEN? */
+ ;
+ if (control & PARPORT_CONTROL_SELECT) /* XXX: What is SELECP? */
+ ret &= ~32; /* /SELECT_IN */
+ if (control & PARPORT_CONTROL_INIT) /* INITP */
+ ret |= 128;
+ if (control & PARPORT_CONTROL_AUTOFD) /* AUTOLF */
+ ret &= ~64;
+ if (control & PARPORT_CONTROL_STROBE) /* Strobe */
+ /* Handled directly by hardware */;


+ return ret;
+}
+

+static unsigned char control_mfc3_to_pc(unsigned char control)
+{
+ unsigned char ret = PARPORT_CONTROL_INTEN | PARPORT_CONTROL_STROBE
+ | PARPORT_CONTROL_AUTOFD | PARPORT_CONTROL_SELECT;
+
+ if (control & 128) /* /INITP */
+ ret |= PARPORT_CONTROL_INIT;
+ if (control & 64) /* /AUTOLF */
+ ret &= ~PARPORT_CONTROL_AUTOFD;
+ if (control & 32) /* /SELECT_IN */
+ ret &= ~PARPORT_CONTROL_SELECT;


+ return ret;
+}
+

+static void mfc3_write_control(struct parport *p, unsigned char control)
+{
+DPRINTK("write_control %02x\n",control);
+ pia(p)->ppra = (pia(p)->ppra & 0x1f) | control_pc_to_mfc3(control);
+}
+
+static unsigned char mfc3_read_control( struct parport *p)
+{
+DPRINTK("read_control \n");
+ return control_mfc3_to_pc(pia(p)->ppra & 0xe0);
+}
+
+static unsigned char mfc3_frob_control( struct parport *p, unsigned char mask, unsigned char val)
+{
+ unsigned char old;
+
+DPRINTK("frob_control mask %02x, value %02x\n",mask,val);
+ old = mfc3_read_control(p);
+ mfc3_write_control(p, (old & ~mask) ^ val);
+ return old;
+}
+
+
+static unsigned char status_pc_to_mfc3(unsigned char status)
+{
+ unsigned char ret = 1;
+
+ if (status & PARPORT_STATUS_BUSY) /* Busy */
+ ret &= ~1;
+ if (status & PARPORT_STATUS_ACK) /* Ack */
+ ret |= 8;
+ if (status & PARPORT_STATUS_PAPEROUT) /* PaperOut */
+ ret |= 2;
+ if (status & PARPORT_STATUS_SELECT) /* select */
+ ret |= 4;
+ if (status & PARPORT_STATUS_ERROR) /* error */
+ ret |= 16;


+ return ret;
+}
+

+static unsigned char status_mfc3_to_pc(unsigned char status)
+{
+ unsigned char ret = PARPORT_STATUS_BUSY;
+
+ if (status & 1) /* Busy */
+ ret &= ~PARPORT_STATUS_BUSY;
+ if (status & 2) /* PaperOut */
+ ret |= PARPORT_STATUS_PAPEROUT;
+ if (status & 4) /* Selected */
+ ret |= PARPORT_STATUS_SELECT;
+ if (status & 8) /* Ack */
+ ret |= PARPORT_STATUS_ACK;
+ if (status & 16) /* /ERROR */
+ ret |= PARPORT_STATUS_ERROR;
+


+ return ret;
+}
+

+static void mfc3_write_status( struct parport *p, unsigned char status)
+{
+DPRINTK("write_status %02x\n",status);
+ pia(p)->ppra = (pia(p)->ppra & 0xe0) | status_pc_to_mfc3(status);
+}
+
+static unsigned char mfc3_read_status(struct parport *p)
+{
+ unsigned char status;
+
+ status = status_mfc3_to_pc(pia(p)->ppra & 0x1f);
+DPRINTK("read_status %02x\n", status);
+ return status;
+}
+
+static void mfc3_change_mode( struct parport *p, int m)
+{
+ /* XXX: This port only has one mode, and I am
+ not sure about the corresponding PC-style mode*/
+}
+
+static int use_cnt = 0;
+
+static void mfc3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ int i;
+
+ for( i = 0; i < MAX_MFC; i++)
+ if (this_port[i] != NULL)
+ if (pia(this_port[i])->crb & 128) { /* Board caused interrupt */
+ dummy = pia(this_port[i])->pprb; /* clear irq bit */
+ parport_generic_irq(irq, this_port[i], regs);
+ }
+}
+
+static void mfc3_release_resources(struct parport *p)
+{
+DPRINTK("realease_resources\n");
+ if (p->irq != PARPORT_IRQ_NONE)
+ if (--use_cnt == 0)
+ free_irq(IRQ_AMIGA_PORTS, &pp_mfc3_ops);
+}
+
+static int mfc3_claim_resources(struct parport *p)
+{
+DPRINTK("claim_resources\n");
+ if (p->irq != PARPORT_IRQ_NONE)
+ if (use_cnt++ == 0)
+ if (request_irq(IRQ_AMIGA_PORTS, mfc3_interrupt, 0, p->name, &pp_mfc3_ops))
+ return use_cnt--;


+ return 0;
+}
+

+static void mfc3_init_state(struct parport_state *s)
+{
+ s->u.amiga.data = 0;
+ s->u.amiga.datadir = 255;
+ s->u.amiga.status = 0;
+ s->u.amiga.statusdir = 0xe0;
+}
+
+static void mfc3_save_state(struct parport *p, struct parport_state *s)
+{
+ s->u.amiga.data = pia(p)->pprb;
+ pia(p)->crb &= ~PIA_DDR;
+ s->u.amiga.datadir = pia(p)->pddrb;
+ pia(p)->crb |= PIA_DDR;
+ s->u.amiga.status = pia(p)->ppra;
+ pia(p)->cra &= ~PIA_DDR;
+ s->u.amiga.statusdir = pia(p)->pddrb;
+ pia(p)->cra |= PIA_DDR;
+}
+
+static void mfc3_restore_state(struct parport *p, struct parport_state *s)
+{
+ pia(p)->pprb = s->u.amiga.data;
+ pia(p)->crb &= ~PIA_DDR;
+ pia(p)->pddrb = s->u.amiga.datadir;
+ pia(p)->crb |= PIA_DDR;
+ pia(p)->ppra = s->u.amiga.status;
+ pia(p)->cra &= ~PIA_DDR;
+ pia(p)->pddrb = s->u.amiga.statusdir;
+ pia(p)->cra |= PIA_DDR;
+}
+
+static void mfc3_enable_irq(struct parport *p)
+{
+ pia(p)->crb |= PIA_C1_ENABLE_IRQ;
+}
+
+static void mfc3_disable_irq(struct parport *p)
+{
+ pia(p)->crb &= ~PIA_C1_ENABLE_IRQ;
+}
+
+static void mfc3_inc_use_count(void)
+{
+ MOD_INC_USE_COUNT;
+}
+
+static void mfc3_dec_use_count(void)


+{
+ MOD_DEC_USE_COUNT;
+}
+

+static void mfc3_fill_inode(struct inode *inode, int fill)
+{
+#ifdef MODULE
+ if (fill)
+ MOD_INC_USE_COUNT;
+ else
+ MOD_DEC_USE_COUNT;
+#endif
+}
+
+static struct parport_operations pp_mfc3_ops = {
+ mfc3_write_data,
+ mfc3_read_data,
+
+ mfc3_write_control,
+ mfc3_read_control,
+ mfc3_frob_control,
+
+ NULL, /* write_econtrol */
+ NULL, /* read_econtrol */
+ NULL, /* frob_econtrol */
+
+ mfc3_write_status,
+ mfc3_read_status,
+
+ NULL, /* write fifo */
+ NULL, /* read fifo */
+
+ mfc3_change_mode,
+
+
+ mfc3_release_resources,
+ mfc3_claim_resources,
+
+
+ NULL, /* epp_write_data */
+ NULL, /* epp_read_data */
+ NULL, /* epp_write_addr */
+ NULL, /* epp_read_addr */
+ NULL, /* epp_check_timeout */
+
+ NULL, /* epp_write_block */
+ NULL, /* epp_read_block */
+
+ NULL, /* ecp_write_block */
+ NULL, /* ecp_read_block */
+
+ mfc3_init_state,
+ mfc3_save_state,
+ mfc3_restore_state,
+
+ mfc3_enable_irq,
+ mfc3_disable_irq,
+ mfc3_interrupt,
+
+ mfc3_inc_use_count,
+ mfc3_dec_use_count,
+ mfc3_fill_inode
+};
+
+/* ----------- Initialisation code --------------------------------- */
+
+__initfunc(int parport_mfc3_init(void))
+{
+ struct parport *p;
+ int pias = 0;
+ struct pia *pp;
+ unsigned int key = 0;
+ const struct ConfigDev *cd;
+
+ if (MACH_IS_AMIGA) {
+ while ((key = zorro_find(ZORRO_PROD_BSC_MULTIFACE_III, 0, key))) {
+ cd = zorro_get_board(key);
+ pp = (struct pia *)ZTWO_VADDR((((u_char *)cd->cd_BoardAddr)+PIABASE));
+ if (pias < MAX_MFC) {
+ pp->crb = 0;
+ pp->pddrb = 255; /* all data pins output */
+ pp->crb = PIA_DDR|32|8;
+ dummy = pp->pddrb; /* reading clears interrupt */
+ pp->cra = 0;
+ pp->pddra = 0xe0; /* /RESET, /DIR ,/AUTO-FEED output */
+ pp->cra = PIA_DDR;
+ pp->ppra = 0; /* reset printer */
+ udelay(10);
+ pp->ppra = 128;
+ if ((p = parport_register_port((unsigned long)pp,
+ IRQ_AMIGA_PORTS, PARPORT_DMA_NONE,
+ &pp_mfc3_ops))) {
+ this_port[pias++] = p;
+ printk(KERN_INFO "%s: Multiface III port using irq\n", p->name);
+ /* XXX: set operating mode */
+ parport_proc_register(p);
+ p->flags |= PARPORT_FLAG_COMA;
+ if (parport_probe_hook)
+ (*parport_probe_hook)(p);
+ zorro_config_board(key, 0);
+ p->private_data = (void *)key;
+ }
+ }
+ }
+ }
+ return pias;


+}
+
+#ifdef MODULE
+

+MODULE_AUTHOR("Joerg Dorchain");
+MODULE_DESCRIPTION("Parport Driver for Multiface 3 expansion cards Paralllel Port");
+MODULE_SUPPORTED_DEVICE("Multiface 3 Parallel Port");
+
+int init_module(void)
+{
+ return ! parport_mfc3_init();
+}
+
+void cleanup_module(void)
+{
+ int i;
+
+ for (i = 0; i < MAX_MFC; i++)
+ if (this_port[i] != NULL) {
+ if (!(this_port[i]->flags & PARPORT_FLAG_COMA))
+ parport_quiesce(this_port[i]);
+ parport_proc_unregister(this_port[i]);
+ parport_unregister_port(this_port[i]);
+ zorro_unconfig_board((unsigned int)this_port[i]->private_data, 0);
+ }
+}
+#endif
+
+
diff -u --recursive --new-file v2.2.7/linux/drivers/misc/parport_pc.c linux/drivers/misc/parport_pc.c
--- v2.2.7/linux/drivers/misc/parport_pc.c Tue Mar 23 14:35:47 1999
+++ linux/drivers/misc/parport_pc.c Mon May 10 10:26:31 1999
@@ -53,6 +53,8 @@
X than PARPORT_MAX (in <linux/parport.h>). */
X #define PARPORT_PC_MAX_PORTS 8
X
+static int user_specified = 0;
+
X static void parport_pc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
X {
X parport_generic_irq(irq, (struct parport *) dev_id, regs);
@@ -103,19 +105,24 @@
X
X void parport_pc_write_control(struct parport *p, unsigned char d)
X {
+ struct parport_pc_private *priv = p->private_data;
+ priv->ctr = d;/* update soft copy */
X outb(d, p->base+CONTROL);
X }
X
X unsigned char parport_pc_read_control(struct parport *p)
X {
- return inb(p->base+CONTROL);
+ struct parport_pc_private *priv = p->private_data;
+ return priv->ctr;
X }
X
X unsigned char parport_pc_frob_control(struct parport *p, unsigned char mask, unsigned char val)
X {
- unsigned char old = inb(p->base+CONTROL);
- outb(((old & ~mask) ^ val), p->base+CONTROL);
- return old;
+ struct parport_pc_private *priv = p->private_data;
+ unsigned char ctr = priv->ctr;
+ ctr = (ctr & ~mask) ^ val;
+ outb (ctr, p->base+CONTROL);
+ return priv->ctr = ctr; /* update soft copy */
X }
X
X void parport_pc_write_status(struct parport *p, unsigned char d)
@@ -345,6 +352,8 @@
X */
X static int parport_SPP_supported(struct parport *pb)
X {
+ unsigned char r, w;
+
X /*
X * first clear an eventually pending EPP timeout
X * I (sai...@ife.ee.ethz.ch) have an SMSC chipset
@@ -354,14 +363,54 @@
X parport_pc_epp_clear_timeout(pb);
X
X /* Do a simple read-write test to make sure the port exists. */
- parport_pc_write_control(pb, 0xc);
- parport_pc_write_data(pb, 0xaa);
- if (parport_pc_read_data(pb) != 0xaa) return 0;
-
- parport_pc_write_data(pb, 0x55);
- if (parport_pc_read_data(pb) != 0x55) return 0;
+ w = 0xc;
+ parport_pc_write_control(pb, w);
+
+ /* Can we read from the control register? Some ports don't
+ * allow reads, so read_control just returns a software
+ * copy. Some ports _do_ allow reads, so bypass the software
+ * copy here. In addition, some bits aren't writable. */
+ r = inb (pb->base+CONTROL);
+ if ((r & 0x3f) == w) {
+ w = 0xe;
+ parport_pc_write_control (pb, w);
+ r = inb (pb->base+CONTROL);
+ parport_pc_write_control (pb, 0xc);
+ if ((r & 0x3f) == w)
+ return PARPORT_MODE_PCSPP;
+ }
+
+ if (user_specified)
+ /* That didn't work, but the user thinks there's a
+ * port here. */
+ printk (KERN_DEBUG "0x%lx: CTR: wrote 0x%02x, read 0x%02x\n",
+ pb->base, w, r);
+
+ /* Try the data register. The data lines aren't tri-stated at
+ * this stage, so we expect back what we wrote. */
+ w = 0xaa;
+ parport_pc_write_data (pb, w);
+ r = parport_pc_read_data (pb);
+ if (r == w) {
+ w = 0x55;
+ parport_pc_write_data (pb, w);
+ r = parport_pc_read_data (pb);
+ if (r == w)
+ return PARPORT_MODE_PCSPP;
+ }
+
+ if (user_specified)
+ /* Didn't work with 0xaa, but the user is convinced
+ * this is the place. */
+ printk (KERN_DEBUG "0x%lx: DATA: wrote 0x%02x, read 0x%02x\n",
+ pb->base, w, r);
+
+ /* It's possible that we can't read the control register or
+ the data register. In that case just believe the user. */
+ if (user_specified)
+ return PARPORT_MODE_PCSPP;
X
- return PARPORT_MODE_PCSPP;


+ return 0;
X }
X

X /* Check for ECP
@@ -712,6 +761,15 @@
X if (check_region(base, 3)) return 0;
X if (!(p = parport_register_port(base, irq, dma, &parport_pc_ops)))
X return 0;
+ p->private_data = kmalloc (sizeof (struct parport_pc_private),
+ GFP_KERNEL);
+ if (!p->private_data) {
+ /* Not enough memory. */
+ printk (KERN_DEBUG "parport (0x%lx): no memory!\n", base);
+ parport_unregister_port (p);
+ return 0;
+ }
+ ((struct parport_pc_private *) (p->private_data))->ctr = 0xc;
X if (p->base != 0x3bc) {
X if (!check_region(base+0x400,3)) {
X p->modes |= parport_ECR_present(p);
@@ -725,6 +783,7 @@
X }
X if (!parport_SPP_supported(p)) {
X /* No port. */
+ kfree (p->private_data);
X parport_unregister_port (p);
X return 0;
X }
@@ -787,6 +846,7 @@
X int count = 0, i = 0;
X if (io && *io) {
X /* Only probe the ports we were given. */
+ user_specified = 1;
X do {
X count += probe_one_port(*(io++), *(irq++), *(dma++));
X } while (*io && (++i < PARPORT_PC_MAX_PORTS));
@@ -829,6 +889,7 @@
X if (!(p->flags & PARPORT_FLAG_COMA))
X parport_quiesce(p);
X parport_proc_unregister(p);
+ kfree (p->private_data);
X parport_unregister_port(p);
X }
X p = tmp;
diff -u --recursive --new-file v2.2.7/linux/drivers/net/3c507.c linux/drivers/net/3c507.c
--- v2.2.7/linux/drivers/net/3c507.c Thu Feb 12 20:56:07 1998
+++ linux/drivers/net/3c507.c Thu May 6 23:14:36 1999
@@ -40,6 +40,7 @@
X info that the casual reader might think that it documents the i82586 :-<.


X */
X
+#include <linux/config.h>

X #include <linux/kernel.h>
X #include <linux/sched.h>
X #include <linux/types.h>
@@ -53,6 +54,7 @@
X #include <asm/bitops.h>
X #include <asm/io.h>
X #include <asm/dma.h>
+#include <asm/spinlock.h>
X #include <linux/errno.h>
X
X #include <linux/netdevice.h>
@@ -123,6 +125,7 @@
X ushort tx_head;
X ushort tx_cmd_link;
X ushort tx_reap;
+ spinlock_t lock;
X };
X
X /*
@@ -448,6 +451,7 @@
X struct net_local *lp = (struct net_local *)dev->priv;
X int ioaddr = dev->base_addr;
X unsigned long shmem = dev->mem_start;


+ unsigned long flags;
X

X if (dev->tbusy)
X {
@@ -487,7 +491,13 @@
X lp->stats.tx_bytes+=length;
X /* Disable the 82586's input to the interrupt line. */
X outb(0x80, ioaddr + MISC_CTRL);
+#ifdef CONFIG_SMP
+ spin_lock_irqsave(&lp->lock, flags);
X hardware_send_packet(dev, buf, length);
+ spin_unlock_irqrestore(&lp->lock, flags);
+#else
+ hardware_send_packet(dev, buf, length);
+#endif
X dev->trans_start = jiffies;
X /* Enable the 82586 interrupt input. */
X outb(0x84, ioaddr + MISC_CTRL);
@@ -515,11 +525,14 @@
X return;
X }
X dev->interrupt = 1;
+
X
X ioaddr = dev->base_addr;
X lp = (struct net_local *)dev->priv;
X shmem = dev->mem_start;
X
+ spin_lock(&lp->lock);
+
X status = readw(shmem+iSCB_STATUS);
X
X if (net_debug > 4) {
@@ -598,6 +611,7 @@
X
X /* Enable the 82586's interrupt input. */
X outb(0x84, ioaddr + MISC_CTRL);
+ spin_unlock(&lp->lock);
X
X return;
X }
diff -u --recursive --new-file v2.2.7/linux/drivers/net/3c509.c linux/drivers/net/3c509.c
--- v2.2.7/linux/drivers/net/3c509.c Tue Mar 23 14:35:47 1999
+++ linux/drivers/net/3c509.c Thu May 6 14:02:34 1999
@@ -568,7 +568,7 @@
X */
X
X #ifdef __SMP__
- disable_irq(dev->irq);
+ disable_irq_nosync(dev->irq);
X spin_lock(&lp->lock);
X #endif
X
diff -u --recursive --new-file v2.2.7/linux/drivers/net/8390.c linux/drivers/net/8390.c
--- v2.2.7/linux/drivers/net/8390.c Wed Mar 10 15:29:46 1999
+++ linux/drivers/net/8390.c Thu May 6 14:02:34 1999
@@ -257,8 +257,7 @@
X
X /* Ugly but a reset can be slow, yet must be protected */
X
- disable_irq(dev->irq);
- synchronize_irq();
+ disable_irq_nosync(dev->irq);
X spin_lock(&ei_local->page_lock);
X
X /* Try to restart the card. Perhaps the user has fixed something. */
@@ -286,8 +285,7 @@
X * Slow phase with lock held.
X */
X
- disable_irq(dev->irq);
- synchronize_irq();
+ disable_irq_nosync(dev->irq);
X
X spin_lock(&ei_local->page_lock);
X
diff -u --recursive --new-file v2.2.7/linux/drivers/net/de4x5.c linux/drivers/net/de4x5.c
--- v2.2.7/linux/drivers/net/de4x5.c Thu Dec 31 10:29:00 1998
+++ linux/drivers/net/de4x5.c Sat May 8 19:46:44 1999
@@ -225,11 +225,18 @@
X to determine this in advance other than by trial and error and common
X sense, e.g. call a BNC connectored port 'BNC', not '10Mb'.
X
- TO DO:
- ------
+ Changed the bus probing. EISA used to be done first, followed by PCI.
+ Most people probably don't even know what a de425 is today and the EISA
+ probe has messed up some SCSI cards in the past, so now PCI is always
+ probed first followed by EISA if a) the architecture allows EISA and
+ either b) there have been no PCI cards detected or c) an EISA probe is
+ forced by the user. To force a probe include "force_eisa" in your
+ insmod "args" line; for built-in kernels either change the driver to do
+ this automatically or include #define DE4X5_FORCE_EISA on or before
+ line 1040 in the driver.
X
- o check what revision numbers the 21142 and 21143 have
- o
+ TO DO:
+ ------
X
X Revision History
X ----------------
@@ -416,11 +423,14 @@
X access traps. This flag is merely for log messages:
X should do something more definitive though...
X 0.543 30-Dec-98 Add SMP spin locking.
-
+ 0.544 8-May-99 Fix for buggy SROM in Motorola embedded boards using
+ a 21143 by <mmpo...@home.com>.
+ Change PCI/EISA bus probing order.
+
X =========================================================================
X */
X
-static const char *version = "de4x5.c:V0.543 1998/12/30 dav...@maniac.ultranet.com\n";
+static const char *version = "de4x5.c:V0.544 1999/5/8 dav...@maniac.ultranet.com\n";
X
X #include <linux/config.h>
X #include <linux/module.h>
@@ -1027,8 +1037,11 @@
X #if !defined(__sparc_v9__) && !defined(__powerpc__) && !defined(__alpha__)
X static u_char de4x5_irq[] = EISA_ALLOWED_IRQ_LIST;
X static int lastEISA = 0;
-#else
-static int lastEISA = MAX_EISA_SLOTS; /* Only PCI probes */
+# ifdef DE4X5_FORCE_EISA /* Force an EISA bus probe or not */
+static int forceEISA = 1;
+# else
+static int forceEISA = 0;
+# endif
X #endif
X static int num_de4x5s = 0;
X static int cfrv = 0, useSROM = 0;
@@ -1098,12 +1111,12 @@
X {
X u_long iobase = dev->base_addr;
X
+ pci_probe(dev, iobase);
X #if !defined(__sparc_v9__) && !defined(__powerpc__) && !defined(__alpha__)
- eisa_probe(dev, iobase);
-#endif
- if (lastEISA == MAX_EISA_SLOTS) {
- pci_probe(dev, iobase);
+ if ((lastPCI == NO_MORE_PCI) && ((num_de4x5s == 0) || forceEISA)) {
+ eisa_probe(dev, iobase);
X }
+#endif
X
X return (dev->priv ? 0 : -ENODEV);
X }
@@ -1230,6 +1243,7 @@
X if ((tmp = (void *)kmalloc(RX_BUFF_SZ * NUM_RX_DESC + ALIGN,
X GFP_KERNEL)) == NULL) {
X kfree(lp->cache.priv);
+ lp->cache.priv = NULL;
X return -ENOMEM;
X }
X
@@ -2066,38 +2080,36 @@
X }
X
X for (status = -ENODEV; (i<maxSlots) && (dev!=NULL); i++, iobase+=EISA_SLOT_INC) {
- if (EISA_signature(name, EISA_ID)) {
- cfid = (u32) inl(PCI_CFID);
- cfrv = (u_short) inl(PCI_CFRV);
- device = (cfid >> 8) & 0x00ffff00;
- vendor = (u_short) cfid;
+ if (check_region(iobase, DE4X5_EISA_TOTAL_SIZE)) continue;
+ if (!EISA_signature(name, EISA_ID)) continue;
+
+ cfid = (u32) inl(PCI_CFID);
+ cfrv = (u_short) inl(PCI_CFRV);
+ device = (cfid >> 8) & 0x00ffff00;
+ vendor = (u_short) cfid;
X
- /* Read the EISA Configuration Registers */
- irq = inb(EISA_REG0);
- irq = de4x5_irq[(irq >> 1) & 0x03];
-
- if (is_DC2114x) {
- device = ((cfrv & CFRV_RN) < DC2114x_BRK ? DC21142 : DC21143);
- }
- lp->chipset = device;
-
- /* Write the PCI Configuration Registers */
- outl(PCI_COMMAND_IO | PCI_COMMAND_MASTER, PCI_CFCS);
- outl(0x00006000, PCI_CFLT);
- outl(iobase, PCI_CBIO);
+ /* Read the EISA Configuration Registers */
+ irq = inb(EISA_REG0);
+ irq = de4x5_irq[(irq >> 1) & 0x03];
+
+ if (is_DC2114x) {
+ device = ((cfrv & CFRV_RN) < DC2114x_BRK ? DC21142 : DC21143);
+ }
+ lp->chipset = device;
+
+ /* Write the PCI Configuration Registers */
+ outl(PCI_COMMAND_IO | PCI_COMMAND_MASTER, PCI_CFCS);
+ outl(0x00006000, PCI_CFLT);
+ outl(iobase, PCI_CBIO);
X
- DevicePresent(EISA_APROM);
- if (check_region(iobase, DE4X5_EISA_TOTAL_SIZE) == 0) {
- dev->irq = irq;
- if ((status = de4x5_hw_init(dev, iobase)) == 0) {
- num_de4x5s++;
- if (loading_module) link_modules(lastModule, dev);
- lastEISA = i;
- return;
- }
- } else if (ioaddr != 0) {
- printk("%s: region already allocated at 0x%04lx.\n", dev->name,iobase);
- }
+ DevicePresent(EISA_APROM);
+
+ dev->irq = irq;
+ if ((status = de4x5_hw_init(dev, iobase)) == 0) {
+ num_de4x5s++;
+ if (loading_module) link_modules(lastModule, dev);
+ lastEISA = i;
+ return;
X }
X }
X
@@ -4794,6 +4806,7 @@
X if (lp->state == INITIALISED) {
X lp->ibn = 3;
X lp->active = *p++;
+ if (MOTO_SROM_BUG) lp->active = 0;
X lp->phy[lp->active].gep = (*p ? p : 0); p += (2 * (*p) + 1);
X lp->phy[lp->active].rst = (*p ? p : 0); p += (2 * (*p) + 1);
X lp->phy[lp->active].mc = TWIDDLE(p); p += 2;
@@ -5326,6 +5339,9 @@
X t = *q;
X *q = '\0';
X
+#if !defined(__sparc_v9__) && !defined(__powerpc__) && !defined(__alpha__)
+ if (strstr(p, "force_eisa") || strstr(p, "FORCE_EISA")) forceEISA = 1;
+#endif
X if (strstr(p, "fdx") || strstr(p, "FDX")) lp->params.fdx = 1;
X
X if (strstr(p, "autosense") || strstr(p, "AUTOSENSE")) {
@@ -5766,6 +5782,12 @@
X release_region(p->base_addr, (lp->bus == PCI ?
X DE4X5_PCI_TOTAL_SIZE :
X DE4X5_EISA_TOTAL_SIZE));
+ if (lp->cache.buf) { /* MAC buffers allocated? */
+ kfree(lp->cache.buf); /* Free the MAC buffers */
+ }
+ if (lp->cache.priv) { /* Private area allocated? */
+ kfree(lp->cache.priv); /* Free the private area */
+ }
X }
X kfree(p);
X } else {
@@ -5799,10 +5821,10 @@
X if (lp->cache.buf) { /* MAC buffers allocated? */
X kfree(lp->cache.buf); /* Free the MAC buffers */
X }
- kfree(lp->cache.priv); /* Free the private area */
X release_region(p->base_addr, (lp->bus == PCI ?
X DE4X5_PCI_TOTAL_SIZE :
X DE4X5_EISA_TOTAL_SIZE));
+ kfree(lp->cache.priv); /* Free the private area */
X }
X unregister_netdev(p);
X kfree(p); /* Free the device structure */
@@ -5867,6 +5889,9 @@
X * Local variables:
X * compile-command: "gcc -D__KERNEL__ -I/linux/include -Wall -Wstrict-prototypes -fomit-frame-pointer -fno-strength-reduce -malign-loops=2 -malign-jumps=2 -malign-functions=2 -O2 -m486 -c de4x5.c"
X *
- * compile-command: "gcc -D__KERNEL__ -DMODULE -I/linux/include -Wall -Wstrict-prototypes -fomit-frame-pointer -fno-strength-reduce -malign-loops=2 -malign-jumps=2 -malign-functions=2 -O2 -m486 -c de4x5.c"
+ * Delete -D__SMP__ below if you didn't define this in your kernel
+ * Delete -DMODVERSIONS below if you didn't define this in your kernel
+ *
+ * compile-command: "gcc -D__KERNEL__ -DMODULE -I/linux/include -Wall -Wstrict-prototypes -fomit-frame-pointer -fno-strength-reduce -malign-loops=2 -malign-jumps=2 -malign-functions=2 -O2 -m486 -DMODVERSIONS -include /linux/include/linux/modversions.h -c de4x5.c"
X * End:
X */
diff -u --recursive --new-file v2.2.7/linux/drivers/net/de4x5.h linux/drivers/net/de4x5.h
--- v2.2.7/linux/drivers/net/de4x5.h Thu Dec 31 10:29:00 1998
+++ linux/drivers/net/de4x5.h Tue May 11 08:34:32 1999
@@ -1027,3 +1027,5 @@
X #define DE4X5_GET_REG 0x0e /* Get the DE4X5 Registers */
X
X #define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s))
+
+#define MOTO_SROM_BUG ((lp->active == 8) && (((le32_to_cpu(get_unaligned(((s32 *)dev->dev_addr))))&0x00ffffff)==0x3e0008))
diff -u --recursive --new-file v2.2.7/linux/drivers/net/eexpress.c linux/drivers/net/eexpress.c
--- v2.2.7/linux/drivers/net/eexpress.c Tue Jan 19 11:32:51 1999
+++ linux/drivers/net/eexpress.c Thu May 6 23:14:36 1999
@@ -83,6 +83,7 @@
X * practice.


X */
X
+#include <linux/config.h>

X #include <linux/module.h>
X
X #include <linux/kernel.h>
@@ -107,6 +108,8 @@
X #include <linux/skbuff.h>
X #include <linux/malloc.h>
X
+#include <asm/spinlock.h>
+
X #ifndef NET_DEBUG
X #define NET_DEBUG 4
X #endif
@@ -141,6 +144,7 @@
X unsigned char width; /* 0 for 16bit, 1 for 8bit */
X unsigned char was_promisc;
X unsigned char old_mc_count;
+ spinlock_t lock;
X };
X
X /* This is the code and data that is downloaded to the EtherExpress card's
@@ -502,6 +506,7 @@
X static int eexp_xmit(struct sk_buff *buf, struct device *dev)
X {
X struct net_local *lp = (struct net_local *)dev->priv;


+ unsigned long flags;
X

X #if NET_DEBUG > 6
X printk(KERN_DEBUG "%s: eexp_xmit()\n", dev->name);
@@ -509,6 +514,15 @@
X
X disable_irq(dev->irq);
X
+ /*
+ * Best would be to use synchronize_irq(); spin_lock() here
+ * lets make it work first..
+ */
+
+#ifdef CONFIG_SMP
+ spin_lock_irqsave(&lp->lock, flags);
+#endif
+
X /* If dev->tbusy is set, all our tx buffers are full but the kernel
X * is calling us anyway. Check that nothing bad is happening.
X */
@@ -516,7 +530,13 @@
X int status = scb_status(dev);
X unstick_cu(dev);
X if ((jiffies - lp->last_tx) < HZ)
+ {
+#ifdef CONFIG_SMP
+ spin_unlock_irqrestore(&lp->lock, flags);
+#endif
+
X return 1;
+ }
X printk(KERN_INFO "%s: transmit timed out, %s?", dev->name,
X (SCB_complete(status)?"lost interrupt":
X "board on fire"));
@@ -544,6 +564,9 @@
X eexp_hw_tx_pio(dev,data,length);
X }
X dev_kfree_skb(buf);
+#ifdef CONFIG_SMP
+ spin_unlock_irqrestore(&lp->lock, flags);
+#endif
X enable_irq(dev->irq);
X return 0;
X }
@@ -646,11 +669,14 @@
X lp = (struct net_local *)dev->priv;
X ioaddr = dev->base_addr;
X
+ spin_lock(&lp->lock);
+
X old_read_ptr = inw(ioaddr+READ_PTR);
X old_write_ptr = inw(ioaddr+WRITE_PTR);
X
X outb(SIRQ_dis|irqrmap[irq],ioaddr+SET_IRQ);
X
+
X dev->interrupt = 1;
X
X status = scb_status(dev);
@@ -726,6 +752,8 @@
X #endif
X outw(old_read_ptr, ioaddr+READ_PTR);
X outw(old_write_ptr, ioaddr+WRITE_PTR);
+
+ spin_unlock(&lp->lock);
X return;
X }
X
diff -u --recursive --new-file v2.2.7/linux/drivers/net/epic100.c linux/drivers/net/epic100.c
--- v2.2.7/linux/drivers/net/epic100.c Wed Jan 13 15:00:42 1999
+++ linux/drivers/net/epic100.c Thu Apr 29 11:53:41 1999
@@ -1106,6 +1106,7 @@
X memcpy(skb_put(skb, pkt_len),
X bus_to_virt(ep->rx_ring[entry].bufaddr), pkt_len);
X #endif
+ ep->rx_ring[entry].status = 0x8000;
X } else {
X skb_put(skb = ep->rx_skbuff[entry], pkt_len);
X ep->rx_skbuff[entry] = NULL;
diff -u --recursive --new-file v2.2.7/linux/drivers/net/eql.c linux/drivers/net/eql.c
--- v2.2.7/linux/drivers/net/eql.c Thu May 7 22:51:50 1998
+++ linux/drivers/net/eql.c Mon May 10 13:00:10 1999
@@ -363,8 +363,8 @@
X
X eql_schedule_slaves (eql->queue);
X
- slave_dev = eql_best_slave_dev (eql->queue);
X slave = eql_best_slave (eql->queue);
+ slave_dev = slave ? slave->dev : 0;
X
X if ( slave_dev != 0 )
X {
diff -u --recursive --new-file v2.2.7/linux/drivers/net/ethertap.c linux/drivers/net/ethertap.c
--- v2.2.7/linux/drivers/net/ethertap.c Fri Oct 23 22:01:21 1998
+++ linux/drivers/net/ethertap.c Tue May 11 08:24:31 1999
@@ -177,11 +177,21 @@
X #endif
X
X if (skb_headroom(skb) < 2) {
- printk(KERN_DEBUG "%s : bug --- xmit with head<2\n", dev->name);
+ static int once;
+ struct sk_buff *skb2;
+
+ if (!once) {
+ once = 1;
+ printk(KERN_DEBUG "%s: not aligned xmit by protocol %04x\n", dev->name, skb->protocol);
+ }
+
+ skb2 = skb_realloc_headroom(skb, 2);
X dev_kfree_skb(skb);
- return 0;
+ if (skb2 == NULL)
+ return 0;
+ skb = skb2;
X }
- skb_push(skb, 2);
+ __skb_push(skb, 2);
X
X /* Make the same thing, which loopback does. */
X if (skb_shared(skb)) {
diff -u --recursive --new-file v2.2.7/linux/drivers/net/ibmtr.c linux/drivers/net/ibmtr.c
--- v2.2.7/linux/drivers/net/ibmtr.c Wed Apr 28 11:37:30 1999
+++ linux/drivers/net/ibmtr.c Fri May 7 10:57:42 1999
@@ -513,6 +513,7 @@
X /* How much shared RAM is on adapter ? */
X #ifdef PCMCIA
X ti->avail_shared_ram = pcmcia_reality_check(get_sram_size(ti));
+ ibmtr_mem_base = ti->sram_base ;
X #else
X ti->avail_shared_ram = get_sram_size(ti);
X #endif
@@ -1498,6 +1499,7 @@
X ti->asb + offsetof(struct asb_rec, rec_buf_addr));
X
X lan_hdr_len=readb(ti->arb + offsetof(struct arb_rec_req, lan_hdr_len));
+ hdr_len = lan_hdr_len + sizeof(struct trllc) + sizeof(struct iphdr);
X
X llc=(rbuffer + offsetof(struct rec_buf, data) + lan_hdr_len);
X
@@ -1524,8 +1526,10 @@
X return;
X }
X
+ length = ntohs(readw(ti->arb+offsetof(struct arb_rec_req, frame_len)));
X if ((readb(llc + offsetof(struct trllc, dsap))==EXTENDED_SAP) &&
- (readb(llc + offsetof(struct trllc, ssap))==EXTENDED_SAP)) {
+ (readb(llc + offsetof(struct trllc, ssap))==EXTENDED_SAP) &&
+ (length>=hdr_len)) {
X IPv4_p = 1;
X }
X
@@ -1556,7 +1560,6 @@
X }
X #endif
X
- length = ntohs(readw(ti->arb+offsetof(struct arb_rec_req, frame_len)));
X skb_size = length-lan_hdr_len+sizeof(struct trh_hdr)+sizeof(struct trllc);
X
X if (!(skb=dev_alloc_skb(skb_size))) {
@@ -1576,7 +1579,6 @@
X
X if (IPv4_p) {
X /* Copy the headers without checksumming */
- hdr_len = lan_hdr_len + sizeof(struct trllc) + sizeof(struct iphdr);
X memcpy_fromio(data, rbufdata, hdr_len);
X
X /* Watch for padded packets and bogons */
diff -u --recursive --new-file v2.2.7/linux/drivers/net/ppp.c linux/drivers/net/ppp.c
--- v2.2.7/linux/drivers/net/ppp.c Wed Apr 28 11:37:30 1999
+++ linux/drivers/net/ppp.c Tue May 11 09:55:45 1999
@@ -4,7 +4,7 @@
X * Al Longyear <long...@netcom.com>
X * Extensively rewritten by Paul Mackerras <pau...@cs.anu.edu.au>
X *
- * ==FILEVERSION 990331==
+ * ==FILEVERSION 990510==
X *
X * NOTE TO MAINTAINERS:
X * If you modify this file at all, please set the number above to the
@@ -90,9 +90,6 @@
X #include <linux/kmod.h>
X #endif
X
-typedef ssize_t rw_ret_t;
-typedef size_t rw_count_t;
-
X /*
X * Local functions
X */
@@ -109,6 +106,7 @@
X static int ppp_async_encode(struct ppp *ppp);
X static int ppp_async_send(struct ppp *, struct sk_buff *);
X static int ppp_sync_send(struct ppp *, struct sk_buff *);
+static void ppp_tty_flush_output(struct ppp *);
X
X static int ppp_ioctl(struct ppp *, unsigned int, unsigned long);
X static int ppp_set_compression (struct ppp *ppp, struct ppp_option_data *odp);
@@ -191,10 +189,10 @@
X * TTY callbacks
X */
X
-static rw_ret_t ppp_tty_read(struct tty_struct *, struct file *, __u8 *,
- rw_count_t);
-static rw_ret_t ppp_tty_write(struct tty_struct *, struct file *, const __u8 *,
- rw_count_t);
+static ssize_t ppp_tty_read(struct tty_struct *, struct file *, __u8 *,
+ size_t);
+static ssize_t ppp_tty_write(struct tty_struct *, struct file *, const __u8 *,
+ size_t);
X static int ppp_tty_ioctl(struct tty_struct *, struct file *, unsigned int,
X unsigned long);
X static unsigned int ppp_tty_poll(struct tty_struct *tty, struct file *filp,
@@ -241,6 +239,7 @@
X 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
X 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
X };
+EXPORT_SYMBOL(ppp_crc16_table);
X
X #ifdef CHECK_CHARACTERS
X static __u32 paritytab[8] =
@@ -445,6 +444,7 @@
X ppp->tty = ppp->backup_tty;
X if (ppp_tty_push(ppp))
X ppp_output_wakeup(ppp);
+ wake_up_interruptible(&ppp->read_wait);
X } else {
X ppp->tty = 0;
X ppp->sc_xfer = 0;
@@ -462,13 +462,13 @@
X * Read a PPP frame from the rcv_q list,
X * waiting if necessary
X */
-static rw_ret_t
+static ssize_t
X ppp_tty_read(struct tty_struct *tty, struct file *file, __u8 * buf,
- rw_count_t nr)
+ size_t nr)
X {
X struct ppp *ppp = tty2ppp (tty);
X struct sk_buff *skb;
- rw_ret_t len, err;
+ ssize_t len, err;
X
X /*
X * Validate the pointers
@@ -550,9 +550,9 @@
X * Writing to a tty in ppp line discipline sends a PPP frame.
X * Used by pppd to send control packets (LCP, etc.).
X */
-static rw_ret_t
+static ssize_t
X ppp_tty_write(struct tty_struct *tty, struct file *file, const __u8 * data,
- rw_count_t count)
+ size_t count)
X {
X struct ppp *ppp = tty2ppp (tty);
X __u8 *new_data;
@@ -604,7 +604,7 @@
X */
X ppp_send_ctrl(ppp, skb);
X
- return (rw_ret_t) count;
+ return (ssize_t) count;
X }
X
X /*
@@ -723,6 +723,21 @@
X error = n_tty_ioctl (tty, file, param2, param3);
X break;
X
+ case TCFLSH:
+ /*
+ * Flush our buffers, then call the generic code to
+ * flush the serial port's buffer.
+ */
+ if (param3 == TCIFLUSH || param3 == TCIOFLUSH) {
+ struct sk_buff *skb;
+ while ((skb = skb_dequeue(&ppp->rcv_q)) != NULL)
+ kfree_skb(skb);
+ }
+ if (param3 == TCIOFLUSH || param3 == TCOFLUSH)
+ ppp_tty_flush_output(ppp);
+ error = n_tty_ioctl (tty, file, param2, param3);
+ break;
+
X case FIONREAD:
X /*
X * Returns how many bytes are available for a read().
@@ -881,7 +896,7 @@
X save_flags(flags);
X cli();
X if (ppp->tty_pushing) {
- /* record wakeup attempt so we don't loose */
+ /* record wakeup attempt so we don't lose */
X /* a wakeup call while doing push processing */
X ppp->woke_up=1;
X restore_flags(flags);
@@ -964,16 +979,20 @@
X int avail, sent, done = 0;
X struct tty_struct *tty = ppp2tty(ppp);
X
- if ( ppp->flags & SC_SYNC )
+ if (ppp->flags & SC_SYNC)
X return ppp_tty_sync_push(ppp);
X
X CHECK_PPP(0);
- if (ppp->tty_pushing)
+ if (ppp->tty_pushing) {
+ ppp->woke_up = 1;
X return 0;
+ }
X if (tty == NULL || tty->disc_data != (void *) ppp)
X goto flush;
X while (ppp->optr < ppp->olim || ppp->tpkt != 0) {
X ppp->tty_pushing = 1;
+ mb();
+ ppp->woke_up = 0;
X avail = ppp->olim - ppp->optr;
X if (avail > 0) {
X tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
@@ -983,18 +1002,24 @@
X ppp->stats.ppp_obytes += sent;
X ppp->optr += sent;
X if (sent < avail) {
+ wmb();
X ppp->tty_pushing = 0;
+ mb();
+ if (ppp->woke_up)
+ continue;
X return done;
X }
X }
X if (ppp->tpkt != 0)
X done = ppp_async_encode(ppp);
+ wmb();
X ppp->tty_pushing = 0;
X }
X return done;
X
X flush:
X ppp->tty_pushing = 1;
+ mb();
X ppp->stats.ppp_oerrors++;
X if (ppp->tpkt != 0) {
X kfree_skb(ppp->tpkt);
@@ -1002,6 +1027,7 @@
X done = 1;
X }
X ppp->optr = ppp->olim;
+ wmb();
X ppp->tty_pushing = 0;
X return done;
X }
@@ -1113,6 +1139,32 @@
X ppp->tpkt_pos = i;
X ppp->tfcs = fcs;
X return 0;
+}
+
+/*
+ * Flush output from our internal buffers.
+ * Called for the TCFLSH ioctl.
+ */
+static void
+ppp_tty_flush_output(struct ppp *ppp)
+{
+ struct sk_buff *skb;
+ int done = 0;
+
+ while ((skb = skb_dequeue(&ppp->xmt_q)) != NULL)
+ kfree_skb(skb);
+ ppp->tty_pushing = 1;
+ mb();
+ ppp->optr = ppp->olim;
+ if (ppp->tpkt != NULL) {
+ kfree_skb(ppp->tpkt);
+ ppp->tpkt = 0;
+ done = 1;
+ }
+ wmb();
+ ppp->tty_pushing = 0;
+ if (done)
+ ppp_output_wakeup(ppp);
X }
X
X /*
diff -u --recursive --new-file v2.2.7/linux/drivers/net/via-rhine.c linux/drivers/net/via-rhine.c
--- v2.2.7/linux/drivers/net/via-rhine.c Mon Dec 28 15:00:52 1998
+++ linux/drivers/net/via-rhine.c Mon May 10 13:00:10 1999
@@ -456,9 +456,9 @@
X pci_tbl[chip_idx].name, pciaddr, irq);
X
X if (pci_tbl[chip_idx].flags & PCI_USES_IO) {
- if (check_region(pciaddr, pci_tbl[chip_idx].io_size))
- continue;
X ioaddr = pciaddr & ~3;
+ if (check_region(ioaddr, pci_tbl[chip_idx].io_size))
+ continue;
X } else if ((ioaddr = (long)ioremap(pciaddr & ~0xf,
X pci_tbl[chip_idx].io_size)) == 0) {
X printk(KERN_INFO "Failed to map PCI address %#lx.\n",
@@ -1053,6 +1053,7 @@
X skb->protocol = eth_type_trans(skb, dev);
X netif_rx(skb);
X dev->last_rx = jiffies;
+ np->stats.rx_bytes += pkt_len;
X np->stats.rx_packets++;
X }
X entry = (++np->cur_rx) % RX_RING_SIZE;
diff -u --recursive --new-file v2.2.7/linux/drivers/net/wavelan.c linux/drivers/net/wavelan.c
--- v2.2.7/linux/drivers/net/wavelan.c Tue Mar 23 14:35:48 1999
+++ linux/drivers/net/wavelan.c Thu Apr 29 11:53:41 1999
@@ -324,6 +324,7 @@
X
X return crc_bytes;
X } /* psa_crc */
+#endif /* SET_PSA_CRC */
X
X /*------------------------------------------------------------------*/
X /*
@@ -334,6 +335,7 @@
X u_long ioaddr,
X u_short hacr)
X {
+#ifdef SET_PSA_CRC
X psa_t psa;
X u_short crc;
X
@@ -363,8 +365,8 @@
X if(crc != 0)
X printk(KERN_WARNING "%s: update_psa_checksum(): CRC does not agree with PSA data (even after recalculating)\n", dev->name);
X #endif /* DEBUG_IOCTL_INFO */
-} /* update_psa_checksum */
X #endif /* SET_PSA_CRC */
+} /* update_psa_checksum */
X
X /*------------------------------------------------------------------*/
X /*
@@ -748,23 +750,23 @@
X unsigned short ias_addr;
X
X /* Check mc_config command */
- if((status & AC_SFLD_OK) != 0)
- printk(KERN_INFO "wv_config_complete(): set_multicast_address failed; status = 0x%x\n",
- dev->name, str, status);
+ if((status & AC_SFLD_OK) != AC_SFLD_OK)
+ printk(KERN_INFO "%s: wv_config_complete(): set_multicast_address failed; status = 0x%x\n",
+ dev->name, status);
X
X /* check ia-config command */
X ias_addr = mcs_addr - sizeof(ac_ias_t);
X obram_read(ioaddr, acoff(ias_addr, ac_status), (unsigned char *)&status, sizeof(status));
- if((status & AC_SFLD_OK) != 0)
- printk(KERN_INFO "wv_config_complete(): set_MAC_address; status = 0x%x\n",
- dev->name, str, status);
+ if((status & AC_SFLD_OK) != AC_SFLD_OK)
+ printk(KERN_INFO "%s: wv_config_complete(): set_MAC_address failed; status = 0x%x\n",
+ dev->name, status);
X
X /* Check config command. */
X cfg_addr = ias_addr - sizeof(ac_cfg_t);
X obram_read(ioaddr, acoff(cfg_addr, ac_status), (unsigned char *)&status, sizeof(status));
- if((status & AC_SFLD_OK) != 0)
- printk(KERN_INFO "wv_config_complete(): configure; status = 0x%x\n",
- dev->name, str, status);
+ if((status & AC_SFLD_OK) != AC_SFLD_OK)
+ printk(KERN_INFO "%s: wv_config_complete(): configure failed; status = 0x%x\n",
+ dev->name, status);
X #endif /* DEBUG_CONFIG_ERROR */
X
X ret = 1; /* Ready to be scrapped */
@@ -800,15 +802,15 @@
X /* Read the first transmit buffer */
X obram_read(ioaddr, acoff(lp->tx_first_in_use, ac_status), (unsigned char *)&tx_status, sizeof(tx_status));
X
+ /* If not completed -> exit */
+ if((tx_status & AC_SFLD_C) == 0)
+ break;
+
X /* Hack for reconfiguration */
X if(tx_status == 0xFFFF)
X if(!wv_config_complete(dev, ioaddr, lp))
X break; /* Not completed */
X
- /* If not completed -> exit */
- if((tx_status & AC_SFLD_C) == 0)
- break;
-
X /* We now remove this buffer */
X nreaped++;
X --lp->tx_n_in_use;
@@ -841,7 +843,7 @@
X lp->stats.tx_packets++;
X ncollisions = tx_status & AC_SFLD_MAXCOL;
X lp->stats.collisions += ncollisions;
-#ifdef DEBUG_INTERRUPT_INFO
+#ifdef DEBUG_TX_INFO
X if(ncollisions > 0)
X printk(KERN_DEBUG "%s: wv_complete(): tx completed after %d collisions.\n",
X dev->name, ncollisions);
@@ -850,53 +852,49 @@
X else
X {
X lp->stats.tx_errors++;
-#ifndef IGNORE_NORMAL_XMIT_ERRS
X if(tx_status & AC_SFLD_S10)
X {
X lp->stats.tx_carrier_errors++;
-#ifdef DEBUG_INTERRUPT_ERROR
- printk(KERN_INFO "%s: wv_complete(): tx error: no CS.\n",
+#ifdef DEBUG_TX_FAIL
+ printk(KERN_DEBUG "%s: wv_complete(): tx error: no CS.\n",
X dev->name);
X #endif
X }
-#endif /* IGNORE_NORMAL_XMIT_ERRS */
X if(tx_status & AC_SFLD_S9)
X {
X lp->stats.tx_carrier_errors++;
-#ifdef DEBUG_INTERRUPT_ERROR
- printk(KERN_INFO "%s: wv_complete(): tx error: lost CTS.\n",
+#ifdef DEBUG_TX_FAIL
+ printk(KERN_DEBUG "%s: wv_complete(): tx error: lost CTS.\n",
X dev->name);
X #endif
X }
X if(tx_status & AC_SFLD_S8)
X {
X lp->stats.tx_fifo_errors++;
-#ifdef DEBUG_INTERRUPT_ERROR
- printk(KERN_INFO "%s: wv_complete(): tx error: slow DMA.\n",
+#ifdef DEBUG_TX_FAIL
+ printk(KERN_DEBUG "%s: wv_complete(): tx error: slow DMA.\n",
X dev->name);
X #endif
X }
-#ifndef IGNORE_NORMAL_XMIT_ERRS
X if(tx_status & AC_SFLD_S6)
X {


SHAR_EOF
true || echo 'restore of patch-2.2.8 failed'
fi

echo 'End of part 16'
echo 'File patch-2.2.8 is continued in part 17'
echo 17 > _shar_seq_.tmp

Thomas...@ciw.uni-karlsruhe.de

unread,
May 12, 1999, 3:00:00 AM5/12/99
to
Archive-name: v2.2/patch-2.2.8/part17

#!/bin/sh
# this is part 17 of a 33 - part archive


# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.8 continued
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 17; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.8'
else
echo 'x - continuing with patch-2.2.8'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.8' &&

X lp->stats.tx_heartbeat_errors++;
-#ifdef DEBUG_INTERRUPT_ERROR
- printk(KERN_INFO "%s: wv_complete(): tx error: heart beat.\n",
+#ifdef DEBUG_TX_FAIL
+ printk(KERN_DEBUG "%s: wv_complete(): tx error: heart beat.\n",


X dev->name);
X #endif
X }

X if(tx_status & AC_SFLD_S5)
X {
X lp->stats.tx_aborted_errors++;
-#ifdef DEBUG_INTERRUPT_ERROR
- printk(KERN_INFO "%s: wv_complete(): tx error: too many collisions.\n",
+#ifdef DEBUG_TX_FAIL
+ printk(KERN_DEBUG "%s: wv_complete(): tx error: too many collisions.\n",


X dev->name);
X #endif
X }
-#endif /* IGNORE_NORMAL_XMIT_ERRS */
X }

X
-#ifdef DEBUG_INTERRUPT_INFO
+#ifdef DEBUG_TX_INFO
X printk(KERN_DEBUG "%s: wv_complete(): tx completed, tx_status 0x%04x\n",
X dev->name, tx_status);
X #endif
@@ -1323,21 +1321,21 @@
X char * msg1, /* Name of the device */
X char * msg2) /* Name of the function */
X {
-#ifndef DEBUG_PACKET_DUMP
+ int i;
+ int maxi;
+
X printk(KERN_DEBUG "%s: %s(): dest %02X:%02X:%02X:%02X:%02X:%02X, length %d\n",
X msg1, msg2, p[0], p[1], p[2], p[3], p[4], p[5], length);
X printk(KERN_DEBUG "%s: %s(): src %02X:%02X:%02X:%02X:%02X:%02X, type 0x%02X%02X\n",
X msg1, msg2, p[6], p[7], p[8], p[9], p[10], p[11], p[12], p[13]);
X
-#else /* DEBUG_PACKET_DUMP */
- int i;
- int maxi;
+#ifdef DEBUG_PACKET_DUMP
X
- printk(KERN_DEBUG "%s: %s(): len=%d, data=\"", msg1, msg2, length);
+ printk(KERN_DEBUG "data=\"");
X
X if((maxi = length) > DEBUG_PACKET_DUMP)
X maxi = DEBUG_PACKET_DUMP;
- for(i = 0; i < maxi; i++)
+ for(i = 14; i < maxi; i++)
X if(p[i] >= ' ' && p[i] <= '~')
X printk(" %c", p[i]);
X else
@@ -1564,7 +1562,9 @@
X /*------------------------------------------------------------------*/
X /*
X * This function doesn't exist.
+ * (Note : it was a nice way to test the reconfigure stuff...)
X */
+#ifdef SET_MAC_ADDRESS
X static int
X wavelan_set_mac_address(device * dev,
X void * addr)
@@ -1579,6 +1579,7 @@
X
X return 0;
X }
+#endif /* SET_MAC_ADDRESS */
X
X #ifdef WIRELESS_EXT /* if wireless extensions exist in the kernel */
X
@@ -1932,10 +1933,8 @@
X /* Disable NWID in the mmc (no filtering). */
X mmc_out(ioaddr, mmwoff(0, mmw_loopt_sel), MMW_LOOPT_SEL_DIS_NWID);
X }
-#ifdef SET_PSA_CRC
X /* update the Wavelan checksum */
X update_psa_checksum(dev, ioaddr, lp->hacr);
-#endif
X break;
X
X case SIOCGIWNWID:
@@ -1992,10 +1991,8 @@
X psa.psa_thr_pre_set = wrq->u.sensitivity & 0x3F;
X psa_write(ioaddr, lp->hacr, (char *)&psa.psa_thr_pre_set - (char *)&psa,
X (unsigned char *) &psa.psa_thr_pre_set, 1);
-#ifdef SET_PSA_CRC
X /* update the Wavelan checksum */
X update_psa_checksum(dev, ioaddr, lp->hacr);
-#endif
X mmc_out(ioaddr, mmwoff(0, mmw_thr_pre_set), psa.psa_thr_pre_set);
X break;
X
@@ -2043,10 +2040,8 @@
X
X mmc_out(ioaddr, mmwoff(0, mmw_encr_enable), 0);
X }
-#ifdef SET_PSA_CRC
X /* update the Wavelan checksum */
X update_psa_checksum(dev, ioaddr, lp->hacr);
-#endif
X break;
X
X case SIOCGIWENCODE:
@@ -2260,10 +2255,8 @@
X psa.psa_quality_thr = *(wrq->u.name) & 0x0F;
X psa_write(ioaddr, lp->hacr, (char *)&psa.psa_quality_thr - (char *)&psa,
X (unsigned char *)&psa.psa_quality_thr, 1);
-#ifdef SET_PSA_CRC
X /* update the Wavelan checksum */
X update_psa_checksum(dev, ioaddr, lp->hacr);
-#endif
X mmc_out(ioaddr, mmwoff(0, mmw_quality_thr), psa.psa_quality_thr);
X break;
X
@@ -2426,7 +2419,7 @@
X
X #ifdef DEBUG_RX_TRACE
X printk(KERN_DEBUG "%s: ->wv_packet_read(0x%X, %d)\n",
- dev->name, fd_p, sksize);
+ dev->name, buf_off, sksize);
X #endif
X
X /* Allocate buffer for the data */
@@ -2514,6 +2507,8 @@
X {
X u_long ioaddr = dev->base_addr;
X net_local * lp = (net_local *)dev->priv;
+ fd_t fd;
+ rbd_t rbd;
X int nreaped = 0;
X
X #ifdef DEBUG_RX_TRACE
@@ -2523,12 +2518,17 @@
X /* Loop on each received packet. */
X for(;;)
X {
- fd_t fd;
- rbd_t rbd;
- ushort pkt_len;
-
X obram_read(ioaddr, lp->rx_head, (unsigned char *) &fd, sizeof(fd));
X
+ /* Note about the status :
+ * It start up to be 0 (the value we set). Then, when the RU
+ * grab the buffer to prepare for reception, it sets the
+ * FD_STATUS_B flag. When the RU has finished receiving the
+ * frame, it clears FD_STATUS_B, set FD_STATUS_C to indicate
+ * completion and set the other flags to indicate the eventual
+ * errors. FD_STATUS_OK indicates that the reception was OK.
+ */
+
X /* If the current frame is not complete, we have reached the end. */
X if((fd.fd_status & FD_STATUS_C) != FD_STATUS_C)
X break; /* This is how we exit the loop. */
@@ -2536,35 +2536,44 @@
X nreaped++;
X
X /* Check whether frame was correctly received. */
- if((fd.fd_status & (FD_STATUS_B | FD_STATUS_OK)) !=
- (FD_STATUS_B | FD_STATUS_OK))
+ if((fd.fd_status & FD_STATUS_OK) == FD_STATUS_OK)
X {
- /*
- * Not sure about this one -- it does not seem
- * to be an error so we will keep quiet about it.
- */
-#ifndef IGNORE_NORMAL_XMIT_ERRS
-#ifdef DEBUG_RX_ERROR
- if((fd.fd_status & FD_STATUS_B) != FD_STATUS_B)
- printk(KERN_INFO "%s: wv_receive(): frame not consumed by RU.\n",
- dev->name);
-#endif
-#endif /* IGNORE_NORMAL_XMIT_ERRS */
+ /* Does the frame contain a pointer to the data? Let's check. */
+ if(fd.fd_rbd_offset != I82586NULL)
+ {
+ /* Read the receive buffer descriptor */
+ obram_read(ioaddr, fd.fd_rbd_offset,
+ (unsigned char *) &rbd, sizeof(rbd));
X
X #ifdef DEBUG_RX_ERROR
- if((fd.fd_status & FD_STATUS_OK) != FD_STATUS_OK)
- printk(KERN_INFO "%s: wv_receive(): frame not received successfully.\n",
+ if((rbd.rbd_status & RBD_STATUS_EOF) != RBD_STATUS_EOF)
+ printk(KERN_INFO "%s: wv_receive(): missing EOF flag.\n",
+ dev->name);
+
+ if((rbd.rbd_status & RBD_STATUS_F) != RBD_STATUS_F)
+ printk(KERN_INFO "%s: wv_receive(): missing F flag.\n",
+ dev->name);
+#endif /* DEBUG_RX_ERROR */
+
+ /* Read the packet and transmit to Linux */
+ wv_packet_read(dev, rbd.rbd_bufl,
+ rbd.rbd_status & RBD_STATUS_ACNT);
+ }
+#ifdef DEBUG_RX_ERROR
+ else /* if frame has no data */
+ printk(KERN_INFO "%s: wv_receive(): frame has no data.\n",


X dev->name);
X #endif
X }
-

- /* Were there problems in processing the frame? Let's check. */
- if((fd.fd_status & (FD_STATUS_S6 | FD_STATUS_S7 | FD_STATUS_S8 |
- FD_STATUS_S9 | FD_STATUS_S10 | FD_STATUS_S11))
- != 0)
+ else /* If reception was no successful */
X {
X lp->stats.rx_errors++;
X
+#ifdef DEBUG_RX_INFO
+ printk(KERN_DEBUG "%s: wv_receive(): frame not received successfully (%X).\n",
+ dev->name, fd.fd_status);
+#endif
+
X #ifdef DEBUG_RX_ERROR
X if((fd.fd_status & FD_STATUS_S6) != 0)
X printk(KERN_INFO "%s: wv_receive(): no EOF flag.\n", dev->name);
@@ -2573,8 +2582,8 @@
X if((fd.fd_status & FD_STATUS_S7) != 0)
X {
X lp->stats.rx_length_errors++;
-#ifdef DEBUG_RX_ERROR
- printk(KERN_INFO "%s: wv_receive(): frame too short.\n",
+#ifdef DEBUG_RX_FAIL
+ printk(KERN_DEBUG "%s: wv_receive(): frame too short.\n",


X dev->name);
X #endif
X }

@@ -2582,8 +2591,8 @@
X if((fd.fd_status & FD_STATUS_S8) != 0)
X {
X lp->stats.rx_over_errors++;
-#ifdef DEBUG_RX_ERROR
- printk(KERN_INFO "%s: wv_receive(): rx DMA overrun.\n",
+#ifdef DEBUG_RX_FAIL
+ printk(KERN_DEBUG "%s: wv_receive(): rx DMA overrun.\n",


X dev->name);
X #endif
X }

@@ -2591,8 +2600,8 @@
X if((fd.fd_status & FD_STATUS_S9) != 0)
X {
X lp->stats.rx_fifo_errors++;
-#ifdef DEBUG_RX_ERROR
- printk(KERN_INFO "%s: wv_receive(): ran out of resources.\n",
+#ifdef DEBUG_RX_FAIL
+ printk(KERN_DEBUG "%s: wv_receive(): ran out of resources.\n",


X dev->name);
X #endif
X }

@@ -2600,8 +2609,8 @@
X if((fd.fd_status & FD_STATUS_S10) != 0)
X {
X lp->stats.rx_frame_errors++;
-#ifdef DEBUG_RX_ERROR
- printk(KERN_INFO "%s: wv_receive(): alignment error.\n",
+#ifdef DEBUG_RX_FAIL
+ printk(KERN_DEBUG "%s: wv_receive(): alignment error.\n",


X dev->name);
X #endif
X }

@@ -2609,38 +2618,12 @@
X if((fd.fd_status & FD_STATUS_S11) != 0)
X {
X lp->stats.rx_crc_errors++;
-#ifdef DEBUG_RX_ERROR
- printk(KERN_INFO "%s: wv_receive(): CRC error.\n", dev->name);
+#ifdef DEBUG_RX_FAIL
+ printk(KERN_DEBUG "%s: wv_receive(): CRC error.\n", dev->name);
X #endif
X }
X }
X
- /* Does the frame contain a pointer to the data? Let's check. */
- if(fd.fd_rbd_offset == I82586NULL)
-#ifdef DEBUG_RX_ERROR
- printk(KERN_INFO "%s: wv_receive(): frame has no data.\n", dev->name);
-#endif
- else
- {
- obram_read(ioaddr, fd.fd_rbd_offset,
- (unsigned char *) &rbd, sizeof(rbd));
-
-#ifdef DEBUG_RX_ERROR
- if((rbd.rbd_status & RBD_STATUS_EOF) != RBD_STATUS_EOF)
- printk(KERN_INFO "%s: wv_receive(): missing EOF flag.\n",
- dev->name);
-
- if((rbd.rbd_status & RBD_STATUS_F) != RBD_STATUS_F)
- printk(KERN_INFO "%s: wv_receive(): missing F flag.\n",
- dev->name);
-#endif
-
- pkt_len = rbd.rbd_status & RBD_STATUS_ACNT;
-
- /* Read the packet and transmit to Linux */
- wv_packet_read(dev, rbd.rbd_bufl, pkt_len);
- } /* if frame has data */
-
X fd.fd_status = 0;
X obram_write(ioaddr, fdoff(lp->rx_head, fd_status),
X (unsigned char *) &fd.fd_status, sizeof(fd.fd_status));
@@ -2775,7 +2758,7 @@
X /*
X * Data
X */
- obram_write(ioaddr, buf_addr, buf, clen);
+ obram_write(ioaddr, buf_addr, buf, length);
X
X /*
X * Overwrite the predecessor NOP link
@@ -2950,11 +2933,9 @@
X (unsigned char *)&psa.psa_quality_thr, 1);
X psa_write(ioaddr, lp->hacr, (char *)&psa.psa_conf_status - (char *)&psa,
X (unsigned char *)&psa.psa_conf_status, 1);
-#ifdef SET_PSA_CRC
X /* update the Wavelan checksum */
X update_psa_checksum(dev, ioaddr, lp->hacr);
X #endif
-#endif
X }
X
X /* Zero the mmc structure. */
@@ -3125,7 +3106,7 @@
X
X if(i <= 0)
X {
-#ifdef DEBUG_CONFIG_ERRORS
+#ifdef DEBUG_CONFIG_ERROR
X printk(KERN_INFO "%s: wavelan_ru_start(): board not accepting command.\n",


X dev->name);
X #endif

@@ -3229,7 +3210,7 @@
X
X if(i <= 0)
X {
-#ifdef DEBUG_CONFIG_ERRORS
+#ifdef DEBUG_CONFIG_ERROR
X printk(KERN_INFO "%s: wavelan_cu_start(): board not accepting command.\n",


X dev->name);
X #endif

@@ -3316,7 +3297,7 @@
X
X if(i <= 0)
X {
-#ifdef DEBUG_CONFIG_ERRORS
+#ifdef DEBUG_CONFIG_ERROR
X printk(KERN_INFO "%s: wv_82586_start(): iscp_busy timeout.\n",


X dev->name);
X #endif

@@ -3336,7 +3317,7 @@
X
X if (i <= 0)
X {
-#ifdef DEBUG_CONFIG_ERRORS
+#ifdef DEBUG_CONFIG_ERROR
X printk(KERN_INFO "%s: wv_82586_start(): status: expected 0x%02x, got 0x%02x.\n",
X dev->name, SCB_ST_CX | SCB_ST_CNA, scb.scb_status);
X #endif
@@ -3357,7 +3338,7 @@
X obram_read(ioaddr, OFFSET_CU, (unsigned char *)&cb, sizeof(cb));
X if(cb.ac_status & AC_SFLD_FAIL)
X {
-#ifdef DEBUG_CONFIG_ERRORS
+#ifdef DEBUG_CONFIG_ERROR
X printk(KERN_INFO "%s: wv_82586_start(): i82586 Self Test failed.\n",


X dev->name);
X #endif

@@ -3638,13 +3619,16 @@
X wv_ints_on(dev);
X
X /* Start card functions */
- if((wv_ru_start(dev) < 0) ||
- (wv_cu_start(dev) < 0))
+ if(wv_cu_start(dev) < 0)
X return -1;
X
- /* Finish configuration. */
+ /* Setup the controller and parameters */
X wv_82586_config(dev);
X
+ /* Finish configuration with the receive unit */
+ if(wv_ru_start(dev) < 0)
+ return -1;
+
X #ifdef DEBUG_CONFIG_TRACE
X printk(KERN_DEBUG "%s: <-wv_hw_reset()\n", dev->name);
X #endif
@@ -3945,7 +3929,7 @@
X /* Check irq */
X if(dev->irq == 0)
X {
-#ifdef DEBUG_CONFIG_ERRORS
+#ifdef DEBUG_CONFIG_ERROR
X printk(KERN_WARNING "%s: wavelan_open(): no IRQ\n", dev->name);
X #endif
X return -ENXIO;
@@ -3953,7 +3937,7 @@
X
X if(request_irq(dev->irq, &wavelan_interrupt, 0, "WaveLAN", dev) != 0)
X {
-#ifdef DEBUG_CONFIG_ERRORS
+#ifdef DEBUG_CONFIG_ERROR
X printk(KERN_WARNING "%s: wavelan_open(): invalid IRQ\n", dev->name);
X #endif
X return -EAGAIN;
@@ -3968,7 +3952,7 @@
X else
X {
X free_irq(dev->irq, dev);
-#ifdef DEBUG_CONFIG_ERRORS
+#ifdef DEBUG_CONFIG_ERROR
X printk(KERN_INFO "%s: wavelan_open(): impossible to start the card\n",


X dev->name);
X #endif

@@ -4065,10 +4049,8 @@
X #endif
X psa_write(ioaddr, HACR_DEFAULT,
X psaoff(0, psa_int_req_no), &irq_mask, 1);
-#ifdef SET_PSA_CRC
X /* update the Wavelan checksum */
X update_psa_checksum(dev, ioaddr, HACR_DEFAULT);
-#endif
X wv_hacr_reset(ioaddr);
X }
X }
@@ -4122,7 +4104,9 @@
X dev->hard_start_xmit = wavelan_packet_xmit;
X dev->get_stats = wavelan_get_stats;
X dev->set_multicast_list = &wavelan_set_multicast_list;
+#ifdef SET_MAC_ADDRESS
X dev->set_mac_address = &wavelan_set_mac_address;
+#endif /* SET_MAC_ADDRESS */
X
X #ifdef WIRELESS_EXT /* if wireless extension exists in the kernel */
X dev->do_ioctl = wavelan_ioctl;
@@ -4176,7 +4160,7 @@
X /* Don't probe at all. */
X if(base_addr < 0)
X {
-#ifdef DEBUG_CONFIG_ERRORS
+#ifdef DEBUG_CONFIG_ERROR
X printk(KERN_WARNING "%s: wavelan_probe(): invalid base address\n",


X dev->name);
X #endif

@@ -4259,7 +4243,7 @@
X /* If probing is asked */
X if(io[0] == 0)
X {
-#ifdef DEBUG_CONFIG_ERRORS
+#ifdef DEBUG_CONFIG_ERROR
X printk(KERN_WARNING "WaveLAN init_module(): doing device probing (bad !)\n");
X printk(KERN_WARNING "Specify base addresses while loading module to correct the problem\n");
X #endif
@@ -4303,7 +4287,7 @@
X } /* if there is something at the address */
X } /* Loop on all addresses. */
X
-#ifdef DEBUG_CONFIG_ERRORS
+#ifdef DEBUG_CONFIG_ERROR
X if(wavelan_list == (net_local *) NULL)
X printk(KERN_WARNING "WaveLAN init_module(): no device found\n");
X #endif
diff -u --recursive --new-file v2.2.7/linux/drivers/net/wavelan.p.h linux/drivers/net/wavelan.p.h
--- v2.2.7/linux/drivers/net/wavelan.p.h Tue Mar 23 14:35:48 1999
+++ linux/drivers/net/wavelan.p.h Thu Apr 29 11:53:41 1999
@@ -34,16 +34,22 @@
X * I try to maintain a web page with the Wireless LAN Howto at :
X * http://www-uk.hpl.hp.com/people/jt/Linux/Wavelan.html
X *
+ * Debugging and options
+ * ---------------------
+ * You will find below a set of '#define" allowing a very fine control
+ * on the driver behaviour and the debug messages printed.
+ * The main options are :
+ * o SET_PSA_CRC, to have your card correctly recognised by
+ * an access point and the Point-to-Point diagnostic tool.
+ * o USE_PSA_CONFIG, to read configuration from the PSA (EEprom)
+ * (otherwise we always start afresh with some defaults)
+ *
X * wavelan.o is too darned big
X * ---------------------------
X * That's true! There is a very simple way to reduce the driver
X * object by 33%! Comment out the following line:
X * #include <linux/wireless.h>
- *
- * Debugging and options
- * ---------------------
- * You will find below a set of '#define" allowing a very fine control
- * on the driver behaviour and the debug messages printed.
+ * Other compile options can also reduce the size of it...
X *
X * MAC address and hardware detection:
X * -----------------------------------
@@ -274,7 +280,17 @@
X * - Correct i82586 configuration parameters
X * - Encryption initialisation bug (Robert McCormack)
X * - New mac addresses detected in the probe
- * - Increase watchdog for busy envirnoments
+ * - Increase watchdog for busy environments
+ *
+ * Changes made for release in 2.0.38 & 2.2.7 :
+ * ------------------------------------------
+ * - Correct the reception logic to better report errors and avoid
+ * sending bogus packet up the stack
+ * - Delay RU config to avoid corrupting first received packet
+ * - Change config completion code (to actually check something)
+ * - Avoid reading out of bound in skbuf to transmit
+ * - Rectify a lot of (useless) debugging code
+ * - Change the way to `#ifdef SET_PSA_CRC'
X *
X * Wishes & dreams:
X * ----------------
@@ -315,6 +331,24 @@
X #include "i82586.h"
X #include "wavelan.h"
X
+/************************** DRIVER OPTIONS **************************/
+/*
+ * `#define' or `#undef' the following constant to change the behaviour
+ * of the driver...
+ */
+#undef SET_PSA_CRC /* Calculate and set the CRC on PSA (slower) */
+#define USE_PSA_CONFIG /* Use info from the PSA. */
+#undef STRUCT_CHECK /* Verify padding of structures. */
+#undef EEPROM_IS_PROTECTED /* doesn't seem to be necessary */
+#define MULTICAST_AVOID /* Avoid extra multicast (I'm sceptical). */
+#undef SET_MAC_ADDRESS /* Experimental */
+
+#ifdef WIRELESS_EXT /* If wireless extensions exist in the kernel */
+/* Warning: this stuff will slow down the driver. */
+#define WIRELESS_SPY /* Enable spying addresses. */
+#undef HISTOGRAM /* Enable histogram of signal level. */
+#endif
+
X /****************************** DEBUG ******************************/
X
X #undef DEBUG_MODULE_TRACE /* module insertion/removal */
@@ -324,14 +358,16 @@
X #define DEBUG_INTERRUPT_ERROR /* problems */
X #undef DEBUG_CONFIG_TRACE /* Trace the config functions. */
X #undef DEBUG_CONFIG_INFO /* what's going on */
-#define DEBUG_CONFIG_ERRORS /* errors on configuration */
+#define DEBUG_CONFIG_ERROR /* errors on configuration */
X #undef DEBUG_TX_TRACE /* transmission calls */
X #undef DEBUG_TX_INFO /* header of the transmitted packet */
-#define DEBUG_TX_ERROR /* unexpected conditions */
+#undef DEBUG_TX_FAIL /* Normal failure conditions */
+#define DEBUG_TX_ERROR /* Unexpected conditions */
X #undef DEBUG_RX_TRACE /* transmission calls */
-#undef DEBUG_RX_INFO /* header of the transmitted packet */
-#define DEBUG_RX_ERROR /* unexpected conditions */
-#undef DEBUG_PACKET_DUMP 16 /* Dump packet on the screen. */
+#undef DEBUG_RX_INFO /* header of the received packet */
+#undef DEBUG_RX_FAIL /* Normal failure conditions */
+#define DEBUG_RX_ERROR /* Unexpected conditions */
+#undef DEBUG_PACKET_DUMP 32 /* Dump packet on the screen. */
X #undef DEBUG_IOCTL_TRACE /* misc. call by Linux */
X #undef DEBUG_IOCTL_INFO /* various debugging info */
X #define DEBUG_IOCTL_ERROR /* what's going wrong */
@@ -343,26 +379,10 @@
X #undef DEBUG_I82586_SHOW /* Show i82586 status. */
X #undef DEBUG_DEVICE_SHOW /* Show device parameters. */
X
-/* Options */
-#define USE_PSA_CONFIG /* Use info from the PSA. */
-#define SET_PSA_CRC /* Calculate and set the CRC on PSA */
-#define IGNORE_NORMAL_XMIT_ERRS /* Don't bother with normal conditions. */
-#undef STRUCT_CHECK /* Verify padding of structures. */
-#undef OLDIES /* old code (to redo) */
-#undef RECORD_SNR /* to redo */
-#undef EEPROM_IS_PROTECTED /* doesn't seem to be necessary */
-#define MULTICAST_AVOID /* Avoid extra multicast (I'm sceptical). */
-
-#ifdef WIRELESS_EXT /* If wireless extensions exist in the kernel */
-/* Warning: this stuff will slow down the driver. */
-#define WIRELESS_SPY /* Enable spying addresses. */
-#undef HISTOGRAM /* Enable histogram of signal level. */
-#endif
-
X /************************ CONSTANTS & MACROS ************************/
X
X #ifdef DEBUG_VERSION_SHOW
-static const char *version = "wavelan.c : v18 (wireless extensions) 18/2/99\n";
+static const char *version = "wavelan.c : v19 (wireless extensions) 20/4/99\n";
X #endif
X
X /* Watchdog temporisation */
diff -u --recursive --new-file v2.2.7/linux/drivers/sbus/char/pcikbd.c linux/drivers/sbus/char/pcikbd.c
--- v2.2.7/linux/drivers/sbus/char/pcikbd.c Wed Apr 28 11:37:30 1999
+++ linux/drivers/sbus/char/pcikbd.c Tue May 11 08:24:32 1999
@@ -1,4 +1,4 @@
-/* $Id: pcikbd.c,v 1.26 1999/04/28 11:55:42 davem Exp $
+/* $Id: pcikbd.c,v 1.27 1999/05/09 06:40:47 ecd Exp $
X * pcikbd.c: Ultra/AX PC keyboard support.
X *


X * Copyright (C) 1997 Eddie C. Dost (e...@skynet.be)

@@ -276,6 +276,7 @@
X prev_scancode = 0;
X return 0;
X }
+ scancode &= 0x7f;
X if(prev_scancode) {
X if(prev_scancode != 0xe0) {
X if(prev_scancode == 0xe1 && scancode == 0x1d) {
diff -u --recursive --new-file v2.2.7/linux/drivers/scsi/Config.in linux/drivers/scsi/Config.in
--- v2.2.7/linux/drivers/scsi/Config.in Fri Apr 16 14:47:30 1999
+++ linux/drivers/scsi/Config.in Thu Apr 29 11:53:41 1999
@@ -55,9 +55,7 @@
X dep_tristate 'EATA-PIO (old DPT PM2001, PM2012A) support' CONFIG_SCSI_EATA_PIO $CONFIG_SCSI
X dep_tristate 'Future Domain 16xx SCSI/AHA-2920A support' CONFIG_SCSI_FUTURE_DOMAIN $CONFIG_SCSI
X if [ "$CONFIG_MCA" = "y" ]; then
- if [ "$CONFIG_SCSI" = "y" ]; then
- bool 'Future Domain MCS-600/700 SCSI support' CONFIG_SCSI_FD_MCS
- fi
+ dep_tristate 'Future Domain MCS-600/700 SCSI support' CONFIG_SCSI_FD_MCS $CONFIG_SCSI
X fi
X dep_tristate 'GDT SCSI Disk Array Controller support' CONFIG_SCSI_GDTH $CONFIG_SCSI
X dep_tristate 'Generic NCR5380/53c400 SCSI support' CONFIG_SCSI_GENERIC_NCR5380 $CONFIG_SCSI
diff -u --recursive --new-file v2.2.7/linux/drivers/scsi/Makefile linux/drivers/scsi/Makefile
--- v2.2.7/linux/drivers/scsi/Makefile Fri Apr 16 14:47:30 1999
+++ linux/drivers/scsi/Makefile Thu Apr 29 11:53:41 1999
@@ -533,8 +533,11 @@
X
X ifeq ($(CONFIG_SCSI_FD_MCS),y)
X L_OBJS += fd_mcs.o
+else
+ ifeq ($(CONFIG_SCSI_FD_MCS),m)
+ M_OBJS += fd_mcs.o
+ endif
X endif
-
X
X ifeq ($(CONFIG_SCSI_T128),y)
X L_OBJS += t128.o
diff -u --recursive --new-file v2.2.7/linux/drivers/scsi/README.ibmmca linux/drivers/scsi/README.ibmmca
--- v2.2.7/linux/drivers/scsi/README.ibmmca Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/README.ibmmca Mon May 10 13:00:10 1999
@@ -0,0 +1,979 @@
+
+
+ -=< The IBM Microchannel SCSI-Subsystem >=-
+
+ for the IBM PS/2 series
+
+ Low Level Software-Driver for Linux
+
+ Copyright (c) 1995 Strom Systems, Inc. under the terms of the GNU
+ General Public License. Originally written by Martin Kolinek, December 1995.
+ Officially maintained by Michael Lang since January 1999.
+
+ Version 3.1e
+
+
+ Last update: 20 February 1999
+
+
+ Authors of this Driver
+ ----------------------
+ - Chris Beauregard (improvement of the SCSI-device mapping by the driver)
+ - Martin Kolinek (origin, first release of this driver)
+ - Klaus Kudielka (multiple SCSI-host management/detection, adaption to
+ Linux Kernel 2.1.x, module support)
+ - Michael Lang (assigning original pun,lun mapping, dynamical ldn
+ assignment, this file, patch, official driver maintenance)
+
+ Table of Contents
+ -----------------
+ 1 Abstract
+ 2 Driver Description
+ 2.1 IBM SCSI-Subsystem Detection
+ 2.2 Physical Units, Logical Units, and Logical Devices
+ 2.3 SCSI-Device Recognition and dynamical ldn Assignment
+ 2.4 SCSI-Device Order
+ 2.5 Regular SCSI-Command-Processing
+ 2.6 Abort & Reset Commands
+ 2.7 Disk Geometry
+ 2.8 Kernel Boot Option
+ 2.9 Driver Module Support
+ 2.10 Multiple Hostadapter Support
+ 2.11 /proc/scsi-Filesystem Information
+ 2.12 /proc/mca-Filesystem Information
+ 2.13 Supported IBM SCSI-Subsystems
+ 2.14 Linux Kernel Versions
+ 3 Code History
+ 4 To do
+ 5 Users' Manual
+ 5.1 Commandline Parameters
+ 5.2 Troubleshooting
+ 5.3 Bugreports
+ 5.4 Support WWW-page
+ 6 References
+ 7 Trademarks
+
+ * * *
+
+ 1 Abstract
+ ----------
+ This README-file describes the IBM SCSI-subsystem low level driver for
+ Linux. The descriptions which were formerly kept in the source-code have
+ been taken out to this file to easify the codes' readability. The driver
+ description has been updated, as most of the former description was already
+ quite outdated. The history of the driver development is also kept inside
+ here. Multiple historical developments have been summarized to shorten the
+ textsize a bit. At the end of this file you can find a small manual for
+ this driver and hints to get it running even on your machine (hopefully).
+
+ 2 Driver Description
+ --------------------
+ 2.1 IBM SCSI-Subsystem Detection
+ --------------------------------
+ This is done in the ibmmca_detect() function. It first checks, if the
+ Microchannel-bus support is enabled, as the IBM SCSI-subsystem needs the
+ Microchannel. In a next step, a free interrupt is chosen and the main
+ interrupt handler is connected to it to handle answers of the SCSI-
+ subsystem(s). In a further step, it is checked, wether there was a forced
+ detection of the adapter via the kernel commandline, where the I/O port
+ and the SCSI-subsystem id can be specified. The next step checks if there
+ is an integrated SCSI-subsystem installed. This register area is fixed
+ through all IBM PS/2 MCA-machines and appears as something like a virtual
+ slot 10 of the MCA-bus. If POS-register 2 is not 0xff, there must be a SCSI-
+ subsystem present and it will be registered as IBM Integrated SCSI-
+ Subsystem. The next step checks, if there is a slot-adapter installed on
+ the MCA-bus. To get this, the first two POS-registers, that represent the
+ adapter ID are checked. If they fit to one of the ids, stored in the
+ adapter list, a SCSI-subsystem is assumed to be found and will be
+ registered. This check is done through all possible MCA-bus slots to allow
+ more than one SCSI-adapter to be present in the PS/2-system and this is
+ already the first point of problems. Looking into the technical reference
+ manual for the IBM PS/2 common interfaces, the POS2 register must have
+ different interpretation of its single bits. While one can assume, that the
+ integrated subsystem has a fix I/O-address at 0x3540 - 0x3547, further
+ installed IBM SCSI-adapters must use a different I/O-address. This is
+ expressed by bit 1 to 3 of POS2 (multiplied by 8 + 0x3540). Bits 2 and 3
+ are reserved for the integrated subsystem, but not for the adapters! The
+ following list shows, how the bits of POS2 and POS3 should be interpreted.
+
+ The POS2-register of all PS/2 models' integrated SCSI-subsystems has the
+ following interpretation of bits:
+ Bit 7 - 4 : Chip Revision ID (Release)
+ Bit 3 - 2 : Reserved
+ Bit 1 : 8k NVRAM Disabled
+ Bit 0 : Chip Enable (EN-Signal)
+ The POS3-register is interpreted as follows (for ALL IBM SCSI-subsys.):
+ Bit 7 - 5 : SCSI ID
+ Bit 4 - 0 : Reserved = 0
+ (taken from "IBM, PS/2 Hardware Interface Technical Reference, Common
+ Interfaces (1991)").
+ In short words, this means, that IBM PS/2 machines only support 1 single
+ subsystem by default. But (additional) slot-adapters must have another
+ configuration on pos2 in order to be enabled to use more than one IBM SCSI-
+ subsystem, e.g. for a network server. From tests with the IBM SCSI Adapter
+ w/cache, the POS2-register for slot adapters should be interpreted in the
+ following way:
+ Bit 7 - 4 : Chip Revision ID (Release)
+ Bit 3 - 1 : port offset factor ( * 8 + 0x3540 )
+ Bit 0 : Chip Enable (EN-Signal)
+
+ One day I found a patch in ibmmca_detect(), forcing the I/O-address to be
+ 0x3540 for integrated SCSI-subsystems, there was a remark placed, that on
+ integrated IBM SCSI-subsystems of model 56, the POS2 register was showing 5.
+ This means, that really for these models, POS2 has to be interpreted
+ sticking to the technical reference guide. In this case, the bit 2 (4) is
+ a reserved bit and may not be interpreted. These differences between the
+ adapters and the integrated controllers are taken into account by the
+ detection routine of the driver on from version >3.0g.
+
+ Every time, a SCSI-subsystem is discovered, the ibmmca_register() function
+ is called. This function checks first, if the requested area for the I/O-
+ address of this SCSI-subsystem is still available and assigns this I/O-
+ area to the SCSI-subsystem. There are always 8 sequential I/O-addresses
+ taken for each individual SCSI-subsystem found, which are:
+
+ Offset Type Permissions
+ 0 Command Interface Register 1 Read/Write
+ 1 Command Interface Register 2 Read/Write
+ 2 Command Interface Register 3 Read/Write
+ 3 Command Interface Register 4 Read/Write
+ 4 Attention Register Read/Write
+ 5 Basic Control Register Read/Write
+ 6 Interrupt Status Register Read
+ 7 Basic Status Register Read
+
+ After the I/O-address range is assigned, the host-adapter is assigned
+ to a local structure which keeps all adapter information needed for the
+ driver itself and the mid- and higher-level SCSI-drivers. The SCSI pun/lun
+ and the adapters' ldn tables are initialized and get probed afterwards by
+ the check_devices() function. If no further adapters are found,
+ ibmmca_detect() quits.
+
+ 2.2 Physical Units, Logical Units, and Logical Devices
+ ------------------------------------------------------
+ There can be up to 56 devices on the SCSI bus (besides the adapter):
+ there are up to 7 "physical units" (each identified by physical unit
+ number or pun, also called the scsi id, this is the number you select
+ with hardware jumpers), and each physical unit can have up to 8
+ "logical units" (each identified by logical unit number, or lun,
+ between 0 and 7).
+
+ Typically the adapter has pun=7, so puns of other physical units
+ are between 0 and 6. Almost all physical units have only one
+ logical unit, with lun=0. A CD-ROM jukebox would be an example of
+ a physical unit with more than one logical unit.
+
+ The embedded microprocessor of the IBM SCSI-subsystem hides the complex
+ two-dimensional (pun,lun) organization from the operating system.
+ When the machine is powered-up (or rebooted), the embedded microprocessor
+ checks, on its own, all 56 possible (pun,lun) combinations, and the first
+ 15 devices found are assigned into a one-dimensional array of so-called
+ "logical devices", identified by "logical device numbers" or ldn. The last
+ ldn=15 is reserved for the subsystem itself.
+
+ 2.3 SCSI-Device Recognition and dynamical ldn Assignment
+ --------------------------------------------------------
+ One consequence of information hiding is that the real (pun,lun)
+ numbers are also hidden. The two possibilities to get around this problem
+ is to offer fake pun/lun combinations to the operating system or to
+ delete the whole mapping of the adapter and to reassign the ldns, using
+ the immediate assign command of the SCSI-subsystem. At the beginning of the
+ development of this driver, the following approach was used:
+ First, the driver checked the ldn's (0 to 6) to find out which ldn's
+ have devices assigned. This was done by the functions check_devices() and
+ device_exists(). The interrupt handler has a special paragraph of code
+ (see local_checking_phase_flag) to assist in the checking. Assume, for
+ example, that three logical devices were found assigned at ldn 0, 1, 2.
+ These are presented to the upper layer of Linux SCSI driver
+ as devices with bogus (pun, lun) equal to (0,0), (1,0), (2,0).
+ On the other hand, if the upper layer issues a command to device
+ say (4,0), this driver returns DID_NO_CONNECT error.
+
+ In a second step of the driver development, the following improvement has
+ been applied: The first approach limited the number of devices to 7, far
+ fewer than the 15 that it could usem then it just maped ldn ->
+ (ldn/8,ldn%8) for pun,lun. We ended up with a real mishmash of puns
+ and luns, but it all seemed to work.
+
+ The latest development, which is implemented from the driver version 3.0
+ and later, realizes the device recognition in the following way:
+ The physical SCSI-devices on the SCSI-bus are probed via immediate_assign-
+ and device_inquiry-commands, that is all implemented in a completely new
+ made check_devices() subroutine. This delivers a exact map of the physical
+ SCSI-world that is now stored in the get_scsi[][]-array. This means,
+ that the once hidden pun,lun assignment is now known to this driver.
+ It no longer believes in default-settings of the subsystem and maps all
+ ldns to existing pun,lun "by foot". This assures full control of the ldn
+ mapping and allows dynamical remapping of ldns to different pun,lun, if
+ there are more SCSI-devices installed than ldns available (n>15). The
+ ldns from 0 to 6 get 'hardwired' by this driver to puns 0 to 7 at lun=0,
+ excluding the pun of the subsystem. This assures, that at least simple
+ SCSI-installations have optimum access-speed and are not touched by
+ dynamical remapping. The ldns 7 to 14 are put to existing devices with
+ lun>0 or to non-existing devices, in order to satisfy the subsystem, if
+ there are less than 15 SCSI-devices connected. In the case of more than 15
+ devices, the dynamical mapping goes active. If the get_scsi[][] reports a
+ device to be existant, but it has no ldn assigned, it gets a ldn out of 7
+ to 14. The numbers are assigned in cyclic order. Therefore it takes 8
+ dynamical reassignments on the SCSI-devices, until a certain device
+ looses its ldn again. This assures, that dynamical remapping is avoided
+ during intense I/O between up to 15 SCSI-devices (means pun,lun
+ combinations). A further advantage of this method is, that people who
+ build their kernel without probing on all luns will get what they expect,
+ because the driver just won't assign everything with lun>0 when
+ multpile lun probing is inactive.
+
+ 2.4 SCSI-Device Order
+ ---------------------
+ Because of the now correct recognition of physical pun,lun, and
+ their report to mid-level- and higher-level-drivers, the new reported puns
+ can be different from the old, faked puns. Therefore, Linux will eventually
+ change /dev/sdXXX assignments and prompt you for corrupted superblock
+ repair on boottime. In this case DO NOT PANIC, YOUR DISKS ARE STILL OK!!!
+ You have to reboot (CTRL-D) with a old kernel and set the /etc/fstab-file
+ entries right. After that, the system should come up as errorfree as before.
+ If your boot-partition is not coming up, also edit the /etc/lilo.conf-file
+ in a Linux session booted on old kernel and run lilo before reboot. Check
+ lilo.conf anyway to get boot on other partitions with foreign OSes right
+ again. But there exists a feature of this driver that allows you to change
+ the assignment order of the SCSI-devices by flipping the PUN-assignment.
+ See the next paragraph for a description.
+
+ The problem for this is, that Linux does not assign the SCSI-devices in the
+ way as described in the ANSI-SCSI-standard. Linux assigns /dev/sda to
+ the device with at minimum id 0. But the first drive should be at id 6,
+ because for historical reasons, drive at id 6 has, by hardware, the highest
+ priority and a drive at id 0 the lowest. IBM was one of the rare producers,
+ where the BIOS assigns drives belonging to the ANSI-SCSI-standard. Most
+ other producers' BIOS does not (I think even Adaptec-BIOS). The
+ IBMMCA_SCSI_ORDER_STANDARD flag, which you set while configuring the
+ kernel enables to choose the preferred way of SCSI-device-assignment.
+ Defining this flag would result in Linux determining the devices in the
+ same order as DOS and OS/2 does on your MCA-machine. This is also standard
+ on most industrial computers and OSes, like e.g. OS-9. Leaving this flag
+ undefined will get your devices ordered in the default way of Linux. See
+ also the remarks of Chris Beauregard from Dec 15, 1997 and the followups
+ in section 3.
+
+ 2.5 Regular SCSI-Command-Processing
+ -----------------------------------
+ Only three functions get involved: ibmmca_queuecommand(), issue_cmd(),
+ and interrupt_handler().
+
+ The upper layer issues a scsi command by calling function
+ ibmmca_queuecommand(). This function fills a "subsystem control block"
+ (scb) and calls a local function issue_cmd(), which writes a scb
+ command into subsystem I/O ports. Once the scb command is carried out,
+ the interrupt_handler() is invoked. If a device is determined to be
+ existant and it has not assigned any ldn, it gets one dynamically.
+ For this, the whole stuff is done in ibmmca_queuecommand().
+
+ 2.6 Abort & Reset Commands
+ --------------------------
+ These are implemented with busy waiting for interrupt to arrive.
+ ibmmca_reset() and ibmmca_abort() do not work sufficently well
+ up to now and need still a lot of development work. But, this seems
+ to be even a problem with other SCSI-low level drivers, too. However,
+ this should be no excuse.
+
+ 2.7 Disk Geometry
+ -----------------
+ The ibmmca_biosparams() function should return the same disk geometry
+ as the bios. This is needed for fdisk, etc. The returned geometry is
+ certainly correct for disks smaller than 1 gigabyte. In the meantime,
+ it has been proved, that this works fine even with disks larger than
+ 1 gigabyte.
+
+ 2.8 Kernel Boot Option
+ ----------------------
+ The function ibmmca_scsi_setup() is called if option ibmmcascsi=n
+ is passed to the kernel. See file linux/init/main.c for details.
+
+ 2.9 Driver Module Support
+ -------------------------
+ Is implemented and tested by K. Kudielka. This could probably not work
+ on kernels <2.1.0.
+
+ 2.10 Multiple Hostadapter Support
+ ---------------------------------
+ This driver supports up to eight interfaces of type IBM-SCSI-Subsystem.
+ Integrated-, and MCA-adapters are automatically recognized. Unrecognizable
+ IBM-SCSI-Subsystem interfaces can be specified as kernel-parameters.
+
+ 2.11 /proc/scsi-Filesystem Information
+ --------------------------------------
+ Information about the driver condition is given in
+ /proc/scsi/ibmmca/<host_no>. ibmmca_proc_info() provides this information.
+
+ This table is quite informative for interested users. It shows the load
+ of commands on the subsystem and wether you are running the bypassed
+ (software) or integrated (hardware) SCSI-command set (see below). The
+ amount of accesses is shown. Read, write, modeselect is shown seperately
+ in order to help debugging problems with CD-ROMs or tapedrives.
+
+ The following table shows the list of 15 logical device numbers, that are
+ used by the SCSI-subsystem. The load on each ldn is shown in the table,
+ again, read and write commands are split. The last column shows the amount
+ of reassignments, that have been applied to the ldns, if you have more than
+ 15 pun/lun combinations available on the SCSI-bus.
+
+ The last two tables show the pun/lun map and the positions of the ldns
+ on this pun/lun map. This may change during operation, when a ldn is
+ reassigned to another pun/lun combination. If the necessity for dynamical
+ assignments is set to 'no', the ldn structure keeps static.
+
+ 2.12 /proc/mca-Filesystem Information
+ -------------------------------------
+ The slot-file contains all default entries and in addition chip and I/O-
+ address information of the SCSI-subsystem. This information is provided
+ by ibmmca_getinfo().
+
+ 2.13 Supported IBM SCSI-Subsystems
+ ----------------------------------
+ The following IBM SCSI-subsystems are supported by this driver:
+
+ - IBM Fast SCSI-2 Adapter
+ - IBM 7568 Industrial Computer SCSI Adapter w/cache
+ - IBM Expansion Unit SCSI Controller
+ - IBM SCSI Adapter w/Cache
+ - IBM SCSI Adapter
+ - IBM Integrated SCSI Controller
+
+ 2.14 Linux Kernel Versions
+ --------------------------
+ The IBM SCSI-subsystem low level driver is prepared to be used with
+ all versions of Linux between 2.0.x and 2.2.x. The compatibility checks
+ are fully implemented up from version 3.1e of the driver. This means, that
+ you just need the latest ibmmca.h and ibmmca.c file and copy it in the
+ linux/drivers/scsi directory. The code is automatically adapted during
+ kernel compilation.
+
+ 3 Code History
+ --------------
+ Jan 15 1996: First public release.
+ - Martin Kolinek
+
+ Jan 23 1996: Scrapped code which reassigned scsi devices to logical
+ device numbers. Instead, the existing assignment (created
+ when the machine is powered-up or rebooted) is used.
+ A side effect is that the upper layer of Linux SCSI
+ device driver gets bogus scsi ids (this is benign),
+ and also the hard disks are ordered under Linux the
+ same way as they are under dos (i.e., C: disk is sda,
+ D: disk is sdb, etc.).
+ - Martin Kolinek
+
+ I think that the CD-ROM is now detected only if a CD is
+ inside CD_ROM while Linux boots. This can be fixed later,
+ once the driver works on all types of PS/2's.
+ - Martin Kolinek
+
+ Feb 7 1996: Modified biosparam function. Fixed the CD-ROM detection.
+ For now, devices other than harddisk and CD_ROM are
+ ignored. Temporarily modified abort() function
+ to behave like reset().
+ - Martin Kolinek
+
+ Mar 31 1996: The integrated scsi subsystem is correctly found
+ in PS/2 models 56,57, but not in model 76. Therefore
+ the ibmmca_scsi_setup() function has been added today.
+ This function allows the user to force detection of
+ scsi subsystem. The kernel option has format
+ ibmmcascsi=n
+ where n is the scsi_id (pun) of the subsystem. Most likely, n is 7.
+ - Martin Kolinek
+
+ Aug 21 1996: Modified the code which maps ldns to (pun,0). It was
+ insufficient for those of us with CD-ROM changers.
+ - Chris Beauregard
+
+ Dec 14 1996: More improvements to the ldn mapping. See check_devices
+ for details. Did more fiddling with the integrated SCSI detection,
+ but I think it's ultimately hopeless without actually testing the
+ model of the machine. The 56, 57, 76 and 95 (ultimedia) all have
+ different integrated SCSI register configurations. However, the 56
+ and 57 are the only ones that have problems with forced detection.
+ - Chris Beauregard
+
+ Mar 8-16 1997: Modified driver to run as a module and to support
+ multiple adapters. A structure, called ibmmca_hostdata, is now
+ present, containing all the variables, that were once only
+ available for one single adapter. The find_subsystem-routine has vanished.
+ The hardware recognition is now done in ibmmca_detect directly.
+ This routine checks for presence of MCA-bus, checks the interrupt
+ level and continues with checking the installed hardware.
+ Certain PS/2-models do not recognize a SCSI-subsystem automatically.
+ Hence, the setup defined by command-line-parameters is checked first.
+ Thereafter, the routine probes for an integrated SCSI-subsystem.
+ Finally, adapters are checked. This method has the advantage to cover all
+ possible combinations of multiple SCSI-subsystems on one MCA-board. Up to
+ eight SCSI-subsystems can be recognized and announced to the upper-level
+ drivers with this improvement. A set of defines made changes to other
+ routines as small as possible.
+ - Klaus Kudielka
+
+ May 30 1997: (v1.5b)
+ 1) SCSI-command capability enlarged by the recognition of MODE_SELECT.
+ This needs the RD-Bit to be disabled on IM_OTHER_SCSI_CMD_CMD which
+ allows data to be written from the system to the device. It is a
+ necessary step to be allowed to set blocksize of SCSI-tape-drives and
+ the tape-speed, whithout confusing the SCSI-Subsystem.
+ 2) The recognition of a tape is included in the check_devices routine.
+ This is done by checking for TYPE_TAPE, that is already defined in
+ the kernel-scsi-environment. The markup of a tape is done in the
+ global ldn_is_tape[] array. If the entry on index ldn
+ is 1, there is a tapedrive connected.
+ 3) The ldn_is_tape[] array is necessary to distinguish between tape- and
+ other devices. Fixed blocklength devices should not cause a problem
+ with the SCB-command for read and write in the ibmmca_queuecommand
+ subroutine. Therefore, I only derivate the READ_XX, WRITE_XX for
+ the tape-devices, as recommended by IBM in this Technical Reference,
+ mentioned below. (IBM recommends to avoid using the read/write of the
+ subsystem, but the fact was, that read/write causes a command error from
+ the subsystem and this causes kernel-panic.)
+ 4) In addition, I propose to use the ldn instead of a fix char for the
+ display of PS2_DISK_LED_ON(). On 95, one can distinguish between the
+ devices that are accessed. It shows activity and easyfies debugging.
+ The tape-support has been tested with a SONY SDT-5200 and a HP DDS-2
+ (I do not know yet the type). Optimization and CD-ROM audio-support,
+ I am working on ...
+ - Michael Lang
+
+ June 19 1997: (v1.6b)
+ 1) Submitting the extra-array ldn_is_tape[] -> to the local ld[]
+ device-array.
+ 2) CD-ROM Audio-Play seems to work now.
+ 3) When using DDS-2 (120M) DAT-Tapes, mtst shows still density-code
+ 0x13 for ordinary DDS (61000 BPM) instead 0x24 for DDS-2. This appears
+ also on Adaptec 2940 adaptor in a PCI-System. Therefore, I assume that
+ the problem is independent of the low-level-driver/bus-architecture.
+ 4) Hexadecimal ldn on PS/2-95 LED-display.
+ 5) Fixing of the PS/2-LED on/off that it works right with tapedrives and
+ does not confuse the disk_rw_in_progress counter.
+ - Michael Lang
+
+ June 21 1997: (v1.7b)
+ 1) Adding of a proc_info routine to inform in /proc/scsi/ibmmca/<host> the
+ outer-world about operational load statistics on the different ldns,
+ seen by the driver. Everybody that has more than one IBM-SCSI should
+ test this, because I only have one and cannot see what happens with more
+ than one IBM-SCSI hosts.
+ 2) Definition of a driver version-number to have a better recognition of
+ the source when there are existing too much releases that may confuse
+ the user, when reading about release-specific problems. Up to know,
+ I calculated the version-number to be 1.7. Because we are in BETA-test
+ yet, it is today 1.7b.
+ 3) Sorry for the heavy bug I programmed on June 19 1997! After that, the
+ CD-ROM did not work any more! The C7-command was a fake impression
+ I got while programming. Now, the READ and WRITE commands for CD-ROM are
+ no longer running over the subsystem, but just over
+ IM_OTHER_SCSI_CMD_CMD. On my observations (PS/2-95), now CD-ROM mounts
+ much faster(!) and hopefully all fancy multimedia-functions, like direct
+ digital recording from audio-CDs also work. (I tried it with cdda2wav
+ from the cdwtools-package and it filled up the harddisk immediately :-).)
+ To easify boolean logics, a further local device-type in ld[], called
+ is_cdrom has been included.
+ 4) If one uses a SCSI-device of unsupported type/commands, one
+ immediately runs into a kernel-panic caused by Command Error. To better
+ understand which SCSI-command caused the problem, I extended this
+ specific panic-message slightly.
+ - Michael Lang
+
+ June 25 1997: (v1.8b)
+ 1) Some cosmetical changes for the handling of SCSI-device-types.
+ Now, also CD-Burners / WORMs and SCSI-scanners should work. For
+ MO-drives I have no experience, therefore not yet supported.
+ In logical_devices I changed from different type-variables to one
+ called 'device_type' where the values, corresponding to scsi.h,
+ of a SCSI-device are stored.
+ 2) There existed a small bug, that maps a device, coming after a SCSI-tape
+ wrong. Therefore, e.g. a CD-ROM changer would have been mapped wrong
+ -> problem removed.
+ 3) Extension of the logical_device structure. Now it contains also device,
+ vendor and revision-level of a SCSI-device for internal usage.
+ - Michael Lang
+
+ June 26-29 1997: (v2.0b)
+ 1) The release number 2.0b is necessary because of the completely new done
+ recognition and handling of SCSI-devices with the adapter. As I got
+ from Chris the hint, that the subsystem can reassign ldns dynamically,
+ I remembered this immediate_assign-command, I found once in the handbook.
+ Now, the driver first kills all ldn assignments that are set by default
+ on the SCSI-subsystem. After that, it probes on all puns and luns for
+ devices by going through all combinations with immediate_assign and
+ probing for devices, using device_inquiry. The found physical(!) pun,lun
+ structure is stored in get_scsi[][] as device types. This is followed
+ by the assignment of all ldns to existing SCSI-devices. If more ldns
+ than devices are available, they are assigned to non existing pun,lun
+ combinations to satisfy the adapter. With this, the dynamical mapping
+ was possible to implement. (For further info see the text in the
+ source-code and in the description below. Read the description
+ below BEFORE installing this driver on your system!)
+ 2) Changed the name IBMMCA_DRIVER_VERSION to IBMMCA_SCSI_DRIVER_VERSION.
+ 3) The LED-display shows on PS/2-95 no longer the ldn, but the SCSI-ID
+ (pun) of the accessed SCSI-device. This is now senseful, because the
+ pun known within the driver is exactly the pun of the physical device
+ and no longer a fake one.
+ 4) The /proc/scsi/ibmmca/<host_no> consists now of the first part, where
+ hit-statistics of ldns is shown and a second part, where the maps of
+ physical and logical SCSI-devices are displayed. This could be very
+ interesting, when one is using more than 15 SCSI-devices in order to
+ follow the dynamical remapping of ldns.
+ - Michael Lang
+
+ June 26-29 1997: (v2.0b-1)
+ 1) I forgot to switch the local_checking_phase_flag to 1 and back to 0
+ in the dynamical remapping part in ibmmca_queuecommand for the
+ device_exist routine. Sorry.
+ - Michael Lang
+
+ July 1-13 1997: (v3.0b,c)
+ 1) Merging of the driver-developments of Klaus Kudielka and Michael Lang
+ in order to get a optimum and unified driver-release for the
+ IBM-SCSI-Subsystem-Adapter(s).
+ For people, using the Kernel-release >=2.1.0, module-support should
+ be no problem. For users, running under <2.1.0, module-support may not
+ work, because the methods have changed between 2.0.x and 2.1.x.
+ 2) Added some more effective statistics for /proc-output.
+ 3) Change typecasting at necessary points from (unsigned long) to
+ virt_to_bus().
+ 4) Included #if... at special points to have specific adaption of the
+ driver to kernel 2.0.x and 2.1.x. It should therefore also run with
+ later releases.
+ 5) Magneto-Optical drives and medium-changers are also recognized, now.
+ Therefore, we have a completely gapfree recognition of all SCSI-
+ device-types, that are known by Linux up to kernel 2.1.31.
+ 6) The flag SCSI_IBMMCA_DEV_RESET has been inserted. If it is set within
+ the configuration, each connected SCSI-device will get a reset command
+ during boottime. This can be necessary for some special SCSI-devices.
+ This flag should be included in Config.in.
+ (See also the new Config.in file.)
+ Probable next improvement: bad disk handler.
+ - Michael Lang
+
+ Sept 14 1997: (v3.0c)
+ 1) Some debugging and speed optimization applied.
+ - Michael Lang
+
+ Dec 15, 1997
+ - chr...@truespectra.com
+ - made the front panel display thingy optional, specified from the
+ command-line via ibmmcascsi=display. Along the lines of the /LED
+ option for the OS/2 driver.
+ - fixed small bug in the LED display that would hang some machines.
+ - reversed ordering of the drives (using the
+ IBMMCA_SCSI_ORDER_STANDARD define). This is necessary for two main
+ reasons:
+ - users who've already installed Linux won't be screwed. Keep
+ in mind that not everyone is a kernel hacker.
+ - be consistent with the BIOS ordering of the drives. In the
+ BIOS, id 6 is C:, id 0 might be D:. With this scheme, they'd be
+ backwards. This confuses the crap out of those heathens who've
+ got a impure Linux installation (which, <wince>, I'm one of).
+ This whole problem arises because IBM is actually non-standard with
+ the id to BIOS mappings. You'll find, in fdomain.c, a similar
+ comment about a few FD BIOS revisions. The Linux (and apparently
+ industry) standard is that C: maps to scsi id (0,0). Let's stick
+ with that standard.
+ - Since this is technically a branch of my own, I changed the
+ version number to 3.0e-cpb.
+
+ Jan 17, 1998: (v3.0f)
+ 1) Addition of some statistical info for /proc in proc_info.
+ 2) Taking care of the SCSI-assignment problem, dealed by Chris at Dec 15
+ 1997. In fact, IBM is right, concerning the assignment of SCSI-devices
+ to driveletters. It is conform to the ANSI-definition of the SCSI-
+ standard to assign drive C: to SCSI-id 6, because it is the highest
+ hardware priority after the hostadapter (that has still today by
+ default everywhere id 7). Also realtime-operating systems that I use,
+ like LynxOS and OS9, which are quite industrial systems use top-down
+ numbering of the harddisks, that is also starting at id 6. Now, one
+ sits a bit between two chairs. On one hand side, using the define
+ IBMMCA_SCSI_ORDER_STANDARD makes Linux assigning disks conform to
+ the IBM- and ANSI-SCSI-standard and keeps this driver downward
+ compatible to older releases, on the other hand side, people is quite
+ habituated in believing that C: is assigned to (0,0) and much other
+ SCSI-BIOS do so. Therefore, I moved the IBMMCA_SCSI_ORDER_STANDARD
+ define out of the driver and put it into Config.in as subitem of
+ 'IBM SCSI support'. A help, added to Documentation/Configure.help
+ explains the differences between saying 'y' or 'n' to the user, when
+ IBMMCA_SCSI_ORDER_STANDARD prompts, so the ordinary user is enabled to
+ choose the way of assignment, depending on his own situation and gusto.
+ 3) Adapted SCSI_IBMMCA_DEV_RESET to the local naming convention, so it is
+ now called IBMMCA_SCSI_DEV_RESET.
+ 4) Optimization of proc_info and its subroutines.
+ 5) Added more in-source-comments and extended the driver description by
+ some explanation about the SCSI-device-assignment problem.
+ - Michael Lang
+
+ Jan 18, 1998: (v3.0g)
+ 1) Correcting names to be absolutely conform to the later 2.1.x releases.
+ This is necessary for
+ IBMMCA_SCSI_DEV_RESET -> CONFIG_IBMMCA_SCSI_DEV_RESET
+ IBMMCA_SCSI_ORDER_STANDARD -> CONFIG_IBMMCA_SCSI_ORDER_STANDARD
+ - Michael Lang
+
+ Jan 18, 1999: (v3.1 MCA-team internal)
+ 1) The multiple hosts structure is accessed from every subroutine, so there
+ is no longer the address of the device structure passed from function
+ to function, but only the hostindex. A call by value, nothing more. This
+ should really be understood by the compiler and the subsystem should get
+ the right values and addresses.
+ 2) The SCSI-subsystem detection was not complete and quite hugely buggy up
+ to now, compared to the technical manual. The interpretation of the pos2
+ register is not as assumed by people before, therefore, I dropped a note
+ in the ibmmca_detect function to show the registers' interpretation.
+ The pos-registers of integrated SCSI-subsystems do not contain any
+ information concerning the IO-port offset, really. Instead, they contain
+ some info about the adapter, the chip, the NVRAM .... The I/O-port is
+ fixed to 0x3540 - 0x3547. There can be more than one adapters in the
+ slots and they get an offset for the I/O area in order to get their own
+ I/O-address area. See chapter 2 for detailed description. At least, the
+ detection should now work right, even on models other than 95. The 95ers
+ came happily around the bug, as their pos2 register contains always 0
+ in the critical area. Reserved bits are not allowed to be interpreted,
+ therefore, IBM is allowed to set those bits as they like and they may
+ really vary between different PS/2 models. So, now, no interpretation
+ of reserved bits - hopefully no trouble here anymore.
+ 3) The command error, which you may get on models 55, 56, 57, 70, 77 and
+ P70 may have been caused by the fact, that adapters of older design do
+ not like sending commands to non-existing SCSI-devices and will react
+ with a command error as a sign of protest. While this error is not
+ present on IBM SCSI Adapter w/cache, it appears on IBM Integrated SCSI
+ Adapters. Therefore, I implemented a workarround to forgive those

SHAR_EOF
true || echo 'restore of patch-2.2.8 failed'
fi

echo 'End of part 17'
echo 'File patch-2.2.8 is continued in part 18'
echo 18 > _shar_seq_.tmp

Thomas...@ciw.uni-karlsruhe.de

unread,
May 12, 1999, 3:00:00 AM5/12/99
to
Archive-name: v2.2/patch-2.2.8/part18

#!/bin/sh
# this is part 18 of a 33 - part archive


# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.8 continued
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 18; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.8'
else
echo 'x - continuing with patch-2.2.8'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.8' &&

+ adapters their protests, but it is marked up in the statisctis, so
+ after a successful boot, you can see in /proc/scsi/ibmmca/<host_number>
+ how often the command errors have been forgiven to the SCSI-subsystem.
+ If the number is bigger than 0, you have a SCSI subsystem of older
+ design, what should no longer matter.
+ 4) ibmmca_getinfo() has been adapted very carefully, so it shows in the
+ slotn file really, what is senseful to be presented.
+ 5) ibmmca_register() has been extended in its parameter list in order to
+ pass the right name of the SCSI-adapter to Linux.


+ - Michael Lang
+

+ Feb 6, 1999: (v3.1)
+ 1) Finally, after some 3.1Beta-releases, the 3.1 release. Sorry, for
+ the delayed release, but it was not finished with the release of
+ Kernel 2.2.0.


+ - Michael Lang
+

+ Feb 10, 1999 (v3.1)
+ 1) Added a new commandline parameter called 'bypass' in order to bypass
+ every integrated subsystem SCSI-command consequently in case of
+ troubles.
+ 2) Concatenated read_capacity requests to the harddisks. It gave a lot
+ of troubles with some controllers and after I wanted to apply some
+ extensions, it jumped out in the same situation, on my w/cache, as like
+ on D. Weinehalls' Model 56, having integrated SCSI. This gave me the
+ descissive hint to move the code-part out and declare it global. Now,
+ it seems to work by far much better an more stable. Let us see, what
+ the world thinks of it...
+ 3) By the way, only Sony DAT-drives seem to show density code 0x13. A
+ test with a HP drive gave right results, so the problem is vendor-
+ specific and not a problem of the OS or the driver.


+ - Michael Lang
+

+ Feb 18, 1999 (v3.1d)
+ 1) The abort command and the reset function have been checked for
+ inconsistencies. From the logical point of thinking, they work
+ at their optimum, now, but as the subsystem does not answer with an
+ interrupt, abort never finishes, sigh...
+ 2) Everything, that is accessed by a busmaster request from the adapter
+ is now declared as global variable, even the return-buffer in the
+ local checking phase. This assures, that no accesses to undefined memory
+ areas are performed.
+ 3) In ibmmca.h, the line unchecked_isa_dma is added with 1 in order to
+ avoid memory-pointers for the areas higher than 16MByte in order to
+ be sure, it also works on 16-Bit Microchannel bus systems.
+ 4) A lot of small things have been found, but nothing that endangered the
+ driver operations. Just it should be more stable, now.


+ - Michael Lang
+

+ Feb 20, 1999 (v3.1e)
+ 1) I took the warning from the Linux Kernel Hackers Guide serious and
+ checked the cmd->result return value to the done-function very carefuly.
+ It is obvious, that the IBM SCSI only delivers the tsb.dev_status, if
+ some error appeared, else it is undefined. Now, this is fixed. Before
+ any SCB command gets queued, the tsb.dev_status is set to 0, so the
+ cmd->result won't screw up Linux higher level drivers.
+ 2) The reset-function has slightly improved. This is still planed for
+ abort. During the abort and the reset function, no interrupts are
+ allowed. This is however quite hard to cope with, so the INT-status
+ register is read. When the interrupt gets queued, one can find its
+ status immediately on that register and is enabled to continue in the
+ reset function. I had no chance to test this really, only in a bogus
+ situation, I got this function running, but the situation was too much
+ worse for Linux :-(, so tests will continue.
+ 3) Buffers got now consistent. No open address mapping, as before and
+ therefore no further troubles with the unassigned memory segmentation
+ faults that scrambled probes on 95XX series and even on 85XX series,
+ when the kernel is done in a not so perfectly fitting way.
+ 4) Spontaneous interrupts from the subsystem, appearing without any
+ command previously queued are answered with a DID_BAD_INTR result.
+ 5) Taken into account ZP Gus' proposals to reverse the SCSI-device
+ scan order. As it does not work on Kernel 2.1.x or 2.2.x, as proposed
+ by him, I implemented it in a slightly derived way, which offers in
+ addition more flexibility.


+ - Michael Lang
+

+ 4 To do
+ -------
+ - It seems that the handling of bad disks is really bad -
+ non-existent, in fact.
+ - More testing of the full driver-controlled dynamical ldn
+ (re)mapping for up to 56 SCSI-devices.
+ - Support more of the SCSI-command set.
+ - Support some of the caching abilities, particularly Read Prefetch.
+ This fetches data into the cache, which later gets hit by the
+ regular Read Data. (<--- This is coming soon!!!!)
+ - Abort and Reset functions still slightly buggy or better say,
+ it is the new episode, called SCREAM III.
+
+ 5 Users' Manual
+ ---------------
+ 5.1 Commandline Parameters
+ --------------------------
+ There exist several features for the IBM SCSI-subsystem driver.
+ The commandline parameter format is:
+
+ ibmmcascsi=<command1>,<command2>,<command3>,...
+
+ where commandN can be one of the following:
+
+ display Owners of a model 95 or other PS/2 systems with an
+ alphanumeric LED display may set this to have their
+ display showing the following output of the 8 digits:
+
+ ------DA
+
+ where '-' stays dark, 'D' shows the SCSI-device id
+ and 'A' shows the SCSI hostindex, beeing currently
+ accessed.
+ adisplay This works like display, but gives more optical overview
+ of the activities on the SCSI-bus. The display will have
+ the following output:
+
+ 6543210A
+
+ where the numbers 0 to 6 light up at the shown position,
+ when the SCSI-device is accessed. A shows again the SCSI
+ hostindex. If display nor adisplay is set, the internal
+ PS/2 harddisk LED is used for media-activities. So, if
+ you really do not have a system with a LED-display, you
+ should not set display or adisplay.
+ bypass This commandline parameter forces the driver never to use
+ SCSI-subsystems' integrated SCSI-command set. Except of
+ the immediate assign, which is of vital importance for
+ every IBM SCSI-subsystem to set its ldns right. Instead,
+ the ordinary ANSI-SCSI-commands are used and passed by the
+ controller to the SCSI-devices, therefore 'bypass'. The
+ effort, done by the subsystem is quite bogus and at a
+ minimum and therefore it should work everywhere. This
+ could maybe solve troubles with old or integrated SCSI-
+ controllers and nasty harddisks. Keep in mind, that using
+ this flag will slow-down SCSI-accesses slightly, as the
+ software generated commands are always slower than the
+ hardware. Non-harddisk devices always get read/write-
+ commands in bypass mode.
+ normal This is the parameter, introduced on the 2.0.x development
+ rail by ZP Gu. This parameter defines the SCSI-device
+ scan order in the new industry standard. This means, that
+ the first SCSI-device is the one with the lowest pun.
+ E.g. harddisk at pun=0 is scanned before harddisk at
+ pun=6, which means, that harddisk at pun=0 gets sda
+ and the one at pun=6 gets sdb.
+ ansi The ANSI-standard for the right scan order, as done by
+ IBM, Microware and Microsoft, scans SCSI-devices starting
+ at the highest pun, which means, that e.g. harddisk at
+ pun=6 gets sda and a harddisk at pun=0 gets sdb. If you
+ like to have the same SCSI-device order, as in DOS, OS-9
+ or OS/2, just use this parameter.
+
+ A further option is that you can force the SCSI-driver to accept a SCSI-
+ subsystem at a certain I/O-address with a predefined adapter PUN. This
+ is done by entering
+
+ commandN = I/O-base
+ commandN+1 = adapter PUN
+
+ e.g. ibmmcascsi=0x3540,7 will force the driver to detect a SCSI-subsystem
+ at I/O-address 0x3540 with adapter PUN 7.
+
+ Examples:
+
+ ibmmcascsi=adisplay,bypass
+
+ This will use the advanced display mode for the model 95 LED display and
+ every SCSI-command passed to a attached device will get bypassed in order
+ not to use any of the subsystem built-in commands.
+
+ ibmmcascsi=display,0x3558,7
+
+ This will activate the default display mode for the model 95 LED display
+ and will force the driver to accept a SCSI-subsystem at I/O-base 0x3558
+ with adapter PUN 7.
+
+ 5.2 Troubleshooting
+ -------------------
+ The following FAQs should help you to solve some major problems with this
+ driver.
+
+ Q: "Reset SCSI-devices at boottime" halts the system at boottime, why?
+ A: This is only tested with the IBM SCSI Adapter w/cache. It is not
+ yet prooved to run on other adapters, however you may be lucky.
+ In version 3.1d this has been hugely improved and should work better,
+ now. Normally you really won't need to activate this flag in the
+ kernel configuration, as all post 1989 SCSI-devices should accept
+ the reset-signal, when the computer is switched on. The SCSI-
+ subsystem generates this reset while beeing initialized. This flag
+ is really reserved for users with very old, very strange or self-made
+ SCSI-devices.
+ Q: Why is the SCSI-order of my drives mirrored to the device-order
+ seen from OS/2 or DOS ?
+ A: It depends on the operating system, if it looks at the devices in
+ ANSI-SCSI-standard (starting from pun 6 and going down to pun 0) or
+ if it just starts at pun 0 and counts up. If you want to be conform
+ with OS/2 and DOS, you have to activate this flag in the kernel
+ configuration or you should set 'ansi' as parameter for the kernel.
+ The parameter 'normal' sets the new industry standard, starting
+ from pun 0, scaning up to pun 6. This allows you to change your
+ opinion still after having already compiled the kernel.
+ Q: Why can I not find the IBM MCA SCSI support in the config menue?
+ A: You have to activate MCA bus support, first.
+ Q: Where can I find the latest info about this driver?
+ A: See the file MAINTAINERS for the current WWW-address, which offers
+ updates, info and Q/A lists. At this files' origin, the webaddress
+ was: http://www.uni-mainz.de/~langm000/linux.html
+ Q: My SCSI-adapter is not recognized by the driver, what can I do?
+ A: Just force it to be recognized by kernel parameters. See section 5.1.
+ Q: The driver screws up, if it starts to probe SCSI-devices, is there
+ some way out of it?
+ A: This is based on some problems with the driver. In such cases, send
+ e-mail to the maintainer. If you are owner of a model with the serial
+ number 95XX, just send as subject NOTIFY 95XX PROBLEM and the
+ maintainer immediately knows about your problem. But please:
+ Check your hardware and only if it works fine with other operating
+ systems, send E-Mail to me to notify the troubles. See the homepage
+ for how to send bug-reports or please read the next Q/A, here:
+ Q: I get a message: panic IBM MCA SCSI: command error .... , what can
+ I do against this?
+ A: Previously, I followed the way by ignoring command errors by using
+ ibmmcascsi=forgiveall, but this command no longer exists and is
+ obsolete. If such a problem appears, it is caused by some segmentation
+ fault of the driver, which maps to some unallowed area. The latest
+ version of the driver should be ok, as most bugs have been solved.
+ Q: There are still kernel panics, even after having set
+ ibmmcascsi=forgiveall. Are there other possibilities to prevent
+ such panics?
+ A: No, get just the latest release of the driver and it should work
+ better and better with increasing version number. Forget this
+ ibmmcascsi=forgiveall, as also ignorecmd are obsolete.
+ Q: Linux panics or stops without any comment, but it is probable, that my
+ harddisk(s) have bad blocks.
+ A: Sorry, the bad-block handling is still a feeble point of this driver,
+ but is on the schedule for development in the near future.
+ Q: Linux panics while dynamically assigning SCSI-ids or ldns.
+ A: If you disconnect a SCSI-device from the machine, while Linux is up
+ and the driver uses dynamical reassignment of logical device numbers
+ (ldn), it really gets "angry" if it won't find devices, that were still
+ present at boottime and stops Linux.
+ Q: The system does not recover after an abort-command has been generated.
+ A: This is regrettably true, as it is not yet understood, why the
+ SCSI-adapter does really NOT generate any interrupt at the end of
+ the abort-command. As no interrupt is generated, the abort command
+ cannot get finished and the system hangs, sorry, but checks are
+ running to hunt down this problem. If there is a real pending command,
+ the interrupt MUST get generated after abort. In this case, it
+ should finish well.
+ Q: The system gets in bad shape after a SCSI-reset, is this known?
+ A: Yes, as there are a lot of prescriptions (see the Linux Hackers'
+ Guide) what has to be done for reset, we still share the bad shape of
+ the reset functions with all other low level SCSI-drivers.
+ Astonishingly, reset works in most cases quite ok, but the harddisks
+ won't run in synchonous mode anymore after a reset, until you reboot.
+ Q: Why does my XXX w/Cache adapter not use read-prefetch?
+ A: w/Cache technical manuals are incoming here, so if I understood the
+ command of read-prefetch, it should be an easy thing to get harddisks
+ read in read-prefetch with w/Cache controllers. Some weeks or months,
+ still ahead and a lot of work still to do, sigh ...
+
+ 5.3 Bugreports
+ --------------
+ If you really find bugs in the sourcecode or the driver will successfully
+ refuse to work on your machine, you should send a bug report to me. The
+ best for this is to follow the instructions on the WWW-page for this
+ driver. Fill out the bug-report form, placed on the WWW-page and ship it,
+ so the bugs can be taken into account with maximum efforts. But, please
+ do not send bug reports about this driver to Linus Torvalds or Leonard
+ Zubkoff, as Linus is burried in E-Mail and Leonard is supervising all
+ SCSI-drivers and won't have the time left to look inside every single
+ driver to fix a bug and especially DO NOT send modified code to Linus
+ Torvalds, which has not been checked here!!! Recently, I got a lot of
+ bugreports for errors in the ibmmca.c code, which I could not imagine, but
+ a look inside some Linux-distribution showed me quite often some modified
+ code, which did no longer work on most other machines than the one of the
+ modifier. Ok, so now that there is maintenance service available for this
+ driver, please use this address first in order to keep the level of
+ confusion low. Thank you!
+
+ When you get a SCSI-error message that panics your system, a list of
+ register-entries of the SCSI-subsystem is shown (from Version 3.1d). With
+ this list, it is very easy for the maintainer to localize the problem in
+ the driver or in the configuration of the user. Please write down all the
+ values from this report and send them to the maintainer. This would really
+ help a lot and makes life easier concerning misunderstandings.
+
+ Use the bug-report form (see 5.4 for its address) to send all the bug-
+ stuff to the maintainer or write e-mail with the values from the table.
+
+ 5.4 Support WWW-page
+ --------------------
+ The address of the IBM SCSI-subsystem supporting WWW-page is:
+
+ http://www.uni-mainz.de/~langm000/linux.html
+
+ Here you can find info about the background of this driver, patches,
+ news and a bugreport form.
+
+ 6 References
+ ------------
+ The source of information is "Update for the PS/2 Hardware
+ Interface Technical Reference, Common Interfaces", September 1991,
+ part number 04G3281, available in the U.S. for $21.75 at
+ 1-800-IBM-PCTB, elsewhere call your local friendly IBM
+ representative. E.g. in Germany, "Hallo IBM" works really great.
+ In addition to SCSI subsystem, this update contains fairly detailed
+ (at hardware register level) sections on diskette controller,
+ keyboard controller, serial port controller, VGA, and XGA.
+
+ Additional information from "Personal System/2 Micro Channel SCSI
+ Adapter with Cache Technical Reference", March 1990, PN 68X2365,
+ probably available from the same source (or possibly found buried
+ in officemates desk).
+
+ Friedhelm Schmidt, "SCSI-Bus und IDE-Schnittstelle - Moderne Peripherie-
+ Schnittstellen: Hardware, Protokollbeschreibung und Anwendung", 2. Aufl.
+ Addison Wesley, 1996.
+
+ Michael K. Johnson, "The Linux Kernel Hackers' Guide", Version 0.6, Chapel
+ Hill - North Carolina, 1995
+
+ Andreas Kaiser, "SCSI TAPE BACKUP for OS/2 2.0", Version 2.12, Stuttgart
+ 1993
+
+ Helmut Rompel, "IBM Computerwelt GUIDE", What is what bei IBM., Systeme *
+ Programme * Begriffe, IWT-Verlag GmbH - Muenchen, 1988
+
+ 7 Trademarks
+ ------------
+ IBM, PS/2, OS/2, Microchannel are registered trademarks of International
+ Business Machines Corp.
+
+ MS-DOS is a registered trademark of Microsoft Corporation
+
+ OS-9 is a registered trademark of Microware Systems
+
+------
+Michael Lang
+(lan...@kph.uni-mainz.de)
diff -u --recursive --new-file v2.2.7/linux/drivers/scsi/ibmmca.c linux/drivers/scsi/ibmmca.c
--- v2.2.7/linux/drivers/scsi/ibmmca.c Thu Dec 31 10:29:01 1998
+++ linux/drivers/scsi/ibmmca.c Mon May 10 13:00:10 1999
@@ -3,291 +3,30 @@
X *
X * Copyright (c) 1995 Strom Systems, Inc. under the terms of the GNU
X * General Public License. Written by Martin Kolinek, December 1995.
+ * Further development by: Chris Beauregard, Klaus Kudielka, Michael Lang
+ * See the file README.ibmmca for a detailed description of this driver,
+ * the commandline arguments and the history of its development.
+ * See the WWW-page: http://www.uni-mainz.de/~langm000/linux.html for latest
+ * updates and info.
X */
X
-/* Update history:
- Jan 15 1996: First public release.
- - Martin Kolinek
-
- Jan 23 1996: Scrapped code which reassigned scsi devices to logical
- device numbers. Instead, the existing assignment (created
- when the machine is powered-up or rebooted) is used.
- A side effect is that the upper layer of Linux SCSI
- device driver gets bogus scsi ids (this is benign),
- and also the hard disks are ordered under Linux the
- same way as they are under dos (i.e., C: disk is sda,
- D: disk is sdb, etc.).
- - Martin Kolinek
-
- I think that the CD-ROM is now detected only if a CD is
- inside CD_ROM while Linux boots. This can be fixed later,
- once the driver works on all types of PS/2's.
- - Martin Kolinek
-
- Feb 7 1996: Modified biosparam function. Fixed the CD-ROM detection.
- For now, devices other than harddisk and CD_ROM are
- ignored. Temporarily modified abort() function
- to behave like reset().
- - Martin Kolinek
-
- Mar 31 1996: The integrated scsi subsystem is correctly found
- in PS/2 models 56,57, but not in model 76. Therefore
- the ibmmca_scsi_setup() function has been added today.
- This function allows the user to force detection of
- scsi subsystem. The kernel option has format
- ibmmcascsi=n
- where n is the scsi_id (pun) of the subsystem. Most likely, n is 7.
- - Martin Kolinek
-
- Aug 21 1996: Modified the code which maps ldns to (pun,0). It was
- insufficient for those of us with CD-ROM changers.
- - Chris Beauregard
-
- Dec 14 1996: More improvements to the ldn mapping. See check_devices
- for details. Did more fiddling with the integrated SCSI detection,
- but I think it's ultimately hopeless without actually testing the
- model of the machine. The 56, 57, 76 and 95 (ultimedia) all have
- different integrated SCSI register configurations. However, the 56
- and 57 are the only ones that have problems with forced detection.
- - Chris Beauregard
-
- Mar 8-16 1997: Modified driver to run as a module and to support
- multiple adapters. A structure, called ibmmca_hostdata, is now
- present, containing all the variables, that were once only
- available for one single adapter. The find_subsystem-routine has vanished.
- The hardware recognition is now done in ibmmca_detect directly.
- This routine checks for presence of MCA-bus, checks the interrupt
- level and continues with checking the installed hardware.
- Certain PS/2-models do not recognize a SCSI-subsystem automatically.
- Hence, the setup defined by command-line-parameters is checked first.
- Thereafter, the routine probes for an integrated SCSI-subsystem.
- Finally, adapters are checked. This method has the advantage to cover all
- possible combinations of multiple SCSI-subsystems on one MCA-board. Up to
- eight SCSI-subsystems can be recognized and announced to the upper-level
- drivers with this improvement. A set of defines made changes to other
- routines as small as possible.
- - Klaus Kudielka
-
- May 30 1997: (v1.5b)
- 1) SCSI-command capability enlarged by the recognition of MODE_SELECT.
- This needs the RD-Bit to be disabled on IM_OTHER_SCSI_CMD_CMD which
- allows data to be written from the system to the device. It is a
- necessary step to be allowed to set blocksize of SCSI-tape-drives and
- the tape-speed, whithout confusing the SCSI-Subsystem.
- 2) The recognition of a tape is included in the check_devices routine.
- This is done by checking for TYPE_TAPE, that is already defined in
- the kernel-scsi-environment. The markup of a tape is done in the
- global ldn_is_tape[] array. If the entry on index ldn
- is 1, there is a tapedrive connected.
- 3) The ldn_is_tape[] array is necessary to distinguish between tape- and
- other devices. Fixed blocklength devices should not cause a problem
- with the SCB-command for read and write in the ibmmca_queuecommand
- subroutine. Therefore, I only derivate the READ_XX, WRITE_XX for
- the tape-devices, as recommended by IBM in this Technical Reference,
- mentioned below. (IBM recommends to avoid using the read/write of the
- subsystem, but the fact was, that read/write causes a command error from
- the subsystem and this causes kernel-panic.)
- 4) In addition, I propose to use the ldn instead of a fix char for the
- display of PS2_DISK_LED_ON(). On 95, one can distinguish between the
- devices that are accessed. It shows activity and easyfies debugging.
- The tape-support has been tested with a SONY SDT-5200 and a HP DDS-2
- (I do not know yet the type). Optimization and CD-ROM audio-support,
- I am working on ...
- - Michael Lang
-
- June 19 1997: (v1.6b)
- 1) Submitting the extra-array ldn_is_tape[] -> to the local ld[]
- device-array.
- 2) CD-ROM Audio-Play seems to work now.
- 3) When using DDS-2 (120M) DAT-Tapes, mtst shows still density-code
- 0x13 for ordinary DDS (61000 BPM) instead 0x24 for DDS-2. This appears
- also on Adaptec 2940 adaptor in a PCI-System. Therefore, I assume that
- the problem is independent of the low-level-driver/bus-architecture.
- 4) Hexadecimal ldn on PS/2-95 LED-display.
- 5) Fixing of the PS/2-LED on/off that it works right with tapedrives and
- does not confuse the disk_rw_in_progress counter.
- - Michael Lang
-
- June 21 1997: (v1.7b)
- 1) Adding of a proc_info routine to inform in /proc/scsi/ibmmca/<host> the
- outer-world about operational load statistics on the different ldns,
- seen by the driver. Everybody that has more than one IBM-SCSI should
- test this, because I only have one and cannot see what happens with more
- than one IBM-SCSI hosts.
- 2) Definition of a driver version-number to have a better recognition of
- the source when there are existing too much releases that may confuse
- the user, when reading about release-specific problems. Up to know,
- I calculated the version-number to be 1.7. Because we are in BETA-test
- yet, it is today 1.7b.
- 3) Sorry for the heavy bug I programmed on June 19 1997! After that, the
- CD-ROM did not work any more! The C7-command was a fake impression
- I got while programming. Now, the READ and WRITE commands for CD-ROM are
- no longer running over the subsystem, but just over
- IM_OTHER_SCSI_CMD_CMD. On my observations (PS/2-95), now CD-ROM mounts
- much faster(!) and hopefully all fancy multimedia-functions, like direct
- digital recording from audio-CDs also work. (I tried it with cdda2wav
- from the cdwtools-package and it filled up the harddisk immediately :-).)
- To easify boolean logics, a further local device-type in ld[], called
- is_cdrom has been included.
- 4) If one uses a SCSI-device of unsupported type/commands, one
- immediately runs into a kernel-panic caused by Command Error. To better
- understand which SCSI-command caused the problem, I extended this
- specific panic-message slightly.
- - Michael Lang
-
- June 25 1997: (v1.8b)
- 1) Some cosmetical changes for the handling of SCSI-device-types.
- Now, also CD-Burners / WORMs and SCSI-scanners should work. For
- MO-drives I have no experience, therefore not yet supported.
- In logical_devices I changed from different type-variables to one
- called 'device_type' where the values, corresponding to scsi.h,
- of a SCSI-device are stored.
- 2) There existed a small bug, that maps a device, coming after a SCSI-tape
- wrong. Therefore, e.g. a CD-ROM changer would have been mapped wrong
- -> problem removed.
- 3) Extension of the logical_device structure. Now it contains also device,
- vendor and revision-level of a SCSI-device for internal usage.
- - Michael Lang
-
- June 26-29 1997: (v2.0b)
- 1) The release number 2.0b is necessary because of the completely new done
- recognition and handling of SCSI-devices with the adapter. As I got
- from Chris the hint, that the subsystem can reassign ldns dynamically,
- I remembered this immediate_assign-command, I found once in the handbook.
- Now, the driver first kills all ldn assignments that are set by default
- on the SCSI-subsystem. After that, it probes on all puns and luns for
- devices by going through all combinations with immediate_assign and
- probing for devices, using device_inquiry. The found physical(!) pun,lun
- structure is stored in get_scsi[][] as device types. This is followed
- by the assignment of all ldns to existing SCSI-devices. If more ldns
- than devices are available, they are assigned to non existing pun,lun
- combinations to satisfy the adapter. With this, the dynamical mapping
- was possible to implement. (For further info see the text in the
- source-code and in the description below. Read the description
- below BEFORE installing this driver on your system!)
- 2) Changed the name IBMMCA_DRIVER_VERSION to IBMMCA_SCSI_DRIVER_VERSION.
- 3) The LED-display shows on PS/2-95 no longer the ldn, but the SCSI-ID
- (pun) of the accessed SCSI-device. This is now senseful, because the
- pun known within the driver is exactly the pun of the physical device
- and no longer a fake one.
- 4) The /proc/scsi/ibmmca/<host_no> consists now of the first part, where
- hit-statistics of ldns is shown and a second part, where the maps of
- physical and logical SCSI-devices are displayed. This could be very
- interesting, when one is using more than 15 SCSI-devices in order to
- follow the dynamical remapping of ldns.
- - Michael Lang
-
- June 26-29 1997: (v2.0b-1)
- 1) I forgot to switch the local_checking_phase_flag to 1 and back to 0
- in the dynamical remapping part in ibmmca_queuecommand for the
- device_exist routine. Sorry.
- - Michael Lang
-
- July 1-13 1997: (v3.0b,c)
- 1) Merging of the driver-developments of Klaus Kudielka and Michael Lang
- in order to get a optimum and unified driver-release for the
- IBM-SCSI-Subsystem-Adapter(s).
- For people, using the Kernel-release >=2.1.0, module-support should
- be no problem. For users, running under <2.1.0, module-support may not
- work, because the methods have changed between 2.0.x and 2.1.x.
- 2) Added some more effective statistics for /proc-output.
- 3) Change typecasting at necessary points from (unsigned long) to
- virt_to_bus().
- 4) Included #if... at special points to have specific adaption of the
- driver to kernel 2.0.x and 2.1.x. It should therefore also run with
- later releases.
- 5) Magneto-Optical drives and medium-changers are also recognized, now.
- Therefore, we have a completely gapfree recognition of all SCSI-
- device-types, that are known by Linux up to kernel 2.1.31.
- 6) The flag SCSI_IBMMCA_DEV_RESET has been inserted. If it is set within
- the configuration, each connected SCSI-device will get a reset command
- during boottime. This can be necessary for some special SCSI-devices.
- This flag should be included in Config.in.
- (See also the new Config.in file.)
- Probable next improvement: bad disk handler.
- - Michael Lang
-
- Sept 14 1997: (v3.0c)
- 1) Some debugging and speed optimization applied.
- - Michael Lang
-
- Dec 15, 1997
- - chr...@truespectra.com
- - made the front panel display thingy optional, specified from the
- command-line via ibmmcascsi=display. Along the lines of the /LED
- option for the OS/2 driver.
- - fixed small bug in the LED display that would hang some machines.
- - reversed ordering of the drives (using the
- IBMMCA_SCSI_ORDER_STANDARD define). This is necessary for two main
- reasons:
- - users who've already installed Linux won't be screwed. Keep
- in mind that not everyone is a kernel hacker.
- - be consistent with the BIOS ordering of the drives. In the
- BIOS, id 6 is C:, id 0 might be D:. With this scheme, they'd be
- backwards. This confuses the crap out of those heathens who've
- got a impure Linux installation (which, <wince>, I'm one of).
- This whole problem arises because IBM is actually non-standard with
- the id to BIOS mappings. You'll find, in fdomain.c, a similar
- comment about a few FD BIOS revisions. The Linux (and apparently
- industry) standard is that C: maps to scsi id (0,0). Let's stick
- with that standard.
- - Since this is technically a branch of my own, I changed the
- version number to 3.0e-cpb.
-
- Jan 17, 1998: (v3.0f)
- 1) Addition of some statistical info for /proc in proc_info.
- 2) Taking care of the SCSI-assignment problem, dealed by Chris at Dec 15
- 1997. In fact, IBM is right, concerning the assignment of SCSI-devices
- to driveletters. It is conform to the ANSI-definition of the SCSI-
- standard to assign drive C: to SCSI-id 6, because it is the highest
- hardware priority after the hostadapter (that has still today by
- default everywhere id 7). Also realtime-operating systems that I use,
- like LynxOS and OS9, which are quite industrial systems use top-down
- numbering of the harddisks, that is also starting at id 6. Now, one
- sits a bit between two chairs. On one hand side, using the define
- IBMMCA_SCSI_ORDER_STANDARD makes Linux assigning disks conform to
- the IBM- and ANSI-SCSI-standard and keeps this driver downward
- compatible to older releases, on the other hand side, people is quite
- habituated in believing that C: is assigned to (0,0) and much other
- SCSI-BIOS do so. Therefore, I moved the IBMMCA_SCSI_ORDER_STANDARD
- define out of the driver and put it into Config.in as subitem of
- 'IBM SCSI support'. A help, added to Documentation/Configure.help
- explains the differences between saying 'y' or 'n' to the user, when
- IBMMCA_SCSI_ORDER_STANDARD prompts, so the ordinary user is enabled to
- choose the way of assignment, depending on his own situation and gusto.
- 3) Adapted SCSI_IBMMCA_DEV_RESET to the local naming convention, so it is
- now called IBMMCA_SCSI_DEV_RESET.
- 4) Optimization of proc_info and its subroutines.
- 5) Added more in-source-comments and extended the driver description by
- some explanation about the SCSI-device-assignment problem.
- - Michael Lang
-
- Jan 18, 1998: (v3.0g)
- 1) Correcting names to be absolutely conform to the later 2.1.x releases.
- This is necessary for
- IBMMCA_SCSI_DEV_RESET -> CONFIG_IBMMCA_SCSI_DEV_RESET
- IBMMCA_SCSI_ORDER_STANDARD -> CONFIG_IBMMCA_SCSI_ORDER_STANDARD
- - Michael Lang
-
- TODO:
-
- - It seems that the handling of bad disks is really bad -
- non-existent, in fact.
- - More testing of the full driver-controlled dynamical ldn
- (re)mapping for up to 56 SCSI-devices.
- - Support more SCSI-device-types, if Linux defines more.
- - Support more of the SCSI-command set.
- - Support some of the caching abilities, particularly Read Prefetch.
- This fetches data into the cache, which later gets hit by the
- regular Read Data.
- - Abort and Reset functions still slightly buggy. Especially when
- floppydisk(!) operations report errors.
+/******************* HEADER FILE INCLUDES ************************************/
+#ifndef LINUX_VERSION_CODE
+#include <linux/version.h>
+#endif
X
-******************************************************************************/
+/* choose adaption for Kernellevel */
+#define local_LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s))
+#if LINUX_VERSION_CODE < local_LinuxVersionCode(2,1,0)
+#define OLDKERN
+#else
+#undef OLDKERN
+#endif
X
X #include <linux/module.h>
X #include <linux/kernel.h>
X #include <linux/types.h>
+#include <linux/ctype.h>
X #include <linux/string.h>
X #include <linux/ioport.h>
X #include <linux/delay.h>
@@ -297,7 +36,9 @@
X #include <linux/stat.h>
X #include <linux/mca.h>
X #include <asm/system.h>
+#ifndef OLDKERN
X #include <asm/spinlock.h>
+#endif
X #include <asm/io.h>
X #include "sd.h"
X #include "scsi.h"
@@ -306,199 +47,29 @@
X
X #include <linux/config.h> /* for CONFIG_SCSI_IBMMCA etc. */
X
-/*--------------------------------------------------------------------*/
-
-/* current version of this driver-source: */
-#define IBMMCA_SCSI_DRIVER_VERSION "3.0f"
-
-/* use standard Linux ordering, where C: maps to (0,0), unlike the IBM
-standard which seems to like C: => (6,0) */
-/* #define IBMMCA_SCSI_ORDER_STANDARD is defined/undefined in Config.in
- * now, while configuring the kernel. */
+/******************* LOCAL DEFINES *******************************************/
X
-/*
- Driver Description
-
- (A) Subsystem Detection
- This is done in the ibmmca_detect() function and is easy, since
- the information about MCA integrated subsystems and plug-in
- adapters is readily available in structure *mca_info.
-
- (B) Physical Units, Logical Units, and Logical Devices
- There can be up to 56 devices on SCSI bus (besides the adapter):
- there are up to 7 "physical units" (each identified by physical unit
- number or pun, also called the scsi id, this is the number you select
- with hardware jumpers), and each physical unit can have up to 8
- "logical units" (each identified by logical unit number, or lun,
- between 0 and 7).
-
- Typically the adapter has pun=7, so puns of other physical units
- are between 0 and 6. Almost all physical units have only one
- logical unit, with lun=0. A CD-ROM jukebox would be an example of
- a physical unit with more than one logical unit.
-
- The embedded microprocessor of IBM SCSI subsystem hides the complex
- two-dimensional (pun,lun) organization from the operating system.
- When the machine is powered-up (or rebooted, I am not sure), the
- embedded microprocessor checks, on it own, all 56 possible (pun,lun)
- combinations, and first 15 devices found are assigned into a
- one-dimensional array of so-called "logical devices", identified by
- "logical device numbers" or ldn. The last ldn=15 is reserved for
- the subsystem itself.
-
- One consequence of information hiding is that the real (pun,lun)
- numbers are also hidden. Therefore this driver takes the following
- approach: It checks the ldn's (0 to 6) to find out which ldn's
- have devices assigned. This is done by function check_devices() and
- device_exists(). The interrupt handler has a special paragraph of code
- (see local_checking_phase_flag) to assist in the checking. Assume, for
- example, that three logical devices were found assigned at ldn 0, 1, 2.
- These are presented to the upper layer of Linux SCSI driver
- as devices with bogus (pun, lun) equal to (0,0), (1,0), (2,0).
- On the other hand, if the upper layer issues a command to device
- say (4,0), this driver returns DID_NO_CONNECT error.
-
- That last paragraph is no longer correct, but is left for
- historical purposes. It limited the number of devices to 7, far
- fewer than the 15 that it could use. Now it just maps
- ldn -> (ldn/8,ldn%8). We end up with a real mishmash of puns
- and luns, but it all seems to work. - Chris Beaurgard
-
- And that last paragraph is also no longer correct. It uses a
- slightly more complex mapping that will always map hard disks to
- (x,0), for some x, and consecutive none disk devices will usually
- share puns.
-
- Again, the last paragraphs are no longer correct. Now, the physical
- SCSI-devices on the SCSI-bus are probed via immediate_assign- and
- device_inquiry-commands. This delivers a exact map of the physical
- SCSI-world that is now stored in the get_scsi[][]-array. This means,
- that the once hidden pun,lun assignment is now known to this driver.
- It no longer believes in default-settings of the subsystem and maps all
- ldns to existing pun,lun by foot. This assures full control of the ldn
- mapping and allows dynamical remapping of ldns to different pun,lun, if
- there are more SCSI-devices installed than ldns available (n>15). The
- ldns from 0 to 6 get 'hardwired' by this driver to puns 0 to 7 at lun=0,
- excluding the pun of the subsystem. This assures, that at least simple
- SCSI-installations have optimum access-speed and are not touched by
- dynamical remapping. The ldns 7 to 14 are put to existing devices with
- lun>0 or to non-existing devices, in order to satisfy the subsystem, if
- there are less than 15 SCSI-devices connected. In the case of more than 15
- devices, the dynamical mapping goes active. If the get_scsi[][] reports a
- device to be existant, but it has no ldn assigned, it gets a ldn out of 7
- to 14. The numbers are assigned in cyclic order. Therefore it takes 8
- dynamical assignments on SCSI-devices, until a certain device
- looses its ldn again. This assures, that dynamical remapping is avoided
- during intense I/O between up to eight SCSI-devices (means pun,lun
- combinations). A further advantage of this method is, that people who
- build their kernel without probing on all luns will get what they expect.
-
- IMPORTANT: Because of the now correct recognition of physical pun,lun, and
- their report to mid-level- and higher-level-drivers, the new reported puns
- can be different from the old, faked puns. Therefore, Linux will eventually
- change /dev/sdXXX assignments and prompt you for corrupted superblock
- repair on boottime. In this case DO NOT PANIC, YOUR DISKS ARE STILL OK!!!
- You have to reboot (CTRL-D) with a old kernel and set the /etc/fstab-file
- entries right. After that, the system should come up as errorfree as before.
- If your boot-partition is not coming up, also edit the /etc/lilo.conf-file
- in a Linux session booted on old kernel and run lilo before reboot. Check
- lilo.conf anyway to get boot on other partitions with foreign OSes right
- again.
-
- The problem is, that Linux does not assign the SCSI-devices in the
- way as described in the ANSI-SCSI-standard. Linux assigns /dev/sda to
- the device with at minimum id 0. But the first drive should be at id 6,
- because for historical reasons, drive at id 6 has, by hardware, the highest
- priority and a drive at id 0 the lowest. IBM was one of the rare producers,
- where the BIOS assigns drives belonging to the ANSI-SCSI-standard. Most
- other producers' BIOS does not (I think even Adaptec-BIOS). The
- IBMMCA_SCSI_ORDER_STANDARD flag helps to be able to choose the preferred
- way of SCSI-device-assignment. Defining this flag would result in Linux
- determining the devices in the same order as DOS and OS/2 does on your
- MCA-machine. This is also standard on most industrial computers. Leaving
- this flag undefined will get your devices ordered in the default way of
- Linux. See also the remarks of Chris Beauregard from Dec 15, 1997 and
- the followups.
-
- (C) Regular Processing
- Only three functions get involved: ibmmca_queuecommand(), issue_cmd(),
- and interrupt_handler().
-
- The upper layer issues a scsi command by calling function
- ibmmca_queuecommand(). This function fills a "subsystem control block"
- (scb) and calls a local function issue_cmd(), which writes a scb
- command into subsystem I/O ports. Once the scb command is carried out,
- interrupt_handler() is invoked. If a device is determined to be existant
- and it has not assigned any ldn, it gets one dynamically.
-
- (D) Abort, Reset.
- These are implemented with busy waiting for interrupt to arrive.
- The abort does not worked well for me, so I instead call the
- ibmmca_reset() from the ibmmca_abort() function.
-
- (E) Disk Geometry
- The ibmmca_biosparams() function should return same disk geometry
- as bios. This is needed for fdisk, etc. The returned geometry is
- certainly correct for disk smaller than 1 gigabyte, but I am not
- 100% sure that it is correct for larger disks.
-
- (F) Kernel Boot Option
- The function ibmmca_scsi_setup() is called if option ibmmcascsi=n
- is passed to the kernel. See file linux/init/main.c for details.
-
- (G) Driver Module Support
- Is implemented and tested by K. Kudielka. This could probably not work
- on kernels <2.1.0.
-
- (H) Multiple Hostadapter Support
- This driver supports up to eight interfaces of type IBM-SCSI-Subsystem.
- Integrated-, and MCA-adapters are automatically recognized. Unrecognizable
- IBM-SCSI-Subsystem interfaces can be specified as kernel-parameters.
-
- (I) /proc-Filesystem Information
- Information about the driver condition is given in
- /proc/scsi/ibmmca/<host_no>. ibmmca_proc_info provides this information.
- */
+#ifndef mdelay
+#define mdelay(a) udelay((a) * 1000)
+#endif
X
X /*--------------------------------------------------------------------*/
-/* Here are the values and structures specific for the subsystem.
- * The source of information is "Update for the PS/2 Hardware
- * Interface Technical Reference, Common Interfaces", September 1991,
- * part number 04G3281, available in the U.S. for $21.75 at
- * 1-800-IBM-PCTB, elsewhere call your local friendly IBM
- * representative.
- * In addition to SCSI subsystem, this update contains fairly detailed
- * (at hardware register level) sections on diskette controller,
- * keyboard controller, serial port controller, VGA, and XGA.
- *
- * Additional information from "Personal System/2 Micro Channel SCSI
- * Adapter with Cache Technical Reference", March 1990, PN 68X2365,
- * probably available from the same source (or possibly found buried
- * in officemates desk).
- *
- * Further literature/program-sources referred for this driver:
- *
- * Friedhelm Schmidt, "SCSI-Bus und IDE-Schnittstelle - Moderne Peripherie-
- * Schnittstellen: Hardware, Protokollbeschreibung und Anwendung", 2. Aufl.
- * Addison Wesley, 1996.
- *
- * Michael K. Johnson, "The Linux Kernel Hackers' Guide", Version 0.6, Chapel
- * Hill - North Carolina, 1995
- *
- * Andreas Kaiser, "SCSI TAPE BACKUP for OS/2 2.0", Version 2.12, Stuttgart
- * 1993
- */
+
+/* current version of this driver-source: */
+#define IBMMCA_SCSI_DRIVER_VERSION "3.1e"
X
X /*--------------------------------------------------------------------*/
X
X /* driver configuration */
X #define IM_MAX_HOSTS 8 /* maximum number of host adapters */
-#define IM_RESET_DELAY 10 /* seconds allowed for a reset */
+#define IM_RESET_DELAY 60 /* seconds allowed for a reset */
X
X /* driver debugging - #undef all for normal operation */
X
X /* if defined: count interrupts and ignore this special one: */
X #undef IM_DEBUG_TIMEOUT 50
+#define TIMEOUT_PUN 0
+#define TIMEOUT_LUN 0
X /* verbose interrupt: */
X #undef IM_DEBUG_INT
X /* verbose queuecommand: */
@@ -512,11 +83,11 @@
X #define IM_DEBUG_CMD_DEVICE TYPE_TAPE
X
X /* relative addresses of hardware registers on a subsystem */
-#define IM_CMD_REG (shpnt->io_port) /*Command Interface, (4 bytes long) */
-#define IM_ATTN_REG (shpnt->io_port+4) /*Attention (1 byte) */
-#define IM_CTR_REG (shpnt->io_port+5) /*Basic Control (1 byte) */
-#define IM_INTR_REG (shpnt->io_port+6) /*Interrupt Status (1 byte, r/o) */
-#define IM_STAT_REG (shpnt->io_port+7) /*Basic Status (1 byte, read only) */
+#define IM_CMD_REG(hi) (hosts[(hi)]->io_port) /*Command Interface, (4 bytes long) */
+#define IM_ATTN_REG(hi) (hosts[(hi)]->io_port+4) /*Attention (1 byte) */
+#define IM_CTR_REG(hi) (hosts[(hi)]->io_port+5) /*Basic Control (1 byte) */
+#define IM_INTR_REG(hi) (hosts[(hi)]->io_port+6) /*Interrupt Status (1 byte, r/o) */
+#define IM_STAT_REG(hi) (hosts[(hi)]->io_port+7) /*Basic Status (1 byte, read only) */
X
X /* basic I/O-port of first adapter */
X #define IM_IO_PORT 0x3540
@@ -668,9 +239,15 @@
X
X /* use_display is set by the ibmmcascsi=display command line arg */
X static int use_display = 0;
+/* use_adisplay is set by ibmmcascsi=adisplay, which offers a higher
+ * level of displayed luxus on PS/2 95 (really fancy! :-))) */
+static int use_adisplay = 0;
+
X #define PS2_DISK_LED_ON(ad,id) {\
X if( use_display ) { outb((char)(id+48), MOD95_LED_PORT ); \
X outb((char)(ad+48), MOD95_LED_PORT+1); } \
+ else if( use_adisplay ) { if (id<7) outb((char)(id+48), \
+ MOD95_LED_PORT+1+id); outb((char)(ad+48), MOD95_LED_PORT); } \
X else outb(inb(PS2_SYS_CTR) | 0xc0, PS2_SYS_CTR); \
X }
X
@@ -678,6 +255,11 @@
X #define PS2_DISK_LED_OFF() {\
X if( use_display ) { outb( ' ', MOD95_LED_PORT ); \
X outb(' ', MOD95_LED_PORT+1); } \
+ if ( use_adisplay ) { outb(' ',MOD95_LED_PORT ); \
+ outb(' ',MOD95_LED_PORT+1); outb(' ',MOD95_LED_PORT+2); \
+ outb(' ',MOD95_LED_PORT+3); outb(' ',MOD95_LED_PORT+4); \
+ outb(' ',MOD95_LED_PORT+5); outb(' ',MOD95_LED_PORT+6); \
+ outb(' ',MOD95_LED_PORT+7); } \
X else outb(inb(PS2_SYS_CTR) & 0x3f, PS2_SYS_CTR); \
X }
X
@@ -693,18 +275,20 @@
X /* List of possible IBM-SCSI-adapters */
X struct subsys_list_struct subsys_list[] =
X {
- {0x8efc, "IBM Fast SCSI-2 Adapter"},
- {0x8efd, "IBM 7568 Industrial Computer SCSI Adapter w/cache"},
- {0x8ef8, "IBM Expansion Unit SCSI Controller"},
- {0x8eff, "IBM SCSI Adapter w/Cache"},
- {0x8efe, "IBM SCSI Adapter"},
-};
+ {0x8efc, "IBM Fast SCSI-2 Adapter"}, /* special = 0 */
+ {0x8efd, "IBM 7568 Industrial Computer SCSI Adapter w/cache"}, /* special = 1 */
+ {0x8ef8, "IBM Expansion Unit SCSI Controller"},/* special = 2 */
+ {0x8eff, "IBM SCSI Adapter w/Cache"}, /* special = 3 */
+ {0x8efe, "IBM SCSI Adapter"}, /* special = 4 */
+};
X
X /*for /proc filesystem */
X struct proc_dir_entry proc_scsi_ibmmca =
X {
X PROC_SCSI_IBMMCA, 6, "ibmmca",
- S_IFDIR | S_IRUGO | S_IXUGO, 2
+ S_IFDIR | S_IRUGO | S_IXUGO, 2,
+ 0, 0, 0, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL
X };
X
X /* Max number of logical devices (can be up from 0 to 14). 15 is the address
@@ -715,8 +299,9 @@
X struct logical_device
X {
X struct im_scb scb; /* SCSI-subsystem-control-block structure */
- struct im_tsb tsb;
- struct im_sge sge[16];
+ struct im_tsb tsb; /* SCSI command complete status block structure */
+ struct im_sge sge[16]; /* scatter gather list structure */
+ unsigned char buf[256]; /* SCSI command return data buffer */
X Scsi_Cmnd *cmd; /* SCSI-command that is currently in progress */
X
X int device_type; /* type of the SCSI-device. See include/scsi/scsi.h
@@ -736,6 +321,7 @@
X int total_accesses; /* total accesses on all ldns */
X int total_interrupts; /* total interrupts (should be
X same as total_accesses) */
+ int total_errors; /* command completed with error */
X /* dynamical assignment statistics */
X int total_scsi_devices; /* number of physical pun,lun */
X int dyn_flag; /* flag showing dynamical mode */
@@ -747,44 +333,54 @@
X /* data structure for each host adapter */
X struct ibmmca_hostdata
X {
- /* array of logical devices: */
- struct logical_device _ld[MAX_LOG_DEV];
- /* array to convert (pun, lun) into logical device number: */
- unsigned char _get_ldn[8][8];
- /*array that contains the information about the physical SCSI-devices
- attached to this host adapter: */
- unsigned char _get_scsi[8][8];
- /* used only when checking logical devices: */
- int _local_checking_phase_flag;
- /* report received interrupt: */
- int _got_interrupt;
- /* report termination-status of SCSI-command: */
- int _stat_result;
- /* reset status (used only when doing reset): */
- int _reset_status;
- /* code of the last SCSI command (needed for panic info): */
- int _last_scsi_command;
- /* Counter that points on the next reassignable ldn for dynamical
- remapping. The default value is 7, that is the first reassignable
- number in the list at boottime: */
- int _next_ldn;
- /* Statistics-structure for this IBM-SCSI-host: */
- struct Driver_Statistics _IBM_DS;
+ /* array of logical devices: */
+ struct logical_device _ld[MAX_LOG_DEV+1];
+ /* array to convert (pun, lun) into logical device number: */
+ unsigned char _get_ldn[8][8];
+ /*array that contains the information about the physical SCSI-devices
+ attached to this host adapter: */
+ unsigned char _get_scsi[8][8];
+ /* used only when checking logical devices: */
+ int _local_checking_phase_flag;
+ /* report received interrupt: */
+ int _got_interrupt;
+ /* report termination-status of SCSI-command: */
+ int _stat_result;
+ /* reset status (used only when doing reset): */
+ int _reset_status;
+ /* code of the last SCSI command (needed for panic info): */
+ int _last_scsi_command[MAX_LOG_DEV+1];
+ /* identifier of the last SCSI-command type */
+ int _last_scsi_type[MAX_LOG_DEV+1];
+ /* Counter that points on the next reassignable ldn for dynamical
+ remapping. The default value is 7, that is the first reassignable
+ number in the list at boottime: */
+ int _next_ldn;
+ /* Statistics-structure for this IBM-SCSI-host: */
+ struct Driver_Statistics _IBM_DS;
+ /* This hostadapters pos-registers pos2 and pos3 */
+ unsigned _pos2, _pos3;
+ /* assign a special variable, that contains dedicated info about the
+ adaptertype */
+ int _special;
X };
X
X /* macros to access host data structure */
-#define HOSTDATA(shpnt) ((struct ibmmca_hostdata *) shpnt->hostdata)
-#define subsystem_pun (shpnt->this_id)
-#define ld (HOSTDATA(shpnt)->_ld)
-#define get_ldn (HOSTDATA(shpnt)->_get_ldn)
-#define get_scsi (HOSTDATA(shpnt)->_get_scsi)
-#define local_checking_phase_flag (HOSTDATA(shpnt)->_local_checking_phase_flag)
-#define got_interrupt (HOSTDATA(shpnt)->_got_interrupt)
-#define stat_result (HOSTDATA(shpnt)->_stat_result)
-#define reset_status (HOSTDATA(shpnt)->_reset_status)
-#define last_scsi_command (HOSTDATA(shpnt)->_last_scsi_command)
-#define next_ldn (HOSTDATA(shpnt)->_next_ldn)
-#define IBM_DS (HOSTDATA(shpnt)->_IBM_DS)
+#define subsystem_pun(hi) (hosts[(hi)]->this_id)
+#define ld(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_ld)
+#define get_ldn(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_get_ldn)
+#define get_scsi(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_get_scsi)
+#define local_checking_phase_flag(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_local_checking_phase_flag)
+#define got_interrupt(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_got_interrupt)
+#define stat_result(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_stat_result)
+#define reset_status(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_reset_status)
+#define last_scsi_command(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_last_scsi_command)
+#define last_scsi_type(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_last_scsi_type)
+#define next_ldn(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_next_ldn)
+#define IBM_DS(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_IBM_DS)
+#define special(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_special)
+#define pos2(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_pos2)
+#define pos3(hi) (((struct ibmmca_hostdata *) hosts[(hi)]->hostdata)->_pos3)
X
X /* Define a arbitrary number as subsystem-marker-type. This number is, as
X described in the ANSI-SCSI-standard, not occupied by other device-types. */
@@ -805,11 +401,23 @@
X #define SET_LDN 0
X #define REMOVE_LDN 1
X
+/* ldn which is used to probe the SCSI devices */
+#define PROBE_LDN 0
+
X /* reset status flag contents */
-#define IM_RESET_NOT_IN_PROGRESS 0
-#define IM_RESET_IN_PROGRESS 1
-#define IM_RESET_FINISHED_OK 2
-#define IM_RESET_FINISHED_FAIL 3
+#define IM_RESET_NOT_IN_PROGRESS 0
+#define IM_RESET_IN_PROGRESS 1
+#define IM_RESET_FINISHED_OK 2
+#define IM_RESET_FINISHED_FAIL 3
+#define IM_RESET_NOT_IN_PROGRESS_NO_INT 4
+#define IM_RESET_FINISHED_OK_NO_INT 5
+
+/* special flags for hostdata structure */
+#define FORCED_DETECTION 100
+#define INTEGRATED_SCSI 101
+
+/* define undefined SCSI-command */
+#define NO_SCSI 0xffff
X
X /*-----------------------------------------------------------------------*/
X
@@ -823,277 +431,517 @@
X MODULE_PARM(io_port, "1-" __MODULE_STRING(IM_MAX_HOSTS) "i");
X MODULE_PARM(scsi_id, "1-" __MODULE_STRING(IM_MAX_HOSTS) "i");
X MODULE_PARM(display, "1i");
+MODULE_PARM(adisplay, "1i");
+MODULE_PARM(bypass, "1i");
+MODULE_PARM(normal, "1i");
+MODULE_PARM(ansi, "1i");
X #endif
X
X /*counter of concurrent disk read/writes, to turn on/off disk led */
X static int disk_rw_in_progress = 0;
X
+/* spinlock handling to avoid command clash while in operation */
+#ifndef OLDKERN
+spinlock_t info_lock = SPIN_LOCK_UNLOCKED;
+spinlock_t proc_lock = SPIN_LOCK_UNLOCKED;
+spinlock_t abort_lock = SPIN_LOCK_UNLOCKED;
+spinlock_t reset_lock = SPIN_LOCK_UNLOCKED;
+spinlock_t issue_lock = SPIN_LOCK_UNLOCKED;
+spinlock_t intr_lock = SPIN_LOCK_UNLOCKED;
+#endif
+
X /* host information */
X static int found = 0;
X static struct Scsi_Host *hosts[IM_MAX_HOSTS+1] = { NULL };
+static unsigned int pos[8]; /* whole pos register-line */
+/* Taking into account the additions, made by ZP Gu.
+ * This selects now the preset value from the configfile and
+ * offers the 'normal' commandline option to be accepted */
+#ifdef CONFIG_IBMMCA_SCSI_ORDER_STANDARD
+static char ibm_ansi_order = 1;
+#else
+static char ibm_ansi_order = 0;
+#endif
+
X /*-----------------------------------------------------------------------*/
X
-/*local functions in forward declaration */
-static void interrupt_handler (int irq, void *dev_id, struct pt_regs *regs);
-static void do_interrupt_handler (int irq, void *dev_id, struct pt_regs *regs);
-static void issue_cmd (struct Scsi_Host *shpnt, unsigned long cmd_reg,
- unsigned char attn_reg);
+/******************* FUNCTIONS IN FORWARD DECLARATION ************************/
+
+static void interrupt_handler (int, void *, struct pt_regs *);
+#ifndef OLDKERN
+static void do_interrupt_handler (int, void *, struct pt_regs *);
+#endif
+static void issue_cmd (int, unsigned long, unsigned char);
X static void internal_done (Scsi_Cmnd * cmd);
-static void check_devices (struct Scsi_Host *shpnt);
-static int immediate_assign(struct Scsi_Host *shpnt, unsigned int pun,
- unsigned int lun, unsigned int ldn,
- unsigned int operation);
-static int device_inquiry(struct Scsi_Host *shpnt, int ldn,
- unsigned char *buf);
-static char *ti_p(int value);
-static char *ti_l(int value);
-static int device_exists (struct Scsi_Host *shpnt, int ldn, int *block_length,


SHAR_EOF
true || echo 'restore of patch-2.2.8 failed'
fi

echo 'End of part 18'
echo 'File patch-2.2.8 is continued in part 19'
echo 19 > _shar_seq_.tmp

Thomas...@ciw.uni-karlsruhe.de

unread,
May 12, 1999, 3:00:00 AM5/12/99
to
Archive-name: v2.2/patch-2.2.8/part19

#!/bin/sh
# this is part 19 of a 33 - part archive


# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.8 continued
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 19; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.8'
else
echo 'x - continuing with patch-2.2.8'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.8' &&

- int *device_type);
-static struct Scsi_Host *ibmmca_register(Scsi_Host_Template * template,
- int port, int id);
+static void check_devices (int);
+static int immediate_assign(int, unsigned int, unsigned int, unsigned int,
+ unsigned int);
+#ifdef CONFIG_IBMMCA_SCSI_DEV_RESET
+static int immediate_reset(int, unsigned int);
+#endif
+static int device_inquiry(int, int);
+static int read_capacity(int, int);
+static char *ti_p(int);
+static char *ti_l(int);
+static int device_exists (int, int, int *, int *);
+static struct Scsi_Host *ibmmca_register(Scsi_Host_Template *,
+ int, int, char *);
X
X /* local functions needed for proc_info */
-static int ldn_access_load(struct Scsi_Host *shpnt, int ldn);
-static int ldn_access_total_read_write(struct Scsi_Host *shpnt);
+static int ldn_access_load(int, int);
+static int ldn_access_total_read_write(int);
X
+static int bypass_controller = 0; /* bypass integrated SCSI-cmd set flag */
X /*--------------------------------------------------------------------*/
X
-static void
-do_interrupt_handler (int irq, void *dev_id, struct pt_regs *regs)
+/******************* LOCAL FUNCTIONS IMPLEMENTATION *************************/
+
+#ifndef OLDKERN
+/* newer Kernels need the spinlock interrupt handler */
+static void do_interrupt_handler (int irq, void *dev_id, struct pt_regs *regs)
X {
X unsigned long flags;
X
X spin_lock_irqsave(&io_request_lock, flags);
X interrupt_handler(irq, dev_id, regs);
X spin_unlock_irqrestore(&io_request_lock, flags);
+ return;
X }
+#endif
X
-static void
-interrupt_handler (int irq, void *dev_id, struct pt_regs *regs)
+static void interrupt_handler (int irq, void *dev_id, struct pt_regs *regs)


X {
- int i = 0;

- struct Scsi_Host *shpnt;
- unsigned int intr_reg;
- unsigned int cmd_result;
- unsigned int ldn;
- unsigned long flags;
+ int host_index;
+ unsigned int intr_reg;
+ unsigned int cmd_result;
+ unsigned int ldn;
+ static unsigned long flags;
+ Scsi_Cmnd *cmd;
+ int errorflag;
+ int interror;
X
- /* search for one adapter-response on shared interrupt */
- do
- shpnt = hosts[i++];
- while (shpnt && !(inb(IM_STAT_REG) & IM_INTR_REQUEST));
-
- /* return if some other device on this IRQ caused the interrupt */
- if (!shpnt) return;
-
- /*get command result and logical device */
- intr_reg = inb (IM_INTR_REG);
- cmd_result = intr_reg & 0xf0;
- ldn = intr_reg & 0x0f;
-
- /*must wait for attention reg not busy, then send EOI to subsystem */
- save_flags(flags);
- while (1) {
- cli ();
- if (!(inb (IM_STAT_REG) & IM_BUSY))
- break;
- restore_flags(flags);
- }
- outb (IM_EOI | ldn, IM_ATTN_REG);
- restore_flags (flags);
-
- /*these should never happen (hw fails, or a local programming bug) */
- if (cmd_result == IM_ADAPTER_HW_FAILURE)
- panic ("IBM MCA SCSI: subsystem hardware failure. Last SCSI_CMD=0x%X. \n",
- last_scsi_command);
- if (cmd_result == IM_CMD_ERROR)
- panic ("IBM MCA SCSI: command error. Last SCSI_CMD=0x%X. \n",
- last_scsi_command);
- if (cmd_result == IM_SOFTWARE_SEQUENCING_ERROR)
- panic ("IBM MCA SCSI: software sequencing error. Last SCSI_CMD=0x%X. \n",
- last_scsi_command);
-
- /* if no panic appeared, increase the interrupt-counter */
- IBM_DS.total_interrupts++;
-
- /*only for local checking phase */
- if (local_checking_phase_flag)
- {
- stat_result = cmd_result;
- got_interrupt = 1;
- reset_status = IM_RESET_FINISHED_OK;
- return;
- }
-
- /*handling of commands coming from upper level of scsi driver */
- else
- {
- Scsi_Cmnd *cmd;
-
- /*verify ldn, and may handle rare reset immediate command */
- if (ldn >= MAX_LOG_DEV)
- {
- if (ldn == 0xf && reset_status == IM_RESET_IN_PROGRESS)
- {
- if (cmd_result == IM_CMD_COMPLETED_WITH_FAILURE)
- {
- reset_status = IM_RESET_FINISHED_FAIL;
- }
- else
- {
- /*reset disk led counter, turn off disk led */
- disk_rw_in_progress = 0;
- PS2_DISK_LED_OFF ();
- reset_status = IM_RESET_FINISHED_OK;
- }


- return;
- }
- else

- panic ("IBM MCA SCSI: invalid logical device number.\n");
- }
+ host_index=0; /* make sure, host_index is 0, else this won't work and
+ never dare to ask, what happens, if an interrupt-handler
+ does not work :-((( .... */
+
+ /* search for one adapter-response on shared interrupt */
+ while (hosts[host_index]
+ && !(inb(IM_STAT_REG(host_index)) & IM_INTR_REQUEST))
+ host_index++;
+
+ /* return if some other device on this IRQ caused the interrupt */
+ if (!hosts[host_index]) return;
X
-#ifdef IM_DEBUG_TIMEOUT
- {
- static int count = 0;
+ /* the reset-function already did all the job, even ints got
+ renabled on the subsystem, so just return */
+ if ((reset_status(host_index) == IM_RESET_NOT_IN_PROGRESS_NO_INT)||
+ (reset_status(host_index) == IM_RESET_FINISHED_OK_NO_INT))
+ {
+ reset_status(host_index) = IM_RESET_NOT_IN_PROGRESS;
+ return;
+ }
+
+ /*get command result and logical device */
+ intr_reg = inb (IM_INTR_REG(host_index));
+ cmd_result = intr_reg & 0xf0;
+ ldn = intr_reg & 0x0f;
X
- if (++count == IM_DEBUG_TIMEOUT) {
- printk("IBM MCA SCSI: Ignoring interrupt.\n");
- return;
- }
- }
+ /*must wait for attention reg not busy, then send EOI to subsystem */
+ while (1)
+ {
+#ifdef OLDKERN
+ save_flags(flags);
+ cli();
+#else
+ spin_lock_irqsave(&intr_lock, flags);
+#endif
+ if (!(inb (IM_STAT_REG(host_index)) & IM_BUSY))
+ break;
+#ifdef OLDKERN
+ restore_flags(flags);
+#else
+ spin_unlock_irqrestore(&intr_lock, flags);
X #endif
+ }
+ outb (IM_EOI | ldn, IM_ATTN_REG(host_index));
+ /* get the last_scsi_command here */
+ interror = last_scsi_command(host_index)[ldn];
+#ifdef OLDKERN
+ restore_flags(flags);
+#else
+ spin_unlock_irqrestore(&intr_lock, flags);
+#endif
+ errorflag = 0; /* no errors by default */
+ /*these should never happen (hw fails, or a local programming bug) */
+ if (cmd_result == IM_ADAPTER_HW_FAILURE)


+ {
+ printk("\n");

+ printk("IBM MCA SCSI: ERROR - subsystem hardware failure!\n");
+ printk(" Last SCSI-command=0x%X, ldn=%d, host=%d.\n",
+ last_scsi_command(host_index)[ldn],ldn,host_index);
+ errorflag = 1;
+ }
+ if (cmd_result == IM_SOFTWARE_SEQUENCING_ERROR)


+ {
+ printk("\n");

+ printk("IBM MCA SCSI: ERROR - software sequencing error!\n");
+ printk(" Last SCSI-command=0x%X, ldn=%d, host=%d.\n",
+ last_scsi_command(host_index)[ldn],ldn,host_index);
+ errorflag = 1;
+ }
+ if (cmd_result == IM_CMD_ERROR)


+ {
+ printk("\n");

+ printk("IBM MCA SCSI: ERROR - command error!\n");
+ printk(" Last SCSI-command=0x%X, ldn=%d, host=%d.\n",
+ last_scsi_command(host_index)[ldn],ldn,host_index);
+ errorflag = 1;
+ }
+ if (errorflag)
+ { /* if errors appear, enter this section to give detailed info */
+ printk("IBM MCA SCSI: Subsystem Error-Status follows:\n");
+ printk(" Command Type................: %x\n",
+ last_scsi_type(host_index)[ldn]);
+ printk(" Attention Register..........: %x\n",
+ inb (IM_ATTN_REG(host_index)));
+ printk(" Basic Control Register......: %x\n",
+ inb (IM_CTR_REG(host_index)));
+ printk(" Interrupt Status Register...: %x\n",
+ intr_reg);
+ printk(" Basic Status Register.......: %x\n",
+ inb (IM_STAT_REG(host_index)));
+ if ((last_scsi_type(host_index)[ldn]==IM_SCB)||
+ (last_scsi_type(host_index)[ldn]==IM_LONG_SCB))
+ {
+ printk(" SCB End Status Word.........: %x\n",
+ ld(host_index)[ldn].tsb.end_status);
+ printk(" Command Status..............: %x\n",
+ ld(host_index)[ldn].tsb.cmd_status);
+ printk(" Device Status...............: %x\n",
+ ld(host_index)[ldn].tsb.dev_status);
+ printk(" Command Error...............: %x\n",
+ ld(host_index)[ldn].tsb.cmd_error);
+ printk(" Device Error................: %x\n",
+ ld(host_index)[ldn].tsb.dev_error);
+ printk(" Last SCB Address (LSW)......: %x\n",
+ ld(host_index)[ldn].tsb.low_of_last_scb_adr);
+ printk(" Last SCB Address (MSW)......: %x\n",
+ ld(host_index)[ldn].tsb.high_of_last_scb_adr);
+ }
+ printk(" Send report to the maintainer.\n");
+ panic("IBM MCA SCSI: Fatal errormessage from the subsystem!\n");
+ }
+
+ /* if no panic appeared, increase the interrupt-counter */
+ IBM_DS(host_index).total_interrupts++;
X
- /*if no command structure, just return, else clear cmd */
- cmd = ld[ldn].cmd;
- if (!cmd)
+ /*only for local checking phase */
+ if (local_checking_phase_flag(host_index))
+ {
+ stat_result(host_index) = cmd_result;
+ got_interrupt(host_index) = 1;
+ reset_status(host_index) = IM_RESET_FINISHED_OK;
+ last_scsi_command(host_index)[ldn] = NO_SCSI;
X return;
- ld[ldn].cmd = 0;
-
+ }
+ /*handling of commands coming from upper level of scsi driver */
+ else
+ {
+ if (last_scsi_type(host_index)[ldn] == IM_IMM_CMD)
+ {
+ /*verify ldn, and may handle rare reset immediate command */
+ if ((reset_status(host_index) == IM_RESET_IN_PROGRESS)&&
+ (last_scsi_command(host_index)[ldn] == IM_RESET_IMM_CMD))
+ {
+ if (cmd_result == IM_CMD_COMPLETED_WITH_FAILURE)
+ {
+ disk_rw_in_progress = 0;
+ PS2_DISK_LED_OFF ();
+ reset_status(host_index) = IM_RESET_FINISHED_FAIL;
+ }
+ else
+ {
+ /*reset disk led counter, turn off disk led */
+ disk_rw_in_progress = 0;
+ PS2_DISK_LED_OFF ();
+ reset_status(host_index) = IM_RESET_FINISHED_OK;
+ }
+ stat_result(host_index) = cmd_result;
+ last_scsi_command(host_index)[ldn] = NO_SCSI;
+ return;
+ }
+ else if (last_scsi_command(host_index)[ldn] == IM_ABORT_IMM_CMD)
+ { /* react on SCSI abort command */
+#ifdef IM_DEBUG_PROBE
+ printk("IBM MCA SCSI: Interrupt from SCSI-abort.\n");
+#endif
+ disk_rw_in_progress = 0;
+ PS2_DISK_LED_OFF();
+ cmd = ld(host_index)[ldn].cmd;
+ if (cmd_result == IM_CMD_COMPLETED_WITH_FAILURE)
+ cmd->result = DID_NO_CONNECT << 16;
+ else
+ cmd->result = DID_ABORT << 16;
+ stat_result(host_index) = cmd_result;
+ last_scsi_command(host_index)[ldn] = NO_SCSI;
+ if (cmd->scsi_done)
+ (cmd->scsi_done) (cmd); /* should be the internal_done */
+ return;
+ }
+ else
+ {
+ disk_rw_in_progress = 0;
+ PS2_DISK_LED_OFF ();
+ reset_status(host_index) = IM_RESET_FINISHED_OK;
+ stat_result(host_index) = cmd_result;
+ last_scsi_command(host_index)[ldn] = NO_SCSI;
+ return;
+ }
+ }
+ last_scsi_command(host_index)[ldn] = NO_SCSI;
+ cmd = ld(host_index)[ldn].cmd;
+#ifdef IM_DEBUG_TIMEOUT
+ if (cmd)
+ {
+ if ((cmd->target == TIMEOUT_PUN)&&(cmd->lun == TIMEOUT_LUN))
+ {
+ printk("IBM MCA SCSI: Ignoring interrupt from pun=%x, lun=%x.\n",
+ cmd->target, cmd->lun);
+ return;
+ }
+ }
+#endif
+ /*if no command structure, just return, else clear cmd */
+ if (!cmd)
+ return;
+ ld(host_index)[ldn].cmd = NULL;
+
X #ifdef IM_DEBUG_INT
- printk("cmd=%02x ireg=%02x ds=%02x cs=%02x de=%02x ce=%02x\n",
- cmd->cmnd[0], intr_reg,
- ld[ldn].tsb.dev_status, ld[ldn].tsb.cmd_status,
- ld[ldn].tsb.dev_error, ld[ldn].tsb.cmd_error);
-#endif
-
- /*if this is end of media read/write, may turn off PS/2 disk led */
- if ((ld[ldn].device_type!=TYPE_NO_LUN)&&
- (ld[ldn].device_type!=TYPE_NO_DEVICE))
- { /* only access this, if there was a valid device addressed */
- switch (cmd->cmnd[0])
- {
- case READ_6:
- case WRITE_6:
- case READ_10:
- case WRITE_10:
- case READ_12:
- case WRITE_12:
- if (--disk_rw_in_progress == 0)
- PS2_DISK_LED_OFF ();
- }
- }
-
- /*write device status into cmd->result, and call done function */
- if (cmd_result == IM_CMD_COMPLETED_WITH_FAILURE)
- cmd->result = ld[ldn].tsb.dev_status & 0x1e;
- else
- cmd->result = 0;
- (cmd->scsi_done) (cmd);
- }
-}
-
-/*--------------------------------------------------------------------*/
-
-static void
-issue_cmd (struct Scsi_Host *shpnt, unsigned long cmd_reg,
- unsigned char attn_reg)


-{
- unsigned long flags;

- /*must wait for attention reg not busy */
- save_flags(flags);
- while (1)
- {
- cli ();
- if (!(inb (IM_STAT_REG) & IM_BUSY))
- break;
- restore_flags (flags);
- }
+ printk("cmd=%02x ireg=%02x ds=%02x cs=%02x de=%02x ce=%02x\n",
+ cmd->cmnd[0], intr_reg,
+ ld(host_index)[ldn].tsb.dev_status,
+ ld(host_index)[ldn].tsb.cmd_status,
+ ld(host_index)[ldn].tsb.dev_error,
+ ld(host_index)[ldn].tsb.cmd_error);
+#endif
+
+ /*if this is end of media read/write, may turn off PS/2 disk led */
+ if ((ld(host_index)[ldn].device_type!=TYPE_NO_LUN)&&
+ (ld(host_index)[ldn].device_type!=TYPE_NO_DEVICE))
+ { /* only access this, if there was a valid device addressed */
+ switch (cmd->cmnd[0])
+ {
+ case READ_6:
+ case WRITE_6:
+ case READ_10:
+ case WRITE_10:
+ case READ_12:
+ case WRITE_12:
+ if (--disk_rw_in_progress == 0)
+ PS2_DISK_LED_OFF ();
+ }
+ }
X
- /*write registers and enable system interrupts */
- outl (cmd_reg, IM_CMD_REG);
- outb (attn_reg, IM_ATTN_REG);
- restore_flags (flags);
+ /* IBM describes the status-mask to be 0x1e, but this is not conform
+ * with SCSI-defintion, I suppose, it is a printing error in the
+ * technical reference and assume as mask 0x3e. (ML) */
+ cmd->result = (ld(host_index)[ldn].tsb.dev_status & 0x3e);
+ /* write device status into cmd->result, and call done function */
+ if (cmd_result == IM_CMD_COMPLETED_WITH_FAILURE)
+ IBM_DS(host_index).total_errors++;
+ if (interror == NO_SCSI) /* unexpected interrupt :-( */
+ cmd->result |= DID_BAD_INTR << 16;
+ else
+ cmd->result |= DID_OK << 16;
+ (cmd->scsi_done) (cmd);
+ }
+ if (interror == NO_SCSI)
+ printk("IBM MCA SCSI: WARNING - Interrupt from non-pending SCSI-command!\n");
+ return;
X }
X
X /*--------------------------------------------------------------------*/
X
-static void
-internal_done (Scsi_Cmnd * cmd)
+static void issue_cmd (int host_index, unsigned long cmd_reg,
+ unsigned char attn_reg)
X {
- cmd->SCp.Status++;
+ static unsigned long flags;
+ /* must wait for attention reg not busy */
+ while (1)
+ {
+#ifdef OLDKERN
+ save_flags(flags);
+ cli();
+#else
+ spin_lock_irqsave(&issue_lock, flags);
+#endif
+ if (!(inb (IM_STAT_REG(host_index)) & IM_BUSY))
+ break;
+#ifdef OLDKERN
+ restore_flags(flags);
+#else
+ spin_unlock_irqrestore(&issue_lock, flags);
+#endif
+ }
+ /*write registers and enable system interrupts */
+ outl (cmd_reg, IM_CMD_REG(host_index));
+ outb (attn_reg, IM_ATTN_REG(host_index));
+#ifdef OLDKERN
+ restore_flags(flags);
+#else
+ spin_unlock_irqrestore(&issue_lock, flags);
+#endif
X }
X
X /*--------------------------------------------------------------------*/
X
-static int ibmmca_getinfo (char *buf, int slot, void *dev)
+static void internal_done (Scsi_Cmnd * cmd)
X {
- struct Scsi_Host *shpnt = dev;
- int len = 0;
-
- len += sprintf (buf + len, "Subsystem PUN: %d\n", subsystem_pun);
- len += sprintf (buf + len, "I/O base address: 0x%lx\n", IM_CMD_REG);
- return len;
+ cmd->SCp.Status++;
X }
X
X /*--------------------------------------------------------------------*/
X
X /* SCSI-SCB-command for device_inquiry */
-static int device_inquiry(struct Scsi_Host *shpnt, int ldn, unsigned char *buf)
+static int device_inquiry(int host_index, int ldn)
X {
- struct im_scb scb;
- struct im_tsb tsb;
- int retries;
-
- for (retries = 0; retries < 3; retries++)
- {
- /*fill scb with inquiry command */
- scb.command = IM_DEVICE_INQUIRY_CMD;
- scb.enable = IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT;
- scb.sys_buf_adr = virt_to_bus(buf);
- scb.sys_buf_length = 255;
- scb.tsb_adr = virt_to_bus(&tsb);
-
- /*issue scb to passed ldn, and busy wait for interrupt */
- got_interrupt = 0;
- issue_cmd (shpnt, virt_to_bus(&scb), IM_SCB | ldn);
- while (!got_interrupt)
- barrier ();
-
- /*if command succesful, break */
- if (stat_result == IM_SCB_CMD_COMPLETED)
- break;
- }
+ int retries;
+ Scsi_Cmnd cmd;
+ struct im_scb *scb;
+ struct im_tsb *tsb;
+ unsigned char *buf;
+
+ scb = &(ld(host_index)[ldn].scb);
+ tsb = &(ld(host_index)[ldn].tsb);
+ buf = (unsigned char *)(&(ld(host_index)[ldn].buf));
+ ld(host_index)[ldn].tsb.dev_status = 0; /* prepare stusblock */
+
+ if (bypass_controller)
+ { /* fill the commonly known field for device-inquiry SCSI cmnd */
+ cmd.cmd_len = 6;
+ memset (&(cmd.cmnd), 0x0, sizeof(char) * cmd.cmd_len);
+ cmd.cmnd[0] = INQUIRY; /* device inquiry */
+ cmd.cmnd[4] = 0xff; /* return buffer size = 255 */
+ }
+ for (retries = 0; retries < 3; retries++)
+ {
+ if (bypass_controller)
+ { /* bypass the hardware integrated command set */
+ scb->command = IM_OTHER_SCSI_CMD_CMD;
+ scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT;
+ scb->u1.scsi_cmd_length = cmd.cmd_len;
+ memcpy (scb->u2.scsi_command, &(cmd.cmnd), cmd.cmd_len);
+ last_scsi_command(host_index)[ldn] = INQUIRY;
+ last_scsi_type(host_index)[ldn] = IM_SCB;
+ }
+ else
+ {
+ /*fill scb with inquiry command */
+ scb->command = IM_DEVICE_INQUIRY_CMD;
+ scb->enable = IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT;
+ last_scsi_command(host_index)[ldn] = IM_DEVICE_INQUIRY_CMD;
+ last_scsi_type(host_index)[ldn] = IM_SCB;
+ }
+ scb->sys_buf_adr = virt_to_bus(buf);
+ scb->sys_buf_length = 0xff; /* maximum bufferlength gives max info */
+ scb->tsb_adr = virt_to_bus(tsb);
+
+ /*issue scb to passed ldn, and busy wait for interrupt */
+ got_interrupt(host_index) = 0;
+ issue_cmd (host_index, virt_to_bus(scb), IM_SCB | ldn);
+ while (!got_interrupt(host_index))
+ barrier ();
+
+ /*if command succesful, break */
+ if ((stat_result(host_index) == IM_SCB_CMD_COMPLETED)||
+ (stat_result(host_index) == IM_SCB_CMD_COMPLETED_WITH_RETRIES))
+ {


+ return 1;
+ }
+ }
+

+ /*if all three retries failed, return "no device at this ldn" */
+ if (retries >= 3)


+ return 0;
+ else

+ return 1;
+}
X
- /*if all three retries failed, return "no device at this ldn" */
- if (retries >= 3)
- return 0;
- else
- return 1;
+static int read_capacity(int host_index, int ldn)
+{
+ int retries;
+ Scsi_Cmnd cmd;
+ struct im_scb *scb;
+ struct im_tsb *tsb;
+ unsigned char *buf;
+
+ scb = &(ld(host_index)[ldn].scb);
+ tsb = &(ld(host_index)[ldn].tsb);
+ buf = (unsigned char *)(&(ld(host_index)[ldn].buf));
+ ld(host_index)[ldn].tsb.dev_status = 0;
+
+ if (bypass_controller)
+ { /* read capacity in commonly known default SCSI-format */
+ cmd.cmd_len = 10;
+ memset (&(cmd.cmnd), 0x0, sizeof(char) * cmd.cmd_len);
+ cmd.cmnd[0] = READ_CAPACITY; /* read capacity */
+ }
+ for (retries = 0; retries < 3; retries++)
+ {
+ /*fill scb with read capacity command */
+ if (bypass_controller)
+ { /* bypass the SCSI-command */
+ scb->command = IM_OTHER_SCSI_CMD_CMD;
+ scb->enable |= IM_READ_CONTROL;
+ scb->u1.scsi_cmd_length = cmd.cmd_len;
+ memcpy (scb->u2.scsi_command, &(cmd.cmnd), cmd.cmd_len);
+ last_scsi_command(host_index)[ldn] = READ_CAPACITY;
+ last_scsi_type(host_index)[ldn] = IM_SCB;
+ }
+ else
+ {
+ scb->command = IM_READ_CAPACITY_CMD;
+ scb->enable = IM_READ_CONTROL;
+ last_scsi_command(host_index)[ldn] = IM_READ_CAPACITY_CMD;
+ last_scsi_type(host_index)[ldn] = IM_SCB;
+ }
+ scb->sys_buf_adr = virt_to_bus(buf);
+ scb->sys_buf_length = 8;
+ scb->tsb_adr = virt_to_bus(tsb);
+
+ /*issue scb to passed ldn, and busy wait for interrupt */
+ got_interrupt(host_index) = 0;
+ issue_cmd (host_index, virt_to_bus(scb), IM_SCB | ldn);
+ while (!got_interrupt(host_index))
+ barrier ();
+
+ /*if got capacity, get block length and return one device found */
+ if ((stat_result(host_index) == IM_SCB_CMD_COMPLETED)||
+ (stat_result(host_index) == IM_SCB_CMD_COMPLETED_WITH_RETRIES))
+ {


+ return 1;
+ }
+ }

+ /*if all three retries failed, return "no device at this ldn" */
+ if (retries >= 3)


+ return 0;
+ else

+ return 1;
X }
X
X /* SCSI-immediate-command for assign. This functions maps/unmaps specific
- ldn-numbers on SCSI (PUN,LUN). It is needed for presetting of the
- subsystem and for dynamical remapping od ldns. */


-static int immediate_assign(struct Scsi_Host *shpnt, unsigned int pun,

+ ldn-numbers on SCSI (PUN,LUN). It is needed for presetting of the
+ subsystem and for dynamical remapping od ldns. */
+static int immediate_assign(int host_index, unsigned int pun,
X unsigned int lun, unsigned int ldn,
X unsigned int operation)
X {
X int retries;
X unsigned long imm_command;
-
+
X for (retries=0; retries<3; retries ++)
- {
- imm_command = inl(IM_CMD_REG);
+ {
+ imm_command = inl(IM_CMD_REG(host_index));
X imm_command &= (unsigned long)(0xF8000000); /* keep reserved bits */
X imm_command |= (unsigned long)(IM_ASSIGN_IMM_CMD);
X imm_command |= (unsigned long)((lun & 7) << 24);
@@ -1101,14 +949,64 @@
X imm_command |= (unsigned long)((pun & 7) << 20);
X imm_command |= (unsigned long)((ldn & 15) << 16);
X
- got_interrupt = 0;
- issue_cmd (shpnt, (unsigned long)(imm_command), IM_IMM_CMD | 0xf);
- while (!got_interrupt)
- barrier ();
-
+ last_scsi_command(host_index)[0xf] = IM_ASSIGN_IMM_CMD;
+ last_scsi_type(host_index)[0xf] = IM_IMM_CMD;
+ got_interrupt(host_index) = 0;
+ issue_cmd (host_index, (unsigned long)(imm_command), IM_IMM_CMD | 0xf);
+ while (!got_interrupt(host_index))
+ barrier ();
+
+ /*if command succesful, break */
+ if (stat_result(host_index) == IM_IMMEDIATE_CMD_COMPLETED)
+ {


+ return 1;
+ }
+ }
+

+ if (retries >= 3)

+ return 0;
+ else

+ return 1;
+}
+

+#ifdef CONFIG_IBMMCA_SCSI_DEV_RESET
+static int immediate_reset(int host_index, unsigned int ldn)
+{
+ int retries;
+ int ticks;
+ unsigned long imm_command;
+
+ for (retries=0; retries<3; retries ++)
+ {
+ imm_command = inl(IM_CMD_REG(host_index));
+ imm_command &= (unsigned long)(0xFFFF0000); /* keep reserved bits */
+ imm_command |= (unsigned long)(IM_RESET_IMM_CMD);
+ last_scsi_command(host_index)[ldn] = IM_RESET_IMM_CMD;
+ last_scsi_type(host_index)[ldn] = IM_IMM_CMD;
+
+ got_interrupt(host_index) = 0;
+ reset_status(host_index) = IM_RESET_IN_PROGRESS;
+ issue_cmd (host_index, (unsigned long)(imm_command), IM_IMM_CMD | ldn);
+ ticks = IM_RESET_DELAY*HZ;
+ while (reset_status(host_index) == IM_RESET_IN_PROGRESS && --ticks)
+ {
+ mdelay(1+999/HZ);
+ barrier();
+ }
+ /* if reset did not complete, just claim */
+ if (!ticks)
+ {
+ printk("IBM MCA SCSI: reset did not complete within %d seconds.\n",
+ IM_RESET_DELAY);
+ reset_status(host_index) = IM_RESET_FINISHED_OK;
+ /* did not work, finish */
+ return 1;
+ }
X /*if command succesful, break */
- if (stat_result == IM_IMMEDIATE_CMD_COMPLETED)
- break;
+ if (stat_result(host_index) == IM_IMMEDIATE_CMD_COMPLETED)


+ {
+ return 1;
+ }

X }
X
X if (retries >= 3)
@@ -1116,24 +1014,25 @@
X else
X return 1;
X }
+#endif
X
X /* type-interpreter for physical device numbers */
X static char *ti_p(int value)
X {
X switch (value)
X {
- case TYPE_IBM_SCSI_ADAPTER: return("A"); break;
- case TYPE_DISK: return("D"); break;
- case TYPE_TAPE: return("T"); break;
- case TYPE_PROCESSOR: return("P"); break;
- case TYPE_WORM: return("W"); break;
- case TYPE_ROM: return("R"); break;
- case TYPE_SCANNER: return("S"); break;
- case TYPE_MOD: return("M"); break;
- case TYPE_MEDIUM_CHANGER: return("C"); break;
- case TYPE_NO_LUN: return("+"); break; /* show NO_LUN */
- case TYPE_NO_DEVICE:
- default: return("-"); break;
+ case TYPE_IBM_SCSI_ADAPTER: return("A"); break;
+ case TYPE_DISK: return("D"); break;
+ case TYPE_TAPE: return("T"); break;
+ case TYPE_PROCESSOR: return("P"); break;
+ case TYPE_WORM: return("W"); break;
+ case TYPE_ROM: return("R"); break;
+ case TYPE_SCANNER: return("S"); break;
+ case TYPE_MOD: return("M"); break;
+ case TYPE_MEDIUM_CHANGER: return("C"); break;
+ case TYPE_NO_LUN: return("+"); break; /* show NO_LUN */
+ case TYPE_NO_DEVICE:
+ default: return("-"); break;
X }
X return("-");
X }
@@ -1141,9 +1040,9 @@
X /* interpreter for logical device numbers (ldn) */
X static char *ti_l(int value)
X {
- const char hex[16] = ("0123456789abcdef");
+ const char hex[16] = "0123456789abcdef";
X static char answer[2];
-
+
X answer[1] = (char)(0x0);
X if (value<=MAX_LOG_DEV)
X answer[0] = hex[value];
@@ -1154,182 +1053,181 @@
X }
X
X /*
- The following routine probes the SCSI-devices in four steps:
- 1. The current ldn -> pun,lun mapping is removed on the SCSI-adapter.
- 2. ldn 0 is used to go through all possible combinations of pun,lun and
- a device_inquiry is done to fiddle out whether there is a device
- responding or not. This physical map is stored in get_scsi[][].
- 3. The 15 available ldns (0-14) are mapped to existing pun,lun.
- If there are more devices than ldns, it stops at 14 for the boot
- time. Dynamical remapping will be done in ibmmca_queuecommand.
- 4. If there are less than 15 valid pun,lun, the remaining ldns are
- mapped to NON-existing pun,lun to satisfy the adapter. Information
- about pun,lun -> ldn is stored as before in get_ldn[][].
- This method leads to the result, that the SCSI-pun,lun shown to Linux
- mid-level- and higher-level-drivers is exactly corresponding to the
- physical reality on the SCSI-bus. Therefore, it is possible that users
- of older releases of this driver have to rewrite their fstab-file, because
- the /dev/sdXXX could have changed due to the right pun,lun report, now.
- The assignment of ALL ldns avoids dynamical remapping by the adapter
- itself.
+ The following routine probes the SCSI-devices in four steps:
+ 1. The current ldn -> pun,lun mapping is removed on the SCSI-adapter.
+ 2. ldn 0 is used to go through all possible combinations of pun,lun and
+ a device_inquiry is done to fiddle out whether there is a device
+ responding or not. This physical map is stored in get_scsi[][].
+ 3. The 15 available ldns (0-14) are mapped to existing pun,lun.
+ If there are more devices than ldns, it stops at 14 for the boot
+ time. Dynamical remapping will be done in ibmmca_queuecommand.
+ 4. If there are less than 15 valid pun,lun, the remaining ldns are
+ mapped to NON-existing pun,lun to satisfy the adapter. Information
+ about pun,lun -> ldn is stored as before in get_ldn[][].
+ This method leads to the result, that the SCSI-pun,lun shown to Linux
+ mid-level- and higher-level-drivers is exactly corresponding to the
+ physical reality on the SCSI-bus. Therefore, it is possible that users
+ of older releases of this driver have to rewrite their fstab-file, because
+ the /dev/sdXXX could have changed due to the right pun,lun report, now.
+ The assignment of ALL ldns avoids dynamical remapping by the adapter
+ itself.
X */


-static void check_devices (struct Scsi_Host *shpnt)

+static void check_devices (int host_index)
X {
- int id, lun, ldn;
- unsigned char buf[256];
- int count_devices = 0; /* local counter for connected device */
-
- /* assign default values to certain variables */
-
- IBM_DS.dyn_flag = 0; /* normally no need for dynamical ldn management */
- next_ldn = 7; /* next ldn to be assigned is 7, because 0-6 is 'hardwired'*/
- last_scsi_command = 0; /* emptify last SCSI-command storage */
-
- /* initialize the very important driver-informational arrays/structs */
- memset (ld, 0, sizeof ld);
- memset (get_ldn, TYPE_NO_DEVICE, sizeof get_ldn); /* this is essential ! */
- memset (get_scsi, TYPE_NO_DEVICE, sizeof get_scsi); /* this is essential ! */
-
- for (lun=0; lun<8; lun++) /* mark the adapter at its pun on all luns*/
- {
- get_scsi[subsystem_pun][lun] = TYPE_IBM_SCSI_ADAPTER;
- get_ldn[subsystem_pun][lun] = MAX_LOG_DEV; /* make sure, the subsystem
- ldn is active for all
- luns. */
- }
-
- /* STEP 1: */
- printk("IBM MCA SCSI: Removing current logical SCSI-device mapping.");
- for (ldn=0; ldn<MAX_LOG_DEV; ldn++)
- {
+ int id, lun, ldn, ticks;
+ int count_devices; /* local counter for connected device */
+
+ /* assign default values to certain variables */
+
+ ticks = 0;
+ count_devices = 0;
+ IBM_DS(host_index).dyn_flag = 0; /* normally no need for dynamical ldn management */
+ IBM_DS(host_index).total_errors = 0; /* set errorcounter to 0 */
+ next_ldn(host_index) = 7; /* next ldn to be assigned is 7, because 0-6 is 'hardwired'*/
+ for (ldn=0; ldn<=MAX_LOG_DEV; ldn++)
+ {
+ last_scsi_command(host_index)[ldn] = NO_SCSI; /* emptify last SCSI-command storage */
+ last_scsi_type(host_index)[ldn] = 0;
+ }
+
+ /* initialize the very important driver-informational arrays/structs */
+ memset (ld(host_index), 0,
+ sizeof(ld(host_index)));
+ memset (get_ldn(host_index), TYPE_NO_DEVICE,
+ sizeof(get_ldn(host_index))); /* this is essential ! */
+ memset (get_scsi(host_index), TYPE_NO_DEVICE,
+ sizeof(get_scsi(host_index))); /* this is essential ! */
+
+ for (lun=0; lun<8; lun++) /* mark the adapter at its pun on all luns*/
+ {
+ get_scsi(host_index)[subsystem_pun(host_index)][lun] = TYPE_IBM_SCSI_ADAPTER;
+ get_ldn(host_index)[subsystem_pun(host_index)][lun] = MAX_LOG_DEV; /* make sure, the subsystem
+ ldn is active for all
+ luns. */
+ }
+
+ /* STEP 1: */
X #ifdef IM_DEBUG_PROBE
- printk(".");
+ printk("IBM MCA SCSI: Current SCSI-host index: %d\n",host_index);
X #endif
- immediate_assign(shpnt,0,0,ldn,REMOVE_LDN); /* remove ldn (wherever)*/
- }
-
- lun = 0; /* default lun is 0 */
+ printk("IBM MCA SCSI: Removing default logical SCSI-device mapping.");
+ for (ldn=0; ldn<MAX_LOG_DEV; ldn++)
+ {
+#ifdef IM_DEBUG_PROBE
+ printk(".");
+#endif
+ immediate_assign(host_index,0,0,ldn,REMOVE_LDN); /* remove ldn (wherever)*/
+ }
X
- /* STEP 2: */
- printk("\nIBM MCA SCSI: Probing SCSI-devices.");
- for (id=0; id<8; id++)
+ lun = 0; /* default lun is 0 */
+
+ /* STEP 2: */
+ printk("\nIBM MCA SCSI: Probing SCSI-devices.");
+ for (id=0; id<8; id++)
X #ifdef CONFIG_SCSI_MULTI_LUN
- for (lun=0; lun<8; lun++)
+ for (lun=0; lun<8; lun++)
X #endif
- {
+ {
X #ifdef IM_DEBUG_PROBE
X printk(".");
X #endif
- if (id != subsystem_pun)
+ if (id != subsystem_pun(host_index))
X { /* if pun is not the adapter: */
- immediate_assign(shpnt,id,lun,0,SET_LDN); /*set ldn=0 to pun,lun*/
- if (device_inquiry(shpnt, 0, buf)) /* probe device */
- {
- get_scsi[id][lun]=(unsigned char)buf[0]; /* entry, even
- for NO_LUN */
- if (buf[0] != TYPE_NO_LUN)
- count_devices++; /* a existing device is found */
- }
- immediate_assign(shpnt,id,lun,0,REMOVE_LDN); /* remove ldn */
+ /*set ldn=0 to pun,lun*/
+ immediate_assign(host_index,id,lun,PROBE_LDN,SET_LDN);
+ if (device_inquiry(host_index, PROBE_LDN)) /* probe device */
+ {
+ get_scsi(host_index)[id][lun]=
+ (unsigned char)(ld(host_index)[PROBE_LDN].buf[0]);
+ /* entry, even for NO_LUN */
+ if (ld(host_index)[PROBE_LDN].buf[0] != TYPE_NO_LUN)
+ count_devices++; /* a existing device is found */
+ }
+ /* remove ldn */
+ immediate_assign(host_index,id,lun,PROBE_LDN,REMOVE_LDN);
X }
- }
-
- /* STEP 3: */
- printk("\nIBM MCA SCSI: Mapping SCSI-devices.");
+ }
+
+ /* STEP 3: */
+ printk("\nIBM MCA SCSI: Mapping SCSI-devices.");
+
+ ldn = 0;
+ lun = 0;
X
- ldn = 0;
- lun = 0;
-
X #ifdef CONFIG_SCSI_MULTI_LUN
- for (lun=0; lun<8 && ldn<MAX_LOG_DEV; lun++)
+ for (lun=0; lun<8 && ldn<MAX_LOG_DEV; lun++)
X #endif
- for (id=0; id<8 && ldn<MAX_LOG_DEV; id++)
- {
+ for (id=0; id<8 && ldn<MAX_LOG_DEV; id++)
+ {
X #ifdef IM_DEBUG_PROBE
X printk(".");
X #endif
- if (id != subsystem_pun)
+ if (id != subsystem_pun(host_index))
X {
- if (get_scsi[id][lun] != TYPE_NO_LUN &&
- get_scsi[id][lun] != TYPE_NO_DEVICE)
- {
- /* Only map if accepted type. Always enter for
+ if (get_scsi(host_index)[id][lun] != TYPE_NO_LUN &&
+ get_scsi(host_index)[id][lun] != TYPE_NO_DEVICE)
+ {
+ /* Only map if accepted type. Always enter for
X lun == 0 to get no gaps into ldn-mapping for ldn<7. */
- immediate_assign(shpnt,id,lun,ldn,SET_LDN);
- get_ldn[id][lun]=ldn; /* map ldn */
- if (device_exists (shpnt, ldn, &ld[ldn].block_length,
- &ld[ldn].device_type))
- {
+ immediate_assign(host_index,id,lun,ldn,SET_LDN);
+ get_ldn(host_index)[id][lun]=ldn; /* map ldn */
+ if (device_exists (host_index, ldn,
+ &ld(host_index)[ldn].block_length,
+ &ld(host_index)[ldn].device_type))
+ {
X #ifdef CONFIG_IBMMCA_SCSI_DEV_RESET
- int ticks;
- printk("(resetting)");
- ticks = IM_RESET_DELAY*HZ;
- reset_status = IM_RESET_IN_PROGRESS;
- issue_cmd (shpnt, IM_RESET_IMM_CMD, IM_IMM_CMD | ldn);
- while (reset_status == IM_RESET_IN_PROGRESS && --ticks)
- {
- mdelay(1+999/HZ);
- barrier();
- }
- /* if reset did not complete, just claim */
- if (!ticks)
- {
- printk("IBM MCA SCSI: reset did not complete within %d seconds.\n",
- IM_RESET_DELAY);
- reset_status = IM_RESET_FINISHED_OK;
- /* did not work, finish */
- }
-#endif
- ldn++;
- }
- else
- {
- /* device vanished, probably because we don't know how to
- * handle it or because it has problems */
- if (lun > 0)
- {
- /* remove mapping */
- get_ldn[id][lun]=TYPE_NO_DEVICE;
- immediate_assign(shpnt,0,0,ldn,REMOVE_LDN);
- }
- else ldn++;
- }
- }
- else if (lun == 0)
- {
- /* map lun == 0, even if no device exists */
- immediate_assign(shpnt,id,lun,ldn,SET_LDN);
- get_ldn[id][lun]=ldn; /* map ldn */
- ldn++;
- }
+ printk("resetting device at ldn=%x ... ",ldn);
+ immediate_reset(host_index,ldn);
+#endif
+ ldn++;
+ }
+ else
+ {
+ /* device vanished, probably because we don't know how to
+ * handle it or because it has problems */
+ if (lun > 0)
+ {
+ /* remove mapping */
+ get_ldn(host_index)[id][lun]=TYPE_NO_DEVICE;
+ immediate_assign(host_index,0,0,ldn,REMOVE_LDN);
+ }
+ else ldn++;
+ }
+ }
+ else if (lun == 0)
+ {
+ /* map lun == 0, even if no device exists */
+ immediate_assign(host_index,id,lun,ldn,SET_LDN);
+ get_ldn(host_index)[id][lun]=ldn; /* map ldn */
+ ldn++;
+ }
X }
- }
-
+ }
+
X /* STEP 4: */
X
X /* map remaining ldns to non-existing devices */
X for (lun=1; lun<8 && ldn<MAX_LOG_DEV; lun++)
X for (id=0; id<8 && ldn<MAX_LOG_DEV; id++)
X {
- if (get_scsi[id][lun] == TYPE_NO_LUN ||
- get_scsi[id][lun] == TYPE_NO_DEVICE)
+ if (get_scsi(host_index)[id][lun] == TYPE_NO_LUN ||
+ get_scsi(host_index)[id][lun] == TYPE_NO_DEVICE)
X {
X /* Map remaining ldns only to NON-existing pun,lun
- combinations to make sure an inquiry will fail.
- For MULTI_LUN, it is needed to avoid adapter autonome
- SCSI-remapping. */
- immediate_assign(shpnt,id,lun,ldn,SET_LDN);
- get_ldn[id][lun]=ldn;
+ combinations to make sure an inquiry will fail.
+ For MULTI_LUN, it is needed to avoid adapter autonome
+ SCSI-remapping. */
+ immediate_assign(host_index,id,lun,ldn,SET_LDN);
+ get_ldn(host_index)[id][lun]=ldn;
X ldn++;
X }
X }
-
+
X printk("\n");
-#ifdef CONFIG_IBMMCA_SCSI_ORDER_STANDARD
- printk("IBM MCA SCSI: SCSI-access-order: IBM/ANSI.\n");
-#else
- printk("IBM MCA SCSI: SCSI-access-order: Linux.\n");
-#endif
+ if (ibm_ansi_order)
+ printk("IBM MCA SCSI: Device order: IBM/ANSI (pun=7 is first).\n");
+ else
+ printk("IBM MCA SCSI: Device order: New Industry Standard (pun=0 is first).\n");
X
X #ifdef IM_DEBUG_PROBE
X /* Show the physical and logical mapping during boot. */
@@ -1338,336 +1236,525 @@
X printk("ID\\LUN 0 1 2 3 4 5 6 7 ID\\LUN 0 1 2 3 4 5 6 7\n");
X for (id=0; id<8; id++)
X {
- printk("%2d %2s %2s %2s %2s %2s %2s %2s %2s",
- id, ti_p(get_scsi[id][0]), ti_p(get_scsi[id][1]),
- ti_p(get_scsi[id][2]), ti_p(get_scsi[id][3]),
- ti_p(get_scsi[id][4]), ti_p(get_scsi[id][5]),
- ti_p(get_scsi[id][6]), ti_p(get_scsi[id][7]));
-
- printk(" %2d ",id);
+ printk("%2d ",id);
+ for (lun=0; lun<8; lun++)
+ printk("%2s ",ti_p(get_scsi(host_index)[id][lun]));
+ printk(" %2d ",id);
X for (lun=0; lun<8; lun++)
- printk("%2s ",ti_l(get_ldn[id][lun]));
+ printk("%2s ",ti_l(get_ldn(host_index)[id][lun]));


X printk("\n");
X }

X #endif
-
+
X /* assign total number of found SCSI-devices to the statistics struct */
- IBM_DS.total_scsi_devices = count_devices;
-
+ IBM_DS(host_index).total_scsi_devices = count_devices;
+
X /* decide for output in /proc-filesystem, if the configuration of
- SCSI-devices makes dynamical reassignment of devices necessary */
+ SCSI-devices makes dynamical reassignment of devices necessary */
X if (count_devices>=MAX_LOG_DEV)
- IBM_DS.dyn_flag = 1; /* dynamical assignment is necessary */
+ IBM_DS(host_index).dyn_flag = 1; /* dynamical assignment is necessary */
X else
- IBM_DS.dyn_flag = 0; /* dynamical assignment is not necessary */
-
+ IBM_DS(host_index).dyn_flag = 0; /* dynamical assignment is not necessary */
+
X /* If no SCSI-devices are assigned, return 1 in order to cause message. */
X if (ldn == 0)
- printk("IBM MCA SCSI: Warning: No SCSI-devices found/assignable!\n");
-
- /* reset the counters for statistics on the current adapter */
- IBM_DS.total_accesses = 0;
- IBM_DS.total_interrupts = 0;
- IBM_DS.dynamical_assignments = 0;
- memset (IBM_DS.ldn_access, 0x0, sizeof (IBM_DS.ldn_access));
- memset (IBM_DS.ldn_read_access, 0x0, sizeof (IBM_DS.ldn_read_access));
- memset (IBM_DS.ldn_write_access, 0x0, sizeof (IBM_DS.ldn_write_access));
- memset (IBM_DS.ldn_inquiry_access, 0x0, sizeof (IBM_DS.ldn_inquiry_access));
- memset (IBM_DS.ldn_modeselect_access, 0x0, sizeof (IBM_DS.ldn_modeselect_access));
- memset (IBM_DS.ldn_assignments, 0x0, sizeof (IBM_DS.ldn_assignments));
+ printk("IBM MCA SCSI: Warning: No SCSI-devices found/assigned!\n");
X
- return;
-}
-
-/*--------------------------------------------------------------------*/
-
-static int
-device_exists (struct Scsi_Host *shpnt, int ldn, int *block_length,
- int *device_type)
-{
- struct im_scb scb;
- struct im_tsb tsb;
- unsigned char buf[256];
- int retries;
-
- /* if no valid device found, return immediately with 0 */
- if (!(device_inquiry(shpnt, ldn, buf))) return 0;
-
- /*if device is CD_ROM, assume block size 2048 and return */
- if (buf[0] == TYPE_ROM)
- {
- *device_type = TYPE_ROM;
- *block_length = 2048; /* (standard blocksize for yellow-/red-book) */
- return 1;
- }
-
- if (buf[0] == TYPE_WORM) /* CD-burner, WORM, Linux handles this as CD-ROM
- therefore, the block_length is also 2048. */
- {
- *device_type = TYPE_WORM;
- *block_length = 2048;
- return 1;
- }
-
- /* if device is disk, use "read capacity" to find its block size */
- if (buf[0] == TYPE_DISK)
- {
- *device_type = TYPE_DISK;
-
- for (retries = 0; retries < 3; retries++)
- {
- /*fill scb with read capacity command */
- scb.command = IM_READ_CAPACITY_CMD;
- scb.enable = IM_READ_CONTROL;
- scb.sys_buf_adr = virt_to_bus(buf);
- scb.sys_buf_length = 8;
- scb.tsb_adr = virt_to_bus(&tsb);
-
- /*issue scb to passed ldn, and busy wait for interrupt */
- got_interrupt = 0;
- issue_cmd (shpnt, virt_to_bus(&scb), IM_SCB | ldn);
- while (!got_interrupt)
- barrier ();
-
- /*if got capacity, get block length and return one device found */
- if (stat_result == IM_SCB_CMD_COMPLETED)
- {
- *block_length = buf[7] + (buf[6] << 8) + (buf[5] << 16) + (buf[4] << 24);
- return 1;
- }
- }
-
- /*if all three retries failed, return "no device at this ldn" */
- if (retries >= 3)
- return 0;
- }
-
- /* if this is a magneto-optical drive, treat it like a harddisk */
- if (buf[0] == TYPE_MOD)
- {
- *device_type = TYPE_MOD;
-
- for (retries = 0; retries < 3; retries++)
- {
- /*fill scb with read capacity command */
- scb.command = IM_READ_CAPACITY_CMD;
- scb.enable = IM_READ_CONTROL;
- scb.sys_buf_adr = virt_to_bus(buf);
- scb.sys_buf_length = 8;
- scb.tsb_adr = virt_to_bus(&tsb);
-
- /*issue scb to passed ldn, and busy wait for interrupt */
- got_interrupt = 0;
- issue_cmd (shpnt, virt_to_bus(&scb), IM_SCB | ldn);
- while (!got_interrupt)
- barrier ();
-
- /*if got capacity, get block length and return one device found */
- if (stat_result == IM_SCB_CMD_COMPLETED)
- {
- *block_length = buf[7] + (buf[6] << 8) + (buf[5] << 16) + (buf[4] << 24);
- return 1;
- }
- }
-
- /*if all three retries failed, return "no device at this ldn" */
- if (retries >= 3)
- return 0;
- }
+ /* reset the counters for statistics on the current adapter */
+ IBM_DS(host_index).total_accesses = 0;
+ IBM_DS(host_index).total_interrupts = 0;
+ IBM_DS(host_index).dynamical_assignments = 0;
+ memset (IBM_DS(host_index).ldn_access, 0x0,
+ sizeof (IBM_DS(host_index).ldn_access));
+ memset (IBM_DS(host_index).ldn_read_access, 0x0,
+ sizeof (IBM_DS(host_index).ldn_read_access));
+ memset (IBM_DS(host_index).ldn_write_access, 0x0,
+ sizeof (IBM_DS(host_index).ldn_write_access));
+ memset (IBM_DS(host_index).ldn_inquiry_access, 0x0,
+ sizeof (IBM_DS(host_index).ldn_inquiry_access));
+ memset (IBM_DS(host_index).ldn_modeselect_access, 0x0,
+ sizeof (IBM_DS(host_index).ldn_modeselect_access));
+ memset (IBM_DS(host_index).ldn_assignments, 0x0,
+ sizeof (IBM_DS(host_index).ldn_assignments));
X
- if (buf[0] == TYPE_TAPE) /* TAPE-device found */
- {
- *device_type = TYPE_TAPE;
- *block_length = 0; /* not in use (setting by mt and mtst in op.) */
- return 1;
- }
-
- if (buf[0] == TYPE_PROCESSOR) /* HP-Scanners, diverse SCSI-processing units*/
- {
- *device_type = TYPE_PROCESSOR;
- *block_length = 0; /* they set their stuff on drivers */
- return 1;
- }
-
- if (buf[0] == TYPE_SCANNER) /* other SCSI-scanners */
- {
- *device_type = TYPE_SCANNER;
- *block_length = 0; /* they set their stuff on drivers */
- return 1;
- }
-
- if (buf[0] == TYPE_MEDIUM_CHANGER) /* Medium-Changer */
- {
- *device_type = TYPE_MEDIUM_CHANGER;
- *block_length = 0; /* One never knows, what to expect on a medium
- changer device. */
- return 1;
- }
-
- /* Up to now, no SCSI-devices that are known up to kernel 2.1.31 are
- ignored! MO-drives are now supported and treated as harddisk. */
- return 0;
+ return;
X }
X
X /*--------------------------------------------------------------------*/
X
-#ifdef CONFIG_SCSI_IBMMCA
-
-void
-ibmmca_scsi_setup (char *str, int *ints)
+static int device_exists (int host_index, int ldn, int *block_length,
+ int *device_type)
X {
- if( str && !strcmp( str, "display" ) ) {
- use_display = 1;
- } else if( ints ) {
- int i;
- for (i = 0; i < IM_MAX_HOSTS && 2*i+2 < ints[0]; i++) {
- io_port[i] = ints[2*i+2];
- scsi_id[i] = ints[2*i+2];
- }
- }
-}
+ unsigned char *buf;
+
+ /* if no valid device found, return immediately with 0 */
+ if (!(device_inquiry(host_index, ldn)))
+ return 0;
+
+ buf = (unsigned char *)(&(ld(host_index)[ldn].buf));
X
-#endif
+ /*if device is CD_ROM, assume block size 2048 and return */
+ if (*buf == TYPE_ROM)
+ {
+ *device_type = TYPE_ROM;
+ *block_length = 2048; /* (standard blocksize for yellow-/red-book) */


+ return 1;
+ }
+

+ if (*buf == TYPE_WORM) /* CD-burner, WORM, Linux handles this as CD-ROM
+ therefore, the block_length is also 2048. */
+ {
+ *device_type = TYPE_WORM;
+ *block_length = 2048;


+ return 1;
+ }
+

+ /* if device is disk, use "read capacity" to find its block size */
+ if (*buf == TYPE_DISK)
+ {
+ *device_type = TYPE_DISK;
+ if (read_capacity( host_index, ldn))
+ {
+ *block_length = *(buf+7) + (*(buf+6) << 8) +
+ (*(buf+5) << 16) + (*(buf+4) << 24);
+ return 1;
+ }
+ else


+ return 0;
+ }
+

+ /* if this is a magneto-optical drive, treat it like a harddisk */
+ if (*buf == TYPE_MOD)
+ {
+ *device_type = TYPE_MOD;
+ if (read_capacity( host_index, ldn))
+ {
+ *block_length = *(buf+7) + (*(buf+6) << 8) +
+ (*(buf+5) << 16) + (*(buf+4) << 24);
+ return 1;
+ }
+ else


+ return 0;
+ }
+

+ if (*buf == TYPE_TAPE) /* TAPE-device found */
+ {
+ *device_type = TYPE_TAPE;
+ *block_length = 0; /* not in use (setting by mt and mtst in op.) */


+ return 1;
+ }
+

+ if (*buf == TYPE_PROCESSOR) /* HP-Scanners, diverse SCSI-processing units*/
+ {
+ *device_type = TYPE_PROCESSOR;
+ *block_length = 0; /* they set their stuff on drivers */


+ return 1;
+ }
+

+ if (*buf == TYPE_SCANNER) /* other SCSI-scanners */
+ {
+ *device_type = TYPE_SCANNER;
+ *block_length = 0; /* they set their stuff on drivers */


+ return 1;
+ }
+

+ if (*buf == TYPE_MEDIUM_CHANGER) /* Medium-Changer */
+ {
+ *device_type = TYPE_MEDIUM_CHANGER;
+ *block_length = 0; /* One never knows, what to expect on a medium
+ changer device. */


+ return 1;
+ }
+

+ /* Up to now, no SCSI-devices that are known up to kernel 2.1.31 are
+ ignored! MO-drives are now supported and treated as harddisk. */
+ return 0;
+}
X
X /*--------------------------------------------------------------------*/
+
+#ifdef CONFIG_SCSI_IBMMCA
X
-int
-ibmmca_detect (Scsi_Host_Template * template)
+void ibmmca_scsi_setup (char *str, int *ints)
X {
- struct Scsi_Host *shpnt;
- int port, id, i, list_size, slot;
- unsigned pos2, pos3;
-
- /* if this is not MCA machine, return "nothing found" */
- if (!MCA_bus)
- return 0;
-
- /* get interrupt request level */
- if (request_irq (IM_IRQ, do_interrupt_handler, SA_SHIRQ, "ibmmca", hosts))
- {
- printk("IBM MCA SCSI: Unable to get IRQ %d.\n", IM_IRQ);
- return 0;
- }
-
- /* if ibmmcascsi setup option was passed to kernel, return "found" */
- for (i = 0; i < IM_MAX_HOSTS; i++)
- if (io_port[i] > 0 && scsi_id[i] >= 0 && scsi_id[i] < 8)
- {
- printk("IBM MCA SCSI: forced detection, io=0x%x, scsi id=%d.\n",
- io_port[i], scsi_id[i]);
- ibmmca_register(template, io_port[i], scsi_id[i]);
- }
- if (found) return found;
+ int i, j, io_base, id_base;
+ char *token;
+
+ io_base = 0;
+ id_base = 0;
+
+ if (str)
+ {
+ token = strtok(str,",");
+ j = 0;
+ while (token)
+ {
+ if (!strcmp(token,"display"))
+ {
+ use_display = 1;
+ }
+ if (!strcmp(token,"adisplay"))
+ {
+ use_adisplay = 1;
+ }
+ if (!strcmp(token,"bypass"))
+ {
+ bypass_controller = 1;
+ }
+ if (!strcmp(token,"normal"))
+ {
+ ibm_ansi_order = 0;
+ }
+ if (!strcmp(token,"ansi"))
+ {
+ ibm_ansi_order = 1;
+ }
+ if ( (*token == '-') || (isdigit(*token)) )
+ {
+ if (!(j%2) && (io_base < IM_MAX_HOSTS))
+ {
+ io_port[io_base++] = simple_strtoul(token,NULL,0);
+ }
+ if ((j%2) && (id_base < IM_MAX_HOSTS))
+ {
+ scsi_id[id_base++] = simple_strtoul(token,NULL,0);
+ }
+ j++;
+ }
+ token = strtok(NULL,",");
+ }
+ }
+ else if (ints)
+ {
+ for (i = 0; i < IM_MAX_HOSTS && 2*i+2 < ints[0]; i++)
+ {
+ io_port[i] = ints[2*i+2];
+ scsi_id[i] = ints[2*i+2];


+ }
+ }
+ return;
+}

X
- /*
- * Patched by ZP Gu to work with the 9556 as well; the 9556 has
- * pos2 = 05, but it should be 00, as it should be interfaced
- * via port = 0x3540.
- */
-
- /* first look for the SCSI integrated on the motherboard */
- pos2 = mca_read_stored_pos(MCA_INTEGSCSI, 2);
-// if (pos2 != 0xff) {
- if ((pos2 & 1) == 0) {
- port = IM_IO_PORT + ((pos2 & 0x0e) << 2);
- } else {
- port = IM_IO_PORT;
- }
- pos3 = mca_read_stored_pos(MCA_INTEGSCSI, 3);
- id = (pos3 & 0xe0) >> 5;
-
- printk("IBM MCA SCSI: integrated SCSI found, io=0x%x, scsi id=%d.\n",
- port, id);
- if ((shpnt = ibmmca_register(template, port, id)))
- {
- mca_set_adapter_name(MCA_INTEGSCSI, "PS/2 Integrated SCSI");
- mca_set_adapter_procfn(MCA_INTEGSCSI, (MCA_ProcFn) ibmmca_getinfo,
- shpnt);
- }
-// }
-
- /* now look for other adapters */
- list_size = sizeof(subsys_list) / sizeof(struct subsys_list_struct);
- for (i = 0; i < list_size; i++)
- {
- slot = 0;
- while ((slot = mca_find_adapter(subsys_list[i].mca_id, slot))
- != MCA_NOTFOUND)
- {
- pos2 = mca_read_stored_pos(slot, 2);
- pos3 = mca_read_stored_pos(slot, 3);
- port = IM_IO_PORT + ((pos2 & 0x0e) << 2);
- id = (pos3 & 0xe0) >> 5;
- printk ("IBM MCA SCSI: %s found in slot %d, io=0x%x, scsi id=%d.\n",
- subsys_list[i].description, slot + 1, port, id);
- if ((shpnt = ibmmca_register(template, port, id)))
- {
- mca_set_adapter_name (slot, subsys_list[i].description);
- mca_set_adapter_procfn (slot, (MCA_ProcFn) ibmmca_getinfo,
- shpnt);
- }
- slot++;
- }
- }
-
- if (!found) {
- free_irq (IM_IRQ, hosts);
- printk("IBM MCA SCSI: No adapter attached.\n");
- }
+#endif
+
+/*--------------------------------------------------------------------*/
+
+static int ibmmca_getinfo (char *buf, int slot, void *dev)
+{
+ struct Scsi_Host *shpnt;
+ int len, special;
+ unsigned int pos2, pos3;
+ static unsigned long flags;
+
+#ifdef OLDKERN
+ save_flags(flags);
+ cli();
+#else
+ spin_lock_irqsave(&info_lock, flags);
+#endif
+
+ shpnt = dev; /* assign host-structure to local pointer */
+ len = 0; /* set filled text-buffer index to 0 */
+ /* get the _special contents of the hostdata structure */
+ special = ((struct ibmmca_hostdata *)shpnt->hostdata)->_special;
+ pos2 = ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos2;
+ pos3 = ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos3;
+
+ if (special == FORCED_DETECTION) /* forced detection */
+ {
+ len += sprintf (buf + len, "Adapter cathegory: forced detected\n");
+ len += sprintf(buf + len, "***************************************\n");
+ len += sprintf(buf + len, "*** Forced detected SCSI Adapter ***\n");
+ len += sprintf(buf + len, "*** No chip-information available ***\n");
+ len += sprintf(buf + len, "***************************************\n");
+ }
+ else if (special == INTEGRATED_SCSI)
+ { /* if the integrated subsystem has been found automatically: */
+ len += sprintf (buf + len, "Adapter cathegory: integrated\n");
+ len += sprintf (buf + len, "Chip revision level: %d\n",
+ ((pos2 & 0xf0) >> 4));
+ len += sprintf (buf + len, "Chip status: %s\n",
+ (pos2 & 1) ? "enabled" : "disabled");
+ len += sprintf (buf + len, "8 kByte NVRAM status: %s\n",
+ (pos2 & 2) ? "locked" : "accessible");
+ }
+ else if ((special>=0)&&
+ (special<(sizeof(subsys_list)/sizeof(struct subsys_list_struct))))
+ { /* if the subsystem is a slot adapter */
+ len += sprintf (buf + len, "Adapter cathegory: slot-card\n");
+ len += sprintf (buf + len, "Chip revision level: %d\n",
+ ((pos2 & 0xf0) >> 4));
+ len += sprintf (buf + len, "Chip status: %s\n",
+ (pos2 & 1) ? "enabled" : "disabled");
+ len += sprintf (buf + len, "Port offset: 0x%x\n",
+ ((pos2 & 0x0e) << 2));
+ }
+ else
+ {
+ len += sprintf (buf + len, "Adapter cathegory: unknown\n");
+ }
+ /* common subsystem information to write to the slotn file */
+ len += sprintf (buf + len, "Subsystem PUN: %d\n", shpnt->this_id);
+ len += sprintf (buf + len, "I/O base address range: 0x%x-0x%x",
+ (unsigned int)(shpnt->io_port),
+ (unsigned int)(shpnt->io_port+7));
+ /* Now make sure, the bufferlength is devideable by 4 to avoid
+ * paging problems of the buffer. */
+ while ( len % sizeof( int ) != ( sizeof ( int ) - 1 ) )
+ {
+ len += sprintf (buf + len, " ");
+ }
+ len += sprintf (buf + len, "\n");
X
- return found;
+#ifdef OLDKERN
+ restore_flags(flags);
+#else
+ spin_unlock_irqrestore(&info_lock, flags);
+#endif

+ return len;
+}
+

+int ibmmca_detect (Scsi_Host_Template * scsi_template)
+{
+ struct Scsi_Host *shpnt;
+ int port, id, i, j, list_size, slot;
+
+ found = 0; /* make absolutely sure, that found is set to 0 */
+
+ /* if this is not MCA machine, return "nothing found" */
+ if (!MCA_bus)
+ {
+ printk("IBM MCA SCSI: No Microchannel-bus support present -> Aborting.\n");
+ return 0;
+ }
+ else
+ printk("IBM MCA SCSI: Version %s\n",IBMMCA_SCSI_DRIVER_VERSION);
+
+ /* get interrupt request level */
+#ifdef OLDKERN
+ if (request_irq (IM_IRQ, interrupt_handler, SA_SHIRQ, "ibmmcascsi",
+ hosts))
+#else
+ if (request_irq (IM_IRQ, do_interrupt_handler, SA_SHIRQ, "ibmmcascsi",
+ hosts))
+#endif
+ {
+ printk("IBM MCA SCSI: Unable to get shared IRQ %d.\n", IM_IRQ);


+ return 0;
+ }
+

+ /* if ibmmcascsi setup option was passed to kernel, return "found" */
+ for (i = 0; i < IM_MAX_HOSTS; i++)
+ if (io_port[i] > 0 && scsi_id[i] >= 0 && scsi_id[i] < 8)
+ {
+ printk("IBM MCA SCSI: forced detected SCSI Adapter, io=0x%x, scsi id=%d.\n",
+ io_port[i], scsi_id[i]);
+ if ((shpnt = ibmmca_register(scsi_template, io_port[i], scsi_id[i],
+ "forced detected SCSI Adapter")))
+ {
+ ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos2 = 0;
+ ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos3 = 0;
+ ((struct ibmmca_hostdata *)shpnt->hostdata)->_special =
+ FORCED_DETECTION;
+ mca_set_adapter_name(MCA_INTEGSCSI, "forced detected SCSI Adapter");
+ mca_set_adapter_procfn(MCA_INTEGSCSI, (MCA_ProcFn) ibmmca_getinfo,
+ shpnt);
+ mca_mark_as_used(MCA_INTEGSCSI);
+ }
+ }
+ if (found) return found;
+
+ /* The POS2-register of all PS/2 model SCSI-subsystems has the following
+ * interpretation of bits:
+ * Bit 7 - 4 : Chip Revision ID (Release)
+ * Bit 3 - 2 : Reserved
+ * Bit 1 : 8k NVRAM Disabled
+ * Bit 0 : Chip Enable (EN-Signal)
+ * The POS3-register is interpreted as follows:
+ * Bit 7 - 5 : SCSI ID
+ * Bit 4 : Reserved = 0
+ * Bit 3 - 0 : Reserved = 0
+ * (taken from "IBM, PS/2 Hardware Interface Technical Reference, Common
+ * Interfaces (1991)").
+ * In short words, this means, that IBM PS/2 machines only support
+ * 1 single subsystem by default. The slot-adapters must have another
+ * configuration on pos2. Here, one has to assume the following
+ * things for POS2-register:
+ * Bit 7 - 4 : Chip Revision ID (Release)
+ * Bit 3 - 1 : port offset factor
+ * Bit 0 : Chip Enable (EN-Signal)
+ * As I found a patch here, setting the IO-registers to 0x3540 forced,
+ * as there was a 0x05 in POS2 on a model 56, I assume, that the
+ * port 0x3540 must be fix for integrated SCSI-controllers.
+ * Ok, this discovery leads to the following implementation: (M.Lang) */
+
+ /* first look for the IBM SCSI integrated subsystem on the motherboard */
+ for (j=0;j<8;j++) /* read the pos-information */
+ pos[j] = mca_read_stored_pos(MCA_INTEGSCSI,j);
+ /* pos2 = pos3 = 0xff if there is no integrated SCSI-subsystem present */


SHAR_EOF
true || echo 'restore of patch-2.2.8 failed'
fi

echo 'End of part 19'
echo 'File patch-2.2.8 is continued in part 20'
echo 20 > _shar_seq_.tmp

Thomas...@ciw.uni-karlsruhe.de

unread,
May 12, 1999, 3:00:00 AM5/12/99
to
Archive-name: v2.2/patch-2.2.8/part20

#!/bin/sh
# this is part 20 of a 33 - part archive


# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.8 continued
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 20; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.8'
else
echo 'x - continuing with patch-2.2.8'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.8' &&

+ if (( pos[2] != 0xff) || (pos[3] != 0xff ))
+ {
+ if ((pos[2] & 1) == 1) /* is the subsystem chip enabled ? */
+ {
+ port = IM_IO_PORT;
+ }
+ else
+ { /* if disabled, no IRQs will be generated, as the chip won't
+ * listen to the incomming commands and will do really nothing,
+ * except for listening to the pos-register settings. If this
+ * happens, I need to hugely think about it, as one has to
+ * write something to the MCA-Bus pos register in order to
+ * enable the chip. Normally, IBM-SCSI won't pass the POST,
+ * when the chip is disabled (see IBM tech. ref.). */
+ port = IM_IO_PORT; /* anyway, set the portnumber and warn */
+ printk("IBM MCA SCSI: WARNING - Your SCSI-subsystem is disabled!\n");
+ printk(" SCSI-operations may not work.\n");
+ }
+ id = (pos[3] & 0xe0) >> 5; /* this is correct and represents the PUN */
+
+ /* give detailed information on the subsystem. This helps me
+ * additionally during debugging and analyzing bug-reports. */
+ printk("IBM MCA SCSI: IBM Integrated SCSI Controller found, io=0x%x, scsi id=%d,\n",
+ port, id);
+ printk(" chip rev.=%d, 8K NVRAM=%s, subsystem=%s\n",
+ ((pos[2] & 0xf0) >> 4), (pos[2] & 2) ? "locked" : "accessible",
+ (pos[2] & 1) ? "enabled." : "disabled.");
+
+ /* register the found integrated SCSI-subsystem */
+ if ((shpnt = ibmmca_register(scsi_template, port, id,
+ "IBM Integrated SCSI Controller")))
+ {
+ ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos2 = pos[2];
+ ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos3 = pos[3];


+ ((struct ibmmca_hostdata *)shpnt->hostdata)->_special =

+ INTEGRATED_SCSI;
+ mca_set_adapter_name(MCA_INTEGSCSI, "IBM Integrated SCSI Controller");


+ mca_set_adapter_procfn(MCA_INTEGSCSI, (MCA_ProcFn) ibmmca_getinfo,
+ shpnt);
+ mca_mark_as_used(MCA_INTEGSCSI);
+ }
+ }
+

+ /* now look for other adapters in MCA slots, */
+ /* determine the number of known IBM-SCSI-subsystem types */
+ /* see the pos[2] dependence to get the adapter port-offset. */
+ list_size = sizeof(subsys_list) / sizeof(struct subsys_list_struct);
+ for (i = 0; i < list_size; i++)
+ { /* scan each slot for a fitting adapter id */
+ slot = 0; /* start at slot 0 */
+ while ((slot = mca_find_adapter(subsys_list[i].mca_id, slot))
+ != MCA_NOTFOUND)
+ { /* scan through all slots */


+ for (j=0;j<8;j++) /* read the pos-information */

+ pos[j] = mca_read_stored_pos(slot, j);
+ if ((pos[2] & 1) == 1) /* is the subsystem chip enabled ? */
+ { /* (explanations see above) */
+ port = IM_IO_PORT + ((pos[2] & 0x0e) << 2);
+ }
+ else
+ { /* anyway, set the portnumber and warn */
+ port = IM_IO_PORT + ((pos[2] & 0x0e) << 2);
+ printk("IBM MCA SCSI: WARNING - Your SCSI-subsystem is disabled!\n");
+ printk(" SCSI-operations may not work.\n");
+ }
+ id = (pos[3] & 0xe0) >> 5; /* get subsystem PUN */
+ printk("IBM MCA SCSI: %s found in slot %d, io=0x%x, scsi id=%d,\n",
+ subsys_list[i].description, slot + 1, port, id);
+ printk(" chip rev.=%d, port-offset=0x%x, subsystem=%s\n",
+ ((pos[2] & 0xf0) >> 4),
+ ((pos[2] & 0x0e) << 2),
+ (pos[2] & 1) ? "enabled." : "disabled.");
+
+ /* register the hostadapter */
+ if ((shpnt = ibmmca_register(scsi_template, port, id,
+ subsys_list[i].description)))
+ {
+ ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos2 = pos[2];
+ ((struct ibmmca_hostdata *)shpnt->hostdata)->_pos3 = pos[3];
+ ((struct ibmmca_hostdata *)shpnt->hostdata)->_special = i;
+
+ mca_set_adapter_name (slot, subsys_list[i].description);
+ mca_set_adapter_procfn (slot, (MCA_ProcFn) ibmmca_getinfo,
+ shpnt);
+ mca_mark_as_used(slot);
+ }
+ slot++; /* advance to next slot */
+ } /* advance to next adapter id in the list of IBM-SCSI-subsystems*/
+ }
+
+ if (!found)
+ { /* maybe ESDI, or other producers' SCSI-hosts */
+ free_irq (IM_IRQ, hosts);
+ printk("IBM MCA SCSI: No IBM SCSI-subsystem adapter attached.\n");
+ }
+ return found; /* return the number of found SCSI hosts. Should be 1 or 0. */
X }
X
X static struct Scsi_Host *
-ibmmca_register(Scsi_Host_Template * template, int port, int id)
+ibmmca_register(Scsi_Host_Template * scsi_template, int port, int id,
+ char *hostname)


X {
- struct Scsi_Host *shpnt;

- int i, j;
+ struct Scsi_Host *shpnt;
+ int i, j;
+ unsigned int ctrl;
+
+ /* check I/O region */
+ if (check_region(port, IM_N_IO_PORT))
+ {
+ printk("IBM MCA SCSI: Unable to get I/O region 0x%x-0x%x (%d ports).\n",
+ port, port + IM_N_IO_PORT - 1, IM_N_IO_PORT);


+ return NULL;
+ }
+

+ /* register host */
+ shpnt = scsi_register(scsi_template, sizeof(struct ibmmca_hostdata));
+ if (!shpnt)
+ {
+ printk("IBM MCA SCSI: Unable to register host.\n");


+ return NULL;
+ }
+

+ /* request I/O region */
+ request_region(port, IM_N_IO_PORT, hostname);
X
- /* check I/O region */
- if (check_region(port, IM_N_IO_PORT))
- {
- printk("IBM MCA SCSI: Unable to get I/O region 0x%x-0x%x.\n",
- port, port + IM_N_IO_PORT);
- return NULL;
- }
-
- /* register host */
- shpnt = scsi_register(template, sizeof(struct ibmmca_hostdata));
- if (!shpnt)
- {
- printk("IBM MCA SCSI: Unable to register host.\n");
- return NULL;
- }
-
- /* request I/O region */
- request_region(port, IM_N_IO_PORT, "ibmmca");
-
- hosts[found++] = shpnt;
- shpnt->irq = IM_IRQ;
- shpnt->io_port = port;
- shpnt->n_io_port = IM_N_IO_PORT;
- shpnt->this_id = id;
-
- reset_status = IM_RESET_NOT_IN_PROGRESS;
-
- for (i = 0; i < 8; i++)
- for (j = 0; j < 8; j++)
- get_ldn[i][j] = MAX_LOG_DEV;
-
- /* check which logical devices exist */
- local_checking_phase_flag = 1;
- check_devices(shpnt);
- local_checking_phase_flag = 0;
+ hosts[found] = shpnt; /* add new found hostadapter to the list */
+ shpnt->irq = IM_IRQ; /* assign necessary stuff for the adapter */
+ shpnt->io_port = port;
+ shpnt->n_io_port = IM_N_IO_PORT;
+ shpnt->this_id = id;
+ /* now, the SCSI-subsystem is connected to Linux */
X
- /* an ibm mca subsystem has been detected */
- return shpnt;
+ ctrl = (unsigned int)(inb(IM_CTR_REG(found))); /* get control-register status */
+#ifdef IM_DEBUG_PROBE
+ printk("IBM MCA SCSI: Control Register contents: %x, status: %x\n",
+ ctrl,inb(IM_STAT_REG(found)));
+ printk("IBM MCA SCSI: This adapters' POS-registers: ");
+ for (i=0;i<8;i++)
+ printk("%x ",pos[i]);
+ printk("\n");
+ if (bypass_controller)
+ printk("IBM MCA SCSI: Subsystem SCSI-commands get bypassed.\n");
+#endif
+
+ reset_status(found) = IM_RESET_NOT_IN_PROGRESS;
+
+ for (i = 0; i < 8; i++) /* reset the tables */
+ for (j = 0; j < 8; j++)
+ get_ldn(found)[i][j] = MAX_LOG_DEV;
+
+ /* check which logical devices exist */
+ local_checking_phase_flag(found) = 1;
+ check_devices(found); /* call by value, using the global variable hosts*/
+ local_checking_phase_flag(found) = 0;
+
+ found++; /* now increase index to be prepared for next found subsystem */
+ /* an ibm mca subsystem has been detected */
+ return shpnt;


X }
X
X /*--------------------------------------------------------------------*/
X

-int
-ibmmca_command (Scsi_Cmnd * cmd)
+int ibmmca_command (Scsi_Cmnd * cmd)
X {
X ibmmca_queuecommand (cmd, internal_done);
X cmd->SCp.Status = 0;
@@ -1678,8 +1765,7 @@
X
X /*--------------------------------------------------------------------*/
X
-int
-ibmmca_release(struct Scsi_Host *shpnt)
+int ibmmca_release(struct Scsi_Host *shpnt)
X {
X release_region(shpnt->io_port, shpnt->n_io_port);
X if (!(--found))
@@ -1708,231 +1794,267 @@
X are sufficient. (The adapter uses always ldn=15, at whatever pun it is.) */
X int ibmmca_queuecommand (Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
X {
- unsigned int ldn;
- unsigned int scsi_cmd;
- struct im_scb *scb;
- struct Scsi_Host *shpnt = cmd->host;
-
- int current_ldn;
- int id,lun;
-
- /* use industry standard ordering of the IDs */
-#ifdef CONFIG_IBMMCA_SCSI_ORDER_STANDARD
- int target = 6 - cmd->target;
-#else
- int target = cmd->target;
-#endif
-
- /*if (target,lun) is NO LUN or not existing at all, return error */
- if ((get_scsi[target][cmd->lun] == TYPE_NO_LUN)||
- (get_scsi[target][cmd->lun] == TYPE_NO_DEVICE))
+ unsigned int ldn;
+ unsigned int scsi_cmd;
+ struct im_scb *scb;
+ struct Scsi_Host *shpnt;
+ int current_ldn;
+ int id,lun;
+ int target;
+ int host_index;
+
+ if (ibm_ansi_order)
+ target = 6 - cmd->target;
+ else
+ target = cmd->target;
+
+ shpnt = cmd->host;
+
+ /* search for the right hostadapter */
+ for (host_index = 0; hosts[host_index] && hosts[host_index]->host_no != shpnt->host_no; host_index++);
+

+ if (!hosts[host_index])

+ { /* invalid hostadapter descriptor address */
+ cmd->result = DID_NO_CONNECT << 16;
+ done (cmd);


+ return 0;
+ }
+

+ /*if (target,lun) is NO LUN or not existing at all, return error */
+ if ((get_scsi(host_index)[target][cmd->lun] == TYPE_NO_LUN)||
+ (get_scsi(host_index)[target][cmd->lun] == TYPE_NO_DEVICE))
X {
X cmd->result = DID_NO_CONNECT << 16;
X done (cmd);


X return 0;
X }
X

- /*if (target,lun) unassigned, do further checks... */
- ldn = get_ldn[target][cmd->lun];
- if (ldn >= MAX_LOG_DEV) /* on invalid ldn do special stuff */
- {
- if (ldn > MAX_LOG_DEV) /* dynamical remapping if ldn unassigned */
- {
- current_ldn = next_ldn; /* stop-value for one circle */
- while (ld[next_ldn].cmd) /* search for a occupied, but not in */
- { /* command-processing ldn. */
- next_ldn ++;
- if (next_ldn>=MAX_LOG_DEV)
- next_ldn = 7;
- if (current_ldn == next_ldn) /* One circle done ? */
- { /* no non-processing ldn found */
- printk("IBM MCA SCSI: Cannot assign SCSI-device dynamically!\n");
- printk(" On ldn 7-14 SCSI-commands everywhere in progress.\n");
- printk(" Reporting DID_NO_CONNECT for device (%d,%d).\n",
- target, cmd->lun);
- cmd->result = DID_NO_CONNECT << 16;/* return no connect*/
- done (cmd);


- return 0;
- }
- }
-

- /* unmap non-processing ldn */


- for (id=0; id<8; id ++)

- for (lun=0; lun<8; lun++)

- {
- if (get_ldn[id][lun] == next_ldn)
- {
- get_ldn[id][lun] = TYPE_NO_DEVICE; /* unmap entry */
- goto DYN_ASSIGN; /* jump out as fast as possible */
- }
- }
-
-DYN_ASSIGN:
- /* unassign found ldn (pun,lun does not matter for remove) */
- immediate_assign(shpnt,0,0,next_ldn,REMOVE_LDN);
- /* assign found ldn to aimed pun,lun */
- immediate_assign(shpnt,target,cmd->lun,next_ldn,SET_LDN);
- /* map found ldn to pun,lun */
- get_ldn[target][cmd->lun] = next_ldn;
- /* change ldn to the right value, that is now next_ldn */
- ldn = next_ldn;
- /* set reduced interrupt_handler-mode for checking */
- local_checking_phase_flag = 1;
- /* get device information for ld[ldn] */


- if (device_exists (shpnt, ldn, &ld[ldn].block_length,
- &ld[ldn].device_type))

+ /*if (target,lun) unassigned, do further checks... */
+ ldn = get_ldn(host_index)[target][cmd->lun];
+ if (ldn >= MAX_LOG_DEV) /* on invalid ldn do special stuff */
+ {
+ if (ldn > MAX_LOG_DEV) /* dynamical remapping if ldn unassigned */
+ {
+ current_ldn = next_ldn(host_index); /* stop-value for one circle */
+ while (ld(host_index)[next_ldn(host_index)].cmd) /* search for a occupied, but not in */
+ { /* command-processing ldn. */
+ next_ldn(host_index)++;
+ if (next_ldn(host_index)>=MAX_LOG_DEV)
+ next_ldn(host_index) = 7;
+ if (current_ldn == next_ldn(host_index)) /* One circle done ? */
+ { /* no non-processing ldn found */
+ printk("IBM MCA SCSI: Cannot assign SCSI-device dynamically!\n");
+ printk(" On ldn 7-14 SCSI-commands everywhere in progress.\n");
+ printk(" Reporting DID_NO_CONNECT for device (%d,%d).\n",
+ target, cmd->lun);
+ cmd->result = DID_NO_CONNECT << 16;/* return no connect*/
+ done (cmd);


+ return 0;
+ }
+ }
+

+ /* unmap non-processing ldn */


+ for (id=0; id<8; id ++)

+ for (lun=0; lun<8; lun++)

X {
- ld[ldn].cmd = 0; /* To prevent panic set 0, because
- devices that were not assigned,
- should have nothing in progress. */
+ if (get_ldn(host_index)[id][lun] == next_ldn(host_index))
+ {
+ get_ldn(host_index)[id][lun] = TYPE_NO_DEVICE;
+ /* unmap entry */
+ }
+ }
+ /* set reduced interrupt_handler-mode for checking */
+ local_checking_phase_flag(host_index) = 1;
+ /* unassign found ldn (pun,lun does not matter for remove) */
+ immediate_assign(host_index,0,0,next_ldn(host_index),REMOVE_LDN);
+ /* assign found ldn to aimed pun,lun */
+ immediate_assign(host_index,target,cmd->lun,next_ldn(host_index),SET_LDN);
+ /* map found ldn to pun,lun */
+ get_ldn(host_index)[target][cmd->lun] = next_ldn(host_index);
+ /* change ldn to the right value, that is now next_ldn */
+ ldn = next_ldn(host_index);
+ /* get device information for ld[ldn] */


+ if (device_exists (host_index, ldn,
+ &ld(host_index)[ldn].block_length,
+ &ld(host_index)[ldn].device_type))
+ {

+ ld(host_index)[ldn].cmd = 0; /* To prevent panic set 0, because
+ devices that were not assigned,
+ should have nothing in progress. */
X
- /* increase assignment counters for statistics in /proc */
- IBM_DS.dynamical_assignments++;
- IBM_DS.ldn_assignments[ldn]++;
+ /* increase assignment counters for statistics in /proc */
+ IBM_DS(host_index).dynamical_assignments++;
+ IBM_DS(host_index).ldn_assignments[ldn]++;
X }
- else
- /* panic here, because a device, found at boottime has
- vanished */
- panic("IBM MCA SCSI: ldn=0x%x, SCSI-device on (%d,%d) vanished!\n",
- ldn, target, cmd->lun);
-
- /* set back to normal interrupt_handling */
- local_checking_phase_flag = 0;
-
- /* Information on syslog terminal */
- printk("IBM MCA SCSI: ldn=0x%x dynamically reassigned to (%d,%d).\n",
- ldn, target, cmd->lun);
-
- /* increase next_ldn for next dynamical assignment */
- next_ldn ++;
- if (next_ldn>=MAX_LOG_DEV) next_ldn = 7;
- }
- else
- { /* wall against Linux accesses to the subsystem adapter */
- cmd->result = DID_NO_CONNECT << 16;
- done (cmd);


- return 0;
- }
- }
-

- /*verify there is no command already in progress for this log dev */
- if (ld[ldn].cmd)
- panic ("IBM MCA SCSI: cmd already in progress for this ldn.\n");
-
- /*save done in cmd, and save cmd for the interrupt handler */
- cmd->scsi_done = done;
- ld[ldn].cmd = cmd;
-
- /*fill scb information independent of the scsi command */
- scb = &(ld[ldn].scb);
- scb->enable = IM_REPORT_TSB_ONLY_ON_ERROR;
- scb->tsb_adr = virt_to_bus(&(ld[ldn].tsb));
- if (cmd->use_sg)
- {
- int i = cmd->use_sg;
- struct scatterlist *sl = (struct scatterlist *) cmd->request_buffer;
- if (i > 16)
- panic ("IBM MCA SCSI: scatter-gather list too long.\n");
- while (--i >= 0)
- {
- ld[ldn].sge[i].address = (void *) virt_to_bus(sl[i].address);
- ld[ldn].sge[i].byte_length = sl[i].length;
- }
- scb->enable |= IM_POINTER_TO_LIST;
- scb->sys_buf_adr = virt_to_bus(&(ld[ldn].sge[0]));
- scb->sys_buf_length = cmd->use_sg * sizeof (struct im_sge);
- }
- else
- {
- scb->sys_buf_adr = virt_to_bus(cmd->request_buffer);
- scb->sys_buf_length = cmd->request_bufflen;
- }
-
- /*fill scb information dependent on scsi command */
- scsi_cmd = cmd->cmnd[0];
+ else
+ /* panic here, because a device, found at boottime has
+ vanished */
+ panic("IBM MCA SCSI: ldn=0x%x, SCSI-device on (%d,%d) vanished!\n",
+ ldn, target, cmd->lun);
+
+ /* set back to normal interrupt_handling */
+ local_checking_phase_flag(host_index) = 0;
+
+ /* Information on syslog terminal */
+ printk("IBM MCA SCSI: ldn=0x%x dynamically reassigned to (%d,%d).\n",
+ ldn, target, cmd->lun);
+
+ /* increase next_ldn for next dynamical assignment */
+ next_ldn(host_index)++;
+ if (next_ldn(host_index)>=MAX_LOG_DEV)
+ next_ldn(host_index) = 7;
+ }
+ else
+ { /* wall against Linux accesses to the subsystem adapter */
+ cmd->result = DID_BAD_TARGET << 16;
+ done (cmd);


+ return 0;
+ }
+ }
+

+ /*verify there is no command already in progress for this log dev */
+ if (ld(host_index)[ldn].cmd)
+ panic ("IBM MCA SCSI: cmd already in progress for this ldn.\n");
+
+ /*save done in cmd, and save cmd for the interrupt handler */
+ cmd->scsi_done = done;
+ ld(host_index)[ldn].cmd = cmd;
+
+ /*fill scb information independent of the scsi command */


+ scb = &(ld(host_index)[ldn].scb);

+ ld(host_index)[ldn].tsb.dev_status = 0;

+ scb->enable = IM_REPORT_TSB_ONLY_ON_ERROR;
+ scb->tsb_adr = virt_to_bus(&(ld(host_index)[ldn].tsb));
+ if (cmd->use_sg)
+ {
+ int i = cmd->use_sg;
+ struct scatterlist *sl = (struct scatterlist *) cmd->request_buffer;
+ if (i > 16)
+ panic ("IBM MCA SCSI: scatter-gather list too long.\n");
+ while (--i >= 0)
+ {
+ ld(host_index)[ldn].sge[i].address = (void *) virt_to_bus(sl[i].address);
+ ld(host_index)[ldn].sge[i].byte_length = sl[i].length;
+ }
+ scb->enable |= IM_POINTER_TO_LIST;
+ scb->sys_buf_adr = virt_to_bus(&(ld(host_index)[ldn].sge[0]));
+ scb->sys_buf_length = cmd->use_sg * sizeof (struct im_sge);
+ }
+ else
+ {
+ scb->sys_buf_adr = virt_to_bus(cmd->request_buffer);
+ scb->sys_buf_length = cmd->request_bufflen;
+ }
+
+ /*fill scb information dependent on scsi command */
+ scsi_cmd = cmd->cmnd[0];
X
X #ifdef IM_DEBUG_CMD
- printk("issue scsi cmd=%02x to ldn=%d\n", scsi_cmd, ldn);
+ printk("issue scsi cmd=%02x to ldn=%d\n", scsi_cmd, ldn);
X #endif
-
- /* for specific device-type debugging: */
+
+ /* for specific device-type debugging: */
X #ifdef IM_DEBUG_CMD_SPEC_DEV
- if (ld[ldn].device_type==IM_DEBUG_CMD_DEVICE)
+ if (ld(host_index)[ldn].device_type==IM_DEBUG_CMD_DEVICE)
X printk("(SCSI-device-type=0x%x) issue scsi cmd=%02x to ldn=%d\n",
- ld[ldn].device_type, scsi_cmd, ldn);
+ ld(host_index)[ldn].device_type, scsi_cmd, ldn);
X #endif
-
- /* for possible panics store current command */
- last_scsi_command = scsi_cmd;
X
- /* update statistical info */
- IBM_DS.total_accesses++;
- IBM_DS.ldn_access[ldn]++;
-
- switch (scsi_cmd)


- {
- case READ_6:
- case WRITE_6:
- case READ_10:
- case WRITE_10:
- case READ_12:
- case WRITE_12:

- /* statistics for proc_info */
- if ((scsi_cmd == READ_6)||(scsi_cmd == READ_10)||(scsi_cmd == READ_12))
- IBM_DS.ldn_read_access[ldn]++; /* increase READ-access on ldn stat. */
- else if ((scsi_cmd == WRITE_6)||(scsi_cmd == WRITE_10)||
- (scsi_cmd == WRITE_12))
- IBM_DS.ldn_write_access[ldn]++; /* increase write-count on ldn stat.*/
-
- /* Distinguish between disk and other devices. Only disks (that are the
- most frequently accessed devices) should be supported by the
+ /* for possible panics store current command */
+ last_scsi_command(host_index)[ldn] = scsi_cmd;

+ last_scsi_type(host_index)[ldn] = IM_SCB;
+

+ /* update statistical info */
+ IBM_DS(host_index).total_accesses++;
+ IBM_DS(host_index).ldn_access[ldn]++;
+
+ switch (scsi_cmd)


+ {
+ case READ_6:
+ case WRITE_6:
+ case READ_10:
+ case WRITE_10:
+ case READ_12:
+ case WRITE_12:

+ /* statistics for proc_info */
+ if ((scsi_cmd == READ_6)||(scsi_cmd == READ_10)||(scsi_cmd == READ_12))
+ IBM_DS(host_index).ldn_read_access[ldn]++; /* increase READ-access on ldn stat. */
+ else if ((scsi_cmd == WRITE_6)||(scsi_cmd == WRITE_10)||
+ (scsi_cmd == WRITE_12))
+ IBM_DS(host_index).ldn_write_access[ldn]++; /* increase write-count on ldn stat.*/
+
+ /* Distinguish between disk and other devices. Only disks (that are the
+ most frequently accessed devices) should be supported by the
X IBM-SCSI-Subsystem commands. */
- switch (ld[ldn].device_type)
- {
- case TYPE_DISK: /* for harddisks enter here ... */
- case TYPE_MOD: /* ... try it also for MO-drives (send flames as */
- /* you like, if this won't work.) */
- if (scsi_cmd == READ_6 || scsi_cmd == READ_10 ||
- scsi_cmd == READ_12)
- {
- scb->command = IM_READ_DATA_CMD;
- scb->enable |= IM_READ_CONTROL;
- }
- else
- {
- scb->command = IM_WRITE_DATA_CMD;
- }
- if (scsi_cmd == READ_6 || scsi_cmd == WRITE_6)
- {
- scb->u1.log_blk_adr = (((unsigned) cmd->cmnd[3]) << 0) |
- (((unsigned) cmd->cmnd[2]) << 8) |
- ((((unsigned) cmd->cmnd[1]) & 0x1f) << 16);
- scb->u2.blk.count = (unsigned) cmd->cmnd[4];
- }
- else
- {
- scb->u1.log_blk_adr = (((unsigned) cmd->cmnd[5]) << 0) |
- (((unsigned) cmd->cmnd[4]) << 8) |
- (((unsigned) cmd->cmnd[3]) << 16) |
- (((unsigned) cmd->cmnd[2]) << 24);
- scb->u2.blk.count = (((unsigned) cmd->cmnd[8]) << 0) |
- (((unsigned) cmd->cmnd[7]) << 8);
- }
- scb->u2.blk.length = ld[ldn].block_length;
- if (++disk_rw_in_progress == 1)
- PS2_DISK_LED_ON (shpnt->host_no, target);
- break;
-
- /* for other devices, enter here. Other types are not known by
- Linux! TYPE_NO_LUN is forbidden as valid device. */
- case TYPE_ROM:
- case TYPE_TAPE:
- case TYPE_PROCESSOR:
- case TYPE_WORM:
- case TYPE_SCANNER:
- case TYPE_MEDIUM_CHANGER:
-
- /* If there is a sequential-device, IBM recommends to use
+ switch (ld(host_index)[ldn].device_type)
+ {
+ case TYPE_DISK: /* for harddisks enter here ... */
+ case TYPE_MOD: /* ... try it also for MO-drives (send flames as */
+ /* you like, if this won't work.) */
+ if (scsi_cmd == READ_6 || scsi_cmd == READ_10 ||
+ scsi_cmd == READ_12)
+ { /* read command preparations */
+ if (bypass_controller)
+ {


+ scb->command = IM_OTHER_SCSI_CMD_CMD;
+ scb->enable |= IM_READ_CONTROL;

+ scb->u1.scsi_cmd_length = cmd->cmd_len;
+ memcpy(scb->u2.scsi_command,cmd->cmnd,cmd->cmd_len);
+ }
+ else
+ {
+ scb->command = IM_READ_DATA_CMD;


+ scb->enable |= IM_READ_CONTROL;
+ }

+ }
+ else
+ { /* write command preparations */
+ if (bypass_controller)
+ {


+ scb->command = IM_OTHER_SCSI_CMD_CMD;

+ scb->u1.scsi_cmd_length = cmd->cmd_len;
+ memcpy(scb->u2.scsi_command,cmd->cmnd,cmd->cmd_len);
+ }
+ else
+ {
+ scb->command = IM_WRITE_DATA_CMD;
+ }
+ }
+
+ if (!bypass_controller)
+ {
+ if (scsi_cmd == READ_6 || scsi_cmd == WRITE_6)
+ {
+ scb->u1.log_blk_adr = (((unsigned) cmd->cmnd[3]) << 0) |
+ (((unsigned) cmd->cmnd[2]) << 8) |
+ ((((unsigned) cmd->cmnd[1]) & 0x1f) << 16);
+ scb->u2.blk.count = (unsigned) cmd->cmnd[4];
+ }
+ else
+ {
+ scb->u1.log_blk_adr = (((unsigned) cmd->cmnd[5]) << 0) |
+ (((unsigned) cmd->cmnd[4]) << 8) |
+ (((unsigned) cmd->cmnd[3]) << 16) |
+ (((unsigned) cmd->cmnd[2]) << 24);
+ scb->u2.blk.count = (((unsigned) cmd->cmnd[8]) << 0) |
+ (((unsigned) cmd->cmnd[7]) << 8);
+ }
+ scb->u2.blk.length = ld(host_index)[ldn].block_length;
+ }
+ if (++disk_rw_in_progress == 1)
+ PS2_DISK_LED_ON (shpnt->host_no, target);
+ break;
+
+ /* for other devices, enter here. Other types are not known by
+ Linux! TYPE_NO_LUN is forbidden as valid device. */
+ case TYPE_ROM:
+ case TYPE_TAPE:
+ case TYPE_PROCESSOR:
+ case TYPE_WORM:
+ case TYPE_SCANNER:
+ case TYPE_MEDIUM_CHANGER:
+
+ /* If there is a sequential-device, IBM recommends to use
X IM_OTHER_SCSI_CMD_CMD instead of subsystem READ/WRITE.
X Good/modern CD-ROM-drives are capable of
X reading sequential AND random-access. This leads to the problem,
@@ -1943,241 +2065,422 @@
X to have a stable state. In addition, data-access on CD-ROMs
X works faster like that. Strange, but obvious. */
X
- scb->command = IM_OTHER_SCSI_CMD_CMD;
- if (scsi_cmd == READ_6 || scsi_cmd == READ_10 ||
- scsi_cmd == READ_12) /* enable READ */
- scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT;
- else
- scb->enable |= IM_SUPRESS_EXCEPTION_SHORT; /* assume WRITE */
-
- scb->u1.scsi_cmd_length = cmd->cmd_len;
- memcpy (scb->u2.scsi_command, cmd->cmnd, cmd->cmd_len);
-
- /* Read/write on this non-disk devices is also displayworthy,

+ scb->command = IM_OTHER_SCSI_CMD_CMD;

+ if (scsi_cmd == READ_6 || scsi_cmd == READ_10 ||
+ scsi_cmd == READ_12) /* enable READ */
+ {


+ scb->enable |= IM_READ_CONTROL;
+ }

+
+ scb->u1.scsi_cmd_length = cmd->cmd_len;
+ memcpy (scb->u2.scsi_command, cmd->cmnd, cmd->cmd_len);
+
+ /* Read/write on this non-disk devices is also displayworthy,
X so flash-up the LED/display. */
- if (++disk_rw_in_progress == 1)
- PS2_DISK_LED_ON (shpnt->host_no, target);
- break;
- }
- break;
- case INQUIRY:
- IBM_DS.ldn_inquiry_access[ldn]++;
- scb->command = IM_DEVICE_INQUIRY_CMD;
- scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT;
- break;
-
- case READ_CAPACITY:
- scb->command = IM_READ_CAPACITY_CMD;
- scb->enable |= IM_READ_CONTROL;
- /* the length of system memory buffer must be exactly 8 bytes */
- if (scb->sys_buf_length >= 8)
- scb->sys_buf_length = 8;
- break;
-
- /* Commands that need read-only-mode (system <- device): */
- case REQUEST_SENSE:
- scb->command = IM_REQUEST_SENSE_CMD;
- scb->enable |= IM_READ_CONTROL;
- break;
-
- /* Commands that need write-only-mode (system -> device): */
- case MODE_SELECT:
- case MODE_SELECT_10:
- IBM_DS.ldn_modeselect_access[ldn]++;
- scb->command = IM_OTHER_SCSI_CMD_CMD;
- scb->enable |= IM_SUPRESS_EXCEPTION_SHORT; /*Select needs WRITE-enabled*/
- scb->u1.scsi_cmd_length = cmd->cmd_len;
- memcpy (scb->u2.scsi_command, cmd->cmnd, cmd->cmd_len);
- break;
-
- /* For other commands, read-only is useful. Most other commands are
- running without an input-data-block. */
- default:
- scb->command = IM_OTHER_SCSI_CMD_CMD;
- scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT;
- scb->u1.scsi_cmd_length = cmd->cmd_len;
- memcpy (scb->u2.scsi_command, cmd->cmnd, cmd->cmd_len);
- break;
- }
+ if (++disk_rw_in_progress == 1)
+ PS2_DISK_LED_ON (shpnt->host_no, target);


+ break;
+ }
+ break;

+ case INQUIRY:
+ IBM_DS(host_index).ldn_inquiry_access[ldn]++;
+ if (bypass_controller)
+ {


+ scb->command = IM_OTHER_SCSI_CMD_CMD;
+ scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT;

+ scb->u1.scsi_cmd_length = cmd->cmd_len;
+ memcpy (scb->u2.scsi_command, cmd->cmnd, cmd->cmd_len);
+ }
+ else
+ {


+ scb->command = IM_DEVICE_INQUIRY_CMD;
+ scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT;
+ }

+ break;
X
- /*issue scb command, and return */
- issue_cmd (shpnt, virt_to_bus(scb), IM_SCB | ldn);
- return 0;
+ case READ_CAPACITY:
+ /* the length of system memory buffer must be exactly 8 bytes */
+ if (scb->sys_buf_length > 8)


+ scb->sys_buf_length = 8;

+ if (bypass_controller)
+ {


+ scb->command = IM_OTHER_SCSI_CMD_CMD;
+ scb->enable |= IM_READ_CONTROL;

+ scb->u1.scsi_cmd_length = cmd->cmd_len;
+ memcpy (scb->u2.scsi_command, cmd->cmnd, cmd->cmd_len);

+ }
+ else
+ {
+ scb->command = IM_READ_CAPACITY_CMD;
+ scb->enable |= IM_READ_CONTROL;
+ }

+ break;
+
+ /* Commands that need read-only-mode (system <- device): */
+ case REQUEST_SENSE:
+ if (bypass_controller)
+ {


+ scb->command = IM_OTHER_SCSI_CMD_CMD;
+ scb->enable |= IM_READ_CONTROL;

+ scb->u1.scsi_cmd_length = cmd->cmd_len;
+ memcpy (scb->u2.scsi_command, cmd->cmnd, cmd->cmd_len);
+ }
+ else
+ {
+ scb->command = IM_REQUEST_SENSE_CMD;


+ scb->enable |= IM_READ_CONTROL;
+ }

+ break;
+
+ /* Commands that need write-only-mode (system -> device): */
+ case MODE_SELECT:
+ case MODE_SELECT_10:
+ IBM_DS(host_index).ldn_modeselect_access[ldn]++;


+ scb->command = IM_OTHER_SCSI_CMD_CMD;

+ scb->enable |= IM_SUPRESS_EXCEPTION_SHORT; /*Select needs WRITE-enabled*/
+ scb->u1.scsi_cmd_length = cmd->cmd_len;
+ memcpy (scb->u2.scsi_command, cmd->cmnd, cmd->cmd_len);
+ break;
+
+ /* For other commands, read-only is useful. Most other commands are
+ running without an input-data-block. */
+ default:


+ scb->command = IM_OTHER_SCSI_CMD_CMD;
+ scb->enable |= IM_READ_CONTROL | IM_SUPRESS_EXCEPTION_SHORT;

+ scb->u1.scsi_cmd_length = cmd->cmd_len;
+ memcpy (scb->u2.scsi_command, cmd->cmnd, cmd->cmd_len);
+ break;
+ }
+
+ /*issue scb command, and return */


+ issue_cmd (host_index, virt_to_bus(scb), IM_SCB | ldn);

+ return 0;


X }
X
X /*--------------------------------------------------------------------*/
X

-int
-ibmmca_abort (Scsi_Cmnd * cmd)
+int ibmmca_abort (Scsi_Cmnd * cmd)
X {
- /* The code below doesn't work right now, so we tell the upper layer
- that we can't abort. This eventually causes a reset.
- */
- return SCSI_ABORT_SNOOZE ;
-
-#if 0
- struct Scsi_host *shpnt = cmd->host;
- unsigned int ldn;
- void (*saved_done) (Scsi_Cmnd *);
+ /* Abort does not work, as the adapter never generates an interrupt on
+ * whatever situation is simulated, even when really pending commands
+ * are running on the adapters' hardware ! */


+
+ struct Scsi_Host *shpnt;

+ unsigned int ldn;
+ void (*saved_done) (Scsi_Cmnd *);
+ int target;
+ int host_index;


+ static unsigned long flags;

+ unsigned long imm_command;
X
-#ifdef CONFIG_IBMMCA_SCSI_ORDER_STANDARD
- int target = 6 - cmd->target;
+ /* return SCSI_ABORT_SNOOZE ; */


+
+#ifdef OLDKERN
+ save_flags(flags);
+ cli();

X #else
- int target = cmd->target;
-#endif
+ spin_lock_irqsave(&abort_lock, flags);
+#endif
+ if (ibm_ansi_order)
+ target = 6 - cmd->target;
+ else
+ target = cmd->target;
+
+ shpnt = cmd->host;
X
- /*get logical device number, and disable system interrupts */
- printk ("IBM MCA SCSI: sending abort to device id=%d lun=%d.\n",
- target, cmd->lun);
- ldn = get_ldn[target][cmd->lun];
- cli ();
-
- /*if cmd for this ldn has already finished, no need to abort */
- if (!ld[ldn].cmd)
- {
- /* sti (); */
- return SCSI_ABORT_NOT_RUNNING;
- }
-
- /* Clear ld.cmd, save done function, install internal done,
- * send abort immediate command (this enables sys. interrupts),
- * and wait until the interrupt arrives.
- */


- ld[ldn].cmd = 0;

- saved_done = cmd->scsi_done;
- cmd->scsi_done = internal_done;
- cmd->SCp.Status = 0;
- issue_cmd (shpnt, T_IMM_CMD, IM_IMM_CMD | ldn);
- while (!cmd->SCp.Status)
- barrier ();
+ /* search for the right hostadapter */
+ for (host_index = 0; hosts[host_index] && hosts[host_index]->host_no != shpnt->host_no; host_index++);
+

+ if (!hosts[host_index])

+ { /* invalid hostadapter descriptor address */
+ cmd->result = DID_NO_CONNECT << 16;
+ if (cmd->scsi_done)
+ (cmd->done) (cmd);
+ return SCSI_ABORT_SNOOZE;
+ }
+
+ /*get logical device number, and disable system interrupts */
+ printk ("IBM MCA SCSI: Sending abort to device pun=%d, lun=%d.\n",
+ target, cmd->lun);
+ ldn = get_ldn(host_index)[target][cmd->lun];
+
+ /*if cmd for this ldn has already finished, no need to abort */
+ if (!ld(host_index)[ldn].cmd)
+ {


+#ifdef OLDKERN
+ restore_flags(flags);
+#else

+ spin_unlock_irqrestore(&abort_lock, flags);
+#endif
+ return SCSI_ABORT_NOT_RUNNING;
+ }
X
- /*if abort went well, call saved done, then return success or error */
- if (cmd->result == 0)
- {
- cmd->result |= DID_ABORT << 16;
- saved_done (cmd);
- return SCSI_ABORT_SUCCESS;
- }
- else
- return SCSI_ABORT_ERROR;
+ /* Clear ld.cmd, save done function, install internal done,
+ * send abort immediate command (this enables sys. interrupts),
+ * and wait until the interrupt arrives.
+ */
+ saved_done = cmd->scsi_done;
+ cmd->scsi_done = internal_done;
+ cmd->SCp.Status = 0;
+ last_scsi_command(host_index)[ldn] = IM_ABORT_IMM_CMD;


+ last_scsi_type(host_index)[ldn] = IM_IMM_CMD;

+ imm_command = inl(IM_CMD_REG(host_index));
+ imm_command &= (unsigned long)(0xffff0000); /* mask reserved stuff */
+ imm_command |= (unsigned long)(IM_ABORT_IMM_CMD);


+ /* must wait for attention reg not busy */
+ while (1)
+ {

+ if (!(inb (IM_STAT_REG(host_index)) & IM_BUSY))
+ break;
+#ifdef OLDKERN
+ restore_flags (flags);
+#else

+ spin_unlock_irqrestore(&abort_lock, flags);
+#endif

+#ifdef OLDKERN
+ save_flags(flags);
+ cli();
+#else

+ spin_lock_irqsave(&abort_lock, flags);


+#endif
+ }
+ /*write registers and enable system interrupts */

+ outl (imm_command, IM_CMD_REG(host_index));
+ outb (IM_IMM_CMD | ldn, IM_ATTN_REG(host_index));
+#ifdef OLDKERN
+ restore_flags (flags);
+#else
+ spin_unlock_irqrestore(&abort_lock, flags);
X #endif
+
+#ifdef IM_DEBUG_PROBE
+ printk("IBM MCA SCSI: Abort submitted, waiting for adapter response...\n");
+#endif
+ while (!cmd->SCp.Status)
+ barrier ();
+ cmd->scsi_done = saved_done;
+ /*if abort went well, call saved done, then return success or error */
+ if (cmd->result == (DID_ABORT << 16))
+ {


+ cmd->result |= DID_ABORT << 16;

+ if (cmd->scsi_done)
+ (cmd->scsi_done) (cmd);

+ ld(host_index)[ldn].cmd = NULL;

+#ifdef IM_DEBUG_PROBE
+ printk("IBM MCA SCSI: Abort finished with success.\n");
+#endif
+ return SCSI_ABORT_SUCCESS;
+ }
+ else
+ {


+ cmd->result |= DID_NO_CONNECT << 16;

+ if (cmd->scsi_done)
+ (cmd->scsi_done) (cmd);

+ ld(host_index)[ldn].cmd = NULL;

+#ifdef IM_DEBUG_PROBE
+ printk("IBM MCA SCSI: Abort failed.\n");
+#endif
+ return SCSI_ABORT_ERROR;
+ }


X }
X
X /*--------------------------------------------------------------------*/
X

-int
-ibmmca_reset (Scsi_Cmnd * cmd, unsigned int reset_flags)
+int ibmmca_reset (Scsi_Cmnd * cmd, unsigned int reset_flags)
X {
- struct Scsi_Host *shpnt = cmd->host;
- int ticks = IM_RESET_DELAY*HZ;
+ struct Scsi_Host *shpnt;
+ Scsi_Cmnd *cmd_aid;
+ int ticks,i;
+ int host_index;


+ static unsigned long flags;

+ unsigned long imm_command;


+
+#ifdef OLDKERN
+ save_flags(flags);
+ cli();
+#else

+ spin_lock_irqsave(&reset_lock, flags);
+#endif
+ ticks = IM_RESET_DELAY*HZ;
+ shpnt = cmd->host;
+ /* search for the right hostadapter */
+ for (host_index = 0; hosts[host_index] && hosts[host_index]->host_no != shpnt->host_no; host_index++);
+


+ if (!hosts[host_index])

+ { /* invalid hostadapter descriptor address */
+ if (!local_checking_phase_flag(host_index))
+ {


+ cmd->result = DID_NO_CONNECT << 16;

+ if (cmd->scsi_done)
+ (cmd->done) (cmd);
+ }
+ return SCSI_ABORT_SNOOZE;
+ }
X
- if (local_checking_phase_flag) {
- printk("IBM MCA SCSI: unable to reset while checking devices.\n");
- return SCSI_RESET_SNOOZE;
- }
-
- /* issue reset immediate command to subsystem, and wait for interrupt */
- printk("IBM MCA SCSI: resetting all devices.\n");
- cli ();
- reset_status = IM_RESET_IN_PROGRESS;
- issue_cmd (shpnt, IM_RESET_IMM_CMD, IM_IMM_CMD | 0xf);


- while (reset_status == IM_RESET_IN_PROGRESS && --ticks) {

- mdelay(1+999/HZ);
- barrier();
- }

- /* if reset did not complete, just return an error*/
- if (!ticks) {


- printk("IBM MCA SCSI: reset did not complete within %d seconds.\n",
- IM_RESET_DELAY);

- reset_status = IM_RESET_FINISHED_FAIL;
- return SCSI_RESET_ERROR;
- }
-
- /* if reset failed, just return an error */
- if (reset_status == IM_RESET_FINISHED_FAIL) {
- printk("IBM MCA SCSI: reset failed.\n");
- return SCSI_RESET_ERROR;
- }
+ if (local_checking_phase_flag(host_index))
+ {
+ printk("IBM MCA SCSI: unable to reset while checking devices.\n");


+#ifdef OLDKERN
+ restore_flags(flags);
+#else

+ spin_unlock_irqrestore(&reset_lock, flags);
+#endif
+ return SCSI_RESET_SNOOZE;
+ }
X
- /* so reset finished ok - call outstanding done's, and return success */
- printk ("IBM MCA SCSI: reset completed without error.\n");
- {
- int i;
- for (i = 0; i < MAX_LOG_DEV; i++)
- {
- Scsi_Cmnd *cmd = ld[i].cmd;
- if (cmd && cmd->scsi_done)
- {
- ld[i].cmd = 0;
- cmd->result = DID_RESET;


- (cmd->scsi_done) (cmd);
- }
- }
- }

- return SCSI_RESET_SUCCESS;
+ /* issue reset immediate command to subsystem, and wait for interrupt */
+ printk("IBM MCA SCSI: resetting all devices.\n");
+ reset_status(host_index) = IM_RESET_IN_PROGRESS;
+ last_scsi_command(host_index)[0xf] = IM_RESET_IMM_CMD;


+ last_scsi_type(host_index)[0xf] = IM_IMM_CMD;

+ imm_command = inl(IM_CMD_REG(host_index));
+ imm_command &= (unsigned long)(0xffff0000); /* mask reserved stuff */


+ imm_command |= (unsigned long)(IM_RESET_IMM_CMD);

+ /* must wait for attention reg not busy */
+ while (1)
+ {

+ if (!(inb (IM_STAT_REG(host_index)) & IM_BUSY))
+ break;
+#ifdef OLDKERN
+ restore_flags(flags);
+#else

+ spin_unlock_irqrestore(&reset_lock, flags);
+#endif

+#ifdef OLDKERN
+ save_flags(flags);
+ cli();
+#else

+ spin_lock_irqsave(&reset_lock, flags);


+#endif
+ }
+ /*write registers and enable system interrupts */

+ outl (imm_command, IM_CMD_REG(host_index));
+ outb (IM_IMM_CMD | 0xf, IM_ATTN_REG(host_index));
+ /* wait for interrupt finished or intr_stat register to be set, as the
+ * interrupt will not be executed, while we are in here! */


+ while (reset_status(host_index) == IM_RESET_IN_PROGRESS && --ticks

+ && ((inb(IM_INTR_REG(host_index)) & 0x8f)!=0x8f)) {


+ mdelay(1+999/HZ);
+ barrier();
+ }

+ /* if reset did not complete, just return an error*/
+ if (!ticks) {


+ printk("IBM MCA SCSI: reset did not complete within %d seconds.\n",
+ IM_RESET_DELAY);

+ reset_status(host_index) = IM_RESET_FINISHED_FAIL;


+#ifdef OLDKERN
+ restore_flags(flags);
+#else

+ spin_unlock_irqrestore(&reset_lock, flags);
+#endif
+ return SCSI_RESET_ERROR;
+ }
+
+ if ((inb(IM_INTR_REG(host_index)) & 0x8f)==0x8f)
+ { /* analysis done by this routine and not by the intr-routine */
+ if (inb(IM_INTR_REG(host_index))==0xaf)
+ reset_status(host_index) = IM_RESET_FINISHED_OK_NO_INT;
+ else if (inb(IM_INTR_REG(host_index))==0xcf)
+ reset_status(host_index) = IM_RESET_FINISHED_FAIL;
+ else /* failed, 4get it */
+ reset_status(host_index) = IM_RESET_NOT_IN_PROGRESS_NO_INT;
+ outb (IM_EOI | 0xf, IM_ATTN_REG(host_index));
+ }
+
+ /* if reset failed, just return an error */
+ if (reset_status(host_index) == IM_RESET_FINISHED_FAIL) {
+ printk("IBM MCA SCSI: reset failed.\n");


+#ifdef OLDKERN
+ restore_flags(flags);
+#else

+ spin_unlock_irqrestore(&reset_lock, flags);
+#endif
+ return SCSI_RESET_ERROR;
+ }
+
+ /* so reset finished ok - call outstanding done's, and return success */
+ printk ("IBM MCA SCSI: Reset completed without known error.\n");


+#ifdef OLDKERN
+ restore_flags(flags);
+#else

+ spin_unlock_irqrestore(&reset_lock, flags);
+#endif
+ for (i = 0; i < MAX_LOG_DEV; i++)
+ {
+ cmd_aid = ld(host_index)[i].cmd;
+ if (cmd_aid && cmd_aid->scsi_done)
+ {
+ ld(host_index)[i].cmd = NULL;
+ cmd_aid->result = DID_RESET << 16;
+ (cmd_aid->scsi_done) (cmd_aid);
+ }
+ }
+ return SCSI_RESET_SUCCESS;


X }
X
X /*--------------------------------------------------------------------*/
X

-int
-ibmmca_biosparam (Disk * disk, kdev_t dev, int *info)
+int ibmmca_biosparam (Disk * disk, kdev_t dev, int *info)
X {
- info[0] = 64;
- info[1] = 32;
- info[2] = disk->capacity / (info[0] * info[1]);
- if (info[2] >= 1024)
- {
- info[0] = 128;
- info[1] = 63;
- info[2] = disk->capacity / (info[0] * info[1]);
- if (info[2] >= 1024)
- {
- info[0] = 255;
- info[1] = 63;
- info[2] = disk->capacity / (info[0] * info[1]);
- if (info[2] >= 1024)
- info[2] = 1023;
- }
- }
- return 0;
+ info[0] = 64;
+ info[1] = 32;
+ info[2] = disk->capacity / (info[0] * info[1]);
+ if (info[2] >= 1024)
+ {
+ info[0] = 128;
+ info[1] = 63;
+ info[2] = disk->capacity / (info[0] * info[1]);
+ if (info[2] >= 1024)
+ {
+ info[0] = 255;
+ info[1] = 63;
+ info[2] = disk->capacity / (info[0] * info[1]);
+ if (info[2] >= 1024)
+ info[2] = 1023;


+ }
+ }
+ return 0;

X }
X
X /* calculate percentage of total accesses on a ldn */


-static int ldn_access_load(struct Scsi_Host *shpnt, int ldn)

+static int ldn_access_load(int host_index, int ldn)
X {
- if (IBM_DS.total_accesses == 0) return (0);
- if (IBM_DS.ldn_access[ldn] == 0) return (0);
- return (IBM_DS.ldn_access[ldn] * 100) / IBM_DS.total_accesses;
+ if (IBM_DS(host_index).total_accesses == 0) return (0);
+ if (IBM_DS(host_index).ldn_access[ldn] == 0) return (0);
+ return (IBM_DS(host_index).ldn_access[ldn] * 100) / IBM_DS(host_index).total_accesses;
X }
X
X /* calculate total amount of r/w-accesses */


-static int ldn_access_total_read_write(struct Scsi_Host *shpnt)

+static int ldn_access_total_read_write(int host_index)
X {
- int a = 0;
+ int a;
X int i;
X
+ a = 0;
X for (i=0; i<=MAX_LOG_DEV; i++)
- a+=IBM_DS.ldn_read_access[i]+IBM_DS.ldn_write_access[i];
+ a+=IBM_DS(host_index).ldn_read_access[i]+IBM_DS(host_index).ldn_write_access[i];
X return(a);
X }
X
-static int ldn_access_total_inquiry(struct Scsi_Host *shpnt)
+static int ldn_access_total_inquiry(int host_index)
X {
- int a = 0;
+ int a;
X int i;
X
+ a = 0;
X for (i=0; i<=MAX_LOG_DEV; i++)
- a+=IBM_DS.ldn_inquiry_access[i];
+ a+=IBM_DS(host_index).ldn_inquiry_access[i];
X return(a);
X }
X
-static int ldn_access_total_modeselect(struct Scsi_Host *shpnt)
+static int ldn_access_total_modeselect(int host_index)
X {
- int a = 0;
+ int a;
X int i;
X
+ a = 0;
X for (i=0; i<=MAX_LOG_DEV; i++)
- a+=IBM_DS.ldn_modeselect_access[i];
+ a+=IBM_DS(host_index).ldn_modeselect_access[i];
X return(a);
X }
X
@@ -2186,28 +2489,30 @@
X int hostno, int inout)
X {
X int len=0;
- int i,id,lun;
+ int i,id,lun,host_index;
X struct Scsi_Host *shpnt;


X unsigned long flags;
X

+#ifdef OLDKERN
+ save_flags(flags);
+ cli();
+#else

+ spin_lock_irqsave(&proc_lock, flags);
+#endif
+
X for (i = 0; hosts[i] && hosts[i]->host_no != hostno; i++);
X shpnt = hosts[i];
+ host_index = i;
X if (!shpnt) {
X len += sprintf(buffer+len, "\nCan't find adapter for host number %d\n", hostno);


X return len;
X }
X

- save_flags(flags);
- cli();
-
X len += sprintf(buffer+len, "\n IBM-SCSI-Subsystem-Linux-Driver, Version %s\n\n\n",
X IBMMCA_SCSI_DRIVER_VERSION);
X len += sprintf(buffer+len, " SCSI Access-Statistics:\n");
-#ifdef CONFIG_IBMMCA_SCSI_ORDER_STANDARD
- len += sprintf(buffer+len, " ANSI-SCSI-standard order.: Yes\n");
-#else
- len += sprintf(buffer+len, " ANSI-SCSI-standard order.: No\n");
-#endif
+ len += sprintf(buffer+len, " Device Scanning Order....: %s\n",
+ (ibm_ansi_order) ? "IBM/ANSI" : "New Industry Standard");
X #ifdef CONFIG_SCSI_MULTI_LUN
X len += sprintf(buffer+len, " Multiple LUN probing.....: Yes\n");
X #else
@@ -2215,72 +2520,74 @@
X #endif
X len += sprintf(buffer+len, " This Hostnumber..........: %d\n",
X hostno);
- len += sprintf(buffer+len, " Base I/O-Port............: 0x%lx\n",
- IM_CMD_REG);
+ len += sprintf(buffer+len, " Base I/O-Port............: 0x%x\n",
+ (unsigned int)(IM_CMD_REG(host_index)));
X len += sprintf(buffer+len, " (Shared) IRQ.............: %d\n",
X IM_IRQ);
+ len += sprintf(buffer+len, " SCSI-command set used....: %s\n",
+ (bypass_controller) ? "software" : "hardware integrated");
X len += sprintf(buffer+len, " Total Interrupts.........: %d\n",
- IBM_DS.total_interrupts);
+ IBM_DS(host_index).total_interrupts);
X len += sprintf(buffer+len, " Total SCSI Accesses......: %d\n",
- IBM_DS.total_accesses);
+ IBM_DS(host_index).total_accesses);
X len += sprintf(buffer+len, " Total SCSI READ/WRITE..: %d\n",
- ldn_access_total_read_write(shpnt));
+ ldn_access_total_read_write(host_index));
X len += sprintf(buffer+len, " Total SCSI Inquiries...: %d\n",
- ldn_access_total_inquiry(shpnt));
+ ldn_access_total_inquiry(host_index));
X len += sprintf(buffer+len, " Total SCSI Modeselects.: %d\n",
- ldn_access_total_modeselect(shpnt));
- len += sprintf(buffer+len, " Total SCSI other cmds..: %d\n\n",
- IBM_DS.total_accesses - ldn_access_total_read_write(shpnt)
- - ldn_access_total_modeselect(shpnt)
- - ldn_access_total_inquiry(shpnt));
-
+ ldn_access_total_modeselect(host_index));
+ len += sprintf(buffer+len, " Total SCSI other cmds..: %d\n",
+ IBM_DS(host_index).total_accesses - ldn_access_total_read_write(host_index)
+ - ldn_access_total_modeselect(host_index)
+ - ldn_access_total_inquiry(host_index));
+ len += sprintf(buffer+len, " Total SCSI command fails.: %d\n\n",
+ IBM_DS(host_index).total_errors);
X len += sprintf(buffer+len, " Logical-Device-Number (LDN) Access-Statistics:\n");
X len += sprintf(buffer+len, " LDN | Accesses [%%] | READ | WRITE | ASSIGNMENTS\n");
X len += sprintf(buffer+len, " -----|--------------|-----------|-----------|--------------\n");
X for (i=0; i<=MAX_LOG_DEV; i++)
X len += sprintf(buffer+len, " %2X | %3d | %8d | %8d | %8d\n",
- i, ldn_access_load(shpnt, i), IBM_DS.ldn_read_access[i],
- IBM_DS.ldn_write_access[i], IBM_DS.ldn_assignments[i]);
+ i, ldn_access_load(host_index, i), IBM_DS(host_index).ldn_read_access[i],
+ IBM_DS(host_index).ldn_write_access[i], IBM_DS(host_index).ldn_assignments[i]);
X len += sprintf(buffer+len, " -----------------------------------------------------------\n\n");
X
X len += sprintf(buffer+len, " Dynamical-LDN-Assignment-Statistics:\n");
X len += sprintf(buffer+len, " Number of physical SCSI-devices..: %d (+ Adapter)\n",
- IBM_DS.total_scsi_devices);
+ IBM_DS(host_index).total_scsi_devices);
X len += sprintf(buffer+len, " Dynamical Assignment necessaray..: %s\n",
- IBM_DS.dyn_flag ? "Yes" : "No ");
+ IBM_DS(host_index).dyn_flag ? "Yes" : "No ");
X len += sprintf(buffer+len, " Next LDN to be assigned..........: 0x%x\n",
- next_ldn);
+ next_ldn(host_index));
X len += sprintf(buffer+len, " Dynamical assignments done yet...: %d\n",
- IBM_DS.dynamical_assignments);
+ IBM_DS(host_index).dynamical_assignments);
X
X len += sprintf(buffer+len, "\n Current SCSI-Device-Mapping:\n");
X len += sprintf(buffer+len, " Physical SCSI-Device Map Logical SCSI-Device Map\n");
X len += sprintf(buffer+len, " ID\\LUN 0 1 2 3 4 5 6 7 ID\\LUN 0 1 2 3 4 5 6 7\n");
X for (id=0; id<=7; id++)
X {
- len += sprintf(buffer+len, " %2d %2s %2s %2s %2s %2s %2s %2s %2s",


- id, ti_p(get_scsi[id][0]), ti_p(get_scsi[id][1]),
- ti_p(get_scsi[id][2]), ti_p(get_scsi[id][3]),
- ti_p(get_scsi[id][4]), ti_p(get_scsi[id][5]),
- ti_p(get_scsi[id][6]), ti_p(get_scsi[id][7]));
-

- len += sprintf(buffer+len, " %2d ",id);
+ len += sprintf(buffer+len, " %2d ",id);


X for (lun=0; lun<8; lun++)

- len += sprintf(buffer+len,"%2s ",ti_l(get_ldn[id][lun]));
+ len += sprintf(buffer+len,"%2s ",ti_p(get_scsi(host_index)[id][lun]));
+ len += sprintf(buffer+len, " %2d ",id);


+ for (lun=0; lun<8; lun++)

+ len += sprintf(buffer+len,"%2s ",ti_l(get_ldn(host_index)[id][lun]));
X len += sprintf(buffer+len,"\n");
X }
X
X len += sprintf(buffer+len, "(A = IBM-Subsystem, D = Harddisk, T = Tapedrive, P = Processor, W = WORM,\n");
X len += sprintf(buffer+len, " R = CD-ROM, S = Scanner, M = MO-Drive, C = Medium-Changer, + = unprovided LUN,\n");
- len += sprintf(buffer+len, " - = nothing found)\n\n");
+ len += sprintf(buffer+len, " - = nothing found, nothing assigned or unprobed LUN)\n\n");
X
X *start = buffer + offset;
X len -= offset;
X if (len > length)
X len = length;
-
+#ifdef OLDKERN
X restore_flags(flags);
-
+#else
+ spin_unlock_irqrestore(&proc_lock, flags);
+#endif

X return len;
X }
X

@@ -2292,6 +2599,4 @@
X #endif
X
X /*--------------------------------------------------------------------*/
-
-
X
diff -u --recursive --new-file v2.2.7/linux/drivers/scsi/ibmmca.h linux/drivers/scsi/ibmmca.h
--- v2.2.7/linux/drivers/scsi/ibmmca.h Tue Feb 17 13:12:47 1998
+++ linux/drivers/scsi/ibmmca.h Tue May 11 10:36:33 1999
@@ -1,24 +1,37 @@
X #ifndef _IBMMCA_H
X #define _IBMMCA_H
X

+#ifndef LINUX_VERSION_CODE
+#include <linux/version.h>
+#endif

+
+#ifndef ibmmca_header_linux_version
+#define ibmmca_header_linux_version(v,p,s) (((v)<<16)+((p)<<8)+(s))
+#endif
+
X /*
X * Low Level Driver for the IBM Microchannel SCSI Subsystem
+ * (Headerfile, see README.ibmmca for description of the IBM MCA SCSI-driver)
X */
X
+/* Common forward declarations for all Linux-versions: */
+
X /*services provided to the higher level of Linux SCSI driver */
-int ibmmca_proc_info (char *, char **, off_t, int, int, int);
-int ibmmca_detect (Scsi_Host_Template *);
-int ibmmca_release (struct Scsi_Host *);
-int ibmmca_command (Scsi_Cmnd *);
-int ibmmca_queuecommand (Scsi_Cmnd *, void (*done) (Scsi_Cmnd *));
-int ibmmca_abort (Scsi_Cmnd *);
-int ibmmca_reset (Scsi_Cmnd *, unsigned int);
-int ibmmca_biosparam (Disk *, kdev_t, int *);
+extern int ibmmca_proc_info (char *, char **, off_t, int, int, int);
+extern int ibmmca_detect (Scsi_Host_Template *);
+extern int ibmmca_release (struct Scsi_Host *);
+extern int ibmmca_command (Scsi_Cmnd *);
+extern int ibmmca_queuecommand (Scsi_Cmnd *, void (*done) (Scsi_Cmnd *));
+extern int ibmmca_abort (Scsi_Cmnd *);
+extern int ibmmca_reset (Scsi_Cmnd *, unsigned int);
+extern int ibmmca_biosparam (Disk *, kdev_t, int *);
X
X /*structure for /proc filesystem */
X extern struct proc_dir_entry proc_scsi_ibmmca;
X
-/*initialization for Scsi_host_template type */
+#if LINUX_VERSION_CODE >= ibmmca_header_linux_version(2,1,0)
+/* Stuff for Linux >= 2.1.0: */
+/*initialization for Scsi_host_template type (Linux >= 2.1.0) */
X /*
X * 2/8/98
X * Note to maintainer of IBMMCA. Do not change this initializer back to
@@ -28,7 +41,7 @@
X #define IBMMCA { \
X proc_dir: &proc_scsi_ibmmca, /*proc_dir*/ \
X proc_info: ibmmca_proc_info, /*proc info fn*/ \
- name: "IBMMCA", /*name*/ \
+ name: "IBM SCSI-Subsystem", /*name*/ \
X detect: ibmmca_detect, /*detect fn*/ \
X release: ibmmca_release, /*release fn*/ \
X command: ibmmca_command, /*command fn*/ \
@@ -40,9 +53,37 @@
X this_id: 7, /*set by detect*/ \
X sg_tablesize: 16, /*sg_tablesize*/ \
X cmd_per_lun: 1, /*cmd_per_lun*/ \
+ unchecked_isa_dma: 0, /*32-Bit Busmaster */ \
X use_clustering: ENABLE_CLUSTERING /*use_clustering*/ \
X }
X
-#endif /* _IBMMCA_H */
+#else
+/* Stuff for Linux < 2.1.0: */
X
+/*initialization for Scsi_host_template type (Linux < 2.1.0) */
+#define IBMMCA { \
+ NULL, /*next*/ \
+ NULL, /*usage_count*/ \
+ &proc_scsi_ibmmca, /*proc_dir*/ \
+ ibmmca_proc_info, /*proc info fn*/ \
+ "IBM SCSI-Subsystem", /*name*/ \
+ ibmmca_detect, /*detect fn*/ \
+ ibmmca_release, /*release fn*/ \
+ NULL, /*info fn*/ \
+ ibmmca_command, /*command fn*/ \
+ ibmmca_queuecommand, /*queuecommand fn*/ \
+ ibmmca_abort, /*abort fn*/ \
+ ibmmca_reset, /*reset fn*/ \
+ NULL, /*slave_attach fn*/ \
+ ibmmca_biosparam, /*bios fn*/ \
+ 16, /*can_queue*/ \
+ 7, /*set by detect*/ \
+ 16, /*sg_tablesize*/ \
+ 1, /*cmd_per_lun*/ \
+ 0, /*present*/ \
+ 0, /*unchecked_isa_dma*/ \
+ ENABLE_CLUSTERING /*use_clustering*/ \
+ }
+#endif /* kernelversion selection */
X
+#endif /* _IBMMCA_H */
diff -u --recursive --new-file v2.2.7/linux/drivers/scsi/imm.c linux/drivers/scsi/imm.c
--- v2.2.7/linux/drivers/scsi/imm.c Tue Feb 23 15:21:33 1999
+++ linux/drivers/scsi/imm.c Fri May 7 10:57:42 1999
@@ -881,6 +881,7 @@
X {
X imm_struct *tmp = (imm_struct *) data;
X Scsi_Cmnd *cmd = tmp->cur_cmd;
+ unsigned long flags;
X
X if (!cmd) {
X printk("IMM: bug in imm_interrupt\n");
@@ -931,8 +932,10 @@
X if (cmd->SCp.phase > 0)
X imm_pb_release(cmd->host->unique_id);
X
+ spin_lock_irqsave(&io_request_lock, flags);
X tmp->cur_cmd = 0;
X cmd->scsi_done(cmd);
+ spin_unlock_irqrestore(&io_request_lock, flags);
X return;
X }
X
diff -u --recursive --new-file v2.2.7/linux/drivers/scsi/megaraid.c linux/drivers/scsi/megaraid.c
--- v2.2.7/linux/drivers/scsi/megaraid.c Fri Apr 16 14:47:31 1999
+++ linux/drivers/scsi/megaraid.c Thu May 6 23:14:37 1999
@@ -9,7 +9,7 @@
X * as published by the Free Software Foundation; either version
X * 2 of the License, or (at your option) any later version.
X *
- * Version : 0.96
+ * Version : 1.00
X *
X * Description: Linux device driver for AMI MegaRAID controller
X *
@@ -73,19 +73,37 @@
X *
X * Version 0.96:
X * 762 fully supported.
+ * Version 0.97:
+ * Changed megaraid_command to use wait_queue.
+ * Fixed bug of undesirably detecting HP onboard controllers which
+ * are disabled.
+ *
+ * Version 1.00:
+ * Checks to see if an irq ocurred while in isr, and runs through
+ * routine again.
+ * Copies mailbox to temp area before processing in isr
+ * Added barrier() in busy wait to fix volatility bug
+ * Uses separate list for freed Scbs, keeps track of cmd state
+ * Put spinlocks around entire queue function for now...
+ * Full multi-io commands working stablely without previous problems
+ * Added skipXX LILO option for Madrona motherboard support
+ *
X *
X * BUGS:
X * Some older 2.1 kernels (eg. 2.1.90) have a bug in pci.c that
X * fails to detect the controller as a pci device on the system.
X *
+ * Timeout period for mid scsi layer is too short for
+ * this controller. Must be increased or Aborts will occur.
+ *
X *===================================================================*/
X
X #define CRLFSTR "\n"
X
-#include <linux/config.h>
X #include <linux/version.h>
X
X #ifdef MODULE
+#include <linux/modversions.h>
X #include <linux/module.h>
X
X #if LINUX_VERSION_CODE >= 0x20100
@@ -213,14 +231,15 @@
X *
X *================================================================
X */
-static int MegaIssueCmd (mega_host_config * megaCfg,
+static int megaIssueCmd (mega_host_config * megaCfg,
X u_char * mboxData,
X mega_scb * scb,
X int intr);
X static int build_sglist (mega_host_config * megaCfg, mega_scb * scb,
X u_long * buffer, u_long * length);
X
-static void mega_runque (void *);
+static int mega_busyWaitMbox(mega_host_config *);
+static void mega_runpendq (mega_host_config *);
X static void mega_rundoneq (void);
X static void mega_cmd_done (mega_host_config *, mega_scb *, int);
X static mega_scb *mega_ioctl (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt);
@@ -241,15 +260,34 @@


SHAR_EOF
true || echo 'restore of patch-2.2.8 failed'
fi

echo 'End of part 20'
echo 'File patch-2.2.8 is continued in part 21'
echo 21 > _shar_seq_.tmp

Thomas...@ciw.uni-karlsruhe.de

unread,
May 12, 1999, 3:00:00 AM5/12/99
to
Archive-name: v2.2/patch-2.2.8/part21

#!/bin/sh
# this is part 21 of a 33 - part archive


# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.8 continued
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 21; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.8'
else
echo 'x - continuing with patch-2.2.8'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.8' &&

X *
X *================================================================
X */

+
+/* Use "megaraid=skipXX" to prohibit driver from scanning XX scsi id
+ on each channel. Used for Madrona motherboard, where SAF_TE
+ processor id cannot be scanned */
+static char *megaraid;
+#if LINUX_VERSION_CODE > 0x20100
+#ifdef MODULE
+MODULE_PARM(megaraid, "s");
+#endif
+#endif
+static int skip_id;
+
X static int numCtlrs = 0;
X static mega_host_config *megaCtlrs[12] = {0};
X
+#if DEBUG
+static u_long maxCmdTime = 0;
+#endif
+
+static mega_scb *pLastScb = NULL;
+
X /* Queue of pending/completed SCBs */
-static mega_scb *qPending = NULL;
X static Scsi_Cmnd *qCompleted = NULL;
X
+#if SERDEBUG
+volatile static spinlock_t serial_lock;
+#endif
X volatile static spinlock_t mega_lock;
-static struct tq_struct runq = {0, 0, mega_runque, NULL};
X
X struct proc_dir_entry proc_scsi_megaraid =
X {
@@ -299,10 +337,12 @@
X int i;
X long flags;
X
+ spin_lock_irqsave(&serial_lock,flags);
X va_start (args, fmt);
X i = vsprintf (strbuf, fmt, args);
X ser_puts (strbuf);
X va_end (args);
+ spin_unlock_irqrestore(&serial_lock,flags);
X
X return i;
X }
@@ -329,27 +369,28 @@
X *
X *-------------------------------------------------------------------------*/
X
-/*================================================
- * Initialize SCB structures
- *================================================
+/*=======================
+ * Free a SCB structure
+ *=======================
X */
-static int initSCB (mega_host_config * megaCfg)
+static void freeSCB (mega_host_config *megaCfg, mega_scb * pScb)
X {
- int idx;
+ mega_scb **ppScb;
X
- for (idx = 0; idx < megaCfg->max_cmds; idx++) {
- megaCfg->scbList[idx].idx = -1;
- megaCfg->scbList[idx].flag = 0;
- megaCfg->scbList[idx].sgList = kmalloc(sizeof(mega_sglist) * MAX_SGLIST,
- GFP_ATOMIC | GFP_DMA);
- if (megaCfg->scbList[idx].sgList == NULL) {
- printk(KERN_WARNING "Can't allocate sglist for id %d\n",idx);
- freeSgList(megaCfg);
- return -1;
+ /* Unlink from pending queue */
+ for(ppScb=&megaCfg->qPending; *ppScb; ppScb=&(*ppScb)->next) {
+ if (*ppScb == pScb) {
+ *ppScb = pScb->next;
+ break;
X }
- megaCfg->scbList[idx].SCpnt = NULL;


X }
- return 0;
+

+ /* Link back into list */
+ pScb->state = SCB_FREE;
+ pScb->SCpnt = NULL;
+
+ pScb->next = megaCfg->qFree;
+ megaCfg->qFree = pScb;
X }
X
X /*===========================
@@ -358,138 +399,134 @@
X */
X static mega_scb * allocateSCB (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt)
X {
- int idx;
- long flags;
-
- spin_lock_irqsave (&mega_lock, flags);
- for (idx = 0; idx < megaCfg->max_cmds; idx++) {
- if (megaCfg->scbList[idx].idx < 0) {
+ mega_scb *pScb;
X
- /* Set Index and SCB pointer */
- megaCfg->scbList[idx].idx = idx;
- spin_unlock_irqrestore (&mega_lock, flags);
- megaCfg->scbList[idx].flag = 0;
- megaCfg->scbList[idx].SCpnt = SCpnt;
- megaCfg->scbList[idx].next = NULL;
+ /* Unlink command from Free List */
+ if ((pScb = megaCfg->qFree) != NULL) {
+ megaCfg->qFree = pScb->next;
+
+ pScb->isrcount = jiffies;
+ pScb->next = NULL;
+ pScb->state = SCB_ACTIVE;
+ pScb->SCpnt = SCpnt;
X
- return &megaCfg->scbList[idx];
- }
+ return pScb;
X }
- spin_unlock_irqrestore (&mega_lock, flags);
X
X printk (KERN_WARNING "Megaraid: Could not allocate free SCB!!!\n");
X
X return NULL;
X }
X
-/*=======================
- * Free a SCB structure
- *=======================
+/*================================================
+ * Initialize SCB structures
+ *================================================
X */
-static void freeSCB (mega_scb * scb)
+static int initSCB (mega_host_config * megaCfg)
X {
- scb->flag = 0;
- scb->next = NULL;
- scb->SCpnt = NULL;
- scb->idx = -1;
+ int idx;
+
+ megaCfg->qFree = NULL;
+ for (idx = megaCfg->max_cmds-1; idx >= 0; idx--) {
+ megaCfg->scbList[idx].idx = idx;
+ megaCfg->scbList[idx].sgList = kmalloc(sizeof(mega_sglist) * MAX_SGLIST,
+ GFP_ATOMIC | GFP_DMA);
+ if (megaCfg->scbList[idx].sgList == NULL) {
+ printk(KERN_WARNING "Can't allocate sglist for id %d\n",idx);
+ freeSgList(megaCfg);


+ return -1;
+ }
+

+ if (idx < MAX_COMMANDS) {
+ /* Link to free list */
+ freeSCB(megaCfg, &megaCfg->scbList[idx]);


+ }
+ }
+ return 0;
X }
X

X /* Run through the list of completed requests */
X static void mega_rundoneq ()
X {
- mega_host_config *megaCfg;
X Scsi_Cmnd *SCpnt;
- char islogical;
X
X while (1) {
X DEQUEUE (SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
X if (SCpnt == NULL)
X return;
X
- megaCfg = (mega_host_config *) SCpnt->host->hostdata;
-
- islogical = (SCpnt->channel == megaCfg->host->max_channel &&
- SCpnt->target == 0);
- if (SCpnt->cmnd[0] == INQUIRY &&
- ((((u_char *) SCpnt->request_buffer)[0] & 0x1F) == TYPE_DISK) &&
- !islogical) {
- SCpnt->result = 0xF0;
- }
-
- /* Convert result to error */
- switch (SCpnt->result) {
- case 0x00:
- case 0x02:
- SCpnt->result |= (DID_OK << 16);
- break;
- case 0x8:
- SCpnt->result |= (DID_BUS_BUSY << 16);
- break;
- default:
- SCpnt->result |= (DID_BAD_TARGET << 16);
- break;
- }
-
X /* Callback */
X callDone (SCpnt);
X }
X }
X
-/* Add command to the list of completed requests */
-static void mega_cmd_done (mega_host_config * megaCfg, mega_scb * pScb, int status)
-{
- pScb->SCpnt->result = status;
- ENQUEUE (pScb->SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
- freeSCB (pScb);
-}
-
-/*----------------------------------------------------
- * Process pending queue list
- *
- * Run as a scheduled task
- *----------------------------------------------------*/
-static void mega_runque (void *dummy)
+/*
+ Runs through the list of pending requests
+ Assumes that mega_lock spin_lock has been acquired.
+*/
+static void mega_runpendq(mega_host_config *megaCfg)
X {
- mega_host_config *megaCfg;
X mega_scb *pScb;
- long flags;
X
- /* Take care of any completed requests */
- mega_rundoneq ();
+ /* Issue any pending commands to the card */
+ for(pScb=megaCfg->qPending; pScb; pScb=pScb->next) {
+ if (pScb->state == SCB_ACTIVE) {
+ megaIssueCmd(megaCfg, pScb->mboxData, pScb, 1);
+ }
+ }
+}
X
- DEQUEUE (pScb, mega_scb, qPending, next);
+/* Add command to the list of completed requests */
+static void mega_cmd_done (mega_host_config * megaCfg, mega_scb * pScb,
+ int status)
+{
+ int islogical;
+ Scsi_Cmnd *SCpnt;
X
- if (pScb) {
- if (pScb->SCpnt) {
- TRACE(("NULL SCpnt for idx %d!\n",pScb->idx));
- }
- megaCfg = (mega_host_config *) pScb->SCpnt->host->hostdata;
-
- if (megaCfg->mbox->busy || megaCfg->flag & (IN_ISR | PENDING)) {
- TRACE (("%.08lx %.02x <%d.%d.%d> busy%d isr%d pending%d\n",
- pScb->SCpnt->serial_number,
- pScb->SCpnt->cmnd[0],
- pScb->SCpnt->channel,
- pScb->SCpnt->target,
- pScb->SCpnt->lun,
- megaCfg->mbox->busy,
- (megaCfg->flag & IN_ISR) ? 1 : 0,
- (megaCfg->flag & PENDING) ? 1 : 0));
- }
-
- if (MegaIssueCmd (megaCfg, pScb->mboxData, pScb, 1)) {
- /* We're BUSY... come back later */
- spin_lock_irqsave (&mega_lock, flags);
- pScb->next = qPending;
- qPending = pScb;
- spin_unlock_irqrestore (&mega_lock, flags);
-
- if (!(megaCfg->flag & PENDING)) {
- /* If PENDING, irq will schedule task */
- queue_task (&runq, &tq_scheduler);
- }
- }
+ if (pScb == NULL) {
+ TRACE(("NULL pScb in mega_cmd_done!"));
+ printk("NULL pScb in mega_cmd_done!");
+ }
+
+ SCpnt = pScb->SCpnt;
+ freeSCB(megaCfg, pScb);
+
+ if (SCpnt == NULL) {
+ TRACE(("NULL SCpnt in mega_cmd_done!"));
+ TRACE(("pScb->idx = ",pScb->idx));
+ TRACE(("pScb->state = ",pScb->state));
+ TRACE(("pScb->state = ",pScb->state));
+ printk("Problem...!\n");
+ while(1);
+ }
+
+ islogical = (SCpnt->channel == megaCfg->host->max_channel &&
+ SCpnt->target == 0);
+ if (SCpnt->cmnd[0] == INQUIRY &&
+ ((((u_char *) SCpnt->request_buffer)[0] & 0x1F) == TYPE_DISK) &&
+ !islogical) {
+ status = 0xF0;
+ }
+
+ SCpnt->result = 0; /* clear result; otherwise, success returns corrupt
+ value */
+
+ /* Convert MegaRAID status to Linux error code */
+ switch (status) {
+ case 0x00: /* SUCCESS */
+ case 0x02: /* ERROR_ABORTED */
+ SCpnt->result |= (DID_OK << 16);
+ break;
+ case 0x8: /* ERR_DEST_DRIVE_FAILED */
+ SCpnt->result |= (DID_BUS_BUSY << 16);
+ break;
+ default:
+ SCpnt->result |= (DID_BAD_TARGET << 16);
+ break;
X }
+
+ /* Add Scsi_Command to end of completed queue */
+ ENQUEUE_NL(SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
X }
X
X /*-------------------------------------------------------------------
@@ -500,7 +537,8 @@
X * If NULL is returned, the scsi_done function MUST have been called
X *
X *-------------------------------------------------------------------*/
-static mega_scb * mega_build_cmd (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt)
+static mega_scb * mega_build_cmd (mega_host_config * megaCfg,
+ Scsi_Cmnd * SCpnt)
X {
X mega_scb *pScb;
X mega_mailbox *mbox;
@@ -508,6 +546,11 @@
X long seg;
X char islogical;
X
+ if (SCpnt == NULL) {
+ printk("NULL SCpnt in mega_build_cmd!\n");
+ while(1);
+ }
+
X if (SCpnt->cmnd[0] & 0x80) /* ioctl from megamgr */
X return mega_ioctl (megaCfg, SCpnt);
X
@@ -519,6 +562,12 @@
X return NULL;
X }
X
+ if (!islogical && SCpnt->target == skip_id) {
+ SCpnt->result = (DID_BAD_TARGET << 16);
+ callDone (SCpnt);


+ return NULL;
+ }
+

X /*-----------------------------------------------------
X *
X * Logical drive commands
@@ -738,6 +787,21 @@
X return (pScb);
X }
X
+#if DEBUG
+static void showMbox(mega_scb *pScb)
+{
+ mega_mailbox *mbox;
+
+ if (pScb == NULL) return;
+
+ mbox = (mega_mailbox *)pScb->mboxData;
+ printk("%u cmd:%x id:%x #scts:%x lba:%x addr:%x logdrv:%x #sg:%x\n",
+ pScb->SCpnt->pid,
+ mbox->cmd, mbox->cmdid, mbox->numsectors,
+ mbox->lba, mbox->xferaddr, mbox->logdrv,
+ mbox->numsgelements);
+}
+#endif
X
X /*--------------------------------------------------------------------
X * Interrupt service routine
@@ -745,7 +809,7 @@
X static void megaraid_isr (int irq, void *devp, struct pt_regs *regs)
X {
X mega_host_config *megaCfg;
- u_char byte, idx, sIdx;
+ u_char byte, idx, sIdx, tmpBox[MAILBOX_SIZE];
X u_long dword;
X mega_mailbox *mbox;
X mega_scb *pScb;
@@ -753,14 +817,14 @@
X int qCnt, qStatus;
X
X megaCfg = (mega_host_config *) devp;
- mbox = (mega_mailbox *) megaCfg->mbox;
-
- if (megaCfg->host->irq == irq) {
+ mbox = (mega_mailbox *)tmpBox;


X
X #if LINUX_VERSION_CODE >= 0x20100

- spin_lock_irqsave (&io_request_lock, flags);
+ spin_lock_irqsave (&io_request_lock, flags);
X #endif
X
+ while (megaCfg->host->irq == irq) {
+
X spin_lock_irqsave (&mega_lock, flags);
X
X if (megaCfg->flag & IN_ISR) {
@@ -769,6 +833,11 @@
X
X megaCfg->flag |= IN_ISR;
X
+ if (mega_busyWaitMbox(megaCfg)) {
+ printk(KERN_WARNING "Error: mailbox busy in isr!\n");
+ }
+
+
X /* Check if a valid interrupt is pending */
X if (megaCfg->flag & BOARD_QUARTZ) {
X dword = RDOUTDOOR (megaCfg);
@@ -776,12 +845,16 @@
X /* Spurious interrupt */
X megaCfg->flag &= ~IN_ISR;
X spin_unlock_irqrestore (&mega_lock, flags);
-#if LINUX_VERSION_CODE >= 0x20100
- spin_unlock_irqrestore (&io_request_lock, flags);
-#endif
- return;
+ break;
X }
X WROUTDOOR (megaCfg, dword);
+
+ /* Copy to temp location */
+ memcpy(tmpBox, (mega_mailbox *)megaCfg->mbox, MAILBOX_SIZE);
+
+ /* Acknowledge interrupt */
+ WRINDOOR (megaCfg, virt_to_bus (megaCfg->mbox) | 0x2);
+ while (RDINDOOR (megaCfg) & 0x02);
X }
X else {
X byte = READ_PORT (megaCfg->host->io_port, INTR_PORT);
@@ -789,71 +862,74 @@
X /* Spurious interrupt */
X megaCfg->flag &= ~IN_ISR;
X spin_unlock_irqrestore (&mega_lock, flags);
-#if LINUX_VERSION_CODE >= 0x20100
- spin_unlock_irqrestore (&io_request_lock, flags);
-#endif
- return;
+ break;
X }
X WRITE_PORT (megaCfg->host->io_port, INTR_PORT, byte);
+
+ /* Copy to temp location */
+ memcpy(tmpBox, (mega_mailbox *)megaCfg->mbox, MAILBOX_SIZE);
+
+ /* Acknowledge interrupt */
+ CLEAR_INTR (megaCfg->host->io_port);
X }
X
X qCnt = mbox->numstatus;
X qStatus = mbox->status;
X
- if (qCnt > 1) {
- TRACE (("ISR: Received %d status\n", qCnt))
- printk (KERN_DEBUG "Got numstatus = %d\n", qCnt);
- }
-
X for (idx = 0; idx < qCnt; idx++) {
X sIdx = mbox->completed[idx];
X if (sIdx > 0) {
X pScb = &megaCfg->scbList[sIdx - 1];
- /* FVF: let's try to avoid un/locking for no good reason */
- pScb->SCpnt->result = qStatus;
- ENQUEUE_NL (pScb->SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
- freeSCB (pScb);
+
+ /* ASSERT(pScb->state == SCB_ISSUED); */
+
+#if DEBUG
+ if (((jiffies) - pScb->isrcount) > maxCmdTime) {
+ maxCmdTime = (jiffies) - pScb->isrcount;
+ printk("cmd time = %u\n", maxCmdTime);
+ }
+#endif
+
+ if (pScb->state == SCB_ABORTED) {
+ printk("Received aborted SCB! %u\n", (int)((jiffies)-pScb->isrcount));
+ }
+
+ /* Mark command as completed */
+ mega_cmd_done(megaCfg, pScb, qStatus);
X }
+
X }
- if (megaCfg->flag & BOARD_QUARTZ) {
- WRINDOOR (megaCfg, virt_to_bus (megaCfg->mbox) | 0x2);
- while (RDINDOOR (megaCfg) & 0x02);
- }
- else {
- CLEAR_INTR (megaCfg->host->io_port);
- }
+ spin_unlock_irqrestore (&mega_lock, flags);
X
X megaCfg->flag &= ~IN_ISR;
- megaCfg->flag &= ~PENDING;
X
- spin_unlock_irqrestore (&mega_lock, flags);
- mega_runque (NULL);
+ mega_rundoneq();
X
-#if LINUX_VERSION_CODE >= 0x20100
- spin_unlock_irqrestore (&io_request_lock, flags);
-#endif
+ /* Loop through any pending requests */
+ spin_lock_irqsave(&mega_lock, flags);
+ mega_runpendq(megaCfg);
+ spin_unlock_irqrestore(&mega_lock,flags);
+ }
X
-#if 0
- /* Queue as a delayed ISR routine */
- queue_task_irq_off (&runq, &tq_immediate);
- mark_bh (IMMEDIATE_BH);
+#if LINUX_VERSION_CODE >= 0x20100
+ spin_unlock_irqrestore (&io_request_lock, flags);
X #endif
-
- }
X }
X
X /*==================================================*/
X /* Wait until the controller's mailbox is available */
X /*==================================================*/
-static int busyWaitMbox (mega_host_config * megaCfg)
+static int mega_busyWaitMbox (mega_host_config * megaCfg)
X {
X mega_mailbox *mbox = (mega_mailbox *) megaCfg->mbox;
X long counter;
X
X for (counter = 0; counter < 10000; counter++) {
- udelay (100);
- if (!mbox->busy)
+ if (!mbox->busy) {
X return 0;
+ }
+ udelay (100);
+ barrier();
X }
X return -1; /* give up after 1 second */
X }
@@ -868,47 +944,55 @@
X * int intr - if 1, interrupt, 0 is blocking
X *=====================================================


X */
-static int MegaIssueCmd (mega_host_config * megaCfg,
+static int megaIssueCmd (mega_host_config * megaCfg,
X u_char * mboxData,

X mega_scb * pScb,
X int intr)
X {
X mega_mailbox *mbox = (mega_mailbox *) megaCfg->mbox;
- long flags;
X u_char byte;
X u_long cmdDone;
-
- mboxData[0x1] = (pScb ? pScb->idx + 1 : 0x00); /* Set cmdid */
+ Scsi_Cmnd *SCpnt;
+
+ mboxData[0x1] = (pScb ? pScb->idx + 1: 0x0); /* Set cmdid */
X mboxData[0xF] = 1; /* Set busy */
X
- spin_lock_irqsave(&mega_lock,flags);
-
-#ifndef CONFIG_MEGARAID_MULTI_IO
- if (megaCfg->flag & PENDING) {
- spin_unlock_irqrestore(&mega_lock,flags);
- return -1;
+#if 0
+ if (intr && mbox->busy) {
+ return 0;
X }
X #endif
X
X /* Wait until mailbox is free */
- if (busyWaitMbox (megaCfg)) {
- if (pScb) {
- TRACE (("Mailbox busy %.08lx <%d.%d.%d>\n", pScb->SCpnt->serial_number,
- pScb->SCpnt->channel, pScb->SCpnt->target, pScb->SCpnt->lun));
- } else {
- TRACE(("pScb NULL in MegaIssueCmd!\n"));
+ while (mega_busyWaitMbox (megaCfg)) {
+ printk("Blocked mailbox!!\n");
+ udelay(1000);
+
+#if DEBUG
+ showMbox(pLastScb);
+#endif
+
+ /* Abort command */
+ if (pScb == NULL) {
+ printk("NULL pScb in megaIssue\n");
+ TRACE(("NULL pScb in megaIssue\n"));
X }
- spin_unlock_irqrestore(&mega_lock,flags);
- return -1;
+ SCpnt = pScb->SCpnt;
+ freeSCB(megaCfg, pScb);
+
+ SCpnt->result = (DID_ABORT << 16);
+ callDone(SCpnt);
+ return 0;
X }
+ pLastScb = pScb;
X
+
X /* Copy mailbox data into host structure */
- memset (mbox, 0, 16);
X memcpy (mbox, mboxData, 16);
X
X /* Kick IO */
- megaCfg->flag |= PENDING;
X if (intr) {
+
X /* Issue interrupt (non-blocking) command */
X if (megaCfg->flag & BOARD_QUARTZ) {
X mbox->mraid_poll = 0;
@@ -919,12 +1003,11 @@
X ENABLE_INTR (megaCfg->host->io_port);
X ISSUE_COMMAND (megaCfg->host->io_port);
X }
- spin_unlock_irqrestore(&mega_lock,flags);
+ pScb->state = SCB_ISSUED;
X }
X else { /* Issue non-ISR (blocking) command */
-
+ disable_irq(megaCfg->host->irq);
X if (megaCfg->flag & BOARD_QUARTZ) {
-
X mbox->mraid_poll = 0;
X mbox->mraid_ack = 0;
X WRINDOOR (megaCfg, virt_to_bus (megaCfg->mbox) | 0x1);
@@ -932,7 +1015,6 @@
X while ((cmdDone = RDOUTDOOR (megaCfg)) != 0x10001234);
X WROUTDOOR (megaCfg, cmdDone);
X
- spin_unlock_irqrestore(&mega_lock,flags);
X if (pScb) {
X mega_cmd_done (megaCfg, pScb, mbox->status);
X mega_rundoneq ();
@@ -941,8 +1023,6 @@
X WRINDOOR (megaCfg, virt_to_bus (megaCfg->mbox) | 0x2);
X while (RDINDOOR (megaCfg) & 0x2);
X
- megaCfg->flag &= ~PENDING;
-
X }
X else {
X DISABLE_INTR (megaCfg->host->io_port);
@@ -954,8 +1034,6 @@
X
X ENABLE_INTR (megaCfg->host->io_port);
X CLEAR_INTR (megaCfg->host->io_port);
- megaCfg->flag &= ~PENDING;
- spin_unlock_irqrestore(&mega_lock,flags);
X
X if (pScb) {
X mega_cmd_done (megaCfg, pScb, mbox->status);
@@ -966,6 +1044,11 @@
X }
X
X }
+ enable_irq(megaCfg->host->irq);
+ }
+ while (mega_busyWaitMbox (megaCfg)) {
+ printk("Blocked mailbox on exit!\n");
+ udelay(1000);
X }
X
X return 0;
@@ -1058,6 +1141,7 @@
X u_long paddr;
X
X spin_lock_init (&mega_lock);
+
X /* Initialize adapter inquiry */
X paddr = virt_to_bus (megaCfg->mega_buffer);
X mbox = (mega_mailbox *) mboxData;
@@ -1070,7 +1154,7 @@
X mbox->xferaddr = paddr;
X
X /* Issue a blocking command to the card */
- MegaIssueCmd (megaCfg, mboxData, NULL, 0);
+ megaIssueCmd (megaCfg, mboxData, NULL, 0);
X
X /* Initialize host/local structures with Adapter info */
X adapterInfo = (mega_RAIDINQ *) megaCfg->mega_buffer;
@@ -1136,7 +1220,7 @@
X * Returns data to be displayed in /proc/scsi/megaraid/X
X *----------------------------------------------------------*/
X int megaraid_proc_info (char *buffer, char **start, off_t offset,
- int length, int inode, int inout)
+ int length, int host_no, int inout)
X {
X *start = buffer;
X return 0;
@@ -1150,35 +1234,33 @@
X struct Scsi_Host *host;
X u_char pciBus, pciDevFun, megaIrq;
X u_long megaBase;
- u_short pciIdx = 0;
+ u_short jdx,pciIdx = 0;
X u_short numFound = 0;
X
X #if LINUX_VERSION_CODE < 0x20100
X while (!pcibios_find_device (pciVendor, pciDev, pciIdx, &pciBus, &pciDevFun)) {
-#if 0
- if (flag & BOARD_QUARTZ) {
- u_int magic;
- pcibios_read_config_dword (pciBus, pciDevFun,
- PCI_CONF_AMISIG,
- &magic);
- if (magic != AMI_SIGNATURE) {
- pciIdx++;
- continue; /* not an AMI board */
- }
- }
-#endif
X
X #if 0
- } /* keep auto-indenters happy */
+ } /* keep auto-indenters happy */
X #endif
-
X #else
+
X struct pci_dev *pdev = pci_devices;
-
+
X while ((pdev = pci_find_device (pciVendor, pciDev, pdev))) {
X pciBus = pdev->bus->number;
X pciDevFun = pdev->devfn;
X #endif
+ if (flag & BOARD_QUARTZ) {
+ u_short magic;
+ pcibios_read_config_word (pciBus, pciDevFun,
+ PCI_CONF_AMISIG,
+ &magic);
+ if (magic != AMI_SIGNATURE) {
+ pciIdx++;
+ continue; /* not an AMI board */
+ }
+ }
X printk (KERN_INFO "megaraid: found 0x%4.04x:0x%4.04x:idx %d:bus %d:slot %d:fun %d\n",
X pciVendor,
X pciDev,
@@ -1196,7 +1278,7 @@
X &megaIrq);
X #else
X megaBase = pdev->base_address[0];
- megaIrq = pdev->irq;
+ megaIrq = pdev->irq;
X #endif
X pciIdx++;
X
@@ -1214,10 +1296,12 @@
X megaCfg = (mega_host_config *) host->hostdata;
X memset (megaCfg, 0, sizeof (mega_host_config));
X
- printk (KERN_INFO " scsi%d: Found a MegaRAID controller at 0x%x, IRQ: %d" CRLFSTR,
+ printk (" scsi%d: Found a MegaRAID controller at 0x%x, IRQ: %d" CRLFSTR,
X host->host_no, (u_int) megaBase, megaIrq);
X
X /* Copy resource info into structure */
+ megaCfg->qPending = NULL;
+ megaCfg->qFree = NULL;
X megaCfg->flag = flag;
X megaCfg->host = host;
X megaCfg->base = megaBase;
@@ -1248,11 +1332,16 @@
X
X mega_register_mailbox (megaCfg, virt_to_bus ((void *) &megaCfg->mailbox));
X mega_i_query_adapter (megaCfg);
+
+ for(jdx=0; jdx<MAX_LOGICAL_DRIVES; jdx++) {
+ megaCfg->nReads[jdx] = 0;
+ megaCfg->nWrites[jdx] = 0;
+ }
X
X /* Initialize SCBs */
X if (initSCB (megaCfg)) {
- scsi_unregister (host);
- continue;
+ scsi_unregister (host);
+ continue;
X }
X
X numFound++;
@@ -1275,6 +1364,16 @@
X return 0;
X }
X #endif
+ skip_id = -1;
+ if (megaraid && !strncmp(megaraid,"skip",strlen("skip"))) {
+ if (megaraid[4] != '\0') {
+ skip_id = megaraid[4] - '0';
+ if (megaraid[5] != '\0') {
+ skip_id = (skip_id * 10) + (megaraid[5] - '0');
+ }
+ }
+ skip_id = (skip_id > 15) ? -1 : skip_id;
+ }
X
X count += findCard (pHostTmpl, 0x101E, 0x9010, 0);
X count += findCard (pHostTmpl, 0x101E, 0x9060, 0);
@@ -1299,10 +1398,11 @@
X memset (mbox, 0, 16);
X mboxData[0] = 0xA;
X
- /* Issue a blocking (interrupts disabled) command to the card */
- MegaIssueCmd (megaCfg, mboxData, NULL, 0);
+ free_irq (megaCfg->host->irq, megaCfg);/* Must be freed first, otherwise
+ extra interrupt is generated */
X
- schedule ();
+ /* Issue a blocking (interrupts disabled) command to the card */
+ megaIssueCmd (megaCfg, mboxData, NULL, 0);
X
X /* Free our resources */
X if (megaCfg->flag & BOARD_QUARTZ) {
@@ -1311,9 +1411,7 @@
X else {
X release_region (megaCfg->host->io_port, 16);
X }
- free_irq (megaCfg->host->irq, megaCfg); /* Must be freed first, otherwise
X
- extra interrupt is generated */
X freeSgList(megaCfg);
X scsi_unregister (pSHost);
X
@@ -1369,6 +1467,9 @@
X {
X mega_host_config *megaCfg;
X mega_scb *pScb;
+ long flags;
+
+ spin_lock_irqsave(&mega_lock,flags);
X
X megaCfg = (mega_host_config *) SCpnt->host->hostdata;
X
@@ -1381,15 +1482,38 @@
X
X SCpnt->scsi_done = pktComp;
X
+ /* If driver in abort or reset.. cancel this command */
+ if (megaCfg->flag & IN_ABORT) {
+ SCpnt->result = (DID_ABORT << 16);
+ ENQUEUE_NL(SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
+
+ spin_unlock_irqrestore(&mega_lock,flags);
+ return 0;
+ }
+ else if (megaCfg->flag & IN_RESET) {
+ SCpnt->result = (DID_RESET << 16);
+ ENQUEUE_NL(SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
+
+ spin_unlock_irqrestore(&mega_lock,flags);


+ return 0;
+ }
+

X /* Allocate and build a SCB request */
X if ((pScb = mega_build_cmd (megaCfg, SCpnt)) != NULL) {
X /* Add SCB to the head of the pending queue */
- ENQUEUE (pScb, mega_scb, qPending, next);
+ ENQUEUE_NL (pScb, mega_scb, megaCfg->qPending, next);
X
- /* Issue the command to the card */
- mega_runque (NULL);
+ /* Issue any pending command to the card if not in ISR */
+ if (!(megaCfg->flag & IN_ISR)) {
+ mega_runpendq(megaCfg);
+ }
+ else {
+ printk("IRQ pend...\n");
+ }
X }
X
+ spin_unlock_irqrestore(&mega_lock,flags);
+


X return 0;
X }
X

@@ -1398,31 +1522,16 @@
X *----------------------------------------------------------------------*/
X volatile static int internal_done_flag = 0;
X volatile static int internal_done_errcode = 0;
+static struct wait_queue *internal_wait = NULL;
X
X static void internal_done (Scsi_Cmnd * SCpnt)
X {
X internal_done_errcode = SCpnt->result;
X internal_done_flag++;
+ wake_up(&internal_wait);
X }
X
-/*
- * This seems dangerous in an SMP environment because
- * while spinning on internal_done_flag in 2.0.x SMP
- * no IRQ's will be taken, including those that might
- * be needed to clear this.
- *
- * I think this should be using a wait queue ?
- * -- AC
- */
-
-/*
- * I'll probably fix this in the next version, but
- * megaraid_command() will never get called since can_queue is set,
- * except maybe in a *really* old kernel in which case it's very
- * unlikely they'd be using SMP anyway. Really this function is
- * just here for completeness.
- * - JLJ
- */
+/* shouldn't be used, but included for completeness */
X
X int megaraid_command (Scsi_Cmnd * SCpnt)
X {
@@ -1431,8 +1540,9 @@
X /* Queue command, and wait until it has completed */
X megaraid_queue (SCpnt, internal_done);
X
- while (!internal_done_flag)
- barrier ();
+ while (!internal_done_flag) {
+ interruptible_sleep_on(&internal_wait);
+ }
X
X return internal_done_errcode;
X }
@@ -1443,31 +1553,77 @@
X int megaraid_abort (Scsi_Cmnd * SCpnt)
X {
X mega_host_config *megaCfg;
- int idx;
- long flags;
+ int rc, idx;
+ long flags;
+ mega_scb *pScb;
+
+ rc = SCSI_ABORT_SUCCESS;
X
X spin_lock_irqsave (&mega_lock, flags);
X
X megaCfg = (mega_host_config *) SCpnt->host->hostdata;
X
+ megaCfg->flag |= IN_ABORT;
+
+ for(pScb=megaCfg->qPending; pScb; pScb=pScb->next) {
+ if (pScb->SCpnt == SCpnt) {
+ /* Found an aborting command */
+#if DEBUG
+ showMbox(pScb);
+#endif
+
+ printk("Abort: %d %u\n",
+ SCpnt->timeout_per_command,
+ (uint)((jiffies) - pScb->isrcount));
+
+ switch(pScb->state) {
+ case SCB_ABORTED: /* Already aborted */
+ rc = SCSI_ABORT_SNOOZE;
+ break;
+ case SCB_ISSUED: /* Waiting on ISR result */
+ rc = SCSI_ABORT_PENDING;
+ pScb->state = SCB_ABORTED;


+ break;
+ }
+ }
+ }

+
+#if 0
X TRACE (("ABORT!!! %.08lx %.02x <%d.%d.%d>\n",
- SCpnt->serial_number, SCpnt->cmnd[0], SCpnt->channel, SCpnt->target,
+ SCpnt->serial_number, SCpnt->cmnd[0], SCpnt->channel, SCpnt->target,
X SCpnt->lun));
+ for(pScb=megaCfg->qPending; pScb; pScb=pScb->next) {
+ if (pScb->SCpnt == SCpnt) {
+ ser_printk("** %d<%x> %c\n", pScb->SCpnt->pid, pScb->idx+1,
+ pScb->state == SCB_ACTIVE ? 'A' : 'I');
+#if DEBUG
+ showMbox(pScb);
+#endif
+ }
+ }
+#endif
+
X /*
X * Walk list of SCBs for any that are still outstanding
X */
X for (idx = 0; idx < megaCfg->max_cmds; idx++) {
- if (megaCfg->scbList[idx].idx >= 0) {
+ if (megaCfg->scbList[idx].state != SCB_FREE) {
X if (megaCfg->scbList[idx].SCpnt == SCpnt) {
- freeSCB (&megaCfg->scbList[idx]);
+ freeSCB (megaCfg, &megaCfg->scbList[idx]);
X
- SCpnt->result = (DID_RESET << 16) | (SUGGEST_RETRY << 24);
- callDone (SCpnt);
+ SCpnt->result = (DID_ABORT << 16) | (SUGGEST_RETRY << 24);
+ ENQUEUE_NL(SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
X }
X }
X }
+
+ megaCfg->flag &= ~IN_ABORT;
+
X spin_unlock_irqrestore (&mega_lock, flags);
- return SCSI_ABORT_SNOOZE;
+
+ mega_rundoneq();
+
+ return rc;
X }
X
X /*---------------------------------------------------------------------
@@ -1483,6 +1639,8 @@
X
X megaCfg = (mega_host_config *) SCpnt->host->hostdata;
X
+ megaCfg->flag |= IN_RESET;
+
X TRACE (("RESET: %.08lx %.02x <%d.%d.%d>\n",
X SCpnt->serial_number, SCpnt->cmnd[0], SCpnt->channel, SCpnt->target,
X SCpnt->lun));
@@ -1491,14 +1649,21 @@
X * Walk list of SCBs for any that are still outstanding
X */
X for (idx = 0; idx < megaCfg->max_cmds; idx++) {
- if (megaCfg->scbList[idx].idx >= 0) {
+ if (megaCfg->scbList[idx].state != SCB_FREE) {
X SCpnt = megaCfg->scbList[idx].SCpnt;
- freeSCB (&megaCfg->scbList[idx]);
- SCpnt->result = (DID_RESET << 16) | (SUGGEST_RETRY << 24);
- callDone (SCpnt);
+ if (SCpnt != NULL) {
+ freeSCB (megaCfg, &megaCfg->scbList[idx]);
+ SCpnt->result = (DID_RESET << 16) | (SUGGEST_RETRY << 24);
+ ENQUEUE_NL(SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
+ }
X }
X }
+
+ megaCfg->flag &= ~IN_RESET;
+
X spin_unlock_irqrestore (&mega_lock, flags);
+
+ mega_rundoneq();
X return SCSI_RESET_PUNT;
X }
X
diff -u --recursive --new-file v2.2.7/linux/drivers/scsi/megaraid.h linux/drivers/scsi/megaraid.h
--- v2.2.7/linux/drivers/scsi/megaraid.h Fri Apr 16 14:47:31 1999
+++ linux/drivers/scsi/megaraid.h Tue May 11 10:36:36 1999
@@ -6,24 +6,23 @@
X #endif
X
X #define IN_ISR 0x80000000L
-#define NO_INTR 0x40000000L
-#define IN_TIMEOUT 0x20000000L
-#define PENDING 0x10000000L
+#define IN_ABORT 0x40000000L
+#define IN_RESET 0x20000000L
X #define BOARD_QUARTZ 0x08000000L
X
-#define SCB_ACTIVE 0x1
-#define SCB_WAITQ 0x2
-#define SCB_ISSUED 0x4
-
-#define SCB_FREE -1
-#define SCB_RESET -2
-#define SCB_ABORT -3
-#define SCB_LOCKED -4
+#define SCB_FREE 0x0
+#define SCB_ACTIVE 0x1
+#define SCB_WAITQ 0x2
+#define SCB_ISSUED 0x3
+#define SCB_COMPLETE 0x4
+#define SCB_ABORTED 0x5
+#define SCB_RESET 0x6
X
X #define MEGA_CMD_TIMEOUT 10
X
X #define MAX_SGLIST 17
-#define MAX_COMMANDS 254
+#define MAX_COMMANDS 250
+#define MAX_CMD_PER_LUN 63
X
X #define MAX_LOGICAL_DRIVES 8
X #define MAX_CHANNEL 5
@@ -99,7 +98,7 @@
X #define PCI_CONF_BASE_ADDR_OFFSET 0x10
X #define PCI_CONF_IRQ_OFFSET 0x3c
X #define PCI_CONF_AMISIG 0xa0
-#define AMI_SIGNATURE 0x11223344
+#define AMI_SIGNATURE 0x3344
X
X #if LINUX_VERSION_CODE < 0x20100
X #define MEGARAID \
@@ -117,11 +116,11 @@
X megaraid_reset, /* Reset Command Function */\
X NULL, /* Slave Attach Function */\
X megaraid_biosparam, /* Disk BIOS Parameters */\
- 254, /* # of cmds that can be\
+ MAX_COMMANDS, /* # of cmds that can be\
X outstanding at any time */\
X 7, /* HBA Target ID */\
X MAX_SGLIST, /* Scatter/Gather Table Size */\
- 64, /* SCSI Commands per LUN */\
+ MAX_CMD_PER_LUN, /* SCSI Commands per LUN */\
X 0, /* Present */\
X 0, /* Default Unchecked ISA DMA */\
X ENABLE_CLUSTERING } /* Enable Clustering */
@@ -138,10 +137,10 @@
X abort: megaraid_abort, /* Abort Command Function */\
X reset: megaraid_reset, /* Reset Command Function */\
X bios_param: megaraid_biosparam, /* Disk BIOS Parameters */\
- can_queue: 1 /* MAX_COMMANDS */, /* Can Queue */\
+ can_queue: MAX_COMMANDS, /* Can Queue */\
X this_id: 7, /* HBA Target ID */\
X sg_tablesize: MAX_SGLIST, /* Scatter/Gather Table Size */\
- cmd_per_lun: 64, /* SCSI Commands per LUN */\
+ cmd_per_lun: MAX_CMD_PER_LUN, /* SCSI Commands per LUN */\
X present: 0, /* Present */\
X unchecked_isa_dma:0, /* Default Unchecked ISA DMA */\
X use_clustering: ENABLE_CLUSTERING /* Enable Clustering */\
@@ -250,13 +249,14 @@
X typedef struct _mega_scb mega_scb;
X
X struct _mega_scb {
- int idx;
- u_long flag;
- Scsi_Cmnd *SCpnt;
- u_char mboxData[16];
- mega_passthru pthru;
- mega_sglist *sgList;
- mega_scb *next;
+ int idx;
+ u_long state;
+ u_long isrcount;
+ u_char mboxData[16];
+ mega_passthru pthru;
+ Scsi_Cmnd *SCpnt;
+ mega_sglist *sgList;
+ mega_scb *next;
X };
X
X /* Per-controller data */
@@ -264,8 +264,12 @@
X u_char numldrv;
X u_long flag;
X u_long base;
+
+ mega_scb *qFree;
+ mega_scb *qPending;
X
- struct tq_struct megaTq;
+ u_long nReads[MAX_LOGICAL_DRIVES];
+ u_long nWrites[MAX_LOGICAL_DRIVES];
X
X /* Host adapter parameters */
X u_char fwVer[7];
diff -u --recursive --new-file v2.2.7/linux/drivers/scsi/ppa.c linux/drivers/scsi/ppa.c
--- v2.2.7/linux/drivers/scsi/ppa.c Mon Mar 29 11:09:11 1999
+++ linux/drivers/scsi/ppa.c Fri May 7 10:57:42 1999
@@ -741,6 +741,7 @@
X {
X ppa_struct *tmp = (ppa_struct *) data;


X Scsi_Cmnd *cmd = tmp->cur_cmd;
+ unsigned long flags;
X
X if (!cmd) {

X printk("PPA: bug in ppa_interrupt\n");
@@ -792,7 +793,10 @@
X ppa_pb_release(cmd->host->unique_id);
X

X tmp->cur_cmd = 0;

+
+ spin_lock_irqsave(&io_request_lock, flags);


X cmd->scsi_done(cmd);
+ spin_unlock_irqrestore(&io_request_lock, flags);
X return;
X }
X

diff -u --recursive --new-file v2.2.7/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c
--- v2.2.7/linux/drivers/scsi/scsi.c Tue Mar 23 14:35:48 1999
+++ linux/drivers/scsi/scsi.c Thu Apr 29 11:53:41 1999
@@ -1926,10 +1926,12 @@
X SDpnt->device_queue = NULL;
X
X for(j=0;j<SDpnt->queue_depth;j++){
- SCpnt = (Scsi_Cmnd *)
+ SCpnt = (Scsi_Cmnd *)
X scsi_init_malloc(sizeof(Scsi_Cmnd),
X GFP_ATOMIC |
X (host->unchecked_isa_dma ? GFP_DMA : 0));
+ if (NULL == SCpnt)
+ break; /* If not, the next line will oops ... */
X memset(&SCpnt->eh_timeout, 0, sizeof(SCpnt->eh_timeout));
X SCpnt->host = host;
X SCpnt->device = SDpnt;
@@ -1951,6 +1953,12 @@
X SDpnt->device_queue = SCpnt;
X SCpnt->state = SCSI_STATE_UNUSED;
X SCpnt->owner = SCSI_OWNER_NOBODY;
+ }
+ if (j < SDpnt->queue_depth) { /* low on space (D.Gilbert 990424) */
+ printk("scsi_build_commandblocks: want=%d, space for=%d blocks\n",
+ SDpnt->queue_depth, j);
+ SDpnt->queue_depth = j;
+ /* Still problem if 0==j , continue anyway ... */
X }
X SDpnt->has_cmdblocks = 1;
X }
diff -u --recursive --new-file v2.2.7/linux/drivers/scsi/scsi_ioctl.c linux/drivers/scsi/scsi_ioctl.c
--- v2.2.7/linux/drivers/scsi/scsi_ioctl.c Wed Sep 9 14:51:09 1998
+++ linux/drivers/scsi/scsi_ioctl.c Thu Apr 29 11:53:41 1999
@@ -131,15 +131,16 @@
X else printk("SCSI device (ioctl) reports ILLEGAL REQUEST.\n");
X break;
X case NOT_READY: /* This happens if there is no disc in drive */
- if(dev->removable){
+ if(dev->removable && (cmd[0] != TEST_UNIT_READY)){
X printk(KERN_INFO "Device not ready. Make sure there is a disc in the drive.\n");
X break;
- };
+ }
X case UNIT_ATTENTION:
X if (dev->removable){
X dev->changed = 1;
X SCpnt->result = 0; /* This is no longer considered an error */
- printk(KERN_INFO "Disc change detected.\n");
+ /* gag this error, VFS will log it anyway /axboe */
+ /* printk(KERN_INFO "Disc change detected.\n"); */
X break;
X };
X default: /* Fall through for non-removable media */
diff -u --recursive --new-file v2.2.7/linux/drivers/scsi/sd.c linux/drivers/scsi/sd.c
--- v2.2.7/linux/drivers/scsi/sd.c Tue Feb 23 15:21:34 1999
+++ linux/drivers/scsi/sd.c Thu Apr 29 11:53:41 1999
@@ -719,6 +719,12 @@
X SCpnt = end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors);
X goto repeat;
X }
+ if (rscsi_disks[dev].sector_size == 4096)
+ if((block & 7) || (SCpnt->request.nr_sectors & 7)) {
+ printk("sd.cBad block number/count requested");
+ SCpnt = end_scsi_request(SCpnt, 0, SCpnt->request.nr_sectors);
+ goto repeat;
+ }
X
X switch (SCpnt->request.cmd)
X {
@@ -984,6 +990,13 @@
X
X cmd[1] = (SCpnt->lun << 5) & 0xe0;
X
+ if (rscsi_disks[dev].sector_size == 4096){
+ if(block & 7) panic("sd.c:Bad block number requested");
+ if(this_count & 7) panic("sd.c:Bad block number requested");
+ block = block >> 3;
+ this_count = block >> 3;
+ }
+
X if (rscsi_disks[dev].sector_size == 2048){
X if(block & 3) panic("sd.c:Bad block number requested");
X if(this_count & 3) panic("sd.c:Bad block number requested");
@@ -1335,6 +1348,7 @@
X if (rscsi_disks[i].sector_size != 512 &&
X rscsi_disks[i].sector_size != 1024 &&
X rscsi_disks[i].sector_size != 2048 &&
+ rscsi_disks[i].sector_size != 4096 &&
X rscsi_disks[i].sector_size != 256)
X {
X printk ("%s : unsupported sector size %d.\n",
@@ -1394,6 +1408,8 @@
X nbuff, hard_sector, rscsi_disks[i].capacity,
X mb, sz_quot, sz_rem);
X }
+ if(rscsi_disks[i].sector_size == 4096)
+ rscsi_disks[i].capacity <<= 3;
X if(rscsi_disks[i].sector_size == 2048)
X rscsi_disks[i].capacity <<= 2; /* Change into 512 byte sectors */
X if(rscsi_disks[i].sector_size == 1024)
diff -u --recursive --new-file v2.2.7/linux/drivers/scsi/sg.c linux/drivers/scsi/sg.c
--- v2.2.7/linux/drivers/scsi/sg.c Fri Apr 16 14:47:31 1999
+++ linux/drivers/scsi/sg.c Fri May 7 11:05:30 1999
@@ -16,7 +16,7 @@
X *
X * Borrows code from st driver. Thanks to Alessandro Rubini's "dd" book.
X */
- static char * sg_version_str = "Version: 2.1.31 (990327)";
+ static char * sg_version_str = "Version: 2.1.32 (990501)";
X /*
X * D. P. Gilbert (dgil...@interlog.com, do...@triode.net.au)
X * - scatter list logic replaces previous large atomic SG_BIG_BUFF
@@ -69,8 +69,9 @@
X
X int sg_big_buff = SG_SCATTER_SZ; /* sg_big_buff is ro through sysctl */
X /* N.B. This global is here to keep existing software happy. It now holds
- the size of the "first buffer" of the most recent sucessful sg_open(). */
-/* Only available when 'sg' compiled into kernel (rather than a module). */
+ the size of the "first buffer" of the most recent sucessful sg_open().
+ Only available when 'sg' compiled into kernel (rather than a module).
+ This should probably be deprecated (use SG_GET_RESERVED_SIZE instead). */
X
X #define SG_SECTOR_SZ 512
X #define SG_SECTOR_MSK (SG_SECTOR_SZ - 1)
@@ -146,6 +147,7 @@
X char closed; /* 1 -> fd closed but request(s) outstanding */
X char my_mem_src; /* heap whereabouts of this sg_fb object */
X char cmd_q; /* 1 -> allow command queuing, 0 -> don't */
+ char underrun_flag; /* 1 -> flag underruns, 0 -> don't, 2 -> test */
X } Sg_fd; /* around 1192 bytes long on i386 */
X
X typedef struct sg_device /* holds the state of each scsi generic device */
@@ -173,7 +175,7 @@
X static char * sg_low_malloc(int rqSz, int lowDma, int mem_src,
X int * retSzp);
X static void sg_low_free(char * buff, int size, int mem_src);
-static Sg_fd * sg_add_sfp(Sg_device * sdp, int dev);
+static Sg_fd * sg_add_sfp(Sg_device * sdp, int dev, int get_reserved);
X static int sg_remove_sfp(Sg_device * sdp, Sg_fd * sfp);
X static Sg_request * sg_get_request(const Sg_fd * sfp, int pack_id);
X static Sg_request * sg_add_request(Sg_fd * sfp);
@@ -240,11 +242,14 @@
X if (! sdp->headfp) { /* no existing opens on this device */
X sdp->sgdebug = 0;
X sdp->sg_tablesize = sdp->device->host->sg_tablesize;
- sdp->merge_fd = SG_DEF_MERGE_FD;
+ sdp->merge_fd = 0; /* A little tricky if SG_DEF_MERGE_FD set */
X }
- if ((sfp = sg_add_sfp(sdp, dev))) {
+ if ((sfp = sg_add_sfp(sdp, dev, O_RDWR == (flags & O_ACCMODE)))) {
+ filp->private_data = sfp;
+#if SG_DEF_MERGE_FD
X if (0 == sdp->merge_fd)
- filp->private_data = sfp;
+ sdp->merge_fd = 1;
+#endif
X }
X else {
X if (flags & O_EXCL) sdp->exclude = 0; /* undo if error */
@@ -322,11 +327,12 @@
X return -ERESTARTSYS;
X srp = sg_get_request(sfp, req_pack_id);
X }
- srp->header.pack_len = srp->header.reply_len; /* Why ????? */
+ if (2 != sfp->underrun_flag)
+ srp->header.pack_len = srp->header.reply_len; /* Why ????? */
X
X /* Now copy the result back to the user buffer. */
X if (count >= size_sg_header) {
- copy_to_user(buf, &srp->header, size_sg_header);
+ __copy_to_user(buf, &srp->header, size_sg_header);
X buf += size_sg_header;
X if (count > srp->header.reply_len)
X count = srp->header.reply_len;
@@ -371,7 +377,7 @@
X ; /* FIXME: Hmm. Seek to the right place, or fail? */
X
X if ((k = verify_area(VERIFY_READ, buf, count)))
- return k;
+ return k; /* protects following copy_from_user()s + get_user()s */
X /* The minimum scsi command length is 6 bytes. If we get anything
X * less than this, it is clearly bogus. */
X if (count < (size_sg_header + 6))
@@ -382,10 +388,10 @@
X SCSI_LOG_TIMEOUT(1, printk("sg_write: queue full, domain error\n"));
X return -EDOM;
X }
- copy_from_user(&srp->header, buf, size_sg_header);
+ __copy_from_user(&srp->header, buf, size_sg_header);
X buf += size_sg_header;
X srp->header.pack_len = count;
- get_user(opcode, buf);
+ __get_user(opcode, buf);
X cmd_size = COMMAND_SIZE(opcode);
X if ((opcode >= 0xc0) && srp->header.twelve_byte)
X cmd_size = 12;
@@ -427,7 +433,7 @@
X SCpnt->sense_buffer[0] = 0;
X SCpnt->cmd_len = cmd_size;
X /* Now copy the SCSI command from the user's address space. */
- copy_from_user(cmnd, buf, cmd_size);
+ __copy_from_user(cmnd, buf, cmd_size);
X
X /* Set the LUN field in the command structure. */
X cmnd[1]= (cmnd[1] & 0x1f) | (sdp->device->lun << 5);
@@ -439,11 +445,10 @@
X SCpnt->use_sg = srp->data.use_sg;
X SCpnt->sglist_len = srp->data.sglist_len;
X SCpnt->bufflen = srp->data.bufflen;
- SCpnt->underflow = srp->data.bufflen;
-/* Not many drivers look at this:
- aic7xxx driver gives DID_RETRY_COMMAND on underrun
- seagate comments out its underrun checking code, and the rest ...
-*/
+ if (1 == sfp->underrun_flag)
+ SCpnt->underflow = srp->data.bufflen;
+ else
+ SCpnt->underflow = 0;
X SCpnt->buffer = srp->data.buffer;
X srp->data.use_sg = 0;
X srp->data.sglist_len = 0;
@@ -479,14 +484,10 @@
X switch(cmd_in)
X {
X case SG_SET_TIMEOUT:
- result = verify_area(VERIFY_READ, (const void *)arg, sizeof(int));
- if (result) return result;
X return get_user(sfp->timeout, (int *)arg);
X case SG_GET_TIMEOUT:
X return sfp->timeout; /* strange ..., for backward compatibility */
X case SG_SET_FORCE_LOW_DMA:
- result = verify_area(VERIFY_READ, (const void *)arg, sizeof(int));
- if (result) return result;
X result = get_user(val, (int *)arg);
X if (result) return result;
X if (val) {
@@ -503,28 +504,23 @@
X sfp->low_dma = sdp->device->host->unchecked_isa_dma;
X return 0;
X case SG_GET_LOW_DMA:
- result = verify_area(VERIFY_WRITE, (void *) arg, sizeof(int));
- if (result) return result;
- put_user((int)sfp->low_dma, (int *)arg);
- return 0;
+ return put_user((int)sfp->low_dma, (int *)arg);
X case SG_GET_SCSI_ID:
X result = verify_area(VERIFY_WRITE, (void *)arg, sizeof(Sg_scsi_id));
X if (result) return result;
X else {
X Sg_scsi_id * sg_idp = (Sg_scsi_id *)arg;
- put_user((int)sdp->device->host->host_no, &sg_idp->host_no);
- put_user((int)sdp->device->channel, &sg_idp->channel);
- put_user((int)sdp->device->id, &sg_idp->scsi_id);
- put_user((int)sdp->device->lun, &sg_idp->lun);
- put_user((int)sdp->device->type, &sg_idp->scsi_type);
- put_user(0, &sg_idp->unused1);
- put_user(0, &sg_idp->unused2);
- put_user(0, &sg_idp->unused3);
+ __put_user((int)sdp->device->host->host_no, &sg_idp->host_no);
+ __put_user((int)sdp->device->channel, &sg_idp->channel);
+ __put_user((int)sdp->device->id, &sg_idp->scsi_id);
+ __put_user((int)sdp->device->lun, &sg_idp->lun);
+ __put_user((int)sdp->device->type, &sg_idp->scsi_type);
+ __put_user(0, &sg_idp->unused1);
+ __put_user(0, &sg_idp->unused2);
+ __put_user(0, &sg_idp->unused3);
X return 0;
X }
X case SG_SET_FORCE_PACK_ID:
- result = verify_area(VERIFY_READ, (const void *)arg, sizeof(int));
- if (result) return result;
X result = get_user(val, (int *)arg);
X if (result) return result;
X sfp->force_packid = val ? 1 : 0;
@@ -535,16 +531,14 @@
X srp = sfp->headrp;
X while (srp) {
X if (! srp->my_cmdp) {
- put_user(srp->header.pack_id, (int *)arg);
+ __put_user(srp->header.pack_id, (int *)arg);
X return 0;
X }
X srp = srp->nextrp;
X }
- put_user(-1, (int *)arg);
+ __put_user(-1, (int *)arg);
X return 0;
X case SG_GET_NUM_WAITING:
- result = verify_area(VERIFY_WRITE, (void *) arg, sizeof(int));
- if (result) return result;
X srp = sfp->headrp;
X val = 0;
X while (srp) {
@@ -552,36 +546,25 @@
X ++val;
X srp = srp->nextrp;
X }
- put_user(val, (int *)arg);
- return 0;
+ return put_user(val, (int *)arg);
X case SG_GET_SG_TABLESIZE:
- result = verify_area(VERIFY_WRITE, (void *) arg, sizeof(int));
- if (result) return result;
- put_user(sdp->sg_tablesize, (int *)arg);
- return 0;
+ return put_user(sdp->sg_tablesize, (int *)arg);
X case SG_SET_RESERVED_SIZE:
X /* currently ignored, future extension */
X if (O_RDWR != (filp->f_flags & O_ACCMODE))
X return -EACCES;
- result = verify_area(VERIFY_READ, (const void *)arg, sizeof(int));
+ result = get_user(val, (int *)arg);
X if (result) return result;
+ /* logic should go here */
X return 0;
X case SG_GET_RESERVED_SIZE:
- result = verify_area(VERIFY_WRITE, (void *) arg, sizeof(int));
- if (result) return result;
- put_user(sfp->fb_size, (int *)arg);
- return 0;
+ return put_user(sfp->fb_size, (int *)arg);
X case SG_GET_MERGE_FD:
- result = verify_area(VERIFY_WRITE, (void *) arg, sizeof(int));
- if (result) return result;
- put_user((int)sdp->merge_fd, (int *)arg);
- return 0;
+ return put_user((int)sdp->merge_fd, (int *)arg);
X case SG_SET_MERGE_FD:
X if (O_RDWR != (filp->f_flags & O_ACCMODE))
X return -EACCES; /* require write access since effect wider
X then just this fd */
- result = verify_area(VERIFY_READ, (const void *)arg, sizeof(int));
- if (result) return result;
X result = get_user(val, (int *)arg);
X if (result) return result;
X val = val ? 1 : 0;
@@ -591,17 +574,19 @@
X sdp->merge_fd = val;
X return 0;
X case SG_SET_COMMAND_Q:
- result = verify_area(VERIFY_READ, (const void *)arg, sizeof(int));
- if (result) return result;
X result = get_user(val, (int *)arg);
X if (result) return result;
X sfp->cmd_q = val ? 1 : 0;
X return 0;
X case SG_GET_COMMAND_Q:
- result = verify_area(VERIFY_WRITE, (void *) arg, sizeof(int));
+ return put_user((int)sfp->cmd_q, (int *)arg);
+ case SG_SET_UNDERRUN_FLAG:
+ result = get_user(val, (int *)arg);
X if (result) return result;
- put_user((int)sfp->cmd_q, (int *)arg);
+ sfp->underrun_flag = val;
X return 0;
+ case SG_GET_UNDERRUN_FLAG:
+ return put_user((int)sfp->underrun_flag, (int *)arg);
X case SG_EMULATED_HOST:
X return put_user(sdp->device->host->hostt->emulated, (int *)arg);
X case SCSI_IOCTL_SEND_COMMAND:
@@ -613,8 +598,6 @@
X dangerous */
X return scsi_ioctl_send_command(sdp->device, (void *)arg);
X case SG_SET_DEBUG:
- result = verify_area(VERIFY_READ, (const void *)arg, sizeof(int));
- if (result) return result;
X result = get_user(val, (int *)arg);
X if (result) return result;
X sdp->sgdebug = (char)val;
@@ -625,6 +608,8 @@
X return 0;
X case SCSI_IOCTL_GET_IDLUN:
X case SCSI_IOCTL_GET_BUS_NUMBER:
+ case SCSI_IOCTL_PROBE_HOST:
+ case SG_GET_TRANSFORM:
X return scsi_ioctl(sdp->device, cmd_in, (void *)arg);
X default:
X if (O_RDWR != (filp->f_flags & O_ACCMODE))
@@ -698,6 +683,7 @@
X sdp = &sg_dev_arr[dev];
X if (NULL == sdp->device)
X return; /* Get out of here quick ... */
+
X sfp = sdp->headfp;
X while (sfp) {
X srp = sfp->headrp;
@@ -721,6 +707,8 @@
X srp->data.sglist_len = SCpnt->sglist_len;
X srp->data.bufflen = SCpnt->bufflen;
X srp->data.buffer = SCpnt->buffer;
+ if (2 == sfp->underrun_flag)
+ srp->header.pack_len = SCpnt->underflow;
X sg_clr_scpnt(SCpnt);
X srp->my_cmdp = NULL;
X
@@ -755,7 +743,7 @@
X * underrun or overrun should signal an error. Until that can be
X * implemented, this kludge allows for returning useful error values
X * except in cases that return DID_ERROR that might be due to an
- * underrun. [Underrun on advansys adapter yields DID_ABORT -dpg] */
+ * underrun. */
X if (SCpnt->sense_buffer[0] == 0 &&
X status_byte(SCpnt->result) == GOOD)
X srp->header.result = 0;
@@ -887,8 +875,9 @@
X printk(">> Following FD has NULL parent pointer ???\n");
X printk(" FD(%d): timeout=%d, fb_size=%d, cmd_q=%d\n",
X k, fp->timeout, fp->fb_size, (int)fp->cmd_q);
- printk(" low_dma=%d, force_packid=%d, closed=%d\n",
- (int)fp->low_dma, (int)fp->force_packid, (int)fp->closed);
+ printk(" low_dma=%d, force_packid=%d, urun_flag=%d, closed=%d\n",
+ (int)fp->low_dma, (int)fp->force_packid,
+ (int)fp->underrun_flag, (int)fp->closed);
X srp = fp->headrp;
X if (NULL == srp)
X printk(" No requests active\n");
@@ -1002,7 +991,7 @@
X sdp->generic_wait = NULL;
X sdp->headfp= NULL;
X sdp->exclude = 0;
- sdp->merge_fd = 0;
+ sdp->merge_fd = 0; /* Cope with SG_DEF_MERGE_FD on open */
X sdp->sgdebug = 0;
X sdp->sg_tablesize = scsidp->host ? scsidp->host->sg_tablesize : 0;
X sdp->i_rdev = MKDEV(SCSI_GENERIC_MAJOR, k);
@@ -1120,7 +1109,7 @@
X if ((blk_size < 0) || (! srp))
X return -EFAULT;
X
- SCSI_LOG_TIMEOUT(4, printk("sg build: m_b_s=%d, num_write_xfer=%d\n",
+ SCSI_LOG_TIMEOUT(4, printk("sg_sc_build: m_b_s=%d, num_write_xfer=%d\n",
X max_buff_size, num_write_xfer));
X if (0 == blk_size)
X ++blk_size; /* don't know why */
@@ -1139,7 +1128,7 @@
X srp->data.mem_src = mem_src;
X srp->data.b_malloc_len = blk_size;
X if (inp && (num_write_xfer > 0))
- copy_from_user(srp->data.buffer, inp, num_write_xfer);
+ __copy_from_user(srp->data.buffer, inp, num_write_xfer);


X return 0;
X }
X }

@@ -1185,17 +1174,17 @@
X }
X sclp->address = p;
X sclp->length = ret_sz;
- sclp->alt_address = (char *)mem_src;
+ sclp->alt_address = (char *)(long)mem_src;
X
X if(inp && (num_write_xfer > 0)) {
X num = (ret_sz > num_write_xfer) ? num_write_xfer : ret_sz;
- copy_from_user(sclp->address, inp, num);
+ __copy_from_user(sclp->address, inp, num);
X num_write_xfer -= num;
X inp += num;
X }
X SCSI_LOG_TIMEOUT(5,
- printk("sg_sc_build: k=%d, a=0x%x, len=%d, ms=%d\n",
- k, (int)sclp->address, ret_sz, (int)sclp->alt_address));
+ printk("sg_sc_build: k=%d, a=0x%p, len=%d, ms=%d\n",
+ k, sclp->address, ret_sz, mem_src));
X } /* end of for loop */
X srp->data.use_sg = k;
X SCSI_LOG_TIMEOUT(5,
@@ -1224,20 +1213,20 @@
X if (num_read_xfer > 0) {
X num = (int)sclp->length;
X if (num > num_read_xfer) {
- copy_to_user(outp, sclp->address, num_read_xfer);
+ __copy_to_user(outp, sclp->address, num_read_xfer);
X outp += num_read_xfer;
X num_read_xfer = 0;
X }
X else {
- copy_to_user(outp, sclp->address, num);
+ __copy_to_user(outp, sclp->address, num);
X outp += num;
X num_read_xfer -= num;
X }
X }
- mem_src = (int)sclp->alt_address;
+ mem_src = (int)(long)sclp->alt_address;
X SCSI_LOG_TIMEOUT(5,
- printk("sg_sc_undo_rem: k=%d, a=0x%x, len=%d, ms=%d\n",
- k, (int)sclp->address, sclp->length, mem_src));
+ printk("sg_sc_undo_rem: k=%d, a=0x%p, len=%d, ms=%d\n",
+ k, sclp->address, sclp->length, mem_src));
X sg_free(srp, sclp->address, sclp->length, mem_src);
X }
X sg_free(srp, srp->data.buffer, srp->data.sglist_len,
@@ -1245,13 +1234,13 @@
X }
X else {
X if (num_read_xfer > 0)
- copy_to_user(outp, srp->data.buffer, num_read_xfer);
+ __copy_to_user(outp, srp->data.buffer, num_read_xfer);
X sg_free(srp, srp->data.buffer, srp->data.b_malloc_len,
X srp->data.mem_src);
X }
X if (0 == sg_remove_request(srp->parentfp, srp)) {
- SCSI_LOG_TIMEOUT(1, printk("sg_sc_undo_rem: srp=%d not found\n",
- (int)srp));
+ SCSI_LOG_TIMEOUT(1, printk("sg_sc_undo_rem: srp=0x%p not found\n",
+ srp));
X }
X return 0;
X }
@@ -1336,7 +1325,7 @@


X return 0;
X }
X

-static Sg_fd * sg_add_sfp(Sg_device * sdp, int dev)
+static Sg_fd * sg_add_sfp(Sg_device * sdp, int dev, int get_reserved)
X {
X Sg_fd * sfp;
X
@@ -1357,8 +1346,12 @@
X sfp->low_dma = (SG_DEF_FORCE_LOW_DMA == 0) ?
X sdp->device->host->unchecked_isa_dma : 1;
X sfp->cmd_q = SG_DEF_COMMAND_Q;
- sfp->fst_buf = sg_low_malloc(SG_SCATTER_SZ, sfp->low_dma,
- SG_HEAP_PAGE, &sfp->fb_size);
+ sfp->underrun_flag = SG_DEF_UNDERRUN_FLAG;
+ if (get_reserved)
+ sfp->fst_buf = sg_low_malloc(SG_SCATTER_SZ, sfp->low_dma,
+ SG_HEAP_PAGE, &sfp->fb_size);
+ else
+ sfp->fst_buf = NULL;
X if (! sfp->fst_buf)
X sfp->fb_size = 0;
X sfp->parentdp = sdp;
@@ -1371,10 +1364,10 @@
X pfp->nextfp = sfp;
X }
X sg_big_buff = sfp->fb_size; /* show sysctl most recent "fb" size */
- SCSI_LOG_TIMEOUT(3, printk("sg_add_sfp: sfp=0x%x, m_s=%d\n",
- (int)sfp, (int)sfp->my_mem_src));
- SCSI_LOG_TIMEOUT(3, printk("sg_add_sfp: fb_sz=%d, fst_buf=0x%x\n",
- sfp->fb_size, (int)sfp->fst_buf));
+ SCSI_LOG_TIMEOUT(3, printk("sg_add_sfp: sfp=0x%p, m_s=%d\n",
+ sfp, (int)sfp->my_mem_src));
+ SCSI_LOG_TIMEOUT(3, printk("sg_add_sfp: fb_sz=%d, fst_buf=0x%p\n",
+ sfp->fb_size, sfp->fst_buf));
X return sfp;
X }
X
@@ -1416,13 +1409,13 @@
X prev_fp = fp;
X }
X }
-SCSI_LOG_TIMEOUT(6, printk("sg_remove_sfp: fb_sz=%d, fst_buf=0x%x\n",
- sfp->fb_size, (int)sfp->fst_buf));
+SCSI_LOG_TIMEOUT(6, printk("sg_remove_sfp: fb_sz=%d, fst_buf=0x%p\n",
+ sfp->fb_size, sfp->fst_buf));
X sg_low_free(sfp->fst_buf, sfp->fb_size, SG_HEAP_PAGE);
X sfp->parentdp = NULL;
X sfp->fst_buf = NULL;
X sfp->fb_size = 0;
- SCSI_LOG_TIMEOUT(6, printk("sg_remove_sfp: sfp=0x%x\n", (int)sfp));
+ SCSI_LOG_TIMEOUT(6, printk("sg_remove_sfp: sfp=0x%p\n", sfp));
X sg_low_free((char *)sfp, sizeof(Sg_fd), sfp->my_mem_src);
X res = 1;
X }
@@ -1573,8 +1566,8 @@
X }
X if (resp) *mem_srcp = l_ms;
X }
- SCSI_LOG_TIMEOUT(6, printk("sg_malloc: size=%d, ms=%d, ret=0x%x\n",
- size, *mem_srcp, (int)resp));
+ SCSI_LOG_TIMEOUT(6, printk("sg_malloc: size=%d, ms=%d, ret=0x%p\n",
+ size, *mem_srcp, resp));
X return resp;
X }
X
@@ -1598,8 +1591,8 @@
X free_pages((unsigned long)buff, order);


SHAR_EOF
true || echo 'restore of patch-2.2.8 failed'
fi

echo 'End of part 21'
echo 'File patch-2.2.8 is continued in part 22'
echo 22 > _shar_seq_.tmp

Thomas...@ciw.uni-karlsruhe.de

unread,
May 12, 1999, 3:00:00 AM5/12/99
to
Archive-name: v2.2/patch-2.2.8/part22

#!/bin/sh
# this is part 22 of a 33 - part archive


# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.8 continued
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 22; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.8'
else
echo 'x - continuing with patch-2.2.8'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.8' &&
X }

X else
- printk("sg_low_free: bad mem_src=%d, buff=0x%x, rqSz=%df\n",
- mem_src, (int)buff, size);
+ printk("sg_low_free: bad mem_src=%d, buff=0x%p, rqSz=%df\n",
+ mem_src, buff, size);
X }
X
X static void sg_free(Sg_request * srp, char * buff, int size, int mem_src)
@@ -1607,7 +1600,7 @@
X Sg_fd * sfp = srp->parentfp;
X
X SCSI_LOG_TIMEOUT(6,
- printk("sg_free: buff=0x%x, size=%d\n", (int)buff, size));
+ printk("sg_free: buff=0x%p, size=%d\n", buff, size));
X if ((! sfp) || (! buff) || (size <= 0))
X ;
X else if (sfp->fst_buf == buff) {
@@ -1624,5 +1617,7 @@
X SCpnt->sglist_len = 0;
X SCpnt->bufflen = 0;
X SCpnt->buffer = NULL;


+ SCpnt->underflow = 0;

+ SCpnt->request.rq_dev = MKDEV(0, 0); /* "sg" _disowns_ command blk */
X }
X
diff -u --recursive --new-file v2.2.7/linux/drivers/scsi/sr_ioctl.c linux/drivers/scsi/sr_ioctl.c
--- v2.2.7/linux/drivers/scsi/sr_ioctl.c Wed Mar 10 15:29:47 1999
+++ linux/drivers/scsi/sr_ioctl.c Mon May 10 13:01:21 1999
@@ -82,7 +82,8 @@
X switch(SCpnt->sense_buffer[2] & 0xf) {
X case UNIT_ATTENTION:
X scsi_CDs[target].device->changed = 1;
- printk(KERN_INFO "sr%d: disc change detected.\n", target);
+ if (!quiet)
+ printk(KERN_INFO "sr%d: disc change detected.\n", target);
X if (retries++ < 10)
X goto retry;
X err = -ENOMEDIUM;
@@ -105,12 +106,13 @@
X spin_unlock_irqrestore(&io_request_lock, flags);
X goto retry;
X } else {
- /* 20 secs are enouth? */
+ /* 20 secs are enough? */
X err = -ENOMEDIUM;
X break;
X }
X }
- printk(KERN_INFO "sr%d: CDROM not ready. Make sure there is a disc in the drive.\n",target);
+ if (!quiet)
+ printk(KERN_INFO "sr%d: CDROM not ready. Make sure there is a disc in the drive.\n",target);
X #ifdef DEBUG
X print_sense("sr", SCpnt);
X #endif
@@ -120,9 +122,11 @@
X if (!quiet)
X printk(KERN_ERR "sr%d: CDROM (ioctl) reports ILLEGAL "
X "REQUEST.\n", target);
- if (SCpnt->sense_buffer[12] == 0x20 &&
+ if ((SCpnt->sense_buffer[12] == 0x20 ||
+ SCpnt->sense_buffer[12] == 0x24) &&
X SCpnt->sense_buffer[13] == 0x00) {
X /* sense: Invalid command operation code */
+ /* or Invalid field in cdb */
X err = -EDRIVE_CANT_DO_THIS;
X } else {
X err = -EINVAL;
@@ -408,7 +412,7 @@
X spin_unlock_irqrestore(&io_request_lock, flags);
X if(!buffer) return -ENOMEM;
X
- result = sr_do_ioctl(target, sr_cmd, buffer, 12, 0);
+ result = sr_do_ioctl(target, sr_cmd, buffer, 12, 1);
X
X tochdr->cdth_trk0 = buffer[2];
X tochdr->cdth_trk1 = buffer[3];
diff -u --recursive --new-file v2.2.7/linux/drivers/scsi/sr_vendor.c linux/drivers/scsi/sr_vendor.c
--- v2.2.7/linux/drivers/scsi/sr_vendor.c Wed May 20 19:10:40 1998
+++ linux/drivers/scsi/sr_vendor.c Mon May 10 13:01:21 1999
@@ -175,7 +175,7 @@
X cmd[1] = (scsi_CDs[minor].device->lun << 5);
X cmd[8] = 12;
X cmd[9] = 0x40;
- rc = sr_do_ioctl(minor, cmd, buffer, 12, 0);
+ rc = sr_do_ioctl(minor, cmd, buffer, 12, 1);
X if (rc != 0)
X break;
X if ((buffer[0] << 8) + buffer[1] < 0x0a) {
@@ -199,7 +199,7 @@
X cmd[0] = 0xde;
X cmd[1] = (scsi_CDs[minor].device->lun << 5) | 0x03;
X cmd[2] = 0xb0;
- rc = sr_do_ioctl(minor, cmd, buffer, 0x16, 0);
+ rc = sr_do_ioctl(minor, cmd, buffer, 0x16, 1);
X if (rc != 0)
X break;
X if (buffer[14] != 0 && buffer[14] != 0xb0) {
@@ -223,7 +223,7 @@
X memset(cmd,0,12);
X cmd[0] = 0xc7;
X cmd[1] = (scsi_CDs[minor].device->lun << 5) | 3;
- rc = sr_do_ioctl(minor, cmd, buffer, 4, 0);
+ rc = sr_do_ioctl(minor, cmd, buffer, 4, 1);
X if (rc == -EINVAL) {
X printk(KERN_INFO "sr%d: Hmm, seems the drive "
X "doesn't support multisession CD's\n",minor);
@@ -248,7 +248,7 @@
X cmd[1] = (scsi_CDs[minor].device->lun << 5);
X cmd[8] = 0x04;
X cmd[9] = 0x40;
- rc = sr_do_ioctl(minor, cmd, buffer, 0x04, 0);
+ rc = sr_do_ioctl(minor, cmd, buffer, 0x04, 1);
X if (rc != 0) {
X break;
X }
@@ -263,7 +263,7 @@
X cmd[6] = rc & 0x7f; /* number of last session */
X cmd[8] = 0x0c;
X cmd[9] = 0x40;
- rc = sr_do_ioctl(minor, cmd, buffer, 12, 0);
+ rc = sr_do_ioctl(minor, cmd, buffer, 12, 1);
X if (rc != 0) {
X break;
X }
diff -u --recursive --new-file v2.2.7/linux/drivers/sound/ad1816.c linux/drivers/sound/ad1816.c
--- v2.2.7/linux/drivers/sound/ad1816.c Mon Jan 25 17:44:34 1999
+++ linux/drivers/sound/ad1816.c Mon May 10 13:01:21 1999
@@ -32,10 +32,10 @@
X
X -------------------------------------------------------------------------------
X
-version: 1.2
-cvs: $Header: /home/tek/tmp/CVSROOT/sound21/ad1816.c,v 1.28 1999/01/16 19:01:36 tek Exp $
+version: 1.3
+cvs: $Header: /home/tek/CVSROOT/sound22/ad1816.c,v 1.3 1999/04/18 16:41:41 tek Exp $
X status: experimental
-date: 1999/01/16
+date: 1999/4/18
X
X Changes:
X Oleg Drokin: Some cleanup of load/unload functions. 1998/11/24
@@ -44,6 +44,13 @@
X some argument checks added 1998/11/30
X
X Thorsten Knabe: Buggy isa bridge workaround added 1999/01/16
+
+ David Moews/Thorsten Knabe: Introduced options
+ parameter. Added slightly modified patch from
+ David Moews to disable dsp audio sources by setting
+ bit 0 of options parameter. This seems to be
+ required by some Aztech/Newcom SC-16 cards. 1999/04/18
+
X */
X
X #include <linux/config.h>
@@ -100,6 +107,8 @@
X
X static int ad1816_clockfreq=33000;
X
+static int options=0;
+
X /* for backward mapping of irq to sound device */
X
X static volatile char irq2dev[17] = {-1, -1, -1, -1, -1, -1, -1, -1,
@@ -1091,12 +1100,14 @@
X int tmp;
X
X printk("ad1816: AD1816 sounddriver Copyright (C) 1998 by Thorsten Knabe\n");
- printk("ad1816: $Header: /home/tek/tmp/CVSROOT/sound21/ad1816.c,v 1.28 1999/01/16 19:01:36 tek Exp $\n");
- printk("ad1816: io=0x%x, irq=%d, dma=%d, dma2=%d, isadmabug=%d\n",
+ printk("ad1816: $Header: /home/tek/CVSROOT/sound22/ad1816.c,v 1.3 1999/04/18 16:41:41 tek Exp $\n");
+ printk("ad1816: io=0x%x, irq=%d, dma=%d, dma2=%d, clockfreq=%d, options=%d isadmabug=%d\n",
X hw_config->io_base,
X hw_config->irq,
X hw_config->dma,
X hw_config->dma2,
+ ad1816_clockfreq,
+ options,
X isa_dma_bridge_buggy);
X
X if (check_region (io_base, 16)) {
@@ -1264,7 +1275,11 @@
X nr_ad1816_devs++;
X
X ad_write(devc,32,0x80f0); /* sound system mode */
- ad_write(devc,33,0x03f8); /* enable all audiosources for dsp */
+ if (options&1) {
+ ad_write(devc,33,0); /* disable all audiosources for dsp */
+ } else {
+ ad_write(devc,33,0x03f8); /* enable all audiosources for dsp */
+ }
X ad_write(devc,4,0x8080); /* default values for volumes (muted)*/
X ad_write(devc,5,0x8080);
X ad_write(devc,6,0x8080);
@@ -1274,7 +1289,7 @@
X ad_write(devc,17,0x8888);
X ad_write(devc,18,0x8888);
X ad_write(devc,19,0xc888); /* +20db mic active */
- ad_write(devc,14,0x0000); /* Master volume unmuted full power */
+ ad_write(devc,14,0x0000); /* Master volume unmuted */
X ad_write(devc,39,0x009f); /* 3D effect on 0% phone out muted */
X ad_write(devc,44,0x0080); /* everything on power, 3d enabled for d/a */
X outb(0x10,devc->base+8); /* set dma mode */
@@ -1382,6 +1397,7 @@
X MODULE_PARM(dma,"i");
X MODULE_PARM(dma2,"i");
X MODULE_PARM(ad1816_clockfreq,"i");
+MODULE_PARM(options,"i");
X
X struct address_info cfg;
X
diff -u --recursive --new-file v2.2.7/linux/drivers/sound/sb_ess.c linux/drivers/sound/sb_ess.c
--- v2.2.7/linux/drivers/sound/sb_ess.c Tue Feb 23 15:21:34 1999
+++ linux/drivers/sound/sb_ess.c Mon May 10 13:01:21 1999
@@ -11,7 +11,7 @@
X * History:
X *
X * Rolf Fokkens (Dec 20 1998): ES188x recording level support on a per
- * input basis.
+ * fokk...@vertis.nl input basis.
X * (Dec 24 1998): Recognition of ES1788, ES1887, ES1888,
X * ES1868, ES1869 and ES1878. Could be used for
X * specific handling in the future. All except
@@ -32,6 +32,14 @@
X * any applications to test it though. So why did
X * I bother to create it anyway?? :) Just for
X * fun.
+ * (May 2 1999): I tried to be too smart by "introducing"
+ * ess_calc_best_speed (). The idea was that two
+ * dividers could be used to setup a samplerate,
+ * ess_calc_best_speed () would choose the best.
+ * This works for playback, but results in
+ * recording problems for high samplerates. I
+ * fixed this by removing ess_calc_best_speed ()
+ * and just doing what the documentation says.
X *
X * This files contains ESS chip specifics. It's based on the existing ESS
X * handling as it resided in sb_common.c, sb_mixer.c and sb_audio.c. This
@@ -315,6 +323,7 @@


X return retval;
X }
X

+#ifdef OBSOLETE
X static int ess_calc_best_speed
X (int clock1, int rev1, int clock2, int rev2, int *divp, int *speedp)
X {
@@ -338,6 +347,7 @@
X
X return retval;


X }
+#endif
X
X /*

X * Depending on the audiochannel ESS devices can
@@ -349,7 +359,7 @@
X */
X static void ess_common_speed (sb_devc *devc, int *speedp, int *divp)
X {
- int diff = 0, div, choice;
+ int diff = 0, div;
X
X if (devc->duplex) {
X /*
@@ -357,8 +367,11 @@
X */
X div = 0x80 | ess_calc_div (795500, 128, speedp, &diff);
X } else {
- choice = ess_calc_best_speed (397700, 128, 795500, 256, &div, speedp);
- if (choice == 2) div |= 0x80;
+ if (*speedp > 22000) {
+ div = 0x80 | ess_calc_div (795500, 256, speedp, &diff);
+ } else {
+ div = 0x00 | ess_calc_div (397700, 128, speedp, &diff);
+ }
X }
X *divp = div;
X }
@@ -1144,6 +1157,18 @@
X if (chip == NULL) {
X chip = "ES1688";
X };
+
+ printk ( KERN_INFO "ESS chip %s %s%s\n"
+ , chip
+ , ( esstype == ESSTYPE_DETECT || esstype == ESSTYPE_LIKE20
+ ? "detected"
+ : "specified"
+ )
+ , ( esstype == ESSTYPE_LIKE20
+ ? " (kernel 2.0 compatible)"
+ : ""
+ )
+ );
X
X sprintf(name,"ESS %s AudioDrive (rev %d)", chip, ess_minor & 0x0f);
X } else {
diff -u --recursive --new-file v2.2.7/linux/drivers/usb/CREDITS linux/drivers/usb/CREDITS
--- v2.2.7/linux/drivers/usb/CREDITS Wed Apr 28 11:37:30 1999
+++ linux/drivers/usb/CREDITS Tue May 11 10:04:03 1999
@@ -2,14 +2,16 @@
X
X The following people have contributed to this code (in alphabetical
X order by last name). I'm sure this list should be longer, its
-difficult to maintain.
+difficult to maintain, add yourself with a patch if desired.
X
+ Alan Cox <al...@lxorguk.ukuu.org.uk>
X Johannes Erdfelt <jerd...@sventech.com>
X ham <h...@unsuave.com>
X Bradley M Keryan <ker...@andrew.cmu.edu>
X Vojtech Pavlik <voj...@twilight.ucw.cz>
X Gregory P. Smith <gr...@electricrain.com>
X Linus Torvalds <torv...@transmeta.com>
+ Roman Weissgaerber <wei...@vienna.at>
X <Kazuki.Y...@fujixerox.co.jp>
X
X Special thanks to:
@@ -20,4 +22,133 @@
X
X The NetBSD & FreeBSD USB developers. For being on the Linux USB list
X and offering suggestions and sharing implementation experiences.
+
+Additional thanks to the following companies and people for donations
+of hardware, support, time and development (this is from the original
+THANKS file in Inaky's driver):
+
+ The following corporations have helped us in the development
+of Linux USB / UUSBD:
+
+ - USAR Systems provided us with one of their excellent USB
+ Evaluation Kits. It allows us to test the Linux-USB driver
+ for compilance with the latest USB specification. USAR
+ Systems recognized the importance of an up-to-date open
+ Operating System and supports this project with
+ Hardware. Thanks!.
+
+ - Thanks to Intel Corporation for their precious help.
+
+ - We teamed up with Cherry to make Linux the first OS with
+ built-in USB support. Cherry is one of the biggest keyboard
+ makers in the world.
+
+ - CMD Technology, Inc. sponsored us kindly donating a CSA-6700
+ PCI-to-USB Controller Board to test the OHCI implementation.
+
+ - Due to their support to us, Keytronic can be sure that they
+ will sell keyboards to some of the 3 million (at least)
+ Linux users.
+
+ - Many thanks to ing büro h doran [http://www.ibhdoran.com]!
+ It was almost imposible to get a PC backplate USB connector
+ for the motherboard here at Europe (mine, home-made, was
+ quite lowsy :). Now I know where to adquire nice USB stuff!
+
+ - Genius Germany donated a USB mouse to test the mouse boot
+ protocol. They've also donated a F-23 digital joystick and a
+ NetMouse Pro. Thanks!
+
+ - AVM GmbH Berlin is supporting the development of the Linux
+ USB driver for the AVM ISDN Controller B1 USB. AVM is a
+ leading manufacturer for active and passive ISDN Controllers
+ and CAPI 2.0-based software. The active design of the AVM B1
+ is open for all OS platforms, including Linux.
+
+ - Thanks to Y-E Data, Inc. for donating their FlashBuster-U
+ USB Floppy Disk Drive, so we could test the bulk transfer
+ code.
+
+ - Many thanks to Logitech for contributing a three axis USB
+ mouse.
+
+ Logitech designs, manufactures and markets
+ Human Interface Devices, having a long history and
+ experience in making devices such as keyboards, mice,
+ trackballs, cameras, loudspeakers and control devices for
+ gaming and professional use.
+
+ Being a recognized vendor and seller for all these devices,
+ they have donated USB mice, a joystick and a scanner, as a
+ way to acknowledge the importance of Linux and to allow
+ Logitech customers to enjoy support in their favorite
+ operating systems and all Linux users to use Logitech and
+ other USB hardware.
+
+ Logitech is official sponsor of the Linux Conference on
+ Feb. 11th 1999 in Vienna, where we'll will present the
+ current state of the Linux USB effort.
+
+ - CATC has provided means to uncover dark corners of the UHCI
+ inner workings with a USB Inspector.
+
+ - Thanks to Entrega for providing PCI to USB cards, hubs and
+ converter products for development.
+
+
+ And thanks go to (hey! in no particular order :)
+
+ - Oren Tirosh <ore...@hishome.net>, for standing so patiently
+ all my doubts'bout USB and giving lots of cool ideas.
+
+ - Jochen Karrer <kar...@wpfd25.physik.uni-wuerzburg.de>, for
+ pointing out mortal bugs and giving advice.
+
+ - Edmund Humemberger <e...@atnet.at>, for it's great work on
+ public relationships and general management stuff for the
+ Linux-USB effort.
+
+ - Alberto Menegazzi <fl...@flash.iol.it> is starting the
+ documentation for the UUSBD. Go for it!
+
+ - Ric Klaren <ia_...@cs.utwente.nl> for doing nice
+ introductory documents (compiting with Alberto's :).
+
+ - Christian Groessler <c...@aladdin.de>, for it's help on those
+ itchy bits ... :)
+
+ - Paul MacKerras for polishing OHCI and pushing me harder for
+ the iMac support, giving improvements and enhancements.
+
+ - Fernando Herrera <fher...@eurielec.etsit.upm.es> has taken
+ charge of composing, maintaining and feeding the
+ long-awaited, unique and marvelous UUSBD FAQ! Tadaaaa!!!
+
+ - Rasca Gmelch <th...@gmx.de> has revived the raw driver and
+ pointed bugs, as well as started the uusbd-utils package.
+
+ - Peter Dettori <det...@ozy.dec.com> is unconvering bugs like
+ crazy, as well as making cool suggestions, great :)
+
+ - All the Free Software and Linux community, the FSF & the GNU
+ project, the MIT X consortium, the TeX people ... everyone!
+ You know who you are!
+
+ - Big thanks to Richard Stallman for creating Emacs!
+
+ - The people at the linux-usb mailing list, for reading so
+ many messages :) Ok, no more kidding; for all your advices!
+
+ - All the people at the USB Implementors Forum for their
+ help and assistance.
+
+ - Nathan Myers <n...@cantrip.org>, for his advice! (hope you
+ liked Cibeles' party).
+
+ - Linus Torvalds, for starting, developing and managing Linux.
+
+ - Mike Smith, Craig Keithley, Thierry Giron and Janet Schank
+ for convincing me USB Standard hubs are not that standard
+ and that's good to allow for vendor specific quirks on the
+ standard hub driver.
X
diff -u --recursive --new-file v2.2.7/linux/drivers/usb/Config.in linux/drivers/usb/Config.in
--- v2.2.7/linux/drivers/usb/Config.in Wed Apr 28 11:37:30 1999
+++ linux/drivers/usb/Config.in Mon May 10 10:18:34 1999
@@ -16,6 +16,10 @@
X if [ ! "$CONFIG_USB" = "n" ]; then
X bool 'UHCI (intel PIIX4 and others) support?' CONFIG_USB_UHCI
X bool 'OHCI (compaq and some others) support?' CONFIG_USB_OHCI
+ bool 'OHCI-HCD (other OHCI opt. Virt. Root Hub) support?' CONFIG_USB_OHCI_HCD
+ if [ "$CONFIG_USB_OHCI_HCD" = "y" ]; then
+ bool 'OHCI-HCD Virtual Root Hub' CONFIG_USB_OHCI_VROOTHUB
+ fi
X
X bool 'USB mouse support' CONFIG_USB_MOUSE
X bool 'USB keyboard support' CONFIG_USB_KBD
diff -u --recursive --new-file v2.2.7/linux/drivers/usb/Makefile linux/drivers/usb/Makefile
--- v2.2.7/linux/drivers/usb/Makefile Wed Apr 28 11:37:30 1999
+++ linux/drivers/usb/Makefile Mon May 10 10:18:34 1999
@@ -59,7 +59,17 @@


X endif
X endif
X

-
+ifeq ($(CONFIG_USB_OHCI_HCD),y)
+ ifeq ($(CONFIG_USB), y)
+ L_OBJS += ohci-hcd.o ohci-root-hub.o
+ else
+ ifeq ($(CONFIG_USB),m)
+ USBO_OBJS += ohci-hcd.o ohci-root-hub.o
+ M_OBJS += usb-ohci-hcd.o
+ MIX_OBJS += $(USBX_OBJS)
+ endif
+ endif
+endif
X include $(TOPDIR)/Rules.make
X
X keymap.o: keymap.c
@@ -73,3 +83,6 @@
X usb-ohci.o: ohci.o ohci-debug.o $(USBX_OBJS)
X $(LD) $(LD_RFLAG) -r -o $@ ohci.o ohci-debug.o $(USBX_OBJS)
X
+usb-ohci-hcd.o: ohci-hcd.o ohci-root-hub.o $(USBX_OBJS)
+ $(LD) $(LD_RFLAG) -r -o $@ ohci-hcd.o ohci-root-hub.o $(USBX_OBJS)
+
diff -u --recursive --new-file v2.2.7/linux/drivers/usb/README.ohci linux/drivers/usb/README.ohci
--- v2.2.7/linux/drivers/usb/README.ohci Wed Apr 28 11:37:30 1999
+++ linux/drivers/usb/README.ohci Tue May 11 10:04:03 1999
@@ -1,8 +1,26 @@
-April 24, 1999 04:37:42 PST
+May 09, 1999 16:25:58
X
-Okay, I've written a lot more of the OHCI code and actually got it back to
-a compiling state now with all of the recent improvements to the way stuff
-is structured. It is completely untested.
+Cool, things are working "well" now. (I'm not getting oops's from the
+OHCI code anyways.. ;). I can attach a usb hub and mouse in any
+possible arrangement of the two and they get configured properly.
+
+You can see that the mouse Interrupt transfers are occuring and being
+acknowledged because /proc/interrupts usb-ohci goes up accordingly with
+mouse movements/events. That means the TD at least returns some data
+and requeues itself.
+
+Device attach/detach from the root hub is not working well. Currently
+every interrupt checks for root hub status changes and frame number
+overflow interrupts are enabled. This means you shouldn't have to
+wait more than 32-33 seconds for the change to occur, less if there is
+other activity. (due to checking in the WDH caused interrupts)
+My OHCI controller [SiS 5598 motherboard] doesn't seem to play well
+with the RHSC interrupt so it has been disabled. The ohci_timer
+should be polling but it not currently working, I haven't had time to
+look into that problem.
+
+However, when I tried telling X to use /dev/psaux for the mouse my
+machine locked up...
X
X - gr...@electricrain.com
X
diff -u --recursive --new-file v2.2.7/linux/drivers/usb/README.ohci_hcd linux/drivers/usb/README.ohci_hcd
--- v2.2.7/linux/drivers/usb/README.ohci_hcd Wed Dec 31 16:00:00 1969
+++ linux/drivers/usb/README.ohci_hcd Mon May 10 10:18:34 1999
@@ -0,0 +1,112 @@
+
+The OHCI HCD layer is a simple but nearly complete implementation of what the
+USB people would call a HCD for the OHCI.
+ (ISO comming soon, Bulk disabled, INT u. CTRL transfers enabled)
+It is based on Linus Torvalds UHCI code and Gregory Smith OHCI fragments (0.03 source tree).
+The layer (functions) on top of it, is for interfacing to the alternate-usb device-drivers.
+
+- Roman Weissgaerber <wei...@vienna.at>
+
+
+ * v2.1 1999/05/09 ep_addr correction, code cleanup
+ * v0.2.0 1999/05/04
+ * everything has been moved into 2 files (ohci-hcd.c, ohci-hub-root.c and headers)
+ * virtual root hub is now an option,
+ * memory allocation based on kmalloc and kfree now, simple Bus error handling,
+ * INT and CTRL transfers enabled, Bulk included but disabled, ISO needs completion
+ *
+ * from Linus Torvalds (uhci.c): APM (not tested); hub, usb_device, bus and related stuff
+ * from Greg Smith (ohci.c): better reset ohci-controller handling, hub
+ *
+ * v0.1.0 1999/04/27 initial release
+
+to remove the module try:
+killall root-hub
+:
+rmmod usb-ohci-hcd
+
+Features:
+- virtual root hub, all basic hub descriptors and commands (state: complete)
+ this is an option now (v0.2.0)
+ #define CONFIG_USB_OHCI_VROOTHUB includes the virtual hub code, (VROOTHUB)
+ default is without.
+ (at the moment: the Virtual Root Hub option is not recommended)
+
+ files: ohci-root-hub.c, ohci-root-hub.h
+
+
+- Endpoint Descriptor (ED) handling more static approach
+ (EDs should be allocated in parallel to the SET CONFIGURATION command and they live
+ as long as the function (device) is alive or another configuration is choosen.
+ In the HCD layer the EDs has to be allocated manually either by calling a subroutine
+ or by sending a USB root hub vendor specific command to the virtual root hub.
+ At the alternate linux usb stack EDs will be added (allocated) at their first use.
+
+ files: ohci-hcd.c ohci-hcd.h
+ routines: (do not use for drivers, use the top layer alternate usb commands instead)
+
+ int usb_ohci_add_ep(struct ohci * ohci, unsigned int ep_addr1,
+ int interval, int load, f_handler handler, int ep_size, int speed)
+ adds an endpoint, (if the endpoint already exists some parameters will be updated)
+
+ int usb_ohci_rm_ep(struct usb_ohci_ed *ed, struct ohci * ohci)
+ removes an endpoint and all pending TDs of that EP
+
+ usb_ohci_rm_function( struct ohci * ohci, union ep_addr_ ep_addr)
+ removes all Endpoints of a function (device)
+
+- Transfer Descriptors (TD): handling and allocation of TDs is transparent to the upper layers
+ The HCD takes care of TDs and EDs memory allocation whereas the upper layers (UBSD ...) has
+ to take care of buffer allocation.
+ files: ohci-hcd.c ohci-hcd.h
+
+ There is one basic command for all types of bus transfers (INT, BULK, ISO, CTRL):
+
+ int ohci_trans_req(struct ohci * ohci, int ep_addr, int ctrl_len, void *ctrl, void * data, int data_len, __OHCI_BAG lw0, __OHCI_BAG lw1)
+
+ CTRL: ctrl, ctrl_len ... cmd buffer
+ data, data_len ... data buffer (in or out)
+ INT, BULK: ctrl = NULL, ctrl_len=0,
+ data, data_len ... data buffer (in or out)
+ ISO: tbd
+
+ There is no buffer reinsertion done by the internal HCD function.
+ (The interface layer does this for a INT-pipe on request.)
+ If you want a transfer then you have to
+ provide buffers by sending ohci_trans_req requests. As they are queued as TDs on an ED
+ you can send as many as you like. They should come back by the callback f_handler in
+ the same order (for each endpoint, not globally) If an error occurs all
+ queued transfers of an endpoint will return unsent. They will be marked with an error status.
+
+ e.g double-buffering for int transfers:
+
+ ohci_trans_req(ohci, ep_addr, 0, NULL, data0, data0_len, 0,0)
+ ohci_trans_req(ohci, ep_addr, 0, NULL, data1, data1_len, 0,0)
+
+ and when a data0 packet returns by the callback f_handler requeue it:
+ ohci_trans_req(ohci, ep_addr, 0, NULL, data0, data0_len, 0,0)
+ and when a data1 packet returns by the callback f_handler requeue it:
+ ohci_trans_req(ohci, ep_addr, 0, NULL, data1, data1_len, 0,0)
+
+ lw0, lw1 are private fields for upper layers for ids or fine grained handlers.
+ The alternate usb uses them for dev_id and usb_device_irq handler.
+
+
+- Done list handling: returns the requests (callback f_handler in ED) and does
+ some error handling, root-hub request dequeuing
+ (files: ohci-done-list.c in ohci-hcd.c now(v0.2.0))
+
+ep_addr union or int is for addressing devices&endpoints:
+__u8 ep_addr.bep.ep ... bit 3..0 endpoint address
+ bit 4 0
+ bit 6,5 type: eg. 10 CTRL, 11 BULK, 01 INT, 00 ISO
+ bit 7 direction 1 IN, 0 OUT
+
+__u8 ep_addr.bep.fa ... bit 6..0 function address
+ bit 7 0
+
+(__u8 ep_addr.bep.hc ... host controller nr) not used
+(__u8 ep_addr.bep.host ... host nr) not used
+
+
+
diff -u --recursive --new-file v2.2.7/linux/drivers/usb/hub.c linux/drivers/usb/hub.c
--- v2.2.7/linux/drivers/usb/hub.c Wed Apr 28 11:37:30 1999
+++ linux/drivers/usb/hub.c Fri Apr 30 08:20:01 1999
@@ -30,6 +30,9 @@
X /* List of hubs needing servicing */
X static struct list_head hub_event_list;
X
+/* PID of khubd */
+static int khubd_pid = 0;
+
X /*
X * A irq handler returns non-zero to indicate to
X * the low-level driver that it wants to be re-activated,
@@ -166,7 +169,8 @@
X /* Is it a hub? */
X if (interface->bInterfaceClass != 9)
X return -1;
- if (interface->bInterfaceSubClass != 0)
+ if ((interface->bInterfaceSubClass != 0) &&
+ (interface->bInterfaceSubClass != 1))
X return -1;
X
X /* Multiple endpoints? What kind of mutant ninja-hub is this? */
@@ -398,8 +402,10 @@
X
X usb_register(&hub_driver);
X pid = kernel_thread(usb_hub_thread, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
- if (pid >= 0)
+ if (pid >= 0) {
+ khubd_pid = pid;
X return 0;
+ }
X
X /* Fall through if kernel_thread failed */
X usb_deregister(&hub_driver);
@@ -407,3 +413,10 @@


X return 0;
X }
X

+void hub_cleanup(void)
+{
+ if (khubd_pid >= 0)
+ kill_proc(khubd_pid, SIGINT, 1);
+
+ usb_deregister(&hub_driver);
+}
diff -u --recursive --new-file v2.2.7/linux/drivers/usb/inits.h linux/drivers/usb/inits.h
--- v2.2.7/linux/drivers/usb/inits.h Wed Apr 28 11:37:30 1999
+++ linux/drivers/usb/inits.h Fri Apr 30 08:20:30 1999
@@ -2,3 +2,5 @@
X int usb_kbd_init(void);
X int usb_audio_init(void);
X int hub_init(void);
+void hub_cleanup(void);
+void usb_mouse_cleanup(void);
diff -u --recursive --new-file v2.2.7/linux/drivers/usb/mouse.c linux/drivers/usb/mouse.c
--- v2.2.7/linux/drivers/usb/mouse.c Wed Apr 28 11:37:30 1999
+++ linux/drivers/usb/mouse.c Fri Apr 30 08:20:49 1999
@@ -1,9 +1,12 @@
X /*
X * USB HID boot protocol mouse support based on MS BusMouse driver, psaux
- * driver, and Linus's skeleton USB mouse driver
+ * driver, and Linus's skeleton USB mouse driver. Fixed up a lot by Linus.
X *
X * Brad Keryan 4/3/1999
X *
+ * version 0.20: Linus rewrote read_mouse() to do PS/2 and do it
+ * correctly. Events are added together, not queued, to keep the rodent sober.
+ *
X * version 0.02: Hmm, the mouse seems drunk because I'm queueing the events.
X * This is wrong: when an application (like X or gpm) reads the mouse device,
X * it wants to find out the mouse's current position, not its recent history.
@@ -282,18 +285,9 @@


X return 0;
X }
X

-#if 0
-
-int init_module(void)
-{
- return usb_mouse_init();
-}
-
-void cleanup_module(void)
+void usb_mouse_cleanup(void)
X {
X /* this, too, probably needs work */
X usb_deregister(&mouse_driver);
X misc_deregister(&usb_mouse);
X }
-
-#endif
diff -u --recursive --new-file v2.2.7/linux/drivers/usb/ohci-debug.c linux/drivers/usb/ohci-debug.c
--- v2.2.7/linux/drivers/usb/ohci-debug.c Wed Apr 28 11:37:30 1999
+++ linux/drivers/usb/ohci-debug.c Tue May 11 10:04:03 1999
@@ -14,40 +14,58 @@
X struct ohci_regs regs;
X int i;
X
- regs.revision = readl(ohci->regs->revision);
- regs.control = readl(ohci->regs->control);
- regs.cmdstatus = readl(ohci->regs->cmdstatus);
- regs.intrstatus = readl(ohci->regs->intrstatus);
- regs.intrenable = readl(ohci->regs->intrenable);
- regs.intrdisable = readl(ohci->regs->intrdisable);
- regs.hcca = readl(ohci->regs->hcca);
- regs.ed_periodcurrent = readl(ohci->regs->ed_periodcurrent);
- regs.ed_controlhead = readl(ohci->regs->ed_controlhead);
- regs.ed_bulkhead = readl(ohci->regs->ed_bulkhead);
- regs.ed_bulkcurrent = readl(ohci->regs->ed_bulkcurrent);
- regs.current_donehead = readl(ohci->regs->current_donehead);
- regs.fminterval = readl(ohci->regs->fminterval);
- regs.fmremaining = readl(ohci->regs->fmremaining);
- regs.fmnumber = readl(ohci->regs->fmnumber);
- regs.periodicstart = readl(ohci->regs->periodicstart);
- regs.lsthresh = readl(ohci->regs->lsthresh);
- regs.roothub.a = readl(ohci->regs->roothub.a);
- regs.roothub.b = readl(ohci->regs->roothub.b);
- regs.roothub.status = readl(ohci->regs->roothub.status);
+ regs.revision = readl(&ohci->regs->revision);
+ regs.control = readl(&ohci->regs->control);
+ regs.cmdstatus = readl(&ohci->regs->cmdstatus);
+ regs.intrstatus = readl(&ohci->regs->intrstatus);
+ regs.intrenable = readl(&ohci->regs->intrenable);
+ regs.hcca = readl(&ohci->regs->hcca);
+ regs.ed_periodcurrent = readl(&ohci->regs->ed_periodcurrent);
+ regs.ed_controlhead = readl(&ohci->regs->ed_controlhead);
+ regs.ed_controlcurrent = readl(&ohci->regs->ed_controlcurrent);
+ regs.ed_bulkhead = readl(&ohci->regs->ed_bulkhead);
+ regs.ed_bulkcurrent = readl(&ohci->regs->ed_bulkcurrent);
+ regs.current_donehead = readl(&ohci->regs->current_donehead);
+ regs.fminterval = readl(&ohci->regs->fminterval);
+ regs.fmremaining = readl(&ohci->regs->fmremaining);
+ regs.fmnumber = readl(&ohci->regs->fmnumber);
+ regs.periodicstart = readl(&ohci->regs->periodicstart);
+ regs.lsthresh = readl(&ohci->regs->lsthresh);
+ regs.roothub.a = readl(&ohci->regs->roothub.a);
+ regs.roothub.b = readl(&ohci->regs->roothub.b);
+ regs.roothub.status = readl(&ohci->regs->roothub.status);
X for (i=0; i<MAX_ROOT_PORTS; ++i)
- regs.roothub.portstatus[i] = readl(ohci->regs->roothub.portstatus[i]);
+ regs.roothub.portstatus[i] = readl(&ohci->regs->roothub.portstatus[i]);
X
- printk(" ohci revision = 0x%x\n", regs.revision);
- printk(" ohci control = 0x%x\n", regs.control);
- printk(" ohci cmdstatus = 0x%x\n", regs.cmdstatus);
- printk(" ohci intrstatus = 0x%x\n", regs.intrstatus);
- printk(" ohci roothub.a = 0x%x\n", regs.roothub.a);
- printk(" ohci roothub.b = 0x%x\n", regs.roothub.b);
- printk(" ohci root status = 0x%x\n", regs.roothub.status);
+ printk(KERN_DEBUG " ohci revision = %x\n", regs.revision);
+ printk(KERN_DEBUG " ohci control = %x\n", regs.control);
+ printk(KERN_DEBUG " ohci cmdstatus = %x\n", regs.cmdstatus);
+ printk(KERN_DEBUG " ohci intrstatus = %x\n", regs.intrstatus);
+ printk(KERN_DEBUG " ohci intrenable = %x\n", regs.intrenable);
+
+ printk(KERN_DEBUG " ohci hcca = %x\n", regs.hcca);
+ printk(KERN_DEBUG " ohci ed_pdcur = %x\n", regs.ed_periodcurrent);
+ printk(KERN_DEBUG " ohci ed_ctrlhead = %x\n", regs.ed_controlhead);
+ printk(KERN_DEBUG " ohci ed_ctrlcur = %x\n", regs.ed_controlcurrent);
+ printk(KERN_DEBUG " ohci ed_bulkhead = %x\n", regs.ed_bulkhead);
+ printk(KERN_DEBUG " ohci ed_bulkcur = %x\n", regs.ed_bulkcurrent);
+ printk(KERN_DEBUG " ohci curdonehead = %x\n", regs.current_donehead);
+
+ printk(KERN_DEBUG " ohci fminterval = %x\n", regs.fminterval);
+ printk(KERN_DEBUG " ohci fmremaining = %x\n", regs.fmremaining);
+ printk(KERN_DEBUG " ohci fmnumber = %x\n", regs.fmnumber);
+ printk(KERN_DEBUG " ohci pdstart = %x\n", regs.periodicstart);
+ printk(KERN_DEBUG " ohci lsthresh = %x\n", regs.lsthresh);
+
+ printk(KERN_DEBUG " ohci roothub.a = %x\n", regs.roothub.a);
+ printk(KERN_DEBUG " ohci roothub.b = %x\n", regs.roothub.b);
+ printk(KERN_DEBUG " ohci root status = %x\n", regs.roothub.status);
+ printk(KERN_DEBUG " roothub.port0 = %x\n", regs.roothub.portstatus[0]);
+ printk(KERN_DEBUG " roothub.port1 = %x\n", regs.roothub.portstatus[1]);
X } /* show_ohci_status() */
X
X
-static void show_ohci_ed(struct ohci_ed *ed)
+void show_ohci_ed(struct ohci_ed *ed)
X {
X int stat = ed->status;
X int skip = (stat & OHCI_ED_SKIP);
@@ -57,82 +75,103 @@
X int dir = (stat & OHCI_ED_D);
X int endnum = (stat & OHCI_ED_EN) >> 7;
X int funcaddr = (stat & OHCI_ED_FA);
- int halted = (ed->head_td & 1);
- int toggle = (ed->head_td & 2) >> 1;
+ int halted = (ed->_head_td & 1);
+ int toggle = (ed->_head_td & 2) >> 1;
X
- printk(" ohci ED:\n");
- printk(" status = 0x%x\n", stat);
- printk(" %sMPS %d%s%s%s%s tc%d e%d fa%d\n",
+ printk(KERN_DEBUG " ohci ED:\n");
+ printk(KERN_DEBUG " status = 0x%x\n", stat);
+ printk(KERN_DEBUG " %sMPS %d%s%s%s%s tc%d e%d fa%d\n",
X skip ? "Skip " : "",
X mps,
X isoc ? "Isoc. " : "",
- low_speed ? "LowSpd " : "",
- (dir == OHCI_ED_D_IN) ? "Input " :
- (dir == OHCI_ED_D_OUT) ? "Output " : "",
- halted ? "Halted " : "",
+ low_speed ? " LowSpd" : "",
+ (dir == OHCI_ED_D_IN) ? " Input" :
+ (dir == OHCI_ED_D_OUT) ? " Output" : "",
+ halted ? " Halted" : "",
X toggle,
X endnum,
X funcaddr);
- printk(" tail_td = 0x%x\n", ed->tail_td);
- printk(" head_td = 0x%x\n", ed->head_td);
- printk(" next_ed = 0x%x\n", ed->next_ed);
+ printk(KERN_DEBUG " tail_td = 0x%x\n", ed->tail_td);
+ printk(KERN_DEBUG " head_td = 0x%x\n", ed_head_td(ed));
+ printk(KERN_DEBUG " next_ed = 0x%x\n", ed->next_ed);
X } /* show_ohci_ed() */
X
X
-static void show_ohci_td(struct ohci_td *td)
+void show_ohci_td(struct ohci_td *td)
X {
X int td_round = td->info & OHCI_TD_ROUND;
X int td_dir = td->info & OHCI_TD_D;
- int td_int_delay = td->info & OHCI_TD_IOC_DELAY;
- int td_toggle = td->info & OHCI_TD_DT;
- int td_errcnt = td_errorcount(td->info);
- int td_cc = td->info & OHCI_TD_CC;
-
- printk(" ohci TD hardware fields:\n");
- printk(" info = 0x%x\n", td->info);
- printk(" %s%s%s%d%s%s%d%s%d\n",
+ int td_int_delay = (td->info & OHCI_TD_IOC_DELAY) >> 21;
+ int td_toggle = (td->info & OHCI_TD_DT) >> 24;
+ int td_errcnt = td_errorcount(*td);
+ int td_cc = OHCI_TD_CC_GET(td->info);
+
+ printk(KERN_DEBUG " ohci TD hardware fields:\n");
+ printk(KERN_DEBUG " info = 0x%x\n", td->info);
+ printk(KERN_DEBUG " %s%s%s%d %s\n",
X td_round ? "Rounding " : "",
X (td_dir == OHCI_TD_D_IN) ? "Input " :
X (td_dir == OHCI_TD_D_OUT) ? "Output " :
X (td_dir == OHCI_TD_D_SETUP) ? "Setup " : "",
- "IntDelay ", td_int_delay >> 21,
- td_toggle ? "Data1 " : "Data0 ",
+ "IntDelay ", td_int_delay,
+ (td_toggle < 2) ? " " :
+ (td_toggle & 1) ? "Data1 " : "Data0 ");
+ printk(KERN_DEBUG " %s%d %s0x%x, %sAccessed, %sActive\n",
X "ErrorCnt ", td_errcnt,
- "ComplCode ", td_cc);
- printk(" %sAccessed, %sActive\n",
- td_cc_accessed(td->info) ? "" : "Not ",
- td_active(td->info) ? "" : "Not ");
-
- printk(" cur_buf = 0x%x\n", td->cur_buf);
- printk(" next_td = 0x%x\n", td->next_td);
- printk(" buf_end = 0x%x\n", td->buf_end);
- printk(" ohci TD driver fields:\n");
- printk(" data = %p\n", td->data);
- printk(" dev_id = %p\n", td->dev_id);
- printk(" ed_bus = %x\n", td->ed_bus);
+ "ComplCode ", td_cc,
+ td_cc_accessed(*td) ? "" : "Not ",
+ td_active(*td) ? "" : "Not ");
+
+ printk(KERN_DEBUG " cur_buf = 0x%x\n", td->cur_buf);
+ printk(KERN_DEBUG " next_td = 0x%x\n", td->next_td);
+ printk(KERN_DEBUG " buf_end = 0x%x\n", td->buf_end);
+ printk(KERN_DEBUG " ohci TD driver fields:\n");
+ printk(KERN_DEBUG " data = %p\n", td->data);
+ printk(KERN_DEBUG " dev_id = %p\n", td->dev_id);
+ printk(KERN_DEBUG " ed = %p\n", td->ed);
+ if (td->data != NULL) {
+ unsigned char *d = td->data;
+ printk(KERN_DEBUG " DATA: %02x %02x %02x %02x %02x %02x %02x %02x\n",
+ d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7] );
+ }
X } /* show_ohci_td() */
X
X
X void show_ohci_device(struct ohci_device *dev)
X {
X int idx;
- printk(" ohci_device usb = %p\n", dev->usb);
- printk(" ohci_device ohci = %p\n", dev->ohci);
- printk(" ohci_device ohci_hcca = %p\n", dev->hcca);
- for (idx=0; idx<8 /*NUM_EDS*/; ++idx) {
- printk(" [ed num %d] ", idx);
+ printk(KERN_DEBUG " ohci_device usb = %p\n", dev->usb);
+ printk(KERN_DEBUG " ohci_device ohci = %p\n", dev->ohci);
+ printk(KERN_DEBUG " ohci_device ohci_hcca = %p\n", dev->hcca);
+ for (idx=0; idx<3 /*NUM_EDS*/; ++idx) {
+ printk(KERN_DEBUG " [ed num %d] ", idx);
X show_ohci_ed(&dev->ed[idx]);
X }
- for (idx=0; idx<8 /*NUM_TDS*/; ++idx) {
- printk(" [td num %d] ", idx);
+ for (idx=0; idx<3 /*NUM_TDS*/; ++idx) {
+ printk(KERN_DEBUG " [td num %d] ", idx);
X show_ohci_td(&dev->td[idx]);
X }
- printk(" ohci_device data\n ");
+ printk(KERN_DEBUG " ohci_device data\n ");
X for (idx=0; idx<4; ++idx) {
- printk(" %08lx", dev->data[idx]);
+ printk(KERN_DEBUG " %08lx", dev->data[idx]);
X }
- printk("\n");
+ printk(KERN_DEBUG "\n");
X } /* show_ohci_device() */
+
+
+void show_ohci_hcca(struct ohci_hcca *hcca)
+{
+ int idx;
+
+ printk(KERN_DEBUG " ohci_hcca\n");
+
+ for (idx=0; idx<NUM_INTS; idx++) {
+ printk(KERN_DEBUG " int_table[%2d] == %p\n", idx, hcca->int_table +idx);
+ }
+
+ printk(KERN_DEBUG " frame_no == %d\n", hcca->frame_no);
+ printk(KERN_DEBUG " donehead == 0x%08x\n", hcca->donehead);
+} /* show_ohci_hcca() */
X
X
X /* vim:sw=8
diff -u --recursive --new-file v2.2.7/linux/drivers/usb/ohci-hcd.c linux/drivers/usb/ohci-hcd.c
--- v2.2.7/linux/drivers/usb/ohci-hcd.c Wed Dec 31 16:00:00 1969
+++ linux/drivers/usb/ohci-hcd.c Tue May 11 09:55:45 1999
@@ -0,0 +1,1489 @@
+/*
+ * OHCI HCD (Host Controller Driver) for USB.
+ *
+ * (C) Copyright 1999 Roman Weissgaerber <wei...@vienna.at>
+ *
+ * The OHCI HCD layer is a simple but nearly complete implementation of what the
+ * USB people would call a HCD for the OHCI.
+ * (ISO comming soon, Bulk disabled, INT u. CTRL transfers enabled)
+ * The layer on top of it, is for interfacing to the alternate-usb device-drivers.
+ *
+ * [ This is based on Linus' UHCI code and gregs OHCI fragments (0.03c source tree). ]
+ * [ Open Host Controller Interface driver for USB. ]
+ * [ (C) Copyright 1999 Linus Torvalds (uhci.c) ]
+ * [ (C) Copyright 1999 Gregory P. Smith <gr...@electricrain.com> ]
+ * [ $Log: ohci.c,v $ ]
+ * [ Revision 1.1 1999/04/05 08:32:30 greg ]
+ *
+ *
+ * v2.1 1999/05/09 ep_addr correction, code clean up
+ * v2.0 1999/05/04
+ * virtual root hub is now an option,
+ * memory allocation based on kmalloc and kfree now, Bus error handling,
+ * INT and CTRL transfers enabled, Bulk included but disabled, ISO needs completion
+ *
+ * from Linus Torvalds (uhci.c) (APM not tested; hub, usb_device, bus and related stuff)
+ * from Greg Smith (ohci.c) (reset controller handling, hub)
+ *
+ * v1.0 1999/04/27 initial release
+ * ohci-hcd.c
+ */
+
+/* #define OHCI_DBG */ /* printk some debug information */
+
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/malloc.h>
+#include <linux/smp_lock.h>
+#include <linux/errno.h>
+#include <linux/timer.h>
+
+#include <asm/spinlock.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+
+#include "usb.h"
+#include "ohci-hcd.h"
+#include "inits.h"
+
+
+
+#ifdef CONFIG_APM
+#include <linux/apm_bios.h>
+static int handle_apm_event(apm_event_t event);
+static int apm_resume = 0;
+#endif
+
+
+
+static struct wait_queue *control_wakeup;
+static struct wait_queue *root_hub = NULL;
+
+static __u8 cc_to_status[16] = { /* mapping of the OHCI CC to the UHCI status codes; first guess */
+/* Activ, Stalled, Data Buffer Err, Babble Detected : NAK recvd, CRC/Timeout, Bitstuff, reservd */
+/* No Error */ 0x00,
+/* CRC Error */ 0x04,
+/* Bit Stuff */ 0x02,
+/* Data Togg */ 0x40,
+/* Stall */ 0x40,
+/* DevNotResp */ 0x04,
+/* PIDCheck */ 0x04,
+/* UnExpPID */ 0x40,
+/* DataOver */ 0x20,
+/* DataUnder */ 0x20,
+/* reservd */ 0x40,
+/* reservd */ 0x40,
+/* BufferOver */ 0x20,
+/* BuffUnder */ 0x20,
+/* Not Access */ 0x80,
+/* Not Access */ 0x80
+ };
+
+
+/********
+ **** Interface functions
+ ***********************************************/
+
+static int sohci_int_handler(void * ohci_in, unsigned int ep_addr, int ctrl_len, void * ctrl, void * data, int data_len, int status, __OHCI_BAG lw0, __OHCI_BAG lw1)
+{
+
+ struct ohci * ohci = ohci_in;
+ usb_device_irq handler=(void *) lw0;
+ void *dev_id = (void *) lw1;
+ int ret;
+
+ OHCI_DEBUG({ int i; printk("USB HC IRQ <<<: %x: data(%d):", ep_addr, data_len);)
+ OHCI_DEBUG( for(i=0; i < data_len; i++ ) printk(" %02x", ((__u8 *) data)[i]);)
+ OHCI_DEBUG( printk(" ret_status: %x\n", status); })
+
+ ret = handler(cc_to_status[status & 0xf], data, dev_id);
+ if(ret == 0) return 0; /* 0 .. do not requeue */
+ if(status > 0) return -1; /* error occured do not requeue ? */
+ ohci_trans_req(ohci, ep_addr, 0, NULL, data, 8, (__OHCI_BAG) handler, (__OHCI_BAG) dev_id); /* requeue int request */


+ return 0;
+}
+

+static int sohci_ctrl_handler(void * ohci_in, unsigned int ep_addr, int ctrl_len, void * ctrl, void * data, int data_len, int status, __OHCI_BAG lw0, __OHCI_BAG lw)
+{
+ *(int * )lw0 = status;
+ wake_up(&control_wakeup);
+
+ OHCI_DEBUG( { int i; printk("USB HC CTRL<<<: %x: ctrl(%d):", ep_addr, ctrl_len);)
+ OHCI_DEBUG( for(i=0; i < 8; i++ ) printk(" %02x", ((__u8 *) ctrl)[i]);)
+ OHCI_DEBUG( printk(" data(%d):", data_len);)
+ OHCI_DEBUG( for(i=0; i < data_len; i++ ) printk(" %02x", ((__u8 *) data)[i]);)
+ OHCI_DEBUG( printk(" ret_status: %x\n", status); })


+ return 0;
+}
+

+static int sohci_request_irq(struct usb_device *usb_dev, unsigned int pipe, usb_device_irq handler, int period, void *dev_id)
+{
+ struct ohci * ohci = usb_dev->bus->hcpriv;
+ union ep_addr_ ep_addr;
+
+ ep_addr.iep = 0;
+ ep_addr.bep.ep = ((pipe >> 15) & 0x0f) /* endpoint address */
+ | (pipe & 0x80) /* direction */
+ | (1 << 5); /* type = int*/
+ ep_addr.bep.fa = ((pipe >> 8) & 0x7f); /* device address */
+
+ OHCI_DEBUG( printk("USB HC IRQ >>>: %x: every %d ms\n", ep_addr.iep, period);)
+
+ usb_ohci_add_ep(ohci, ep_addr.iep, period, 1, sohci_int_handler, 1 << ((pipe & 0x03) + 3) , (pipe >> 26) & 0x01);
+
+ ohci_trans_req(ohci, ep_addr.iep, 0, NULL, ((struct ohci_device *) usb_dev->hcpriv)->data, 8, (__OHCI_BAG) handler, (__OHCI_BAG) dev_id);


+ return 0;
+}
+

+
+static int sohci_control_msg(struct usb_device *usb_dev, unsigned int pipe, void *cmd, void *data, int len)


+{
+ struct wait_queue wait = { current, NULL };

+ struct ohci * ohci = usb_dev->bus->hcpriv;
+ int status;
+ union ep_addr_ ep_addr;
+
+ ep_addr.iep = 0;
+ ep_addr.bep.ep = ((pipe >> 15) & 0x0f) /* endpoint address */
+ | (pipe & 0x80) /* direction */
+ | (1 << 6); /* type = ctrl*/
+ ep_addr.bep.fa = ((pipe >> 8) & 0x7f); /* device address */
+
+ status = 0xf; /* CC not Accessed */
+ OHCI_DEBUG( { int i; printk("USB HC CTRL>>>: %x: ctrl(%d):", ep_addr.iep, 8);)
+ OHCI_DEBUG( for(i=0; i < 8; i++ ) printk(" %02x", ((__u8 *) cmd)[i]);)
+ OHCI_DEBUG( printk(" data(%d):", len);)
+ OHCI_DEBUG( for(i=0; i < len; i++ ) printk(" %02x", ((__u8 *) data)[i]);)
+ OHCI_DEBUG( printk("\n"); })
+
+ usb_ohci_add_ep(ohci, ep_addr.iep, 0, 1, sohci_ctrl_handler, 1 << ((pipe & 0x03) + 3) , (pipe >> 26) & 0x01);
+

+ current->state = TASK_UNINTERRUPTIBLE;

+ add_wait_queue(&control_wakeup, &wait);
+
+ ohci_trans_req(ohci, ep_addr.iep, 8, cmd, data, len, (__OHCI_BAG) &status, 0);
+
+ schedule_timeout(HZ/10);
+
+ remove_wait_queue(&control_wakeup, &wait);
+
+ OHCI_DEBUG(printk("USB HC status::: %x\n", cc_to_status[status & 0x0f]);)
+
+ return cc_to_status[status & 0x0f];
+}
+
+
+static int sohci_usb_deallocate(struct usb_device *usb_dev) {
+ struct ohci_device *dev = usb_to_ohci(usb_dev);
+ union ep_addr_ ep_addr;
+
+ ep_addr.iep = 0;
+
+ OHCI_DEBUG(printk("USB HC dealloc %x\n", usb_dev->devnum);)
+
+ /* wait_ms(20); */
+
+ if(usb_dev->devnum >=0) {
+ ep_addr.bep.fa = usb_dev->devnum;
+ usb_ohci_rm_function(((struct ohci_device *)usb_dev->hcpriv)->ohci, ep_addr.iep);
+ }
+
+ USB_FREE(dev);
+ USB_FREE(usb_dev);
+


+ return 0;
+}
+

+static struct usb_device *sohci_usb_allocate(struct usb_device *parent) {
+
+ struct usb_device *usb_dev;
+ struct ohci_device *dev;
+
+
+ USB_ALLOC(usb_dev, sizeof(*usb_dev));
+ if (!usb_dev)
+ return NULL;
+
+ memset(usb_dev, 0, sizeof(*usb_dev));
+
+ USB_ALLOC(dev, sizeof(*dev));
+ if (!dev) {
+ USB_FREE(usb_dev);


+ return NULL;
+ }
+

+ /* Initialize "dev" */
+ memset(dev, 0, sizeof(*dev));
+
+ usb_dev->hcpriv = dev;
+ dev->usb = usb_dev;
+
+ usb_dev->parent = parent;
+
+ if (parent) {
+ usb_dev->bus = parent->bus;
+ dev->ohci = usb_to_ohci(parent)->ohci;
+ }
+ return usb_dev;
+}
+
+struct usb_operations sohci_device_operations = {
+ sohci_usb_allocate,
+ sohci_usb_deallocate,
+ sohci_control_msg,
+ sohci_request_irq,
+};
+
+
+/******
+ *** ED handling functions
+ ************************************/
+
+
+
+/*
+ * search for the right place to insert an interrupt ed into the int tree
+ * do some load ballancing
+ * */
+
+static int usb_ohci_int_ballance(struct ohci * ohci, int interval, int load) {
+
+ int i,j;
+
+ j = 0; /* search for the least loaded interrupt endpoint branch of all 32 branches */
+ for(i=0; i< 32; i++) if(ohci->ohci_int_load[j] > ohci->ohci_int_load[i]) j=i;
+
+ if(interval < 1) interval = 1;
+ if(interval > 32) interval = 32;
+ for(i= 0; ((interval >> i) > 1 ); interval &= (0xfffe << i++ )); /* interval = 2^int(ld(interval)) */
+
+
+ for(i=j%interval; i< 32; i+=interval) ohci->ohci_int_load[i] += load;
+ j = interval + (j % interval);
+
+ OHCI_DEBUG(printk("USB HC new int ed on pos : %x \n",j);)
+
+ return j;
+}
+
+/* get the ed from the endpoint / device adress */
+
+struct usb_ohci_ed * ohci_find_ep(struct ohci *ohci, unsigned int ep_addr_in) {
+
+union ep_addr_ ep_addr;
+struct usb_ohci_ed *tmp;
+unsigned int mask;
+
+mask = 0;
+ep_addr.iep = ep_addr_in;
+
+#ifdef VROOTHUB
+ if(ep_addr.bep.fa == ohci->root_hub_funct_addr) {
+ if((ep_addr.bep.ep & 0x0f) == 0)
+ return &ohci->ed_rh_ep0; /* root hub ep0 */
+ else
+ return &ohci->ed_rh_epi; /* root hub int ep */
+ }
+#endif
+
+ tmp = ohci->ed_func_ep0[ep_addr.bep.fa];
+ mask = ((((ep_addr.bep.ep >> 5) & 0x03)==2)?0x7f:0xff);
+ ep_addr.bep.ep &= mask; /* mask out direction of ctrl ep */
+
+ while (tmp != NULL) {
+ if (tmp->ep_addr.iep == ep_addr.iep)
+ return tmp;
+ tmp = tmp->ed_list;
+ }


+ return NULL;
+}
+

+spinlock_t usb_ed_lock = SPIN_LOCK_UNLOCKED;
+/* add a new endpoint ep_addr */
+struct usb_ohci_ed *usb_ohci_add_ep(struct ohci * ohci, unsigned int ep_addr_in, int interval, int load, f_handler handler, int ep_size, int speed) {
+
+ struct usb_ohci_ed * ed;
+ struct usb_ohci_td * td;
+ union ep_addr_ ep_addr;
+
+
+ int int_junk;
+
+ struct usb_ohci_ed *tmp;
+
+ ep_addr.iep = ep_addr_in ;
+ ep_addr.bep.ep &= ((((ep_addr.bep.ep >> 5) & 0x03)==2)?0x7f:0xff); /* mask out direction of ctrl ep */
+
+ spin_lock(&usb_ed_lock);
+
+ tmp = ohci_find_ep(ohci, ep_addr.iep);
+ if (tmp != NULL) {
+
+#ifdef VROOTHUB
+ if(ep_addr.bep.fa == ohci->root_hub_funct_addr) {
+ if((ep_addr.bep.ep & 0x0f) != 0) { /* root hub int ep */
+ ohci->ed_rh_epi.handler = handler;
+ ohci_init_rh_int_timer(ohci, interval);
+ }
+ else { /* root hub ep0 */
+ ohci->ed_rh_ep0.handler = handler;
+ }
+ }
+
+ else
+#endif
+
+ {
+ tmp->hw.info = ep_addr.bep.fa | ((ep_addr.bep.ep & 0xf) <<7)
+
+ | (((ep_addr.bep.ep & 0x60) == 0)? 0x8000 : 0)
+ | (speed << 13)
+ | ep_size <<16;
+
+ tmp->handler = handler;
+ }
+ spin_unlock(&usb_ed_lock);
+ return tmp; /* ed already in use */
+ }
+
+
+ OHCI_ALLOC(td, sizeof(td)); /* dummy td; end of td list for ed */
+ OHCI_ALLOC(ed, sizeof(ed));
+ td->prev_td = NULL;
+
+ ed->hw.tail_td = virt_to_bus(&td->hw);
+ ed->hw.head_td = ed->hw.tail_td;
+ ed->hw.info = ep_addr.bep.fa | ((ep_addr.bep.ep & 0xf) <<7)
+ /* | ((ep_addr.bep.port & 0x80)? 0x1000 : 0x0800 ) */
+ | (((ep_addr.bep.ep & 0x60) == 0)? 0x8000 : 0)
+ | (speed << 13)
+ | ep_size <<16;
+
+ ed->handler = handler;
+
+ switch((ep_addr.bep.ep >> 5) & 0x03) {
+ case CTRL:
+ ed->hw.next_ed = 0;
+ if(ohci->ed_controltail == NULL) {
+ writel(virt_to_bus(&ed->hw), &ohci->regs->ed_controlhead);
+ }
+ else {
+ ohci->ed_controltail->hw.next_ed = virt_to_bus(&ed->hw);
+ }
+ ed->ed_prev = ohci->ed_controltail;
+ ohci->ed_controltail = ed;
+ break;
+ case BULK:
+ ed->hw.next_ed = 0;
+ if(ohci->ed_bulktail == NULL) {
+ writel(virt_to_bus(&ed->hw), &ohci->regs->ed_bulkhead);
+ }
+ else {
+ ohci->ed_bulktail->hw.next_ed = virt_to_bus(&ed->hw);
+ }
+ ed->ed_prev = ohci->ed_bulktail;
+ ohci->ed_bulktail = ed;
+ break;
+ case INT:
+ int_junk = usb_ohci_int_ballance(ohci, interval, load);
+ ed->hw.next_ed = ohci->hc_area->ed[int_junk].next_ed;
+ ohci->hc_area->ed[int_junk].next_ed = virt_to_bus(&ed->hw);
+ ed->ed_prev = (struct usb_ohci_ed *) &ohci->hc_area->ed[int_junk];
+ break;
+ case ISO:
+ ed->hw.next_ed = 0;
+ ohci->ed_isotail->hw.next_ed = virt_to_bus(&ed->hw);
+ ed->ed_prev = ohci->ed_isotail;
+ ohci->ed_isotail = ed;
+ break;
+ }
+ ed->ep_addr = ep_addr;
+
+ /* Add it to the "hash"-table of known endpoint descriptors */
+
+ ed->ed_list = ohci->ed_func_ep0[ed->ep_addr.bep.fa];
+ ohci->ed_func_ep0[ed->ep_addr.bep.fa] = ed;
+
+ spin_unlock(&usb_ed_lock);
+
+ OHCI_DEBUG(printk("USB HC new ed %x: %x :", ep_addr.iep, (unsigned int ) ed); )
+ OHCI_DEBUG({ int i; for( i= 0; i<8 ;i++) printk(" %4x", ((unsigned int *) ed)[i]) ; printk("\n"); }; )


+ return 0;
+}
+

+/*****
+ * Request the removal of an endpoint
+ *
+ * put the ep on the rm_list and request a stop of the bulk or ctrl list
+ * real removal is done at the next start of frame hardware interrupt
+ */
+int usb_ohci_rm_ep(struct ohci * ohci, struct usb_ohci_ed *ed)
+{
+ unsigned int flags;
+ struct usb_ohci_ed *tmp;
+
+ OHCI_DEBUG(printk("USB HC remove ed %x: %x :\n", ed->ep_addr.iep, (unsigned int ) ed); )
+
+ spin_lock_irqsave(&usb_ed_lock, flags);
+
+ tmp = ohci->ed_func_ep0[ed->ep_addr.bep.fa];
+ if (tmp == NULL) {
+ spin_unlock_irqrestore(&usb_ed_lock, flags);


+ return 0;
+ }
+

+ if(tmp == ed) {
+ ohci->ed_func_ep0[ed->ep_addr.bep.fa] = ed->ed_list;
+ }
+ else {
+ while (tmp->ed_list != ed) {
+ if (tmp->ed_list == NULL) {
+ spin_unlock_irqrestore(&usb_ed_lock, flags);
+ return 0;
+ }
+ tmp = tmp->ed_list;
+ }
+ tmp->ed_list = ed->ed_list;
+ }
+ ed->ed_list = ohci->ed_rm_list;
+ ohci->ed_rm_list = ed;
+ ed->hw.info |= OHCI_ED_SKIP;
+
+ switch((ed->ep_addr.bep.ep >> 5) & 0x03) {
+ case CTRL:
+ writel_mask(~(0x01<<4), &ohci->regs->control); /* stop CTRL list */
+ break;
+ case BULK:
+ writel_mask(~(0x01<<5), &ohci->regs->control); /* stop BULK list */


+ break;
+ }
+
+

+ writel( OHCI_INTR_SF, &ohci->regs->intrenable); /* enable sof interrupt */
+
+ spin_unlock_irqrestore(&usb_ed_lock, flags);


+
+ return 1;
+}
+

+/* we have requested to stop the bulk or CTRL list,
+ * now we can remove the eds on the rm_list */
+
+static int ohci_rm_eds(struct ohci * ohci) {
+
+ unsigned int flags;
+ struct usb_ohci_ed *ed;
+ struct usb_ohci_ed *ed_tmp;
+ struct usb_ohci_td *td;
+ __u32 td_hw_tmp;
+ __u32 td_hw;
+
+ spin_lock_irqsave(&usb_ed_lock, flags);
+
+ ed = ohci->ed_rm_list;
+
+ while (ed != NULL) {
+
+ switch((ed->ep_addr.bep.ep >> 5) & 0x03) {
+ case CTRL:
+ if(ed->ed_prev == NULL) {
+ writel(ed->hw.next_ed, &ohci->regs->ed_controlhead);
+ }
+ else {
+ ed->ed_prev->hw.next_ed = ed->hw.next_ed;
+ }
+ if(ohci->ed_controltail == ed) {
+ ohci->ed_controltail = ed->ed_prev;
+ }
+ break;
+ case BULK:
+ if(ed->ed_prev == NULL) {
+ writel(ed->hw.next_ed, &ohci->regs->ed_bulkhead);
+ }
+ else {
+ ed->ed_prev->hw.next_ed = ed->hw.next_ed;
+ }
+ if(ohci->ed_bulktail == ed) {
+ ohci->ed_bulktail = ed->ed_prev;
+ }
+ break;
+ case INT:
+ ed->ed_prev->hw.next_ed = ed->hw.next_ed;
+ break;
+ case ISO:
+ ed->ed_prev->hw.next_ed = ed->hw.next_ed;
+ if(ohci->ed_isotail == ed) {
+ ohci->ed_isotail = ed->ed_prev;
+ }
+ break;
+ }
+
+ if(ed->hw.next_ed != 0) ((struct usb_ohci_ed *) bus_to_virt(ed->hw.next_ed))->ed_prev = ed->ed_prev;
+
+
+/* tds directly connected to ed */
+
+ td_hw = ed->hw.head_td & 0xfffffff0;
+ while(td_hw != 0) {
+ td = bus_to_virt(td_hw);
+ td_hw_tmp = td_hw;
+ td_hw = td->hw.next_td;
+ OHCI_FREE(td); /* free pending tds */
+ if(td_hw_tmp == ed->hw.tail_td) break;
+
+ }
+
+ /* mark TDs on the hc done list (if there are any) */
+ td_hw = readl(&ohci->regs->donehead) & 0xfffffff0;
+ while(td_hw != 0) {
+ td = bus_to_virt(td_hw);
+ td_hw = td->hw.next_td;
+ if(td->ep == ed) td->ep = 0;
+ }
+
+ /* mark TDs on the hcca done list (if there are any) */
+ td_hw = ohci->hc_area->hcca.done_head & 0xfffffff0 ;
+
+ while(td_hw != 0) {
+ td = bus_to_virt(td_hw);
+ td_hw = td->hw.next_td;
+ if(td->ep == ed) td->ep = 0;
+ }
+
+ ed_tmp = ed;
+ ed = ed->ed_list;
+ OHCI_FREE(ed_tmp); /* free ed */
+ }
+ writel(0, &ohci->regs->ed_controlcurrent); /* reset CTRL list */
+ writel(0, &ohci->regs->ed_bulkcurrent); /* reset BULK list */
+ writel_set((0x01<<4), &ohci->regs->control); /* start CTRL u. (BULK list) */
+
+ spin_unlock_irqrestore(&usb_ed_lock, flags);
+
+ ohci->ed_rm_list = NULL;
+ OHCI_DEBUG(printk("USB HC after rm ed control: %4x intrstat: %4x intrenable: %4x\n", readl(&ohci->regs->control),readl(&ohci->regs->intrstatus),readl(&ohci->regs->intrenable));)


+
+
+ return 0;

+}
+
+/* remove all endpoints of a function (device) */
+int usb_ohci_rm_function( struct ohci * ohci, unsigned int ep_addr_in)
+{
+ struct usb_ohci_ed *ed;
+ struct usb_ohci_ed *tmp;
+ union ep_addr_ ep_addr;
+
+
+
+ ep_addr.iep = ep_addr_in;
+
+ for(ed = ohci->ed_func_ep0[ep_addr.bep.fa]; ed != NULL;) {
+ tmp = ed;
+ ed = ed->ed_list;
+ usb_ohci_rm_ep(ohci, tmp);
+ }
+
+


+
+ return 1;
+}
+
+
+

+
+
+/******
+ *** TD handling functions
+ ************************************/
+
+
+#define FILL_TD(TD_PT, HANDLER, INFO, DATA, LEN, LW0, LW1) \
+ td_pt = (TD_PT); \
+ td_pt1 = (struct usb_ohci_td *) bus_to_virt(usb_ep->hw.tail_td); \
+ td_pt1->ep = usb_ep; \
+ td_pt1->handler = (HANDLER); \
+ td_pt1->buffer_start = (DATA); \
+ td_pt1->lw0 = (LW0); \
+ td_pt1->lw1 = (LW1); \
+ td_pt1->hw.info = (INFO); \
+ td_pt1->hw.cur_buf = virt_to_bus(DATA); \
+ td_pt1->hw.buf_end = td_pt1->hw.cur_buf + (LEN) - 1; \
+ td_pt1->hw.next_td = virt_to_bus(td_pt); \
+ usb_ep->hw.tail_td = virt_to_bus(td_pt); \
+ td_pt->prev_td = td_pt1; \
+ td_pt->hw.next_td = 0
+
+spinlock_t usb_req_lock = SPIN_LOCK_UNLOCKED;
+
+int ohci_trans_req(struct ohci * ohci, unsigned int ep_addr, int ctrl_len, void *ctrl, void * data, int data_len, __OHCI_BAG lw0, __OHCI_BAG lw1) {
+
+ int ed_type;
+ unsigned int flags;
+ struct usb_ohci_td *td_pt;
+ struct usb_ohci_td *td_pt1;
+ struct usb_ohci_td *td_pt_a1, *td_pt_a2, *td_pt_a3;
+ struct usb_ohci_ed *usb_ep;
+ f_handler handler;
+
+
+ td_pt_a1 =NULL;
+ td_pt_a2 =NULL;
+ td_pt_a3 =NULL;
+
+ usb_ep = ohci_find_ep(ohci, ep_addr);
+ if(usb_ep == NULL ) return -1; /* not known ep */
+
+ handler = usb_ep->handler;
+
+#ifdef VROOTHUB
+ if(usb_ep == &ohci->ed_rh_ep0) { /* root hub ep 0 control endpoint */
+ root_hub_control_msg(ohci, 8, ctrl, data, data_len, lw0, lw1, handler);


+ return 0;
+ }
+

+ if(usb_ep == &ohci->ed_rh_epi) { /* root hub interrupt endpoint */
+
+ root_hub_int_req(ohci, 8, ctrl, data, data_len, lw0, lw1, handler);

+ return 0;
+ }
+#endif

+ /* struct usb_ohci_ed * usb_ep = usb_ohci_add_ep(pipe, ohci, interval, 1); */
+
+ ed_type = ((((union ep_addr_)ep_addr).bep.ep >> 5) & 0x07);
+
+ switch(ed_type) {
+ case BULK_IN:
+ case BULK_OUT:
+ case INT_IN:
+ case INT_OUT:
+ OHCI_ALLOC(td_pt_a1, sizeof(td_pt_a1));
+ break;
+
+ case CTRL_IN:
+ case CTRL_OUT:
+ OHCI_ALLOC(td_pt_a1, sizeof(td_pt_a1));
+ OHCI_ALLOC(td_pt_a3, sizeof(td_pt_a3));
+ if(data_len > 0) {
+ OHCI_ALLOC(td_pt_a2, sizeof(td_pt_a2));
+ }
+ break;
+
+ case ISO_IN:
+ case ISO_OUT:
+
+ }
+
+ spin_lock_irqsave(&usb_req_lock, flags);
+
+ switch(ed_type) {
+ case BULK_IN:
+ FILL_TD( td_pt_a1, handler, TD_CC | TD_R | TD_DP_IN | TD_T_TOGGLE, data, data_len, lw0, lw1 );


SHAR_EOF
true || echo 'restore of patch-2.2.8 failed'
fi

echo 'End of part 22'
echo 'File patch-2.2.8 is continued in part 23'
echo 23 > _shar_seq_.tmp

Thomas...@ciw.uni-karlsruhe.de

unread,
May 12, 1999, 3:00:00 AM5/12/99
to
Archive-name: v2.2/patch-2.2.8/part23

#!/bin/sh
# this is part 23 of a 33 - part archive


# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.8 continued
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 23; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.8'
else
echo 'x - continuing with patch-2.2.8'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.8' &&

+ writel( OHCI_BLF, &ohci->regs->cmdstatus); /* start bulk list */
+ break;
+
+ case BULK_OUT:
+ FILL_TD( td_pt_a1, handler, TD_CC | TD_DP_OUT | TD_T_TOGGLE, data, data_len, lw0, lw1 );
+ writel( OHCI_BLF, &ohci->regs->cmdstatus); /* start bulk list */
+ break;
+
+ case INT_IN:

+ FILL_TD( td_pt_a1, handler, TD_CC | TD_R | TD_DP_IN | TD_T_TOGGLE, data, data_len, lw0, lw1 );

+ break;
+
+ case INT_OUT:
+ FILL_TD( td_pt_a1, handler, TD_CC | TD_DP_OUT | TD_T_TOGGLE, data, data_len, lw0, lw1 );


+ break;
+
+ case CTRL_IN:

+ FILL_TD( td_pt_a1, NULL, TD_CC | TD_DP_SETUP | TD_T_DATA0, ctrl, ctrl_len, 0, 0 );
+ if(data_len > 0) {
+ FILL_TD( td_pt_a2, NULL, TD_CC | TD_R | TD_DP_IN | TD_T_DATA1, data, data_len, 0, 0 );
+ }
+ FILL_TD( td_pt_a3, handler, TD_CC | TD_DP_OUT | TD_T_DATA1, NULL, 0, lw0, lw1 );
+ writel( OHCI_CLF, &ohci->regs->cmdstatus); /* start Control list */
+ break;
+
+ case CTRL_OUT:
+ FILL_TD( td_pt_a1, NULL, TD_CC | TD_DP_SETUP | TD_T_DATA0, ctrl, ctrl_len, 0, 0 );
+ if(data_len > 0) {
+ FILL_TD( td_pt_a2, NULL, TD_CC | TD_R | TD_DP_OUT | TD_T_DATA1, data, data_len, 0, 0 );
+ }
+ FILL_TD( td_pt_a3, handler, TD_CC | TD_DP_IN | TD_T_DATA1, NULL, 0, lw0, lw1 );
+ writel( OHCI_CLF, &ohci->regs->cmdstatus); /* start Control list */
+ break;
+


+ case ISO_IN:
+ case ISO_OUT:

+ break;
+ }
+
+
+

+


+ td_pt1 = (struct usb_ohci_td *) bus_to_virt(usb_ep->hw.tail_td);
+

+
+ if(td_pt_a3 != NULL) td_pt_a3->prev_td = NULL;
+ else if (td_pt_a2 != NULL) td_pt_a2->prev_td = NULL;
+ else if (td_pt_a1 != NULL) td_pt_a1->prev_td = NULL;
+
+ spin_unlock_irqrestore(&usb_req_lock, flags);


+ return 0;
+}
+
+

+/******
+ *** Done List handling functions
+ ************************************/
+
+/* replies to the request have to be on a FIFO basis so
+ * we reverse the reversed done-list */
+
+static struct usb_ohci_td * ohci_reverse_done_list(struct ohci * ohci) {
+
+ __u32 td_list_hc;
+ struct usb_ohci_td * td_list = NULL;
+ struct usb_ohci_td * td_rev = NULL;
+
+ td_list_hc = ohci->hc_area->hcca.done_head & 0xfffffff0;
+ ohci->hc_area->hcca.done_head = 0;
+
+ while(td_list_hc) {
+
+ td_list = (struct usb_ohci_td *) bus_to_virt(td_list_hc);
+ td_list->next_dl_td = td_rev;
+
+ td_rev = td_list;
+ td_list_hc = td_list->hw.next_td & 0xfffffff0;
+ }
+ return td_list;
+}
+
+/* all done requests are replied here */
+static int usb_ohci_done_list(struct ohci * ohci) {
+
+ struct usb_ohci_td * td = NULL;
+ struct usb_ohci_td * td_list;
+ struct usb_ohci_td * td_list_next = NULL;
+ struct usb_ohci_td * td_err = NULL;


+ __u32 td_hw;
+
+

+ td_list = ohci_reverse_done_list(ohci);
+
+ while(td_list) {
+ td_list_next = td_list->next_dl_td;
+ td = td_list;
+
+ if(td->ep == NULL) { /* removed ep */
+ OHCI_FREE(td_list);
+ break;
+ }
+
+ /* the HC halts an ED if an error occurs; put all pendings TDs of an halted ED on the
+ * done list; they are marked with an 0xf CC_error code
+ */
+
+ if(TD_CC_GET(td_list->hw.info) != TD_CC_NOERROR) { /* on error move all pending tds of an ed into the done list */
+ printk("******* USB BUS error %x @ep %x\n", TD_CC_GET(td_list->hw.info), td_list->ep->ep_addr.iep);
+ td_err= td_list;
+ td_hw = td_list->ep->hw.head_td & 0xfffffff0;
+ while(td_hw != 0) {
+ if(td_hw == td_list->ep->hw.tail_td) break;
+ td = bus_to_virt(td_hw);
+ td_err->next_dl_td = td;
+ td_err= td;


+ td_hw = td->hw.next_td;
+ }

+ td_list->ep->hw.head_td = td_list->ep->hw.tail_td;
+ td->next_dl_td = td_list_next;
+ td_list_next = td_list->next_dl_td;
+
+ }
+ /* send the reply */
+ if(td_list->handler != NULL) {
+ if(td_list->prev_td == NULL) {
+ td_list->handler((void *) ohci,
+ td_list->ep->ep_addr.iep,
+ 0,
+ NULL,
+ td_list->buffer_start,
+ td_list->hw.buf_end-virt_to_bus(td_list->buffer_start)+1,
+ TD_CC_GET(td_list->hw.info),
+ td_list->lw0,
+ td_list->lw1);
+ OHCI_FREE(td_list);
+ }
+ else {
+ if(td_list->prev_td->prev_td == NULL) { /* cntrl 2 Transactions dataless */
+ td_list->handler((void *) ohci,
+ td_list->ep->ep_addr.iep,
+ td_list->prev_td->hw.buf_end-virt_to_bus(td_list->prev_td->buffer_start)+1,
+ td_list->prev_td->buffer_start,
+ NULL,
+ 0,
+ (TD_CC_GET(td_list->prev_td->hw.info) > 0) ? TD_CC_GET(td_list->prev_td->hw.info) : TD_CC_GET(td_list->hw.info),
+ td_list->lw0,
+ td_list->lw1);
+ OHCI_FREE(td_list->prev_td);
+ OHCI_FREE(td_list);
+ }
+ else { /* cntrl 3 Transactions */
+ td_list->handler((void *) ohci,
+ td_list->ep->ep_addr.iep,
+ td_list->prev_td->prev_td->hw.buf_end-virt_to_bus(td_list->prev_td->prev_td->buffer_start)+1,
+ td_list->prev_td->prev_td->buffer_start,
+ td_list->prev_td->buffer_start,
+ td_list->prev_td->hw.buf_end-virt_to_bus(td_list->prev_td->buffer_start)+1,
+ (TD_CC_GET(td_list->prev_td->prev_td->hw.info) > 0) ? TD_CC_GET(td_list->prev_td->prev_td->hw.info)
+ : (TD_CC_GET(td_list->prev_td->hw.info) > 0) ? TD_CC_GET(td_list->prev_td->hw.info) : TD_CC_GET(td_list->hw.info),
+ td_list->lw0,
+ td_list->lw1);
+ OHCI_FREE(td_list->prev_td->prev_td);
+ OHCI_FREE(td_list->prev_td);
+ OHCI_FREE(td_list);


+
+ }
+ }
+
+ }

+ td_list = td_list_next;


+ }
+ return 0;
+}
+

+
+
+/******
+ *** HC functions


+ ************************************/
+
+
+

+void reset_hc(struct ohci *ohci) {
+ int retries = 5;
+ int timeout = 30;
+ int fminterval;
+
+ if(readl(&ohci->regs->control) & 0x100) { /* SMM owns the HC */
+ writel(0x08, &ohci->regs->cmdstatus); /* request ownership */
+ printk("USB HC TakeOver from SMM\n");
+ do {
+ wait_ms(100);
+ if(--retries) {
+ printk("USB HC TakeOver timed out!\n");
+ break;
+ }
+ }
+ while(readl(&ohci->regs->control) & 0x100);
+ }
+
+ writel((1<<31), &ohci->regs->intrdisable); /* Disable HC interrupts */
+ OHCI_DEBUG(printk("USB HC reset_hc: %x ; retries: %d\n", readl(&ohci->regs->control), 5-retries);)
+ fminterval = readl(&ohci->regs->fminterval) & 0x3fff;
+ writel(1, &ohci->regs->cmdstatus); /* HC Reset */
+ while ((readl(&ohci->regs->cmdstatus) & 0x01) != 0) { /* 10us Reset */
+ if (--timeout == 0) {
+ printk("USB HC reset timed out!\n");
+ return;
+ }
+ udelay(1);
+ }
+ /* set the timing */
+ fminterval |= (((fminterval -210) * 6)/7)<<16;
+ writel(fminterval, &ohci->regs->fminterval);
+ writel(((fminterval&0x3fff)*9)/10, &ohci->regs->periodicstart);
+}
+
+
+/*
+ * Reset and start an OHCI controller
+ */
+void start_hc(struct ohci *ohci)
+{
+ /* int fminterval; */
+ unsigned int mask;
+ /* fminterval = readl(&ohci->regs->fminterval) & 0x3fff;
+ reset_hc(ohci); */
+
+
+ writel(virt_to_bus(&ohci->hc_area->hcca), &ohci->regs->hcca); /* a reset clears this */
+
+ /* Choose the interrupts we care about now, others later on demand */
+ mask = OHCI_INTR_MIE | OHCI_INTR_WDH;
+ /* | OHCI_INTR_SO | OHCI_INTR_UE |OHCI_INTR_RHSC |OHCI_INTR_SF|
+ OHCI_INTR_FNO */
+
+
+
+ writel((0x00), &ohci->regs->control); /* USB Reset BUS */
+ wait_ms(10);
+
+ writel((0x97), &ohci->regs->control); /* USB Operational */
+
+ writel( 0x10000, &ohci->regs->roothub.status); /* root hub power on */
+ wait_ms(50);
+
+ OHCI_DEBUG(printk("USB HC rstart_hc_operational: %x\n", readl(&ohci->regs->control)); )
+ OHCI_DEBUG(printk("USB HC roothubstata: %x \n", readl( &(ohci->regs->roothub.a) )); )
+ OHCI_DEBUG(printk("USB HC roothubstatb: %x \n", readl( &(ohci->regs->roothub.b) )); )
+ OHCI_DEBUG(printk("USB HC roothubstatu: %x \n", readl( &(ohci->regs->roothub.status) )); )
+ OHCI_DEBUG(printk("USB HC roothubstat1: %x \n", readl( &(ohci->regs->roothub.portstatus[0]) )); )
+ OHCI_DEBUG(printk("USB HC roothubstat2: %x \n", readl( &(ohci->regs->roothub.portstatus[1]) )); )
+
+ /* control_wakeup = NULL; */
+ writel(mask, &ohci->regs->intrenable);
+ writel(mask, &ohci->regs->intrstatus);
+
+#ifdef VROOTHUB
+ {
+
+ struct usb_device * usb_dev;


+ struct ohci_device *dev;
+

+ usb_dev = sohci_usb_allocate(ohci->root_hub->usb);
+ dev = usb_dev->hcpriv;
+
+ dev->ohci = ohci;
+
+ usb_connect(usb_dev);
+
+ ohci->root_hub->usb->children[0] = usb_dev;
+
+ usb_new_device(usb_dev);
+ }
+#endif


+
+
+
+}
+
+
+

+
+static void ohci_interrupt(int irq, void *__ohci, struct pt_regs *r)
+{
+ struct ohci *ohci = __ohci;
+ struct ohci_regs *regs = ohci->regs;
+
+ int ints;
+
+
+ if((ohci->hc_area->hcca.done_head != 0) && !(ohci->hc_area->hcca.done_head & 0x01)) {
+ ints = OHCI_INTR_WDH;
+ }
+ else {
+ if((ints = (readl(&regs->intrstatus) & readl(&regs->intrenable))) == 0)
+ return;
+ }
+
+ ohci->intrstatus |= ints;
+ OHCI_DEBUG(printk("USB HC interrupt: %x (%x) \n", ints, readl(&ohci->regs->intrstatus));)
+
+ /* ints &= ~(OHCI_INTR_WDH); WH Bit will be set by done list subroutine */
+ /* if(ints & OHCI_INTR_FNO) {
+ writel(OHCI_INTR_FNO, &regs->intrstatus);
+ if (waitqueue_active(&ohci_tasks)) wake_up(&ohci_tasks);
+ } */
+
+ if(ints & OHCI_INTR_WDH) {
+ writel(OHCI_INTR_WDH, &regs->intrdisable);
+ ohci->intrstatus &= (~OHCI_INTR_WDH);
+ usb_ohci_done_list(ohci); /* prepare out channel list */
+ writel(OHCI_INTR_WDH, &ohci->regs->intrstatus);
+ writel(OHCI_INTR_WDH, &ohci->regs->intrenable);
+
+ }
+
+ if(ints & OHCI_INTR_SF) {
+ writel(OHCI_INTR_SF, &regs->intrdisable);
+ writel(OHCI_INTR_SF, &ohci->regs->intrstatus);
+ ohci->intrstatus &= (~OHCI_INTR_SF);
+ if(ohci->ed_rm_list != NULL) {
+ ohci_rm_eds(ohci);
+ }
+ }
+#ifndef VROOTHUB
+ if(ints & OHCI_INTR_RHSC) {
+ writel(OHCI_INTR_RHSC, &regs->intrdisable);
+ writel(OHCI_INTR_RHSC, &ohci->regs->intrstatus);
+ wake_up(&root_hub);
+
+ }
+ #endif
+
+ writel(OHCI_INTR_MIE, &regs->intrenable);
+
+}
+
+#ifndef VROOTHUB
+/*
+ * This gets called if the connect status on the root
+ * hub (and the root hub only) changes.
+ */
+static void ohci_connect_change(struct ohci *ohci, unsigned int port_nr)


+{
+ struct usb_device *usb_dev;
+ struct ohci_device *dev;

+ OHCI_DEBUG(printk("uhci_connect_change: called for %d stat %x\n", port_nr,readl(&ohci->regs->roothub.portstatus[port_nr]) );)
+
+ /*
+ * Even if the status says we're connected,
+ * the fact that the status bits changed may
+ * that we got disconnected and then reconnected.
+ *
+ * So start off by getting rid of any old devices..
+ */
+ usb_disconnect(&ohci->root_hub->usb->children[port_nr]);
+
+ if(!(readl(&ohci->regs->roothub.portstatus[port_nr]) & RH_PS_CCS)) {
+ writel(RH_PS_CCS, &ohci->regs->roothub.portstatus[port_nr]);
+ return; /* nothing connected */
+ }
+ /*
+ * Ok, we got a new connection. Allocate a device to it,
+ * and find out what it wants to do..
+ */
+ usb_dev = sohci_usb_allocate(ohci->root_hub->usb);
+ dev = usb_dev->hcpriv;
+ dev->ohci = ohci;
+ usb_connect(dev->usb);
+ ohci->root_hub->usb->children[port_nr] = usb_dev;
+ wait_ms(200); /* wait for powerup */
+ /* reset port/device */
+ writel(RH_PS_PRS, &ohci->regs->roothub.portstatus[port_nr]); /* reset port */
+ while(!(readl( &ohci->regs->roothub.portstatus[port_nr]) & RH_PS_PRSC)) wait_ms(10); /* reset active ? */
+ writel(RH_PS_PES, &ohci->regs->roothub.portstatus[port_nr]); /* enable port */
+ wait_ms(10);
+ /* Get speed information */
+ usb_dev->slow = (readl( &ohci->regs->roothub.portstatus[port_nr]) & RH_PS_LSDA) ? 1 : 0;
+
+ /*
+ * Ok, all the stuff specific to the root hub has been done.
+ * The rest is generic for any new USB attach, regardless of
+ * hub type.
+ */
+ usb_new_device(usb_dev);
+}
+#endif
+
+
+
+/*
+ * Allocate the resources required for running an OHCI controller.
+ * Host controller interrupts must not be running while calling this
+ * function.
+ *
+ * The mem_base parameter must be the usable -virtual- address of the
+ * host controller's memory mapped I/O registers.
+ *
+ * This is where OHCI triumphs over UHCI, because good is dumb.
+ * Note how much simpler this function is than in uhci.c.
+ *
+ * OHCI hardware takes care of most of the scheduling of different
+ * transfer types with the correct prioritization for us.
+ */
+
+
+static struct ohci *alloc_ohci(void* mem_base)
+{
+ int i,j;
+ struct ohci *ohci;
+ struct ohci_hc_area *hc_area;
+ struct usb_bus *bus;
+ struct ohci_device *dev;
+ struct usb_device *usb;
+
+ /*
+ * Here we allocate some dummy EDs as well as the
+ * OHCI host controller communications area. The HCCA is just
+ * a nice pool of memory with pointers to endpoint descriptors
+ * for the different interrupts.
+ *
+ * The first page of memory contains the HCCA and ohci structure
+ */
+ hc_area = (struct ohci_hc_area *) __get_free_pages(GFP_KERNEL, 1);
+ if (!hc_area)
+ return NULL;
+ memset(hc_area, 0, sizeof(*hc_area));
+ ohci = &hc_area->ohci;
+ ohci->irq = -1;
+ ohci->regs = mem_base;
+
+ ohci->hc_area = hc_area;
+ /* Tell the controller where the HCCA is */
+ writel(virt_to_bus(&hc_area->hcca), &ohci->regs->hcca);
+
+
+ /*
+ * Initialize the ED polling "tree", full tree;
+ * dummy eds ed[i] (hc should skip them)
+ * i == 0 is the end of the iso list;
+ * 1 is the 1ms node,
+ * 2,3 2ms nodes,
+ * 4,5,6,7 4ms nodes,
+ * 8 ... 15 8ms nodes,
+ * 16 ... 31 16ms nodes,
+ * 32 ... 63 32ms nodes
+ * Sequenzes:
+ * 32-16- 8-4-2-1-0
+ * 33-17- 9-5-3-1-0
+ * 34-18-10-6-2-1-0
+ * 35-19-11-7-3-1-0
+ * 36-20-12-4-2-1-0
+ * 37-21-13-5-3-1-0
+ * 38-22-14-6-2-1-0
+ * 39-23-15-7-3-1-0
+ * 40-24- 8-4-2-1-0
+ * 41-25- 9-5-3-1-0
+ * 42-26-10-6-2-1-0
+ * : :
+ * 63-31-15-7-3-1-0
+ */
+ hc_area->ed[ED_ISO].info |= OHCI_ED_SKIP; /* place holder, so skip it */
+ hc_area->ed[ED_ISO].next_ed = 0x0000; /* end of iso list */
+
+ hc_area->ed[1].next_ed = virt_to_bus(&(hc_area->ed[ED_ISO]));
+ hc_area->ed[1].info |= OHCI_ED_SKIP; /* place holder, skip it */
+
+ j=1;
+ for (i = 2; i < (NUM_INTS * 2); i++) {
+ if (i >= NUM_INTS)
+ hc_area->hcca.int_table[i - NUM_INTS] = virt_to_bus(&(hc_area->ed[i]));
+
+ if( i == j*4) j *= 2;
+ hc_area->ed[i].next_ed = virt_to_bus(&(hc_area->ed[j+ i%j]));
+ hc_area->ed[i].info |= OHCI_ED_SKIP; /* place holder, skip it */
+ }
+
+
+ /*
+ * for load ballancing of the interrupt branches
+ */
+ for (i = 0; i < NUM_INTS; i++) ohci->ohci_int_load[i] = 0;
+
+ /*
+ * Store the end of control and bulk list eds. So, we know where we can add
+ * elements to these lists.
+ */
+ ohci->ed_isotail = (struct usb_ohci_ed *) &(hc_area->ed[ED_ISO]);
+ ohci->ed_controltail = NULL;
+ ohci->ed_bulktail = NULL;
+
+ /*
+ * Tell the controller where the control and bulk lists are
+ * The lists are empty now.
+ */
+ writel(0, &ohci->regs->ed_controlhead);
+ writel(0, &ohci->regs->ed_bulkhead);
+
+
+ USB_ALLOC(bus, sizeof(*bus));
+ if (!bus)
+ return NULL;
+
+ memset(bus, 0, sizeof(*bus));
+
+ ohci->bus = bus;
+ bus->hcpriv = (void *) ohci;
+ bus->op = &sohci_device_operations;
+
+
+ usb = sohci_usb_allocate(NULL);
+ if (!usb)
+ return NULL;
+
+ dev = ohci->root_hub = usb_to_ohci(usb);
+
+ usb->bus = bus;
+ /* bus->root_hub = ohci_to_usb(ohci->root_hub); */
+ dev->ohci = ohci;
+
+ /* Initialize the root hub */
+
+ usb->maxchild = readl(&ohci->regs->roothub.a) & 0xff;
+ usb_init_root_hub(usb);
+
+ return ohci;
+}
+
+
+/*
+ * De-allocate all resources..
+ */
+
+static void release_ohci(struct ohci *ohci)
+{
+ int i;
+ union ep_addr_ ep_addr;


+ ep_addr.iep = 0;
+

+ OHCI_DEBUG(printk("USB HC release ohci \n");)
+
+ if (ohci->irq >= 0) {
+ free_irq(ohci->irq, ohci);
+ ohci->irq = -1;
+ }
+
+ /* stop hc */
+ writel(OHCI_USB_SUSPEND, &ohci->regs->control);
+
+ /* deallocate all EDs and TDs */
+ for(i=0; i < 128; i ++) {
+ ep_addr.bep.fa = i;
+ usb_ohci_rm_function(ohci, ep_addr.iep);
+ }
+ ohci_rm_eds(ohci); /* remove eds */
+
+ /* disconnect all devices */
+ if(ohci->root_hub)
+ for(i = 0; i < ohci->root_hub->usb->maxchild; i++)
+ usb_disconnect(ohci->root_hub->usb->children + i);
+
+ USB_FREE(ohci->root_hub->usb);
+ USB_FREE(ohci->root_hub);
+ USB_FREE(ohci->bus);
+
+ /* unmap the IO address space */
+ iounmap(ohci->regs);
+
+
+ free_pages((unsigned int) ohci->hc_area, 1);
+
+}
+
+
+void cleanup_drivers(void);
+
+static int ohci_roothub_thread(void * __ohci)
+{
+ struct ohci *ohci = (struct ohci *)__ohci;
+ lock_kernel();
+
+ /*
+ * This thread doesn't need any user-level access,
+ * so get rid of all our resources..
+ */
+ printk("ohci_roothub_thread at %p\n", &ohci_roothub_thread);
+ exit_mm(current);
+ exit_files(current);
+ exit_fs(current);
+
+
+ strcpy(current->comm, "root-hub");
+
+
+ start_hc(ohci);
+ writel( 0x10000, &ohci->regs->roothub.status);
+ wait_ms(50); /* root hub power on */
+ do {
+#ifdef CONFIG_APM
+ if (apm_resume) {
+ apm_resume = 0;
+ start_hc(ohci);
+ continue;
+ }
+#endif
+
+ OHCI_DEBUG(printk("USB RH tasks: int: %x\n", ohci->intrstatus); )
+#ifndef VROOTHUB
+ /* if (ohci->intrstatus & OHCI_INTR_RHSC) */
+ {
+ int port_nr;
+ for(port_nr=0; port_nr< ohci->root_hub->usb->maxchild; port_nr++)
+ if(readl(&ohci->regs->roothub.portstatus[port_nr]) & (RH_PS_CSC | RH_PS_PRSC)) {
+ ohci_connect_change(ohci, port_nr);
+ writel(0xffff0000, &ohci->regs->roothub.portstatus[port_nr]);
+ }
+ ohci->intrstatus &= ~(OHCI_INTR_RHSC);
+ writel(OHCI_INTR_RHSC, &ohci->regs->intrenable);
+ }
+#endif
+
+ interruptible_sleep_on(&root_hub);
+
+ } while (!signal_pending(current));
+
+#ifdef VROOTHUB
+ ohci_del_rh_int_timer(ohci);
+#endif
+
+
+ cleanup_drivers();
+ /* reset_hc(ohci); */
+
+ release_ohci(ohci);
+ MOD_DEC_USE_COUNT;
+
+ printk("ohci_control_thread exiting\n");


+
+ return 0;
+}
+

+
+
+
+/*
+ * Increment the module usage count, start the control thread and
+ * return success.
+ */
+static int found_ohci(int irq, void* mem_base)
+{
+ int retval;
+ struct ohci *ohci;
+ OHCI_DEBUG(printk("USB HC found ohci: irq= %d membase= %x \n", irq, (int)mem_base);)
+ /* Allocate the running OHCI structures */
+ ohci = alloc_ohci(mem_base);
+ if (!ohci) {


+ return -ENOMEM;
+ }
+

+ reset_hc(ohci);
+
+ retval = -EBUSY;
+ if (request_irq(irq, ohci_interrupt, SA_SHIRQ, "ohci-usb", ohci) == 0) {
+ int pid;
+
+ MOD_INC_USE_COUNT;
+ ohci->irq = irq;
+
+ pid = kernel_thread(ohci_roothub_thread, ohci, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);


+ if (pid >= 0)

+ return 0;
+
+

+ MOD_DEC_USE_COUNT;
+ retval = pid;
+ }
+
+ release_ohci(ohci);


+ return retval;
+}
+

+static int start_ohci(struct pci_dev *dev)
+{
+ unsigned int mem_base = dev->base_address[0];
+
+ /* If its OHCI, its memory */
+ if (mem_base & PCI_BASE_ADDRESS_SPACE_IO)
+ return -ENODEV;
+
+ /* Get the memory address and map it for IO */
+ mem_base &= PCI_BASE_ADDRESS_MEM_MASK;
+
+ /*
+ * FIXME ioremap_nocache isn't implemented on all CPUs (such
+ * as the Alpha) [?] What should I use instead...
+ *
+ * The iounmap() is done on in release_ohci.
+ */
+ mem_base = (unsigned int) ioremap_nocache(mem_base, 4096);
+
+ if (!mem_base) {
+ printk("Error mapping OHCI memory\n");


+ return -EFAULT;
+ }
+

+ return found_ohci(dev->irq, (void *) mem_base);
+}

+
+
+
+#ifdef CONFIG_APM

+static int handle_apm_event(apm_event_t event)
+{
+ static int down = 0;
+
+ switch (event) {
+ case APM_SYS_SUSPEND:
+ case APM_USER_SUSPEND:
+ if (down) {
+ printk(KERN_DEBUG "ohci: received extra suspend event\n");
+ break;
+ }
+ down = 1;
+ break;
+ case APM_NORMAL_RESUME:
+ case APM_CRITICAL_RESUME:
+ if (!down) {
+ printk(KERN_DEBUG "ohci: received bogus resume event\n");
+ break;
+ }
+ down = 0;
+ if (waitqueue_active(&root_hub)) {
+ apm_resume = 1;
+ wake_up(&root_hub);
+ }
+ break;
+ }


+ return 0;
+}
+#endif
+

+
+ int usb_mouse_init(void);

+#ifdef MODULE
+
+void cleanup_module(void)
+{

+#ifdef CONFIG_APM
+ apm_unregister_callback(&handle_apm_event);
+#endif
+}
+
+#define ohci_hcd_init init_module
+
+#endif
+
+#define PCI_CLASS_SERIAL_USB_OHCI 0x0C0310
+#define PCI_CLASS_SERIAL_USB_OHCI_PG 0x10
+
+
+int ohci_hcd_init(void)
+{
+ int retval;
+ struct pci_dev *dev = NULL;
+
+ retval = -ENODEV;
+
+ dev = NULL;
+ while((dev = pci_find_class(PCI_CLASS_SERIAL_USB_OHCI, dev))) { /* OHCI */
+ retval = start_ohci(dev);
+ if (retval < 0) break;
+
+
+#ifdef CONFIG_USB_MOUSE
+ usb_mouse_init();
+#endif
+#ifdef CONFIG_USB_KBD
+ usb_kbd_init();
+#endif
+ hub_init();
+#ifdef CONFIG_USB_AUDIO
+ usb_audio_init();
+#endif
+#ifdef CONFIG_APM
+ apm_register_callback(&handle_apm_event);
+#endif


+
+ return 0;
+ }

+ return retval;
+}
+
+void cleanup_drivers(void)
+{
+ hub_cleanup();
+#ifdef CONFIG_USB_MOUSE
+ usb_mouse_cleanup();
+#endif
+}
+
diff -u --recursive --new-file v2.2.7/linux/drivers/usb/ohci-hcd.h linux/drivers/usb/ohci-hcd.h
--- v2.2.7/linux/drivers/usb/ohci-hcd.h Wed Dec 31 16:00:00 1969
+++ linux/drivers/usb/ohci-hcd.h Tue May 11 09:55:45 1999
@@ -0,0 +1,404 @@
+ /*


+ * OHCI HCD (Host Controller Driver) for USB.
+ *
+ * (C) Copyright 1999 Roman Weissgaerber <wei...@vienna.at>
+ *
+ * The OHCI HCD layer is a simple but nearly complete implementation of what the
+ * USB people would call a HCD for the OHCI.
+ * (ISO comming soon, Bulk disabled, INT u. CTRL transfers enabled)
+ * The layer on top of it, is for interfacing to the alternate-usb device-drivers.
+ *
+ * [ This is based on Linus' UHCI code and gregs OHCI fragments (0.03c source tree). ]
+ * [ Open Host Controller Interface driver for USB. ]
+ * [ (C) Copyright 1999 Linus Torvalds (uhci.c) ]
+ * [ (C) Copyright 1999 Gregory P. Smith <gr...@electricrain.com> ]
+ * [ $Log: ohci.c,v $ ]
+ * [ Revision 1.1 1999/04/05 08:32:30 greg ]
+ *
+ *
+ * v2.1 1999/05/09 ep_addr correction, code clean up
+ * v2.0 1999/05/04

+ * v1.0 1999/04/27
+ * ohci-hcd.h


+ */
+
+#include <linux/config.h>
+

+#ifdef CONFIG_USB_OHCI_VROOTHUB
+#define VROOTHUB
+#endif
+/* enables virtual root hub
+ * (root hub will be managed by the hub controller
+ * hub.c of the alternate usb driver)
+ * last time I did more testing without virtual root hub
+ * -> the virtual root hub could be more unstable now */
+
+
+
+#ifdef OHCI_DBG
+#define OHCI_DEBUG(X) X
+#else
+#define OHCI_DEBUG(X)
+#endif
+
+/* for readl writel functions */
+#include <linux/list.h>
+#include <asm/io.h>
+
+/* for ED and TD structures */
+
+typedef void * __OHCI_BAG;
+typedef int (*f_handler )(void * ohci, unsigned int ep_addr, int cmd_len, void *cmd, void *data, int data_len, int status, __OHCI_BAG lw0, __OHCI_BAG lw1);
+
+
+
+struct ep_address {
+ __u8 ep; /* bit 7: IN/-OUT, 6,5: type 10..CTRL 00..ISO 11..BULK 10..INT, 3..0: ep nr */
+ __u8 fa; /* function address */
+ __u8 hc;
+ __u8 host;
+};
+
+union ep_addr_ {
+ unsigned int iep;
+ struct ep_address bep;
+};
+
+/*
+ * ED and TD descriptors has to be 16-byte aligned
+ */
+struct ohci_hw_ed {
+ __u32 info;
+ __u32 tail_td; /* TD Queue tail pointer */
+ __u32 head_td; /* TD Queue head pointer */
+ __u32 next_ed; /* Next ED */
+} __attribute((aligned(16)));
+
+
+struct usb_ohci_ed {
+ struct ohci_hw_ed hw;
+ /* struct ohci * ohci; */
+ f_handler handler;
+ union ep_addr_ ep_addr;
+ struct usb_ohci_ed *ed_list;
+ struct usb_ohci_ed *ed_prev;
+} __attribute((aligned(32)));
+
+ /* OHCI Hardware fields */
+struct ohci_hw_td {
+ __u32 info;
+ __u32 cur_buf; /* Current Buffer Pointer */
+ __u32 next_td; /* Next TD Pointer */
+ __u32 buf_end; /* Memory Buffer End Pointer */
+} __attribute((aligned(16)));
+
+/* TD info field */
+#define TD_CC 0xf0000000
+#define TD_CC_GET(td_p) ((td_p >>28) & 0x04)
+#define TD_EC 0x0C000000
+#define TD_T 0x03000000
+#define TD_T_DATA0 0x02000000
+#define TD_T_DATA1 0x03000000
+#define TD_T_TOGGLE 0x00000000
+#define TD_R 0x00040000
+#define TD_DI 0x00E00000
+#define TD_DI_SET(X) (((X) & 0x07)<< 21)
+#define TD_DP 0x00180000
+#define TD_DP_SETUP 0x00000000
+#define TD_DP_IN 0x00100000
+#define TD_DP_OUT 0x00080000
+
+/* CC Codes */
+#define TD_CC_NOERROR 0x00
+#define TD_CC_CRC 0x01
+#define TD_CC_BITSTUFFING 0x02
+#define TD_CC_DATATOGGLEM 0x03
+#define TD_CC_STALL 0x04
+#define TD_DEVNOTRESP 0x05
+#define TD_PIDCHECKFAIL 0x06
+#define TD_UNEXPECTEDPID 0x07
+#define TD_DATAOVERRUN 0x08
+#define TD_DATAUNDERRUN 0x09
+#define TD_BUFFEROVERRUN 0x0C
+#define TD_BUFFERUNDERRUN 0x0D
+#define TD_NOTACCESSED 0x0F
+
+
+
+struct usb_ohci_td {
+ struct ohci_hw_td hw;
+ void * buffer_start;
+ f_handler handler;
+ struct usb_ohci_td *prev_td;
+ struct usb_ohci_ed *ep;
+ struct usb_ohci_td *next_dl_td;
+ __OHCI_BAG lw0;
+ __OHCI_BAG lw1;
+} __attribute((aligned(32)));
+
+
+
+/* TD types */
+#define BULK 0x03
+#define INT 0x01
+#define CTRL 0x02
+#define ISO 0x00
+/* TD types with direction */
+#define BULK_IN 0x07
+#define BULK_OUT 0x03
+#define INT_IN 0x05
+#define INT_OUT 0x01
+#define CTRL_IN 0x06
+#define CTRL_OUT 0x02
+#define ISO_IN 0x04
+#define ISO_OUT 0x00
+
+struct ohci_rep_td {
+ int cmd_len;
+ void * cmd;
+ void * data;
+ int data_len;
+ f_handler handler;
+ struct ohci_rep_td *next_td;
+ int ep_addr;
+ __OHCI_BAG lw0;
+ __OHCI_BAG lw1;
+ __u32 status;
+} __attribute((aligned(32)));
+
+#define OHCI_ED_SKIP (1 << 14)
+#define OHCI_ED_MPS (0x7ff << 16)
+#define OHCI_ED_F_NORM (0)
+#define OHCI_ED_F_ISOC (1 << 15)
+#define OHCI_ED_S_LOW (1 << 13)
+#define OHCI_ED_S_HIGH (0)
+#define OHCI_ED_D (3 << 11)
+#define OHCI_ED_D_IN (2 << 11)
+#define OHCI_ED_D_OUT (1 << 11)
+#define OHCI_ED_EN (0xf << 7)
+#define OHCI_ED_FA (0x7f)
+
+
+/*
+ * The HCCA (Host Controller Communications Area) is a 256 byte
+ * structure defined in the OHCI spec. that the host controller is
+ * told the base address of. It must be 256-byte aligned.
+ */
+#define NUM_INTS 32 /* part of the OHCI standard */
+struct ohci_hcca {
+ __u32 int_table[NUM_INTS]; /* Interrupt ED table */
+ __u16 frame_no; /* current frame number */
+ __u16 pad1; /* set to 0 on each frame_no change */
+ __u32 done_head; /* info returned for an interrupt */
+ u8 reserved_for_hc[116];
+} __attribute((aligned(256)));
+
+
+
+#define ED_INT_1 1
+#define ED_INT_2 2
+#define ED_INT_4 4
+#define ED_INT_8 8
+#define ED_INT_16 16
+#define ED_INT_32 32
+#define ED_CONTROL 64
+#define ED_BULK 65
+#define ED_ISO 0 /* same as 1ms interrupt queue */
+
+
+/*
+ * This is the maximum number of root hub ports. I don't think we'll
+ * ever see more than two as that's the space available on an ATX
+ * motherboard's case, but it could happen. The OHCI spec allows for
+ * up to 15... (which is insane!)
+ *
+ * Although I suppose several "ports" could be connected directly to
+ * internal laptop devices such as a keyboard, mouse, camera and
+ * serial/parallel ports. hmm... That'd be neat.
+ */
+#define MAX_ROOT_PORTS 15 /* maximum OHCI root hub ports */
+
+/*
+ * This is the structure of the OHCI controller's memory mapped I/O
+ * region. This is Memory Mapped I/O. You must use the readl() and
+ * writel() macros defined in asm/io.h to access these!!
+ */
+struct ohci_regs {
+ /* control and status registers */
+ __u32 revision;
+ __u32 control;
+ __u32 cmdstatus;
+ __u32 intrstatus;
+ __u32 intrenable;
+ __u32 intrdisable;
+ /* memory pointers */
+ __u32 hcca;
+ __u32 ed_periodcurrent;
+ __u32 ed_controlhead;
+ __u32 ed_controlcurrent;
+ __u32 ed_bulkhead;
+ __u32 ed_bulkcurrent;
+ __u32 donehead;
+ /* frame counters */
+ __u32 fminterval;
+ __u32 fmremaining;
+ __u32 fmnumber;
+ __u32 periodicstart;
+ __u32 lsthresh;
+ /* Root hub ports */
+ struct ohci_roothub_regs {
+ __u32 a;
+ __u32 b;
+ __u32 status;
+ __u32 portstatus[MAX_ROOT_PORTS];
+ } roothub;
+} __attribute((aligned(32)));
+
+
+/*
+ * Read a MMIO register and re-write it after ANDing with (m)
+ */
+#define writel_mask(m, a) writel( (readl((__u32)(a))) & (__u32)(m), (__u32)(a) )
+
+/*
+ * Read a MMIO register and re-write it after ORing with (b)
+ */
+#define writel_set(b, a) writel( (readl((__u32)(a))) | (__u32)(b), (__u32)(a) )
+
+/*
+ * cmdstatus register */
+#define OHCI_CLF 0x02
+#define OHCI_BLF 0x04
+
+/*
+ * Interrupt register masks
+ */
+#define OHCI_INTR_SO (1)
+#define OHCI_INTR_WDH (1 << 1)
+#define OHCI_INTR_SF (1 << 2)
+#define OHCI_INTR_RD (1 << 3)
+#define OHCI_INTR_UE (1 << 4)
+#define OHCI_INTR_FNO (1 << 5)
+#define OHCI_INTR_RHSC (1 << 6)
+#define OHCI_INTR_OC (1 << 30)
+#define OHCI_INTR_MIE (1 << 31)
+
+/*
+ * Control register masks
+ */
+#define OHCI_USB_OPER (2 << 6)
+#define OHCI_USB_SUSPEND (3 << 6)
+
+/*
+ * This is the full ohci controller description
+ *
+ * Note how the "proper" USB information is just
+ * a subset of what the full implementation needs. (Linus)
+ */
+
+
+struct ohci {
+ int irq;
+ struct ohci_regs *regs; /* OHCI controller's memory */
+ struct ohci_hc_area *hc_area; /* hcca, int ed-tree, ohci itself .. */
+ int root_hub_funct_addr; /* Address of Root Hub endpoint */
+ int ohci_int_load[32]; /* load of the 32 Interrupt Chains (for load ballancing)*/
+ struct usb_ohci_ed * ed_rm_list; /* list of all endpoints to be removed */
+ struct usb_ohci_ed * ed_bulktail; /* last endpoint of bulk list */
+ struct usb_ohci_ed * ed_controltail; /* last endpoint of control list */
+ struct usb_ohci_ed * ed_isotail; /* last endpoint of iso list */
+ struct ohci_device * root_hub;
+ struct usb_ohci_ed ed_rh_ep0;
+ struct usb_ohci_ed ed_rh_epi;
+ struct ohci_rep_td *td_rh_epi;
+ int intrstatus;
+ struct usb_ohci_ed *ed_func_ep0[128]; /* "hash"-table for ep to ed mapping */
+ struct ohci_rep_td *repl_queue; /* for internal requests */
+ int rh_int_interval;
+ int rh_int_timer;
+ struct usb_bus *bus;
+
+
+};
+
+/*
+ * Warning: This constant must not be so large as to cause the
+ * ohci_device structure to exceed one 4096 byte page. Or "weird
+ * things will happen" as the alloc_ohci() function assumes that
+ * its less than one page at the moment. (FIXME)
+ */
+#define NUM_TDS 4 /* num of preallocated transfer descriptors */
+#define NUM_EDS 80 /* num of preallocated endpoint descriptors */
+
+struct ohci_hc_area {
+
+ struct ohci_hcca hcca; /* OHCI mem. mapped IO area 256 Bytes*/
+
+ struct ohci_hw_ed ed[NUM_EDS]; /* Endpoint Descriptors 80 * 16 : 1280 Bytes */
+ struct ohci_hw_td td[NUM_TDS]; /* Transfer Descriptors 2 * 32 : 64 Bytes */
+ struct ohci ohci;
+
+};
+struct ohci_device {
+ struct usb_device *usb;
+ struct ohci *ohci;
+ unsigned long data[16];
+};
+
+#define ohci_to_usb(uhci) ((ohci)->usb)
+#define usb_to_ohci(usb) ((struct ohci_device *)(usb)->hcpriv)
+
+/* Debugging code */
+/*void show_ed(struct ohci_ed *ed);
+void show_td(struct ohci_td *td);
+void show_status(struct ohci *ohci); */
+
+/* hcd */
+int ohci_trans_req(struct ohci * ohci, unsigned int ep_addr, int cmd_len, void *cmd, void * data, int data_len, __OHCI_BAG lw0, __OHCI_BAG lw1);
+struct usb_ohci_ed *usb_ohci_add_ep(struct ohci * ohci, unsigned int ep_addr, int interval, int load, f_handler handler, int ep_size, int speed);
+int usb_ohci_rm_function(struct ohci * ohci, unsigned int ep_addr);
+int usb_ohci_rm_ep(struct ohci * ohci, struct usb_ohci_ed *ed);


+struct usb_ohci_ed * ohci_find_ep(struct ohci *ohci, unsigned int ep_addr_in);
+

+/* roothub */
+int ohci_del_rh_int_timer(struct ohci * ohci);
+int ohci_init_rh_int_timer(struct ohci * ohci, int interval);
+int root_hub_int_req(struct ohci * ohci, int cmd_len, void * ctrl, void * data, int data_len, __OHCI_BAG lw0, __OHCI_BAG lw1, f_handler handler);
+int root_hub_send_irq(struct ohci * ohci, void * data, int data_len );
+int root_hub_control_msg(struct ohci *ohci, int cmd_len, void *rh_cmd, void *rh_data, int len, __OHCI_BAG lw0, __OHCI_BAG lw1, f_handler handler);
+int queue_reply(struct ohci * ohci, unsigned int ep_addr, int cmd_len,void * cmd, void * data,int len, __OHCI_BAG lw0, __OHCI_BAG lw1, f_handler handler);
+int send_replies(struct ohci * ohci);
+
+
+
+
+/* Root-Hub Register info */
+
+#define RH_PS_CCS 0x00000001
+#define RH_PS_PES 0x00000002
+#define RH_PS_PSS 0x00000004
+#define RH_PS_POCI 0x00000008
+#define RH_PS_PRS 0x00000010
+#define RH_PS_PPS 0x00000100
+#define RH_PS_LSDA 0x00000200
+#define RH_PS_CSC 0x00010000
+#define RH_PS_PESC 0x00020000
+#define RH_PS_PSSC 0x00040000
+#define RH_PS_OCIC 0x00080000
+#define RH_PS_PRSC 0x00100000
+
+
+#ifdef OHCI_DBG
+#define OHCI_FREE(x) kfree(x); printk("OHCI FREE: %d\n", -- __ohci_free_cnt)
+#define OHCI_ALLOC(x,size) (x) = kmalloc(size, GFP_KERNEL); printk("OHCI ALLO: %d\n", ++ __ohci_free_cnt)
+#define USB_FREE(x) kfree(x); printk("USB FREE: %d\n", -- __ohci_free1_cnt)
+#define USB_ALLOC(x,size) (x) = kmalloc(size, GFP_KERNEL); printk("USB ALLO: %d\n", ++ __ohci_free1_cnt)
+static int __ohci_free_cnt = 0;
+static int __ohci_free1_cnt = 0;
+#else
+#define OHCI_FREE(x) kfree(x)
+#define OHCI_ALLOC(x,size) (x) = kmalloc(size, GFP_KERNEL)
+#define USB_FREE(x) kfree(x)
+#define USB_ALLOC(x,size) (x) = kmalloc(size, GFP_KERNEL)
+#endif
+
diff -u --recursive --new-file v2.2.7/linux/drivers/usb/ohci-root-hub.c linux/drivers/usb/ohci-root-hub.c
--- v2.2.7/linux/drivers/usb/ohci-root-hub.c Wed Dec 31 16:00:00 1969
+++ linux/drivers/usb/ohci-root-hub.c Mon May 10 10:18:34 1999
@@ -0,0 +1,604 @@
+/*
+ * HCD (OHCI) Virtual Root Hub for USB.
+ *
+ * (C) Copyright 1999 Roman Weissgaerber (wei...@vienna.at)
+ *
+ * The Root Hub is build into the HC (UHCI or OHCI) hardware.
+ * This piece of code lets it look like it resides on the usb
+ * like the other hubs.
+ * (for anyone who wants to do a control operation on the root hub)
+ *
+ * v2.1 1999/05/09
+ * v2.0 1999/05/04
+ * v1.0 1999/04/27
+ * ohci-root-hub.c


+ *
+ */
+
+

+


+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/malloc.h>

+#include <linux/string.h>


+
+#include "usb.h"
+#include "ohci-hcd.h"
+

+#ifdef VROOTHUB
+
+#include "ohci-root-hub.h"
+
+
+static __u8 root_hub_dev_des[] =
+{
+ 0x12, /* __u8 bLength; */
+ 0x01, /* __u8 bDescriptorType; Device */
+ 0x00, /* __u16 bcdUSB; v1.0 */
+ 0x01,
+ 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */
+ 0x00, /* __u8 bDeviceSubClass; */
+ 0x00, /* __u8 bDeviceProtocol; */
+ 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */
+ 0x00, /* __u16 idVendor; */
+ 0x00,
+ 0x00, /* __u16 idProduct; */
+ 0x00,
+ 0x00, /* __u16 bcdDevice; */
+ 0x00,
+ 0x00, /* __u8 iManufacturer; */
+ 0x00, /* __u8 iProduct; */
+ 0x00, /* __u8 iSerialNumber; */
+ 0x01 /* __u8 bNumConfigurations; */
+};
+
+
+/* Configuration descriptor */
+static __u8 root_hub_config_des[] =
+{
+ 0x09, /* __u8 bLength; */
+ 0x02, /* __u8 bDescriptorType; Configuration */
+ 0x19, /* __u16 wTotalLength; */
+ 0x00,
+ 0x01, /* __u8 bNumInterfaces; */
+ 0x01, /* __u8 bConfigurationValue; */
+ 0x00, /* __u8 iConfiguration; */
+ 0x40, /* __u8 bmAttributes;
+ Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, 4..0: resvd */
+ 0x00, /* __u8 MaxPower; */
+
+ /* interface */
+ 0x09, /* __u8 if_bLength; */
+ 0x04, /* __u8 if_bDescriptorType; Interface */
+ 0x00, /* __u8 if_bInterfaceNumber; */
+ 0x00, /* __u8 if_bAlternateSetting; */
+ 0x01, /* __u8 if_bNumEndpoints; */
+ 0x09, /* __u8 if_bInterfaceClass; HUB_CLASSCODE */
+ 0x00, /* __u8 if_bInterfaceSubClass; */
+ 0x00, /* __u8 if_bInterfaceProtocol; */
+ 0x00, /* __u8 if_iInterface; */
+
+ /* endpoint */
+ 0x07, /* __u8 ep_bLength; */
+ 0x05, /* __u8 ep_bDescriptorType; Endpoint */
+ 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */
+ 0x03, /* __u8 ep_bmAttributes; Interrupt */
+ 0x40, /* __u16 ep_wMaxPacketSize; 64 Bytes */
+ 0x00,
+ 0xff /* __u8 ep_bInterval; 255 ms */
+};
+
+/*
+For OHCI we need just the 2nd Byte, so we
+don't need this constant byte-array
+
+static __u8 root_hub_hub_des[] =
+{
+ 0x00, * __u8 bLength; *
+ 0x29, * __u8 bDescriptorType; Hub-descriptor *
+ 0x02, * __u8 bNbrPorts; *
+ 0x00, * __u16 wHubCharacteristics; *
+ 0x00,
+ 0x01, * __u8 bPwrOn2pwrGood; 2ms *
+ 0x00, * __u8 bHubContrCurrent; 0 mA *
+ 0x00, * __u8 DeviceRemovable; *** 8 Ports max *** *
+ 0xff * __u8 PortPwrCtrlMask; *** 8 ports max *** *
+};
+*/
+
+
+int root_hub_control_msg(struct ohci *ohci, int cmd_len, void *rh_cmd, void *rh_data, int leni, __OHCI_BAG lw0, __OHCI_BAG lw1, f_handler handler)
+{
+
+ __u32 stat;
+ __u32 rep_handler;
+ int req_reply=0;
+ union ep_addr_ ep_addr;
+ union ep_addr_ ep_addr_ret;
+ __u8 * cmd = rh_cmd;
+ __u8 * data = rh_data;
+ int i;
+ int len =leni;
+
+ __u8 bmRequestType = cmd[0];
+ __u8 bRequest = cmd[1];
+ __u16 wValue = cmd[3] << 8 | cmd [2];
+ __u16 wIndex = cmd[5] << 8 | cmd [4];
+ __u16 wLength = cmd[7] << 8 | cmd [6];
+printk("USB root hub: adr: %8x cmd(%8x): ", ohci->root_hub_funct_addr, 8);
+for(i=0;i<8;i++)
+ printk("%2x", ((char *)rh_cmd)[i]);
+
+printk(" ; \n");
+
+ ep_addr_ret.iep = 0;
+ ep_addr_ret.bep.fa = ohci->root_hub_funct_addr;
+ ep_addr_ret.bep.ep = (bmRequestType & 0x80) | 0x40;
+
+ switch (bmRequestType | bRequest << 8) {
+ /* Request Destination:
+ without flags: Device,
+ RH_INTERFACE: interface,
+ RH_ENDPOINT: endpoint,
+ RH_CLASS means HUB here,
+ RH_OTHER | RH_CLASS almost ever means HUB_PORT here
+ */
+
+ case RH_GET_STATUS:
+ len = 2;
+ data[0] = 0x01;
+ data[1] = 0x00;
+ req_reply = RH_ACK;
+ break;
+ case RH_GET_STATUS | RH_INTERFACE:
+ len = 2;
+ data[0] = 0x00;
+ data[1] = 0x00;
+ req_reply = RH_ACK;
+ break;
+ case RH_GET_STATUS | RH_ENDPOINT:
+ len = 2;
+ data[0] = 0x00;
+ data[1] = 0x00;
+ req_reply = RH_ACK;
+ break;
+ case RH_GET_STATUS | RH_CLASS: /* HUB_STATUS */
+ stat = readl(&ohci->regs->roothub.status) & 0x7fff7fff; /* bit 31 u. 15 has other meaning */
+ data[0] = stat & 0xff;
+ data[1] = (stat >> 8) & 0xff;
+ data[2] = (stat >> 16) & 0xff;
+ data[3] = (stat >> 24) & 0xff;
+ len = 4;
+ req_reply = RH_ACK;
+ break;
+ case RH_GET_STATUS | RH_OTHER | RH_CLASS: /* PORT_STATUS */
+ stat = readl(&ohci->regs->roothub.portstatus[wIndex-1]);
+ data[0] = stat & 0xff;
+ data[1] = (stat >> 8) & 0xff;
+ data[2] = (stat >> 16) & 0xff;
+ data[3] = (stat >> 24) & 0xff;
+ len = 4;
+ req_reply = RH_ACK;
+ printk("rh: stat %4x wIndex %4x;\n", stat , wIndex);
+ break;
+
+ case RH_CLEAR_FEATURE:
+ switch (wValue) {
+ case (RH_DEVICE_REMOTE_WAKEUP):
+ default:
+ }
+ break;
+
+ case RH_CLEAR_FEATURE | RH_ENDPOINT:
+ switch (wValue) {
+ case (RH_ENDPOINT_STALL):
+ len=0;
+ req_reply = RH_ACK;
+ break;
+ default:
+ }
+ break;
+
+ case RH_CLEAR_FEATURE | RH_CLASS:
+ switch (wValue) {
+ /* case (RH_C_HUB_LOCAL_POWER): OHCI says: no switching of this one */
+ case (RH_C_HUB_OVER_CURRENT):
+ writel(RH_PS_OCIC, &ohci->regs->roothub.status);
+ len=0;
+ req_reply = RH_ACK;
+ break;
+ default:
+ }
+ break;
+ case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
+ switch (wValue) {
+ case (RH_PORT_ENABLE):
+ writel(RH_PS_CCS, &ohci->regs->roothub.portstatus[wIndex-1]);
+ len=0;
+ req_reply = RH_ACK;
+ break;
+ case (RH_PORT_SUSPEND):
+ writel(RH_PS_POCI, &ohci->regs->roothub.portstatus[wIndex-1]);
+ len=0;
+ req_reply = RH_ACK;
+ break;
+ case (RH_PORT_POWER):
+ writel(RH_PS_LSDA, &ohci->regs->roothub.portstatus[wIndex-1]);
+ len=0;
+ req_reply = RH_ACK;
+ break;
+ case (RH_C_PORT_CONNECTION):
+ writel(RH_PS_CSC, &ohci->regs->roothub.portstatus[wIndex-1]);
+ len=0;
+ req_reply = RH_ACK;
+ break;
+ case (RH_C_PORT_ENABLE):
+ writel(RH_PS_PESC, &ohci->regs->roothub.portstatus[wIndex-1]);
+ len=0;
+ req_reply = RH_ACK;
+ break;
+ case (RH_C_PORT_SUSPEND):
+ writel(RH_PS_PSSC, &ohci->regs->roothub.portstatus[wIndex-1]);
+ len=0;
+ req_reply = RH_ACK;
+ break;
+ case (RH_C_PORT_OVER_CURRENT):
+ writel(RH_PS_OCIC, &ohci->regs->roothub.portstatus[wIndex-1]);
+ len=0;
+ req_reply = RH_ACK;
+ break;
+ case (RH_C_PORT_RESET):
+ writel(RH_PS_PRSC, &ohci->regs->roothub.portstatus[wIndex-1]);
+ len=0;
+ req_reply = RH_ACK;
+ break;
+ /*
+ case (RH_PORT_CONNECTION):
+ case (RH_PORT_OVER_CURRENT):
+ case (RH_PORT_RESET):
+ case (RH_PORT_LOW_SPEED):
+ */
+ default:
+ }
+ break;
+ case RH_SET_FEATURE:
+ switch (wValue) {
+ case (RH_DEVICE_REMOTE_WAKEUP):
+ default:
+ }
+ break;
+
+ case RH_SET_FEATURE | RH_ENDPOINT:
+ switch (wValue) {
+ case (RH_ENDPOINT_STALL):
+ default:
+ }
+ break;
+
+ case RH_SET_FEATURE | RH_CLASS:
+ switch (wValue) {
+ /* case (RH_C_HUB_LOCAL_POWER): Root Hub has no local Power
+ case (RH_C_HUB_OVER_CURRENT): */
+ default:
+ }
+ break;
+ case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
+ switch (wValue) {
+ case (RH_PORT_SUSPEND):
+ writel(RH_PS_PSS, &ohci->regs->roothub.portstatus[wIndex-1]);
+ len=0;
+ req_reply = RH_ACK;
+ break;
+ case (RH_PORT_RESET):
+ if((readl(&ohci->regs->roothub.portstatus[wIndex-1]) &1) != 0) /* BUG IN HUP CODE *********/
+ writel(RH_PS_PRS, &ohci->regs->roothub.portstatus[wIndex-1]);
+ len=0;
+ req_reply = RH_ACK;
+ break;
+ case (RH_PORT_POWER):
+ writel(RH_PS_PPS, &ohci->regs->roothub.portstatus[wIndex-1]);
+ len=0;
+ req_reply = RH_ACK;
+ break;
+ case (RH_PORT_ENABLE):
+ writel(RH_PS_PES, &ohci->regs->roothub.portstatus[wIndex-1]);
+ len=0;
+ req_reply = RH_ACK;
+ break;
+ /*
+ case (RH_PORT_CONNECTION):
+ case (RH_PORT_OVER_CURRENT):
+ case (RH_PORT_LOW_SPEED):
+ case (RH_C_PORT_CONNECTION):
+ case (RH_C_PORT_ENABLE):
+ case (RH_C_PORT_SUSPEND):
+ case (RH_C_PORT_OVER_CURRENT):
+ case (RH_C_PORT_RESET):
+ */
+ default:
+ }
+ break;
+
+ case RH_SET_ADDRESS:
+ ohci->root_hub_funct_addr = wValue;
+ /* ohci->ed_func_ep0[wValue] = &ohci->ed_rh_ep0;
+ ohci->ed_func_ep0[wValue]->ep_addr.bep.fa = wValue;
+ ohci->ed_func_ep0[wValue]->ed_list = &ohci->ed_rh_epi; */
+ ohci->ed_rh_epi.ed_list = NULL;
+ ohci->ed_rh_epi.ep_addr.bep.fa = wValue;
+ ohci->ed_rh_epi.ep_addr.bep.ep = 0xa1; /* Int in port 1 */
+ ohci->ed_func_ep0[0]= NULL;
+ len = 0;
+ req_reply = RH_ACK;
+ break;
+
+ case RH_GET_DESCRIPTOR:
+ switch ((wValue & 0xff00) >> 8) {
+ case (0x01): /* device descriptor */
+ len = min(sizeof(root_hub_dev_des), wLength);
+ memcpy(data, root_hub_dev_des, len);
+ req_reply = RH_ACK;
+ break;
+ case (0x02): /* configuration descriptor */
+ len = min(sizeof(root_hub_config_des), wLength);
+ memcpy(data, root_hub_config_des, len);
+ req_reply = RH_ACK;
+ break;
+ case (0x03): /* string descriptors */
+ default:
+ }
+ break;
+ case RH_GET_DESCRIPTOR | RH_CLASS:
+ data[1] = 0x29;
+ stat = readl(&ohci->regs->roothub.a);
+ data[2] = stat & 0xff; /* number of ports */
+ data[0] = (data[2] / 8) * 2 + 9; /* length of descriptor */
+ if(data[0] > wLength) {
+ req_reply = RH_REQ_ERR;
+ break;
+ }
+ data[3] = (stat >> 8) & 0xff;
+ data[4] = (stat >> 16) & 0xff;
+ data[5] = (stat >> 24) & 0xff;
+ data[6] = 0; /* Root Hub needs no current from bus */
+ stat = readl(&ohci->regs->roothub.b);
+ if(data[2] <= 8) { /* less than 8 Ports */
+ data[7] = stat & 0xff;
+ data[8] = (stat >> 16) & 0xff; /* 0xff for USB Rev. 1.1 ?, stat >> 16 for USB Rev. 1.0 */
+ }
+ else {
+ data[7] = stat & 0xff;
+ data[8] = (stat >> 8) & 0xff;
+ data[9] = (stat >> 16) & 0xff; /* 0xff for USB Rev. 1.1?, stat >> 16 for USB Rev. 1.0 */
+ data[10] = (stat >> 24) & 0xff; /* 0xff for USB Rev. 1.1?, stat >> 24 for USB Rev. 1.0 */
+ }
+ len = data[0];
+ req_reply = RH_ACK;
+ break;
+
+ case RH_SET_DESCRIPTOR:
+ break;
+
+ case RH_GET_CONFIGURATION:
+ len = 1;
+ data[0] = 0x01;
+ req_reply = RH_ACK;
+ break;
+
+ case RH_SET_CONFIGURATION: /* start it up */
+ writel( 0x10000, &ohci->regs->roothub.status);
+ /*writel( OHCI_INTR_RHSC, &ohci->regs->intrenable);*/
+ len = 0;
+ req_reply = RH_ACK;
+ break;
+ /* Optional or meaningless requests
+ case RH_GET_STATE | RH_OTHER | RH_CLASS:
+ case RH_GET_INTERFACE | RH_INTERFACE:
+ case RH_SET_INTERFACE | RH_INTERFACE:
+ case RH_SYNC_FRAME | RH_ENDPOINT:
+ */
+
+ /* Vendor Requests, we are the vendor!
+ Will the USB-Consortium give us a Vendor Id
+ for a virtual hub-device :-) ?
+ We could use these requests for configuration purposes on the HCD Driver, not used in the altenate usb !*/
+
+ case RH_SET_FEATURE | RH_VENDOR: /* remove all endpoints of device wIndex = Dev << 8 */
+ switch(wValue) {
+ case RH_REMOVE_EP:
+ ep_addr.iep = 0;
+ ep_addr.bep.ep = wIndex & 0xff;
+ ep_addr.bep.fa = (wIndex << 8) & 0xff00;
+ usb_ohci_rm_function(ohci, ep_addr.iep);
+ len=0;
+ req_reply = RH_ACK;
+ break;
+ }
+ break;
+ case RH_SET_FEATURE | RH_ENDPOINT | RH_VENDOR: /* remove endpoint wIndex = Dev << 8 | EP */
+ switch(wValue) {
+ case RH_REMOVE_EP:
+ ep_addr.iep = 0;
+ ep_addr.bep.ep = wIndex & 0xff;
+ ep_addr.bep.fa = (wIndex << 8) & 0xff00;
+ usb_ohci_rm_ep(ohci, ohci_find_ep(ohci, ep_addr.iep));
+ len=0;
+ req_reply = RH_ACK;
+ break;
+ }
+ break;
+ case RH_SET_EP | RH_ENDPOINT | RH_VENDOR:
+ ep_addr.bep.ep = data[0];
+ ep_addr.bep.fa = data[1];
+ ep_addr.bep.hc = data[2];
+ ep_addr.bep.host = data[3];
+ rep_handler = data[7] << 24 |data[6] << 16 | data[5] << 8 | data[4];
+ /* struct usb_ohci_ed *usb_ohci_add_ep(union ep_addr_ ep_addr,
+ struct ohci * ohci, int interval, int load, int (*handler)(int, void*), int ep_size, int speed) */
+ usb_ohci_add_ep(ohci, ep_addr.iep, data[8], data[9], (f_handler) rep_handler, data[11] << 8 | data[10] , data[12]);
+ len=0;
+ req_reply = RH_ACK;
+ break;
+
+ default:
+ }
+ printk("USB HC roothubstat1: %x \n", readl( &(ohci->regs->roothub.portstatus[0]) ));
+ printk("USB HC roothubstat2: %x \n", readl( &(ohci->regs->roothub.portstatus[1]) ));
+
+ /* if (req_reply == RH_ACK) len; */
+ queue_reply(ohci, ep_addr_ret.iep, 8, rh_cmd, data, len, lw0, lw1, handler);


+ return 0;
+}
+

+int root_hub_int_req(struct ohci * ohci, int cmd_len, void * ctrl, void * data, int data_len, __OHCI_BAG lw0, __OHCI_BAG lw1, f_handler handler){
+
+ struct ohci_rep_td *td;
+ struct ohci_rep_td *tmp;


+ union ep_addr_ ep_addr;
+

+ td = kmalloc(sizeof(td),GFP_KERNEL);
+ tmp = ohci->td_rh_epi;
+ td->next_td = NULL;
+ if(tmp == NULL) { /* queue td */
+ ohci->td_rh_epi = td;
+ }
+ else {
+ while(tmp->next_td != NULL) tmp = tmp->next_td;
+ tmp->next_td = td;


+ }
+ ep_addr.iep = 0;

+ ep_addr.bep.fa = ohci->root_hub_funct_addr;
+ ep_addr.bep.ep = 0xA1; /* INT IN EP endpoint 1 */
+ td->cmd_len = 0;
+ td->cmd = NULL;
+ td->data = data;
+ td->data_len = data_len;
+ td->handler = handler;
+ td->next_td = NULL;
+ td->ep_addr = ep_addr.iep;
+ td->lw0 = lw0;
+ td->lw1 = lw1;
+ ohci_init_rh_int_timer(ohci, 255);


+ return 0;
+}
+
+

+/* prepare Interrupt pipe transaction data; HUP INTERRUPT ENDPOINT */
+int root_hub_send_irq(struct ohci * ohci, void * rh_data, int rh_len ) {
+
+ int num_ports;
+ int i;
+ int ret;
+ int len;
+
+ __u8 * data = rh_data;
+
+ num_ports = readl(&ohci->regs->roothub.a) & 0xff;
+ data[0] = (readl(&ohci->regs->roothub.status) & 0x00030000)>0?1:0;
+ ret = data[0];
+
+ for(i=0; i < num_ports; i++) {
+ data[i/8] |= ((readl(&ohci->regs->roothub.portstatus[i]) & 0x001f0000)>0?1:0) << ((i+1) % 8);
+ ret += data[i/8];
+ }
+ len = i/8 + 1;
+
+ if (ret > 0) return len;
+
+ return RH_NACK;


+}
+
+
+
+
+

+static struct timer_list rh_int_timer;
+
+/* Virtual Root Hub INTs are polled by this timer every "intervall" ms */
+static void rh_int_timer_do(unsigned long ptr) {
+ int len;
+ int interval;
+ struct ohci * ohci = (struct ohci *) ptr;
+ struct ohci_rep_td *td = ohci->td_rh_epi;
+
+ if(td != NULL) { /* if ther is a TD handle the INT request */
+
+ len = root_hub_send_irq(ohci, td->data, td->data_len );
+ if(len > 0) {
+ ohci->td_rh_epi = td->next_td;
+ td->next_td = ohci->repl_queue;
+ ohci->repl_queue = td;
+ send_replies(ohci);
+ }
+ }
+ interval = ohci->rh_int_interval;
+ init_timer(& rh_int_timer);
+ rh_int_timer.function = rh_int_timer_do;
+ rh_int_timer.data = (unsigned long) ohci;
+ rh_int_timer.expires = jiffies + (HZ * (interval<30?30: interval)) /1000;
+ add_timer(&rh_int_timer);
+}
+
+/* Root Hub INTs are polled by this timer */
+int ohci_init_rh_int_timer(struct ohci * ohci, int interval) {
+
+ if(!(ohci->rh_int_timer)) {
+ ohci->rh_int_timer = 1;
+ ohci->rh_int_interval = interval;
+ init_timer(& rh_int_timer);
+ rh_int_timer.function = rh_int_timer_do;
+ rh_int_timer.data = (unsigned long) ohci;
+ rh_int_timer.expires = jiffies + (HZ * (interval<30?30: interval)) /1000;
+ add_timer(&rh_int_timer);


+ }
+ return 0;
+}
+

+int ohci_del_rh_int_timer(struct ohci * ohci) {
+ del_timer(&rh_int_timer);
+ return 0;
+}
+/* for root hub replies, queue the reply, (it will be sent immediately now) */
+
+int queue_reply(struct ohci * ohci, unsigned int ep_addr, int cmd_len,void * cmd, void * data,int len, __OHCI_BAG lw0, __OHCI_BAG lw1, f_handler handler) {
+
+ struct ohci_rep_td *td;
+ int status = 0;
+
+printk("queue_reply ep: %x len: %x\n", ep_addr, len);
+td = kmalloc(sizeof(td), GFP_KERNEL);
+
+ if (len < 0) { status = len; len = 0;}
+ td->cmd_len = cmd_len;
+ td->cmd = cmd;
+ td->data = data;
+ td->data_len = len;
+ td->handler = handler;
+ td->next_td = ohci->repl_queue; ohci->repl_queue = td;
+ td->ep_addr = ep_addr;
+ td->lw0 = lw0;
+ td->lw1 = lw1;
+ td->status = status;
+ send_replies(ohci);
+return 0;
+}
+
+/* for root hub replies; send the reply */
+int send_replies(struct ohci * ohci) {
+ struct ohci_rep_td *td;
+ struct ohci_rep_td *tmp;
+
+ td = ohci->repl_queue; ohci->repl_queue = NULL;
+ while ( td != NULL) {
+ td->handler((void *) ohci, td->ep_addr,td->cmd_len,td->cmd, td->data, td->data_len, td->status, td->lw0, td->lw1);
+ tmp = td;
+ td = td->next_td;
+
+ kfree(tmp);


+ }
+ return 0;
+}
+

+#endif
diff -u --recursive --new-file v2.2.7/linux/drivers/usb/ohci-root-hub.h linux/drivers/usb/ohci-root-hub.h
--- v2.2.7/linux/drivers/usb/ohci-root-hub.h Wed Dec 31 16:00:00 1969
+++ linux/drivers/usb/ohci-root-hub.h Mon May 10 10:18:34 1999
@@ -0,0 +1,71 @@
+/*
+ * HCD (OHCI) Virtual Root Hub Protocol for USB.
+ *
+ * (C) Copyright 1999 Roman Weissgaerber (wei...@vienna.at)
+ *
+ * The Root Hub is build into the HC (UHCI or OHCI) hardware.
+ * This piece of code lets it look like it resides on the bus
+ * like the other hubs.
+ * (for anyone who wants to do a control operation on the root hub)


+ *
+ * v1.0 1999/04/27

+ * ohci-root-hub.h


+ *
+ */
+

+/* destination of request */
+#define RH_INTERFACE 0x01
+#define RH_ENDPOINT 0x02
+#define RH_OTHER 0x03
+
+#define RH_CLASS 0x20
+#define RH_VENDOR 0x40
+
+/* Requests: bRequest << 8 | bmRequestType */
+#define RH_GET_STATUS 0x0080
+#define RH_CLEAR_FEATURE 0x0100
+#define RH_SET_FEATURE 0x0300
+#define RH_SET_ADDRESS 0x0500
+#define RH_GET_DESCRIPTOR 0x0680
+#define RH_SET_DESCRIPTOR 0x0700
+#define RH_GET_CONFIGURATION 0x0880
+#define RH_SET_CONFIGURATION 0x0900
+#define RH_GET_STATE 0x0280
+#define RH_GET_INTERFACE 0x0A80
+#define RH_SET_INTERFACE 0x0B00
+#define RH_SYNC_FRAME 0x0C80
+/* Our Vendor Specific Request */
+#define RH_SET_EP 0x2000
+
+
+/* Hub port features */
+#define RH_PORT_CONNECTION 0x00
+#define RH_PORT_ENABLE 0x01
+#define RH_PORT_SUSPEND 0x02
+#define RH_PORT_OVER_CURRENT 0x03
+#define RH_PORT_RESET 0x04
+#define RH_PORT_POWER 0x08
+#define RH_PORT_LOW_SPEED 0x09
+#define RH_C_PORT_CONNECTION 0x10
+#define RH_C_PORT_ENABLE 0x11
+#define RH_C_PORT_SUSPEND 0x12
+#define RH_C_PORT_OVER_CURRENT 0x13
+#define RH_C_PORT_RESET 0x14
+
+/* Hub features */
+#define RH_C_HUB_LOCAL_POWER 0x00
+#define RH_C_HUB_OVER_CURRENT 0x01
+
+#define RH_DEVICE_REMOTE_WAKEUP 0x00
+#define RH_ENDPOINT_STALL 0x01
+
+/* Our Vendor Specific feature */
+#define RH_REMOVE_EP 0x00
+
+
+#define RH_ACK 0x01
+#define RH_REQ_ERR -1
+#define RH_NACK 0x00
+
+#define min(a,b) (((a)<(b))?(a):(b))
+
diff -u --recursive --new-file v2.2.7/linux/drivers/usb/ohci.c linux/drivers/usb/ohci.c
--- v2.2.7/linux/drivers/usb/ohci.c Wed Apr 28 11:37:30 1999
+++ linux/drivers/usb/ohci.c Tue May 11 10:27:04 1999
@@ -29,7 +29,7 @@
X *
X * No filesystems were harmed in the development of this code.
X *
- * $Id: ohci.c,v 1.11 1999/04/25 00:18:52 greg Exp $
+ * $Id: ohci.c,v 1.26 1999/05/11 07:34:47 greg Exp $


X */
X
X #include <linux/config.h>

@@ -59,6 +59,10 @@
X
X static struct wait_queue *ohci_configure = NULL;
X
+#ifdef OHCI_TIMER
+static struct timer_list ohci_timer; /* timer for root hub polling */
+#endif
+
X
X static int ohci_td_result(struct ohci_device *dev, struct ohci_td *td)
X {
@@ -69,86 +73,258 @@
X /* TODO Debugging code for TD failures goes here */
X
X return status;
-}
+} /* ohci_td_result() */
X
X
X static spinlock_t ohci_edtd_lock = SPIN_LOCK_UNLOCKED;
X
X /*
- * Add a TD to the end of the TD list on a given ED. td->next_td is
- * assumed to be set correctly for the situation of no TDs already
- * being on the list (ie: pointing to NULL).
+ * Add a TD to the end of the TD list on a given ED. If td->next_td
+ * points to any more TDs, they will be added as well (naturally).
+ * Otherwise td->next_td must be 0.
+ *
+ * The SKIP flag will be cleared after this function.
+ *
+ * Important! This function needs locking and atomicity as it works
+ * in parallel with the HC's DMA. Locking ohci_edtd_lock while using
+ * the function is a must.
+ *
+ * This function can be called by the interrupt handler.
X */
X static void ohci_add_td_to_ed(struct ohci_td *td, struct ohci_ed *ed)
X {
- struct ohci_td *tail = bus_to_virt(ed->tail_td);
- struct ohci_td *head = bus_to_virt(ed->head_td);
- unsigned long flags;
+ /* don't let the HC pull anything from underneath us */
+ ed->status |= OHCI_ED_SKIP;
X
- spin_lock_irqsave(&ohci_edtd_lock, flags);
-
- if (tail == head) { /* empty list, put it on the head */
- head = (struct ohci_td *) virt_to_bus(td);
- tail = 0;
+ if (ed_head_td(ed) == 0) { /* empty list, put it on the head */
+ set_ed_head_td(ed, virt_to_bus(td));
+ ed->tail_td = 0;
X } else {
+ struct ohci_td *tail, *head;
+ head = (ed_head_td(ed) == 0) ? NULL : bus_to_virt(ed_head_td(ed));
+ tail = (ed->tail_td == 0) ? NULL : bus_to_virt(ed->tail_td);
X if (!tail) { /* no tail, single element list */
X td->next_td = head->next_td;
X head->next_td = virt_to_bus(td);
- tail = (struct ohci_td *) virt_to_bus(td);
+ ed->tail_td = virt_to_bus(td);
X } else { /* append to the list */
X td->next_td = tail->next_td;
X tail->next_td = virt_to_bus(td);
- tail = (struct ohci_td *) virt_to_bus(td);
+ ed->tail_td = virt_to_bus(td);


SHAR_EOF
true || echo 'restore of patch-2.2.8 failed'
fi

echo 'End of part 23'
echo 'File patch-2.2.8 is continued in part 24'
echo 24 > _shar_seq_.tmp

Thomas...@ciw.uni-karlsruhe.de

unread,
May 12, 1999, 3:00:00 AM5/12/99
to
Archive-name: v2.2/patch-2.2.8/part24

#!/bin/sh
# this is part 24 of a 33 - part archive


# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.8 continued
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 24; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.8'
else
echo 'x - continuing with patch-2.2.8'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.8' &&

X }
X }
- /* save the reverse link */
- td->ed_bus = virt_to_bus(ed);
X
- spin_unlock_irqrestore(&ohci_edtd_lock, flags);
+ /* save the ED link in each of the TDs added */
+ td->ed = ed;
+ while (td->next_td != 0) {
+ td = bus_to_virt(td->next_td);
+ td->ed = ed;
+ }
+
+ /* turn off the SKIP flag */
+ ed->status &= ~OHCI_ED_SKIP;
X } /* ohci_add_td_to_ed() */
X
X
+inline void ohci_start_control(struct ohci *ohci)
+{
+ /* tell the HC to start processing the control list */
+ writel(OHCI_CMDSTAT_CLF, &ohci->regs->cmdstatus);
+}
+
+inline void ohci_start_bulk(struct ohci *ohci)
+{
+ /* tell the HC to start processing the bulk list */
+ writel(OHCI_CMDSTAT_BLF, &ohci->regs->cmdstatus);
+}
+
+inline void ohci_start_periodic(struct ohci *ohci)
+{
+ /* enable processing periodc transfers starting next frame */
+ writel_set(OHCI_USB_PLE, &ohci->regs->control);
+}
+
+inline void ohci_start_isoc(struct ohci *ohci)
+{
+ /* enable processing isoc. transfers starting next frame */
+ writel_set(OHCI_USB_IE, &ohci->regs->control);
+}
+
X /*
- * Remove a TD from the given EDs TD list
+ * Add an ED to the hardware register ED list pointed to by hw_listhead_p
+ */
+static void ohci_add_ed_to_hw(struct ohci_ed *ed, void* hw_listhead_p)
+{
+ __u32 listhead;


+ unsigned long flags;
+

+ spin_lock_irqsave(&ohci_edtd_lock, flags);
+
+ listhead = readl(hw_listhead_p);
+
+ /* if the list is not empty, insert this ED at the front */
+ /* XXX should they go on the end? */
+ if (listhead) {
+ ed->next_ed = listhead;
+ }
+
+ /* update the hardware listhead pointer */
+ writel(virt_to_bus(ed), hw_listhead_p);
+
+ spin_unlock_irqrestore(&ohci_edtd_lock, flags);
+} /* ohci_add_ed() */
+
+
+/*
+ * Put another control ED on the controller's list
+ */
+void ohci_add_control_ed(struct ohci *ohci, struct ohci_ed *ed)
+{
+ ohci_add_ed_to_hw(ed, &ohci->regs->ed_controlhead);
+ ohci_start_control(ohci);
+} /* ohci_add_control_ed() */
+
+
+#if 0
+/*
+ * Put another control ED on the controller's list
+ */
+void ohci_add_periodic_ed(struct ohci *ohci, struct ohci_ed *ed, int period)
+{
+ ohci_add_ed_to_hw(ed, /* XXX */);
+ ohci_start_periodic(ohci);
+} /* ohci_add_control_ed() */
+#endif
+
+
+/*
+ * Remove an ED from the HC list whos bus headpointer is pointed to
+ * by hw_listhead_p
+ *
+ * Note that the SKIP bit is left on in the removed ED.
+ */
+void ohci_remove_ed_from_hw(struct ohci_ed *ed, __u32* hw_listhead_p)


+{
+ unsigned long flags;

+ struct ohci_ed *cur;
+ __u32 bus_ed = virt_to_bus(ed);
+ __u32 bus_cur;
+
+ if (ed == NULL || !bus_ed)
+ return;
+
+ /* tell the controller this skip ED */


+ ed->status |= OHCI_ED_SKIP;

+
+ bus_cur = readl(hw_listhead_p);
+
+ if (bus_cur == 0)
+ return; /* the list is already empty */
+
+ cur = bus_to_virt(bus_cur);
+
+ spin_lock_irqsave(&ohci_edtd_lock, flags);
+
+ /* if its the head ED, move the head */
+ if (bus_cur == bus_ed) {
+ writel(cur->next_ed, hw_listhead_p);
+ } else if (cur->next_ed != 0) {
+ struct ohci_ed *prev;
+
+ /* walk the list and unlink the ED if found */
+ for (;;) {
+ prev = cur;
+ cur = bus_to_virt(cur->next_ed);
+
+ if (virt_to_bus(cur) == bus_ed) {
+ /* unlink from the list */
+ prev->next_ed = cur->next_ed;
+ break;
+ }
+
+ if (cur->next_ed == 0)


+ break;
+ }
+ }
+

+ /* clear any links from the ED for safety */
+ ed->next_ed = 0;
+
+ spin_unlock_irqrestore(&ohci_edtd_lock, flags);
+} /* ohci_remove_ed_from_hw() */
+
+/*
+ * Remove an ED from the controller's control list. Note that the SKIP bit
+ * is left on in the removed ED.
+ */
+inline void ohci_remove_control_ed(struct ohci *ohci, struct ohci_ed *ed)
+{
+ ohci_remove_ed_from_hw(ed, &ohci->regs->ed_controlhead);
+}
+
+/*
+ * Remove an ED from the controller's bulk list. Note that the SKIP bit
+ * is left on in the removed ED.
+ */
+inline void ohci_remove_bulk_ed(struct ohci *ohci, struct ohci_ed *ed)
+{
+ ohci_remove_ed_from_hw(ed, &ohci->regs->ed_bulkhead);
+}
+
+
+/*
+ * Remove a TD from the given EDs TD list.
X */
X static void ohci_remove_td_from_ed(struct ohci_td *td, struct ohci_ed *ed)
X {


- struct ohci_td *head = bus_to_virt(ed->head_td);

- struct ohci_td *tmp_td;
X unsigned long flags;
+ struct ohci_td *head_td;
+
+ if ((td == NULL) || (ed == NULL))
+ return;
X
X spin_lock_irqsave(&ohci_edtd_lock, flags);
X

+ if (ed_head_td(ed) == 0)

+ return;
+
X /* set the "skip me bit" in this ED */
- writel_set(OHCI_ED_SKIP, ed->status);


+ ed->status |= OHCI_ED_SKIP;
X

X /* XXX Assuming this list will never be circular */
X
- if (td == head) {
- /* unlink this TD; it was at the beginning */
- ed->head_td = head->next_td;
- }
-
- tmp_td = head;
- head = (struct ohci_td *) ed->head_td;
-
- while (head != NULL) {
+ head_td = bus_to_virt(ed_head_td(ed));
+ if (virt_to_bus(td) == ed_head_td(ed)) {
+ /* It's the first TD, remove it. */
+ set_ed_head_td(ed, head_td->next_td);
+ } else {
+ struct ohci_td *prev_td, *cur_td;
X
- if (td == head) {
- /* unlink this TD from the middle or end */
- tmp_td->next_td = head->next_td;
+ /* FIXME: collapse this into a nice simple loop :) */
+ if (head_td->next_td != 0) {
+ prev_td = head_td;
+ cur_td = bus_to_virt(head_td->next_td);
+ for (;;) {
+ if (td == cur_td) {
+ /* remove it */
+ prev_td->next_td = cur_td->next_td;
+ break;
+ }
+ if (cur_td->next_td == 0)
+ break;
+ prev_td = cur_td;
+ cur_td = bus_to_virt(cur_td->next_td);
+ }
X }
-
- tmp_td = head;
- head = bus_to_virt(head->next_td);
X }
X
- td->next_td = virt_to_bus(NULL); /* remove links to ED list */
+ td->next_td = 0; /* remove the TDs links */
+ td->ed = NULL;
X
- /* XXX mark this TD for possible cleanup? */
+ /* TODO return this TD to the pool of free TDs */
X
X /* unset the "skip me bit" in this ED */
- writel_mask(~(__u32)OHCI_ED_SKIP, ed->status);
+ ed->status &= ~OHCI_ED_SKIP;
X
X spin_unlock_irqrestore(&ohci_edtd_lock, flags);
X } /* ohci_remove_td_from_ed() */
@@ -165,60 +341,67 @@
X int idx;
X
X for (idx=0; idx < NUM_TDS; idx++) {
- if (td_done(dev->td[idx].info)) {
- /* XXX should this also zero out the structure? */
- /* mark all new TDs as unaccessed */
- dev->td[idx].info = OHCI_TD_CC_NEW;
- return &dev->td[idx];
+ if (!td_allocated(dev->td[idx])) {
+ struct ohci_td *new_td = &dev->td[idx];
+ /* zero out the TD */
+ memset(new_td, 0, sizeof(*new_td));
+ /* mark the new TDs as unaccessed */
+ new_td->info = OHCI_TD_CC_NEW;
+ /* mark it as allocated */
+ allocate_td(new_td);
+ return new_td;
X }
X }
X
+ printk("usb-ohci error: unable to allocate a TD\n");
X return NULL;
X } /* ohci_get_free_td() */
X
X
-/**********************************
- * OHCI interrupt list operations *
- **********************************/
-static spinlock_t irqlist_lock = SPIN_LOCK_UNLOCKED;
-
-static void ohci_add_irq_list(struct ohci *ohci, struct ohci_td *td, usb_device_irq completed, void *dev_id)
+/*
+ * Initialize a TD
+ *
+ * dir = OHCI_TD_D_IN, OHCI_TD_D_OUT, or OHCI_TD_D_SETUP
+ * toggle = TOGGLE_AUTO, TOGGLE_DATA0, TOGGLE_DATA1
+ */
+inline struct ohci_td *ohci_fill_new_td(struct ohci_td *td, int dir, int toggle, __u32 flags, void *data, __u32 len, void *dev_id, usb_device_irq completed)
X {
- unsigned long flags;
+ /* hardware fields */
+ td->info = OHCI_TD_CC_NEW |
+ (dir & OHCI_TD_D) |
+ (toggle & OHCI_TD_DT) |
+ flags;
+ td->cur_buf = (data == NULL) ? 0 : virt_to_bus(data);
+ td->buf_end = (len == 0) ? 0 : td->cur_buf + len - 1;
X
- /* save the irq in our private portion of the TD */
- td->completed = completed;
+ /* driver fields */


+ td->data = data;

X td->dev_id = dev_id;
+ td->completed = completed;
X
- spin_lock_irqsave(&irqlist_lock, flags);
- list_add(&td->irq_list, &ohci->interrupt_list);
- spin_unlock_irqrestore(&irqlist_lock, flags);
-} /* ohci_add_irq_list() */
+ return td;
+} /* ohci_fill_new_td() */
X
-static void ohci_remove_irq_list(struct ohci_td *td)


-{
- unsigned long flags;

X
- spin_lock_irqsave(&irqlist_lock, flags);
- list_del(&td->irq_list);
- spin_unlock_irqrestore(&irqlist_lock, flags);
-} /* ohci_remove_irq_list() */
+/**********************************
+ * OHCI interrupt list operations *
+ **********************************/
X
X /*
X * Request an interrupt handler for one "pipe" of a USB device.
X * (this function is pretty minimal right now)
X *
X * At the moment this is only good for input interrupts. (ie: for a
- * mouse)
+ * mouse or keyboard)
X *
- * period is desired polling interval in ms. The closest, shorter
+ * Period is desired polling interval in ms. The closest, shorter
X * match will be used. Powers of two from 1-32 are supported by OHCI.
X */
X static int ohci_request_irq(struct usb_device *usb, unsigned int pipe,
X usb_device_irq handler, int period, void *dev_id)
X {
X struct ohci_device *dev = usb_to_ohci(usb);
- struct ohci_td *td = dev->td; /* */
+ struct ohci_td *td;
X struct ohci_ed *interrupt_ed; /* endpoint descriptor for this irq */
X
X /*
@@ -239,42 +422,68 @@
X usb_pipe_endpdev(pipe) |
X OHCI_ED_F_NORM;
X
+ td = ohci_get_free_td(dev);
+ /* FIXME: check for NULL */
+
+ /* Fill in the TD */
+ ohci_fill_new_td(td, td_set_dir_out(usb_pipeout(pipe)),
+ TOGGLE_AUTO,
+ OHCI_TD_ROUND,
+ dev->data, DATA_BUF_LEN,
+ dev_id, handler);
X /*
- * Set the not accessed condition code, allow odd sized data,
- * and set the data transfer direction.
+ * TODO: be aware that OHCI won't advance out of the 4kb
+ * page cur_buf started in. It'll wrap around to the start
+ * of the page... annoying or useful? you decide.
+ *
+ * We should make sure dev->data doesn't cross a page...
X */
- td->info = OHCI_TD_CC_NEW | OHCI_TD_ROUND |
- td_set_dir_out(usb_pipeout(pipe));
X
- /* point it to our data buffer */
- td->cur_buf = virt_to_bus(dev->data);
+ /* FIXME: this just guarantees that its the end of the list */
+ td->next_td = 0;
X
- /* FIXME: we're only using 1 TD right now! */
- td->next_td = virt_to_bus(&td);
+ /* Linus did this. see asm/system.h; scary concept... I don't
+ * know if its needed here or not but it won't hurt. */
+ wmb();
X
X /*
- * FIXME: be aware that OHCI won't advance out of the 4kb
- * page cur_buf started in. It'll wrap around to the start
- * of the page... annoying or useful? you decide.
- *
- * A pointer to the last *byte* in the buffer (ergh.. we get
- * to work around C's pointer arithmatic here with a typecast)
+ * Put the TD onto our ED
X */
- td->buf_end = virt_to_bus(((u8*)(dev->data + DATA_BUF_LEN)) - 1);


+ {
+ unsigned long flags;

+ spin_lock_irqsave(&ohci_edtd_lock, flags);
+ ohci_add_td_to_ed(td, interrupt_ed);
+ spin_unlock_irqrestore(&ohci_edtd_lock, flags);
+ }
X
- /* does this make sense for ohci?.. time to think.. */
- ohci_add_irq_list(dev->ohci, td, handler, dev_id);
- wmb(); /* found in asm/system.h; scary concept... */
- ohci_add_td_to_ed(td, interrupt_ed);
+#if 0
+ /* Assimilate the new ED into the collective */
+ /*
+ * When dynamic ED allocation is done, this call will be
+ * useful. For now, the correct ED already on the
+ * controller's proper periodic ED lists was chosen above.
+ */
+ ohci_add_periodic_ed(dev->ohci, interrupt_ed, period);
+#else
+ /* enable periodic (interrupt) transfers on the HC */
+ ohci_start_periodic(dev->ohci);
+#endif
X
X return 0;
X } /* ohci_request_irq() */
X
+
X /*
X * Control thread operations:
X */
X static struct wait_queue *control_wakeup;
X
+/*
+ * This is the handler that gets called when a control transaction
+ * completes.
+ *
+ * This function is called from the interrupt handler.
+ */
X static int ohci_control_completed(int stats, void *buffer, void *dev_id)
X {
X wake_up(&control_wakeup);
@@ -283,41 +492,16 @@
X
X
X /*
- * Run a control transaction from the root hub's control endpoint.
- * The passed in TD is the control transfer's Status TD.
- */
-static int ohci_run_control(struct ohci_device *dev, struct ohci_td *status_td)
-{
- struct wait_queue wait = { current, NULL };
- struct ohci_ed *control_ed = &dev->ohci->root_hub->ed[ED_CONTROL];
-
- current->state = TASK_UNINTERRUPTIBLE;
- add_wait_queue(&control_wakeup, &wait);
-
- ohci_add_irq_list(dev->ohci, status_td, ohci_control_completed, NULL);
- ohci_add_td_to_ed(status_td, control_ed);
-
- /* FIXME? isn't this a little gross */
- schedule_timeout(HZ/10);
-
- ohci_remove_irq_list(status_td);
- ohci_remove_td_from_ed(status_td, control_ed);
-
- return ohci_td_result(dev, status_td);
-} /* ohci_run_control() */
-
-/*
X * Send or receive a control message on a "pipe"
X *
+ * The cmd parameter is a pointer to the 8 byte setup command to be
+ * sent. FIXME: This is a devrequest in usb.h. The function
+ * should be updated to accept a devrequest* instead of void*..
+ *
X * A control message contains:
X * - The command itself
- * - An optional data phase
+ * - An optional data phase (if len > 0)
X * - Status complete phase
- *
- * The data phase can be an arbitrary number of TD's. Currently since
- * we use statically allocated TDs if too many come in we'll just
- * start tossing them and printk() some warning goo... Most control
- * messages won't have much data anyways.
X */
X static int ohci_control_msg(struct usb_device *usb, unsigned int pipe, void *cmd, void *data, int len)
X {
@@ -330,10 +514,12 @@
X * anyways? ;)
X */
X struct ohci_ed *control_ed = &dev->ohci->root_hub->ed[ED_CONTROL];
- struct ohci_td *control_td;
- struct ohci_td *data_td;
- struct ohci_td *last_td;
- __u32 data_td_info;
+ struct ohci_td *setup_td, *data_td, *status_td;


+ struct wait_queue wait = { current, NULL };
+

+#if 0
+ printk(KERN_DEBUG "entering ohci_control_msg %p (ohci_dev: %p) pipe 0x%x, cmd %p, data %p, len %d\n", usb, dev, pipe, cmd, data, len);
+#endif
X
X /*
X * Set the max packet size, device speed, endpoint number, usb
@@ -351,95 +537,174 @@
X */
X
X /* get a TD to send this control message with */
- control_td = ohci_get_free_td(dev);
+ setup_td = ohci_get_free_td(dev);
X /* TODO check for NULL */
X
X /*
X * Set the not accessed condition code, allow odd sized data,
X * and set the data transfer type to SETUP. Setup DATA always
X * uses a DATA0 packet.
- */
- control_td->info = OHCI_TD_CC_NEW | OHCI_TD_ROUND |
- OHCI_TD_D_SETUP | OHCI_TD_IOC_OFF | td_force_toggle(0);
-
- /* point it to the command */
- control_td->cur_buf = virt_to_bus(cmd);
+ *
+ * The setup packet contains a devrequest (usb.h) which
+ * will always be 8 bytes long. FIXME: the cmd parameter
+ * should be a pointer to one of these instead of a void* !!!
+ */
+ ohci_fill_new_td(setup_td, OHCI_TD_D_SETUP, TOGGLE_DATA0,
+ OHCI_TD_IOC_OFF,
+ cmd, 8, /* cmd is always 8 bytes long */
+ NULL, NULL);
X
- /* link to a free TD for the control data input */
+ /* allocate the next TD */
X data_td = ohci_get_free_td(dev); /* TODO check for NULL */
- control_td->next_td = virt_to_bus(data_td);
+
+ /* link to the next TD */
+ setup_td->next_td = virt_to_bus(data_td);


+
+ if (len > 0) {

+
+ /* build the Control DATA TD, it starts with a DATA1. */
+ ohci_fill_new_td(data_td, td_set_dir_out(usb_pipeout(pipe)),
+ TOGGLE_DATA1,
+ OHCI_TD_ROUND | OHCI_TD_IOC_OFF,
+ data, len,
+ NULL, NULL);
+
+ /*
+ * XXX we should check that the data buffer doesn't
+ * cross a 4096 byte boundary. If so, it needs to be
+ * copied into a single 4096 byte aligned area for the
+ * OHCI's TD logic to see it all, or multiple TDs need
+ * to be made for each page.
+ *
+ * It's not likely a control transfer will run into
+ * this problem.. (famous last words)
+ */
+
+ status_td = ohci_get_free_td(dev); /* TODO check for NULL */
+ data_td->next_td = virt_to_bus(status_td);
+ } else {
+ status_td = data_td; /* no data_td, use it for status */
+ }
+
+ /* The control status packet always uses a DATA1 */
+ ohci_fill_new_td(status_td,
+ td_set_dir_in(usb_pipeout(pipe) | (len == 0)),
+ TOGGLE_DATA1,
+ 0,
+ NULL, 0,
+ NULL, ohci_control_completed);
+ status_td->next_td = 0; /* end of TDs */
X
X /*
- * Build the DATA TDs
+ * Start the control transaction..
X */


+ current->state = TASK_UNINTERRUPTIBLE;
+ add_wait_queue(&control_wakeup, &wait);

X
- data_td_info = OHCI_TD_CC_NEW | OHCI_TD_ROUND | OHCI_TD_IOC_OFF |
- td_set_dir_out(usb_pipeout(pipe));
-
- while (len > 0) {
- int pktsize = len;
- struct ohci_td *tmp_td;
+ /*
+ * Add the chain of 2-3 control TDs to the control ED's TD list
+ */


+ {
+ unsigned long flags;

+ spin_lock_irqsave(&ohci_edtd_lock, flags);
+ ohci_add_td_to_ed(setup_td, control_ed);
+ spin_unlock_irqrestore(&ohci_edtd_lock, flags);
+ }
+
+#if 0
+ /* complete transaction debugging output (before) */
+ printk(KERN_DEBUG " Control ED %lx:\n", virt_to_bus(control_ed));
+ show_ohci_ed(control_ed);
+ printk(KERN_DEBUG " Setup TD %lx:\n", virt_to_bus(setup_td));
+ show_ohci_td(setup_td);
+ if (data_td != status_td) {
+ printk(KERN_DEBUG " Data TD %lx:\n", virt_to_bus(data_td));
+ show_ohci_td(data_td);
+ }
+ printk(KERN_DEBUG " Status TD %lx:\n", virt_to_bus(status_td));
+ show_ohci_td(status_td);
+#endif
X
- if (pktsize > usb_maxpacket(pipe))
- pktsize = usb_maxpacket(pipe);
+ /* Give the ED to the HC */
+ ohci_add_control_ed(dev->ohci, control_ed);
X
- /* set the data transaction type */
- data_td->info = data_td_info;
- /* point to the current spot in the data buffer */
- data_td->cur_buf = virt_to_bus(data);
- /* point to the end of this data */
- data_td->buf_end = virt_to_bus(data+pktsize-1);
+ /* FIXME:
+ * this should really check to see that the transaction completed.
+ */
+ schedule_timeout(HZ/10);
X
- /* allocate the next TD */
- tmp_td = ohci_get_free_td(dev); /* TODO check for NULL */
- data_td->next_td = virt_to_bus(tmp_td);
- data_td = tmp_td;
+ remove_wait_queue(&control_wakeup, &wait);
X
- /* move on.. */
- data += pktsize;
- len -= pktsize;
+#if 0
+ /* complete transaction debugging output (after) */
+ printk(KERN_DEBUG " (after) Control ED:\n");
+ show_ohci_ed(control_ed);
+ printk(KERN_DEBUG " (after) Setup TD:\n");
+ show_ohci_td(setup_td);
+ if (data_td != status_td) {
+ printk(KERN_DEBUG " (after) Data TD:\n");
+ show_ohci_td(data_td);
X }
+ printk(KERN_DEBUG " (after) Status TD:\n");
+ show_ohci_td(status_td);
+#endif
X
- /* point it at the newly allocated TD from above */
- last_td = data_td;
+ /* clean up incase it failed */
+ /* XXX only do this if their ed pointer still points to control_ed
+ * incase they've been reclaimed and used by something else
+ * already. -greg */
+ ohci_remove_td_from_ed(setup_td, control_ed);
+ ohci_remove_td_from_ed(data_td, control_ed);
+ ohci_remove_td_from_ed(status_td, control_ed);
X
- /* The control status packet always uses a DATA1 */
- last_td->info = OHCI_TD_CC_NEW | OHCI_TD_ROUND | td_force_toggle(1);
- last_td->next_td = 0; /* end of TDs */
- last_td->cur_buf = 0; /* no data in this packet */
- last_td->buf_end = 0;
+ /* remove the control ED */
+ ohci_remove_control_ed(dev->ohci, control_ed);
X
- /*
- * Start the control transaction.. give it the last TD so the
- * result can be returned.
- */
- return ohci_run_control(dev, last_td);
+#if 0
+ printk(KERN_DEBUG "leaving ohci_control_msg\n");
+#endif
+
+ return ohci_td_result(dev, status_td);
X } /* ohci_control_msg() */
X
X
+/*
+ * Allocate a new USB device to be attached to an OHCI controller
+ */
X static struct usb_device *ohci_usb_allocate(struct usb_device *parent)
X {
X struct usb_device *usb_dev;
X struct ohci_device *dev;
X
+ /*
+ * Allocate the generic USB device
+ */
X usb_dev = kmalloc(sizeof(*usb_dev), GFP_KERNEL);
X if (!usb_dev)
X return NULL;
X
X memset(usb_dev, 0, sizeof(*usb_dev));
X
+ /*
+ * Allocate an OHCI device (EDs and TDs for this device)
+ */
X dev = kmalloc(sizeof(*dev), GFP_KERNEL);
X if (!dev) {
X kfree(usb_dev);


X return NULL;
X }
X

- /* Initialize "dev" */
X memset(dev, 0, sizeof(*dev));
X
+ /*
+ * Link them together
+ */
X usb_dev->hcpriv = dev;
X dev->usb = usb_dev;
X
+ /*
+ * Link the device to its parent (hub, etc..) if any.
+ */
X usb_dev->parent = parent;
X
X if (parent) {
@@ -448,8 +713,14 @@
X }
X
X return usb_dev;
-}
+} /* ohci_usb_allocate() */
+
X
+/*
+ * Free a usb device.
+ *
+ * TODO This function needs to take better care of the EDs and TDs, etc.
+ */
X static int ohci_usb_deallocate(struct usb_device *usb_dev)
X {
X kfree(usb_to_ohci(usb_dev));
@@ -457,6 +728,7 @@


X return 0;
X }
X

+
X /*
X * functions for the generic USB driver
X */
@@ -467,42 +739,92 @@
X ohci_request_irq,


X };
X
+
X /*

- * Reset an OHCI controller
+ * Reset an OHCI controller. Returns >= 0 on success.
+ *
+ * Afterwards the HC will be in the "suspend" state which prevents you
+ * from writing to some registers. Bring it to the operational state
+ * ASAP.
X */
-static void reset_hc(struct ohci *ohci)
+static int reset_hc(struct ohci *ohci)
X {
- writel((1<<31), &ohci->regs->intrdisable); /* Disable HC interrupts */
- writel(1, &ohci->regs->cmdstatus); /* HC Reset */
+ int timeout = 1000; /* prevent an infinite loop */
+
+#if 0
+ printk(KERN_DEBUG "usb-ohci: resetting HC %p\n", ohci);
+#endif
+
+ writel(~0x0, &ohci->regs->intrdisable); /* Disable HC interrupts */


+ writel(1, &ohci->regs->cmdstatus); /* HC Reset */

X writel_mask(0x3f, &ohci->regs->control); /* move to UsbReset state */
+
+ while ((readl(&ohci->regs->cmdstatus) & OHCI_CMDSTAT_HCR) != 0) {
+ if (!--timeout) {
+ printk("usb-ohci: USB HC reset timed out!\n");
+ return -1;


+ }
+ udelay(1);
+ }
+

+ printk(KERN_DEBUG "usb-ohci: HC %p reset.\n", ohci);
+
+ return 0;
X } /* reset_hc() */
X
X
X /*
- * Reset and start an OHCI controller
+ * Reset and start an OHCI controller. Returns >= 0 on success.
X */
-static void start_hc(struct ohci *ohci)
+static int start_hc(struct ohci *ohci)
X {
- int timeout = 1000; /* used to prevent an infinite loop. */
+ int ret = 0;
+ int fminterval;
X
- reset_hc(ohci);


+ fminterval = readl(&ohci->regs->fminterval) & 0x3fff;

+#if 0
+ printk(KERN_DEBUG "entering start_hc %p\n", ohci);
+#endif
X
- while ((readl(&ohci->regs->control) & 0xc0) == 0) {
- if (!--timeout) {
- printk("USB HC Reset timed out!\n");
- break;
- }
- }
+ if (reset_hc(ohci) < 0)
+ return -1;
+
+ /* restore registers cleared by the reset */
+ writel(virt_to_bus(ohci->root_hub->hcca), &ohci->regs->hcca);
+
+ /*
+ * XXX Should fminterval also be set here?
+ * The spec suggests 0x2edf [11,999]. (FIXME: make this a constant)
+ */
+ fminterval |= (0x2edf << 16);


+ writel(fminterval, &ohci->regs->fminterval);

+ /* Start periodic transfers at 90% of fminterval (fmremaining
+ * counts down; this will put them in the first 10% of the
+ * frame). */
+ writel((0x2edf*9)/10, &ohci->regs->periodicstart);
X
+ /*
+ * FNO (frame number overflow) could be enabled... they
+ * occur every 32768 frames (every 32-33 seconds). This is
+ * useful for debugging and as a bus heartbeat. -greg
+ */
X /* Choose the interrupts we care about */
- writel( OHCI_INTR_MIE | OHCI_INTR_RHSC | OHCI_INTR_SF |
- OHCI_INTR_WDH | OHCI_INTR_SO | OHCI_INTR_UE |
- OHCI_INTR_FNO,
+ writel( OHCI_INTR_MIE | /* OHCI_INTR_RHSC | */
+ OHCI_INTR_WDH | OHCI_INTR_FNO,
X &ohci->regs->intrenable);
X
X /* Enter the USB Operational state & start the frames a flowing.. */
X writel_set(OHCI_USB_OPER, &ohci->regs->control);
+
+ /* Enable control lists */
+ writel_set(OHCI_USB_IE | OHCI_USB_CLE | OHCI_USB_BLE, &ohci->regs->control);
+
+ /* Turn on power to the root hub ports (thanks Roman!) */
+ writel( OHCI_ROOT_LPSC, &ohci->regs->roothub.status );
+
+ printk("usb-ohci: host controller operational\n");
X
+ return ret;
X } /* start_hc() */
X
X
@@ -511,23 +833,20 @@
X */
X static void ohci_reset_port(struct ohci *ohci, unsigned int port)
X {
- short ms;
X int status;
X
X /* Don't allow overflows. */
X if (port >= MAX_ROOT_PORTS) {
- printk("Bad port # passed to ohci_reset_port\n");
+ printk("usb-ohci: bad port #%d in ohci_reset_port\n", port);
X port = MAX_ROOT_PORTS-1;
X }
X
X writel(PORT_PRS, &ohci->regs->roothub.portstatus[port]); /* Reset */
X
X /*
- * Get the time required for a root hub port to reset and wait
- * it out (adding 1ms for good measure).
+ * Wait for the reset to complete.
X */
- ms = (readl(&ohci->regs->roothub.a) >> 24) * 2 + 1;
- wait_ms(ms);
+ wait_ms(10);
X
X /* check port status to see that the reset completed */
X status = readl(&ohci->regs->roothub.portstatus[port]);
@@ -555,6 +874,8 @@
X void *portaddr = &ohci->regs->roothub.portstatus[port];
X int portstatus;
X
+ printk(KERN_DEBUG "ohci_connect_change(%p, %d)\n", ohci, port);
+
X /*
X * Because of the status change we have to forget
X * everything we think we know about the device
@@ -593,6 +914,7 @@
X * Do generic USB device tree processing on the new device.
X */
X usb_new_device(usb_dev);
+
X } /* ohci_connect_change() */
X
X
@@ -603,66 +925,241 @@
X */
X static void ohci_check_configuration(struct ohci *ohci)
X {


+ struct ohci_regs *regs = ohci->regs;

X int num = 0;
X int maxport = readl(&ohci->regs->roothub) & 0xff;
X
+#if 1
+ printk(KERN_DEBUG "entering ohci_check_configuration %p\n", ohci);
+#endif
+
X do {
- if (readl(ohci->regs->roothub.portstatus[num]) & PORT_CSC)
+ if (readl(&regs->roothub.portstatus[num]) & PORT_CSC) {
+ /* reset the connect status change bit */
+ writel(PORT_CSC, &regs->roothub.portstatus[num]);
+ /* check the port for a nifty device */
X ohci_connect_change(ohci, num);
+ }
X } while (++num < maxport);
+
+#if 0
+ printk(KERN_DEBUG "leaving ohci_check_configuration %p\n", ohci);
+#endif
X } /* ohci_check_configuration() */
X
X
+
+/*
+ * Check root hub port status and wake the control thread up if
+ * anything has changed.
+ *
+ * This function is called from the interrupt handler.
+ */
+static void ohci_root_hub_events(struct ohci *ohci)
+{
+ if (waitqueue_active(&ohci_configure)) {
+ int num = 0;
+ int maxport = ohci->root_hub->usb->maxchild;
+
+ do {
+ if (readl(&ohci->regs->roothub.portstatus[num]) &
+ PORT_CSC) {
+ if (waitqueue_active(&ohci_configure))
+ wake_up(&ohci_configure);
+ return;
+ }
+ } while (++num < maxport);
+ }
+} /* ohci_root_hub_events() */
+
+
+/*
+ * The done list is in reverse order; we need to process TDs in the
+ * order they were finished (FIFO). This function builds the FIFO
+ * list using the next_dl_td pointer.
+ *
+ * This function originally by Roman Weissgaerber (wei...@vienna.at)
+ *
+ * This function is called from the interrupt handler.
+ */
+static struct ohci_td * ohci_reverse_donelist(struct ohci * ohci)
+{
+ __u32 td_list_hc;
+ struct ohci_hcca *hcca = ohci->root_hub->hcca;
+ struct ohci_td *td_list = NULL;
+ struct ohci_td *td_rev = NULL;
+
+ td_list_hc = hcca->donehead & 0xfffffff0;
+ hcca->donehead = 0;
+
+ while(td_list_hc) {
+ td_list = (struct ohci_td *) bus_to_virt(td_list_hc);


+ td_list->next_dl_td = td_rev;
+
+ td_rev = td_list;

+ td_list_hc = td_list->next_td & 0xfffffff0;
+ }
+
+ return td_list;
+} /* ohci_reverse_donelist() */
+
+
+/*
+ * Collect this interrupt's goodies off of the list of finished TDs
+ * that the OHCI controller is kind enough to setup for us.
+ *
+ * This function is called from the interrupt handler.
+ */
+static void ohci_reap_donelist(struct ohci *ohci)
+{
+ struct ohci_td *td; /* used for walking the list */
+
+ spin_lock(&ohci_edtd_lock);
+
+ /* create the FIFO ordered donelist */
+ td = ohci_reverse_donelist(ohci);
+
+ while (td != NULL) {
+ struct ohci_td *next_td = td->next_dl_td;
+
+ /* FIXME: munge td->info into a future standard status format */
+ /* Check if TD should be re-queued */
+ if ((td->completed != NULL) &&
+ (td->completed(OHCI_TD_CC_GET(td->info), td->data, td->dev_id)))
+ {
+ /* Mark the TD as active again:
+ * Set the not accessed condition code
+ * FIXME: should this reset OHCI_TD_ERRCNT?
+ */
+ td->info |= OHCI_TD_CC_NEW;
+
+ /* point it back to the start of the data buffer */
+ td->cur_buf = virt_to_bus(td->data);
+
+ /* XXX disabled for debugging reasons right now.. */
+ /* insert it back on its ED */
+ ohci_add_td_to_ed(td, td->ed);
+ } else {
+ /* return it to the pool of free TDs */
+ ohci_free_td(td);
+ }
+
+ td = next_td;
+ }
+
+ spin_unlock(&ohci_edtd_lock);
+} /* ohci_reap_donelist() */
+
+
+#if 0
+static int in_int = 0;
+#endif
X /*
X * Get annoyed at the controller for bothering us.
+ * This pretty much follows the OHCI v1.0a spec, section 5.3.
X */
X static void ohci_interrupt(int irq, void *__ohci, struct pt_regs *r)
X {
X struct ohci *ohci = __ohci;
X struct ohci_regs *regs = ohci->regs;
X struct ohci_hcca *hcca = ohci->root_hub->hcca;
- __u32 donehead = hcca->donehead;
+ __u32 status, context;
X
- /*
- * Check the interrupt status register if needed
- */
- if (!donehead || (donehead & 1)) {
- __u32 intrstatus = readl(&regs->intrstatus);
+#if 0
+ /* for debugging to keep IRQs from running away. */
+ if (in_int >= 2)
+ return;
+ ++in_int;
+ return;
+#endif
X
- /*
- * XXX eek! printk's in an interrupt handler. shoot me!
- */
- if (intrstatus & OHCI_INTR_SO) {
- printk(KERN_DEBUG "usb-ohci: scheduling overrun\n");
- }
- if (intrstatus & OHCI_INTR_RD) {
- printk(KERN_DEBUG "usb-ohci: resume detected\n");
- }
- if (intrstatus & OHCI_INTR_UE) {
- printk(KERN_DEBUG "usb-ohci: unrecoverable error\n");
+ /* Save the status of the interrupts that are enabled */
+ status = readl(&regs->intrstatus);
+ status &= readl(&regs->intrenable);
+
+
+ /* make context = the interrupt status bits that we care about */
+ if (hcca->donehead != 0) {
+ context = OHCI_INTR_WDH; /* hcca donehead needs processing */
+ if (hcca->donehead & 1) {
+ context |= status; /* other status change to check */
X }
- if (intrstatus & OHCI_INTR_OC) {
- printk(KERN_DEBUG "usb-ohci: ownership change?\n");
+ } else {
+ context = status;
+ if (!context) {
+ /* TODO increment a useless interrupt counter here */
+ return;
X }
+ }
X
- if (intrstatus & OHCI_INTR_RHSC) {
- /* TODO Process events on the root hub */
- }
+ /* Disable HC interrupts */
+ writel(OHCI_INTR_MIE, &regs->intrdisable);
+
+ /* Process the done list */
+ if (context & OHCI_INTR_WDH) {
+ /* See which TD's completed.. */
+ ohci_reap_donelist(ohci);
+
+ /* reset the done queue and tell the controller */
+ hcca->donehead = 0;
+ writel(OHCI_INTR_WDH, &regs->intrstatus);
+
+ context &= ~OHCI_INTR_WDH; /* mark this as checked */
X }
X
- /*
- * Process the done list
- */
- if (donehead &= ~0x1) {
- /*
- * TODO See which TD's completed..
+ /* Process any root hub status changes */
+ if (context & OHCI_INTR_RHSC) {
+ /* Wake the thread to process root hub events */
+ if (waitqueue_active(&ohci_configure))
+ wake_up(&ohci_configure);
+
+ writel(OHCI_INTR_RHSC, &regs->intrstatus);
+ /*
+ * Don't unset RHSC in context; it should be disabled.
+ * The control thread will re-enable it after it has
+ * checked the root hub status.
X */
+ } else {
+ /* check the root hub status anyways. Some controllers
+ * might not generate the interrupt properly. (?) */
+ ohci_root_hub_events(ohci);
X }
X
- /* Re-enable done queue interrupts and reset the donehead */
- hcca->donehead = 0;
- writel(OHCI_INTR_WDH, &regs->intrenable);
-
+ /* Check those "other" pesky bits */
+ if (context & (OHCI_INTR_FNO)) {
+ writel(OHCI_INTR_FNO, &regs->intrstatus);
+ context &= ~OHCI_INTR_FNO; /* mark this as checked */
+ }
+ if (context & OHCI_INTR_SO) {
+ writel(OHCI_INTR_SO, &regs->intrstatus);
+ context &= ~OHCI_INTR_SO; /* mark this as checked */
+ }
+ if (context & OHCI_INTR_RD) {
+ writel(OHCI_INTR_RD, &regs->intrstatus);
+ context &= ~OHCI_INTR_RD; /* mark this as checked */
+ }
+ if (context & OHCI_INTR_UE) {
+ /* FIXME: need to have the control thread reset the
+ * controller now and keep a count of unrecoverable
+ * errors. If there are too many, it should just shut
+ * the broken controller down entirely. */
+ writel(OHCI_INTR_UE, &regs->intrstatus);
+ context &= ~OHCI_INTR_UE; /* mark this as checked */
+ }
+ if (context & OHCI_INTR_OC) {
+ writel(OHCI_INTR_OC, &regs->intrstatus);
+ context &= ~OHCI_INTR_OC; /* mark this as checked */
+ }
+
+ /* Mask out any remaining unprocessed interrupts so we don't
+ * get any more of them. */
+ if (context & ~OHCI_INTR_MIE) {
+ writel(context, &regs->intrdisable);
+ }
+
+ /* Re-enable HC interrupts */


+ writel(OHCI_INTR_MIE, &regs->intrenable);
+

X } /* ohci_interrupt() */
X
X
@@ -682,6 +1179,10 @@
X struct ohci_device *dev;
X struct usb_device *usb;
X
+#if 0
+ printk(KERN_DEBUG "entering alloc_ohci %p\n", mem_base);
+#endif
+
X ohci = kmalloc(sizeof(*ohci), GFP_KERNEL);
X if (!ohci)
X return NULL;
@@ -703,6 +1204,8 @@
X bus->op = &ohci_device_operations;
X
X /*
+ * Allocate the USB device structure and root hub.
+ *
X * Here we allocate our own root hub and TDs as well as the
X * OHCI host controller communications area. The HCCA is just
X * a nice pool of memory with pointers to endpoint descriptors
@@ -717,17 +1220,22 @@
X usb->bus = bus;
X
X /* Initialize the root hub */
- memset(dev, 0, sizeof(*dev));
X dev->ohci = ohci; /* link back to the controller */
X
X /*
- * Allocate the Host Controller Communications Area
+ * Allocate the Host Controller Communications Area on a 256
+ * byte boundary. XXX take the easy way out and just grab a
+ * page as that's guaranteed to have a nice boundary.
X */
- dev->hcca = (struct ohci_hcca *) kmalloc(sizeof(*dev->hcca), GFP_KERNEL);
+ dev->hcca = (struct ohci_hcca *) __get_free_page(GFP_KERNEL);
X
X /* Tell the controller where the HCCA is */
X writel(virt_to_bus(dev->hcca), &ohci->regs->hcca);
X
+#if 0
+ printk(KERN_DEBUG "usb-ohci: HCCA allocated at %p (bus %p)\n", dev->hcca, (void*)virt_to_bus(dev->hcca));
+#endif
+
X /* Get the number of ports on the root hub */
X usb->maxchild = readl(&ohci->regs->roothub.a) & 0xff;
X if (usb->maxchild > MAX_ROOT_PORTS) {
@@ -740,11 +1248,6 @@
X }
X printk("usb-ohci: %d root hub ports found\n", usb->maxchild);
X
- printk("alloc_ohci() controller\n");
- show_ohci_status(ohci);
- printk("alloc_ohci() root_hub device\n");
- show_ohci_device(dev);
-
X /*
X * Initialize the ED polling "tree" (for simplicity's sake in
X * this driver many nodes in the tree will be identical)
@@ -759,11 +1262,9 @@
X * Initialize the polling table to call interrupts at the
X * intended intervals.
X */
- for (i = 0; i < NUM_INTS; i++) {
- if (i == 0)
- dev->hcca->int_table[i] =
- virt_to_bus(&dev->ed[ED_INT_32]);
- else if (i & 1)
+ dev->hcca->int_table[0] = virt_to_bus(&dev->ed[ED_INT_32]);
+ for (i = 1; i < NUM_INTS; i++) {
+ if (i & 1)
X dev->hcca->int_table[i] =
X virt_to_bus(&dev->ed[ED_INT_16]);
X else if (i & 2)
@@ -782,9 +1283,23 @@
X
X /*
X * Tell the controller where the control and bulk lists are
+ * The lists start out empty.
X */


+ writel(0, &ohci->regs->ed_controlhead);
+ writel(0, &ohci->regs->ed_bulkhead);

+ /*
X writel(virt_to_bus(&dev->ed[ED_CONTROL]), &ohci->regs->ed_controlhead);
X writel(virt_to_bus(&dev->ed[ED_BULK]), &ohci->regs->ed_bulkhead);
+ */
+
+#if 0
+ printk(KERN_DEBUG "alloc_ohci(): controller\n");
+ show_ohci_status(ohci);
+#endif
+
+#if 0
+ printk(KERN_DEBUG "leaving alloc_ohci %p\n", ohci);
+#endif
X
X return ohci;
X } /* alloc_ohci() */
@@ -795,16 +1310,25 @@
X */
X static void release_ohci(struct ohci *ohci)
X {
+ printk(KERN_DEBUG "entering release_ohci %p\n", ohci);
+
+#ifdef OHCI_TIMER
+ /* stop our timer */
+ del_timer(&ohci_timer);
+#endif
X if (ohci->irq >= 0) {
X free_irq(ohci->irq, ohci);
X ohci->irq = -1;
X }
X
+ /* stop all OHCI interrupts */
+ writel(~0x0, &ohci->regs->intrdisable);
+
X if (ohci->root_hub) {
X /* ensure that HC is stopped before releasing the HCCA */
X writel(OHCI_USB_SUSPEND, &ohci->regs->control);
- free_pages((unsigned int) ohci->root_hub->hcca, 1);
- free_pages((unsigned int) ohci->root_hub, 1);
+ free_page((unsigned long) ohci->root_hub->hcca);
+ kfree(ohci->root_hub);
X ohci->root_hub->hcca = NULL;
X ohci->root_hub = NULL;
X }
@@ -812,20 +1336,26 @@
X /* unmap the IO address space */
X iounmap(ohci->regs);
X
+ kfree(ohci);
+
+ MOD_DEC_USE_COUNT;
+
X /* If the ohci itself were dynamic we'd free it here */
X
+ printk(KERN_DEBUG "usb-ohci: HC resources released.\n");
X } /* release_ohci() */
X
+
X /*
X * USB OHCI control thread
X */
X static int ohci_control_thread(void * __ohci)
X {
X struct ohci *ohci = (struct ohci *)__ohci;
-
+
X /*
X * I'm unfamiliar with the SMP kernel locking.. where should
- * this be released? -greg
+ * this be released and what does it do? -greg
X */
X lock_kernel();
X
@@ -833,7 +1363,7 @@
X * This thread doesn't need any user-level access,
X * so get rid of all of our resources..
X */
- printk("ohci_control_thread at %p\n", &ohci_control_thread);
+ printk("ohci_control_thread code at %p\n", &ohci_control_thread);
X exit_mm(current);
X exit_files(current);
X exit_fs(current);
@@ -843,23 +1373,64 @@
X /*
X * Damn the torpedoes, full speed ahead
X */
- start_hc(ohci);
- do {
+ if (start_hc(ohci) < 0) {
+ printk("usb-ohci: failed to start the controller\n");
+ release_ohci(ohci);
+ printk(KERN_DEBUG "leaving ohci_control_thread %p\n", __ohci);


+ return 0;
+ }
+

+ for(;;) {
+ siginfo_t info;
+ int unsigned long signr;
+
+ wait_ms(200);
+
+ /* check the root hub configuration for changes. */
+ ohci_check_configuration(ohci);
+
+ /* re-enable root hub status change interrupts. */
+#if 0


+ writel(OHCI_INTR_RHSC, &ohci->regs->intrenable);

+#endif
+
+ printk(KERN_DEBUG "ohci-control thread sleeping\n");
X interruptible_sleep_on(&ohci_configure);
X #ifdef CONFIG_APM
X if (apm_resume) {
X apm_resume = 0;
- start_hc(ohci);
+ if (start_hc(ohci) < 0)
+ break;
X continue;
X }
X #endif
- ohci_check_configuration(ohci);
- } while (!signal_pending(current));
X
- reset_hc(ohci);
+ /*
+ * If we were woken up by a signal, see if its useful,
+ * otherwise exit.
+ */
+ if (signal_pending(current)) {
+ /* sending SIGUSR1 makes us print out some info */
+ spin_lock_irq(&current->sigmask_lock);
+ signr = dequeue_signal(&current->blocked, &info);
+ spin_unlock_irq(&current->sigmask_lock);
+
+ if(signr == SIGUSR1) {
+ /* FIXME: have it do a full ed/td queue dump */
+ printk(KERN_DEBUG "OHCI status dump:\n");
+ show_ohci_status(ohci);
+ } else {
+ /* unknown signal, exit the thread */
+ break;
+ }
+ }
+ } /* for (;;) */
X
+ reset_hc(ohci);
X release_ohci(ohci);
- MOD_DEC_USE_COUNT;
+
+ printk(KERN_DEBUG "leaving ohci_control_thread %p\n", __ohci);
+
X return 0;
X } /* ohci_control_thread() */
X
@@ -892,10 +1463,28 @@
X break;
X }
X return 0;
-}
+} /* handle_apm_event() */
+#endif
+
+
+#ifdef OHCI_TIMER
+/*
+ * Inspired by Iñaky's driver. This function is a timer routine that
+ * is called OHCI_TIMER_FREQ times per second. It polls the root hub
+ * for status changes as on my system things are acting a bit odd at
+ * the moment..
+ */
+static void ohci_timer_func (unsigned long ohci_ptr)
+{
+ struct ohci *ohci = (struct ohci*)ohci_ptr;
+
+ ohci_root_hub_events(ohci);
+
+ /* press the snooze button... */
+ mod_timer(&ohci_timer, jiffies + (OHCI_TIMER_FREQ*HZ));
+} /* ohci_timer_func() */
X #endif
X
-/* ... */
X
X /*
X * Increment the module usage count, start the control thread and
@@ -906,32 +1495,50 @@
X int retval;
X struct ohci *ohci;
X
+#if 0
+ printk(KERN_DEBUG "entering found_ohci %d %p\n", irq, mem_base);
+#endif
+
X /* Allocate the running OHCI structures */
X ohci = alloc_ohci(mem_base);
- if (!ohci)
+ if (!ohci) {
X return -ENOMEM;
+ }
X
- printk("usb-ohci: alloc_ohci() = %p\n", ohci);
-
- reset_hc(ohci);
+#ifdef OHCI_TIMER
+ init_timer(&ohci_timer);
+ ohci_timer.expires = jiffies + (OHCI_TIMER_FREQ*HZ);
+ ohci_timer.data = (unsigned long)ohci;
+ ohci_timer.function = ohci_timer_func;
+#endif
X
X retval = -EBUSY;
X if (request_irq(irq, ohci_interrupt, SA_SHIRQ, "usb-ohci", ohci) == 0) {
X int pid;
X
- MOD_INC_USE_COUNT;
X ohci->irq = irq;
X
+#if 0
+ printk(KERN_DEBUG "usb-ohci: starting ohci-control thread\n");
+#endif
+
X /* fork off the handler */
X pid = kernel_thread(ohci_control_thread, ohci,
X CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
- if (pid >= 0)
+ if (pid >= 0) {


X return 0;
+ }
X

- MOD_DEC_USE_COUNT;
X retval = pid;
+ } else {
+ printk("usb-ohci: Couldn't allocate interrupt %d\n", irq);
X }
X release_ohci(ohci);
+
+#if 0
+ printk(KERN_DEBUG "leaving found_ohci %d %p\n", irq, mem_base);
+#endif
+
X return retval;
X } /* found_ohci() */
X
@@ -941,35 +1548,44 @@
X */
X static int init_ohci(struct pci_dev *dev)
X {
- unsigned int mem_base = dev->base_address[0];
+ unsigned long mem_base = dev->base_address[0];
X
- printk("usb-ohci: mem_base is %p\n", (void*)mem_base);
-
X /* If its OHCI, its memory */
X if (mem_base & PCI_BASE_ADDRESS_SPACE_IO)
X return -ENODEV;
X
X /* Get the memory address and map it for IO */
X mem_base &= PCI_BASE_ADDRESS_MEM_MASK;
+
+ /* no interrupt won't work... */
+ if (dev->irq == 0) {
+ printk("usb-ohci: no irq assigned? check your BIOS settings.\n");


+ return -ENODEV;
+ }
+

X /*
X * FIXME ioremap_nocache isn't implemented on all CPUs (such
X * as the Alpha) [?] What should I use instead...
X *
X * The iounmap() is done on in release_ohci.
X */
- mem_base = (unsigned int) ioremap_nocache(mem_base, 4096);
+ mem_base = (unsigned long) ioremap_nocache(mem_base, 4096);
X
X if (!mem_base) {
X printk("Error mapping OHCI memory\n");
X return -EFAULT;
X }
+ MOD_INC_USE_COUNT;
X
- return found_ohci(dev->irq, (void *) mem_base);
-} /* init_ohci() */
+ if (found_ohci(dev->irq, (void *) mem_base) < 0) {
+ MOD_DEC_USE_COUNT;


+ return -1;
+ }
X

+ return 0;
+} /* init_ohci() */
X
X #ifdef MODULE
-
X /*
X * Clean up when unloading the module
X */
@@ -978,6 +1594,10 @@
X #ifdef CONFIG_APM
X apm_unregister_callback(&handle_apm_event);
X #endif


+#ifdef CONFIG_USB_MOUSE
+ usb_mouse_cleanup();
+#endif

+ printk("usb-ohci: module unloaded\n");
X }
X
X #define ohci_init init_module
@@ -1005,6 +1625,8 @@
X return -ENODEV;
X }
X
+ printk("OHCI USB Driver loading\n");
+
X retval = -ENODEV;
X for (;;) {
X /* Find an OHCI USB controller */
@@ -1024,9 +1646,16 @@
X
X /* TODO check module params here to determine what to load */
X
-/* usb_mouse_init(); */
-/* usb_kbd_init();
- hub_init(); */


+#ifdef CONFIG_USB_MOUSE
+ usb_mouse_init();
+#endif
+#ifdef CONFIG_USB_KBD
+ usb_kbd_init();
+#endif
+ hub_init();
+#ifdef CONFIG_USB_AUDIO
+ usb_audio_init();
+#endif

X #ifdef CONFIG_APM
X apm_register_callback(&handle_apm_event);
X #endif
@@ -1034,7 +1663,7 @@
X return 0; /* no error */
X }
X return retval;
-} /* init_module() */
+} /* ohci_init */


X
X /* vim:sw=8

X */
diff -u --recursive --new-file v2.2.7/linux/drivers/usb/ohci.h linux/drivers/usb/ohci.h
--- v2.2.7/linux/drivers/usb/ohci.h Wed Apr 28 11:37:30 1999
+++ linux/drivers/usb/ohci.h Tue May 11 10:04:03 1999
@@ -6,7 +6,7 @@
X *
X * (C) Copyright 1999 Gregory P. Smith <gr...@electricrain.com>
X *
- * $Id: ohci.h,v 1.6 1999/04/24 22:50:06 greg Exp $
+ * $Id: ohci.h,v 1.15 1999/05/09 23:25:49 greg Exp $
X */
X
X #include <linux/list.h>
@@ -14,50 +14,65 @@
X
X #include "usb.h"
X
+struct ohci_ed;
+
X /*
X * Each TD must be aligned on a 16-byte boundary. From the OHCI v1.0 spec
X * it does not state that TDs must be contiguious in memory (due to the
X * use of the next_td field). This gives us extra room at the end of a
X * TD for our own driver specific data.
X *
- * This structure's size must be a multiple of 16 bytes.
+ * This structure's size must be a multiple of 16 bytes. ?? no way, I
+ * don't see why. Alignment should be all that matters.
X */
X struct ohci_td {
X /* OHCI Hardware fields */
- __u32 info;
- __u32 cur_buf; /* Current Buffer Pointer */
- __u32 next_td; /* Next TD Pointer */
- __u32 buf_end; /* Memory Buffer End Pointer */
+ __u32 info; /* TD status & type flags */
+ __u32 cur_buf; /* Current Buffer Pointer (bus address) */
+ __u32 next_td; /* Next TD Pointer (bus address) */
+ __u32 buf_end; /* Memory Buffer End Pointer (bus address) */
X
X /* Driver specific fields */
- struct list_head irq_list; /* Active interrupt list */
+ struct ohci_ed *ed; /* address of the ED this TD is on */
+ struct ohci_td *next_dl_td; /* used during donelist processing */
+ void *data; /* virt. address of the the buffer */
X usb_device_irq completed; /* Completion handler routine */
- void *data; /* XXX ? */
- void *dev_id; /* XXX ? */
- __u32 ed_bus; /* bus address of original ED */
-} __attribute((aligned(32)));
+ int allocated; /* boolean: is this TD allocated? */
+
+ /* User or Device class driver specific fields */
+ void *dev_id; /* user defined pointer passed to irq handler */
+} __attribute((aligned(16)));
X
X #define OHCI_TD_ROUND (1 << 18) /* buffer rounding bit */
-#define OHCI_TD_D (3 << 11) /* direction of xfer: */
-#define OHCI_TD_D_IN (2 << 11)
-#define OHCI_TD_D_OUT (1 << 11)
-#define OHCI_TD_D_SETUP (0)
+#define OHCI_TD_D (3 << 19) /* direction of xfer: */
+#define OHCI_TD_D_IN (2 << 19)
+#define OHCI_TD_D_OUT (1 << 19)
+#define OHCI_TD_D_SETUP (0 << 19)
X #define td_set_dir_in(d) ((d) ? OHCI_TD_D_IN : OHCI_TD_D_OUT )
X #define td_set_dir_out(d) ((d) ? OHCI_TD_D_OUT : OHCI_TD_D_IN )
X #define OHCI_TD_IOC_DELAY (7 << 21) /* frame delay allowed before int. */
X #define OHCI_TD_IOC_OFF (OHCI_TD_IOC_DELAY) /* no interrupt on complete */
X #define OHCI_TD_DT (3 << 24) /* data toggle bits */
+#define TOGGLE_AUTO (0 << 24) /* automatic (from the ED) */
+#define TOGGLE_DATA0 (2 << 24) /* force Data0 */
+#define TOGGLE_DATA1 (3 << 24) /* force Data1 */
X #define td_force_toggle(b) (((b) | 2) << 24)
X #define OHCI_TD_ERRCNT (3 << 26) /* error count */
-#define td_errorcount(td) (((td) >> 26) & 3)
+#define td_errorcount(td) (((td).info >> 26) & 3)
X #define OHCI_TD_CC (0xf << 28) /* condition code */
+#define OHCI_TD_CC_GET(td_i) (((td_i) >> 28) & 0xf)
X #define OHCI_TD_CC_NEW (OHCI_TD_CC) /* set this on all unaccessed TDs! */
-#define td_cc_notaccessed(td) ((td >> 29) == 7)
-#define td_cc_accessed(td) ((td >> 29) != 7)
-#define td_cc_noerror(td) (((td) & OHCI_TD_CC) == 0)
+#define td_cc_notaccessed(td) (((td).info >> 29) == 7)
+#define td_cc_accessed(td) (((td).info >> 29) != 7)
+#define td_cc_noerror(td) ((((td).info) & OHCI_TD_CC) == 0)
X #define td_active(td) (!td_cc_noerror((td)) && (td_errorcount((td)) < 3))
X #define td_done(td) (td_cc_noerror((td)) || (td_errorcount((td)) == 3))
X
+#define td_allocated(td) ((td).allocated)
+#define allocate_td(td) ((td)->allocated = 1)
+#define ohci_free_td(td) ((td)->allocated = 0)
+
+
X /*
X * The endpoint descriptors also requires 16-byte alignment
X */
@@ -65,10 +80,16 @@
X /* OHCI hardware fields */
X __u32 status;
X __u32 tail_td; /* TD Queue tail pointer */
- __u32 head_td; /* TD Queue head pointer */
+ __u32 _head_td; /* TD Queue head pointer, toggle carry & halted bits */
X __u32 next_ed; /* Next ED */
X } __attribute((aligned(16)));
X
+/* get the head_td */
+#define ed_head_td(ed) ((ed)->_head_td & 0xfffffff0)
+
+/* save the carry flag while setting the head_td */
+#define set_ed_head_td(ed, td) ((ed)->_head_td = (td) | ((ed)->_head_td & 3))
+
X #define OHCI_ED_SKIP (1 << 14)
X #define OHCI_ED_MPS (0x7ff << 16)
X /* FIXME: should cap at the USB max packet size [0x4ff] */
@@ -90,10 +111,10 @@
X
X /* NOTE: bits 27-31 of the status dword are reserved for the driver */
X /*
- * We'll use this status flag for the non-predefined EDs to mark if
- * they're in use or not.
+ * We'll use this status flag for to mark if an ED is in use by the
+ * driver or not. If the bit is set, it is used.
X *
- * FIXME: unimplemented (needed?)
+ * FIXME: implement this!
X */
X #define ED_USED (1 << 31)
X
@@ -174,8 +195,8 @@
X
X /*
X * Given a period p in ms, convert it to the closest endpoint
- * interrupt frequency; rounding down. I'm sure many feel that this
- * is a gross macro. Feel free to toss it for actual code.
+ * interrupt frequency; rounding down. This is a gross macro.
+ * Feel free to toss it for actual code. (gasp!)
X */
X #define ms_to_ed_int(p) \
X ((p >= 32) ? ED_INT_32 : \
@@ -257,6 +278,15 @@
X #define PORT_OCIC (1 << 19) /* port over current indicator chg */
X #define PORT_PRSC (1 << 20) /* port reset status change */
X
+/*
+ * Root Hub status register masks
+ */
+#define OHCI_ROOT_LPS (1) /* turn off root hub ports power */
+#define OHCI_ROOT_OCI (1 << 1) /* Overcurrent Indicator */
+#define OHCI_ROOT_DRWE (1 << 15) /* Device remote wakeup enable */
+#define OHCI_ROOT_LPSC (1 << 16) /* turn on root hub ports power */
+#define OHCI_ROOT_OCIC (1 << 17) /* Overcurrent indicator change */
+#define OHCI_ROOT_CRWE (1 << 31) /* Clear RemoteWakeupEnable */
X
X /*
X * Interrupt register masks
@@ -276,6 +306,19 @@
X */
X #define OHCI_USB_OPER (2 << 6)
X #define OHCI_USB_SUSPEND (3 << 6)
+#define OHCI_USB_PLE (1 << 2) /* Periodic (interrupt) list enable */
+#define OHCI_USB_IE (1 << 3) /* Isochronous list enable */
+#define OHCI_USB_CLE (1 << 4) /* Control list enable */
+#define OHCI_USB_BLE (1 << 5) /* Bulk list enable */
+
+/*
+ * Command status register masks
+ */
+#define OHCI_CMDSTAT_HCR (1)
+#define OHCI_CMDSTAT_CLF (1 << 1)
+#define OHCI_CMDSTAT_BLF (1 << 2)
+#define OHCI_CMDSTAT_OCR (1 << 3)
+#define OHCI_CMDSTAT_SOC (3 << 16)
X
X /*
X * This is the full ohci controller description
@@ -291,10 +334,15 @@
X struct list_head interrupt_list; /* List of interrupt active TDs for this OHCI */
X };
X
+#define OHCI_TIMER
+#define OHCI_TIMER_FREQ (1) /* frequency of OHCI status checks */
+
X /* Debugging code */
-void show_ed(struct ohci_ed *ed);
-void show_td(struct ohci_td *td);
-void show_status(struct ohci *ohci);
+void show_ohci_ed(struct ohci_ed *ed);
+void show_ohci_td(struct ohci_td *td);
+void show_ohci_status(struct ohci *ohci);
+void show_ohci_device(struct ohci_device *dev);
+void show_ohci_hcca(struct ohci_hcca *hcca);
X
X #endif
X /* vim:sw=8
diff -u --recursive --new-file v2.2.7/linux/drivers/usb/restart linux/drivers/usb/restart
--- v2.2.7/linux/drivers/usb/restart Wed Apr 28 11:37:30 1999
+++ linux/drivers/usb/restart Tue May 11 10:04:03 1999
@@ -11,25 +11,28 @@
X # fi
X #fi
X
-UPID=`ps aux | grep uhci-control | grep -v grep | awk '{print $2}'`
+UPID=`ps aux | grep ohci-control | grep -v grep | awk '{print $2}'`
X if test "$UPID"; then
X echo "$ME: killing $UPID"
X kill $UPID
X fi
X
-UMOD=`lsmod | grep '^usb-uhci' | grep -v grep`
+UMOD=`lsmod | grep '^usb-ohci' | grep -v grep`
X if test "$UMOD"; then
- echo "$ME: removing usb-uhci.o"
+ echo "$ME: removing usb-ohci.o"
X sleep 1
- if ! rmmod usb-uhci; then
- echo "$ME: cannot remove usb-uhci.o"
+ if ! rmmod usb-ohci; then
+ echo "$ME: cannot remove usb-ohci.o"
X exit 1


X fi
X fi
X

X dmesg -c > /dev/null
X
-echo "$ME: starting usb-uhci.o"
-insmod -m usb-uhci.o > usb-uhci.map
-#echo "$ME: starting bp-mouse.o"
-#insmod -m bp-mouse.o > bp-mouse.map
+echo "$ME: starting usb-ohci.o"
+insmod -m usb-ohci.o > usb-ohci.map
+
+sleep 1
+UPID=`ps aux | grep ohci-control | grep -v grep | awk '{print $2}'`
+if test "$UPID"; then echo "$ME: ohci-control is pid $UPID" ; fi
+
diff -u --recursive --new-file v2.2.7/linux/drivers/usb/stopusb linux/drivers/usb/stopusb
--- v2.2.7/linux/drivers/usb/stopusb Wed Apr 28 11:37:30 1999
+++ linux/drivers/usb/stopusb Tue May 11 10:04:03 1999
@@ -1,8 +1,7 @@
X #!/bin/sh
X
-killall uhci-control
-killall khubd
+killall ohci-control
X
-sleep 1
+sleep 2
X
-rmmod usb-uhci
+rmmod usb-ohci
diff -u --recursive --new-file v2.2.7/linux/drivers/usb/uhci.c linux/drivers/usb/uhci.c
--- v2.2.7/linux/drivers/usb/uhci.c Wed Apr 28 11:37:30 1999
+++ linux/drivers/usb/uhci.c Fri Apr 30 08:20:53 1999
@@ -47,9 +47,6 @@
X
X #define compile_assert(x) do { switch (0) { case 1: case !(x): } } while (0)
X
-int usb_mouse_init(void);
-int hub_init(void);
-
X static struct wait_queue *uhci_configure = NULL;
X
X /*
@@ -515,6 +512,7 @@
X
X dev = kmalloc(sizeof(*dev), GFP_KERNEL);
X if (!dev) {
+ usb_destroy_configuration(usb_dev);
X kfree(usb_dev);
X return NULL;
X }
@@ -573,6 +571,7 @@
X }
X
X kfree(dev);
+ usb_destroy_configuration(usb_dev);
X kfree(usb_dev);
X
X return 0;
@@ -995,6 +994,8 @@
X kfree(uhci);
X }
X
+void cleanup_drivers(void);
+
X static int uhci_control_thread(void * __uhci)
X {
X struct uhci *uhci = (struct uhci *)__uhci;
@@ -1052,6 +1053,8 @@
X usb_disconnect(uhci->root_hub->usb->children + i);
X #endif
X
+ cleanup_drivers();
+
X reset_hc(uhci);
X release_region(uhci->io_addr, 32);
X
@@ -1199,4 +1202,12 @@
X return 0;
X }
X return retval;


+}
+
+void cleanup_drivers(void)
+{
+ hub_cleanup();
+#ifdef CONFIG_USB_MOUSE
+ usb_mouse_cleanup();
+#endif

X }
diff -u --recursive --new-file v2.2.7/linux/drivers/usb/usb.c linux/drivers/usb/usb.c
--- v2.2.7/linux/drivers/usb/usb.c Wed Apr 28 11:37:30 1999
+++ linux/drivers/usb/usb.c Fri May 7 15:16:04 1999
@@ -213,6 +213,15 @@


X return -1;
X }
X

+ interface->endpoint = (struct usb_endpoint_descriptor *)
+ kmalloc(interface->bNumEndpoints * sizeof(struct usb_endpoint_descriptor), GFP_KERNEL);
+ if(interface->endpoint==NULL)
+ {
+ printk(KERN_WARNING "usb: out of memory.\n");
+ return -1;
+ }
+ memset(interface->endpoint, 0, interface->bNumEndpoints*sizeof(struct usb_endpoint_descriptor));
+
X for (i = 0; i < interface->bNumEndpoints; i++) {
X // if(((USB_DT_HID << 8) | 9) == *(unsigned short*)(ptr + parsed)) {
X // parsed += 9; /* skip over the HID descriptor for now */
@@ -242,8 +251,18 @@
X {
X printk(KERN_WARNING "usb: too many interfaces.\n");
X return -1;
+
X }
X
+ config->interface = (struct usb_interface_descriptor *)
+ kmalloc(config->bNumInterfaces * sizeof(struct usb_interface_descriptor), GFP_KERNEL);
+ if(config->interface==NULL)
+ {
+ printk(KERN_WARNING "usb: out of memory.\n");
+ return -1;
+ }
+ memset(config->interface, 0, config->bNumInterfaces*sizeof(struct usb_interface_descriptor));
+
X for (i = 0; i < config->bNumInterfaces; i++) {
X int retval = usb_parse_interface(dev, config->interface + i, ptr + parsed, len);
X if (retval < 0)
@@ -266,6 +285,14 @@


X return -1;
X }
X

+ dev->config = (struct usb_config_descriptor *)
+ kmalloc(dev->descriptor.bNumConfigurations * sizeof(struct usb_config_descriptor), GFP_KERNEL);
+ if(dev->config==NULL)
+ {
+ printk(KERN_WARNING "usb: out of memory.\n");
+ return -1;
+ }
+ memset(dev->config, 0, dev->descriptor.bNumConfigurations*sizeof(struct usb_config_descriptor));
X for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
X int retval = usb_parse_config(dev, dev->config + i, ptr, bytes);
X if (retval < 0)
@@ -276,6 +303,31 @@


X return 0;
X }
X

+void usb_destroy_configuration(struct usb_device *dev)
+{
+ int c, i;
+ struct usb_config_descriptor *cf;
+ struct usb_interface_descriptor *ifp;
+
+ if(dev->config==NULL)
+ return;
+ for(c=0;c<dev->descriptor.bNumConfigurations;c++)
+ {
+ cf=&dev->config[c];
+ if(cf->interface==NULL)
+ break;
+ for(i=0;i<cf->bNumInterfaces;i++)
+ {
+ ifp=&cf->interface[i];
+ if(ifp->endpoint==NULL)
+ break;
+ kfree(ifp->endpoint);
+ }
+ kfree(cf->interface);
+ }
+ kfree(dev->config);
+}
+
X void usb_init_root_hub(struct usb_device *dev)
X {
X dev->devnum = -1;
@@ -517,24 +569,29 @@
X
X int usb_get_configuration(struct usb_device *dev)
X {
- unsigned int size;
+ unsigned int cfgno,size;
X unsigned char buffer[400];
-
- /* Get the first 8 bytes - guaranteed */
- if (usb_get_descriptor(dev, USB_DT_CONFIG, 0, buffer, 8))
- return -1;
-
- /* Get the full buffer */
- size = *(unsigned short *)(buffer+2);
- if (size > sizeof(buffer))
- {
- printk(KERN_INFO "usb: truncated DT_CONFIG (want %d).\n", size);
- size = sizeof(buffer);
+ unsigned char * bufptr;
+
+ bufptr=buffer;
+ for (cfgno=0;cfgno<dev->descriptor.bNumConfigurations;cfgno++) {
+ /* Get the first 8 bytes - guaranteed */
+ if (usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, bufptr, 8))
+ return -1;
+
+ /* Get the full buffer */
+ size = *(unsigned short *)(bufptr+2);
+ if (bufptr+size > buffer+sizeof(buffer))
+ {
+ printk(KERN_INFO "usb: truncated DT_CONFIG (want %d).\n", size);
+ size = buffer+sizeof(buffer)-bufptr;
+ }
+ if (usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, bufptr, size))
+ return -1;
+
+ /* Prepare for next configuration */
+ bufptr+=size;
X }
-
- if (usb_get_descriptor(dev, USB_DT_CONFIG, 0, buffer, size))
- return -1;
-
X return usb_parse_configuration(dev, buffer, size);
X }
X
diff -u --recursive --new-file v2.2.7/linux/drivers/usb/usb.h linux/drivers/usb/usb.h
--- v2.2.7/linux/drivers/usb/usb.h Wed Apr 28 11:37:30 1999
+++ linux/drivers/usb/usb.h Tue May 11 10:04:03 1999
@@ -1,6 +1,7 @@
X #ifndef __LINUX_USB_H
X #define __LINUX_USB_H
X
+#include <linux/config.h>
X #include <linux/types.h>
X #include <linux/list.h>
X #include <linux/sched.h>
@@ -8,7 +9,7 @@
X static __inline__ void wait_ms(unsigned int ms)
X {
X current->state = TASK_UNINTERRUPTIBLE;
- schedule_timeout(1 + ms / 10);
+ schedule_timeout(1 + ms * HZ / 1000);
X }
X
X
@@ -99,17 +100,11 @@
X *
X * USB device information
X *
- * Make this MUCH dynamic, right now
- * it contains enough information for
- * a USB floppy controller, and nothing
- * else.
- *
- * I'm not proud. I just want this dang
- * thing to start working.
X */
-#define USB_MAXCONFIG 2
-#define USB_MAXINTERFACES 8
-#define USB_MAXENDPOINTS 4


SHAR_EOF
true || echo 'restore of patch-2.2.8 failed'
fi

echo 'End of part 24'
echo 'File patch-2.2.8 is continued in part 25'
echo 25 > _shar_seq_.tmp

Thomas...@ciw.uni-karlsruhe.de

unread,
May 12, 1999, 3:00:00 AM5/12/99
to
Archive-name: v2.2/patch-2.2.8/part25

#!/bin/sh
# this is part 25 of a 33 - part archive


# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.8 continued
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 25; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.8'
else
echo 'x - continuing with patch-2.2.8'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.8' &&

+
+#define USB_MAXCONFIG 8
+#define USB_MAXINTERFACES 32
+#define USB_MAXENDPOINTS 32
X
X struct usb_device_descriptor {
X __u8 bLength;
@@ -136,6 +131,7 @@
X __u8 bmAttributes;
X __u16 wMaxPacketSize;
X __u8 bInterval;
+ void *audio;
X };
X
X /* Interface descriptor */
@@ -150,7 +146,8 @@
X __u8 bInterfaceProtocol;
X __u8 iInterface;
X
- struct usb_endpoint_descriptor endpoint[USB_MAXENDPOINTS];
+ struct usb_endpoint_descriptor *endpoint;
+ void *audio;
X };
X
X /* Configuration descriptor information.. */
@@ -164,7 +161,7 @@
X __u8 bmAttributes;
X __u8 MaxPower;
X
- struct usb_interface_descriptor interface[USB_MAXINTERFACES];
+ struct usb_interface_descriptor *interface;
X };
X
X /* String descriptor */
@@ -197,6 +194,14 @@
X
X /*
X * Pointer to a device endpoint interrupt function -greg
+ * Parameters:
+ * int status - This needs to be defined. Right now each HCD
+ * passes different transfer status bits back. Don't use it
+ * until we come up with a common meaning.
+ * void *buffer - This is a pointer to the data used in this
+ * USB transfer.
+ * void *dev_id - This is a user defined pointer set when the IRQ
+ * is requested that is passed back.
X */
X typedef int (*usb_device_irq)(int, void *, void *);


X
@@ -228,7 +233,7 @@

X struct usb_bus *bus; /* Bus we're apart of */
X struct usb_driver *driver; /* Driver */
X struct usb_device_descriptor descriptor; /* Descriptor */
- struct usb_config_descriptor config[USB_MAXCONFIG]; /* All of the configs */
+ struct usb_config_descriptor *config; /* All of the configs */
X struct usb_device *parent;
X
X /*
@@ -363,8 +368,8 @@
X void usb_audio_interface(struct usb_interface_descriptor *, u8 *);
X void usb_audio_endpoint(struct usb_endpoint_descriptor *, u8 *);
X #else
-extern inline void usb_audio_interface(struct usb_interface_descriptor *, u8 *) {}
-extern inline void usb_audio_endpoint(struct usb_endpoint_descriptor *, u8 *) {}
+extern inline void usb_audio_interface(struct usb_interface_descriptor *interface, u8 *data) {}
+extern inline void usb_audio_endpoint(struct usb_endpoint_descriptor *interface, u8 *data) {}
X #endif
X
X #endif
diff -u --recursive --new-file v2.2.7/linux/drivers/video/matroxfb.c linux/drivers/video/matroxfb.c
--- v2.2.7/linux/drivers/video/matroxfb.c Wed Apr 28 11:37:30 1999
+++ linux/drivers/video/matroxfb.c Thu Apr 29 12:53:48 1999
@@ -57,6 +57,9 @@
X * "H. Peter Arvin" <h...@transmeta.com>
X * Ideas
X *
+ * "Cort Dougan" <co...@cs.nmt.edu>
+ * CHRP fixes and PReP cleanup
+ *
X * (following author is not in any relation with this code, but his code
X * is included in this driver)
X *
@@ -187,14 +190,8 @@
X #if defined(__m68k__)
X #define MAP_BUSTOVIRT
X #else
-#if defined(CONFIG_PPC) && defined(CONFIG_PREP) && defined(_ISA_MEM_BASE)
-/* do not tell me that PPC is not broken... if ioremap() oops with
- invalid value written to msr... */
-#define MAP_ISAMEMBASE
-#else
X #define MAP_IOREMAP
X #endif
-#endif
X
X #ifdef DEBUG
X #define dprintk(X...) printk(X)
@@ -354,11 +351,7 @@
X #ifdef MAP_BUSTOVIRT
X virt->vaddr = bus_to_virt(phys);
X #else
-#ifdef MAP_ISAMEMBASE
- virt->vaddr = (void*)(phys + _ISA_MEM_BASE);
-#else
X #error "Your architecture does not have neither ioremap nor bus_to_virt... Giving up"
-#endif
X #endif
X #endif
X return (virt->vaddr == 0); /* 0, !0... 0, error_code in future */
diff -u --recursive --new-file v2.2.7/linux/drivers/video/offb.c linux/drivers/video/offb.c
--- v2.2.7/linux/drivers/video/offb.c Tue Mar 23 14:35:48 1999
+++ linux/drivers/video/offb.c Thu Apr 29 12:53:48 1999
@@ -476,9 +476,7 @@
X printk("no framebuffer address found for %s\n", dp->full_name);
X return;
X }
- /* needed for the gxt on the f50 -- Cort */
- if ( dp->addrs[i].address < isa_mem_base )
- (u_long)dp->addrs[i].address += isa_mem_base;
+
X address = (u_long)dp->addrs[i].address;
X
X /* kludge for valkyrie */
@@ -487,6 +485,7 @@
X }
X offb_init_fb(dp->name, dp->full_name, width, height, depth,
X pitch, address);
+
X }
X
X __initfunc(static void offb_init_fb(const char *name, const char *full_name,
diff -u --recursive --new-file v2.2.7/linux/drivers/video/vesafb.c linux/drivers/video/vesafb.c
--- v2.2.7/linux/drivers/video/vesafb.c Fri Apr 16 14:47:31 1999
+++ linux/drivers/video/vesafb.c Tue May 11 09:55:45 1999
@@ -21,7 +21,6 @@
X #include <linux/selection.h>
X #include <linux/ioport.h>
X #include <linux/init.h>
-#include <linux/config.h>
X
X #include <asm/io.h>
X #include <asm/mtrr.h>
@@ -635,10 +634,8 @@
X video_cmap_len = 256;
X }
X request_region(0x3c0, 32, "vga+");
-#ifdef CONFIG_MTRR
X if (mtrr)
X mtrr_add((unsigned long)video_base, video_size, MTRR_TYPE_WRCOMB, 1);
-#endif
X
X strcpy(fb_info.modename, "VESA VGA");
X fb_info.changevar = NULL;
diff -u --recursive --new-file v2.2.7/linux/fs/adfs/namei.c linux/fs/adfs/namei.c
--- v2.2.7/linux/fs/adfs/namei.c Wed Apr 28 11:37:30 1999
+++ linux/fs/adfs/namei.c Mon May 10 14:14:28 1999
@@ -46,7 +46,7 @@
X unsigned long parent_object_id, dir_object_id;
X int buffers, pos;
X
- if (!dir || !S_ISDIR(dir->i_mode))
+ if (!S_ISDIR(dir->i_mode))
X return 0;
X
X sb = dir->i_sb;
diff -u --recursive --new-file v2.2.7/linux/fs/autofs/root.c linux/fs/autofs/root.c
--- v2.2.7/linux/fs/autofs/root.c Wed Apr 28 11:37:30 1999
+++ linux/fs/autofs/root.c Sat May 8 17:56:37 1999
@@ -168,7 +168,7 @@
X * yet completely filled in, and revalidate has to delay such
X * lookups..
X */
-static int autofs_revalidate(struct dentry * dentry)
+static int autofs_revalidate(struct dentry * dentry, int flags)
X {
X struct inode * dir = dentry->d_parent->d_inode;
X struct autofs_sb_info *sbi = autofs_sbi(dir->i_sb);
@@ -241,7 +241,7 @@
X d_add(dentry, NULL);
X
X up(&dir->i_sem);
- autofs_revalidate(dentry);
+ autofs_revalidate(dentry, 0);
X down(&dir->i_sem);
X
X /*
diff -u --recursive --new-file v2.2.7/linux/fs/binfmt_aout.c linux/fs/binfmt_aout.c
--- v2.2.7/linux/fs/binfmt_aout.c Tue Mar 23 14:35:48 1999
+++ linux/fs/binfmt_aout.c Mon May 10 13:01:21 1999
@@ -58,8 +58,19 @@
X * These are the only things you should do on a core-file: use only these
X * macros to write out all the necessary info.
X */
-#define DUMP_WRITE(addr,nr) \
-while (file->f_op->write(file,(char *)(addr),(nr),&file->f_pos) != (nr)) goto close_coredump
+
+static int dump_write(struct file *file, const void *addr, int nr)
+{
+ int r;
+ down(&file->f_dentry->d_inode->i_sem);
+ r = file->f_op->write(file, addr, nr, &file->f_pos) == nr;
+ up(&file->f_dentry->d_inode->i_sem);
+ return r;
+}
+
+#define DUMP_WRITE(addr, nr) \
+ if (!dump_write(file, (void *)(addr), (nr))) \
+ goto close_coredump;
X
X #define DUMP_SEEK(offset) \
X if (file->f_op->llseek) { \
diff -u --recursive --new-file v2.2.7/linux/fs/binfmt_elf.c linux/fs/binfmt_elf.c
--- v2.2.7/linux/fs/binfmt_elf.c Tue Mar 23 14:35:48 1999
+++ linux/fs/binfmt_elf.c Mon May 10 13:01:21 1999
@@ -927,7 +927,11 @@
X */
X static int dump_write(struct file *file, const void *addr, int nr)
X {
- return file->f_op->write(file, addr, nr, &file->f_pos) == nr;
+ int r;
+ down(&file->f_dentry->d_inode->i_sem);
+ r = file->f_op->write(file, addr, nr, &file->f_pos) == nr;
+ up(&file->f_dentry->d_inode->i_sem);
+ return r;
X }
X
X static int dump_seek(struct file *file, off_t off)
diff -u --recursive --new-file v2.2.7/linux/fs/buffer.c linux/fs/buffer.c
--- v2.2.7/linux/fs/buffer.c Wed Apr 28 11:37:30 1999
+++ linux/fs/buffer.c Tue May 11 09:55:49 1999
@@ -100,7 +100,8 @@
X each time we call refill */
X int nref_dirt; /* Dirty buffer threshold for activating bdflush
X when trying to refill buffers. */
- int dummy1; /* unused */
+ int interval; /* Interval (seconds) between spontaneous
+ bdflush runs */
X int age_buffer; /* Time for normal buffer to age before
X we flush it */
X int age_super; /* Time for superblock to age before we
@@ -109,10 +110,10 @@
X int dummy3; /* unused */
X } b_un;
X unsigned int data[N_PARAM];
-} bdf_prm = {{40, 500, 64, 256, 15, 30*HZ, 5*HZ, 1884, 2}};
+} bdf_prm = {{40, 500, 64, 256, 5, 30*HZ, 5*HZ, 1884, 2}};
X
X /* These are the min and max parameter values that we will allow to be assigned */
-int bdflush_min[N_PARAM] = { 0, 10, 5, 25, 0, 1*HZ, 1*HZ, 1, 1};
+int bdflush_min[N_PARAM] = { 0, 10, 5, 25, 1, 1*HZ, 1*HZ, 1, 1};
X int bdflush_max[N_PARAM] = {100,5000, 2000, 2000,100, 600*HZ, 600*HZ, 2047, 5};
X
X void wakeup_bdflush(int);
@@ -1553,7 +1554,6 @@
X * response to dirty buffers. Once this process is activated, we write back
X * a limited number of buffers to the disks and then go back to sleep again.
X */
-static struct wait_queue * bdflush_wait = NULL;
X static struct wait_queue * bdflush_done = NULL;
X struct task_struct *bdflush_tsk = 0;
X
@@ -1561,7 +1561,7 @@
X {
X if (current == bdflush_tsk)
X return;
- wake_up(&bdflush_wait);
+ wake_up_process(bdflush_tsk);
X if (wait) {
X run_task_queue(&tq_disk);
X sleep_on(&bdflush_done);
@@ -1570,82 +1570,107 @@
X
X
X /*
- * Here we attempt to write back old buffers. We also try to flush inodes
- * and supers as well, since this function is essentially "update", and
- * otherwise there would be no way of ensuring that these quantities ever
- * get written back. Ideally, we would have a timestamp on the inodes
- * and superblocks so that we could write back only the old ones as well
- */
+ * Here we attempt to write back old buffers.
+ * To prevent deadlocks for a loop device:
+ * 1) Do non-blocking writes to loop (avoids deadlock with running
+ * out of request blocks).
+ * 2) But do a blocking write if the only dirty buffers are loop buffers
+ * (otherwise we go into an infinite busy-loop).
+ * 3) Quit writing loop blocks if a freelist went low (avoids deadlock
+ * with running out of free buffers for loop's "real" device).
+*/
X
-static int sync_old_buffers(void)
+static inline void sync_old_buffers(void)
X {
X int i;
- int ndirty, nwritten;
- int nlist;
- int ncount;
- struct buffer_head * bh, *next;
-
- sync_supers(0);
- sync_inodes(0);
-
- ncount = 0;
+ int ndirty = 0;
+ int wrta_cmd = WRITEA;
X #ifdef DEBUG
- for(nlist = 0; nlist < NR_LIST; nlist++)
-#else
- for(nlist = BUF_LOCKED; nlist <= BUF_DIRTY; nlist++)
+ int ncount = 0, nwritten = 0;
X #endif
- {
- ndirty = 0;
- nwritten = 0;
- repeat:
+ struct buffer_head * bh, *next;
X
- bh = lru_list[nlist];
- if(bh)
- for (i = nr_buffers_type[nlist]; i-- > 0; bh = next) {
- /* We may have stalled while waiting for I/O to complete. */
- if(bh->b_list != nlist) goto repeat;
- next = bh->b_next_free;
- if(!lru_list[nlist]) {
- printk("Dirty list empty %d\n", i);
- break;
- }
-
- /* Clean buffer on dirty list? Refile it */
- if (nlist == BUF_DIRTY && !buffer_dirty(bh) && !buffer_locked(bh)) {
- refile_buffer(bh);
- continue;
- }
-
- /* Unlocked buffer on locked list? Refile it */
- if (nlist == BUF_LOCKED && !buffer_locked(bh)) {
- refile_buffer(bh);
- continue;
- }
-
- if (buffer_locked(bh) || !buffer_dirty(bh))
- continue;
- ndirty++;
- if(time_before(jiffies, bh->b_flushtime))
- continue;
- nwritten++;
- next->b_count++;
- bh->b_count++;
- bh->b_flushtime = 0;
X #ifdef DEBUG
- if(nlist != BUF_DIRTY) ncount++;
+ bh = lru_list[BUF_CLEAN];
+ if(bh)
+ for(i = nr_buffers_type[BUF_CLEAN]; --i > 0; bh = next) {
+ next = bh->b_next_free;
+
+ /* Dirty/locked buffer on clean list? Refile it */
+ if (buffer_locked(bh) || buffer_dirty(bh)) {
+ ncount++;
+ refile_buffer(bh);
+ }
+ }
X #endif
- ll_rw_block(WRITE, 1, &bh);
- bh->b_count--;
- next->b_count--;
- }
+
+ bh = lru_list[BUF_LOCKED];
+ if(bh)
+ for(i = nr_buffers_type[BUF_LOCKED]; --i > 0; bh = next) {
+ next = bh->b_next_free;
+
+ /* Unlocked buffer on locked list? Refile it */
+ if (!buffer_locked(bh))
+ refile_buffer(bh);
+ }
+
+ restart:
+ bh = lru_list[BUF_DIRTY];
+ if(bh)
+ for (i = nr_buffers_type[BUF_DIRTY];
+ i-- > 0 && ndirty < bdf_prm.b_un.ndirty;
+ bh = next) {
+ /* We may have stalled while waiting for
+ I/O to complete. */
+ if(bh->b_list != BUF_DIRTY)
+ goto restart;
+ next = bh->b_next_free;
+ if(!lru_list[BUF_DIRTY]) {
+ printk("Dirty list empty %d\n", i);
+ break;
+ }
+
+ /* Clean buffer on dirty list? Refile it */
+ if (!buffer_dirty(bh)) {
+ refile_buffer(bh);
+ continue;
+ }
+
+ if (buffer_locked(bh))
+ continue;
+ /* Should we write back buffers that are
+ shared or not?? Currently dirty buffers
+ are not shared, so it does not matter */
+ next->b_count++;
+ bh->b_count++;
+ ndirty++;
+ bh->b_flushtime = 0;
+ if (MAJOR(bh->b_dev) == LOOP_MAJOR) {
+ ll_rw_block(wrta_cmd,1, &bh);
+ wrta_cmd = WRITEA;
+ if (buffer_dirty(bh))
+ --ndirty;
+ }
+ else
+ ll_rw_block(WRITE, 1, &bh);
+ bh->b_count--;
+ next->b_count--;
+ }
+ /* If we didn't write anything, but there are still
+ * dirty buffers, then make the next write to a
+ * loop device to be a blocking write.
+ * This lets us block--which we _must_ do! */
+ if (ndirty == 0
+ && nr_buffers_type[BUF_DIRTY] > 0 && wrta_cmd != WRITE) {
+ wrta_cmd = WRITE;
+ goto restart;
X }
- run_task_queue(&tq_disk);
+
X #ifdef DEBUG
X if (ncount) printk("sync_old_buffers: %d dirty buffers not on dirty list\n", ncount);
- printk("Wrote %d/%d buffers\n", nwritten, ndirty);
+ printk("wrote %d/%d buffers...", nwritten, ndirty);
X #endif
X run_task_queue(&tq_disk);
- return 0;
X }
X
X
@@ -1662,10 +1687,12 @@
X if (!capable(CAP_SYS_ADMIN))
X goto out;
X
- if (func == 1) {
- error = sync_old_buffers();
- goto out;
- }
+ if (func == 1)
+ /* Func 1 used to call sync_old_buffers; a user space
+ daemon would call it periodically. This is no
+ longer necessary. Returning -EPERM here makes the
+ daemon silently exit. */
+ goto out;
X
X /* Basically func 1 means read param 1, 2 means write param 1, etc */
X if (func >= 2) {
@@ -1694,27 +1721,17 @@
X return error;
X }
X
-/* This is the actual bdflush daemon itself. It used to be started from
- * the syscall above, but now we launch it ourselves internally with
- * kernel_thread(...) directly after the first thread in init/main.c */
+/* This is the actual bdflush daemon itself. It used to be started
+ * from the syscall above, but now we launch it ourselves internally
+ * with kernel_thread(...) directly after the first thread in
+ * init/main.c. Every so often, or when woken up by another task that
+ * needs memory, we call sync_old_buffers to partially clear the dirty list.
+ */
X
-/* To prevent deadlocks for a loop device:
- * 1) Do non-blocking writes to loop (avoids deadlock with running
- * out of request blocks).
- * 2) But do a blocking write if the only dirty buffers are loop buffers
- * (otherwise we go into an infinite busy-loop).
- * 3) Quit writing loop blocks if a freelist went low (avoids deadlock
- * with running out of free buffers for loop's "real" device).
-*/
X int bdflush(void * unused)
X {
- int i;
- int ndirty;
- int nlist;
- int ncount;
- struct buffer_head * bh, *next;
- int major;
- int wrta_cmd = WRITEA; /* non-blocking write for LOOP */
+ long remaining = HZ * bdf_prm.b_un.interval;
+ struct task_struct *tsk = current;
X
X /*
X * We have a bare-bones task_struct, and really should fill
@@ -1722,10 +1739,12 @@
X * display semi-sane things. Not real crucial though...
X */
X
- current->session = 1;
- current->pgrp = 1;
- sprintf(current->comm, "kflushd");
- bdflush_tsk = current;
+ tsk->session = 1;
+ tsk->pgrp = 1;
+ tsk->dumpable = 0; /* inhibit ptrace() */
+ strcpy(tsk->comm, "kflushd");
+ sigfillset(&tsk->blocked);
+ bdflush_tsk = tsk;
X
X /*
X * As a kernel thread we want to tamper with system buffers
@@ -1735,93 +1754,36 @@
X lock_kernel();
X
X for (;;) {
+ tsk->state = TASK_INTERRUPTIBLE;
+ remaining = schedule_timeout(remaining);
+
X #ifdef DEBUG
X printk("bdflush() activated...");
X #endif
-
X CHECK_EMERGENCY_SYNC
X
- ncount = 0;
-#ifdef DEBUG
- for(nlist = 0; nlist < NR_LIST; nlist++)
-#else
- for(nlist = BUF_LOCKED; nlist <= BUF_DIRTY; nlist++)
-#endif
- {
- ndirty = 0;
- repeat:
-
- bh = lru_list[nlist];
- if(bh)
- for (i = nr_buffers_type[nlist]; i-- > 0 && ndirty < bdf_prm.b_un.ndirty;
- bh = next) {
- /* We may have stalled while waiting for I/O to complete. */
- if(bh->b_list != nlist) goto repeat;
- next = bh->b_next_free;
- if(!lru_list[nlist]) {
- printk("Dirty list empty %d\n", i);
- break;
- }
-
- /* Clean buffer on dirty list? Refile it */
- if (nlist == BUF_DIRTY && !buffer_dirty(bh)) {
- refile_buffer(bh);
- continue;
- }
-
- /* Unlocked buffer on locked list? Refile it */
- if (nlist == BUF_LOCKED && !buffer_locked(bh)) {
- refile_buffer(bh);
- continue;
- }
-
- if (buffer_locked(bh) || !buffer_dirty(bh))
- continue;
- major = MAJOR(bh->b_dev);
- /* Should we write back buffers that are shared or not??
- currently dirty buffers are not shared, so it does not matter */
- next->b_count++;
- bh->b_count++;
- ndirty++;
- bh->b_flushtime = 0;
- if (major == LOOP_MAJOR) {
- ll_rw_block(wrta_cmd,1, &bh);
- wrta_cmd = WRITEA;
- if (buffer_dirty(bh))
- --ndirty;
- }
- else
- ll_rw_block(WRITE, 1, &bh);
-#ifdef DEBUG
- if(nlist != BUF_DIRTY) ncount++;
-#endif
- bh->b_count--;
- next->b_count--;
- }
- }
+ if (remaining == 0) {
+ /*
+ * Also try to flush inodes and supers, since
+ * otherwise there would be no way of ensuring
+ * that these quantities ever get written
+ * back. Ideally, we would have a timestamp
+ * on the inodes and superblocks so that we
+ * could write back only the old ones.
+ */
+ sync_supers(0);
+ sync_inodes(0);
+ remaining = HZ * bdf_prm.b_un.interval;
+ }
+
+ /* Keep flushing till there aren't very many dirty buffers */
+ do {
+ sync_old_buffers();
+ } while(nr_buffers_type[BUF_DIRTY] > nr_buffers * bdf_prm.b_un.nfract/100);
+
+ wake_up(&bdflush_done);
X #ifdef DEBUG
- if (ncount) printk("sys_bdflush: %d dirty buffers not on dirty list\n", ncount);
X printk("sleeping again.\n");
X #endif
- /* If we didn't write anything, but there are still
- * dirty buffers, then make the next write to a
- * loop device to be a blocking write.
- * This lets us block--which we _must_ do! */
- if (ndirty == 0 && nr_buffers_type[BUF_DIRTY] > 0 && wrta_cmd != WRITE) {
- wrta_cmd = WRITE;
- continue;
- }
- run_task_queue(&tq_disk);
- wake_up(&bdflush_done);
-
- /* If there are still a lot of dirty buffers around, skip the sleep
- and flush some more */
- if(ndirty == 0 || nr_buffers_type[BUF_DIRTY] <= nr_buffers * bdf_prm.b_un.nfract/100) {
- spin_lock_irq(&current->sigmask_lock);
- flush_signals(current);
- spin_unlock_irq(&current->sigmask_lock);
-
- interruptible_sleep_on(&bdflush_wait);
- }
X }
X }
diff -u --recursive --new-file v2.2.7/linux/fs/coda/dir.c linux/fs/coda/dir.c
--- v2.2.7/linux/fs/coda/dir.c Wed Apr 28 11:37:31 1999
+++ linux/fs/coda/dir.c Sat May 8 17:56:37 1999
@@ -44,7 +44,7 @@
X static int coda_readdir(struct file *file, void *dirent, filldir_t filldir);
X
X /* dentry ops */
-static int coda_dentry_revalidate(struct dentry *de);
+static int coda_dentry_revalidate(struct dentry *de, int);
X static void coda_dentry_delete(struct dentry *);
X
X /* support routines */
@@ -778,7 +778,7 @@
X }
X
X /* called when a cache lookup succeeds */
-static int coda_dentry_revalidate(struct dentry *de)
+static int coda_dentry_revalidate(struct dentry *de, int flags)
X {
X int valid = 1;
X struct inode *inode = de->d_inode;
diff -u --recursive --new-file v2.2.7/linux/fs/devpts/root.c linux/fs/devpts/root.c
--- v2.2.7/linux/fs/devpts/root.c Wed Apr 28 11:37:31 1999
+++ linux/fs/devpts/root.c Sat May 8 17:56:37 1999
@@ -18,7 +18,7 @@
X
X static int devpts_root_readdir(struct file *,void *,filldir_t);
X static struct dentry *devpts_root_lookup(struct inode *,struct dentry *);
-static int devpts_revalidate(struct dentry *);
+static int devpts_revalidate(struct dentry *, int);
X
X static struct file_operations devpts_root_operations = {
X NULL, /* llseek */
@@ -116,7 +116,7 @@
X * the pty really does still exist. Never revalidate negative dentries;
X * for simplicity (fix later?)
X */
-static int devpts_revalidate(struct dentry * dentry)
+static int devpts_revalidate(struct dentry * dentry, int flags)
X {
X struct devpts_sb_info *sbi;
X
diff -u --recursive --new-file v2.2.7/linux/fs/dquot.c linux/fs/dquot.c
--- v2.2.7/linux/fs/dquot.c Wed Mar 10 15:29:49 1999
+++ linux/fs/dquot.c Fri May 7 18:04:12 1999
@@ -1268,11 +1268,11 @@
X
X int quota_on(kdev_t dev, short type, char *path)
X {
- struct file *filp = NULL;
- struct dentry *dentry;
+ struct file *f;
X struct vfsmount *vfsmnt;
X struct inode *inode;
X struct dquot *dquot;
+ struct quota_mount_options *mnt_dquot;
X char *tmp;
X int error;
X
@@ -1281,69 +1281,48 @@
X return -ENODEV;
X
X if (is_enabled(vfsmnt, type))
- return(-EBUSY);
+ return -EBUSY;
+ mnt_dquot = &vfsmnt->mnt_dquot;
X
X tmp = getname(path);
X error = PTR_ERR(tmp);
X if (IS_ERR(tmp))
X return error;
X
- dentry = open_namei(tmp, O_RDWR, 0600);
+ f = filp_open(tmp, O_RDWR, 0600);
X putname(tmp);
+ if (IS_ERR(f))
+ return PTR_ERR(f);
X
- error = PTR_ERR(dentry);
- if (IS_ERR(dentry))
- return error;


- inode = dentry->d_inode;

-
- if (!S_ISREG(inode->i_mode)) {
- dput(dentry);
- return -EACCES;
- }
-
- if (inode->i_size == 0 || (inode->i_size % sizeof(struct dqblk)) != 0) {
- dput(dentry);
- return(-EINVAL);
- }
-
- filp = get_empty_filp();
- if (filp != (struct file *)NULL) {
- filp->f_mode = (O_RDWR + 1) & O_ACCMODE;
- filp->f_flags = O_RDWR;
- filp->f_dentry = dentry;
- filp->f_pos = 0;
- filp->f_reada = 0;
- filp->f_op = inode->i_op->default_file_ops;
- if (filp->f_op->read || filp->f_op->write) {
- error = get_write_access(inode);
- if (!error) {
- if (filp->f_op && filp->f_op->open)
- error = filp->f_op->open(inode, filp);
- if (!error) {
- set_enable_flags(vfsmnt, type);
- vfsmnt->mnt_dquot.files[type] = filp;
-
- dquot = dqget(dev, 0, type);
- vfsmnt->mnt_dquot.inode_expire[type] = (dquot) ? dquot->dq_itime : MAX_IQ_TIME;
- vfsmnt->mnt_dquot.block_expire[type] = (dquot) ? dquot->dq_btime : MAX_DQ_TIME;
- dqput(dquot);
-
- vfsmnt->mnt_sb->dq_op = &dquot_operations;
- add_dquot_ref(dev, type);
-
- return(0);
- }
- put_write_access(inode);
- }
- } else
- error = -EIO;
- put_filp(filp);
- } else
- error = -EMFILE;
-
- dput(dentry);
-
- return(error);
+ /* sanity checks */
+ error = -EIO;
+ if (!f->f_op->read && !f->f_op->write)
+ goto cleanup;
+ inode = f->f_dentry->d_inode;
+ error = -EACCES;
+ if (!S_ISREG(inode->i_mode))
+ goto cleanup;
+ error = -EINVAL;
+ if (inode->i_size == 0 || (inode->i_size % sizeof(struct dqblk)) != 0)
+ goto cleanup;
+
+ /* OK, there we go */
+ set_enable_flags(vfsmnt, type);
+ mnt_dquot->files[type] = f;
+
+ dquot = dqget(dev, 0, type);
+ mnt_dquot->inode_expire[type] = (dquot) ? dquot->dq_itime : MAX_IQ_TIME;
+ mnt_dquot->block_expire[type] = (dquot) ? dquot->dq_btime : MAX_DQ_TIME;
+ dqput(dquot);
+
+ vfsmnt->mnt_sb->dq_op = &dquot_operations;
+ add_dquot_ref(dev, type);
+
+ return(0);
+
+cleanup:
+ fput(f);
+ return error;
X }
X
X /*
@@ -1370,8 +1349,8 @@
X case Q_GETSTATS:
X break;
X case Q_GETQUOTA:
- if (((type == USRQUOTA && current->uid != id) ||
- (type == GRPQUOTA && current->gid != id)) &&
+ if (((type == USRQUOTA && current->euid != id) ||
+ (type == GRPQUOTA && current->egid != id)) &&
X !capable(CAP_SYS_RESOURCE))
X goto out;
X break;
diff -u --recursive --new-file v2.2.7/linux/fs/exec.c linux/fs/exec.c
--- v2.2.7/linux/fs/exec.c Tue Jan 19 11:32:52 1999
+++ linux/fs/exec.c Thu Apr 29 22:10:12 1999
@@ -29,7 +29,6 @@
X #include <linux/a.out.h>
X #include <linux/stat.h>
X #include <linux/fcntl.h>
-#include <linux/user.h>
X #include <linux/smp_lock.h>
X #include <linux/init.h>
X
diff -u --recursive --new-file v2.2.7/linux/fs/ext2/inode.c linux/fs/ext2/inode.c
--- v2.2.7/linux/fs/ext2/inode.c Tue Mar 23 14:35:48 1999
+++ linux/fs/ext2/inode.c Tue May 4 16:27:07 1999
@@ -286,7 +286,8 @@
X u32 * p;
X struct buffer_head * result;
X int blocks = inode->i_sb->s_blocksize / 512;
-
+ unsigned long limit;
+
X if (!bh)
X return NULL;
X if (!buffer_uptodate(bh)) {
@@ -309,13 +310,22 @@
X brelse (result);
X goto repeat;
X }
- if (!create || new_block >=
- (current->rlim[RLIMIT_FSIZE].rlim_cur >>
- EXT2_BLOCK_SIZE_BITS(inode->i_sb))) {
+ *err = -EFBIG;
+ if (!create) {
X brelse (bh);
- *err = -EFBIG;
X return NULL;
X }
+
+ limit = current->rlim[RLIMIT_FSIZE].rlim_cur;
+ if (limit < RLIM_INFINITY) {
+ limit >>= EXT2_BLOCK_SIZE_BITS(inode->i_sb);
+ if (new_block >= limit) {
+ brelse (bh);
+ send_sig(SIGXFSZ, current, 0);


+ return NULL;
+ }
+ }

+
X if (inode->u.ext2_i.i_next_alloc_block == new_block)
X goal = inode->u.ext2_i.i_next_alloc_goal;
X if (!goal) {
diff -u --recursive --new-file v2.2.7/linux/fs/ext2/namei.c linux/fs/ext2/namei.c
--- v2.2.7/linux/fs/ext2/namei.c Wed Apr 28 11:37:31 1999
+++ linux/fs/ext2/namei.c Mon May 10 14:14:28 1999
@@ -74,8 +74,6 @@
X int block, toread, i, err;
X
X *res_dir = NULL;
- if (!dir)
- return NULL;
X sb = dir->i_sb;
X
X if (namelen > EXT2_NAME_LEN)
diff -u --recursive --new-file v2.2.7/linux/fs/hfs/sysdep.c linux/fs/hfs/sysdep.c
--- v2.2.7/linux/fs/hfs/sysdep.c Mon Dec 28 15:00:52 1998
+++ linux/fs/hfs/sysdep.c Sat May 8 17:56:37 1999
@@ -18,7 +18,7 @@
X #include <linux/hfs_fs_i.h>
X #include <linux/hfs_fs.h>
X
-static int hfs_revalidate_dentry(struct dentry *);
+static int hfs_revalidate_dentry(struct dentry *, int);
X static int hfs_hash_dentry(struct dentry *, struct qstr *);
X static int hfs_compare_dentry(struct dentry *, struct qstr *, struct qstr *);
X static void hfs_dentry_iput(struct dentry *, struct inode *);
@@ -89,7 +89,7 @@
X iput(inode);
X }
X
-static int hfs_revalidate_dentry(struct dentry *dentry)
+static int hfs_revalidate_dentry(struct dentry *dentry, int flags)
X {
X struct inode *inode = dentry->d_inode;
X int diff;
diff -u --recursive --new-file v2.2.7/linux/fs/inode.c linux/fs/inode.c
--- v2.2.7/linux/fs/inode.c Wed Apr 28 11:37:31 1999
+++ linux/fs/inode.c Tue May 4 10:57:12 1999
@@ -522,6 +522,7 @@
X inode->i_nlink = 1;
X inode->i_writecount = 0;
X inode->i_size = 0;
+ inode->i_generation = 0;
X memset(&inode->i_dquot, 0, sizeof(inode->i_dquot));
X sema_init(&inode->i_sem, 1);
X }
diff -u --recursive --new-file v2.2.7/linux/fs/isofs/namei.c linux/fs/isofs/namei.c
--- v2.2.7/linux/fs/isofs/namei.c Wed Apr 28 11:37:31 1999
+++ linux/fs/isofs/namei.c Mon May 10 14:14:28 1999
@@ -74,7 +74,6 @@
X char c;
X
X *ino = 0;
- if (!dir) return NULL;
X
X if (!(block = dir->u.isofs_i.i_first_extent)) return NULL;
X
diff -u --recursive --new-file v2.2.7/linux/fs/locks.c linux/fs/locks.c
--- v2.2.7/linux/fs/locks.c Tue Mar 23 14:35:48 1999
+++ linux/fs/locks.c Tue May 11 08:52:14 1999
@@ -263,16 +263,18 @@
X if (waiter->fl_notify)
X waiter->fl_notify(waiter);
X wake_up(&waiter->fl_wait);
- if (wait)
+ if (wait) {
X /* Let the blocked process remove waiter from the
X * block list when it gets scheduled.
X */
+ current->policy |= SCHED_YIELD;
X schedule();
- else
+ } else {
X /* Remove waiter from the block list, because by the
X * time it wakes up blocker won't exist any more.
X */
X locks_delete_block(blocker, waiter);
+ }
X }
X return;
X }
diff -u --recursive --new-file v2.2.7/linux/fs/minix/namei.c linux/fs/minix/namei.c
--- v2.2.7/linux/fs/minix/namei.c Wed Apr 28 11:37:31 1999
+++ linux/fs/minix/namei.c Mon May 10 14:15:16 1999
@@ -45,7 +45,7 @@
X struct minix_dir_entry *de;
X
X *res_dir = NULL;
- if (!dir || !dir->i_sb)
+ if (!dir->i_sb)
X return NULL;
X info = &dir->i_sb->u.minix_sb;
X if (namelen > info->s_namelen) {
@@ -249,12 +249,6 @@
X struct buffer_head * bh;
X struct minix_dir_entry * de;
X
- bh = minix_find_entry(dir, dentry->d_name.name,
- dentry->d_name.len, &de);
- if (bh) {
- brelse(bh);
- return -EEXIST;
- }
X inode = minix_new_inode(dir);
X if (!inode)
X return -ENOSPC;
@@ -295,12 +289,6 @@
X struct minix_sb_info * info;
X
X info = &dir->i_sb->u.minix_sb;
- bh = minix_find_entry(dir, dentry->d_name.name,
- dentry->d_name.len, &de);
- if (bh) {
- brelse(bh);
- return -EEXIST;
- }
X if (dir->i_nlink >= info->s_link_max)
X return -EMLINK;
X inode = minix_new_inode(dir);
@@ -524,15 +512,6 @@
X brelse(name_block);
X inode->i_size = i;
X mark_inode_dirty(inode);
- bh = minix_find_entry(dir, dentry->d_name.name,
- dentry->d_name.len, &de);
- if (bh) {
- inode->i_nlink--;
- mark_inode_dirty(inode);
- iput(inode);
- brelse(bh);
- return -EEXIST;
- }
X i = minix_add_entry(dir, dentry->d_name.name,
X dentry->d_name.len, &bh, &de);
X if (i) {
@@ -562,12 +541,6 @@
X if (inode->i_nlink >= inode->i_sb->u.minix_sb.s_link_max)
X return -EMLINK;
X
- bh = minix_find_entry(dir, dentry->d_name.name,
- dentry->d_name.len, &de);
- if (bh) {
- brelse(bh);
- return -EEXIST;
- }
X error = minix_add_entry(dir, dentry->d_name.name,
X dentry->d_name.len, &bh, &de);
X if (error) {
diff -u --recursive --new-file v2.2.7/linux/fs/namei.c linux/fs/namei.c
--- v2.2.7/linux/fs/namei.c Wed Apr 28 11:37:31 1999
+++ linux/fs/namei.c Sat May 8 20:46:08 1999
@@ -23,18 +23,6 @@
X #include <asm/page.h>
X #include <asm/pgtable.h>
X
-/*
- * The bitmask for a lookup event:
- * - follow links at the end
- * - require a directory
- * - ending slashes ok even for nonexistent files
- * - internal "there are more path compnents" flag
- */
-#define LOOKUP_FOLLOW (1)
-#define LOOKUP_DIRECTORY (2)
-#define LOOKUP_SLASHOK (4)
-#define LOOKUP_CONTINUE (8)
-
X #include <asm/namei.h>
X
X /* This can be removed after the beta phase. */
@@ -225,12 +213,12 @@
X /*
X * Internal lookup() using the new generic dcache.
X */
-static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name)
+static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name, int flags)
X {
X struct dentry * dentry = d_lookup(parent, name);
X
X if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
- if (!dentry->d_op->d_revalidate(dentry) && !d_invalidate(dentry)) {
+ if (!dentry->d_op->d_revalidate(dentry, flags) && !d_invalidate(dentry)) {
X dput(dentry);
X dentry = NULL;
X }
@@ -245,7 +233,7 @@
X * We get the directory semaphore, and after getting that we also
X * make sure that nobody added the entry to the dcache in the meantime..
X */
-static struct dentry * real_lookup(struct dentry * parent, struct qstr * name)
+static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, int flags)
X {
X struct dentry * result;
X struct inode *dir = parent->d_inode;
@@ -258,7 +246,7 @@
X * FIXME! This could use version numbering or similar to
X * avoid unnecessary cache lookups.
X */
- result = cached_lookup(parent, name);
+ result = cached_lookup(parent, name, flags);
X if (!result) {
X struct dentry * dentry = d_alloc(parent, name);
X result = ERR_PTR(-ENOMEM);
@@ -392,9 +380,9 @@
X /* This does the actual lookups.. */
X dentry = reserved_lookup(base, &this);
X if (!dentry) {
- dentry = cached_lookup(base, &this);
+ dentry = cached_lookup(base, &this, flags);
X if (!dentry) {
- dentry = real_lookup(base, &this);
+ dentry = real_lookup(base, &this, flags);
X if (IS_ERR(dentry))
X break;
X }
diff -u --recursive --new-file v2.2.7/linux/fs/ncpfs/dir.c linux/fs/ncpfs/dir.c
--- v2.2.7/linux/fs/ncpfs/dir.c Wed Apr 28 11:37:31 1999
+++ linux/fs/ncpfs/dir.c Sat May 8 17:56:37 1999
@@ -112,14 +112,14 @@
X /*
X * Dentry operations routines
X */
-static int ncp_lookup_validate(struct dentry *);
+static int ncp_lookup_validate(struct dentry *, int);
X static int ncp_hash_dentry(struct dentry *, struct qstr *);
X static int ncp_compare_dentry (struct dentry *, struct qstr *, struct qstr *);
X static void ncp_delete_dentry(struct dentry *);
X
X struct dentry_operations ncp_dentry_operations =
X {
- ncp_lookup_validate, /* d_validate(struct dentry *) */
+ ncp_lookup_validate, /* d_revalidate(struct dentry *, int) */
X ncp_hash_dentry, /* d_hash */
X ncp_compare_dentry, /* d_compare */
X ncp_delete_dentry /* d_delete(struct dentry *) */
@@ -345,7 +345,7 @@


X
X
X static int

-ncp_lookup_validate(struct dentry * dentry)
+ncp_lookup_validate(struct dentry * dentry, int flags)
X {
X struct ncp_server *server;
X struct inode *dir = dentry->d_parent->d_inode;
diff -u --recursive --new-file v2.2.7/linux/fs/nfs/dir.c linux/fs/nfs/dir.c
--- v2.2.7/linux/fs/nfs/dir.c Wed Apr 28 11:37:31 1999
+++ linux/fs/nfs/dir.c Sat May 8 23:18:22 1999
@@ -72,9 +72,9 @@
X NULL, /* select - default */
X NULL, /* ioctl - default */
X NULL, /* mmap */
- NULL, /* no special open is needed */
+ nfs_open, /* open */


X NULL, /* flush */
- NULL, /* no special release code */

+ nfs_release, /* release */


X NULL /* fsync */
X };
X

@@ -364,7 +364,48 @@
X dentry->d_time = jiffies;
X }
X
-#define NFS_REVALIDATE_INTERVAL (5*HZ)
+static inline int nfs_dentry_force_reval(struct dentry *dentry, int flags)
+{
+ struct inode *inode = dentry->d_inode;
+ unsigned long timeout = NFS_ATTRTIMEO(inode);
+
+ /*
+ * If it's the last lookup in a series, we use a stricter
+ * cache consistency check by looking at the parent mtime.
+ *
+ * If it's been modified in the last hour, be really strict.
+ * (This still means that we can avoid doing unnecessary
+ * work on directories like /usr/share/bin etc which basically
+ * never change).
+ */
+ if (!(flags & LOOKUP_CONTINUE)) {
+ long diff = CURRENT_TIME - dentry->d_parent->d_inode->i_mtime;
+
+ if (diff < 15*60)
+ timeout = 0;
+ }
+
+ return time_after(jiffies,dentry->d_time + timeout);
+}
+
+/*
+ * We judge how long we want to trust negative
+ * dentries by looking at the parent inode mtime.
+ *
+ * If mtime is close to present time, we revalidate
+ * more often.
+ */
+static inline int nfs_neg_need_reval(struct dentry *dentry)
+{
+ unsigned long timeout = 30 * HZ;
+ long diff = CURRENT_TIME - dentry->d_parent->d_inode->i_mtime;
+
+ if (diff < 5*60)
+ timeout = 1 * HZ;
+
+ return time_after(jiffies, dentry->d_time + timeout);
+}
+
X /*
X * This is called every time the dcache has a lookup hit,
X * and we should check whether we can really trust that
@@ -377,7 +418,7 @@
X * we do a new lookup and verify that the dentry is still
X * correct.
X */
-static int nfs_lookup_revalidate(struct dentry * dentry)
+static int nfs_lookup_revalidate(struct dentry * dentry, int flags)
X {
X struct dentry * parent = dentry->d_parent;
X struct inode * inode = dentry->d_inode;
@@ -386,11 +427,15 @@
X struct nfs_fattr fattr;
X
X /*
- * If we don't have an inode, let's just assume
- * a 5-second "live" time for negative dentries.
+ * If we don't have an inode, let's look at the parent
+ * directory mtime to get a hint about how often we
+ * should validate things..
X */
- if (!inode)
- goto do_lookup;
+ if (!inode) {
+ if (nfs_neg_need_reval(dentry))
+ goto out_bad;
+ goto out_valid;
+ }
X
X if (is_bad_inode(inode)) {
X dfprintk(VFS, "nfs_lookup_validate: %s/%s has dud inode\n",
@@ -398,27 +443,17 @@
X goto out_bad;
X }
X
- if (_nfs_revalidate_inode(NFS_DSERVER(dentry), dentry))
- goto out_bad;
-
- if (time_before(jiffies,dentry->d_time+NFS_ATTRTIMEO(inode)))
+ if (IS_ROOT(dentry))
X goto out_valid;
X
- if (IS_ROOT(dentry))
+ if (!nfs_dentry_force_reval(dentry, flags))
X goto out_valid;
X
-do_lookup:
X /*
X * Do a new lookup and check the dentry attributes.
X */
- error = nfs_proc_lookup(NFS_DSERVER(parent), NFS_FH(parent),
+ error = nfs_proc_lookup(NFS_DSERVER(parent), NFS_FH(parent),
X dentry->d_name.name, &fhandle, &fattr);
- if (dentry->d_inode == NULL) {
- if (error == -ENOENT &&
- time_before(jiffies,dentry->d_time+NFS_REVALIDATE_INTERVAL))
- goto out_valid;
- goto out_bad;
- }
X if (error)
X goto out_bad;
X
@@ -496,7 +531,7 @@
X }
X
X struct dentry_operations nfs_dentry_operations = {
- nfs_lookup_revalidate, /* d_validate(struct dentry *) */
+ nfs_lookup_revalidate, /* d_revalidate(struct dentry *, int) */
X NULL, /* d_hash */
X NULL, /* d_compare */
X nfs_dentry_delete, /* d_delete(struct dentry *) */
diff -u --recursive --new-file v2.2.7/linux/fs/nfs/file.c linux/fs/nfs/file.c
--- v2.2.7/linux/fs/nfs/file.c Tue Mar 23 14:35:48 1999
+++ linux/fs/nfs/file.c Sat May 8 20:01:19 1999
@@ -46,9 +46,9 @@
X NULL, /* select - default */
X NULL, /* ioctl - default */
X nfs_file_mmap, /* mmap */
- NULL, /* no special open is needed */
+ nfs_open, /* open */
X nfs_file_flush, /* flush */
- NULL, /* release */
+ nfs_release, /* release */
X nfs_fsync, /* fsync */
X NULL, /* fasync */
X NULL, /* check_media_change */
diff -u --recursive --new-file v2.2.7/linux/fs/nfs/inode.c linux/fs/nfs/inode.c
--- v2.2.7/linux/fs/nfs/inode.c Wed Apr 28 11:37:31 1999
+++ linux/fs/nfs/inode.c Sat May 8 20:00:46 1999
@@ -696,6 +696,22 @@
X }
X
X /*
+ * These are probably going to contain hooks for
+ * allocating and releasing RPC credentials for
+ * the file. I'll have to think about Tronds patch
+ * a bit more..
+ */
+int nfs_open(struct inode *inode, struct file *filp)
+{


+ return 0;
+}
+

+int nfs_release(struct inode *inode, struct file *filp)
+{


+ return 0;
+}
+

+/*
X * This function is called whenever some part of NFS notices that
X * the cached attributes have to be refreshed.
X */
diff -u --recursive --new-file v2.2.7/linux/fs/proc/array.c linux/fs/proc/array.c
--- v2.2.7/linux/fs/proc/array.c Tue Mar 23 14:35:48 1999
+++ linux/fs/proc/array.c Mon May 10 10:05:18 1999
@@ -896,7 +896,7 @@
X
X return sprintf(buffer,"%d (%s) %c %d %d %d %d %d %lu %lu \
X %lu %lu %lu %lu %lu %ld %ld %ld %ld %ld %ld %lu %lu %ld %lu %lu %lu %lu %lu \
-%lu %lu %lu %lu %lu %lu %lu %lu %d\n",
+%lu %lu %lu %lu %lu %lu %lu %lu %d %d\n",
X pid,
X tsk->comm,
X state,
@@ -938,7 +938,8 @@
X wchan,
X tsk->nswap,
X tsk->cnswap,
- tsk->exit_signal);
+ tsk->exit_signal,
+ tsk->processor);
X }
X
X static inline void statm_pte_range(pmd_t * pmd, unsigned long address, unsigned long size,
diff -u --recursive --new-file v2.2.7/linux/fs/qnx4/namei.c linux/fs/qnx4/namei.c
--- v2.2.7/linux/fs/qnx4/namei.c Wed Apr 28 11:37:31 1999
+++ linux/fs/qnx4/namei.c Mon May 10 14:14:28 1999
@@ -70,12 +70,8 @@
X struct buffer_head *bh;
X
X *res_dir = NULL;
- if (!dir || !dir->i_sb) {
- if (!dir) {
- printk("qnx4: NULL dir.\n");
- } else {
- printk("qnx4: no superblock on dir.\n");
- }
+ if (!dir->i_sb) {
+ printk("qnx4: no superblock on dir.\n");
X return NULL;
X }
X bh = NULL;
diff -u --recursive --new-file v2.2.7/linux/fs/smbfs/dir.c linux/fs/smbfs/dir.c
--- v2.2.7/linux/fs/smbfs/dir.c Wed Apr 28 11:37:31 1999
+++ linux/fs/smbfs/dir.c Sat May 8 17:56:37 1999
@@ -191,14 +191,14 @@
X /*
X * Dentry operations routines
X */
-static int smb_lookup_validate(struct dentry *);
+static int smb_lookup_validate(struct dentry *, int);
X static int smb_hash_dentry(struct dentry *, struct qstr *);
X static int smb_compare_dentry(struct dentry *, struct qstr *, struct qstr *);
X static void smb_delete_dentry(struct dentry *);
X
X static struct dentry_operations smbfs_dentry_operations =
X {
- smb_lookup_validate, /* d_validate(struct dentry *) */
+ smb_lookup_validate, /* d_revalidate(struct dentry *) */
X smb_hash_dentry, /* d_hash */
X smb_compare_dentry, /* d_compare */
X smb_delete_dentry /* d_delete(struct dentry *) */
@@ -208,7 +208,7 @@
X * This is the callback when the dcache has a lookup hit.


X */
X static int

-smb_lookup_validate(struct dentry * dentry)
+smb_lookup_validate(struct dentry * dentry, int flags)
X {
X struct inode * inode = dentry->d_inode;
X unsigned long age = jiffies - dentry->d_time;
diff -u --recursive --new-file v2.2.7/linux/fs/super.c linux/fs/super.c
--- v2.2.7/linux/fs/super.c Fri Apr 16 14:47:31 1999
+++ linux/fs/super.c Mon May 10 10:08:51 1999
@@ -1131,6 +1131,7 @@
X sb = get_empty_super(); /* "can't fail" */
X sb->s_dev = get_unnamed_dev();
X sb->s_flags = root_mountflags;
+ sema_init(&sb->s_vfs_rename_sem,1);
X vfsmnt = add_vfsmnt(sb, "/dev/root", "/");
X if (vfsmnt) {
X if (nfs_root_mount(sb) >= 0) {
@@ -1156,12 +1157,22 @@
X
X #ifdef CONFIG_BLK_DEV_FD
X if (MAJOR(ROOT_DEV) == FLOPPY_MAJOR) {
+#ifdef CONFIG_BLK_DEV_RAM
+ extern int rd_doload;
+#endif
X floppy_eject();
X #ifndef CONFIG_BLK_DEV_RAM
X printk(KERN_NOTICE "(Warning, this kernel has no ramdisk support)\n");
+#else
+ /* rd_doload is 2 for a dual initrd/ramload setup */
+ if(rd_doload==2)
+ rd_load_secondary();
+ else
X #endif
- printk(KERN_NOTICE "VFS: Insert root floppy and press ENTER\n");
- wait_for_keypress();
+ {
+ printk(KERN_NOTICE "VFS: Insert root floppy and press ENTER\n");
+ wait_for_keypress();
+ }
X }
X #endif
X
diff -u --recursive --new-file v2.2.7/linux/fs/sysv/namei.c linux/fs/sysv/namei.c
--- v2.2.7/linux/fs/sysv/namei.c Wed Apr 28 11:37:31 1999
+++ linux/fs/sysv/namei.c Mon May 10 14:14:28 1999
@@ -67,8 +67,6 @@
X struct buffer_head * bh;
X
X *res_dir = NULL;
- if (!dir)
- return NULL;
X sb = dir->i_sb;
X if (namelen > SYSV_NAMELEN) {
X if (sb->sv_truncate)
diff -u --recursive --new-file v2.2.7/linux/fs/ufs/namei.c linux/fs/ufs/namei.c
--- v2.2.7/linux/fs/ufs/namei.c Wed Apr 28 11:37:31 1999
+++ linux/fs/ufs/namei.c Mon May 10 14:14:28 1999
@@ -91,8 +91,6 @@
X UFSD(("ENTER, dir_ino %lu, name %s, namlen %u\n", dir->i_ino, name, namelen))
X
X *res_dir = NULL;
- if (!dir)
- return NULL;
X
X sb = dir->i_sb;
X flags = sb->u.ufs_sb.s_flags;
diff -u --recursive --new-file v2.2.7/linux/fs/umsdos/dir.c linux/fs/umsdos/dir.c
--- v2.2.7/linux/fs/umsdos/dir.c Wed Apr 28 11:37:31 1999
+++ linux/fs/umsdos/dir.c Sat May 8 17:56:37 1999
@@ -30,7 +30,7 @@
X */
X
X /* nothing for now ... */
-static int umsdos_dentry_validate(struct dentry *dentry)
+static int umsdos_dentry_validate(struct dentry *dentry, int flags)
X {
X return 1;
X }
@@ -46,7 +46,7 @@
X
X struct dentry_operations umsdos_dentry_operations =
X {
- umsdos_dentry_validate, /* d_validate(struct dentry *) */
+ umsdos_dentry_validate, /* d_revalidate(struct dentry *, int) */
X NULL, /* d_hash */
X NULL, /* d_compare */
X umsdos_dentry_dput, /* d_delete(struct dentry *) */
diff -u --recursive --new-file v2.2.7/linux/fs/vfat/namei.c linux/fs/vfat/namei.c
--- v2.2.7/linux/fs/vfat/namei.c Wed Apr 28 11:37:31 1999
+++ linux/fs/vfat/namei.c Sat May 8 17:56:37 1999
@@ -71,7 +71,7 @@
X static int vfat_hash(struct dentry *parent, struct qstr *qstr);
X static int vfat_cmpi(struct dentry *dentry, struct qstr *a, struct qstr *b);
X static int vfat_cmp(struct dentry *dentry, struct qstr *a, struct qstr *b);
-static int vfat_revalidate(struct dentry *dentry);
+static int vfat_revalidate(struct dentry *dentry, int);
X
X static struct dentry_operations vfat_dentry_ops[4] = {
X {
@@ -106,7 +106,7 @@
X MOD_DEC_USE_COUNT;
X }
X
-static int vfat_revalidate(struct dentry *dentry)
+static int vfat_revalidate(struct dentry *dentry, int flags)
X {
X PRINTK1(("vfat_revalidate: %s\n", dentry->d_name.name));
X if (dentry->d_time == dentry->d_parent->d_inode->i_version) {
diff -u --recursive --new-file v2.2.7/linux/include/asm-alpha/fpu.h linux/include/asm-alpha/fpu.h
--- v2.2.7/linux/include/asm-alpha/fpu.h Tue Mar 17 22:18:15 1998
+++ linux/include/asm-alpha/fpu.h Mon May 10 09:55:21 1999
@@ -81,6 +81,18 @@
X return fp;
X }
X
+static inline unsigned long
+ieee_fpcr_to_swcr(unsigned long fp)
+{
+ unsigned long sw;
+ sw = (fp >> 35) & IEEE_STATUS_MASK;
+ sw |= (~fp >> 48) & (IEEE_TRAP_ENABLE_INV
+ | IEEE_TRAP_ENABLE_DZE
+ | IEEE_TRAP_ENABLE_OVF);
+ sw |= (~fp >> 57) & (IEEE_TRAP_ENABLE_UNF | IEEE_TRAP_ENABLE_INE);
+ return sw;
+}
+
X #ifdef __KERNEL__
X
X /* The following two functions don't need trapb/excb instructions
diff -u --recursive --new-file v2.2.7/linux/include/asm-alpha/pgtable.h linux/include/asm-alpha/pgtable.h
--- v2.2.7/linux/include/asm-alpha/pgtable.h Tue Mar 23 14:35:48 1999
+++ linux/include/asm-alpha/pgtable.h Mon May 10 09:55:21 1999
@@ -167,19 +167,6 @@
X
X #else /* __SMP__ */
X
-/* ipi_msg_flush_tb is owned by the holder of the global kernel lock. */
-struct ipi_msg_flush_tb_struct {
- volatile unsigned int flush_tb_mask;
- union {
- struct mm_struct * flush_mm;
- struct vm_area_struct * flush_vma;
- } p;
- unsigned long flush_addr;
- unsigned long flush_end;
-};
-
-extern struct ipi_msg_flush_tb_struct ipi_msg_flush_tb;
-
X extern void flush_tlb_all(void);
X extern void flush_tlb_mm(struct mm_struct *);
X extern void flush_tlb_page(struct vm_area_struct *, unsigned long);
diff -u --recursive --new-file v2.2.7/linux/include/asm-alpha/semaphore.h linux/include/asm-alpha/semaphore.h
--- v2.2.7/linux/include/asm-alpha/semaphore.h Wed Apr 28 11:37:31 1999
+++ linux/include/asm-alpha/semaphore.h Fri May 7 10:55:26 1999
@@ -190,7 +190,7 @@
X " stl_c $28,%1\n"
X " beq $28,2f\n"
X " mb\n"
- " ble $27,3f\n"
+ " ble $24,3f\n"
X "4:\n"
X ".section .text2,\"ax\"\n"
X "2: br 1b\n"
diff -u --recursive --new-file v2.2.7/linux/include/asm-alpha/system.h linux/include/asm-alpha/system.h
--- v2.2.7/linux/include/asm-alpha/system.h Tue Jan 19 11:32:52 1999
+++ linux/include/asm-alpha/system.h Tue May 11 09:55:45 1999
@@ -1,6 +1,7 @@
X #ifndef __ALPHA_SYSTEM_H
X #define __ALPHA_SYSTEM_H
X
+#include <linux/config.h>
X #include <asm/pal.h>
X #include <asm/page.h>
X
@@ -97,12 +98,15 @@
X
X extern void halt(void) __attribute__((noreturn));
X
-#define switch_to(prev,next) do { \
- current = next; \
- alpha_switch_to((unsigned long) &current->tss - IDENT_ADDR); \
+#define switch_to(prev,next,last) \
+do { \
+ unsigned long pcbb; \
+ current = (next); \
+ pcbb = virt_to_phys(&current->tss); \
+ (last) = alpha_switch_to(pcbb, (prev)); \
X } while (0)
X
-extern void alpha_switch_to(unsigned long pctxp);
+extern struct task_struct* alpha_switch_to(unsigned long, struct task_struct*);
X
X #define mb() \
X __asm__ __volatile__("mb": : :"memory")
@@ -119,6 +123,34 @@
X #define draina() \
X __asm__ __volatile__ ("call_pal %0 #draina" : : "i" (PAL_draina) : "memory")
X
+enum implver_enum {
+ IMPLVER_EV4,
+ IMPLVER_EV5,
+ IMPLVER_EV6
+};
+
+#ifdef CONFIG_ALPHA_GENERIC
+#define implver() \
+({ unsigned long __implver; \
+ __asm__ ("implver %0" : "=r"(__implver)); \
+ (enum implver_enum) __implver; })
+#else
+/* Try to eliminate some dead code. */
+#ifdef CONFIG_ALPHA_EV4
+#define implver() IMPLVER_EV4
+#endif
+#ifdef CONFIG_ALPHA_EV5
+#define implver() IMPLVER_EV5
+#endif
+#ifdef CONFIG_ALPHA_EV6
+#define implver() IMPLVER_EV6
+#endif
+#endif
+
+#define amask(mask) \
+({ unsigned long __amask, __input = (mask); \
+ __asm__ ("amask %1,%0" : "=r"(__amask) : "rI"(__input)); \
+ __amask; })
X
X static inline unsigned long
X wrperfmon(unsigned long perf_fun, unsigned long arg)
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/a.out.h linux/include/asm-arm/a.out.h
--- v2.2.7/linux/include/asm-arm/a.out.h Fri Jan 8 22:36:15 1999
+++ linux/include/asm-arm/a.out.h Sat May 8 11:06:57 1999
@@ -26,7 +26,9 @@
X
X #define M_ARM 103
X
+#ifdef __KERNEL__
X #include <asm/arch/a.out.h>
+#endif
X
X #ifndef LIBRARY_START_TEXT
X #define LIBRARY_START_TEXT (0x00c00000)
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-arc/a.out.h linux/include/asm-arm/arch-arc/a.out.h
--- v2.2.7/linux/include/asm-arm/arch-arc/a.out.h Fri Jan 8 22:36:17 1999
+++ linux/include/asm-arm/arch-arc/a.out.h Sat May 8 11:06:57 1999
@@ -1,16 +1,14 @@
X /*
X * linux/include/asm-arm/arch-arc/a.out.h
X *
- * Copyright (C) 1996 Russell King
- *
- * Acorn Archimedes/A5000 a.out.h specs
+ * Copyright (C) 1996-1999 Russell King
X */
X #ifndef __ASM_ARCH_A_OUT_H
X #define __ASM_ARCH_A_OUT_H
X
-#ifdef __KERNEL__
-#define STACK_TOP (0x01a00000)
-#endif
+#include <asm/arch/memory.h>
+
+#define STACK_TOP TASK_SIZE
X
X #endif
X
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-arc/hardware.h linux/include/asm-arm/arch-arc/hardware.h
--- v2.2.7/linux/include/asm-arm/arch-arc/hardware.h Fri Jan 8 22:36:18 1999
+++ linux/include/asm-arm/arch-arc/hardware.h Sat May 8 11:06:57 1999
@@ -1,7 +1,7 @@
X /*
X * linux/include/asm-arm/arch-arc/hardware.h
X *
- * Copyright (C) 1996 Russell King.
+ * Copyright (C) 1996-1999 Russell King.
X *
X * This file contains the hardware definitions of the
X * Acorn Archimedes/A5000 machines.
@@ -9,21 +9,20 @@
X * Modifications:
X * 04-04-1998 PJB/RMK Merged arc and a5k versions
X */
-
X #ifndef __ASM_ARCH_HARDWARE_H
X #define __ASM_ARCH_HARDWARE_H


X
X #include <linux/config.h>
X

+#include <asm/arch/memory.h>
+
X /*
X * What hardware must be present - these can be tested by the kernel
X * source.
X */
X #define HAS_IOC
-#include <asm/ioc.h>
X #define HAS_MEMC
X #include <asm/memc.h>
-#define HAS_MEMC1A
X #define HAS_VIDC
X
X /*
@@ -56,6 +55,12 @@
X * for use with inb/outb
X */
X #define IO_VIDC_BASE 0x80100000
+#ifdef CONFIG_ARCH_A5K
+#define IOEB_VID_CTL 0x800d4012
+#define IOEB_PRESENT 0x800d4014
+#define IOEB_PSCLR 0x800d4016
+#define IOEB_MONTYPE 0x800d401c
+#endif
X #ifdef CONFIG_ARCH_ARC
X #define LATCHAADDR 0x80094010
X #define LATCHBADDR 0x80094006
@@ -66,6 +71,14 @@
X #define IO_EC_IOC_BASE 0x80090000
X #define IO_EC_MEMC_BASE 0x80000000
X
+#ifdef CONFIG_ARCH_ARC
+/* A680 hardware */
+#define WD1973_BASE 0x03290000
+#define WD1973_LATCH 0x03350000
+#define Z8530_BASE 0x032b0008
+#define SCSI_BASE 0x03100000
+#endif
+
X /*
X * IO definitions
X */
@@ -77,11 +90,8 @@
X /*
X * RAM definitions
X */
-#define MAPTOPHYS(a) (((unsigned long)a & 0x007fffff) + PAGE_OFFSET)
-#define KERNTOPHYS(a) ((((unsigned long)(&a)) & 0x007fffff) + PAGE_OFFSET)
X #define GET_MEMORY_END(p) (PAGE_OFFSET + (p->u1.s.page_size) * (p->u1.s.nr_pages))
X #define PARAMS_BASE (PAGE_OFFSET + 0x7c000)
-#define KERNEL_BASE (PAGE_OFFSET + 0x80000)
X
X #else
X
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-arc/irq.h linux/include/asm-arm/arch-arc/irq.h
--- v2.2.7/linux/include/asm-arm/arch-arc/irq.h Wed Sep 9 14:51:10 1998
+++ linux/include/asm-arm/arch-arc/irq.h Sat May 8 11:06:57 1999
@@ -10,6 +10,9 @@
X * 11-01-1998 RMK Added mask_and_ack_irq
X * 22-08-1998 RMK Restructured IRQ routines
X */
+#include <asm/ioc.h>
+
+#define fixup_irq(x) (x)
X
X static void arc_mask_irq_ack_a(unsigned int irq)
X {
@@ -108,10 +111,17 @@
X outb(0, IOC_FIQMASK);
X
X for (irq = 0; irq < NR_IRQS; irq++) {
- switch (irq & 0xf8) {
+ switch (irq) {
X case 0 ... 6:
X irq_desc[irq].probe_ok = 1;
+ irq_desc[irq].valid = 1;
+ irq_desc[irq].mask_ack = arc_mask_irq_ack_a;
+ irq_desc[irq].mask = arc_mask_irq_a;
+ irq_desc[irq].unmask = arc_unmask_irq_a;
+ break;
+
X case 7:
+ irq_desc[irq].noautoenable = 1;
X irq_desc[irq].valid = 1;
X irq_desc[irq].mask_ack = arc_mask_irq_ack_a;
X irq_desc[irq].mask = arc_mask_irq_a;
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-arc/keyboard.h linux/include/asm-arm/arch-arc/keyboard.h
--- v2.2.7/linux/include/asm-arm/arch-arc/keyboard.h Wed Apr 28 11:37:31 1999
+++ linux/include/asm-arm/arch-arc/keyboard.h Sat May 8 11:06:57 1999
@@ -11,7 +11,6 @@
X
X #define NR_SCANCODES 128
X
-extern int a5kkbd_translate(unsigned char scancode, unsigned char *keycode_p, char *up_flag_p);
X extern void a5kkbd_leds(unsigned char leds);
X extern void a5kkbd_init_hw(void);
X extern unsigned char a5kkbd_sysrq_xlate[NR_SCANCODES];
@@ -19,11 +18,7 @@
X #define kbd_setkeycode(sc,kc) (-EINVAL)
X #define kbd_getkeycode(sc) (-EINVAL)
X
-/* Prototype: int kbd_translate(scancode, *keycode, *up_flag, raw_mode)
- * Returns : 0 to ignore scancode, *keycode set to keycode, *up_flag
- * set to 0200 if scancode indicates release
- */
-#define kbd_translate(sc, kcp, ufp, rm) a5kkbd_translate(sc, kcp, ufp)
+#define kbd_translate(sc, kcp, rm) ({ *(kcp) = (sc); 1; })
X #define kbd_unexpected_up(kc) (0200)
X #define kbd_leds(leds) a5kkbd_leds(leds)
X #define kbd_init_hw() a5kkbd_init_hw()
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-arc/memory.h linux/include/asm-arm/arch-arc/memory.h
--- v2.2.7/linux/include/asm-arm/arch-arc/memory.h Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-arc/memory.h Sat May 8 11:06:57 1999
@@ -0,0 +1,41 @@
+/*
+ * linux/include/asm-arm/arch-arc/memory.h
+ *
+ * Copyright (c) 1996-1999 Russell King.
+ *
+ * Changelog:
+ * 22-Nov-1996 RMK Created
+ * 21-Mar-1999 RMK Renamed to memory.h
+ * RMK Moved PAGE_OFFSET and TASK_SIZE here
+ */
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
+
+/*
+ * User space: 26MB
+ */
+#define TASK_SIZE (0x01a00000UL)
+
+/*
+ * Page offset: 32MB
+ */
+#define PAGE_OFFSET (0x02000000UL)
+
+#define __virt_to_phys__is_a_macro
+#define __virt_to_phys(vpage) vpage
+#define __phys_to_virt__is_a_macro
+#define __phys_to_virt(ppage) ppage
+
+/*
+ * Virtual view <-> DMA view memory address translations
+ * virt_to_bus: Used to translate the virtual address to an
+ * address suitable to be passed to set_dma_addr
+ * bus_to_virt: Used to convert an address for DMA operations
+ * to an address that the kernel can use.
+ */
+#define __virt_to_bus__is_a_macro
+#define __virt_to_bus(x) (x)
+#define __bus_to_virt__is_a_macro
+#define __bus_to_virt(x) (x)
+
+#endif
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-arc/mmu.h linux/include/asm-arm/arch-arc/mmu.h
--- v2.2.7/linux/include/asm-arm/arch-arc/mmu.h Tue Apr 14 14:29:25 1998
+++ linux/include/asm-arm/arch-arc/mmu.h Wed Dec 31 16:00:00 1969
@@ -1,29 +0,0 @@
-/*
- * linux/include/asm-arm/arch-arc/mmu.h
- *
- * Copyright (c) 1996 Russell King.
- *
- * Changelog:
- * 22-11-1996 RMK Created
- */
-#ifndef __ASM_ARCH_MMU_H
-#define __ASM_ARCH_MMU_H
-
-#define __virt_to_phys__is_a_macro
-#define __virt_to_phys(vpage) vpage
-#define __phys_to_virt__is_a_macro
-#define __phys_to_virt(ppage) ppage
-
-/*
- * Virtual view <-> DMA view memory address translations
- * virt_to_bus: Used to translate the virtual address to an
- * address suitable to be passed to set_dma_addr
- * bus_to_virt: Used to convert an address for DMA operations
- * to an address that the kernel can use.
- */
-#define __virt_to_bus__is_a_macro
-#define __virt_to_bus(x) (x)
-#define __bus_to_virt__is_a_macro
-#define __bus_to_virt(x) (x)
-
-#endif
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-arc/oldlatches.h linux/include/asm-arm/arch-arc/oldlatches.h
--- v2.2.7/linux/include/asm-arm/arch-arc/oldlatches.h Tue Apr 14 14:29:25 1998
+++ linux/include/asm-arm/arch-arc/oldlatches.h Sat May 8 11:06:57 1999
@@ -34,6 +34,8 @@
X /* newval=(oldval & mask)|newdata */
X void oldlatch_aupdate(unsigned char mask,unsigned char newdata);
X
+void oldlatch_init(void);
+
X #elif defined(CONFIG_ARCH_A5K)
X
X #ifdef __need_oldlatches
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-arc/processor.h linux/include/asm-arm/arch-arc/processor.h
--- v2.2.7/linux/include/asm-arm/arch-arc/processor.h Fri Jan 8 22:36:20 1999
+++ linux/include/asm-arm/arch-arc/processor.h Sat May 8 11:06:57 1999
@@ -1,15 +1,18 @@
X /*
X * linux/include/asm-arm/arch-arc/processor.h
X *
- * Copyright (c) 1996 Russell King.
+ * Copyright (c) 1996-1999 Russell King.


X *
X * Changelog:

- * 10-09-1996 RMK Created
+ * 10-Sep-1996 RMK Created
+ * 21-Mar-1999 RMK Added asm/arch/memory.h
X */
X
X #ifndef __ASM_ARCH_PROCESSOR_H
X #define __ASM_ARCH_PROCESSOR_H
X
+#include <asm/arch/memory.h>
+
X /*
X * Bus types
X */
@@ -18,17 +21,9 @@
X #define MCA_bus 0
X #define MCA_bus__is_a_macro /* for versions in ksyms.c */
X
-/*
- * User space: 26MB
- */
-#define TASK_SIZE (0x01a00000UL)
-
X /* This decides where the kernel will search for a free chunk of vm
X * space during mmap's.
X */
X #define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
-
-#define INIT_MMAP \
-{ &init_mm, 0, 0, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap }
X
X #endif
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-arc/time.h linux/include/asm-arm/arch-arc/time.h
--- v2.2.7/linux/include/asm-arm/arch-arc/time.h Tue Jan 20 16:39:42 1998
+++ linux/include/asm-arm/arch-arc/time.h Sat May 8 11:06:57 1999
@@ -8,6 +8,9 @@
X * 10-Oct-1996 RMK Brought up to date with arch-sa110eval
X * 04-Dec-1997 RMK Updated for new arch/arm/time.c
X */
+#include <asm/ioc.h>
+
+static long last_rtc_update = 0; /* last time the cmos clock got updated */
X
X extern __inline__ unsigned long gettimeoffset (void)
X {
@@ -51,46 +54,140 @@
X return offset;
X }
X
-/*
- * No need to reset the timer at every irq
- */
-#define reset_timer() 1
+extern int iic_control (unsigned char, int, char *, int);
X
-/*
- * Updating of the RTC. We don't currently write the time to the
- * CMOS clock.
- */


SHAR_EOF
true || echo 'restore of patch-2.2.8 failed'
fi

echo 'End of part 25'
echo 'File patch-2.2.8 is continued in part 26'
echo 26 > _shar_seq_.tmp

Thomas...@ciw.uni-karlsruhe.de

unread,
May 12, 1999, 3:00:00 AM5/12/99
to
Archive-name: v2.2/patch-2.2.8/part26

#!/bin/sh
# this is part 26 of a 33 - part archive


# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.8 continued
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 26; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.8'
else
echo 'x - continuing with patch-2.2.8'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.8' &&

-#define update_rtc()
+static int set_rtc_time(unsigned long nowtime)
+{
+ char buf[5], ctrl;
+
+ if (iic_control(0xa1, 0, &ctrl, 1) != 0)
+ printk("RTC: failed to read control reg\n");
+
+ /*
+ * Reset divider
+ */
+ ctrl |= 0x80;
+
+ if (iic_control(0xa0, 0, &ctrl, 1) != 0)
+ printk("RTC: failed to stop the clock\n");
+
+ /*
+ * We only set the time - we don't set the date.
+ * This means that there is the possibility once
+ * a day for the correction to disrupt the date.
+ * We really ought to write the time and date, or
+ * nothing at all.
+ */
+ buf[0] = 0;
+ buf[1] = nowtime % 60; nowtime /= 60;
+ buf[2] = nowtime % 60; nowtime /= 60;
+ buf[3] = nowtime % 24;
+
+ BIN_TO_BCD(buf[1]);
+ BIN_TO_BCD(buf[2]);
+ BIN_TO_BCD(buf[3]);
+
+ if (iic_control(0xa0, 1, buf, 4) != 0)
+ printk("RTC: Failed to set the time\n");
+
+ /*
+ * Re-enable divider
+ */
+ ctrl &= ~0x80;
+
+ if (iic_control(0xa0, 0, &ctrl, 1) != 0)
+ printk("RTC: failed to start the clock\n");


+
+ return 0;
+}
+

+extern __inline__ unsigned long get_rtc_time(void)
+{
+ unsigned int year, i;
+ char buf[8];
+
+ /*
+ * The year is not part of the RTC counter
+ * registers, and is stored in RAM. This
+ * means that it will not be automatically
+ * updated.
+ */
+ if (iic_control(0xa1, 0xc0, buf, 1) != 0)
+ printk("RTC: failed to read the year\n");
+
+ /*
+ * If the year is before 1970, then the year
+ * is actually 100 in advance. This gives us
+ * a year 2070 bug...
+ */
+ year = 1900 + buf[0];


+ if (year < 1970)
+ year += 100;

+
+ /*
+ * Read the time and date in one go - this
+ * will ensure that we don't get any effects
+ * due to carry (the RTC latches the counters
+ * during a read).
+ */
+ if (iic_control(0xa1, 2, buf, 5) != 0) {
+ printk("RTC: failed to read the time and date\n");
+ memset(buf, 0, sizeof(buf));
+ }
+
+ /*
+ * The RTC combines years with date and weekday
+ * with month. We need to mask off this extra
+ * information before converting the date to
+ * binary.
+ */
+ buf[4] &= 0x1f;
+ buf[3] &= 0x3f;
+
+ for (i = 0; i < 5; i++)
+ BCD_TO_BIN(buf[i]);
+
+ return mktime(year, buf[4], buf[3], buf[2], buf[1], buf[0]);
+}
+
+static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ do_timer(regs);
+
+ /* If we have an externally synchronized linux clock, then update
+ * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
+ * called as close as possible to 500 ms before the new second starts.
+ */
+ if ((time_status & STA_UNSYNC) == 0 &&
+ xtime.tv_sec > last_rtc_update + 660 &&
+ xtime.tv_usec >= 50000 - (tick >> 1) &&
+ xtime.tv_usec < 50000 + (tick >> 1)) {
+ if (set_rtc_time(xtime.tv_sec) == 0)
+ last_rtc_update = xtime.tv_sec;
+ else
+ last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
+ }
+}
+
+static struct irqaction timerirq = {
+ timer_interrupt,
+ 0,
+ 0,
+ "timer",
+ NULL,
+ NULL
+};
X
X /*
X * Set up timer interrupt, and return the current time in seconds.
X */
-extern __inline__ unsigned long setup_timer (void)
+extern __inline__ void setup_timer(void)
X {
- extern int iic_control (unsigned char, int, char *, int);
- unsigned int year, mon, day, hour, min, sec;
- char buf[8];
-
X outb(LATCH & 255, IOC_T0LTCHL);
X outb(LATCH >> 8, IOC_T0LTCHH);
X outb(0, IOC_T0GO);
X
- iic_control (0xa0, 0xc0, buf, 1);
- year = buf[0];
- if ((year += 1900) < 1970)
- year += 100;
-
- iic_control (0xa0, 2, buf, 5);
- mon = buf[4] & 0x1f;
- day = buf[3] & 0x3f;
- hour = buf[2];
- min = buf[1];
- sec = buf[0];
- BCD_TO_BIN(mon);
- BCD_TO_BIN(day);
- BCD_TO_BIN(hour);
- BCD_TO_BIN(min);
- BCD_TO_BIN(sec);
+ xtime.tv_sec = get_rtc_time();
X
- return mktime(year, mon, day, hour, min, sec);
+ setup_arm_irq(IRQ_TIMER, &timerirq);
X }
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-arc/uncompress.h linux/include/asm-arm/arch-arc/uncompress.h
--- v2.2.7/linux/include/asm-arm/arch-arc/uncompress.h Wed Sep 9 14:51:10 1998
+++ linux/include/asm-arm/arch-arc/uncompress.h Sat May 8 11:06:57 1999
@@ -5,8 +5,6 @@
X */
X #define VIDMEM ((char *)0x02000000)
X
-#include "../arch/arm/drivers/char/font.h"
-
X int video_num_columns, video_num_lines, video_size_row;
X int white, bytes_per_char_h;
X extern unsigned long con_charconvtable[256];
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-ebsa110/a.out.h linux/include/asm-arm/arch-ebsa110/a.out.h
--- v2.2.7/linux/include/asm-arm/arch-ebsa110/a.out.h Fri Jan 8 22:36:21 1999
+++ linux/include/asm-arm/arch-ebsa110/a.out.h Sat May 8 11:06:57 1999
@@ -1,15 +1,16 @@
X /*
X * linux/include/asm-arm/arch-ebsa110/a.out.h


X *
- * Copyright (C) 1996 Russell King

+ * Copyright (C) 1996-1999 Russell King
X */

-


X #ifndef __ASM_ARCH_A_OUT_H
X #define __ASM_ARCH_A_OUT_H
X
-#ifdef __KERNEL__

-#define STACK_TOP ((current->personality==PER_LINUX_32BIT)? 0xc0000000 : 0x04000000)
-#endif
+#include <asm/arch/memory.h>
+
+#define STACK_TOP \
+ ((current->personality == PER_LINUX_32BIT) ? \
+ TASK_SIZE : 0x04000000)
X
X #endif
X
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-ebsa110/hardware.h linux/include/asm-arm/arch-ebsa110/hardware.h
--- v2.2.7/linux/include/asm-arm/arch-ebsa110/hardware.h Fri Jan 8 22:36:21 1999
+++ linux/include/asm-arm/arch-ebsa110/hardware.h Sat May 8 11:06:57 1999
@@ -1,19 +1,13 @@
X /*
X * linux/include/asm-arm/arch-ebsa110/hardware.h
X *
- * Copyright (C) 1996,1997,1998 Russell King.


+ * Copyright (C) 1996-1999 Russell King.
X *

X * This file contains the hardware definitions of the EBSA-110.


X */
-
X #ifndef __ASM_ARCH_HARDWARE_H
X #define __ASM_ARCH_HARDWARE_H
X

-/*
- * What hardware must be present
- */
-#define HAS_PCIO
-
X #ifndef __ASSEMBLER__
X
X /*
@@ -23,28 +17,28 @@
X #define PIT_T2 ((volatile unsigned char *)0xf2000009)
X #define PIT_T1 ((volatile unsigned char *)0xf2000005)
X #define PIT_T0 ((volatile unsigned char *)0xf2000001)
-#define PCIO_BASE 0xf0000000
X
X /*
X * Mapping areas
X */
X #define IO_BASE 0xe0000000
-#define IO_SIZE 0x20000000
-#define IO_START 0xe0000000
X
X /*


X * RAM definitions
X */

-#define MAPTOPHYS(a) ((unsigned long)(a) - PAGE_OFFSET)
-#define KERNTOPHYS(a) ((unsigned long)(&a))
-#define KERNEL_BASE (0xc0008000)
X #define FLUSH_BASE_PHYS 0x40000000
X
X #else
X
-#define PCIO_BASE 0xf0000000
X #define IO_BASE 0
X
X #endif
+
+#define IO_SIZE 0x20000000
+#define IO_START 0xe0000000
+
+#define FLUSH_BASE 0xdf000000
+#define PCIO_BASE 0xf0000000
+
X #endif
X
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-ebsa110/irq.h linux/include/asm-arm/arch-ebsa110/irq.h
--- v2.2.7/linux/include/asm-arm/arch-ebsa110/irq.h Wed Sep 9 14:51:10 1998
+++ linux/include/asm-arm/arch-ebsa110/irq.h Sat May 8 11:06:57 1999
@@ -11,6 +11,8 @@
X #define IRQ_MSET ((volatile unsigned char *)0xf2c00000)
X #define IRQ_MASK ((volatile unsigned char *)0xf2c00000)
X
+#define fixup_irq(x) (x)
+
X static void ebsa110_mask_and_ack_irq(unsigned int irq)
X {
X *IRQ_MCLR = 1 << irq;
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-ebsa110/memory.h linux/include/asm-arm/arch-ebsa110/memory.h
--- v2.2.7/linux/include/asm-arm/arch-ebsa110/memory.h Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-ebsa110/memory.h Sat May 8 11:06:57 1999
@@ -0,0 +1,35 @@
+/*
+ * linux/include/asm-arm/arch-ebsa110/memory.h


+ *
+ * Copyright (c) 1996-1999 Russell King.
+ *
+ * Changelog:

+ * 20-Oct-1996 RMK Created
+ * 31-Dec-1997 RMK Fixed definitions to reduce warnings


+ * 21-Mar-1999 RMK Renamed to memory.h

+ * RMK Moved TASK_SIZE and PAGE_OFFSET here


+ */
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
+
+/*

+ * Task size: 3GB
+ */
+#define TASK_SIZE (0xc0000000UL)
+
+/*
+ * Page offset: 3GB
+ */
+#define PAGE_OFFSET (0xc0000000UL)
+
+#define __virt_to_phys__is_a_macro
+#define __virt_to_phys(vpage) ((vpage) - PAGE_OFFSET)
+#define __phys_to_virt__is_a_macro
+#define __phys_to_virt(ppage) ((ppage) + PAGE_OFFSET)
+
+#define __virt_to_bus__is_a_macro
+#define __virt_to_bus(x) __virt_to_phys(x)
+#define __bus_to_virt__is_a_macro
+#define __bus_to_virt(x) __phys_to_virt(x)
+
+#endif
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-ebsa110/mm-init.h linux/include/asm-arm/arch-ebsa110/mm-init.h
--- v2.2.7/linux/include/asm-arm/arch-ebsa110/mm-init.h Wed Sep 9 14:51:10 1998
+++ linux/include/asm-arm/arch-ebsa110/mm-init.h Wed Dec 31 16:00:00 1969
@@ -1,5 +0,0 @@
-/*
- * linux/include/asm-arm/arch-ebsa110/mmap.h
- *
- * Copyright (C) 1996,1997,1998 Russell King
- */
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-ebsa110/mmu.h linux/include/asm-arm/arch-ebsa110/mmu.h
--- v2.2.7/linux/include/asm-arm/arch-ebsa110/mmu.h Wed Sep 9 14:51:10 1998
+++ linux/include/asm-arm/arch-ebsa110/mmu.h Wed Dec 31 16:00:00 1969
@@ -1,23 +0,0 @@
-/*
- * linux/include/asm-arm/arch-ebsa110/mmu.h
- *
- * Copyright (c) 1996,1997,1998 Russell King.


- *
- * Changelog:

- * 20-10-1996 RMK Created
- * 31-12-1997 RMK Fixed definitions to reduce warnings


- */
-#ifndef __ASM_ARCH_MMU_H
-#define __ASM_ARCH_MMU_H
-
-#define __virt_to_phys__is_a_macro

-#define __virt_to_phys(vpage) ((vpage) - PAGE_OFFSET)
-#define __phys_to_virt__is_a_macro
-#define __phys_to_virt(ppage) ((ppage) + PAGE_OFFSET)
-
-#define __virt_to_bus__is_a_macro
-#define __virt_to_bus(x) __virt_to_phys(x)
-#define __bus_to_virt__is_a_macro
-#define __bus_to_virt(x) __phys_to_virt(x)
-
-#endif
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-ebsa110/oldlatches.h linux/include/asm-arm/arch-ebsa110/oldlatches.h
--- v2.2.7/linux/include/asm-arm/arch-ebsa110/oldlatches.h Tue Jan 20 16:39:42 1998
+++ linux/include/asm-arm/arch-ebsa110/oldlatches.h Wed Dec 31 16:00:00 1969
@@ -1,9 +0,0 @@
-/*
- * Dummy oldlatches.h
- *


- * Copyright (C) 1996 Russell King

- */
-
-#ifdef __need_oldlatches
-#error "Old latches not present in this (rpc) machine"
-#endif
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-ebsa110/processor.h linux/include/asm-arm/arch-ebsa110/processor.h
--- v2.2.7/linux/include/asm-arm/arch-ebsa110/processor.h Fri Jan 8 22:36:21 1999
+++ linux/include/asm-arm/arch-ebsa110/processor.h Sat May 8 11:06:57 1999
@@ -1,12 +1,17 @@
X /*
X * linux/include/asm-arm/arch-ebsa110/processor.h
X *
- * Copyright (C) 1996,1997,1998 Russell King


+ * Copyright (C) 1996-1999 Russell King

+ *
+ * Changelog:

+ * 21-Mar-1999 RMK Added asm/arch/memory.h
X */
X
X #ifndef __ASM_ARCH_PROCESSOR_H
X #define __ASM_ARCH_PROCESSOR_H
X
+#include <asm/arch/memory.h>
+
X /*
X * Bus types
X */

@@ -15,17 +20,9 @@


X #define MCA_bus 0
X #define MCA_bus__is_a_macro /* for versions in ksyms.c */
X
-/*

- * User space: 3GB
- */
-#define TASK_SIZE (0xc0000000UL)


-
X /* This decides where the kernel will search for a free chunk of vm
X * space during mmap's.
X */
X #define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
-
-#define INIT_MMAP \
-{ &init_mm, 0, 0, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap }
X
X #endif

diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-ebsa110/time.h linux/include/asm-arm/arch-ebsa110/time.h
--- v2.2.7/linux/include/asm-arm/arch-ebsa110/time.h Fri Jan 8 22:36:21 1999
+++ linux/include/asm-arm/arch-ebsa110/time.h Sat May 8 11:06:57 1999
@@ -38,63 +38,67 @@


X return 0;
X }
X

-#ifndef DIVISOR
-extern __inline__ int reset_timer (void)
+static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
X {
X *PIT_T1 = (PIT1_COUNT) & 0xff;
X *PIT_T1 = (PIT1_COUNT) >> 8;
- return 1;
-}
-#else
-extern __inline__ int reset_timer (void)
-{
- static unsigned int divisor;
-#ifdef CONFIG_LEDS
- static int count = 50;
-#endif
-
- *PIT_T1 = (PIT1_COUNT) & 0xff;
- *PIT_T1 = (PIT1_COUNT) >> 8;
X
X #ifdef CONFIG_LEDS
- if (--count == 0) {
- count = 50;
- leds_event(led_timer);
+ {
+ static int count = 50;
+ if (--count == 0) {
+ count = 50;
+ leds_event(led_timer);


+ }
X }
X #endif
X

- if (divisor == 0) {
- divisor = DIVISOR - 1;
- return 1;
+ {
+#ifdef DIVISOR
+ static unsigned int divisor;
+
+ if (divisor-- == 0) {
+ divisor = DIVISOR - 1;
+#else
+ {
+#endif
+ do_timer(regs);
+ }
X }
- divisor -= 1;
- return 0;
X }
-#endif
X
-/*
- * We don't have a RTC to update!
- */
-#define update_rtc()
+static struct irqaction timerirq = {
+ timer_interrupt,
+ 0,
+ 0,
+ "timer",
+ NULL,
+ NULL
+};
X
X /*
X * Set up timer interrupt, and return the current time in seconds.
X */
-extern __inline__ unsigned long setup_timer (void)
+extern __inline__ void setup_timer(void)
X {
X /*
X * Timer 1, mode 0, 16-bit, autoreload
X */
X *PIT_CTRL = 0x70;
+
X /*
X * Refresh counter clocked at 47.8MHz/7 = 146.4ns
X * We want centi-second interrupts
X */
- reset_timer ();
+ *PIT_T1 = (PIT1_COUNT) & 0xff;
+ *PIT_T1 = (PIT1_COUNT) >> 8;
+
X /*
X * Default the date to 1 Jan 1970 0:0:0
X * You will have to run a time daemon to set the
X * clock correctly at bootup
X */
- return mktime(1970, 1, 1, 0, 0, 0);
+ xtime.tv_sec = mktime(1970, 1, 1, 0, 0, 0);
+
+ setup_arm_irq(IRQ_TIMER, &timerirq);
X }
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-ebsa285/a.out.h linux/include/asm-arm/arch-ebsa285/a.out.h
--- v2.2.7/linux/include/asm-arm/arch-ebsa285/a.out.h Fri Jan 8 22:36:21 1999
+++ linux/include/asm-arm/arch-ebsa285/a.out.h Sat May 8 11:06:57 1999
@@ -1,15 +1,16 @@
X /*
X * linux/include/asm-arm/arch-ebsa110/a.out.h


X *
- * Copyright (C) 1996 Russell King

+ * Copyright (C) 1996-1999 Russell King
X */

-


X #ifndef __ASM_ARCH_A_OUT_H
X #define __ASM_ARCH_A_OUT_H
X
-#ifdef __KERNEL__

-#define STACK_TOP ((current->personality==PER_LINUX_32BIT)? 0xc0000000 : 0x04000000)
-#endif
+#include <asm/arch/memory.h>
+
+#define STACK_TOP \
+ ((current->personality == PER_LINUX_32BIT) ? \
+ TASK_SIZE : 0x04000000)
X
X #endif
X
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-ebsa285/dma.h linux/include/asm-arm/arch-ebsa285/dma.h
--- v2.2.7/linux/include/asm-arm/arch-ebsa285/dma.h Fri Jan 8 22:36:21 1999
+++ linux/include/asm-arm/arch-ebsa285/dma.h Sat May 8 11:06:57 1999
@@ -3,8 +3,8 @@
X *
X * Architecture DMA routines
X *
- * Copyright (C) 1998 Russell King
- * Copyright (C) 1998 Philip Blundell
+ * Copyright (C) 1998,1999 Russell King
+ * Copyright (C) 1998,1999 Philip Blundell
X */
X #ifndef __ASM_ARCH_DMA_H
X #define __ASM_ARCH_DMA_H
@@ -15,12 +15,16 @@
X #define MAX_DMA_ADDRESS 0xffffffff
X
X /*
- * The 21285 has two internal DMA channels; we call these 0 and 1.
+ * The 21285 has two internal DMA channels; we call these 8 and 9.
X * On CATS hardware we have an additional eight ISA dma channels
- * numbered 2..9.
+ * numbered 0..7.
X */
+#define _ISA_DMA(x) (0+(x))
+#define _DC21285_DMA(x) (8+(x))
+
X #define MAX_DMA_CHANNELS 10
-#define DMA_ISA_BASE 2
-#define DMA_FLOPPY (DMA_ISA_BASE + 2)
+
+#define DMA_FLOPPY _ISA_DMA(2)
+#define DMA_ISA_CASCADE _ISA_DMA(4)
X
X #endif /* _ASM_ARCH_DMA_H */
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-ebsa285/hardware.h linux/include/asm-arm/arch-ebsa285/hardware.h
--- v2.2.7/linux/include/asm-arm/arch-ebsa285/hardware.h Fri Jan 8 22:36:21 1999
+++ linux/include/asm-arm/arch-ebsa285/hardware.h Sat May 8 11:06:57 1999
@@ -1,47 +1,135 @@
X /*
X * linux/include/asm-arm/arch-ebsa285/hardware.h
X *
- * Copyright (C) 1998 Russell King.
+ * Copyright (C) 1998-1999 Russell King.
X *
X * This file contains the hardware definitions of the EBSA-285.
X */
+#ifndef __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H
X
+#include <linux/config.h>
+#include <asm/arch/memory.h>
X
-/* Logical Physical
+#ifdef CONFIG_HOST_FOOTBRIDGE
+/* Virtual Physical
X * 0xfff00000 0x40000000 X-Bus
- * 0xffe00000 0x7c000000 PCI I/O space
+ * 0xff000000 0x7c000000 PCI I/O space
X *
X * 0xfe000000 0x42000000 CSR
X * 0xfd000000 0x78000000 Outbound write flush
X * 0xfc000000 0x79000000 PCI IACK/special space
X *
- * 0xf9000000 0x7a010000 PCI Config type 1
- * 0xf8000000 0x7b010000 PCI Config type 0
+ * 0xf9000000 0x7a000000 PCI Config type 1
+ * 0xf8000000 0x7b000000 PCI Config type 0
X *
X */
+#define XBUS_SIZE 0x00100000
+#define XBUS_BASE 0xfff00000
X
-#include <asm/dec21285.h>
-
-#define IO_BASE 0xe0000000
-#define PCIO_BASE 0xffe00000
-#define PCI_IACK 0xfc000000
+#define PCIO_SIZE 0x00100000
+#define PCIO_BASE 0xff000000
X
-#define XBUS_LEDS ((volatile unsigned char *)0xfff12000)
+#define ARMCSR_SIZE 0x01000000
+#define ARMCSR_BASE 0xfe000000
+
+#define WFLUSH_SIZE 0x01000000
+#define WFLUSH_BASE 0xfd000000
+
+#define PCIIACK_SIZE 0x01000000
+#define PCIIACK_BASE 0xfc000000
+
+#define PCICFG1_SIZE 0x01000000
+#define PCICFG1_BASE 0xf9000000
+
+#define PCICFG0_SIZE 0x01000000
+#define PCICFG0_BASE 0xf8000000
+
+#define PCIMEM_SIZE 0x18000000
+#define PCIMEM_BASE 0xe0000000
+
+#define FLUSH_SIZE 0x00100000
+#define FLUSH_BASE 0xdf000000
+
+#define FLASH_SIZE 0x00400000
+#define FLASH_BASE 0xd8000000
+
+#elif defined(CONFIG_ARCH_CO285)
+
+#define PCIMEM_SIZE 0x80000000
+#define PCIMEM_BASE 0x80000000
+
+#define FLASH_SIZE 0x01000000
+#define FLASH_BASE 0x7f000000
+
+#define FLUSH_SIZE 0x00100000
+#define FLUSH_BASE 0x7e000000
+
+#define WFLUSH_SIZE 0x01000000
+#define WFLUSH_BASE 0x7d000000
+
+#define ARMCSR_SIZE 0x00100000
+#define ARMCSR_BASE 0x7cf00000
+
+#define XBUS_SIZE 0x00020000
+#define XBUS_BASE 0x7cee0000
+
+#define PCIO_SIZE 0x00010000
+#define PCIO_BASE 0x7ced0000
+
+#else
+
+#error Add your add-in architecture here
+
+#endif
+
+#define XBUS_LEDS ((volatile unsigned char *)(XBUS_BASE + 0x12000))
X #define XBUS_LED_AMBER (1 << 0)
X #define XBUS_LED_GREEN (1 << 1)
X #define XBUS_LED_RED (1 << 2)
X #define XBUS_LED_TOGGLE (1 << 8)
X
-#define XBUS_SWITCH ((volatile unsigned char *)0xfff12000)
+#define XBUS_SWITCH ((volatile unsigned char *)(XBUS_BASE + 0x12000))
X #define XBUS_SWITCH_SWITCH ((*XBUS_SWITCH) & 15)
X #define XBUS_SWITCH_J17_13 ((*XBUS_SWITCH) & (1 << 4))
X #define XBUS_SWITCH_J17_11 ((*XBUS_SWITCH) & (1 << 5))
X #define XBUS_SWITCH_J17_9 ((*XBUS_SWITCH) & (1 << 6))
X
-#define KERNTOPHYS(a) ((unsigned long)(&a))
-
X #define PARAMS_OFFSET 0x0100
X #define PARAMS_BASE (PAGE_OFFSET + PARAMS_OFFSET)
X
X #define FLUSH_BASE_PHYS 0x50000000
X
+
+/* PIC irq control */
+#define PIC_LO 0x20
+#define PIC_MASK_LO 0x21
+#define PIC_HI 0xA0
+#define PIC_MASK_HI 0xA1
+
+/* GPIO pins */
+#define GPIO_CCLK 0x800
+#define GPIO_DSCLK 0x400
+#define GPIO_E2CLK 0x200
+#define GPIO_IOLOAD 0x100
+#define GPIO_RED_LED 0x080
+#define GPIO_WDTIMER 0x040
+#define GPIO_DATA 0x020
+#define GPIO_IOCLK 0x010
+#define GPIO_DONE 0x008
+#define GPIO_FAN 0x004
+#define GPIO_GREEN_LED 0x002
+#define GPIO_RESET 0x001
+
+/* CPLD pins */
+#define CPLD_DSRESET 8
+#define CPLD_UNMUTE 2
+
+#ifndef __ASSEMBLY__
+extern void gpio_modify_op(int mask, int set);
+extern void gpio_modify_io(int mask, int in);
+extern int gpio_read(void);
+extern void cpld_modify(int mask, int set);
+#endif
+
+#endif
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-ebsa285/io.h linux/include/asm-arm/arch-ebsa285/io.h
--- v2.2.7/linux/include/asm-arm/arch-ebsa285/io.h Fri Jan 8 22:36:21 1999
+++ linux/include/asm-arm/arch-ebsa285/io.h Sat May 8 11:06:57 1999
@@ -16,34 +16,37 @@
X * has the constant-optimised IO
X */
X #undef ARCH_IO_DELAY
+#define ARCH_READWRITE
X
X /*
X * Dynamic IO functions - let the compiler
X * optimize the expressions
X */
-#define DECLARE_DYN_OUT(fnsuffix,instr,typ) \
-extern __inline__ void __out##fnsuffix (unsigned int value, unsigned int port) \
-{ \
- __asm__ __volatile__( \
- "str%?" ##instr## " %0, [%1, %2] @ out"###fnsuffix \
- : \
- : "r" (value), "r" (PCIO_BASE), typ (port)); \
-}
-
-#define DECLARE_DYN_IN(sz,fnsuffix,instr,typ) \
-extern __inline__ unsigned sz __in##fnsuffix (unsigned int port) \
-{ \
- unsigned long value; \
- __asm__ __volatile__( \
- "ldr%?" ##instr## " %0, [%1, %2] @ in"###fnsuffix \
- : "=&r" (value) \
- : "r" (PCIO_BASE), typ (port)); \
- return (unsigned sz)value; \
-}
-
-extern __inline__ unsigned int __ioaddr (unsigned int port) \
-{ \
- return (unsigned int)(PCIO_BASE + port); \
+#define DECLARE_DYN_OUT(fnsuffix,instr,typ) \
+extern __inline__ void \
+__out##fnsuffix (unsigned int value, unsigned int port) \
+{ \
+ __asm__ __volatile__( \
+ "str%?" ##instr## " %0, [%1, %2] @ out"###fnsuffix \
+ : \
+ : "r" (value), "r" (PCIO_BASE), typ (port)); \
+}
+
+#define DECLARE_DYN_IN(sz,fnsuffix,instr,typ) \
+extern __inline__ unsigned sz \
+__in##fnsuffix (unsigned int port) \
+{ \
+ unsigned long value; \
+ __asm__ __volatile__( \
+ "ldr%?" ##instr## " %0, [%1, %2] @ in"###fnsuffix \
+ : "=&r" (value) \
+ : "r" (PCIO_BASE), typ (port)); \
+ return (unsigned sz)value; \
+}
+
+extern __inline__ unsigned int __ioaddr (unsigned int port) \
+{ \
+ return (unsigned int)(PCIO_BASE + port); \
X }
X
X #define DECLARE_IO(sz,fnsuffix,instr,typ) \
@@ -64,65 +67,65 @@
X * These have to be macros for the 'J' constraint to work -
X * +/-4096 immediate operand.
X */
-#define __outbc(value,port) \
-({ \
- __asm__ __volatile__( \
- "str%?b %0, [%1, %2] @ outbc" \
- : \
- : "r" (value), "r" (PCIO_BASE), "Jr" (port)); \
-})
-
-#define __inbc(port) \
-({ \
- unsigned char result; \
- __asm__ __volatile__( \
- "ldr%?b %0, [%1, %2] @ inbc" \
- : "=r" (result) \
- : "r" (PCIO_BASE), "Jr" (port)); \
- result; \
-})
-
-#define __outwc(value,port) \
-({ \
- __asm__ __volatile__( \
- "str%?h %0, [%1, %2] @ outwc" \
- : \
- : "r" (value), "r" (PCIO_BASE), "r" (port)); \
-})
-
-#define __inwc(port) \
-({ \
- unsigned short result; \
- __asm__ __volatile__( \
- "ldr%?h %0, [%1, %2] @ inwc" \
- : "=r" (result) \
- : "r" (PCIO_BASE), "r" (port)); \
- result & 0xffff; \
-})
-
-#define __outlc(value,port) \
-({ \
- __asm__ __volatile__( \
- "str%? %0, [%1, %2] @ outlc" \
- : \
- : "r" (value), "r" (PCIO_BASE), "Jr" (port)); \
-})
-
-#define __inlc(port) \
-({ \
- unsigned long result; \
- __asm__ __volatile__( \
- "ldr%? %0, [%1, %2] @ inlc" \
- : "=r" (result) \
- : "r" (PCIO_BASE), "Jr" (port)); \
- result; \
-})
-
-#define __ioaddrc(port) \
-({ \
- unsigned long addr; \
- addr = PCIO_BASE + port; \
- addr; \
+#define __outbc(value,port) \
+({ \
+ __asm__ __volatile__( \
+ "str%?b %0, [%1, %2] @ outbc" \
+ : \
+ : "r" (value), "r" (PCIO_BASE), "Jr" (port)); \
+})
+
+#define __inbc(port) \
+({ \
+ unsigned char result; \
+ __asm__ __volatile__( \
+ "ldr%?b %0, [%1, %2] @ inbc" \
+ : "=r" (result) \
+ : "r" (PCIO_BASE), "Jr" (port)); \
+ result; \
+})
+
+#define __outwc(value,port) \
+({ \
+ __asm__ __volatile__( \
+ "str%?h %0, [%1, %2] @ outwc" \
+ : \
+ : "r" (value), "r" (PCIO_BASE), "r" (port)); \
+})
+
+#define __inwc(port) \
+({ \
+ unsigned short result; \
+ __asm__ __volatile__( \
+ "ldr%?h %0, [%1, %2] @ inwc" \
+ : "=r" (result) \
+ : "r" (PCIO_BASE), "r" (port)); \
+ result & 0xffff; \
+})
+
+#define __outlc(value,port) \
+({ \
+ __asm__ __volatile__( \
+ "str%? %0, [%1, %2] @ outlc" \
+ : \
+ : "r" (value), "r" (PCIO_BASE), "Jr" (port)); \
+})
+
+#define __inlc(port) \
+({ \
+ unsigned long result; \
+ __asm__ __volatile__( \
+ "ldr%? %0, [%1, %2] @ inlc" \
+ : "=r" (result) \
+ : "r" (PCIO_BASE), "Jr" (port)); \
+ result; \
+})
+
+#define __ioaddrc(port) \
+({ \
+ unsigned long addr; \
+ addr = PCIO_BASE + port; \
+ addr; \
X })
X
X /*
@@ -130,20 +133,22 @@
X *
X * IO address has already been translated to a virtual address
X */
-#define outb_t(v,p) \
+#define outb_t(v,p) \
X (*(volatile unsigned char *)(p) = (v))
X
-#define inb_t(p) \
+#define inb_t(p) \
X (*(volatile unsigned char *)(p))
X
-#define outl_t(v,p) \
+#define outl_t(v,p) \
X (*(volatile unsigned long *)(p) = (v))
X
-#define inl_t(p) \
+#define inl_t(p) \
X (*(volatile unsigned long *)(p))
X
X /*
- * ioremap support
+ * ioremap support - validate a PCI memory address,
+ * and convert a PCI memory address to a physical
+ * address for the page tables.
X */
X #define valid_ioaddr(iomem,size) ((iomem) < 0x80000000 && (iomem) + (size) <= 0x80000000)
X #define io_to_phys(iomem) ((iomem) + DC21285_PCI_MEM)
@@ -153,58 +158,48 @@
X * is using read*() and so on with addresses they didn't get from ioremap
X * this can go away.
X */
-#define IO_FUDGE_FACTOR 0xe0000000
+#define IO_FUDGE_FACTOR PCIMEM_BASE
X
-extern inline void *ioremap(unsigned long iomem_addr, unsigned long size)
-{
- unsigned long phys_addr;
-
- if (!valid_ioaddr(iomem_addr, size))
- return NULL;
-
- phys_addr = io_to_phys(iomem_addr & PAGE_MASK);
-
- return (void *)((unsigned long)__ioremap(phys_addr, size, 0)
- - IO_FUDGE_FACTOR);
-}
+/*
+ * ioremap takes a PCI memory address, as specified in
+ * linux/Documentation/IO-mapping.txt
+ */
+#define ioremap(iomem_addr,size) \
+({ \
+ unsigned long _addr = (iomem_addr), _size = (size); \
+ void *_ret = NULL; \
+ if (valid_ioaddr(_addr, _size)) { \
+ _addr = io_to_phys(_addr); \
+ _ret = __ioremap(_addr, _size, 0) - IO_FUDGE_FACTOR; \
+ } \
+ _ret; })
X
X #define ioremap_nocache(iomem_addr,size) ioremap((iomem_addr),(size))
X
X extern void iounmap(void *addr);
X
-/*
- * We'd probably be better off with these as macros rather than functions.
- * Firstly that would be more efficient and secondly we could do with the
- * ability to stop GCC whinging about type conversions. --philb
- */
-static inline void writeb(unsigned char b, unsigned int addr)
-{
- *(volatile unsigned char *)(IO_FUDGE_FACTOR + (addr)) = b;
-}
-
-static inline unsigned char readb(unsigned int addr)
-{
- return *(volatile unsigned char *)(IO_FUDGE_FACTOR + (addr));
+#define DECLARE_PCI_WRITE(typ,fnsuffix) \
+static inline void write##fnsuffix(unsigned typ val, unsigned int addr) \
+{ \
+ *(volatile unsigned typ *)(IO_FUDGE_FACTOR + addr) = val; \
X }
X
-static inline void writew(unsigned short b, unsigned int addr)
-{
- *(volatile unsigned short *)(IO_FUDGE_FACTOR + (addr)) = b;
+#define DECLARE_PCI_READ(typ,fnsuffix) \
+static inline unsigned typ read##fnsuffix (unsigned int addr) \
+{ \
+ return *(volatile unsigned typ *)(IO_FUDGE_FACTOR + addr); \
X }
X
-static inline unsigned short readw(unsigned int addr)
-{
- return *(volatile unsigned short *)(IO_FUDGE_FACTOR + (addr));
-}
+#define DECLARE_PCI(typ,fnsuffix) \
+ DECLARE_PCI_WRITE(typ,fnsuffix) \
+ DECLARE_PCI_READ(typ,fnsuffix)
X
-static inline void writel(unsigned long b, unsigned int addr)
-{
- *(volatile unsigned long *)(IO_FUDGE_FACTOR + (addr)) = b;
-}
+DECLARE_PCI(char,b)
+DECLARE_PCI(short,w)
+DECLARE_PCI(long,l)
X
-static inline unsigned short readl(unsigned int addr)
-{
- return *(volatile unsigned long *)(IO_FUDGE_FACTOR + (addr));
-}
+#undef DECLARE_PCI
+#undef DECLARE_PCI_READ
+#undef DECLARE_PCI_WRITE
X
X #endif
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-ebsa285/irq.h linux/include/asm-arm/arch-ebsa285/irq.h
--- v2.2.7/linux/include/asm-arm/arch-ebsa285/irq.h Fri Jan 8 22:36:21 1999
+++ linux/include/asm-arm/arch-ebsa285/irq.h Mon May 10 10:17:28 1999
@@ -4,136 +4,206 @@
X * Copyright (C) 1996-1998 Russell King


X *
X * Changelog:

- * 22-08-1998 RMK Restructured IRQ routines
- * 03-09-1998 PJB Merged CATS support
+ * 22-Aug-1998 RMK Restructured IRQ routines
+ * 03-Sep-1998 PJB Merged CATS support
+ * 20-Jan-1998 RMK Started merge of EBSA286, CATS and NetWinder
+ * 26-Jan-1999 PJB Don't use IACK on CATS
+ * 16-Mar-1999 RMK Added autodetect of ISA PICs
X */
X #include <linux/config.h>
+#include <asm/hardware.h>
+#include <asm/dec21285.h>
+#include <asm/irq.h>
X
-static void ebsa285_mask_irq(unsigned int irq)
+/*
+ * Footbridge IRQ translation table
+ * Converts from our IRQ numbers into FootBridge masks
+ */
+static int dc21285_irq_mask[] = {
+ IRQ_MASK_UART_RX, /* 0 */
+ IRQ_MASK_UART_TX, /* 1 */
+ IRQ_MASK_TIMER1, /* 2 */
+ IRQ_MASK_TIMER2, /* 3 */
+ IRQ_MASK_TIMER3, /* 4 */
+ IRQ_MASK_IN0, /* 5 */
+ IRQ_MASK_IN1, /* 6 */
+ IRQ_MASK_IN2, /* 7 */
+ IRQ_MASK_IN3, /* 8 */
+ IRQ_MASK_DOORBELLHOST, /* 9 */
+ IRQ_MASK_DMA1, /* 10 */
+ IRQ_MASK_DMA2, /* 11 */
+ IRQ_MASK_PCI, /* 12 */
+ IRQ_MASK_SDRAMPARITY, /* 13 */
+ IRQ_MASK_I2OINPOST, /* 14 */
+ IRQ_MASK_PCI_ERR /* 15 */
+};
+
+static int isa_irq = -1;
+
+static inline int fixup_irq(unsigned int irq)
+{
+#ifdef CONFIG_HOST_FOOTBRIDGE
+ if (irq == isa_irq)
+ irq = *(unsigned char *)PCIIACK_BASE;
+#endif


+
+ return irq;
+}
+

+static void dc21285_mask_irq(unsigned int irq)
X {
- *CSR_IRQ_DISABLE = 1 << irq;
+ *CSR_IRQ_DISABLE = dc21285_irq_mask[irq & 15];
X }
X
-static void ebsa285_unmask_irq(unsigned int irq)
+static void dc21285_unmask_irq(unsigned int irq)
X {
- *CSR_IRQ_ENABLE = 1 << irq;
+ *CSR_IRQ_ENABLE = dc21285_irq_mask[irq & 15];
X }
X
-#ifdef CONFIG_CATS
+static void isa_mask_pic_lo_irq(unsigned int irq)
+{
+ unsigned int mask = 1 << (irq & 7);
X
-/*
- * This contains the irq mask for both 8259A irq controllers,
- */
-static unsigned int isa_irq_mask = 0xffff;
+ outb(inb(PIC_MASK_LO) | mask, PIC_MASK_LO);
+}
X
-#define cached_21 (isa_irq_mask & 0xff)
-#define cached_A1 ((isa_irq_mask >> 8) & 0xff)
+static void isa_mask_ack_pic_lo_irq(unsigned int irq)
+{
+ unsigned int mask = 1 << (irq & 7);
X
-#define update_8259(_irq) \
- if ((_irq) & 8) \
- outb(cached_A1, 0xa1); \
- else \
- outb(cached_21, 0x21);
-
-static void isa_interrupt(int irq, void *h, struct pt_regs *regs)
-{
- asmlinkage void do_IRQ(int irq, struct pt_regs * regs);
- unsigned int irqbits = inb(0x20) | (inb(0xa0) << 8), irqnr = 0;
- irqbits &= ~(1<<2); /* don't try to service the cascade */
- while (irqbits) {
- if (irqbits & 1)
- do_IRQ(32 + irqnr, regs);
- irqbits >>= 1;
- irqnr++;
- }
+ outb(inb(PIC_MASK_LO) | mask, PIC_MASK_LO);
+ outb(0x20, PIC_LO);
X }
X
-static void no_action(int cpl, void *dev_id, struct pt_regs *regs) { }
+static void isa_unmask_pic_lo_irq(unsigned int irq)
+{
+ unsigned int mask = 1 << (irq & 7);
+
+ outb(inb(PIC_MASK_LO) & ~mask, PIC_MASK_LO);
+}
X
-static struct irqaction irq_isa =
- { isa_interrupt, SA_INTERRUPT, 0, "ISA PIC", NULL, NULL };
-static struct irqaction irq_cascade =
- { no_action, 0, 0, "cascade", NULL, NULL };
-
-static void cats_mask_and_ack_isa_irq(unsigned int irq)
-{
- isa_irq_mask |= (1 << (irq - 32));
- update_8259(irq);
- if (irq & 8) {


- inb(0xA1); /* DUMMY */
- outb(cached_A1,0xA1);
- outb(0x62,0x20); /* Specific EOI to cascade */

- outb(0x20,0xA0);
- } else {


- inb(0x21); /* DUMMY */
- outb(cached_21,0x21);

- outb(0x20,0x20);
- }
+static void isa_mask_pic_hi_irq(unsigned int irq)
+{
+ unsigned int mask = 1 << (irq & 7);
+
+ outb(inb(PIC_MASK_HI) | mask, PIC_MASK_HI);
X }
X
-static void cats_mask_isa_irq(unsigned int irq)
+static void isa_mask_ack_pic_hi_irq(unsigned int irq)
X {
- isa_irq_mask |= (1 << (irq - 32));
- update_8259(irq);
+ unsigned int mask = 1 << (irq & 7);
+
+ outb(inb(PIC_MASK_HI) | mask, PIC_MASK_HI);
+ outb(0x62, PIC_LO);
+ outb(0x20, PIC_HI);
X }
X
-static void cats_unmask_isa_irq(unsigned int irq)
+static void isa_unmask_pic_hi_irq(unsigned int irq)
X {
- isa_irq_mask &= ~(1 << (irq - 32));
- update_8259(irq);
+ unsigned int mask = 1 << (irq & 7);
+
+ outb(inb(PIC_MASK_HI) & ~mask, PIC_MASK_HI);
X }
-
-#endif
+
+static void no_action(int cpl, void *dev_id, struct pt_regs *regs)
+{
+}
+
+static struct irqaction irq_cascade = { no_action, 0, 0, "cascade", NULL, NULL };
X
X static __inline__ void irq_init_irq(void)
X {
X int irq;
X
+ /*
+ * setup DC21285 IRQs
+ */
X *CSR_IRQ_DISABLE = -1;
X *CSR_FIQ_DISABLE = -1;
X
- for (irq = 0; irq < NR_IRQS; irq++) {
+ for (irq = _DC21285_IRQ(0); irq < _DC21285_IRQ(16); irq++) {


X irq_desc[irq].valid = 1;

X irq_desc[irq].probe_ok = 1;
-#ifdef CONFIG_CATS
- if (machine_is_cats() && IRQ_IS_ISA(irq)) {
- irq_desc[irq].mask_ack = cats_mask_and_ack_isa_irq;
- irq_desc[irq].mask = cats_mask_isa_irq;
- irq_desc[irq].unmask = cats_unmask_isa_irq;
+ irq_desc[irq].mask_ack = dc21285_mask_irq;
+ irq_desc[irq].mask = dc21285_mask_irq;
+ irq_desc[irq].unmask = dc21285_unmask_irq;
+ }
+
+ /*
+ * Determine the ISA settings for
+ * the machine we're running on.
+ */
+ switch (machine_arch_type) {
+ default:
+ isa_irq = -1;
+ break;
+
+ case MACH_TYPE_EBSA285:
+ /* The following is dependent on which slot
+ * you plug the Southbridge card into. We
+ * currently assume that you plug it into
+ * the right-hand most slot.
+ */
+ isa_irq = IRQ_PCI;
+ break;
+
+ case MACH_TYPE_CATS:
+ isa_irq = IRQ_IN2;
+ break;
+
+ case MACH_TYPE_NETWINDER:
+ isa_irq = IRQ_IN3;
+ break;
+ }
+
+ if (isa_irq != -1) {
+ /*
+ * Setup, and then probe for an ISA PIC
+ */
+ outb(0x11, PIC_LO);
+ outb(_ISA_IRQ(0), PIC_MASK_LO); /* IRQ number */
+ outb(0x04, PIC_MASK_LO); /* Slave on Ch2 */
+ outb(0x01, PIC_MASK_LO); /* x86 */
+ outb(0xf5, PIC_MASK_LO); /* pattern: 11110101 */
+
+ outb(0x11, PIC_HI);
+ outb(_ISA_IRQ(8), PIC_MASK_HI); /* IRQ number */
+ outb(0x02, PIC_MASK_HI); /* Slave on Ch1 */
+ outb(0x01, PIC_MASK_HI); /* x86 */
+ outb(0xfa, PIC_MASK_HI); /* pattern: 11111010 */
+
+// outb(0x68, PIC_LO); /* enable special mode */
+// outb(0x68, PIC_HI); /* enable special mode */
+ outb(0x0b, PIC_LO);
+ outb(0x0b, PIC_HI);
+
+ if (inb(PIC_MASK_LO) == 0xf5 && inb(PIC_MASK_HI) == 0xfa) {
+ outb(0xff, PIC_MASK_LO);/* mask all IRQs */
+ outb(0xff, PIC_MASK_HI);/* mask all IRQs */
X } else
-#endif
- {
- irq_desc[irq].mask_ack = ebsa285_mask_irq;
- irq_desc[irq].mask = ebsa285_mask_irq;
- irq_desc[irq].unmask = ebsa285_unmask_irq;
- }
+ isa_irq = -1;
X }
X
-#ifdef CONFIG_CATS
- if (machine_is_cats()) {
- request_region(0x20, 2, "pic1");
- request_region(0xa0, 2, "pic2");
-
- /* set up master 8259 */
- outb(0x11, 0x20);
- outb(0, 0x21);
- outb(1<<2, 0x21);
- outb(0x1, 0x21);
- outb(0xff, 0x21);
- outb(0x68, 0x20);
- outb(0xa, 0x20);
-
- /* set up slave 8259 */
- outb(0x11, 0xa0);
- outb(0, 0xa1);
- outb(2, 0xa1);
- outb(0x1, 0xa1);
- outb(0xff, 0xa1);
- outb(0x68, 0xa0);
- outb(0xa, 0xa0);
+ if (isa_irq != -1) {
+ for (irq = _ISA_IRQ(0); irq < _ISA_IRQ(8); irq++) {


+ irq_desc[irq].valid = 1;

+ irq_desc[irq].probe_ok = 1;
+ irq_desc[irq].mask_ack = isa_mask_ack_pic_lo_irq;
+ irq_desc[irq].mask = isa_mask_pic_lo_irq;
+ irq_desc[irq].unmask = isa_unmask_pic_lo_irq;
+ }
+
+ for (irq = _ISA_IRQ(8); irq < _ISA_IRQ(16); irq++) {


+ irq_desc[irq].valid = 1;

+ irq_desc[irq].probe_ok = 1;
+ irq_desc[irq].mask_ack = isa_mask_ack_pic_hi_irq;
+ irq_desc[irq].mask = isa_mask_pic_hi_irq;
+ irq_desc[irq].unmask = isa_unmask_pic_hi_irq;
+ }
X
- setup_arm_irq(IRQ_ISA_PIC, &irq_isa);
+ request_region(PIC_LO, 2, "pic1");
+ request_region(PIC_HI, 2, "pic2");
X setup_arm_irq(IRQ_ISA_CASCADE, &irq_cascade);
+ setup_arm_irq(isa_irq, &irq_cascade);
X }
-#endif
X }
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-ebsa285/irqs.h linux/include/asm-arm/arch-ebsa285/irqs.h
--- v2.2.7/linux/include/asm-arm/arch-ebsa285/irqs.h Tue Dec 22 14:16:58 1998
+++ linux/include/asm-arm/arch-ebsa285/irqs.h Sat May 8 11:06:57 1999
@@ -3,55 +3,85 @@
X *
X * Copyright (C) 1998 Russell King
X * Copyright (C) 1998 Phil Blundell


+ *
+ * Changelog:

+ * 20-Jan-1998 RMK Started merge of EBSA286, CATS and NetWinder
+ * 01-Feb-1999 PJB ISA IRQs start at 0 not 16
X */
X
-#define NR_IRQS 48
+#define NR_IRQS 32
+#define NR_DC21285_IRQS 16
+
+#define _ISA_IRQ(x) (0 + (x))
+#define _DC21285_IRQ(x) (16 + (x))
X
X /*
X * This is a list of all interrupts that the 21285
- * can generate
+ * can generate and we handle.
X */
-#define IRQ_RESERVED 0
-#define IRQ_SOFTIRQ 1
-#define IRQ_CONRX 2
-#define IRQ_CONTX 3
-#define IRQ_TIMER1 4
-#define IRQ_TIMER2 5
-#define IRQ_TIMER3 6
-#define IRQ_TIMER4 7
-#define IRQ_IN0 8
-#define IRQ_IN1 9
-#define IRQ_IN2 10
-#define IRQ_IN3 11
-#define IRQ_XCS0 12
-#define IRQ_XCS1 13
-#define IRQ_XCS2 14
-#define IRQ_DOORBELLHOST 15
-#define IRQ_DMA1 16
-#define IRQ_DMA2 17
-#define IRQ_PCI 18
-#define IRQ_BIST 22
-#define IRQ_SERR 23
-#define IRQ_SDRAMPARITY 24
-#define IRQ_I2OINPOST 25
-#define IRQ_DISCARDTIMER 27
-#define IRQ_PCIDATAPARITY 28
-#define IRQ_PCIMASTERABORT 29
-#define IRQ_PCITARGETABORT 30
-#define IRQ_PCIPARITY 31
-
-/* IRQs 32-47 are the 16 ISA interrupts on a CATS board. */
-#define IRQ_ISA_PIC IRQ_IN2
-#define IRQ_IS_ISA(_x) (((_x) >= 32) && ((_x) <= 47))
-#define IRQ_ISA(_x) ((_x) + 0x20)
-#define IRQ_ISA_CASCADE IRQ_ISA(2)
+#define IRQ_CONRX _DC21285_IRQ(0)
+#define IRQ_CONTX _DC21285_IRQ(1)
+#define IRQ_TIMER1 _DC21285_IRQ(2)
+#define IRQ_TIMER2 _DC21285_IRQ(3)
+#define IRQ_TIMER3 _DC21285_IRQ(4)
+#define IRQ_IN0 _DC21285_IRQ(5)
+#define IRQ_IN1 _DC21285_IRQ(6)
+#define IRQ_IN2 _DC21285_IRQ(7)
+#define IRQ_IN3 _DC21285_IRQ(8)
+#define IRQ_DOORBELLHOST _DC21285_IRQ(9)
+#define IRQ_DMA1 _DC21285_IRQ(10)
+#define IRQ_DMA2 _DC21285_IRQ(11)
+#define IRQ_PCI _DC21285_IRQ(12)
+#define IRQ_SDRAMPARITY _DC21285_IRQ(13)
+#define IRQ_I2OINPOST _DC21285_IRQ(14)
+#define IRQ_PCI_ERR _DC21285_IRQ(15)
+
+#define IRQ_ISA_TIMER _ISA_IRQ(0)
+#define IRQ_ISA_KEYBOARD _ISA_IRQ(1)
+#define IRQ_ISA_CASCADE _ISA_IRQ(2)
+#define IRQ_ISA_UART2 _ISA_IRQ(3)
+#define IRQ_ISA_UART _ISA_IRQ(4)
+#define IRQ_ISA_FLOPPY _ISA_IRQ(6)
+#define IRQ_ISA_PRINTER _ISA_IRQ(7)
+#define IRQ_ISA_RTC_ALARM _ISA_IRQ(8)
+#define IRQ_ISA_2 _ISA_IRQ(9)
+#define IRQ_ISA_PS2MOUSE _ISA_IRQ(12)
+#define IRQ_ISA_HARDDISK1 _ISA_IRQ(14)
+#define IRQ_ISA_HARDDISK2 _ISA_IRQ(15)
+
+#define IRQ_MASK_UART_RX (1 << 2)
+#define IRQ_MASK_UART_TX (1 << 3)
+#define IRQ_MASK_TIMER1 (1 << 4)
+#define IRQ_MASK_TIMER2 (1 << 5)
+#define IRQ_MASK_TIMER3 (1 << 6)
+#define IRQ_MASK_IN0 (1 << 8)
+#define IRQ_MASK_IN1 (1 << 9)
+#define IRQ_MASK_IN2 (1 << 10)
+#define IRQ_MASK_IN3 (1 << 11)
+#define IRQ_MASK_DOORBELLHOST (1 << 15)
+#define IRQ_MASK_DMA1 (1 << 16)
+#define IRQ_MASK_DMA2 (1 << 17)
+#define IRQ_MASK_PCI (1 << 18)
+#define IRQ_MASK_SDRAMPARITY (1 << 24)
+#define IRQ_MASK_I2OINPOST (1 << 25)
+#define IRQ_MASK_PCI_ERR ((1 <<23) | (1 << 27) | (1 << 28) | (1 << 29) | (1 << 30) | (1 << 31))
X
X /*
- * Now map them to the Linux interrupts
+ * Netwinder interrupt allocations
X */
-#define IRQ_TIMER IRQ_TIMER1
-#define IRQ_FLOPPYDISK IRQ_ISA(6)
-#define IRQ_HARDDISK IRQ_ISA(14)
-#define IRQ_HARDDISK_SECONDARY IRQ_ISA(15)
+#define IRQ_NETWINDER_ETHER10 IRQ_IN0
+#define IRQ_NETWINDER_ETHER100 IRQ_IN1
+#define IRQ_NETWINDER_VIDCOMP IRQ_IN2
+#define IRQ_NETWINDER_PS2MOUSE _ISA_IRQ(5)
+#define IRQ_NETWINDER_IR _ISA_IRQ(6)
+#define IRQ_NETWINDER_BUTTON _ISA_IRQ(10)
+#define IRQ_NETWINDER_VGA _ISA_IRQ(11)
+#define IRQ_NETWINDER_SOUND _ISA_IRQ(12)
+
+#undef RTC_IRQ
+#define RTC_IRQ IRQ_ISA_RTC_ALARM
+#undef AUX_IRQ
+#define AUX_IRQ (machine_is_netwinder() ? IRQ_NETWINDER_PS2MOUSE : IRQ_ISA_PS2MOUSE)
+#define IRQ_FLOPPYDISK IRQ_ISA_FLOPPY
X
-#define irq_cannonicalize(_i) (((_i) == IRQ_ISA_CASCADE) ? IRQ_ISA(9) : _i)
+#define irq_cannonicalize(_i) (((_i) == IRQ_ISA_CASCADE) ? IRQ_ISA_2 : _i)
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-ebsa285/keyboard.h linux/include/asm-arm/arch-ebsa285/keyboard.h
--- v2.2.7/linux/include/asm-arm/arch-ebsa285/keyboard.h Wed Apr 28 11:37:31 1999
+++ linux/include/asm-arm/arch-ebsa285/keyboard.h Sat May 8 11:06:57 1999
@@ -6,16 +6,10 @@
X * (C) 1998 Russell King
X * (C) 1998 Phil Blundell
X */
-
-#include <linux/config.h>
X #include <asm/irq.h>
X #include <asm/system.h>
X
-#define NR_SCANCODES 128
-
-#ifdef CONFIG_CATS
-
-#define KEYBOARD_IRQ IRQ_ISA(1)
+extern int have_isa_bridge;
X
X extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode);
X extern int pckbd_getkeycode(unsigned int scancode);
@@ -26,40 +20,52 @@
X extern void pckbd_init_hw(void);
X extern unsigned char pckbd_sysrq_xlate[128];
X
-#define kbd_setkeycode pckbd_setkeycode
-#define kbd_getkeycode pckbd_getkeycode
-#define kbd_translate(sc, kcp, ufp, rm) ({ *ufp = sc & 0200; \
- pckbd_translate(sc & 0x7f, kcp, rm);})
+#define KEYBOARD_IRQ IRQ_ISA_KEYBOARD
X
-#define kbd_unexpected_up pckbd_unexpected_up
-#define kbd_leds pckbd_leds
-#define kbd_init_hw() \
- do { if (machine_is_cats()) pckbd_init_hw(); } while (0)
-#define kbd_sysrq_xlate pckbd_sysrq_xlate
-#define kbd_disable_irq()
-#define kbd_enable_irq()
+#define NR_SCANCODES 128
X
-#define SYSRQ_KEY 0x54
+#define kbd_setkeycode(sc,kc) \
+ ({ \
+ int __ret; \
+ if (have_isa_bridge) \
+ __ret = pckbd_setkeycode(sc,kc);\
+ else \
+ __ret = -EINVAL; \
+ __ret; \
+ })
+
+#define kbd_getkeycode(sc) \
+ ({ \
+ int __ret; \
+ if (have_isa_bridge) \
+ __ret = pckbd_getkeycode(sc); \
+ else \
+ __ret = -EINVAL; \
+ __ret; \
+ })
+
+#define kbd_translate(sc, kcp, rm) \
+ ({ \
+ pckbd_translate(sc, kcp, rm); \
+ })
X
-#else
+#define kbd_unexpected_up pckbd_unexpected_up
X
-/* Dummy keyboard definitions */
+#define kbd_leds(leds) \
+ do { \
+ if (have_isa_bridge) \
+ pckbd_leds(leds); \
+ } while (0)
+
+#define kbd_init_hw() \
+ do { \
+ if (have_isa_bridge) \
+ pckbd_init_hw(); \
+ } while (0)
X
-#define kbd_setkeycode(sc,kc) (-EINVAL)
-#define kbd_getkeycode(sc) (-EINVAL)
+#define kbd_sysrq_xlate pckbd_sysrq_xlate


X
-/* Prototype: int kbd_translate(scancode, *keycode, *up_flag, raw_mode)
- * Returns : 0 to ignore scancode, *keycode set to keycode, *up_flag
- * set to 0200 if scancode indicates release
- */

-#define kbd_translate(sc, kcp, ufp, rm) (1)
-#define kbd_unexpected_up(kc) (0200)
-#define kbd_leds(leds)
-#define kbd_init_hw()
-//#define kbd_sysrq_xlate ps2kbd_sysrq_xlate
X #define kbd_disable_irq()
X #define kbd_enable_irq()
X
-#define SYSRQ_KEY 13
-
-#endif
+#define SYSRQ_KEY 0x54
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-ebsa285/memory.h linux/include/asm-arm/arch-ebsa285/memory.h
--- v2.2.7/linux/include/asm-arm/arch-ebsa285/memory.h Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-ebsa285/memory.h Mon May 10 10:17:28 1999
@@ -0,0 +1,74 @@
+/*
+ * linux/include/asm-arm/arch-ebsa285/memory.h


+ *
+ * Copyright (c) 1996-1999 Russell King.
+ *
+ * Changelog:

+ * 20-Oct-1996 RMK Created
+ * 31-Dec-1997 RMK Fixed definitions to reduce warnings.
+ * 17-May-1998 DAG Added __virt_to_bus and __bus_to_virt functions.
+ * 21-Nov-1998 RMK Changed __virt_to_bus and __bus_to_virt to macros.
+ * 21-Mar-1999 RMK Added PAGE_OFFSET for co285 architecture.
+ * Renamed to memory.h
+ * Moved PAGE_OFFSET and TASK_SIZE here
+ */
+#ifndef __ASM_ARCH_MMU_H
+#define __ASM_ARCH_MMU_H
+
+#include <linux/config.h>
+
+#if defined(CONFIG_HOST_FOOTBRIDGE)
+
+/*
+ * Task size: 3GB
+ */
+#define TASK_SIZE (0xc0000000UL)
+
+/*
+ * Page offset: 3GB
+ */
+#define PAGE_OFFSET (0xc0000000UL)
+
+#define __virt_to_bus__is_a_macro
+#define __virt_to_bus(x) ((x) - 0xe0000000)
+#define __bus_to_virt__is_a_macro
+#define __bus_to_virt(x) ((x) + 0xe0000000)
+
+#elif defined(CONFIG_ADDIN_FOOTBRIDGE)
+
+#if defined(CONFIG_ARCH_CO285)
+
+/*
+ * Task size: 1.5GB
+ */
+#define TASK_SIZE (0x60000000UL)
+
+/*
+ * Page offset: 1.5GB
+ */
+#define PAGE_OFFSET (0x60000000UL)
+
+#else
+
+#error Add in your architecture here
+
+#endif
+
+#ifndef __ASSEMBLY__
+extern unsigned long __virt_to_bus(unsigned long);
+extern unsigned long __bus_to_virt(unsigned long);
+#endif
+
+#endif
+
+/*
+ * On Footbridge machines, the dram is contiguous.
+ * On Host Footbridge, these conversions are constant.
+ * On an add-in footbridge, these depend on register settings.
+ */
+#define __virt_to_phys__is_a_macro
+#define __virt_to_phys(vpage) ((unsigned long)(vpage) - PAGE_OFFSET)
+#define __phys_to_virt__is_a_macro
+#define __phys_to_virt(ppage) ((unsigned long)(ppage) + PAGE_OFFSET)
+
+#endif
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-ebsa285/mm-init.h linux/include/asm-arm/arch-ebsa285/mm-init.h
--- v2.2.7/linux/include/asm-arm/arch-ebsa285/mm-init.h Tue Apr 14 14:29:25 1998
+++ linux/include/asm-arm/arch-ebsa285/mm-init.h Wed Dec 31 16:00:00 1969
@@ -1,5 +0,0 @@
-/*
- * linux/include/asm-arm/arch-ebsa110/mmap.h
- *
- * Copyright (C) 1996,1997,1998 Russell King
- */
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-ebsa285/mmu.h linux/include/asm-arm/arch-ebsa285/mmu.h
--- v2.2.7/linux/include/asm-arm/arch-ebsa285/mmu.h Fri Jan 8 22:36:21 1999
+++ linux/include/asm-arm/arch-ebsa285/mmu.h Wed Dec 31 16:00:00 1969
@@ -1,28 +0,0 @@
-/*
- * linux/include/asm-arm/arch-ebsa285/mmu.h
- *
- * Copyright (c) 1996,1997,1998 Russell King.


- *
- * Changelog:

- * 20-10-1996 RMK Created
- * 31-12-1997 RMK Fixed definitions to reduce warnings
- * 17-05-1998 DAG Added __virt_to_bus and __bus_to_virt functions.
- * 21-11-1998 RMK Changed __virt_to_bus and __bus_to_virt to macros.


- */
-#ifndef __ASM_ARCH_MMU_H
-#define __ASM_ARCH_MMU_H
-

-/*
- * On ebsa285, the dram is contiguous
- */
-#define __virt_to_phys__is_a_macro
-#define __virt_to_phys(vpage) ((unsigned long)(vpage) - PAGE_OFFSET)
-#define __phys_to_virt__is_a_macro
-#define __phys_to_virt(ppage) ((unsigned long)(ppage) + PAGE_OFFSET)
-
-#define __virt_to_bus__is_a_macro
-#define __virt_to_bus(x) ((x) - 0xe0000000)
-#define __bus_to_virt__is_a_macro
-#define __bus_to_virt(x) ((x) + 0xe0000000)
-
-#endif
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-ebsa285/oldlatches.h linux/include/asm-arm/arch-ebsa285/oldlatches.h
--- v2.2.7/linux/include/asm-arm/arch-ebsa285/oldlatches.h Tue Apr 14 14:29:25 1998
+++ linux/include/asm-arm/arch-ebsa285/oldlatches.h Wed Dec 31 16:00:00 1969
@@ -1,9 +0,0 @@
-/*
- * Dummy oldlatches.h
- *


- * Copyright (C) 1996 Russell King

- */
-
-#ifdef __need_oldlatches
-#error "Old latches not present in this (rpc) machine"
-#endif
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-ebsa285/processor.h linux/include/asm-arm/arch-ebsa285/processor.h
--- v2.2.7/linux/include/asm-arm/arch-ebsa285/processor.h Fri Jan 8 22:36:21 1999
+++ linux/include/asm-arm/arch-ebsa285/processor.h Sat May 8 11:06:57 1999
@@ -1,12 +1,17 @@
X /*
X * linux/include/asm-arm/arch-ebsa110/processor.h
X *
- * Copyright (C) 1996,1997,1998 Russell King


+ * Copyright (C) 1996-1999 Russell King

+ *
+ * Changelog:

+ * 21-Mar-1999 RMK Added asm/arch/memory.h
X */
X
X #ifndef __ASM_ARCH_PROCESSOR_H
X #define __ASM_ARCH_PROCESSOR_H
X
+#include <asm/arch/memory.h>
+
X /*
X * Bus types
X */

@@ -15,17 +20,9 @@


X #define MCA_bus 0
X #define MCA_bus__is_a_macro /* for versions in ksyms.c */
X
-/*

- * User space: 3GB
- */
-#define TASK_SIZE (0xc0000000UL)


-
X /* This decides where the kernel will search for a free chunk of vm
X * space during mmap's.
X */
X #define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
-
-#define INIT_MMAP \
-{ &init_mm, 0, 0, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap }
X
X #endif

diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-ebsa285/serial.h linux/include/asm-arm/arch-ebsa285/serial.h
--- v2.2.7/linux/include/asm-arm/arch-ebsa285/serial.h Fri Jan 8 22:36:21 1999
+++ linux/include/asm-arm/arch-ebsa285/serial.h Sat May 8 11:06:57 1999
@@ -10,8 +10,6 @@
X #ifndef __ASM_ARCH_SERIAL_H
X #define __ASM_ARCH_SERIAL_H
X
-#include <linux/config.h>
-
X #include <asm/irq.h>
X
X /*
@@ -23,13 +21,8 @@
X */
X #define BASE_BAUD (1843200 / 16)
X
-#ifdef CONFIG_CATS
-#define _SER_IRQ0 IRQ_ISA(4)
-#define _SER_IRQ1 IRQ_ISA(3)
-#else
-#define _SER_IRQ0 0
-#define _SER_IRQ1 0
-#endif
+#define _SER_IRQ0 IRQ_ISA_UART
+#define _SER_IRQ1 IRQ_ISA_UART2
X
X #define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
X
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-ebsa285/system.h linux/include/asm-arm/arch-ebsa285/system.h
--- v2.2.7/linux/include/asm-arm/arch-ebsa285/system.h Fri Jan 8 22:36:21 1999
+++ linux/include/asm-arm/arch-ebsa285/system.h Sat May 8 11:06:57 1999
@@ -3,6 +3,8 @@
X *
X * Copyright (c) 1996,1997,1998 Russell King.
X */
+#include <asm/dec21285.h>
+#include <asm/io.h>
X #include <asm/hardware.h>
X #include <asm/leds.h>
X
@@ -16,14 +18,37 @@
X mov r0, #0x130
X mcr p15, 0, r0, c1, c0 @ MMU off
X mcr p15, 0, ip, c7, c7 @ flush caches
- mov pc, lr");
+ mov pc, lr" : : : "cc");
X } else {
- /* To reboot, we set up the 21285 watchdog and enable it.
- * We then wait for it to timeout.
- */
- *CSR_TIMER4_LOAD = 0x8000;
- *CSR_TIMER4_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_AUTORELOAD | TIMER_CNTL_DIV16;
- *CSR_SA110_CNTL |= 1 << 13;
+ if (machine_is_ebsa285() || machine_is_co285()) {
+ /* To reboot, we set up the 21285 watchdog and
+ * enable it. We then wait for it to timeout.
+ */
+ *CSR_TIMER4_LOAD = 0x8000;
+ *CSR_TIMER4_CNTL = TIMER_CNTL_ENABLE |
+ TIMER_CNTL_AUTORELOAD |
+ TIMER_CNTL_DIV16;
+ *CSR_SA110_CNTL |= 1 << 13;
+ } else if (machine_is_netwinder()) {
+ /* open up the SuperIO chip
+ */
+ outb(0x87, 0x370);
+ outb(0x87, 0x370);
+
+ /* aux function group 1 (logical device 7)
+ */
+ outb(0x07, 0x370);
+ outb(0x07, 0x371);
+
+ /* set GP16 for WD-TIMER output
+ */
+ outb(0xe6, 0x370);
+ outb(0x00, 0x371);
+
+ /* set a RED LED and toggle WD_TIMER for rebooting
+ */
+ outb(0xc4, 0x338);
+ }
X }
X }
X
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-ebsa285/time.h linux/include/asm-arm/arch-ebsa285/time.h
--- v2.2.7/linux/include/asm-arm/arch-ebsa285/time.h Fri Jan 8 22:36:21 1999
+++ linux/include/asm-arm/arch-ebsa285/time.h Sat May 8 11:06:57 1999
@@ -10,116 +10,346 @@
X * 21-Mar-1998 RMK Created
X * 27-Aug-1998 PJB CATS support
X * 28-Dec-1998 APH Made leds optional
+ * 20-Jan-1999 RMK Started merge of EBSA285, CATS and NetWinder
+ * 16-Mar-1999 RMK More support for EBSA285-like machines with RTCs in
X */
X
-#define RTC_PORT(x) (0x72+(x))
-#define RTC_ALWAYS_BCD 1
+#define RTC_PORT(x) (rtc_base+(x))
+#define RTC_ALWAYS_BCD 0
X
X #include <linux/config.h>
+#include <linux/mc146818rtc.h>
+
+#include <asm/dec21285.h>
X #include <asm/leds.h>
X #include <asm/system.h>
-#include <linux/mc146818rtc.h>
X
-extern __inline__ unsigned long gettimeoffset (void)
+static int rtc_base;
+static unsigned long (*gettimeoffset)(void);
+static int (*set_rtc_mmss)(unsigned long nowtime);


+static long last_rtc_update = 0; /* last time the cmos clock got updated */

+
+#ifdef CONFIG_LEDS
+static void do_leds(void)
+{
+ static unsigned int count = 50;
+ static int last_pid;
+
+ if (current->pid != last_pid) {
+ last_pid = current->pid;
+ if (last_pid)
+ leds_event(led_idle_end);
+ else
+ leds_event(led_idle_start);
+ }
+
+ if (--count == 0) {
+ count = 50;
+ leds_event(led_timer);
+ }
+}
+#else
+#define do_leds()
+#endif
+
+#define mSEC_10_from_14 ((14318180 + 100) / 200)
+
+static unsigned long isa_gettimeoffset(void)
+{
+ int count;
+
+ static int count_p = (mSEC_10_from_14/6); /* for the first call after boot */
+ static unsigned long jiffies_p = 0;
+
+ /*
+ * cache volatile jiffies temporarily; we have IRQs turned off.
+ */
+ unsigned long jiffies_t;
+
+ /* timer count may underflow right here */
+ outb_p(0x00, 0x43); /* latch the count ASAP */
+
+ count = inb_p(0x40); /* read the latched count */
+
+ /*
+ * We do this guaranteed double memory access instead of a _p
+ * postfix in the previous port access. Wheee, hackady hack
+ */
+ jiffies_t = jiffies;
+
+ count |= inb_p(0x40) << 8;
+
+ /* Detect timer underflows. If we haven't had a timer tick since
+ the last time we were called, and time is apparently going
+ backwards, the counter must have wrapped during this routine. */
+ if ((jiffies_t == jiffies_p) && (count > count_p))
+ count -= (mSEC_10_from_14/6);
+ else
+ jiffies_p = jiffies_t;
+
+ count_p = count;
+
+ count = (((mSEC_10_from_14/6)-1) - count) * tick;
+ count = (count + (mSEC_10_from_14/6)/2) / (mSEC_10_from_14/6);
+
+ return count;
+}
+
+static void isa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ if (machine_is_netwinder())
+ do_leds();
+
+ do_timer(regs);
+
+ /* If we have an externally synchronized linux clock, then update
+ * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
+ * called as close as possible to 500 ms before the new second starts.
+ */
+ if ((time_status & STA_UNSYNC) == 0 &&
+ xtime.tv_sec > last_rtc_update + 660 &&
+ xtime.tv_usec > 50000 - (tick >> 1) &&
+ xtime.tv_usec < 50000 + (tick >> 1)) {
+ if (set_rtc_mmss(xtime.tv_sec) == 0)
+ last_rtc_update = xtime.tv_sec;
+ else
+ last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
+ }
+}
+
+static struct irqaction isa_timer_irq = {
+ isa_timer_interrupt,
+ 0,
+ 0,
+ "timer",
+ NULL,
+ NULL
+};
+
+__initfunc(static unsigned long
+get_isa_cmos_time(void))
+{


+ unsigned int year, mon, day, hour, min, sec;

+ int i;
+
+ // check to see if the RTC makes sense.....
+ if ((CMOS_READ(RTC_VALID) & RTC_VRT) == 0)
+ return mktime(1970, 1, 1, 0, 0, 0);
+
+ /* The Linux interpretation of the CMOS clock register contents:
+ * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
+ * RTC registers show the second which has precisely just started.
+ * Let's hope other operating systems interpret the RTC the same way.
+ */
+ /* read RTC exactly on falling edge of update flag */


+ for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */

+ if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
+ break;
+
+ for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */


+ if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))

+ break;
+
+ do { /* Isn't this overkill ? UIP above should guarantee consistency */


+ sec = CMOS_READ(RTC_SECONDS);
+ min = CMOS_READ(RTC_MINUTES);
+ hour = CMOS_READ(RTC_HOURS);
+ day = CMOS_READ(RTC_DAY_OF_MONTH);
+ mon = CMOS_READ(RTC_MONTH);
+ year = CMOS_READ(RTC_YEAR);
+ } while (sec != CMOS_READ(RTC_SECONDS));
+

+ if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {


+ BCD_TO_BIN(sec);
+ BCD_TO_BIN(min);
+ BCD_TO_BIN(hour);
+ BCD_TO_BIN(day);
+ BCD_TO_BIN(mon);
+ BCD_TO_BIN(year);
+ }

+ if ((year += 1900) < 1970)
+ year += 100;


+ return mktime(year, mon, day, hour, min, sec);
+}
+

+static int
+set_isa_cmos_time(unsigned long nowtime)


+{
+ int retval = 0;

+ int real_seconds, real_minutes, cmos_minutes;
+ unsigned char save_control, save_freq_select;
+
+ save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */


+ CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
+

+ save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */


+ CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
+

+ cmos_minutes = CMOS_READ(RTC_MINUTES);
+ if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
+ BCD_TO_BIN(cmos_minutes);
+
+ /*
+ * since we're only adjusting minutes and seconds,
+ * don't interfere with hour overflow. This avoids
+ * messing with unknown time zones but requires your
+ * RTC not to be off by more than 15 minutes
+ */
+ real_seconds = nowtime % 60;
+ real_minutes = nowtime / 60;
+ if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
+ real_minutes += 30; /* correct for half hour time zone */
+ real_minutes %= 60;
+
+ if (abs(real_minutes - cmos_minutes) < 30) {
+ if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
+ BIN_TO_BCD(real_seconds);
+ BIN_TO_BCD(real_minutes);
+ }
+ CMOS_WRITE(real_seconds,RTC_SECONDS);
+ CMOS_WRITE(real_minutes,RTC_MINUTES);


+ } else
+ retval = -1;
+

+ /* The following flags have to be released exactly in this order,
+ * otherwise the DS12887 (popular MC146818A clone with integrated
+ * battery and quartz) will not reset the oscillator and will not
+ * update precisely 500 ms later. You won't find this mentioned in
+ * the Dallas Semiconductor data sheets, but who believes data
+ * sheets anyway ... -- Markus Kuhn
+ */


+ CMOS_WRITE(save_control, RTC_CONTROL);
+ CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);

+
+ return retval;
+}
+

+
+
+static unsigned long __ebsa285_text timer1_gettimeoffset (void)
X {
X unsigned long value = LATCH - *CSR_TIMER1_VALUE;
X
X return (tick * value) / LATCH;
X }
X
-extern __inline__ int reset_timer (void)
+static void __ebsa285_text timer1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
X {
X *CSR_TIMER1_CLR = 0;
X
-#ifdef CONFIG_LEDS
- /*
- * Do the LEDs thing on EBSA-285 hardware.
+ /* Do the LEDs things on non-CATS hardware.
X */
- if (!machine_is_cats()) {
- static unsigned int count = 50;
- static int last_pid;
-
- if (current->pid != last_pid) {
- last_pid = current->pid;
- if (last_pid)
- leds_event(led_idle_end);
- else
- leds_event(led_idle_start);
- }
-
- if (--count == 0) {
- count = 50;
- leds_event(led_timer);
- }
+ if (!machine_is_cats())
+ do_leds();
+
+ do_timer(regs);
+
+ /* If we have an externally synchronized linux clock, then update
+ * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be


SHAR_EOF
true || echo 'restore of patch-2.2.8 failed'
fi

echo 'End of part 26'
echo 'File patch-2.2.8 is continued in part 27'
echo 27 > _shar_seq_.tmp

Thomas...@ciw.uni-karlsruhe.de

unread,
May 12, 1999, 3:00:00 AM5/12/99
to
Archive-name: v2.2/patch-2.2.8/part27

#!/bin/sh
# this is part 27 of a 33 - part archive


# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.8 continued
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 27; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.8'
else
echo 'x - continuing with patch-2.2.8'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.8' &&

+ * called as close as possible to 500 ms before the new second starts.
+ */
+ if ((time_status & STA_UNSYNC) == 0 &&
+ xtime.tv_sec > last_rtc_update + 660 &&
+ xtime.tv_usec > 50000 - (tick >> 1) &&
+ xtime.tv_usec < 50000 + (tick >> 1)) {
+ if (set_rtc_mmss(xtime.tv_sec) == 0)
+ last_rtc_update = xtime.tv_sec;
+ else
+ last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */

X }
-#endif
-
- return 1;
X }


X
-/*
- * We don't have a RTC to update!
- */
-#define update_rtc()

+static struct irqaction __ebsa285_data timer1_irq = {
+ timer1_interrupt,


+ 0,
+ 0,
+ "timer",
+ NULL,
+ NULL
+};
+

+static int
+set_dummy_time(unsigned long secs)
+{
+ return 1;


+}
X
X /*
X * Set up timer interrupt, and return the current time in seconds.
X */
-extern __inline__ unsigned long setup_timer (void)
+extern __inline__ void setup_timer(void)
X {

- int year, mon, day, hour, min, sec;
+ switch(machine_arch_type) {
+ case MACH_TYPE_CO285:
+ /*
+ * Add-in 21285s shouldn't access the RTC
+ */
+ rtc_base = 0;
+ break;
X
- /*
- * Default the date to 1 Jan 1970 0:0:0
- */
- year = 1970; mon = 1; day = 1;
- hour = 0; min = 0; sec = 0;
+ default:
+ rtc_base = 0x70;
+ break;
+ }
+
+ if (rtc_base) {
+ int reg_d, reg_b;
+
+ reg_d = CMOS_READ(RTC_REG_D);
X
- *CSR_TIMER1_CLR = 0;
- *CSR_TIMER1_LOAD = LATCH;
- *CSR_TIMER1_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_AUTORELOAD | TIMER_CNTL_DIV16;
-
- if (machine_is_cats())
- {
- int i;
X /*
- * Read the real time from the Dallas chip. (Code borrowed
- * from arch/i386/kernel/time.c).
+ * make sure the divider is set
X */
-
- /* The Linux interpretation of the CMOS clock register contents:
- * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
- * RTC registers show the second which has precisely just started.
- * Let's hope other operating systems interpret the RTC the same way.
+ CMOS_WRITE(RTC_REF_CLCK_32KHZ, RTC_REG_A);
+
+ /*
+ * Set control reg B
+ * (24 hour mode, update enabled)
X */
+ reg_b = CMOS_READ(RTC_REG_B) & 0x7f;
+ reg_b |= 2;
+ CMOS_WRITE(reg_b, RTC_REG_B);
+
+ if ((CMOS_READ(RTC_REG_A) & 0x7f) == RTC_REF_CLCK_32KHZ &&
+ CMOS_READ(RTC_REG_B) == reg_b) {
+
+ /*
+ * Check the battery
+ */
+ if ((reg_d & 0x80) == 0)
+ printk(KERN_WARNING "RTC: *** warning: CMOS battery bad\n");
+
+ xtime.tv_sec = get_isa_cmos_time();
+ set_rtc_mmss = set_isa_cmos_time;
+ } else
+ rtc_base = 0;
+ }
X
- /* read RTC exactly on falling edge of update flag */
- for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */
- if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
- break;
- for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */
- if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
- break;
- do { /* Isn't this overkill ? UIP above should guarantee consistency */
- sec = CMOS_READ(RTC_SECONDS);
- min = CMOS_READ(RTC_MINUTES);
- hour = CMOS_READ(RTC_HOURS);
- day = CMOS_READ(RTC_DAY_OF_MONTH);
- mon = CMOS_READ(RTC_MONTH);
- year = CMOS_READ(RTC_YEAR);
- } while (sec != CMOS_READ(RTC_SECONDS));
- if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD)


- {
- BCD_TO_BIN(sec);
- BCD_TO_BIN(min);
- BCD_TO_BIN(hour);
- BCD_TO_BIN(day);
- BCD_TO_BIN(mon);
- BCD_TO_BIN(year);
- }

- if ((year += 1900) < 1970)
- year += 100;

+ if (!rtc_base) {
+ /*
+ * Default the date to 1 Jan 1970 0:0:0
+ */


+ xtime.tv_sec = mktime(1970, 1, 1, 0, 0, 0);

+ set_rtc_mmss = set_dummy_time;
X }


X
- return mktime(year, mon, day, hour, min, sec);

+ if (machine_is_ebsa285()) {
+ gettimeoffset = timer1_gettimeoffset;
+
+ *CSR_TIMER1_CLR = 0;
+ *CSR_TIMER1_LOAD = LATCH;
+ *CSR_TIMER1_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_AUTORELOAD | TIMER_CNTL_DIV16;
+
+ setup_arm_irq(IRQ_TIMER1, &timer1_irq);
+ } else {
+ /* enable PIT timer */
+ /* set for periodic (4) and LSB/MSB write (0x30) */
+ outb(0x34, 0x43);
+ outb((mSEC_10_from_14/6) & 0xFF, 0x40);
+ outb((mSEC_10_from_14/6) >> 8, 0x40);
+
+ gettimeoffset = isa_gettimeoffset;
+
+ setup_arm_irq(IRQ_ISA_TIMER, &isa_timer_irq);
+ }
X }
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-ebsa285/timex.h linux/include/asm-arm/arch-ebsa285/timex.h
--- v2.2.7/linux/include/asm-arm/arch-ebsa285/timex.h Tue Apr 14 14:29:25 1998
+++ linux/include/asm-arm/arch-ebsa285/timex.h Sat May 8 11:06:57 1999
@@ -7,8 +7,8 @@
X */
X
X /*
- * On the EBSA, the clock ticks at weird rates.
- * This is therefore not used to calculate the
- * divisor.
+ * On EBSA285 boards, the clock runs at 50MHz and is
+ * divided by a 4-bit prescaler. Other boards use an
+ * ISA derived timer, and this is unused.
X */
X #define CLOCK_TICK_RATE (50000000 / 16)
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-ebsa285/uncompress.h linux/include/asm-arm/arch-ebsa285/uncompress.h
--- v2.2.7/linux/include/asm-arm/arch-ebsa285/uncompress.h Fri Jan 8 22:36:21 1999
+++ linux/include/asm-arm/arch-ebsa285/uncompress.h Sat May 8 11:06:57 1999


@@ -1,9 +1,12 @@
X /*

- * linux/include/asm-arm/arch-ebsa110/uncompress.h
+ * linux/include/asm-arm/arch-ebsa285/uncompress.h
X *
X * Copyright (C) 1996,1997,1998 Russell King
X */
X
+/*
+ * Note! This could cause problems on the NetWinder
+ */
X #define BASE 0x42000160
X
X static __inline__ void putc(char c)
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-nexuspci/a.out.h linux/include/asm-arm/arch-nexuspci/a.out.h
--- v2.2.7/linux/include/asm-arm/arch-nexuspci/a.out.h Fri Jan 8 22:36:21 1999
+++ linux/include/asm-arm/arch-nexuspci/a.out.h Sat May 8 11:06:57 1999


@@ -1,15 +1,16 @@
X /*

X * linux/include/asm-arm/arch-nexuspci/a.out.h


X *
- * Copyright (C) 1996 Russell King
+ * Copyright (C) 1996-1999 Russell King
X */
-
X #ifndef __ASM_ARCH_A_OUT_H
X #define __ASM_ARCH_A_OUT_H
X
-#ifdef __KERNEL__
-#define STACK_TOP ((current->personality==PER_LINUX_32BIT)? 0xc0000000 : 0x04000000)
-#endif
+#include <asm/arch/memory.h>
+
+#define STACK_TOP \
+ ((current->personality == PER_LINUX_32BIT) ? \
+ TASK_SIZE : 0x04000000)
X
X #endif
X

diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-nexuspci/hardware.h linux/include/asm-arm/arch-nexuspci/hardware.h
--- v2.2.7/linux/include/asm-arm/arch-nexuspci/hardware.h Fri Jan 8 22:36:21 1999
+++ linux/include/asm-arm/arch-nexuspci/hardware.h Sat May 8 11:06:57 1999
@@ -1,10 +1,12 @@
X /*
X * linux/include/asm-arm/arch-nexuspci/hardware.h
X *


- * Copyright (C) 1998 Philip Blundell

+ * Copyright (C) 1998-1999 Philip Blundell
X *
X * This file contains the hardware definitions of the Nexus PCI card.


X */
+#ifndef __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H
X

X /* Logical Physical
X * 0xfff00000 0x10000000 SCC2691 DUART
@@ -13,27 +15,17 @@
X * 0xffc00000 0x60000000 PLX registers
X * 0xfe000000 0x70000000 PCI I/O
X */
-
-#ifndef __ASM_ARCH_HARDWARE_H
-#define __ASM_ARCH_HARDWARE_H
-


-/*
- * What hardware must be present
- */
-

-#define HAS_PCIO
-#define PCIO_BASE 0xfe000000


X
X /*
X * Mapping areas
X */

-#define IO_BASE 0xfe000000
+#define PCIO_BASE 0xfe000000
+#define FLUSH_BASE 0xdf000000


X
X /*
X * RAM definitions
X */

X #define RAM_BASE 0x40000000
-#define KERNTOPHYS(a) ((unsigned long)(&a))


X #define FLUSH_BASE_PHYS 0x40000000
X

X #endif
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-nexuspci/irq.h linux/include/asm-arm/arch-nexuspci/irq.h
--- v2.2.7/linux/include/asm-arm/arch-nexuspci/irq.h Wed Sep 9 14:51:12 1998
+++ linux/include/asm-arm/arch-nexuspci/irq.h Sat May 8 11:06:57 1999
@@ -9,6 +9,8 @@
X
X #include <asm/io.h>


X
+#define fixup_irq(x) (x)
+

X #define INTCONT 0xffe00000
X
X extern unsigned long soft_irq_mask;
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-nexuspci/memory.h linux/include/asm-arm/arch-nexuspci/memory.h
--- v2.2.7/linux/include/asm-arm/arch-nexuspci/memory.h Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-nexuspci/memory.h Sat May 8 11:06:57 1999
@@ -0,0 +1,37 @@
+/*
+ * linux/include/asm-arm/arch-nexuspci/memory.h
+ *
+ * Copyright (c) 1997, 1998 Philip Blundell.
+ * Copyright (c) 1999 Russell King
+ *


+ */
+#ifndef __ASM_ARCH_MMU_H
+#define __ASM_ARCH_MMU_H
+

+/*
+ * Task size: 3GB
+ */
+#define TASK_SIZE (0xc0000000UL)
+
+/*
+ * Page offset: 3GB
+ */
+#define PAGE_OFFSET (0xc0000000UL)
+

+/*
+ * On NexusPCI, the DRAM is contiguous
+ */
+#define __virt_to_phys(vpage) ((vpage) - PAGE_OFFSET + 0x40000000)
+#define __phys_to_virt(ppage) ((ppage) + PAGE_OFFSET - 0x40000000)
+#define __virt_to_phys__is_a_macro
+#define __phys_to_virt__is_a_macro
+
+/*
+ * On the PCI bus the DRAM appears at address 0
+ */
+#define __virt_to_bus__is_a_macro
+#define __virt_to_bus(x) ((x) - PAGE_OFFSET)
+#define __bus_to_virt__is_a_macro
+#define __bus_to_virt(x) ((x) + PAGE_OFFSET)
+
+#endif
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-nexuspci/mm-init.h linux/include/asm-arm/arch-nexuspci/mm-init.h
--- v2.2.7/linux/include/asm-arm/arch-nexuspci/mm-init.h Tue Apr 14 14:29:25 1998
+++ linux/include/asm-arm/arch-nexuspci/mm-init.h Wed Dec 31 16:00:00 1969


@@ -1,5 +0,0 @@
-/*

- * linux/include/asm-arm/arch-nexuspci/mmap.h
- *
- * Copyright (C) 1998 Philip Blundell
- */
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-nexuspci/mmu.h linux/include/asm-arm/arch-nexuspci/mmu.h
--- v2.2.7/linux/include/asm-arm/arch-nexuspci/mmu.h Tue Jul 21 00:15:32 1998
+++ linux/include/asm-arm/arch-nexuspci/mmu.h Wed Dec 31 16:00:00 1969
@@ -1,26 +0,0 @@
-/*
- * linux/include/asm-arm/arch-nexuspci/mmu.h
- *
- * Copyright (c) 1997, 1998 Philip Blundell.
- *


- */
-#ifndef __ASM_ARCH_MMU_H
-#define __ASM_ARCH_MMU_H
-
-/*

- * On NexusPCI, the DRAM is contiguous
- */
-#define __virt_to_phys(vpage) ((vpage) - PAGE_OFFSET + 0x40000000)
-#define __phys_to_virt(ppage) ((ppage) + PAGE_OFFSET - 0x40000000)
-#define __virt_to_phys__is_a_macro
-#define __phys_to_virt__is_a_macro
-
-/*
- * On the PCI bus the DRAM appears at address 0
- */
-#define __virt_to_bus__is_a_macro
-#define __virt_to_bus(x) ((x) - PAGE_OFFSET)
-#define __bus_to_virt__is_a_macro
-#define __bus_to_virt(x) ((x) + PAGE_OFFSET)
-
-#endif
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-nexuspci/processor.h linux/include/asm-arm/arch-nexuspci/processor.h
--- v2.2.7/linux/include/asm-arm/arch-nexuspci/processor.h Fri Jan 8 22:36:22 1999
+++ linux/include/asm-arm/arch-nexuspci/processor.h Sat May 8 11:06:57 1999
@@ -1,13 +1,18 @@
X /*
- * linux/include/asm-arm/arch-ebsa110/processor.h
+ * linux/include/asm-arm/arch-nexuspci/processor.h
X * from linux/include/asm-arm/arch-ebsa110/processor.h


X *
- * Copyright (C) 1996,1997,1998 Russell King
+ * Copyright (C) 1996-1999 Russell King
+ *
+ * Changelog:
+ * 21-Mar-1999 RMK Added asm/arch/memory.h
X */
X
X #ifndef __ASM_ARCH_PROCESSOR_H
X #define __ASM_ARCH_PROCESSOR_H
X
+#include <asm/arch/memory.h>
+
X /*
X * Bus types
X */

@@ -16,17 +21,9 @@


X #define MCA_bus 0
X #define MCA_bus__is_a_macro /* for versions in ksyms.c */
X
-/*
- * User space: 3GB
- */
-#define TASK_SIZE (0xc0000000UL)
-
X /* This decides where the kernel will search for a free chunk of vm
X * space during mmap's.
X */
X #define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
-
-#define INIT_MMAP \
-{ &init_mm, 0, 0, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap }
X
X #endif

diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-nexuspci/time.h linux/include/asm-arm/arch-nexuspci/time.h
--- v2.2.7/linux/include/asm-arm/arch-nexuspci/time.h Tue Jul 21 00:15:32 1998
+++ linux/include/asm-arm/arch-nexuspci/time.h Sat May 8 11:06:57 1999
@@ -17,37 +17,53 @@


X return 0;
X }
X

-extern __inline__ int reset_timer (void)
+static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
X {

X static int count = 50;
+
X writeb(0x90, UART_BASE + 8);


- if (--count == 0)

- {


+
+ if (--count == 0) {

X static int state = 1;
X state ^= 1;
X writeb(0x1a + state, INTCONT);
X count = 50;
X }
+
X readb(UART_BASE + 0x14);
X readb(UART_BASE + 0x14);
X readb(UART_BASE + 0x14);
X readb(UART_BASE + 0x14);
X readb(UART_BASE + 0x14);
X readb(UART_BASE + 0x14);
- return 1;
+
+ do_timer(regs);
X }
X
-extern __inline__ unsigned long setup_timer (void)


+static struct irqaction timerirq = {
+ timer_interrupt,
+ 0,
+ 0,
+ "timer",
+ NULL,
+ NULL
+};

+


+extern __inline__ void setup_timer(void)
X {

X int tick = 3686400 / 16 / 2 / 100;
+
X writeb(tick & 0xff, UART_BASE + 0x1c);
X writeb(tick >> 8, UART_BASE + 0x18);
X writeb(0x80, UART_BASE + 8);
X writeb(0x10, UART_BASE + 0x14);


+
X /*
X * Default the date to 1 Jan 1970 0:0:0
X * You will have to run a time daemon to set the
X * clock correctly at bootup
X */
- return mktime(1970, 1, 1, 0, 0, 0);
+ xtime.tv_sec = mktime(1970, 1, 1, 0, 0, 0);
+
+ setup_arm_irq(IRQ_TIMER, &timerirq);
X }

diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-rpc/a.out.h linux/include/asm-arm/arch-rpc/a.out.h
--- v2.2.7/linux/include/asm-arm/arch-rpc/a.out.h Fri Jan 8 22:36:22 1999
+++ linux/include/asm-arm/arch-rpc/a.out.h Sat May 8 11:06:57 1999


@@ -1,15 +1,16 @@
X /*

X * linux/include/asm-arm/arch-rpc/a.out.h


X *
- * Copyright (C) 1996 Russell King
+ * Copyright (C) 1996-1999 Russell King
X */
-
X #ifndef __ASM_ARCH_A_OUT_H
X #define __ASM_ARCH_A_OUT_H
X
-#ifdef __KERNEL__
-#define STACK_TOP ((current->personality==PER_LINUX_32BIT)? 0xc0000000 : 0x04000000)
-#endif
+#include <asm/arch/memory.h>
+
+#define STACK_TOP \
+ ((current->personality == PER_LINUX_32BIT) ? \
+ TASK_SIZE : 0x04000000)
X
X #endif
X

diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-rpc/hardware.h linux/include/asm-arm/arch-rpc/hardware.h
--- v2.2.7/linux/include/asm-arm/arch-rpc/hardware.h Fri Jan 8 22:36:22 1999
+++ linux/include/asm-arm/arch-rpc/hardware.h Sat May 8 11:06:57 1999
@@ -1,19 +1,19 @@
X /*
X * linux/include/asm-arm/arch-rpc/hardware.h
X *
- * Copyright (C) 1996 Russell King.


+ * Copyright (C) 1996-1999 Russell King.
X *

X * This file contains the hardware definitions of the RiscPC series machines.


X */
-
X #ifndef __ASM_ARCH_HARDWARE_H
X #define __ASM_ARCH_HARDWARE_H
X

+#include <asm/arch/memory.h>
+
X /*

X * What hardware must be present
X */
X #define HAS_IOMD
-#include <asm/iomd.h>
X #define HAS_VIDC20
X
X /* Hardware addresses of major areas.
@@ -26,7 +26,7 @@
X
X #define EASI_SIZE 0x08000000 /* EASI I/O */
X #define EASI_START 0x08000000
-#define EASI_BASE 0xe8000000
+#define EASI_BASE 0xe5000000
X
X #define IO_START 0x03000000 /* I/O */
X #define IO_SIZE 0x01000000
@@ -38,6 +38,8 @@
X #define SCREEN1_END 0xd8000000
X #define SCREEN1_BASE 0xd0000000
X
+#define FLUSH_BASE 0xdf000000
+
X
X #ifndef __ASSEMBLER__
X
@@ -47,8 +49,9 @@
X #define IO_VIDC_AUDIO_BASE 0x80140000
X #define IO_VIDC_BASE 0x80100000
X #define IO_IOMD_BASE 0x80080000
+#define IOC_BASE 0x80080000
X
-#define IO_EC_EASI_BASE 0x82000000
+#define IO_EC_EASI_BASE 0x81400000
X #define IO_EC_IOC4_BASE 0x8009c000
X #define IO_EC_IOC_BASE 0x80090000
X #define IO_EC_MEMC8_BASE 0x8000ac00
@@ -59,7 +62,6 @@
X */
X #define EXPMASK_BASE ((volatile unsigned char *)0xe0360000)
X #define IOEB_BASE ((volatile unsigned char *)0xe0350050)
-#define IOC_BASE ((volatile unsigned char *)0xe0200000)
X #define PCIO_FLOPPYDMABASE ((volatile unsigned char *)0xe002a000)
X #define PCIO_BASE 0xe0010000
X
@@ -67,23 +69,19 @@
X * Offsets from RAM base
X */
X #define PARAMS_OFFSET 0x0100
-#define KERNEL_OFFSET 0x8000


X
X /*
X * RAM definitions
X */

-#define MAPTOPHYS(x) (x)
-#define KERNTOPHYS(x) ((unsigned long)(&x))
X #define GET_MEMORY_END(p) (PAGE_OFFSET + p->u1.s.page_size * \
X (p->u1.s.pages_in_bank[0] + \
X p->u1.s.pages_in_bank[1] + \
X p->u1.s.pages_in_bank[2] + \
X p->u1.s.pages_in_bank[3]))
X
-#define KERNEL_BASE (PAGE_OFFSET + KERNEL_OFFSET)


X #define PARAMS_BASE (PAGE_OFFSET + PARAMS_OFFSET)

X #define Z_PARAMS_BASE (RAM_START + PARAMS_OFFSET)
-#define SAFE_ADDR 0x00000000 /* ROM */
+#define FLUSH_BASE_PHYS 0x00000000 /* ROM */
X
X #else
X
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-rpc/irq.h linux/include/asm-arm/arch-rpc/irq.h
--- v2.2.7/linux/include/asm-arm/arch-rpc/irq.h Wed Sep 9 14:51:12 1998
+++ linux/include/asm-arm/arch-rpc/irq.h Sat May 8 11:06:57 1999
@@ -7,6 +7,9 @@
X * 10-10-1996 RMK Brought up to date with arch-sa110eval
X * 22-08-1998 RMK Restructured IRQ routines
X */
+#include <asm/iomd.h>


+
+#define fixup_irq(x) (x)
X

X static void rpc_mask_irq_ack_a(unsigned int irq)
X {
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-rpc/keyboard.h linux/include/asm-arm/arch-rpc/keyboard.h
--- v2.2.7/linux/include/asm-arm/arch-rpc/keyboard.h Wed Apr 28 11:37:31 1999
+++ linux/include/asm-arm/arch-rpc/keyboard.h Sat May 8 11:06:57 1999
@@ -10,7 +10,6 @@


X
X #define NR_SCANCODES 128
X

-extern int ps2kbd_translate(unsigned char scancode, unsigned char *keycode_p, char *up_flag_p);
X extern void ps2kbd_leds(unsigned char leds);
X extern void ps2kbd_init_hw(void);
X extern unsigned char ps2kbd_sysrq_xlate[NR_SCANCODES];
@@ -18,15 +17,7 @@


X #define kbd_setkeycode(sc,kc) (-EINVAL)
X #define kbd_getkeycode(sc) (-EINVAL)

X
-/* Prototype: int kbd_translate(scancode, *keycode, *up_flag, raw_mode)
- * Returns : 0 to ignore scancode, *keycode set to keycode, *up_flag
- * set to 0200 if scancode indicates release
- */

-#ifdef NEW_KEYBOARD
-#define kbd_translate(sc, kcp, ufp, rm) ps2kbd_translate(sc, kcp, ufp)
-#else
-#define kbd_translate(sc, kcp, rm) ({ unsigned int up_flag; ps2kbd_translate(sc, kcp, &up_flag); })
-#endif


+#define kbd_translate(sc, kcp, rm) ({ *(kcp) = (sc); 1; })
X #define kbd_unexpected_up(kc) (0200)

X #define kbd_leds(leds) ps2kbd_leds(leds)
X #define kbd_init_hw() ps2kbd_init_hw()
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-rpc/memory.h linux/include/asm-arm/arch-rpc/memory.h
--- v2.2.7/linux/include/asm-arm/arch-rpc/memory.h Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-rpc/memory.h Sat May 8 11:06:57 1999


@@ -0,0 +1,41 @@
+/*

+ * linux/include/asm-arm/arch-rpc/memory.h
+ *
+ * Copyright (c) 1996,1997,1998 Russell King.
+ *


+ * Changelog:
+ * 20-Oct-1996 RMK Created
+ * 31-Dec-1997 RMK Fixed definitions to reduce warnings

+ * 11-Jan-1998 RMK Uninlined to reduce hits on cache
+ * 08-Feb-1998 RMK Added __virt_to_bus and __bus_to_virt


+ * 21-Mar-1999 RMK Renamed to memory.h

+ * RMK Added TASK_SIZE and PAGE_OFFSET


+ */
+#ifndef __ASM_ARCH_MMU_H
+#define __ASM_ARCH_MMU_H
+

+/*
+ * Task size: 3GB
+ */
+#define TASK_SIZE (0xc0000000UL)
+
+/*
+ * Page offset: 3GB
+ */
+#define PAGE_OFFSET (0xc0000000UL)
+

+#ifndef __ASSEMBLY__
+extern unsigned long __virt_to_phys(unsigned long vpage);
+extern unsigned long __phys_to_virt(unsigned long ppage);
+#endif
+
+/*
+ * These are exactly the same on the RiscPC as the
+ * physical memory view.
+ */


+#define __virt_to_bus__is_a_macro
+#define __virt_to_bus(x) __virt_to_phys(x)
+#define __bus_to_virt__is_a_macro
+#define __bus_to_virt(x) __phys_to_virt(x)
+
+#endif

diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-rpc/mmu.h linux/include/asm-arm/arch-rpc/mmu.h
--- v2.2.7/linux/include/asm-arm/arch-rpc/mmu.h Tue Apr 14 14:29:25 1998
+++ linux/include/asm-arm/arch-rpc/mmu.h Wed Dec 31 16:00:00 1969
@@ -1,27 +0,0 @@
-/*
- * linux/include/asm-arm/arch-rpc/mmu.h


- *
- * Copyright (c) 1996,1997,1998 Russell King.
- *
- * Changelog:
- * 20-10-1996 RMK Created
- * 31-12-1997 RMK Fixed definitions to reduce warnings

- * 11-01-1998 RMK Uninlined to reduce hits on cache
- * 08-02-1998 RMK Added __virt_to_bus and __bus_to_virt


- */
-#ifndef __ASM_ARCH_MMU_H
-#define __ASM_ARCH_MMU_H
-

-extern unsigned long __virt_to_phys(unsigned long vpage);
-extern unsigned long __phys_to_virt(unsigned long ppage);
-
-/*
- * These are exactly the same on the RiscPC as the
- * physical memory view.
- */


-#define __virt_to_bus__is_a_macro
-#define __virt_to_bus(x) __virt_to_phys(x)
-#define __bus_to_virt__is_a_macro
-#define __bus_to_virt(x) __phys_to_virt(x)
-
-#endif

diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-rpc/oldlatches.h linux/include/asm-arm/arch-rpc/oldlatches.h
--- v2.2.7/linux/include/asm-arm/arch-rpc/oldlatches.h Tue Jan 20 16:39:42 1998
+++ linux/include/asm-arm/arch-rpc/oldlatches.h Wed Dec 31 16:00:00 1969


@@ -1,9 +0,0 @@
-/*
- * Dummy oldlatches.h
- *
- * Copyright (C) 1996 Russell King
- */
-
-#ifdef __need_oldlatches
-#error "Old latches not present in this (rpc) machine"
-#endif

diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-rpc/processor.h linux/include/asm-arm/arch-rpc/processor.h
--- v2.2.7/linux/include/asm-arm/arch-rpc/processor.h Fri Jan 8 22:36:22 1999
+++ linux/include/asm-arm/arch-rpc/processor.h Sat May 8 11:06:57 1999
@@ -1,15 +1,18 @@
X /*
X * linux/include/asm-arm/arch-rpc/processor.h
X *
- * Copyright (c) 1996 Russell King.
+ * Copyright (c) 1996-1999 Russell King.
X *


X * Changelog:
- * 10-09-1996 RMK Created
+ * 10-Sep-1996 RMK Created

+ * 21-Mar-1999 RMK Added asm/arch/memory.h
X */
X
X #ifndef __ASM_ARCH_PROCESSOR_H
X #define __ASM_ARCH_PROCESSOR_H
X
+#include <asm/arch/memory.h>
+
X /*
X * Bus types
X */

@@ -18,17 +21,9 @@


X #define MCA_bus 0
X #define MCA_bus__is_a_macro /* for versions in ksyms.c */
X
-/*
- * User space: 3GB
- */
-#define TASK_SIZE (0xc0000000UL)
-
X /* This decides where the kernel will search for a free chunk of vm
X * space during mmap's.
X */
X #define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
-
-#define INIT_MMAP \
-{ &init_mm, 0, 0, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap }
X
X #endif

diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-rpc/system.h linux/include/asm-arm/arch-rpc/system.h
--- v2.2.7/linux/include/asm-arm/arch-rpc/system.h Fri Jan 8 22:36:22 1999
+++ linux/include/asm-arm/arch-rpc/system.h Sat May 8 11:06:57 1999
@@ -6,7 +6,7 @@
X #ifndef __ASM_ARCH_SYSTEM_H
X #define __ASM_ARCH_SYSTEM_H
X
-#include <asm/proc-fns.h>
+#include <asm/iomd.h>
X
X #define arch_reset(mode) { \
X extern void ecard_reset (int card); \
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-rpc/time.h linux/include/asm-arm/arch-rpc/time.h
--- v2.2.7/linux/include/asm-arm/arch-rpc/time.h Tue Jan 20 16:39:42 1998
+++ linux/include/asm-arm/arch-rpc/time.h Sat May 8 11:06:57 1999


@@ -8,6 +8,9 @@
X * 10-Oct-1996 RMK Brought up to date with arch-sa110eval
X * 04-Dec-1997 RMK Updated for new arch/arm/time.c
X */

+#include <asm/iomd.h>
+


+static long last_rtc_update = 0; /* last time the cmos clock got updated */

X
X extern __inline__ unsigned long gettimeoffset (void)
X {
@@ -51,46 +54,148 @@


X return offset;
X }
X
-/*
- * No need to reset the timer at every irq
- */
-#define reset_timer() 1

+extern int iic_control(unsigned char, int, char *, int);


X
-/*
- * Updating of the RTC. We don't currently write the time to the
- * CMOS clock.

- */
-#define update_rtc()

+ /*FIXME:
+ * This doesn't seem to work. Does RISC OS
+ * actually use the RTC year? It doesn't
+ * seem to. In that case, how does it update
+ * the CMOS year?
+ */
+ /*year += (buf[3] >> 6) & 3;*/
+
+ /*


+ * The RTC combines years with date and weekday
+ * with month. We need to mask off this extra
+ * information before converting the date to
+ * binary.
+ */
+ buf[4] &= 0x1f;
+ buf[3] &= 0x3f;

+printk("Year %4d mon %02X day %02X hour %02X min %02X sec %02X\n", year, buf[4], buf[3], buf[2], buf[1], buf[0]);

X outb(LATCH & 255, IOMD_T0LTCHL);
X outb(LATCH >> 8, IOMD_T0LTCHH);
X outb(0, IOMD_T0GO);


X
- iic_control (0xa0, 0xc0, buf, 1);
- year = buf[0];
- if ((year += 1900) < 1970)
- year += 100;
-
- iic_control (0xa0, 2, buf, 5);
- mon = buf[4] & 0x1f;
- day = buf[3] & 0x3f;
- hour = buf[2];
- min = buf[1];
- sec = buf[0];
- BCD_TO_BIN(mon);
- BCD_TO_BIN(day);
- BCD_TO_BIN(hour);
- BCD_TO_BIN(min);
- BCD_TO_BIN(sec);
+ xtime.tv_sec = get_rtc_time();
X
- return mktime(year, mon, day, hour, min, sec);
+ setup_arm_irq(IRQ_TIMER, &timerirq);
X }

diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-rpc/uncompress.h linux/include/asm-arm/arch-rpc/uncompress.h
--- v2.2.7/linux/include/asm-arm/arch-rpc/uncompress.h Wed Sep 9 14:51:12 1998
+++ linux/include/asm-arm/arch-rpc/uncompress.h Sat May 8 11:06:57 1999
@@ -5,7 +5,6 @@
X */
X #define VIDMEM ((char *)SCREEN_START)
X
-#include "../arch/arm/drivers/char/font.h"
X #include <asm/hardware.h>
X #include <asm/io.h>
X
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-vnc/a.out.h linux/include/asm-arm/arch-vnc/a.out.h
--- v2.2.7/linux/include/asm-arm/arch-vnc/a.out.h Fri Jan 8 22:36:22 1999
+++ linux/include/asm-arm/arch-vnc/a.out.h Wed Dec 31 16:00:00 1969
@@ -1,14 +0,0 @@
-/*
- * linux/include/asm-arm/arch-ebsa110/a.out.h


- *
- * Copyright (C) 1996 Russell King
- */
-

-#ifndef __ASM_ARCH_A_OUT_H
-#define __ASM_ARCH_A_OUT_H
-


-#ifdef __KERNEL__
-#define STACK_TOP ((current->personality==PER_LINUX_32BIT)? 0xc0000000 : 0x04000000)
-#endif

-
-#endif
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-vnc/dma.h linux/include/asm-arm/arch-vnc/dma.h
--- v2.2.7/linux/include/asm-arm/arch-vnc/dma.h Fri Jan 8 22:36:22 1999
+++ linux/include/asm-arm/arch-vnc/dma.h Wed Dec 31 16:00:00 1969
@@ -1,19 +0,0 @@
-/*
- * linux/include/asm-arm/arch-ebsa110/dma.h
- *
- * Architecture DMA routes
- *
- * Copyright (C) 1997.1998 Russell King
- */
-#ifndef __ASM_ARCH_DMA_H
-#define __ASM_ARCH_DMA_H
-
-/*
- * This is the maximum DMA address that can be DMAd to.
- * There should not be more than (0xd0000000 - 0xc0000000)
- * bytes of RAM.
- */
-#define MAX_DMA_ADDRESS 0xd0000000
-#define MAX_DMA_CHANNELS 8
-
-#endif /* _ASM_ARCH_DMA_H */
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-vnc/hardware.h linux/include/asm-arm/arch-vnc/hardware.h
--- v2.2.7/linux/include/asm-arm/arch-vnc/hardware.h Fri Jan 8 22:36:22 1999
+++ linux/include/asm-arm/arch-vnc/hardware.h Wed Dec 31 16:00:00 1969
@@ -1,74 +0,0 @@
-/*
- * linux/include/asm-arm/arch-vnc/hardware.h
- *
- * Copyright (C) 1998 Corel Computer/Russell King.
- *
- * This file contains the hardware definitions of the VNC.
- */
-
-/* Logical Physical


- * 0xffe00000 0x7c000000 PCI I/O space

- * 0xfe000000 0x42000000 CSR
- * 0xfd000000 0x78000000 Outbound write flush
- * 0xfc000000 0x79000000 PCI IACK/special space
- * 0xf9000000 0x7a000000 PCI Config type 1
- * 0xf8000000 0x7b000000 PCI Config type 0
- *
- */
-
-#include <asm/dec21285.h>
-
-#define IO_BASE_ARM_CSR 0xfe000000
-#define PCI_IACK 0xfc000000
-
-/* LEDs */


-#define XBUS_LEDS ((volatile unsigned char *)0xfff12000)

-#define XBUS_LED_AMBER (1 << 0)
-#define XBUS_LED_GREEN (1 << 1)
-#define XBUS_LED_RED (1 << 2)
-#define XBUS_LED_TOGGLE (1 << 8)
-
-/* PIC irq control */
-#define PIC_LO 0x20
-#define PIC_MASK_LO 0x21
-#define PIC_HI 0xA0
-#define PIC_MASK_HI 0xA1
-
-#define IO_END 0xffffffff
-#define IO_BASE 0xe0000000
-#define IO_SIZE (IO_END - IO_BASE)
-
-#define HAS_PCIO
-#define PCIO_BASE 0xffe00000
-


-#define KERNTOPHYS(a) ((unsigned long)(&a))
-

-//#define PARAMS_OFFSET 0x0100
-//#define PARAMS_BASE (PAGE_OFFSET + PARAMS_OFFSET)
-
-#define FLUSH_BASE_PHYS 0x50000000
-
-/* GPIO pins */
-#define GPIO_CCLK 0x800
-#define GPIO_DSCLK 0x400
-#define GPIO_E2CLK 0x200
-#define GPIO_IOLOAD 0x100
-#define GPIO_RED_LED 0x080
-#define GPIO_WDTIMER 0x040
-#define GPIO_DATA 0x020
-#define GPIO_IOCLK 0x010
-#define GPIO_DONE 0x008
-#define GPIO_FAN 0x004
-#define GPIO_GREEN_LED 0x002
-#define GPIO_RESET 0x001
-
-/* CPLD pins */
-#define CPLD_DSRESET 8
-#define CPLD_UNMUTE 2
-
-#ifndef __ASSEMBLY__
-extern void gpio_modify_op(int mask, int set);
-extern void gpio_modify_io(int mask, int in);
-extern int gpio_read(void);
-extern void cpld_modify(int mask, int set);
-#endif
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-vnc/ide.h linux/include/asm-arm/arch-vnc/ide.h
--- v2.2.7/linux/include/asm-arm/arch-vnc/ide.h Tue Dec 22 14:16:58 1998
+++ linux/include/asm-arm/arch-vnc/ide.h Wed Dec 31 16:00:00 1969
@@ -1,42 +0,0 @@
-/*
- * linux/include/asm-arm/arch-vnc/ide.h
- *
- * Copyright (c) 1998 Russell King
- *
- * Modifications:
- * 29-07-1998 RMK Major re-work of IDE architecture specific code
- */
-#include <asm/irq.h>
-
-/*
- * Set up a hw structure for a specified data port, control port and IRQ.
- * This should follow whatever the default interface uses.
- */
-static __inline__ void
-ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int irq)
-{
- ide_ioreg_t reg = (ide_ioreg_t) data_port;
- int i;
-
- memset(hw, 0, sizeof(*hw));
-
- for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
- hw->io_ports[i] = reg;
- reg += 1;
- }
- hw->io_ports[IDE_CONTROL_OFFSET] = (ide_ioreg_t) ctrl_port;
- hw->irq = irq;
-}
-
-/*
- * This registers the standard ports for this architecture with the IDE
- * driver.
- */
-static __inline__ void
-ide_init_default_hwifs(void)
-{
- hw_regs_t hw;
-
- ide_init_hwif_ports(&hw, 0x1f0, 0x3f6, IRQ_HARDDISK);
- ide_register_hw(&hw, NULL);
-}
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-vnc/io.h linux/include/asm-arm/arch-vnc/io.h
--- v2.2.7/linux/include/asm-arm/arch-vnc/io.h Fri Jan 8 22:36:22 1999
+++ linux/include/asm-arm/arch-vnc/io.h Wed Dec 31 16:00:00 1969
@@ -1,176 +0,0 @@
-/*
- * linux/include/asm-arm/arch-ebsa110/io.h
- *
- * Copyright (C) 1997,1998 Russell King
- *
- * Modifications:
- * 06-Dec-1997 RMK Created.
- */
-#ifndef __ASM_ARM_ARCH_IO_H
-#define __ASM_ARM_ARCH_IO_H
-
-/*
- * This architecture does not require any delayed IO, and
- * has the constant-optimised IO
- */
-#undef ARCH_IO_DELAY
-
-/*
- * Dynamic IO functions - let the compiler
- * optimize the expressions
- */


-#define DECLARE_DYN_OUT(fnsuffix,instr,typ) \
-extern __inline__ void __out##fnsuffix (unsigned int value, unsigned int port) \
-{ \
- __asm__ __volatile__( \
- "str%?" ##instr## " %0, [%1, %2] @ out"###fnsuffix \
- : \
- : "r" (value), "r" (PCIO_BASE), typ (port)); \
-}
-
-#define DECLARE_DYN_IN(sz,fnsuffix,instr,typ) \
-extern __inline__ unsigned sz __in##fnsuffix (unsigned int port) \
-{ \
- unsigned long value; \
- __asm__ __volatile__( \
- "ldr%?" ##instr## " %0, [%1, %2] @ in"###fnsuffix \
- : "=&r" (value) \
- : "r" (PCIO_BASE), typ (port)); \
- return (unsigned sz)value; \
-}
-
-extern __inline__ unsigned int __ioaddr (unsigned int port) \
-{ \
- return (unsigned int)(PCIO_BASE + port); \

-}
-
-#define DECLARE_IO(sz,fnsuffix,instr,typ) \
- DECLARE_DYN_OUT(fnsuffix,instr,typ) \
- DECLARE_DYN_IN(sz,fnsuffix,instr,typ)
-
-DECLARE_IO(char,b,"b","Jr")
-DECLARE_IO(short,w,"h","r")
-DECLARE_IO(long,l,"","Jr")
-
-#undef DECLARE_IO
-#undef DECLARE_DYN_OUT
-#undef DECLARE_DYN_IN
-
-/*
- * Constant address IO functions
- *
- * These have to be macros for the 'J' constraint to work -
- * +/-4096 immediate operand.
- */


-#define __outbc(value,port) \
-({ \
- __asm__ __volatile__( \

- "strb %0, [%1, %2] @ outbc" \


- : \
- : "r" (value), "r" (PCIO_BASE), "Jr" (port)); \
-})
-
-#define __inbc(port) \
-({ \
- unsigned char result; \
- __asm__ __volatile__( \

- "ldrb %0, [%1, %2] @ inbc" \


- : "=r" (result) \
- : "r" (PCIO_BASE), "Jr" (port)); \
- result; \
-})
-
-#define __outwc(value,port) \
-({ \
- __asm__ __volatile__( \

- "strh %0, [%1, %2] @ outwc" \


- : \
- : "r" (value), "r" (PCIO_BASE), "r" (port)); \
-})
-
-#define __inwc(port) \
-({ \
- unsigned short result; \
- __asm__ __volatile__( \

- "ldrh %0, [%1, %2] @ inwc" \


- : "=r" (result) \
- : "r" (PCIO_BASE), "r" (port)); \
- result & 0xffff; \
-})
-
-#define __outlc(value,port) \
-({ \
- __asm__ __volatile__( \

- "str %0, [%1, %2] @ outlc" \


- : \
- : "r" (value), "r" (PCIO_BASE), "Jr" (port)); \
-})
-
-#define __inlc(port) \
-({ \
- unsigned long result; \
- __asm__ __volatile__( \

- "ldr %0, [%1, %2] @ inlc" \


- : "=r" (result) \
- : "r" (PCIO_BASE), "Jr" (port)); \
- result; \
-})
-
-#define __ioaddrc(port) \
-({ \
- unsigned long addr; \
- addr = PCIO_BASE + port; \
- addr; \

-})
-
-/*
- * Translated address IO functions
- *
- * IO address has already been translated to a virtual address
- */
-#define outb_t(v,p) \
- (*(volatile unsigned char *)(p) = (v))
-
-#define inb_t(p) \
- (*(volatile unsigned char *)(p))
-
-#define outl_t(v,p) \
- (*(volatile unsigned long *)(p) = (v))
-
-#define inl_t(p) \
- (*(volatile unsigned long *)(p))
-
-/*
- * This is not sufficient... (and it's a hack anyway)


- */
-static inline void writeb(unsigned char b, unsigned int addr)
-{

- *(volatile unsigned char *)(0xe0000000 + (addr)) = b;


-}
-
-static inline unsigned char readb(unsigned int addr)
-{

- return *(volatile unsigned char *)(0xe0000000 + (addr));
-}
-


-static inline void writew(unsigned short b, unsigned int addr)
-{

- *(volatile unsigned short *)(0xe0000000 + (addr)) = b;
-}
-


-static inline unsigned short readw(unsigned int addr)
-{

- return *(volatile unsigned short *)(0xe0000000 + (addr));
-}
-


-static inline void writel(unsigned long b, unsigned int addr)
-{

- *(volatile unsigned long *)(0xe0000000 + (addr)) = b;
-}
-
-static inline unsigned long readl(unsigned int addr)
-{
- return *(volatile unsigned long *)(0xe0000000 + (addr));
-}
-
-#endif
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-vnc/irq.h linux/include/asm-arm/arch-vnc/irq.h
--- v2.2.7/linux/include/asm-arm/arch-vnc/irq.h Tue Dec 22 14:16:58 1998
+++ linux/include/asm-arm/arch-vnc/irq.h Wed Dec 31 16:00:00 1969
@@ -1,156 +0,0 @@
-/*
- * include/asm-arm/arch-vnc/irq.h
- *


- * Copyright (C) 1998 Russell King
- *

- * Changelog:


- * 22-08-1998 RMK Restructured IRQ routines

- */
-
-#include <asm/dec21285.h>
-#include <asm/irq.h>
-
-/*
- * FootBridge IRQ translation table
- * Converts form our IRQ numbers into FootBridge masks (defined in irqs.h)
- */
-static int fb_irq_mask[16] = {
- 0,
- IRQ_MASK_SOFTIRQ,
- IRQ_MASK_UART_DEBUG,
- 0,
- IRQ_MASK_TIMER0,
- IRQ_MASK_TIMER1,
- IRQ_MASK_TIMER2,
- IRQ_MASK_WATCHDOG,
- IRQ_MASK_ETHER10,
- IRQ_MASK_ETHER100,
- IRQ_MASK_VIDCOMP,
- IRQ_MASK_EXTERN_IRQ,
- IRQ_MASK_DMA1,
- 0,
- 0,
- IRQ_MASK_PCI_ERR
-};
-
-static void vnc_mask_csr_irq(unsigned int irq)
-{
- *CSR_IRQ_DISABLE = fb_irq_mask[irq];
-}
-
-static void vnc_unmask_csr_irq(unsigned int irq)
-{
- *CSR_IRQ_ENABLE = fb_irq_mask[irq];
-}
-
-static void vnc_mask_pic_lo_irq(unsigned int irq)
-{
- unsigned int mask = 1 << (irq & 7);
-
- outb(inb(PIC_MASK_LO) | mask, PIC_MASK_LO);
-}
-
-static void vnc_mask_ack_pic_lo_irq(unsigned int irq)
-{
- unsigned int mask = 1 << (irq & 7);
-
- outb(inb(PIC_MASK_LO) | mask, PIC_MASK_LO);
- outb(0x20, PIC_LO);
-}
-
-static void vnc_unmask_pic_lo_irq(unsigned int irq)
-{
- unsigned int mask = ~(1 << (irq & 7));
-
- outb(inb(PIC_MASK_LO) & mask, PIC_MASK_LO);
-}
-
-static void vnc_mask_pic_hi_irq(unsigned int irq)
-{
- unsigned int mask = 1 << (irq & 7);
-
- outb(inb(PIC_MASK_HI) | mask, PIC_MASK_HI);
-}
-
-static void vnc_mask_ack_pic_hi_irq(unsigned int irq)
-{
- unsigned int mask = 1 << (irq & 7);
-
- outb(inb(PIC_MASK_HI) | mask, PIC_MASK_HI);
- outb(0x62, PIC_LO);
- outb(0x20, PIC_HI);
-}
-
-static void vnc_unmask_pic_hi_irq(unsigned int irq)
-{
- unsigned int mask = 1 << (irq & 7);
-
- outb(inb(PIC_MASK_HI) & ~mask, PIC_MASK_HI);
-}
-
-static void no_action(int irq, void *dev_id, struct pt_regs *regs)
-{
-}
-
-static struct irqaction irq_cascade = { no_action, 0, 0, "cascade", NULL, NULL };
-
-static __inline__ void irq_init_irq(void)
-{
- unsigned int irq;
-
- outb(0x11, PIC_LO);
- outb(0x10, PIC_MASK_LO);
- outb(0x04, PIC_MASK_LO);
- outb(1, PIC_MASK_LO);
-
- outb(0x11, PIC_HI);
- outb(0x18, PIC_MASK_HI);
- outb(0x02, PIC_MASK_HI);
- outb(1, PIC_MASK_HI);
-
- *CSR_IRQ_DISABLE = ~IRQ_MASK_EXTERN_IRQ;
- *CSR_IRQ_ENABLE = IRQ_MASK_EXTERN_IRQ;
- *CSR_FIQ_DISABLE = -1;
-


- for (irq = 0; irq < NR_IRQS; irq++) {

- irq_desc[irq].valid = 1;
- irq_desc[irq].probe_ok = 1;
-
- if (irq < 16) {
- irq_desc[irq].mask_ack = vnc_mask_csr_irq;
- irq_desc[irq].mask = vnc_mask_csr_irq;
- irq_desc[irq].unmask = vnc_unmask_csr_irq;
- } else if (irq < 24) {
-irq_desc[irq].probe_ok = 0;
- irq_desc[irq].mask_ack = vnc_mask_ack_pic_lo_irq;
- irq_desc[irq].mask = vnc_mask_pic_lo_irq;
- irq_desc[irq].unmask = vnc_unmask_pic_lo_irq;
- } else {
-irq_desc[irq].probe_ok = 0;
- irq_desc[irq].mask_ack = vnc_mask_ack_pic_hi_irq;
- irq_desc[irq].mask = vnc_mask_pic_hi_irq;
- irq_desc[irq].unmask = vnc_unmask_pic_hi_irq;
- }
- }
-
- irq_desc[0].probe_ok = 0;
- irq_desc[IRQ_SOFTIRQ].probe_ok = 0;
- irq_desc[IRQ_CONRX].probe_ok = 0;
- irq_desc[IRQ_CONTX].probe_ok = 0;
- irq_desc[IRQ_TIMER0].probe_ok = 0;
- irq_desc[IRQ_TIMER1].probe_ok = 0;
- irq_desc[IRQ_TIMER2].probe_ok = 0;
- irq_desc[IRQ_WATCHDOG].probe_ok = 0;
- irq_desc[IRQ_DMA1].probe_ok = 0;
- irq_desc[13].probe_ok = 0;
- irq_desc[14].probe_ok = 0;
- irq_desc[IRQ_PCI_ERR].probe_ok = 0;
- irq_desc[IRQ_PIC_HI].probe_ok = 0;
- irq_desc[29].probe_ok = 0;
- irq_desc[31].probe_ok = 0;
-
- outb(0xff, PIC_MASK_LO);
- outb(0xff, PIC_MASK_HI);
-
- setup_arm_irq(IRQ_PIC_HI, &irq_cascade);
-}
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-vnc/irqs.h linux/include/asm-arm/arch-vnc/irqs.h
--- v2.2.7/linux/include/asm-arm/arch-vnc/irqs.h Fri Jan 8 22:36:22 1999
+++ linux/include/asm-arm/arch-vnc/irqs.h Wed Dec 31 16:00:00 1969
@@ -1,67 +0,0 @@
-/*
- * linux/include/asm-arm/arch-vnc/irqs.h
- *
- * Copyright (C) 1998 Russell King
- */
-
-#define NR_IRQS 32
-
-/*
- * This is a list of all interrupts that the 21285
- * can generate
- */
-#define IRQ_SOFTIRQ 1 /* from FB.1 */
-#define IRQ_CONRX 2 /* from FB.2 */
-#define IRQ_CONTX 3 /* from FB.3 */
-#define IRQ_TIMER0 4 /* from FB.4 */
-#define IRQ_TIMER1 5 /* from FB.5 */
-#define IRQ_TIMER2 6 /* from FB.6 */
-#define IRQ_WATCHDOG 7 /* from FB.7 */
-#define IRQ_ETHER10 8 /* from FB.8 */
-#define IRQ_ETHER100 9 /* from FB.9 */
-#define IRQ_VIDCOMP 10 /* from FB.10 */
-#define IRQ_EXTERN_IRQ 11 /* from FB.11: chain to IDE irq's */
-#define IRQ_DMA1 12 /* from future */
-#define IRQ_PCI_ERR 15 /* from FB.[28:31] */
-
-#define IRQ_TIMER4 16 /* from 553.0 */
-#define IRQ_KEYBOARD 17 /* from 553.1 */
-#define IRQ_PIC_HI 18 /* from 533.2: chained to 553.[8:15] */
-#define IRQ_UART2 19 /* from 553.3 */
-#define IRQ_UART 20 /* from 553.4 */
-#define IRQ_MOUSE 21 /* from 553.5 */
-#define IRQ_UART_IR 22 /* from 553.6 */
-#define IRQ_PRINTER 23 /* from 553.7 */
-#define IRQ_RTC_ALARM 24 /* from 553.8 */
-#define IRQ_POWERLOW 26 /* from 553.10 */
-#define IRQ_VGA 27 /* from 553.11 */
-#define IRQ_SOUND 28 /* from 553.12 */
-#define IRQ_HARDDISK 30 /* from 553.14 */
-
-/* These defines handle the translation from the above FB #defines
- * into physical bits for the FootBridge IRQ registers
- */
-#define IRQ_MASK_SOFTIRQ 0x00000002
-#define IRQ_MASK_UART_DEBUG 0x0000000C
-#define IRQ_MASK_TIMER0 0x00000010
-#define IRQ_MASK_TIMER1 0x00000020
-#define IRQ_MASK_TIMER2 0x00000040
-#define IRQ_MASK_WATCHDOG 0x00000080
-#define IRQ_MASK_ETHER10 0x00000100
-#define IRQ_MASK_ETHER100 0x00000200
-#define IRQ_MASK_VIDCOMP 0x00000400
-#define IRQ_MASK_EXTERN_IRQ 0x00000800
-#define IRQ_MASK_DMA1 0x00030000
-#define IRQ_MASK_PCI_ERR 0xf8800000
-
-/*


- * Now map them to the Linux interrupts

- */
-#undef IRQ_TIMER
-#define IRQ_TIMER IRQ_TIMER0
-#undef RTC_IRQ
-#define RTC_IRQ IRQ_RTC_ALARM
-#undef AUX_IRQ
-#define AUX_IRQ IRQ_MOUSE
-
-#define irq_cannonicalize(i) (i)
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-vnc/keyboard.h linux/include/asm-arm/arch-vnc/keyboard.h
--- v2.2.7/linux/include/asm-arm/arch-vnc/keyboard.h Wed Apr 28 11:37:31 1999
+++ linux/include/asm-arm/arch-vnc/keyboard.h Wed Dec 31 16:00:00 1969
@@ -1,36 +0,0 @@
-/*
- * linux/include/asm-arm/arch-vnc/keyboard.h
- *
- * Keyboard driver definitions for VNC architecture
- *
- * (C) 1998 Russell King
- */
-
-#include <asm/irq.h>
-
-#define NR_SCANCODES 128
-
-#define KEYBOARD_IRQ IRQ_KEYBOARD
-
-extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode);
-extern int pckbd_getkeycode(unsigned int scancode);
-extern int pckbd_translate(unsigned char scancode, unsigned char *keycode,
- char raw_mode);
-extern char pckbd_unexpected_up(unsigned char keycode);
-extern void pckbd_leds(unsigned char leds);
-extern void pckbd_init_hw(void);
-extern unsigned char pckbd_sysrq_xlate[128];
-


-#define kbd_setkeycode pckbd_setkeycode
-#define kbd_getkeycode pckbd_getkeycode
-#define kbd_translate(sc, kcp, ufp, rm) ({ *ufp = sc & 0200; \
- pckbd_translate(sc & 0x7f, kcp, rm);})

-


-#define kbd_unexpected_up pckbd_unexpected_up
-#define kbd_leds pckbd_leds

-#define kbd_init_hw() pckbd_init_hw()


-#define kbd_sysrq_xlate pckbd_sysrq_xlate
-#define kbd_disable_irq()
-#define kbd_enable_irq()

-
-#define SYSRQ_KEY 0x54
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-vnc/mm-init.h linux/include/asm-arm/arch-vnc/mm-init.h
--- v2.2.7/linux/include/asm-arm/arch-vnc/mm-init.h Tue Jul 21 00:15:32 1998
+++ linux/include/asm-arm/arch-vnc/mm-init.h Wed Dec 31 16:00:00 1969


@@ -1,5 +0,0 @@
-/*
- * linux/include/asm-arm/arch-ebsa110/mmap.h
- *
- * Copyright (C) 1996,1997,1998 Russell King
- */

diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-vnc/mmu.h linux/include/asm-arm/arch-vnc/mmu.h
--- v2.2.7/linux/include/asm-arm/arch-vnc/mmu.h Tue Dec 22 14:16:58 1998
+++ linux/include/asm-arm/arch-vnc/mmu.h Wed Dec 31 16:00:00 1969
@@ -1,26 +0,0 @@


-/*
- * linux/include/asm-arm/arch-ebsa110/mmu.h
- *
- * Copyright (c) 1996,1997,1998 Russell King.
- *
- * Changelog:
- * 20-10-1996 RMK Created
- * 31-12-1997 RMK Fixed definitions to reduce warnings
- */
-#ifndef __ASM_ARCH_MMU_H
-#define __ASM_ARCH_MMU_H
-

-/*
- * On ebsa, the dram is contiguous
- */
-#define __virt_to_phys__is_a_macro


-#define __virt_to_phys(vpage) ((vpage) - PAGE_OFFSET)
-#define __phys_to_virt__is_a_macro
-#define __phys_to_virt(ppage) ((ppage) + PAGE_OFFSET)
-
-#define __virt_to_bus__is_a_macro

-#define __virt_to_bus(x) (x - 0xe0000000)
-#define __bus_to_virt__is_a_macro
-#define __bus_to_virt(x) (x + 0xe0000000)
-
-#endif
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-vnc/oldlatches.h linux/include/asm-arm/arch-vnc/oldlatches.h
--- v2.2.7/linux/include/asm-arm/arch-vnc/oldlatches.h Tue Jul 21 00:15:32 1998
+++ linux/include/asm-arm/arch-vnc/oldlatches.h Wed Dec 31 16:00:00 1969


@@ -1,9 +0,0 @@
-/*
- * Dummy oldlatches.h
- *
- * Copyright (C) 1996 Russell King
- */
-
-#ifdef __need_oldlatches
-#error "Old latches not present in this (rpc) machine"
-#endif

diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-vnc/param.h linux/include/asm-arm/arch-vnc/param.h
--- v2.2.7/linux/include/asm-arm/arch-vnc/param.h Wed Sep 9 14:51:12 1998
+++ linux/include/asm-arm/arch-vnc/param.h Wed Dec 31 16:00:00 1969
@@ -1,8 +0,0 @@
-/*
- * linux/include/asm-arm/arch-vnc/param.h


- *
- * Copyright (C) 1996 Russell King

- * Copyright (C) 1998 Philip Blundell

- */
-
-#define HZ 100
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-vnc/processor.h linux/include/asm-arm/arch-vnc/processor.h
--- v2.2.7/linux/include/asm-arm/arch-vnc/processor.h Fri Jan 8 22:36:22 1999
+++ linux/include/asm-arm/arch-vnc/processor.h Wed Dec 31 16:00:00 1969
@@ -1,31 +0,0 @@
-/*
- * linux/include/asm-arm/arch-vnc/processor.h


- *
- * Copyright (C) 1996,1997,1998 Russell King
- */

-
-#ifndef __ASM_ARCH_PROCESSOR_H
-#define __ASM_ARCH_PROCESSOR_H
-
-/*
- * Bus types
- */
-#define EISA_bus 0
-#define EISA_bus__is_a_macro /* for versions in ksyms.c */
-#define MCA_bus 0
-#define MCA_bus__is_a_macro /* for versions in ksyms.c */
-


-/*
- * User space: 3GB
- */
-#define TASK_SIZE (0xc0000000UL)
-

-/* This decides where the kernel will search for a free chunk of vm
- * space during mmap's.
- */
-#define TASK_UNMAPPED_BASE (TASK_SIZE / 3)


-
-#define INIT_MMAP \
-{ &init_mm, 0, 0, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap }

-
-#endif
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-vnc/serial.h linux/include/asm-arm/arch-vnc/serial.h
--- v2.2.7/linux/include/asm-arm/arch-vnc/serial.h Tue Jul 21 00:15:32 1998
+++ linux/include/asm-arm/arch-vnc/serial.h Wed Dec 31 16:00:00 1969
@@ -1,43 +0,0 @@
-/*
- * linux/include/asm-arm/arch-vnc/serial.h
- *
- * Copyright (c) 1996 Russell King.


- *
- * Changelog:

- * 15-10-1996 RMK Created
- * 03-05-1998 RMK Modified for Corel Video NC
- */
-#ifndef __ASM_ARCH_SERIAL_H
-#define __ASM_ARCH_SERIAL_H
-
-#include <asm/irq.h>
-
-/*
- * This assumes you have a 1.8432 MHz clock for your UART.
- *
- * It'd be nice if someone built a serial card with a 24.576 MHz
- * clock, since the 16550A is capable of handling a top speed of 1.5
- * megabits/second; but this requires the faster clock.
- */
-#define BASE_BAUD (1843200 / 16)
-
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
-
- /* UART CLK PORT IRQ FLAGS */
-#define SERIAL_PORT_DFNS \
- { 0, BASE_BAUD, 0x3F8, IRQ_UART , STD_COM_FLAGS }, /* ttyS0 */ \
- { 0, BASE_BAUD, 0x2F8, IRQ_UART2, STD_COM_FLAGS }, /* ttyS1 */ \
- { 0, BASE_BAUD, 0 , 0 , STD_COM_FLAGS }, /* ttyS2 */ \
- { 0, BASE_BAUD, 0 , 0 , STD_COM_FLAGS }, /* ttyS3 */ \
- { 0, BASE_BAUD, 0 , 0 , STD_COM_FLAGS }, /* ttyS4 */ \
- { 0, BASE_BAUD, 0 , 0 , STD_COM_FLAGS }, /* ttyS5 */ \
- { 0, BASE_BAUD, 0 , 0 , STD_COM_FLAGS }, /* ttyS6 */ \
- { 0, BASE_BAUD, 0 , 0 , STD_COM_FLAGS }, /* ttyS7 */ \
- { 0, BASE_BAUD, 0 , 0 , STD_COM_FLAGS }, /* ttyS8 */ \
- { 0, BASE_BAUD, 0 , 0 , STD_COM_FLAGS }, /* ttyS9 */ \
- { 0, BASE_BAUD, 0 , 0 , STD_COM_FLAGS }, /* ttyS10 */ \
- { 0, BASE_BAUD, 0 , 0 , STD_COM_FLAGS }, /* ttyS11 */ \
- { 0, BASE_BAUD, 0 , 0 , STD_COM_FLAGS }, /* ttyS12 */ \
- { 0, BASE_BAUD, 0 , 0 , STD_COM_FLAGS }, /* ttyS13 */
-
-#endif
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-vnc/shmparam.h linux/include/asm-arm/arch-vnc/shmparam.h
--- v2.2.7/linux/include/asm-arm/arch-vnc/shmparam.h Tue Jul 21 00:15:32 1998
+++ linux/include/asm-arm/arch-vnc/shmparam.h Wed Dec 31 16:00:00 1969


@@ -1,5 +0,0 @@
-/*

- * linux/include/asm-arm/arch-ebsa110/shmparam.h
- *
- * Copyright (c) 1996 Russell King.
- */
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-vnc/system.h linux/include/asm-arm/arch-vnc/system.h
--- v2.2.7/linux/include/asm-arm/arch-vnc/system.h Fri Jan 8 22:36:22 1999
+++ linux/include/asm-arm/arch-vnc/system.h Wed Dec 31 16:00:00 1969
@@ -1,37 +0,0 @@
-/*
- * linux/include/asm-arm/arch-vnc/system.h


- *
- * Copyright (c) 1996,1997,1998 Russell King.

- * Copyright (c) 1998 Corel Computer Corp.
- */
-#include <asm/hardware.h>
-#include <asm/dec21285.h>
-#include <asm/leds.h>
-#include <asm/io.h>
-
-extern __inline__ void arch_reset(char mode)
-{
- cli();
-
- /* open up the SuperIO chip
- */
- outb(0x87, 0x370);
- outb(0x87, 0x370);
-
- /* aux function group 1 (Logical Device 7)
- */
- outb(0x07, 0x370);
- outb(0x07, 0x371);
-
- /* set GP16 for WD-TIMER output
- */
- outb(0xE6, 0x370);
- outb(0x00, 0x371);
-
- /* set a RED LED and toggle WD_TIMER for rebooting...
- */
- outb(0xC4, 0x338);
-}
-
-#define arch_start_idle() leds_event(led_idle_start)
-#define arch_end_idle() leds_event(led_idle_end)
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-vnc/time.h linux/include/asm-arm/arch-vnc/time.h
--- v2.2.7/linux/include/asm-arm/arch-vnc/time.h Fri Jan 8 22:36:22 1999
+++ linux/include/asm-arm/arch-vnc/time.h Wed Dec 31 16:00:00 1969
@@ -1,232 +0,0 @@
-/*
- * linux/include/asm-arm/arch-vnc/time.h
- *
- * Copyright (c) 1997 Corel Computer Corp.
- * Slight modifications to bring in line with ebsa285 port.
- * -- Russell King.
- * Added LED driver (based on the ebsa285 code) - Alex Holden 28/12/98.
- */
-
-#include <linux/config.h>
-#include <linux/mc146818rtc.h>
-
-#include <asm/leds.h>
-#include <asm/system.h>
-
-#undef IRQ_TIMER
-#define IRQ_TIMER IRQ_TIMER4
-
-#define mSEC_10_from_14 ((14318180 + 100) / 200)
-


-extern __inline__ unsigned long gettimeoffset (void)

-{
- int count;
-
- static int count_p = (mSEC_10_from_14/6); /* for the first call after boot */
- static unsigned long jiffies_p = 0;
-
- /*
- * cache volatile jiffies temporarily; we have IRQs turned off.
- */
- unsigned long jiffies_t;
-
- /* timer count may underflow right here */
- outb_p(0x00, 0x43); /* latch the count ASAP */
-
- count = inb_p(0x40); /* read the latched count */
-
- /*
- * We do this guaranteed double memory access instead of a _p
- * postfix in the previous port access. Wheee, hackady hack
- */
- jiffies_t = jiffies;
-
- count |= inb_p(0x40) << 8;
-
- /* Detect timer underflows. If we haven't had a timer tick since
- the last time we were called, and time is apparently going
- backwards, the counter must have wrapped during this routine. */
- if ((jiffies_t == jiffies_p) && (count > count_p))
- count -= (mSEC_10_from_14/6);
- else
- jiffies_p = jiffies_t;
-
- count_p = count;
-
- count = (((mSEC_10_from_14/6)-1) - count) * tick;
- count = (count + (mSEC_10_from_14/6)/2) / (mSEC_10_from_14/6);
-
- return count;
-}
-


-extern __inline__ int reset_timer (void)
-{

-#ifdef CONFIG_LEDS


- static unsigned int count = 50;
- static int last_pid;
-
- if (current->pid != last_pid) {
- last_pid = current->pid;
- if (last_pid)
- leds_event(led_idle_end);
- else
- leds_event(led_idle_start);
- }
-
- if (--count == 0) {
- count = 50;
- leds_event(led_timer);
- }

-#endif


- return 1;
-}
-

-unsigned long set_rtc_mmss(unsigned long nowtime)
-{
- int retval = 0;
- int real_seconds, real_minutes, cmos_minutes;
- unsigned char save_control, save_freq_select;
-
- save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */
- CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
-
- save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */
- CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
-
- cmos_minutes = CMOS_READ(RTC_MINUTES);
- if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
- BCD_TO_BIN(cmos_minutes);
-
- /*
- * since we're only adjusting minutes and seconds,
- * don't interfere with hour overflow. This avoids
- * messing with unknown time zones but requires your
- * RTC not to be off by more than 15 minutes
- */
- real_seconds = nowtime % 60;
- real_minutes = nowtime / 60;
- if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
- real_minutes += 30; /* correct for half hour time zone */
- real_minutes %= 60;
-
- if (abs(real_minutes - cmos_minutes) < 30) {
- if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
- BIN_TO_BCD(real_seconds);
- BIN_TO_BCD(real_minutes);
- }
- CMOS_WRITE(real_seconds,RTC_SECONDS);
- CMOS_WRITE(real_minutes,RTC_MINUTES);
- } else
- retval = -1;
-
- /* The following flags have to be released exactly in this order,
- * otherwise the DS12887 (popular MC146818A clone with integrated
- * battery and quartz) will not reset the oscillator and will not
- * update precisely 500 ms later. You won't find this mentioned in
- * the Dallas Semiconductor data sheets, but who believes data
- * sheets anyway ... -- Markus Kuhn
- */
- CMOS_WRITE(save_control, RTC_CONTROL);
- CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
-
- return retval;
-}
-


-/*
- * We don't have a RTC to update!
- */

-extern __inline__ void update_rtc(void)
-{
- static long last_rtc_update = 0; /* last time the cmos clock got updated */
-
- /* If we have an externally synchronized linux clock, then update
- * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
- * called as close as possible to 500 ms before the new second starts.
- */
- if (time_state != TIME_BAD && xtime.tv_sec > last_rtc_update + 660 &&
- xtime.tv_usec > 50000 - (tick >> 1) &&
- xtime.tv_usec < 50000 + (tick >> 1)) {
- if (set_rtc_mmss(xtime.tv_sec) == 0)
- last_rtc_update = xtime.tv_sec;
- else
- last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
- }
-}
-
-extern __inline__ unsigned long get_cmos_time(void)
-{


- unsigned int year, mon, day, hour, min, sec;

- int i;
-
- // check to see if the RTC makes sense.....
- if ((CMOS_READ(RTC_VALID) & RTC_VRT) == 0)


- return mktime(1970, 1, 1, 0, 0, 0);

-
- /* The Linux interpretation of the CMOS clock register contents:
- * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
- * RTC registers show the second which has precisely just started.
- * Let's hope other operating systems interpret the RTC the same way.
- */
- /* read RTC exactly on falling edge of update flag */
- for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */
- if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
- break;
-
- for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */
- if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
- break;
-
- do { /* Isn't this overkill ? UIP above should guarantee consistency */
- sec = CMOS_READ(RTC_SECONDS);
- min = CMOS_READ(RTC_MINUTES);
- hour = CMOS_READ(RTC_HOURS);
- day = CMOS_READ(RTC_DAY_OF_MONTH);
- mon = CMOS_READ(RTC_MONTH);
- year = CMOS_READ(RTC_YEAR);
- } while (sec != CMOS_READ(RTC_SECONDS));
-
- if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {


- BCD_TO_BIN(sec);
- BCD_TO_BIN(min);
- BCD_TO_BIN(hour);
- BCD_TO_BIN(day);
- BCD_TO_BIN(mon);
- BCD_TO_BIN(year);
- }

- if ((year += 1900) < 1970)
- year += 100;

- return mktime(year, mon, day, hour, min, sec);

-}
-
-/*
- * Set up timer interrupt, and return the current time in seconds.
- */


-extern __inline__ unsigned long setup_timer (void)

-{
- unsigned int c;
-
- /* Turn on the RTC */
- outb(13, 0x70);
- if ((inb(0x71) & 0x80) == 0)
- printk("RTC: *** warning: CMOS battery bad\n");
-
- outb(10, 0x70); /* select control reg */
- outb(32, 0x71); /* make sure the divider is set */
- outb(11, 0x70); /* select other control reg */
- c = inb(0x71) & 0xfb; /* read it */
- outb(11, 0x70);
- outb(c | 2, 0x71); /* turn on BCD counting and 24 hour clock mode */
-
- /* enable PIT timer */
- /* set for periodic (4) and LSB/MSB write (0x30) */
- outb(0x34, 0x43);
- outb((mSEC_10_from_14/6) & 0xFF, 0x40);
- outb((mSEC_10_from_14/6) >> 8, 0x40);
-
- /*
- * Default the date to 1 Jan 1970 00:00:00
- * You will have to run a time daemon to set the


SHAR_EOF
true || echo 'restore of patch-2.2.8 failed'
fi

echo 'End of part 27'
echo 'File patch-2.2.8 is continued in part 28'
echo 28 > _shar_seq_.tmp

Thomas...@ciw.uni-karlsruhe.de

unread,
May 12, 1999, 3:00:00 AM5/12/99
to
Archive-name: v2.2/patch-2.2.8/part28

#!/bin/sh
# this is part 28 of a 33 - part archive


# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.8 continued
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 28; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.8'
else
echo 'x - continuing with patch-2.2.8'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.8' &&

- * clock correctly at bootup
- */
- return get_cmos_time();
-}
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-vnc/timex.h linux/include/asm-arm/arch-vnc/timex.h
--- v2.2.7/linux/include/asm-arm/arch-vnc/timex.h Tue Jul 21 00:15:32 1998
+++ linux/include/asm-arm/arch-vnc/timex.h Wed Dec 31 16:00:00 1969
@@ -1,13 +0,0 @@
-/*
- * linux/include/asm-arm/arch-vnc/timex.h
- *
- * Corel Video NC architecture timex specifications


- *
- * Copyright (C) 1998 Corel Computer/Russell King

- */
-
-/*
- * On the VNC, the clock runs at 66MHz and is divided
- * by a 4-bit prescaler.
- */
-#define CLOCK_TICK_RATE (66000000 / 16)
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/arch-vnc/uncompress.h linux/include/asm-arm/arch-vnc/uncompress.h
--- v2.2.7/linux/include/asm-arm/arch-vnc/uncompress.h Wed Sep 9 14:51:12 1998
+++ linux/include/asm-arm/arch-vnc/uncompress.h Wed Dec 31 16:00:00 1969
@@ -1,34 +0,0 @@
-/*
- * linux/include/asm-arm/arch-ebsa110/uncompress.h


- *
- * Copyright (C) 1996,1997,1998 Russell King
- */
-

-/*
- * This does not append a newline
- */
-static void puts(const char *s)
-{
- __asm__ __volatile__("
- ldrb %0, [%2], #1
- teq %0, #0
- beq 3f
-1: strb %0, [%3]
-2: ldrb %1, [%3, #0x14]
- and %1, %1, #0x60
- teq %1, #0x60
- bne 2b
- teq %0, #'\n'
- moveq %0, #'\r'
- beq 1b
- ldrb %0, [%2], #1
- teq %0, #0
- bne 1b
-3: " : : "r" (0), "r" (0), "r" (s), "r" (0xf0000be0) : "cc");
-}
-
-/*
- * nothing to do
- */
-#define arch_decomp_setup()
-#define arch_decomp_wdog()
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/dec21285.h linux/include/asm-arm/dec21285.h
--- v2.2.7/linux/include/asm-arm/dec21285.h Fri Jan 8 22:36:22 1999
+++ linux/include/asm-arm/dec21285.h Sat May 8 11:06:57 1999
@@ -15,17 +15,20 @@
X #define DC21285_PCI_MEM 0x80000000
X
X #ifndef __ASSEMBLY__
-#define DC21285_IO(x) ((volatile unsigned long *)(0xfe000000+(x)))
+#include <asm/arch/hardware.h>
+#define DC21285_IO(x) ((volatile unsigned long *)(ARMCSR_BASE+(x)))
X #else
X #define DC21285_IO(x) (x)
X #endif
X
X #define CSR_PCICMD DC21285_IO(0x0004)
+#define CSR_CLASSREV DC21285_IO(0x0008)
X #define CSR_PCICACHELINESIZE DC21285_IO(0x000c)
X #define CSR_PCICSRBASE DC21285_IO(0x0010)
X #define CSR_PCICSRIOBASE DC21285_IO(0x0014)
X #define CSR_PCISDRAMBASE DC21285_IO(0x0018)
X #define CSR_PCIROMBASE DC21285_IO(0x0030)
+#define CSR_ROMWRITEREG DC21285_IO(0x0068)
X #define CSR_CSRBASEMASK DC21285_IO(0x00f8)
X #define CSR_CSRBASEOFFSET DC21285_IO(0x00fc)
X #define CSR_SDRAMBASEMASK DC21285_IO(0x0100)
@@ -44,6 +47,33 @@
X #define CSR_I2O_OUTPOSTCOUNT DC21285_IO(0x0134)
X #define CSR_I2O_INPOSTCOUNT DC21285_IO(0x0138)
X #define CSR_SA110_CNTL DC21285_IO(0x013c)
+#define SA110_CNTL_INITCMPLETE (1 << 0)
+#define SA110_CNTL_ASSERTSERR (1 << 1)
+#define SA110_CNTL_RXSERR (1 << 3)
+#define SA110_CNTL_SA110DRAMPARITY (1 << 4)
+#define SA110_CNTL_PCISDRAMPARITY (1 << 5)
+#define SA110_CNTL_DMASDRAMPARITY (1 << 6)
+#define SA110_CNTL_DISCARDTIMER (1 << 8)
+#define SA110_CNTL_PCINRESET (1 << 9)
+#define SA110_CNTL_I2O_256 (0 << 10)
+#define SA110_CNTL_I20_512 (1 << 10)
+#define SA110_CNTL_I2O_1024 (2 << 10)
+#define SA110_CNTL_I2O_2048 (3 << 10)
+#define SA110_CNTL_I2O_4096 (4 << 10)
+#define SA110_CNTL_I2O_8192 (5 << 10)
+#define SA110_CNTL_I2O_16384 (6 << 10)
+#define SA110_CNTL_I2O_32768 (7 << 10)
+#define SA110_CNTL_WATCHDOG (1 << 13)
+#define SA110_CNTL_ROMWIDTH_UNDEF (0 << 14)
+#define SA110_CNTL_ROMWIDTH_16 (1 << 14)
+#define SA110_CNTL_ROMWIDTH_32 (2 << 14)
+#define SA110_CNTL_ROMWIDTH_8 (3 << 14)
+#define SA110_CNTL_ROMACCESSTIME(x) ((x)<<16)
+#define SA110_CNTL_ROMBURSTTIME(x) ((x)<<20)
+#define SA110_CNTL_ROMTRISTATETIME(x) ((x)<<24)
+#define SA110_CNTL_XCSDIR(x) ((x)<<28)
+#define SA110_CNTL_PCICFN (1 << 31)
+
X #define CSR_PCIADDR_EXTN DC21285_IO(0x0140)
X #define CSR_PREFETCHMEMRANGE DC21285_IO(0x0144)
X #define CSR_XBUS_CYCLE DC21285_IO(0x0148)
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/dma.h linux/include/asm-arm/dma.h
--- v2.2.7/linux/include/asm-arm/dma.h Fri Jan 8 22:36:22 1999
+++ linux/include/asm-arm/dma.h Sat May 8 11:07:16 1999
@@ -6,20 +6,20 @@
X #include <linux/config.h>
X #include <linux/kernel.h>
X #include <asm/irq.h>
-#include <asm/system.h>
X #include <asm/spinlock.h>
X #include <asm/arch/dma.h>
X
X /*
- * DMA modes - we have two, IN and OUT
+ * DMA modes
X */
X typedef unsigned int dmamode_t;
X
-#define DMA_MODE_MASK 1
+#define DMA_MODE_MASK 3
X
-#define DMA_MODE_READ 0
-#define DMA_MODE_WRITE 1
-#define DMA_AUTOINIT 2
+#define DMA_MODE_READ 0
+#define DMA_MODE_WRITE 1
+#define DMA_MODE_CASCADE 2
+#define DMA_AUTOINIT 4
X
X typedef struct {
X unsigned long address;
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/ecard.h linux/include/asm-arm/ecard.h
--- v2.2.7/linux/include/asm-arm/ecard.h Tue Dec 22 14:16:58 1998
+++ linux/include/asm-arm/ecard.h Sat May 8 11:06:57 1999
@@ -47,6 +47,9 @@
X #define MANU_ICS 0x003c
X #define PROD_ICS_IDE 0x00ae
X
+#define MANU_ICS2 0x003d
+#define PROD_ICS2_IDE 0x00ae
+
X #define MANU_SERPORT 0x003f
X #define PROD_SERPORT_DSPORT 0x00b9
X
@@ -76,7 +79,7 @@
X #define CONST const
X #endif
X
-#define MAX_ECARDS 8
+#define MAX_ECARDS 9
X
X typedef enum { /* Cards address space */
X ECARD_IOC,
@@ -116,14 +119,18 @@
X typedef struct { /* Card handler routines */
X void (*irqenable)(ecard_t *ec, int irqnr);
X void (*irqdisable)(ecard_t *ec, int irqnr);
+ int (*irqpending)(ecard_t *ec);
X void (*fiqenable)(ecard_t *ec, int fiqnr);
X void (*fiqdisable)(ecard_t *ec, int fiqnr);
+ int (*fiqpending)(ecard_t *ec);
X } expansioncard_ops_t;
X
X /*
X * This contains all the info needed on an expansion card
X */
X struct expansion_card {
+ struct expansion_card *next;
+
X /* Public data */
X volatile unsigned char *irqaddr; /* address of IRQ register */
X volatile unsigned char *fiqaddr; /* address of FIQ register */
@@ -135,10 +142,10 @@
X void *fiq_data; /* Data for use for FIQ by card */
X expansioncard_ops_t *ops; /* Enable/Disable Ops for card */
X
- CONST unsigned char slot_no; /* Slot number */
- CONST unsigned char dma; /* DMA number (for request_dma) */
- CONST unsigned char irq; /* IRQ number (for request_irq) */
- CONST unsigned char fiq; /* FIQ number (for request_irq) */
+ CONST unsigned int slot_no; /* Slot number */
+ CONST unsigned int dma; /* DMA number (for request_dma) */
+ CONST unsigned int irq; /* IRQ number (for request_irq) */
+ CONST unsigned int fiq; /* FIQ number (for request_irq) */
X CONST card_type_t type; /* Type of card */
X CONST struct in_ecid cid; /* Card Identification */
X
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/fiq.h linux/include/asm-arm/fiq.h
--- v2.2.7/linux/include/asm-arm/fiq.h Wed Sep 9 14:51:12 1998
+++ linux/include/asm-arm/fiq.h Sat May 8 11:06:57 1999
@@ -30,5 +30,6 @@
X extern void release_fiq(struct fiq_handler *f);
X extern void set_fiq_handler(void *start, unsigned int length);
X extern void set_fiq_regs(struct pt_regs *regs);
+extern void get_fiq_regs(struct pt_regs *regs);
X
X #endif
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/floppy.h linux/include/asm-arm/floppy.h
--- v2.2.7/linux/include/asm-arm/floppy.h Tue Jun 23 10:01:26 1998
+++ linux/include/asm-arm/floppy.h Sat May 8 11:06:57 1999
@@ -120,5 +120,20 @@
X #define FLOPPY_MOTOR_MASK 0xf0
X
X #define CROSS_64KB(a,s) (0)
+
+/*
+ * This allows people to reverse the order of
+ * fd0 and fd1, in case their hardware is
+ * strangely connected (as some RiscPCs
+ * and A5000s seem to be).
+ */
+static void driveswap(int *ints, int dummy, int dummy2)
+{
+ floppy_selects[0][0] ^= floppy_selects[0][1];
+ floppy_selects[0][1] ^= floppy_selects[0][0];
+ floppy_selects[0][0] ^= floppy_selects[0][1];
+}
+
+#define EXTRA_FLOPPY_PARAMS ,{ "driveswap", &driveswap, NULL, 0, 0 }
X
X #endif
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/hardware.h linux/include/asm-arm/hardware.h
--- v2.2.7/linux/include/asm-arm/hardware.h Fri Jan 8 22:36:22 1999
+++ linux/include/asm-arm/hardware.h Sat May 8 11:06:57 1999
@@ -11,10 +11,6 @@
X
X #include <asm/arch/hardware.h>
X
-#ifndef FLUSH_BASE
-#define FLUSH_BASE 0xdf000000
-#endif
-
X #ifdef HAS_EXPMASK
X #ifndef __ASSEMBLER__
X #define __EXPMASK(offset) (((volatile unsigned char *)EXPMASK_BASE)[offset])
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/init.h linux/include/asm-arm/init.h
--- v2.2.7/linux/include/asm-arm/init.h Fri Jan 8 22:36:22 1999
+++ linux/include/asm-arm/init.h Sat May 8 11:06:57 1999
@@ -5,7 +5,7 @@
X
X /* C routines */
X
-#ifdef CONFIG_TEXT_INIT_SECTION
+#ifdef CONFIG_TEXT_SECTIONS
X
X #define __init __attribute__ ((__section__ (".text.init")))
X #define __initfunc(__arginit) \
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/io.h linux/include/asm-arm/io.h
--- v2.2.7/linux/include/asm-arm/io.h Fri Jan 8 22:36:22 1999
+++ linux/include/asm-arm/io.h Sat May 8 11:06:57 1999
@@ -8,12 +8,35 @@
X * constant addresses and variable addresses.
X * 04-Dec-1997 RMK Moved a lot of this stuff to the new architecture
X * specific IO header files.
+ * 27-Mar-1999 PJB Second parameter of memcpy_toio is const..
+ * 04-Apr-1999 PJB Added check_signature.
X */
X #ifndef __ASM_ARM_IO_H
X #define __ASM_ARM_IO_H
X
+#ifdef __KERNEL__
+
+#ifndef NULL
+#define NULL ((void *) 0)
+#endif
+
+extern void * __ioremap(unsigned long offset, unsigned long size, unsigned long flags);
+
+/*
+ * String version of IO memory access ops:
+ */
+extern void _memcpy_fromio(void *, unsigned long, unsigned long);
+extern void _memcpy_toio(unsigned long, const void *, unsigned long);
+extern void _memset_io(unsigned long, int, unsigned long);
+
+#define memcpy_fromio(to,from,len) _memcpy_fromio((to),(unsigned long)(from),(len))
+#define memcpy_toio(to,from,len) _memcpy_toio((unsigned long)(to),(from),(len))
+#define memset_io(addr,c,len) _memset_io((unsigned long)(addr),(c),(len))
+
+#endif
+
X #include <asm/hardware.h>
-#include <asm/arch/mmu.h>
+#include <asm/arch/memory.h>
X #include <asm/arch/io.h>
X #include <asm/proc/io.h>
X
@@ -168,25 +191,43 @@
X
X #endif
X
-#undef ARCH_IO_DELAY
-#undef ARCH_IO_CONSTANT
+#ifndef ARCH_READWRITE
X
-#ifdef __KERNEL__
+/* for panic */
+#include <linux/kernel.h>
X
-extern void * __ioremap(unsigned long offset, unsigned long size, unsigned long flags);
+#define readb(p) (panic("readb called, but not implemented"),0)
+#define readw(p) (panic("readw called, but not implemented"),0)
+#define readl(p) (panic("readl called, but not implemented"),0)
+#define writeb(v,p) panic("writeb called, but not implemented")
+#define writew(v,p) panic("writew called, but not implemented")
+#define writel(v,p) panic("writel called, but not implemented")
X
-/*
- * String version of IO memory access ops:
- */
-extern void _memcpy_fromio(void *, unsigned long, unsigned long);
-extern void _memcpy_toio(unsigned long, void *, unsigned long);
-extern void _memset_io(unsigned long, int, unsigned long);
+#endif
X
-#define memcpy_fromio(to,from,len) _memcpy_fromio((to),(unsigned long)(from),(len))
-#define memcpy_toio(to,from,len) _memcpy_toio((unsigned long)(to),(from),(len))
-#define memset_io(addr,c,len) _memset_io((unsigned long)(addr),(c),(len))
+/*
+ * This isn't especially architecture dependent so it seems like it
+ * might as well go here as anywhere.
+ */
+static inline int check_signature(unsigned long io_addr,
+ const unsigned char *signature, int length)


+{
+ int retval = 0;

+ do {
+ if (readb(io_addr) != *signature)
+ goto out;
+ io_addr++;
+ signature++;
+ length--;
+ } while (length);
+ retval = 1;
+out:
+ return retval;
+}
X
-#endif
+#undef ARCH_READWRITE
+#undef ARCH_IO_DELAY
+#undef ARCH_IO_CONSTANT
X
X #endif
X
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/ioc.h linux/include/asm-arm/ioc.h
--- v2.2.7/linux/include/asm-arm/ioc.h Fri Jan 8 22:36:22 1999
+++ linux/include/asm-arm/ioc.h Sat May 8 11:06:57 1999
@@ -3,6 +3,8 @@
X * read/write.
X */
X
+#ifndef IOC_CONTROL
+
X #ifndef __ASSEMBLER__
X #define __IOC(offset) (IOC_BASE + (offset >> 2))
X #else
@@ -54,3 +56,4 @@
X #define IOC_T3GO __IOC(0x78)
X #define IOC_T3LATCH __IOC(0x7c)
X
+#endif
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/iomd.h linux/include/asm-arm/iomd.h
--- v2.2.7/linux/include/asm-arm/iomd.h Fri Jan 8 22:36:22 1999
+++ linux/include/asm-arm/iomd.h Sat May 8 11:06:57 1999
@@ -125,6 +125,8 @@
X #define DMA_ST_OFL 4
X #define DMA_ST_INT 2
X #define DMA_ST_AB 1
+
+#ifndef IOC_CONTROL
X /*
X * IOC compatability
X */
@@ -155,6 +157,7 @@
X #define IOC_T1LTCHH IOMD_T1LTCHH
X #define IOC_T1GO IOMD_T1GO
X #define IOC_T1LATCH IOMD_T1LATCH
+#endif
X
X /*
X * DMA (MEMC) compatability
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/irq.h linux/include/asm-arm/irq.h
--- v2.2.7/linux/include/asm-arm/irq.h Tue Dec 22 14:16:58 1998
+++ linux/include/asm-arm/irq.h Sat May 8 11:07:16 1999
@@ -16,8 +16,10 @@
X * capability
X */
X #ifndef NO_IRQ
-#define NO_IRQ 255
+#define NO_IRQ ((unsigned int)(-1))
X #endif
+
+#define disable_irq_nosync(i) disable_irq(i)
X
X extern void disable_irq(unsigned int);
X extern void enable_irq(unsigned int);
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/leds.h linux/include/asm-arm/leds.h
--- v2.2.7/linux/include/asm-arm/leds.h Fri Jan 8 22:36:22 1999
+++ linux/include/asm-arm/leds.h Sat May 8 11:06:57 1999
@@ -10,15 +10,32 @@
X #ifndef ASM_ARM_LEDS_H
X #define ASM_ARM_LEDS_H
X
+#include <linux/config.h>
+
X typedef enum {
X led_idle_start,
X led_idle_end,
X led_timer,
X led_start,
- led_stop
+ led_stop,
+ led_claim, /* override idle & timer leds */
+ led_release, /* restore idle & timer leds */
+ led_green_on,
+ led_green_off,
+ led_amber_on,
+ led_amber_off,
+ led_red_on,
+ led_red_off
X } led_event_t;
X
X /* Use this routine to handle LEDs */
-extern void leds_event(led_event_t);
+
+#ifdef CONFIG_LEDS
+extern void (*leds_event)(led_event_t);
+#define set_leds_event(r) leds_event = r
+#else
+#define leds_event(e)
+#define set_leds_event(r)
+#endif
X
X #endif
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/memc.h linux/include/asm-arm/memc.h
--- v2.2.7/linux/include/asm-arm/memc.h Fri Jan 8 22:36:22 1999
+++ linux/include/asm-arm/memc.h Sat May 8 11:06:57 1999
@@ -4,6 +4,9 @@
X #define VDMA_START 1
X #define VDMA_END 2
X
+#ifndef __ASSEMBLER__
+extern void memc_write(unsigned int reg, unsigned long val);
+
X #define video_set_dma(start,end,offset) \
X do { \
X memc_write (VDMA_START, (start >> 2)); \
@@ -11,3 +14,4 @@
X memc_write (VDMA_INIT, (offset >> 2)); \
X } while (0)
X
+#endif
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/mm-init.h linux/include/asm-arm/mm-init.h
--- v2.2.7/linux/include/asm-arm/mm-init.h Tue Jan 20 16:39:42 1998
+++ linux/include/asm-arm/mm-init.h Wed Dec 31 16:00:00 1969
@@ -1,46 +0,0 @@
-/*
- * linux/include/asm-arm/mm-init.h


- *
- * Copyright (C) 1997,1998 Russell King
- *

- * Contained within are structures to describe how to set up the
- * initial memory map. It includes both a processor-specific header
- * for parsing these structures, and an architecture-specific header
- * to fill out the structures.
- */
-#ifndef __ASM_MM_INIT_H
-#define __ASM_MM_INIT_H
-
-typedef enum {
- // physical address is absolute
- init_mem_map_absolute,
- /* physical address is relative to start_mem
- * as passed in paging_init
- */
- init_mem_map_relative_start_mem
-} init_memmap_type_t;
-
-typedef struct {
- init_memmap_type_t type;
- unsigned long physical_address;
- unsigned long virtual_address;
- unsigned long size;
-} init_memmap_t;
-
-#define INIT_MEM_MAP_SENTINEL { init_mem_map_absolute, 0, 0, 0 }
-#define INIT_MEM_MAP_ABSOLUTE(p,l,s) { init_mem_map_absolute,p,l,s }
-#define INIT_MEM_MAP_RELATIVE(o,l,s) { init_mem_map_relative_start_mem,o,l,s }
-
-/*
- * Within this file, initialise an array of init_mem_map_t's
- * to describe your initial memory mapping structure.
- */
-#include <asm/arch/mm-init.h>
-
-/*
- * Contained within this file is code to read the array
- * of init_mem_map_t's created above.
- */
-#include <asm/proc/mm-init.h>
-
-#endif
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/page.h linux/include/asm-arm/page.h
--- v2.2.7/linux/include/asm-arm/page.h Fri May 8 23:14:54 1998
+++ linux/include/asm-arm/page.h Sat May 8 11:06:57 1999
@@ -1,15 +1,15 @@
X #ifndef _ASMARM_PAGE_H
X #define _ASMARM_PAGE_H
X
-#include <asm/arch/mmu.h>
+#include <asm/arch/memory.h>
X #include <asm/proc/page.h>
X
X #ifdef __KERNEL__
X
X #define get_user_page(vaddr) __get_free_page(GFP_KERNEL)
X #define free_user_page(page, addr) free_page(addr)
-#define clear_page(page) memzero((void *)(page), PAGE_SIZE)
-#define copy_page(to,from) memcpy((void *)(to), (void *)(from), PAGE_SIZE)
+#define clear_page(page) memzero((void *)(page), PAGE_SIZE)
+#define copy_page(to,from) memcpy((void *)(to), (void *)(from), PAGE_SIZE)
X
X #endif
X
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/posix_types.h linux/include/asm-arm/posix_types.h
--- v2.2.7/linux/include/asm-arm/posix_types.h Tue Dec 22 14:16:58 1998
+++ linux/include/asm-arm/posix_types.h Sat May 8 11:06:57 1999
@@ -45,6 +45,8 @@
X #endif /* !defined(__KERNEL__) && !defined(__USE_ALL) */
X } __kernel_fsid_t;
X
+#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
+
X #undef __FD_SET
X #define __FD_SET(fd, fdsetp) \
X (((fd_set *)fdsetp)->fds_bits[fd >> 5] |= (1<<(fd & 31)))
@@ -60,5 +62,7 @@
X #undef __FD_ZERO
X #define __FD_ZERO(fdsetp) \
X (memset (fdsetp, 0, sizeof (*(fd_set *)fdsetp)))
+
+#endif
X
X #endif
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/proc-armo/mm-init-flat.h linux/include/asm-arm/proc-armo/mm-init-flat.h
--- v2.2.7/linux/include/asm-arm/proc-armo/mm-init-flat.h Tue Jan 20 16:39:42 1998
+++ linux/include/asm-arm/proc-armo/mm-init-flat.h Wed Dec 31 16:00:00 1969
@@ -1,82 +0,0 @@
-/*
- * linux/include/asm-arm/proc-armo/mmap.h


- *
- * Copyright (C) 1996 Russell King
- *

- * This contains the code to setup the memory map on an ARM2/ARM250/ARM3
- * machine. This is both processor & architecture specific, and requires
- * some more work to get it to fit into our separate processor and
- * architecture structure.
- */
-
-static unsigned long phys_screen_end;
-int page_nr;
-
-#define setup_processor_functions()
-
-/*
- * This routine needs more work to make it dynamically release/allocate mem!
- */
-unsigned long map_screen_mem(unsigned long log_start, unsigned long kmem, int update)
-{
- static int updated = 0;
- unsigned long address = SCREEN_START, i;
- pgd_t *pg_dir;
- pmd_t *pm_dir;
- pte_t *pt_entry;
-
- if (updated)
- return 0;
- updated = update;
-
- pg_dir = swapper_pg_dir + (SCREEN1_BASE >> PGDIR_SHIFT);
- pm_dir = pmd_offset(pg_dir, SCREEN1_BASE);
- pt_entry = pte_offset(pm_dir, SCREEN1_BASE);
-
- for (i = SCREEN1_BASE; i < SCREEN1_END; i += PAGE_SIZE) {
- if (i >= log_start) {
- *pt_entry = mk_pte(address, __pgprot(_PAGE_PRESENT));
- address += PAGE_SIZE;
- } else
- *pt_entry = mk_pte(0, __pgprot(0));
- pt_entry++;
- }
- phys_screen_end = address;
- if (update)
- flush_tlb_all ();
- return kmem;
-}
-
-static inline unsigned long setup_pagetables(unsigned long start_mem, unsigned long end_mem)
-{
- unsigned long address;
- unsigned int spi;
-
- page_nr = MAP_NR(end_mem);
-
- /* Allocate zero page */
- address = PAGE_OFFSET + 480*1024;
- for (spi = 0; spi < 32768 >> PAGE_SHIFT; spi++) {
- pgd_val(swapper_pg_dir[spi]) = pte_val(mk_pte(address, PAGE_READONLY));
- address += PAGE_SIZE;
- }
-
- while (spi < (PAGE_OFFSET >> PGDIR_SHIFT))
- pgd_val(swapper_pg_dir[spi++]) = 0;
-
- map_screen_mem (SCREEN1_END - 480*1024, 0, 0);
- return start_mem;
-}
-
-static inline void mark_usable_memory_areas(unsigned long *start_mem, unsigned long end_mem)
-{
- unsigned long smem = PAGE_ALIGN(*start_mem);
-
- while (smem < end_mem) {
- clear_bit(PG_reserved, &mem_map[MAP_NR(smem)].flags);
- smem += PAGE_SIZE;
- }
-
- for (smem = phys_screen_end; smem < SCREEN2_END; smem += PAGE_SIZE)
- clear_bit(PG_reserved, &mem_map[MAP_NR(smem)].flags);
-}
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/proc-armo/mm-init.h linux/include/asm-arm/proc-armo/mm-init.h
--- v2.2.7/linux/include/asm-arm/proc-armo/mm-init.h Fri May 8 23:14:54 1998
+++ linux/include/asm-arm/proc-armo/mm-init.h Sat May 8 11:06:57 1999
@@ -8,8 +8,8 @@
X * some more work to get it to fit into our separate processor and
X * architecture structure.
X */
-extern unsigned long phys_screen_end;
-extern unsigned long map_screen_mem(unsigned long log_start, unsigned long kmem, int update);
+#include <asm/arch/memory.h>
+
X int page_nr;
X
X #define setup_processor_functions()
@@ -20,10 +20,11 @@
X set_pmd (pmd_offset (swapper_pg_dir + index, 0), mk_pmd (ptep));
X }
X
-static inline unsigned long setup_pagetables(unsigned long start_mem, unsigned long end_mem)
+static inline unsigned long
+setup_pagetables(unsigned long start_mem, unsigned long end_mem)
X {
X unsigned int i;
- union {unsigned long l; pte_t *pte; } u;
+ union { unsigned long l; pte_t *pte; } u;
X
X page_nr = MAP_NR(end_mem);
X
@@ -37,14 +38,11 @@
X for (i = 1; i < PTRS_PER_PGD; i++)
X pgd_val(swapper_pg_dir[i]) = 0;
X
- /* now map screen mem in */
- phys_screen_end = SCREEN2_END;
- map_screen_mem (SCREEN1_END - 480*1024, 0, 0);
-
X return start_mem;
X }
X
-static inline void mark_usable_memory_areas(unsigned long *start_mem, unsigned long end_mem)
+static inline void
+mark_usable_memory_areas(unsigned long *start_mem, unsigned long end_mem)
X {
X unsigned long smem;
X
@@ -54,7 +52,4 @@
X clear_bit(PG_reserved, &mem_map[MAP_NR(smem)].flags);
X smem += PAGE_SIZE;
X }
-
- for (smem = phys_screen_end; smem < SCREEN2_END; smem += PAGE_SIZE)
- clear_bit(PG_reserved, &mem_map[MAP_NR(smem)].flags);
X }
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/proc-armo/page.h linux/include/asm-arm/proc-armo/page.h
--- v2.2.7/linux/include/asm-arm/proc-armo/page.h Fri May 8 23:14:54 1998
+++ linux/include/asm-arm/proc-armo/page.h Sat May 8 11:06:57 1999
@@ -68,7 +68,6 @@
X #define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK)
X
X /* This handles the memory map.. */
-#define PAGE_OFFSET 0x02000000
X #define MAP_NR(addr) (((unsigned long)(addr) - PAGE_OFFSET) >> PAGE_SHIFT)
X
X #endif /* __KERNEL__ */
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/proc-armo/pgtable-flat.h linux/include/asm-arm/proc-armo/pgtable-flat.h
--- v2.2.7/linux/include/asm-arm/proc-armo/pgtable-flat.h Tue Jan 20 16:39:42 1998
+++ linux/include/asm-arm/proc-armo/pgtable-flat.h Wed Dec 31 16:00:00 1969
@@ -1,307 +0,0 @@
-/*
- * linux/include/asm-arm/proc-armo/pgtable.h
- *
- * Copyright (C) 1995, 1996 Russell King
- */
-#ifndef __ASM_PROC_PGTABLE_H
-#define __ASM_PROC_PGTABLE_H
-
-#include <asm/arch/mmu.h>
-
-#define LIBRARY_TEXT_START 0x0c000000
-
-/*
- * Cache flushing...
- */
-#define flush_cache_all() do { } while (0)
-#define flush_cache_mm(mm) do { } while (0)
-#define flush_cache_range(mm,start,end) do { } while (0)
-#define flush_cache_page(vma,vmaddr) do { } while (0)
-#define flush_page_to_ram(page) do { } while (0)
-
-/*
- * TLB flushing:
- *
- * - flush_tlb() flushes the current mm struct TLBs
- * - flush_tlb_all() flushes all processes TLBs
- * - flush_tlb_mm(mm) flushes the specified mm context TLB's
- * - flush_tlb_page(vma, vmaddr) flushes one page
- * - flush_tlb_range(mm, start, end) flushes a range of pages
- */
-
-#define flush_tlb() flush_tlb_mm(current->mm)
-
-extern __inline__ void flush_tlb_all(void)
-{
- struct task_struct *p;
-
- p = &init_task;
- do {
- processor.u.armv2._update_map(p);
- p = p->next_task;
- } while (p != &init_task);
-
- processor.u.armv2._remap_memc (current);
-}
-
-extern __inline__ void flush_tlb_mm(struct mm_struct *mm)
-{
- struct task_struct *p;
-
- p = &init_task;
- do {
- if (p->mm == mm)
- processor.u.armv2._update_map(p);
- p = p->next_task;
- } while (p != &init_task);
-
- if (current->mm == mm)
- processor.u.armv2._remap_memc (current);
-}
-
-#define flush_tlb_range(mm, start, end) flush_tlb_mm(mm)
-#define flush_tlb_page(vma, vmaddr) flush_tlb_mm(vma->vm_mm)
-
-#define __flush_entry_to_ram(entry)
-
-/* Certain architectures need to do special things when pte's
- * within a page table are directly modified. Thus, the following
- * hook is made available.
- */
-#define set_pte(pteptr, pteval) ((*(pteptr)) = (pteval))
-
-/* PMD_SHIFT determines the size of the area a second-level page table can map */
-#define PMD_SHIFT PAGE_SHIFT
-#define PMD_SIZE (1UL << PMD_SHIFT)
-#define PMD_MASK (~(PMD_SIZE-1))
-
-/* PGDIR_SHIFT determines what a third-level page table entry can map */
-#define PGDIR_SHIFT PAGE_SHIFT
-#define PGDIR_SIZE (1UL << PGDIR_SHIFT)
-#define PGDIR_MASK (~(PGDIR_SIZE-1))
-
-/*
- * entries per page directory level: the arm3 is one-level, so
- * we don't really have any PMD or PTE directory physically.
- */
-#define PTRS_PER_PTE 1
-#define PTRS_PER_PMD 1
-#define PTRS_PER_PGD 1024
-
-/* Just any arbitrary offset to the start of the vmalloc VM area: the
- * current 8MB value just means that there will be a 8MB "hole" after the
- * physical memory until the kernel virtual memory starts. That means that
- * any out-of-bounds memory accesses will hopefully be caught.
- * The vmalloc() routines leaves a hole of 4kB between each vmalloced
- * area for the same reason. ;)
- */
-#define VMALLOC_START 0x01a00000
-#define VMALLOC_VMADDR(x) ((unsigned long)(x))
-
-#define _PAGE_PRESENT 0x001
-#define _PAGE_RW 0x002
-#define _PAGE_USER 0x004
-#define _PAGE_PCD 0x010
-#define _PAGE_ACCESSED 0x020
-#define _PAGE_DIRTY 0x040
-
-#define _PAGE_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_DIRTY)
-#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY)
-
-#define PAGE_NONE __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED)
-#define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED)
-#define PAGE_COPY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
-#define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
-#define PAGE_KERNEL __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED)
-
-/*
- * The arm can't do page protection for execute, and considers that the same are read.
- * Also, write permissions imply read permissions. This is the closest we can get..
- */
-#define __P000 PAGE_NONE
-#define __P001 PAGE_READONLY
-#define __P010 PAGE_COPY
-#define __P011 PAGE_COPY
-#define __P100 PAGE_READONLY
-#define __P101 PAGE_READONLY
-#define __P110 PAGE_COPY
-#define __P111 PAGE_COPY
-
-#define __S000 PAGE_NONE
-#define __S001 PAGE_READONLY
-#define __S010 PAGE_SHARED
-#define __S011 PAGE_SHARED
-#define __S100 PAGE_READONLY
-#define __S101 PAGE_READONLY
-#define __S110 PAGE_SHARED
-#define __S111 PAGE_SHARED
-
-#undef TEST_VERIFY_AREA
-
-/*
- * BAD_PAGE is used for a bogus page.
- *
- * ZERO_PAGE is a global shared page that is always zero: used
- * for zero-mapped memory areas etc..
- */
-extern pte_t __bad_page(void);
-extern unsigned long *empty_zero_page;
-
-#define BAD_PAGE __bad_page()
-#define ZERO_PAGE ((unsigned long) empty_zero_page)
-
-/* number of bits that fit into a memory pointer */
-#define BYTES_PER_PTR (sizeof(unsigned long))
-#define BITS_PER_PTR (8*BYTES_PER_PTR)
-
-/* to align the pointer to a pointer address */
-#define PTR_MASK (~(sizeof(void*)-1))
-
-/* sizeof(void*)==1<<SIZEOF_PTR_LOG2 */
-#define SIZEOF_PTR_LOG2 2
-
-/* to find an entry in a page-table */
-#define PAGE_PTR(address) \
-((unsigned long)(address)>>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK)
-
-/* to set the page-dir */
-#define SET_PAGE_DIR(tsk,pgdir) \
-do { \
- tsk->tss.memmap = (unsigned long)pgdir; \
- processor.u.armv2._update_map(tsk); \
- if ((tsk) == current) \
- processor.u.armv2._remap_memc (current); \
-} while (0)
-
-extern unsigned long physical_start;
-extern unsigned long physical_end;
-
-extern inline int pte_none(pte_t pte) { return !pte_val(pte); }
-extern inline int pte_present(pte_t pte) { return pte_val(pte) & _PAGE_PRESENT; }
-extern inline void pte_clear(pte_t *ptep) { pte_val(*ptep) = 0; }
-
-extern inline int pmd_none(pmd_t pmd) { return 0; }
-extern inline int pmd_bad(pmd_t pmd) { return 0; }
-extern inline int pmd_present(pmd_t pmd) { return 1; }
-extern inline void pmd_clear(pmd_t * pmdp) { }
-
-/*
- * The "pgd_xxx()" functions here are trivial for a folded two-level
- * setup: the pgd is never bad, and a pmd always exists (as it's folded
- * into the pgd entry)
- */
-extern inline int pgd_none(pgd_t pgd) { return 0; }
-extern inline int pgd_bad(pgd_t pgd) { return 0; }
-extern inline int pgd_present(pgd_t pgd) { return 1; }
-extern inline void pgd_clear(pgd_t * pgdp) { }
-
-/*
- * The following only work if pte_present() is true.
- * Undefined behaviour if not..
- */
-extern inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_USER; }
-extern inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_RW; }
-extern inline int pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_USER; }
-extern inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
-extern inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
-#define pte_cacheable(pte) 1
-
-extern inline pte_t pte_nocache(pte_t pte) { return pte; }
-extern inline pte_t pte_wrprotect(pte_t pte) { pte_val(pte) &= ~_PAGE_RW; return pte; }
-extern inline pte_t pte_rdprotect(pte_t pte) { pte_val(pte) &= ~_PAGE_USER; return pte; }
-extern inline pte_t pte_exprotect(pte_t pte) { pte_val(pte) &= ~_PAGE_USER; return pte; }
-extern inline pte_t pte_mkclean(pte_t pte) { pte_val(pte) &= ~_PAGE_DIRTY; return pte; }
-extern inline pte_t pte_mkold(pte_t pte) { pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
-extern inline pte_t pte_mkwrite(pte_t pte) { pte_val(pte) |= _PAGE_RW; return pte; }
-extern inline pte_t pte_mkread(pte_t pte) { pte_val(pte) |= _PAGE_USER; return pte; }
-extern inline pte_t pte_mkexec(pte_t pte) { pte_val(pte) |= _PAGE_USER; return pte; }
-extern inline pte_t pte_mkdirty(pte_t pte) { pte_val(pte) |= _PAGE_DIRTY; return pte; }
-extern inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) |= _PAGE_ACCESSED; return pte; }
-
-/*
- * Conversion functions: convert a page and protection to a page entry,
- * and a page entry and page directory to the page they refer to.
- */
-extern inline pte_t mk_pte(unsigned long page, pgprot_t pgprot)
-{ pte_t pte; pte_val(pte) = virt_to_phys(page) | pgprot_val(pgprot); return pte; }
-
-extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
-{ pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot); return pte; }
-
-extern inline unsigned long pte_page(pte_t pte)
-{ return phys_to_virt(pte_val(pte) & PAGE_MASK); }
-
-extern inline unsigned long pmd_page(pmd_t pmd)
-{ return phys_to_virt(pmd_val(pmd) & PAGE_MASK); }
-
-/* to find an entry in a page-table-directory */
-extern inline pgd_t * pgd_offset(struct mm_struct * mm, unsigned long address)
-{
- return mm->pgd + (address >> PGDIR_SHIFT);
-}
-
-/* Find an entry in the second-level page table.. */
-#define pmd_offset(dir, address) ((pmd_t *)(dir))
-
-/* Find an entry in the third-level page table.. */
-#define pte_offset(dir, address) ((pte_t *)(dir))
-
-/*
- * Allocate and free page tables. The xxx_kernel() versions are
- * used to allocate a kernel page table - this turns on ASN bits
- * if any.
- */
-extern inline void pte_free_kernel(pte_t * pte)
-{
- pte_val(*pte) = 0;
-}
-
-extern inline pte_t * pte_alloc_kernel(pmd_t *pmd, unsigned long address)
-{
- return (pte_t *) pmd;
-}
-
-/*
- * allocating and freeing a pmd is trivial: the 1-entry pmd is
- * inside the pgd, so has no extra memory associated with it.
- */
-#define pmd_free_kernel(pmdp)
-#define pmd_alloc_kernel(pgd,address) ((pmd_t *)(pgd))
-
-#define pte_free(ptep)
-#define pte_alloc(pmd,address) ((pte_t *)(pmd))
-
-/*
- * allocating and freeing a pmd is trivial: the 1-entry pmd is
- * inside the pgd, so has no extra memory associated with it.
- */
-#define pmd_free(pmd)
-#define pmd_alloc(pgd,address) ((pmd_t *)(pgd))
-
-extern inline void pgd_free(pgd_t * pgd)
-{
- extern void kfree(void *);
- kfree((void *)pgd);
-}
-
-extern inline pgd_t * pgd_alloc(void)
-{
- pgd_t *pgd;
- extern void *kmalloc(unsigned int, int);
-
- pgd = (pgd_t *) kmalloc(PTRS_PER_PGD * BYTES_PER_PTR, GFP_KERNEL);
- if (pgd)
- memset(pgd, 0, PTRS_PER_PGD * BYTES_PER_PTR);
- return pgd;
-}
-
-extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
-
-#define update_mmu_cache(vma,address,pte) processor.u.armv2._update_mmu_cache(vma,address,pte)
-
-#define SWP_TYPE(entry) (((entry) >> 1) & 0x7f)
-#define SWP_OFFSET(entry) ((entry) >> 8)
-#define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << 8))
-
-#endif /* __ASM_PROC_PAGE_H */
-
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/proc-armo/pgtable.h linux/include/asm-arm/proc-armo/pgtable.h
--- v2.2.7/linux/include/asm-arm/proc-armo/pgtable.h Fri Jan 8 22:36:22 1999
+++ linux/include/asm-arm/proc-armo/pgtable.h Sat May 8 11:06:57 1999
@@ -7,9 +7,9 @@
X #ifndef __ASM_PROC_PGTABLE_H
X #define __ASM_PROC_PGTABLE_H
X
-#include <asm/arch/mmu.h>
+#include <linux/config.h>
X #include <linux/slab.h>
-#include <asm/arch/processor.h> /* For TASK_SIZE */
+#include <asm/arch/memory.h> /* For TASK_SIZE */
X
X #define LIBRARY_TEXT_START 0x0c000000
X
@@ -280,13 +280,17 @@
X return __phys_to_virt(pte_val(pte) & PAGE_MASK);
X }
X
-extern __inline__ pmd_t mk_pmd (pte_t *ptep)
+extern __inline__ pmd_t mk_pmd(pte_t *ptep)
X {
X pmd_t pmd;
X pmd_val(pmd) = __virt_to_phys((unsigned long)ptep) | _PAGE_TABLE;
X return pmd;
X }
X
+/* these are aliases for the above function */
+#define mk_user_pmd(ptep) mk_pmd(ptep)
+#define mk_kernel_pmd(ptep) mk_pmd(ptep)
+
X #define set_pmd(pmdp,pmd) ((*(pmdp)) = (pmd))
X
X extern __inline__ unsigned long pmd_page(pmd_t pmd)
@@ -319,6 +323,7 @@
X */
X
X #ifndef __SMP__
+#ifndef CONFIG_NO_PGT_CACHE
X extern struct pgtable_cache_struct {
X unsigned long *pgd_cache;
X unsigned long *pte_cache;
@@ -329,13 +334,16 @@
X #define pte_quicklist (quicklists.pte_cache)
X #define pgd_quicklist (quicklists.pgd_cache)
X #define pgtable_cache_size (quicklists.pgtable_cache_sz)
+#endif
X
X #else
X #error Pgtable caches have to be per-CPU, so that no locking is needed.
X #endif
X
X extern pgd_t *get_pgd_slow(void);
+extern void free_table(void *table);
X
+#ifndef CONFIG_NO_PGT_CACHE
X extern __inline__ pgd_t *get_pgd_fast(void)
X {
X unsigned long *ret;
@@ -355,14 +363,17 @@
X pgd_quicklist = (unsigned long *) pgd;
X pgtable_cache_size++;
X }
+#endif
X
+/* keep this as an inline so we get type checking */
X extern __inline__ void free_pgd_slow(pgd_t *pgd)
X {
- kfree(pgd);
+ free_table((void *)pgd);
X }
X
X extern pte_t *get_pte_slow(pmd_t *pmd, unsigned long address_preadjusted);
X
+#ifndef CONFIG_NO_PGT_CACHE
X extern __inline__ pte_t *get_pte_fast(void)
X {
X unsigned long *ret;
@@ -381,10 +392,12 @@
X pte_quicklist = (unsigned long *) pte;
X pgtable_cache_size++;
X }
+#endif
X
+/* keep this as an inline so we get type checking */
X extern __inline__ void free_pte_slow(pte_t *pte)
X {
- kfree(pte);
+ free_table((void *)pte);
X }
X
X /* We don't use pmd cache, so this is a dummy routine */
@@ -404,6 +417,26 @@
X extern void __bad_pmd(pmd_t *pmd);
X extern void __bad_pmd_kernel(pmd_t *pmd);
X
+#ifdef CONFIG_NO_PGT_CACHE
+#define pte_free_kernel(pte) free_pte_slow(pte)
+#define pte_free(pte) free_pte_slow(pte)
+#define pgd_free(pgd) free_pgd_slow(pgd)
+#define pgd_alloc() get_pgd_slow()
+
+extern __inline__ pte_t *pte_alloc(pmd_t * pmd, unsigned long address)
+{
+ address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
+
+ if (pmd_none (*pmd)) {
+ return get_pte_slow(pmd, address);
+ }
+ if (pmd_bad (*pmd)) {
+ __bad_pmd(pmd);
+ return NULL;
+ }
+ return (pte_t *) pmd_page(*pmd) + address;
+}
+#else
X #define pte_free_kernel(pte) free_pte_fast(pte)
X #define pte_free(pte) free_pte_fast(pte)
X #define pgd_free(pgd) free_pgd_fast(pgd)
@@ -427,6 +460,7 @@
X }
X return (pte_t *) pmd_page(*pmd) + address;
X }
+#endif
X
X /*
X * allocating and freeing a pmd is trivial: the 1-entry pmd is
@@ -448,7 +482,6 @@
X extern __inline__ void set_pgdir(unsigned long address, pgd_t entry)
X {
X struct task_struct * p;
- pgd_t *pgd;
X
X read_lock(&tasklist_lock);
X for_each_task(p) {
@@ -457,8 +490,14 @@
X *pgd_offset(p->mm,address) = entry;
X }
X read_unlock(&tasklist_lock);
- for (pgd = (pgd_t *)pgd_quicklist; pgd; pgd = (pgd_t *)*(unsigned long *)pgd)
- pgd[address >> PGDIR_SHIFT] = entry;
+#ifndef CONFIG_NO_PGT_CACHE
+ {
+ pgd_t *pgd;
+ for (pgd = (pgd_t *)pgd_quicklist; pgd;
+ pgd = (pgd_t *)*(unsigned long *)pgd)
+ pgd[address >> PGDIR_SHIFT] = entry;
+ }
+#endif
X }
X
X extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/proc-armo/processor.h linux/include/asm-arm/proc-armo/processor.h
--- v2.2.7/linux/include/asm-arm/proc-armo/processor.h Tue Dec 22 14:16:58 1998
+++ linux/include/asm-arm/proc-armo/processor.h Sat May 8 11:06:57 1999
@@ -14,8 +14,6 @@
X #ifndef __ASM_PROC_PROCESSOR_H
X #define __ASM_PROC_PROCESSOR_H
X
-#ifdef __KERNEL__
-
X #include <asm/assembler.h>
X #include <linux/string.h>
X
@@ -32,6 +30,8 @@
X unsigned long pc;
X };
X
+#define INIT_CSS (struct context_save_struct){ 0, 0, 0, 0, 0, 0, 0, SVC26_MODE }
+
X typedef struct {
X void (*put_byte)(void); /* Special calling convention */
X void (*get_byte)(void); /* Special calling convention */
@@ -50,50 +50,13 @@
X
X #define EXTRA_THREAD_STRUCT \
X uaccess_t *uaccess; /* User access functions*/ \
- struct context_save_struct *save; \
- unsigned long memmap; \
X unsigned long memcmap[256];
X
X #define EXTRA_THREAD_STRUCT_INIT \
- &uaccess_kernel, \
- 0, \
- (unsigned long) swapper_pg_dir, \
+ ,&uaccess_kernel, \
X { 0, }
X
-DECLARE_THREAD_STRUCT;
-
-/*
- * Return saved PC of a blocked thread.
- */
-extern __inline__ unsigned long thread_saved_pc (struct thread_struct *t)
-{
- if (t->save)
- return t->save->pc & ~PCMASK;
- else
- return 0;
-}
-
-extern __inline__ unsigned long get_css_fp (struct thread_struct *t)
-{
- if (t->save)
- return t->save->fp;
- else


- return 0;
-}
-

-asmlinkage void ret_from_sys_call(void) __asm__("ret_from_sys_call");
-
-extern __inline__ void copy_thread_css (struct context_save_struct *save)
-{
- save->r4 =
- save->r5 =
- save->r6 =
- save->r7 =
- save->r8 =
- save->r9 =
- save->fp = 0;
- save->pc = ((unsigned long)ret_from_sys_call) | SVC26_MODE;
-}
+#define SWAPPER_PG_DIR ((unsigned long)swapper_pg_dir)
X
X #define start_thread(regs,pc,sp) \
X ({ \
@@ -105,18 +68,16 @@
X regs->ARM_r2 = stack[2]; /* r2 (envp) */ \
X regs->ARM_r1 = stack[1]; /* r1 (argv) */ \
X regs->ARM_r0 = stack[0]; /* r0 (argc) */ \
- flush_tlb_mm(current->mm); \
X })
X
X /* Allocation and freeing of basic task resources. */
X /*
X * NOTE! The task struct and the stack go together
X */
-#define alloc_task_struct() \
- ((struct task_struct *) __get_free_pages(GFP_KERNEL,1))
-#define free_task_struct(p) free_pages((unsigned long)(p),1)
-
+extern unsigned long get_page_8k(int priority);
+extern void free_page_8k(unsigned long page);
X
-#endif
+#define ll_alloc_task_struct() ((struct task_struct *)get_page_8k(GFP_KERNEL))
+#define ll_free_task_struct(p) free_page_8k((unsigned long)(p))
X
X #endif
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/proc-armo/ptrace.h linux/include/asm-arm/proc-armo/ptrace.h
--- v2.2.7/linux/include/asm-arm/proc-armo/ptrace.h Wed Sep 9 14:51:12 1998
+++ linux/include/asm-arm/proc-armo/ptrace.h Sat May 8 11:06:57 1999
@@ -68,8 +68,13 @@
X /* Are the current registers suitable for user mode?
X * (used to maintain security in signal handlers)
X */
-#define valid_user_regs(regs) \
- (user_mode(regs) && ((regs)->ARM_sp & 3) == 0)
+static inline int valid_user_regs(struct pt_regs *regs)
+{
+ if (!user_mode(regs) || regs->ARM_pc & (F_BIT | I_BIT))
+ return 1;


+
+ return 0;
+}

X
X #endif
X
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/proc-armo/semaphore.h linux/include/asm-arm/proc-armo/semaphore.h
--- v2.2.7/linux/include/asm-arm/proc-armo/semaphore.h Tue Jan 20 16:39:42 1998
+++ linux/include/asm-arm/proc-armo/semaphore.h Sat May 8 11:06:57 1999
@@ -13,17 +13,19 @@
X __asm__ __volatile__ ("
X @ atomic down operation
X mov r0, pc
- orr r1, r0, #0x08000000
+ orr lr, r0, #0x08000000
X and r0, r0, #0x0c000003
- teqp r1, #0
- ldr r1, [%0]
- subs r1, r1, #1
- str r1, [%0]
- mov r1, pc, lsr #28
- teqp r0, r1, lsl #28
+ teqp lr, #0
+ ldr lr, [%0]
+ subs lr, lr, #1
+ str lr, [%0]
+ mov lr, pc, lsr #28
+ teqp r0, lr, lsl #28
X movmi r0, %0
- blmi " SYMBOL_NAME_STR(__down)
- : : "r" (sem) : "r0", "r1", "r2", "r3", "ip", "lr", "cc");
+ blmi " SYMBOL_NAME_STR(__down_failed)
+ :
+ : "r" (sem)
+ : "r0", "lr", "cc");
X }
X
X /*
@@ -36,22 +38,47 @@
X __asm__ __volatile__ ("
X @ atomic down operation
X mov r0, pc
- orr r1, r0, #0x08000000
+ orr lr, r0, #0x08000000
X and r0, r0, #0x0c000003
- teqp r1, #0
- ldr r1, [%1]
- subs r1, r1, #1
- str r1, [%1]
- mov r1, pc, lsr #28
+ teqp lr, #0
+ ldr lr, [%1]
+ subs lr, lr, #1
+ str lr, [%1]
+ mov lr, pc, lsr #28
X orrmi r0, r0, #0x80000000 @ set N
- teqp r0, r1, lsl #28
+ teqp r0, lr, lsl #28
X movmi r0, %1
X movpl r0, #0
- blmi " SYMBOL_NAME_STR(__down_interruptible) "
+ blmi " SYMBOL_NAME_STR(__down_interruptible_failed) "
X mov %0, r0"
X : "=r" (result)
X : "r" (sem)
- : "r0", "r1", "r2", "r3", "ip", "lr", "cc");
+ : "r0", "lr", "cc");


+ return result;
+}
+

+extern inline int down_trylock(struct semaphore * sem)
+{
+ int result;
+ __asm__ __volatile__ ("
+ @ atomic down operation
+ mov r0, pc
+ orr lr, r0, #0x08000000
+ and r0, r0, #0x0c000003
+ teqp lr, #0
+ ldr lr, [%1]
+ subs lr, lr, #1
+ str lr, [%1]
+ mov lr, pc, lsr #28
+ orrmi r0, r0, #0x80000000 @ set N
+ teqp r0, lr, lsl #28
+ movmi r0, %1
+ movpl r0, #0
+ blmi " SYMBOL_NAME_STR(__down_trylock_failed) "
+ mov %0, r0"
+ : "=r" (result)
+ : "r" (sem)
+ : "r0", "lr", "cc");
X return result;
X }
X
@@ -66,18 +93,20 @@
X __asm__ __volatile__ ("
X @ atomic up operation
X mov r0, pc
- orr r1, r0, #0x08000000
+ orr lr, r0, #0x08000000
X and r0, r0, #0x0c000003
- teqp r1, #0
- ldr r1, [%0]
- adds r1, r1, #1
- str r1, [%0]
- mov r1, pc, lsr #28
+ teqp lr, #0
+ ldr lr, [%0]
+ adds lr, lr, #1
+ str lr, [%0]
+ mov lr, pc, lsr #28
X orrls r0, r0, #0x80000000 @ set N
- teqp r0, r1, lsl #28
+ teqp r0, lr, lsl #28
X movmi r0, %0
- blmi " SYMBOL_NAME_STR(__up)
- : : "r" (sem) : "r0", "r1", "r2", "r3", "ip", "lr", "cc");
+ blmi " SYMBOL_NAME_STR(__up_wakeup)
+ :
+ : "r" (sem)
+ : "r0", "lr", "cc");
X }
X
X #endif
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/proc-armv/io.h linux/include/asm-arm/proc-armv/io.h
--- v2.2.7/linux/include/asm-arm/proc-armv/io.h Tue Dec 22 14:16:58 1998
+++ linux/include/asm-arm/proc-armv/io.h Sat May 8 11:06:58 1999
@@ -22,17 +22,14 @@
X
X #include <asm/proc-fns.h>
X
-extern inline void dma_cache_inv(unsigned long start, unsigned long size)
-{
- processor.u.armv3v4._cache_purge_area(start, start + size);
-}
+#define dma_cache_inv(start, size) \
+ do { processor.u.armv3v4._cache_purge_area((unsigned long)(start), \
+ ((unsigned long)(start)+(size))); } while (0)
X
-extern inline void dma_cache_wback(unsigned long start, unsigned long size)
-{
- processor.u.armv3v4._cache_wback_area(start, start + size);
-}
+#define dma_cache_wback(start, size) \
+ do { processor.u.armv3v4._cache_wback_area((unsigned long)(start), \
+ ((unsigned long)(start)+(size))); } while (0)
X
-extern inline void dma_cache_wback_inv(unsigned long start, unsigned long size)
-{
- processor.u.armv3v4._flush_cache_area(start, start + size, 0);
-}
+#define dma_cache_wback_inv(start, size) \
+ do { processor.u.armv3v4._flush_cache_area((unsigned long)(start), \
+ ((unsigned long)(start)+(size)), 0); } while (0)
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/proc-armv/mm-init.h linux/include/asm-arm/proc-armv/mm-init.h
--- v2.2.7/linux/include/asm-arm/proc-armv/mm-init.h Fri Jan 8 22:36:23 1999
+++ linux/include/asm-arm/proc-armv/mm-init.h Sat May 8 11:06:58 1999
@@ -37,7 +37,7 @@
X */
X #include <asm/pgtable.h>
X
-#define PTE_SIZE (PTRS_PER_PTE * 4)
+#define PTE_SIZE (PTRS_PER_PTE * BYTES_PER_PTR)
X
X extern unsigned long setup_io_pagetables(unsigned long start_mem);
X
@@ -79,7 +79,7 @@
X alloc_init_page(unsigned long *mem, unsigned long virt, unsigned long phys, int domain, int prot)
X {
X pgd_t *pgdp;
- pmd_t *pmdp, pmd;
+ pmd_t *pmdp;
X pte_t *ptep;
X
X pgdp = pgd_offset_k(virt);
@@ -92,46 +92,41 @@
X
X ptep = (pte_t *)memory;
X memzero(ptep, PTE_SIZE);
+ memory += PTE_SIZE;
X
- pmd_val(pmd) = __virt_to_phys(memory) | PMD_TYPE_TABLE | PMD_DOMAIN(domain);
- set_pmd(pmdp, pmd);
+ ptep = (pte_t *)memory;
+ memzero(ptep, PTE_SIZE);
+
+ set_pmd(pmdp, __mk_pmd(ptep, PMD_TYPE_TABLE | PMD_DOMAIN(domain)));
X
X *mem = memory + PTE_SIZE;
X }
X
X ptep = pte_offset(pmdp, virt);
X
- pte_val(*ptep) = phys | prot | PTE_TYPE_SMALL;
+ set_pte(ptep, mk_pte_phys(phys, __pgprot(prot)));
X }
X
X static inline unsigned long
X setup_pagetables(unsigned long start_mem, unsigned long end_mem)
X {
- unsigned long address;
+ unsigned long address = 0;
X
- /*
- * map in zero page
- */
- alloc_init_page(&start_mem, 0, __virt_to_phys(PAGE_OFFSET), DOMAIN_USER, PTE_CACHEABLE);
-
- /*
- * ensure no mappings in user space
- */
- for (address = PGDIR_SIZE; address < PAGE_OFFSET; address += PGDIR_SIZE)
- free_init_section(address);
-
- /*
- * map in physical ram & kernel
- */
- for (address = PAGE_OFFSET; address < end_mem; address += PGDIR_SIZE)
- alloc_init_section(&start_mem, address, __virt_to_phys(address), DOMAIN_KERNEL,
- PMD_SECT_CACHEABLE | PMD_SECT_BUFFERABLE | PMD_SECT_AP_WRITE);
+ do {
+ if (address >= PAGE_OFFSET && address < end_mem)
+ /*
+ * map in physical ram & kernel
+ */
+ alloc_init_section(&start_mem, address, __virt_to_phys(address), DOMAIN_KERNEL,
+ PMD_SECT_CACHEABLE | PMD_SECT_BUFFERABLE | PMD_SECT_AP_WRITE);
+ else
+ /*
+ * unmap everything else
+ */
+ free_init_section(address);
X
- /*
- * unmap everything else
- */
- for (address = end_mem; address; address += PGDIR_SIZE)
- free_init_section(address);
+ address += PGDIR_SIZE;
+ } while (address != 0);
X
X /*
X * An area to invalidate the cache
@@ -144,6 +139,12 @@
X */
X start_mem = setup_io_pagetables(start_mem);
X
+ /*
+ * map in zero page
+ */
+ alloc_init_page(&start_mem, 0, __virt_to_phys(PAGE_OFFSET),
+ DOMAIN_USER, L_PTE_CACHEABLE | L_PTE_YOUNG | L_PTE_PRESENT);
+
X flush_cache_all();
X
X return start_mem;
@@ -156,9 +157,21 @@
X
X *start_mem = smem = PAGE_ALIGN(*start_mem);
X
+ /*
+ * Mark all of memory from the end of kernel to end of memory
+ */
X while (smem < end_mem) {
- clear_bit(PG_reserved, &mem_map[MAP_NR(smem)].flags);
- smem += PAGE_SIZE;
+ clear_bit(PG_reserved, &mem_map[MAP_NR(smem)].flags);
+ smem += PAGE_SIZE;
+ }
+
+ /*
+ * Mark memory from page 1 to start of the swapper page directory
+ */
+ smem = PAGE_OFFSET + PAGE_SIZE;
+ while (smem < (unsigned long)&swapper_pg_dir) {
+ clear_bit(PG_reserved, &mem_map[MAP_NR(smem)].flags);
+ smem += PAGE_SIZE;
X }
X }
X
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/proc-armv/pgtable.h linux/include/asm-arm/proc-armv/pgtable.h
--- v2.2.7/linux/include/asm-arm/proc-armv/pgtable.h Wed Sep 9 14:51:12 1998
+++ linux/include/asm-arm/proc-armv/pgtable.h Sat May 8 11:06:58 1999
@@ -3,14 +3,15 @@
X *
X * Copyright (C) 1995, 1996, 1997 Russell King
X *
- * 12-01-1997 RMK Altered flushing routines to use function pointers
+ * 12-Jan-1997 RMK Altered flushing routines to use function pointers
X * now possible to combine ARM6, ARM7 and StrongARM versions.
+ * 17-Apr-1999 RMK Now pass an area size to clean_cache_area and
+ * flush_icache_area.
X */
X #ifndef __ASM_PROC_PGTABLE_H
X #define __ASM_PROC_PGTABLE_H
X
-#include <asm/arch/mmu.h>
-#include <asm/arch/processor.h> /* For TASK_SIZE */
+#include <asm/arch/memory.h> /* For TASK_SIZE */
X
X #define LIBRARY_TEXT_START 0x0c000000
X
@@ -41,8 +42,23 @@
X ((_vma)->vm_flags & VM_EXEC) ? 1 : 0); \
X } while (0)
X
+#define clean_cache_range(_start,_end) \
+ do { \
+ unsigned long _s, _sz; \
+ _s = (unsigned long)_start; \
+ _sz = (unsigned long)_end - _s; \
+ processor.u.armv3v4._clean_cache_area(_s, _sz); \
+ } while (0)
+
+#define clean_cache_area(_start,_size) \
+ do { \
+ unsigned long _s; \
+ _s = (unsigned long)_start; \
+ processor.u.armv3v4._clean_cache_area(_s, _size); \
+ } while (0)
+
X #define flush_icache_range(_start,_end) \
- processor.u.armv3v4._flush_icache_area((_start), (_end))
+ processor.u.armv3v4._flush_icache_area((_start), (_end) - (_start))
X
X /*
X * We don't have a MEMC chip...
@@ -60,12 +76,6 @@
X processor.u.armv3v4._flush_ram_page ((_page) & PAGE_MASK);
X
X /*
- * Make the page uncacheable (must flush page beforehand).
- */
-#define uncache_page(_page) \
- processor.u.armv3v4._flush_ram_page ((_page) & PAGE_MASK);
-
-/*
X * TLB flushing:
X *
X * - flush_tlb() flushes the current mm struct TLBs
@@ -106,22 +116,15 @@
X } while (0)
X
X /*
- * Since the page tables are in cached memory, we need to flush the dirty
- * data cached entries back before we flush the tlb... This is also useful
- * to flush out the SWI instruction for signal handlers...
+ * PMD_SHIFT determines the size of the area a second-level page table can map
X */
-#define __flush_entry_to_ram(entry) \
- processor.u.armv3v4._flush_cache_entry((unsigned long)(entry))
-
-#define __flush_pte_to_ram(entry) \
- processor.u.armv3v4._flush_cache_pte((unsigned long)(entry))
-
-/* PMD_SHIFT determines the size of the area a second-level page table can map */
X #define PMD_SHIFT 20
X #define PMD_SIZE (1UL << PMD_SHIFT)
X #define PMD_MASK (~(PMD_SIZE-1))
X
-/* PGDIR_SHIFT determines what a third-level page table entry can map */
+/*
+ * PGDIR_SHIFT determines what a third-level page table entry can map
+ */
X #define PGDIR_SHIFT 20
X #define PGDIR_SIZE (1UL << PGDIR_SHIFT)
X #define PGDIR_MASK (~(PGDIR_SIZE-1))
@@ -135,6 +138,7 @@
X #define PTRS_PER_PGD 4096
X #define USER_PTRS_PER_PGD (TASK_SIZE/PGDIR_SIZE)
X
+
X /* Just any arbitrary offset to the start of the vmalloc VM area: the
X * current 8MB value just means that there will be a 8MB "hole" after the
X * physical memory until the kernel virtual memory starts. That means that
@@ -147,87 +151,28 @@
X #define VMALLOC_VMADDR(x) ((unsigned long)(x))
X #define VMALLOC_END (PAGE_OFFSET + 0x10000000)
X
-/* PMD types (actually level 1 descriptor) */
-#define PMD_TYPE_MASK 0x0003
-#define PMD_TYPE_FAULT 0x0000
-#define PMD_TYPE_TABLE 0x0001
-#define PMD_TYPE_SECT 0x0002
-#define PMD_UPDATABLE 0x0010
-#define PMD_SECT_CACHEABLE 0x0008
-#define PMD_SECT_BUFFERABLE 0x0004
-#define PMD_SECT_AP_WRITE 0x0400
-#define PMD_SECT_AP_READ 0x0800
-#define PMD_DOMAIN(x) ((x) << 5)
-
-/* PTE types (actially level 2 descriptor) */
-#define PTE_TYPE_MASK 0x0003
-#define PTE_TYPE_FAULT 0x0000
-#define PTE_TYPE_LARGE 0x0001
-#define PTE_TYPE_SMALL 0x0002
-#define PTE_AP_READ 0x0aa0
-#define PTE_AP_WRITE 0x0550
-#define PTE_CACHEABLE 0x0008
-#define PTE_BUFFERABLE 0x0004
X
-/* Domains */
+/*
+ * Domains
+ */
X #define DOMAIN_USER 0
X #define DOMAIN_KERNEL 1
X #define DOMAIN_TABLE 1
X #define DOMAIN_IO 2
X
-#define _PAGE_CHG_MASK (0xfffff00c | PTE_TYPE_MASK)
X
-/*
- * We define the bits in the page tables as follows:
- * PTE_BUFFERABLE page is dirty
- * PTE_AP_WRITE page is writable
- * PTE_AP_READ page is a young (unsetting this causes faults for any access)
- * PTE_CACHEABLE page is readable
- *
- * A page will not be made writable without the dirty bit set.
- * It is not legal to have a writable non-dirty page though (it breaks).
- *
- * A readable page is marked as being cacheable.
- * Youngness is indicated by hardware read. If the page is old,
- * then we will fault and make the page young again.
- */
-#define _PTE_YOUNG PTE_AP_READ
-#define _PTE_DIRTY PTE_BUFFERABLE
-#define _PTE_READ PTE_CACHEABLE
-#define _PTE_WRITE PTE_AP_WRITE
-
-#define PAGE_NONE __pgprot(PTE_TYPE_SMALL | _PTE_YOUNG)
-#define PAGE_SHARED __pgprot(PTE_TYPE_SMALL | _PTE_YOUNG | _PTE_READ | _PTE_WRITE)
-#define PAGE_COPY __pgprot(PTE_TYPE_SMALL | _PTE_YOUNG | _PTE_READ)
-#define PAGE_READONLY __pgprot(PTE_TYPE_SMALL | _PTE_YOUNG | _PTE_READ)
-#define PAGE_KERNEL __pgprot(PTE_TYPE_SMALL | _PTE_READ | _PTE_DIRTY | _PTE_WRITE)
X
-#define _PAGE_USER_TABLE (PMD_TYPE_TABLE | PMD_DOMAIN(DOMAIN_USER))
-#define _PAGE_KERNEL_TABLE (PMD_TYPE_TABLE | PMD_DOMAIN(DOMAIN_KERNEL))
+#undef TEST_VERIFY_AREA
X
X /*
- * The arm can't do page protection for execute, and considers that the same are read.
- * Also, write permissions imply read permissions. This is the closest we can get..
+ * The sa110 doesn't have any external MMU info: the kernel page
+ * tables contain all the necessary information.
X */
-#define __P000 PAGE_NONE
-#define __P001 PAGE_READONLY
-#define __P010 PAGE_COPY
-#define __P011 PAGE_COPY
-#define __P100 PAGE_READONLY
-#define __P101 PAGE_READONLY
-#define __P110 PAGE_COPY
-#define __P111 PAGE_COPY
-
-#define __S000 PAGE_NONE
-#define __S001 PAGE_READONLY
-#define __S010 PAGE_SHARED
-#define __S011 PAGE_SHARED
-#define __S100 PAGE_READONLY
-#define __S101 PAGE_READONLY
-#define __S110 PAGE_SHARED
-#define __S111 PAGE_SHARED
+extern __inline__ void update_mmu_cache(struct vm_area_struct * vma,
+ unsigned long address, pte_t pte)
+{
+}
X
-#undef TEST_VERIFY_AREA
X
X /*
X * BAD_PAGETABLE is used when we need a bogus page-table, while
@@ -240,97 +185,40 @@
X extern pte_t * __bad_pagetable(void);
X extern unsigned long *empty_zero_page;
X
-#define BAD_PAGETABLE __bad_pagetable()
-#define BAD_PAGE __bad_page()
-#define ZERO_PAGE ((unsigned long) empty_zero_page)
+#define BAD_PAGETABLE __bad_pagetable()
+#define BAD_PAGE __bad_page()
+#define ZERO_PAGE ((unsigned long) empty_zero_page)
X
X /* number of bits that fit into a memory pointer */
-#define BYTES_PER_PTR (sizeof(unsigned long))
-#define BITS_PER_PTR (8*BYTES_PER_PTR)
+#define BYTES_PER_PTR (sizeof(unsigned long))
+#define BITS_PER_PTR (8*BYTES_PER_PTR)
X
X /* to align the pointer to a pointer address */
-#define PTR_MASK (~(sizeof(void*)-1))
+#define PTR_MASK (~(sizeof(void*)-1))
X
X /* sizeof(void*)==1<<SIZEOF_PTR_LOG2 */
-#define SIZEOF_PTR_LOG2 2
+#define SIZEOF_PTR_LOG2 2
X
X /* to find an entry in a page-table */
X #define PAGE_PTR(address) \
X ((unsigned long)(address)>>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK)
X
-/* to set the page-dir */
+/* to set the page-dir
+ * Note that we need to flush the cache and TLBs
+ * if we are affecting the current task.
+ */
X #define SET_PAGE_DIR(tsk,pgdir) \
X do { \
X tsk->tss.memmap = __virt_to_phys((unsigned long)pgdir); \
- if ((tsk) == current) \
+ if ((tsk) == current) { \
+ flush_cache_all(); \
X __asm__ __volatile__( \
X "mcr%? p15, 0, %0, c2, c0, 0\n" \
X : : "r" (tsk->tss.memmap)); \
+ flush_tlb_all(); \
+ } \
X } while (0)
X
-extern __inline__ int pte_none(pte_t pte)
-{
- return !pte_val(pte);
-}
-
-#define pte_clear(ptep) set_pte(ptep, __pte(0))
-
-extern __inline__ int pte_present(pte_t pte)
-{
-#if 0
- /* This is what it really does, the else
- part is just to make it easier for the compiler */
- switch (pte_val(pte) & PTE_TYPE_MASK) {
- case PTE_TYPE_LARGE:
- case PTE_TYPE_SMALL:
- return 1;
- default:
- return 0;
- }
-#else
- return ((pte_val(pte) + 1) & 2);
-#endif
-}
-
-extern __inline__ int pmd_none(pmd_t pmd)
-{
- return !pmd_val(pmd);
-}
-
-#define pmd_clear(pmdp) set_pmd(pmdp, __pmd(0))
-
-extern __inline__ int pmd_bad(pmd_t pmd)
-{
-#if 0
- /* This is what it really does, the else
- part is just to make it easier for the compiler */
- switch (pmd_val(pmd) & PMD_TYPE_MASK) {
- case PMD_TYPE_FAULT:
- case PMD_TYPE_TABLE:
- return 0;
- default:


- return 1;
- }
-#else

- return pmd_val(pmd) & 2;
-#endif
-}
-
-extern __inline__ int pmd_present(pmd_t pmd)
-{
-#if 0
- /* This is what it really does, the else
- part is just to make it easier for the compiler */
- switch (pmd_val(pmd) & PMD_TYPE_MASK) {
- case PMD_TYPE_TABLE:
- return 1;
- default:
- return 0;
- }
-#else
- return ((pmd_val(pmd) + 1) & 2);
-#endif
-}
X
X /*
X * The "pgd_xxx()" functions here are trivial for a folded two-level
@@ -342,231 +230,224 @@
X #define pgd_present(pgd) (1)
X #define pgd_clear(pgdp)
X
-/*
- * The following only work if pte_present() is true.
- * Undefined behaviour if not..
- */
-#define pte_read(pte) (1)
-#define pte_exec(pte) (1)
+/* to find an entry in a kernel page-table-directory */
+#define pgd_offset_k(address) pgd_offset(&init_mm, address)


SHAR_EOF
true || echo 'restore of patch-2.2.8 failed'
fi

echo 'End of part 28'
echo 'File patch-2.2.8 is continued in part 29'
echo 29 > _shar_seq_.tmp

Thomas...@ciw.uni-karlsruhe.de

unread,
May 12, 1999, 3:00:00 AM5/12/99
to
Archive-name: v2.2/patch-2.2.8/part29

#!/bin/sh
# this is part 29 of a 33 - part archive


# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.8 continued
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 29; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.8'
else
echo 'x - continuing with patch-2.2.8'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.8' &&

X
-extern __inline__ int pte_write(pte_t pte)
+/* to find an entry in a page-table-directory */
+extern __inline__ pgd_t * pgd_offset(struct mm_struct * mm, unsigned long address)
X {
- return pte_val(pte) & _PTE_WRITE;
+ return mm->pgd + (address >> PGDIR_SHIFT);
X }
X
-extern __inline__ int pte_dirty(pte_t pte)
-{
- return pte_val(pte) & _PTE_DIRTY;
-}
+extern unsigned long get_page_2k(int priority);
+extern void free_page_2k(unsigned long page);
X
-extern __inline__ int pte_young(pte_t pte)
-{
- return pte_val(pte) & _PTE_YOUNG;
-}
+/*
+ * Allocate and free page tables. The xxx_kernel() versions are
+ * used to allocate a kernel page table - this turns on ASN bits
+ * if any.
+ */
X
-extern __inline__ pte_t pte_wrprotect(pte_t pte)
-{
- pte_val(pte) &= ~_PTE_WRITE;
- return pte;
-}
+#ifndef __SMP__
+extern struct pgtable_cache_struct {
+ unsigned long *pgd_cache;
+ unsigned long *pte_cache;
+ unsigned long pgtable_cache_sz;
+} quicklists;
X
-extern __inline__ pte_t pte_nocache(pte_t pte)
-{
- pte_val(pte) &= ~PTE_CACHEABLE;
- return pte;
-}
+#define pgd_quicklist (quicklists.pgd_cache)
+#define pmd_quicklist ((unsigned long *)0)
+#define pte_quicklist (quicklists.pte_cache)
+#define pgtable_cache_size (quicklists.pgtable_cache_sz)
+#else
+#error Pgtable caches have to be per-CPU, so that no locking is needed.
+#endif
X
-extern __inline__ pte_t pte_mkclean(pte_t pte)
-{
- pte_val(pte) &= ~_PTE_DIRTY;
- return pte;
-}
+extern pgd_t *get_pgd_slow(void);
X
-extern __inline__ pte_t pte_mkold(pte_t pte)
+extern __inline__ pgd_t *get_pgd_fast(void)
X {
- pte_val(pte) &= ~_PTE_YOUNG;
- return pte;
+ unsigned long *ret;
+
+ if((ret = pgd_quicklist) != NULL) {
+ pgd_quicklist = (unsigned long *)(*ret);
+ ret[0] = ret[1];
+ clean_cache_area(ret, 4);
+ pgtable_cache_size--;
+ } else
+ ret = (unsigned long *)get_pgd_slow();
+ return (pgd_t *)ret;
X }
X
-extern __inline__ pte_t pte_mkwrite(pte_t pte)
+extern __inline__ void free_pgd_fast(pgd_t *pgd)
X {
- pte_val(pte) |= _PTE_WRITE;
- return pte;
+ *(unsigned long *)pgd = (unsigned long) pgd_quicklist;
+ pgd_quicklist = (unsigned long *) pgd;
+ pgtable_cache_size++;
X }
X
-extern __inline__ pte_t pte_mkdirty(pte_t pte)
+extern __inline__ void free_pgd_slow(pgd_t *pgd)
X {
- pte_val(pte) |= _PTE_DIRTY;
- return pte;
+ free_pages((unsigned long) pgd, 2);
X }
X
-extern __inline__ pte_t pte_mkyoung(pte_t pte)
+#define pgd_free(pgd) free_pgd_fast(pgd)
+#define pgd_alloc() get_pgd_fast()
+
+extern __inline__ void set_pgdir(unsigned long address, pgd_t entry)
X {
- pte_val(pte) |= _PTE_YOUNG;
- return pte;
+ struct task_struct * p;
+ pgd_t *pgd;
+
+ read_lock(&tasklist_lock);
+ for_each_task(p) {
+ if (!p->mm)
+ continue;
+ *pgd_offset(p->mm,address) = entry;
+ }
+ read_unlock(&tasklist_lock);
+ for (pgd = (pgd_t *)pgd_quicklist; pgd; pgd = (pgd_t *)*(unsigned long *)pgd)


+ pgd[address >> PGDIR_SHIFT] = entry;

X }
X
-/*
- * The following are unable to be implemented on this MMU
- */
-#if 0
-extern __inline__ pte_t pte_rdprotect(pte_t pte)
+extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
+
+/****************
+* PMD functions *
+****************/
+
+/* PMD types (actually level 1 descriptor) */
+#define PMD_TYPE_MASK 0x0003
+#define PMD_TYPE_FAULT 0x0000
+#define PMD_TYPE_TABLE 0x0001
+#define PMD_TYPE_SECT 0x0002
+#define PMD_UPDATABLE 0x0010
+#define PMD_SECT_CACHEABLE 0x0008
+#define PMD_SECT_BUFFERABLE 0x0004
+#define PMD_SECT_AP_WRITE 0x0400
+#define PMD_SECT_AP_READ 0x0800
+#define PMD_DOMAIN(x) ((x) << 5)
+
+#define _PAGE_USER_TABLE (PMD_TYPE_TABLE | PMD_DOMAIN(DOMAIN_USER))
+#define _PAGE_KERNEL_TABLE (PMD_TYPE_TABLE | PMD_DOMAIN(DOMAIN_KERNEL))
+
+#define pmd_none(pmd) (!pmd_val(pmd))
+#define pmd_clear(pmdp) set_pmd(pmdp, __pmd(0))
+#define pmd_bad(pmd) (pmd_val(pmd) & 2)
+#define mk_user_pmd(ptep) __mk_pmd(ptep, _PAGE_USER_TABLE)
+#define mk_kernel_pmd(ptep) __mk_pmd(ptep, _PAGE_KERNEL_TABLE)
+#define set_pmd(pmdp,pmd) processor.u.armv3v4._set_pmd(pmdp,pmd)
+
+/* Find an entry in the second-level page table.. */
+#define pmd_offset(dir, address) ((pmd_t *)(dir))
+
+extern __inline__ int pmd_present(pmd_t pmd)
X {
- pte_val(pte) &= ~(PTE_CACHEABLE|PTE_AP_READ);
- return pte;
+ return ((pmd_val(pmd) + 1) & 2);
X }
X
-extern __inline__ pte_t pte_exprotect(pte_t pte)
+/* We don't use pmd cache, so this is a dummy routine */
+extern __inline__ pmd_t *get_pmd_fast(void)
X {
- pte_val(pte) &= ~(PTE_CACHEABLE|PTE_AP_READ);
- return pte;
+ return (pmd_t *)0;
X }
X
-extern __inline__ pte_t pte_mkread(pte_t pte)
+extern __inline__ void free_pmd_fast(pmd_t *pmd)
X {
- pte_val(pte) |= PTE_CACHEABLE;
- return pte;
X }
X
-extern __inline__ pte_t pte_mkexec(pte_t pte)
+extern __inline__ void free_pmd_slow(pmd_t *pmd)
X {
- pte_val(pte) |= PTE_CACHEABLE;
- return pte;
X }
-#endif
+
+extern void __bad_pmd(pmd_t *pmd);
+extern void __bad_pmd_kernel(pmd_t *pmd);
X
X /*


- * Conversion functions: convert a page and protection to a page entry,
- * and a page entry and page directory to the page they refer to.

+ * allocating and freeing a pmd is trivial: the 1-entry pmd is
+ * inside the pgd, so has no extra memory associated with it.
X */
-extern __inline__ pte_t mk_pte(unsigned long page, pgprot_t pgprot)
+extern __inline__ void pmd_free(pmd_t *pmd)
X {
- pte_t pte;
- pte_val(pte) = __virt_to_phys(page) | pgprot_val(pgprot);
- return pte;
X }
X
-/* This takes a physical page address that is used by the remapping functions */
-extern __inline__ pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot)
+extern __inline__ pmd_t *pmd_alloc(pgd_t *pgd, unsigned long address)
X {
- pte_t pte;
- pte_val(pte) = physpage + pgprot_val(pgprot);
- return pte;
+ return (pmd_t *) pgd;
X }
X
-extern __inline__ pte_t pte_modify(pte_t pte, pgprot_t newprot)


-{
- pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot);

- return pte;
-}
+#define pmd_free_kernel pmd_free
+#define pmd_alloc_kernel pmd_alloc
X
-extern __inline__ void set_pte(pte_t *pteptr, pte_t pteval)
+extern __inline__ pmd_t __mk_pmd(pte_t *ptep, unsigned long prot)
X {
- *pteptr = pteval;
- __flush_pte_to_ram(pteptr);
-}
+ unsigned long pte_ptr = (unsigned long)ptep;
+ pmd_t pmd;
X
-extern __inline__ unsigned long pte_page(pte_t pte)
-{
- return __phys_to_virt(pte_val(pte) & PAGE_MASK);
-}
+ pte_ptr -= PTRS_PER_PTE * BYTES_PER_PTR;
X
-extern __inline__ pmd_t mk_user_pmd(pte_t *ptep)
-{
- pmd_t pmd;
- pmd_val(pmd) = __virt_to_phys((unsigned long)ptep) | _PAGE_USER_TABLE;
- return pmd;
-}
+ /*
+ * The pmd must be loaded with the physical
+ * address of the PTE table
+ */
+ pmd_val(pmd) = __virt_to_phys(pte_ptr) | prot;
X
-extern __inline__ pmd_t mk_kernel_pmd(pte_t *ptep)
-{
- pmd_t pmd;
- pmd_val(pmd) = __virt_to_phys((unsigned long)ptep) | _PAGE_KERNEL_TABLE;


X return pmd;
X }
X

-#if 1
-#define set_pmd(pmdp,pmd) processor.u.armv3v4._set_pmd(pmdp,pmd)
-#else
-extern __inline__ void set_pmd(pmd_t *pmdp, pmd_t pmd)
-{
- *pmdp = pmd;
- __flush_pte_to_ram(pmdp);
-}
-#endif
-


X extern __inline__ unsigned long pmd_page(pmd_t pmd)

X {
- return __phys_to_virt(pmd_val(pmd) & 0xfffffc00);
-}
-
-/* to find an entry in a kernel page-table-directory */
-#define pgd_offset_k(address) pgd_offset(&init_mm, address)
+ unsigned long ptr;
X

-/* to find an entry in a page-table-directory */

-extern __inline__ pgd_t * pgd_offset(struct mm_struct * mm, unsigned long address)


-{
- return mm->pgd + (address >> PGDIR_SHIFT);
-}

+ ptr = pmd_val(pmd) & ~(PTRS_PER_PTE * BYTES_PER_PTR - 1);
X

-/* Find an entry in the second-level page table.. */
-#define pmd_offset(dir, address) ((pmd_t *)(dir))

+ ptr += PTRS_PER_PTE * BYTES_PER_PTR;
X

-/* Find an entry in the third-level page table.. */

-extern __inline__ pte_t * pte_offset(pmd_t * dir, unsigned long address)
-{
- return (pte_t *) pmd_page(*dir) + ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1));
+ return __phys_to_virt(ptr);
X }
X
-extern unsigned long get_small_page(int priority);
-extern void free_small_page(unsigned long page);
X

-/*
- * Allocate and free page tables. The xxx_kernel() versions are
- * used to allocate a kernel page table - this turns on ASN bits
- * if any.
- */
-

-#ifndef __SMP__
-extern struct pgtable_cache_struct {
- unsigned long *pgd_cache;
- unsigned long *pte_cache;
- unsigned long pgtable_cache_sz;
-} quicklists;
+/****************
+* PTE functions *
+****************/
X
-#define pgd_quicklist (quicklists.pgd_cache)
-#define pmd_quicklist ((unsigned long *)0)
-#define pte_quicklist (quicklists.pte_cache)
-#define pgtable_cache_size (quicklists.pgtable_cache_sz)
-#else
-#error Pgtable caches have to be per-CPU, so that no locking is needed.
-#endif
+/* PTE types (actially level 2 descriptor) */
+#define PTE_TYPE_MASK 0x0003
+#define PTE_TYPE_FAULT 0x0000
+#define PTE_TYPE_LARGE 0x0001
+#define PTE_TYPE_SMALL 0x0002
+#define PTE_AP_READ 0x0aa0
+#define PTE_AP_WRITE 0x0550
+#define PTE_CACHEABLE 0x0008
+#define PTE_BUFFERABLE 0x0004
X
-extern pgd_t *get_pgd_slow(void);
+#define pte_none(pte) (!pte_val(pte))
+#define pte_clear(ptep) set_pte(ptep, __pte(0))
X
-extern __inline__ pgd_t *get_pgd_fast(void)
+/*
+ * Conversion functions: convert a page and protection to a page entry,
+ * and a page entry and page directory to the page they refer to.
+ */
+extern __inline__ pte_t mk_pte(unsigned long page, pgprot_t pgprot)
X {
- unsigned long *ret;
-
- if((ret = pgd_quicklist) != NULL) {
- pgd_quicklist = (unsigned long *)(*ret);
- ret[0] = ret[1];
- pgtable_cache_size--;
- } else
- ret = (unsigned long *)get_pgd_slow();
- return (pgd_t *)ret;
+ pte_t pte;
+ pte_val(pte) = __virt_to_phys(page) | pgprot_val(pgprot);
+ return pte;
X }
X
-extern __inline__ void free_pgd_fast(pgd_t *pgd)
+/* This takes a physical page address that is used by the remapping functions */
+extern __inline__ pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot)
X {
- *(unsigned long *)pgd = (unsigned long) pgd_quicklist;
- pgd_quicklist = (unsigned long *) pgd;
- pgtable_cache_size++;
+ pte_t pte;
+ pte_val(pte) = physpage + pgprot_val(pgprot);
+ return pte;
X }
X
-extern __inline__ void free_pgd_slow(pgd_t *pgd)
+#define set_pte(ptep, pte) processor.u.armv3v4._set_pte(ptep,pte)
+
+extern __inline__ unsigned long pte_page(pte_t pte)
X {
- free_pages((unsigned long) pgd, 2);
+ return __phys_to_virt(pte_val(pte) & PAGE_MASK);
X }
X

X extern pte_t *get_pte_slow(pmd_t *pmd, unsigned long address_preadjusted);

@@ -579,6 +460,7 @@
X if((ret = (unsigned long *)pte_quicklist) != NULL) {
X pte_quicklist = (unsigned long *)(*ret);
X ret[0] = ret[1];
+ clean_cache_area(ret, 4);
X pgtable_cache_size--;
X }
X return (pte_t *)ret;
@@ -593,31 +475,124 @@
X

X extern __inline__ void free_pte_slow(pte_t *pte)
X {

- free_small_page((unsigned long)pte);
+ free_page_2k((unsigned long)(pte - PTRS_PER_PTE));
X }
X
-/* We don't use pmd cache, so this is a dummy routine */
-extern __inline__ pmd_t *get_pmd_fast(void)
-{
- return (pmd_t *)0;
-}
+#define pte_free_kernel(pte) free_pte_fast(pte)
+#define pte_free(pte) free_pte_fast(pte)
X
-extern __inline__ void free_pmd_fast(pmd_t *pmd)
+/*###############################################################################
+ * New PageTableEntry stuff...
+ */
+/* We now keep two sets of ptes - the physical and the linux version.
+ * This gives us many advantages, and allows us greater flexibility.
+ *
+ * The Linux pte's contain:
+ * bit meaning
+ * 0 page present
+ * 1 young
+ * 2 bufferable - matches physical pte
+ * 3 cacheable - matches physical pte
+ * 4 user
+ * 5 write
+ * 6 execute
+ * 7 dirty
+ * 8-11 unused
+ * 12-31 virtual page address
+ *
+ * These are stored at the pte pointer; the physical PTE is at -1024bytes
+ */
+#define L_PTE_PRESENT (1 << 0)
+#define L_PTE_YOUNG (1 << 1)
+#define L_PTE_BUFFERABLE (1 << 2)
+#define L_PTE_CACHEABLE (1 << 3)
+#define L_PTE_USER (1 << 4)
+#define L_PTE_WRITE (1 << 5)
+#define L_PTE_EXEC (1 << 6)
+#define L_PTE_DIRTY (1 << 7)
+
+/*
+ * The following macros handle the cache and bufferable bits...
+ */
+#define _L_PTE_DEFAULT L_PTE_PRESENT | L_PTE_YOUNG
+#define _L_PTE_READ L_PTE_USER | L_PTE_CACHEABLE
+#define _L_PTE_EXEC _L_PTE_READ | L_PTE_EXEC
+
+#define PAGE_NONE __pgprot(_L_PTE_DEFAULT)
+#define PAGE_COPY __pgprot(_L_PTE_DEFAULT | _L_PTE_READ | L_PTE_BUFFERABLE)
+#define PAGE_SHARED __pgprot(_L_PTE_DEFAULT | _L_PTE_READ | L_PTE_BUFFERABLE | L_PTE_WRITE)
+#define PAGE_READONLY __pgprot(_L_PTE_DEFAULT | _L_PTE_READ)
+#define PAGE_KERNEL __pgprot(_L_PTE_DEFAULT | L_PTE_CACHEABLE | L_PTE_BUFFERABLE | L_PTE_DIRTY | L_PTE_WRITE)
+
+#define _PAGE_CHG_MASK (PAGE_MASK | L_PTE_DIRTY | L_PTE_YOUNG)
+
+/*
+ * The table below defines the page protection levels that we insert into our
+ * Linux page table version. These get translated into the best that the
+ * architecture can perform. Note that on most ARM hardware:
+ * 1) We cannot do execute protection
+ * 2) If we could do execute protection, then read is implied
+ * 3) write implies read permissions
+ */
+#define __P000 PAGE_NONE
+#define __P001 PAGE_READONLY
+#define __P010 PAGE_COPY
+#define __P011 PAGE_COPY
+#define __P100 PAGE_READONLY
+#define __P101 PAGE_READONLY
+#define __P110 PAGE_COPY
+#define __P111 PAGE_COPY
+
+#define __S000 PAGE_NONE
+#define __S001 PAGE_READONLY
+#define __S010 PAGE_SHARED
+#define __S011 PAGE_SHARED
+#define __S100 PAGE_READONLY
+#define __S101 PAGE_READONLY
+#define __S110 PAGE_SHARED
+#define __S111 PAGE_SHARED
+
+
+
+#define pte_present(pte) (pte_val(pte) & L_PTE_PRESENT)
+
+/*
+ * The following only work if pte_present() is true.
+ * Undefined behaviour if not..
+ */
+#define pte_read(pte) (pte_val(pte) & L_PTE_USER)
+#define pte_write(pte) (pte_val(pte) & L_PTE_WRITE)
+#define pte_exec(pte) (pte_val(pte) & L_PTE_EXEC)
+#define pte_dirty(pte) (pte_val(pte) & L_PTE_DIRTY)
+#define pte_young(pte) (pte_val(pte) & L_PTE_YOUNG)
+
+#define PTE_BIT_FUNC(fn,op) \
+extern inline pte_t fn##(pte_t pte) { pte_val(pte) op##; return pte; }
+
+//PTE_BIT_FUNC(pte_rdprotect, &= ~L_PTE_USER);
+PTE_BIT_FUNC(pte_wrprotect, &= ~L_PTE_WRITE);
+PTE_BIT_FUNC(pte_exprotect, &= ~L_PTE_EXEC);
+PTE_BIT_FUNC(pte_mkclean, &= ~L_PTE_DIRTY);
+PTE_BIT_FUNC(pte_mkold, &= ~L_PTE_YOUNG);
+//PTE_BIT_FUNC(pte_mkread, |= L_PTE_USER);
+PTE_BIT_FUNC(pte_mkwrite, |= L_PTE_WRITE);
+PTE_BIT_FUNC(pte_mkexec, |= L_PTE_EXEC);
+PTE_BIT_FUNC(pte_mkdirty, |= L_PTE_DIRTY);
+PTE_BIT_FUNC(pte_mkyoung, |= L_PTE_YOUNG);
+PTE_BIT_FUNC(pte_nocache, &= ~L_PTE_CACHEABLE);
+
+extern __inline__ pte_t pte_modify(pte_t pte, pgprot_t newprot)
X {
+ pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot);
+ return pte;
X }
X
-extern __inline__ void free_pmd_slow(pmd_t *pmd)
+/* Find an entry in the third-level page table.. */
+extern __inline__ pte_t * pte_offset(pmd_t * dir, unsigned long address)
X {
+ return (pte_t *) pmd_page(*dir) + ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1));
X }
X
-extern void __bad_pmd(pmd_t *pmd);
-extern void __bad_pmd_kernel(pmd_t *pmd);
-
-#define pte_free_kernel(pte) free_pte_fast(pte)
-#define pte_free(pte) free_pte_fast(pte)
-#define pgd_free(pgd) free_pgd_fast(pgd)
-#define pgd_alloc() get_pgd_fast()
-
X extern __inline__ pte_t * pte_alloc_kernel(pmd_t *pmd, unsigned long address)
X {
X address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
@@ -653,49 +628,6 @@
X return NULL;


X }
X return (pte_t *) pmd_page(*pmd) + address;

-}
-
-/*
- * allocating and freeing a pmd is trivial: the 1-entry pmd is
- * inside the pgd, so has no extra memory associated with it.
- */

-extern __inline__ void pmd_free(pmd_t *pmd)
-{
-}
-
-extern __inline__ pmd_t *pmd_alloc(pgd_t *pgd, unsigned long address)
-{
- return (pmd_t *) pgd;
-}
-
-#define pmd_free_kernel pmd_free
-#define pmd_alloc_kernel pmd_alloc
-
-extern __inline__ void set_pgdir(unsigned long address, pgd_t entry)
-{
- struct task_struct * p;
- pgd_t *pgd;
-
- read_lock(&tasklist_lock);
- for_each_task(p) {
- if (!p->mm)
- continue;
- *pgd_offset(p->mm,address) = entry;
- }
- read_unlock(&tasklist_lock);


- for (pgd = (pgd_t *)pgd_quicklist; pgd; pgd = (pgd_t *)*(unsigned long *)pgd)
- pgd[address >> PGDIR_SHIFT] = entry;

-}
-
-extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
-

-/*
- * The sa110 doesn't have any external MMU info: the kernel page
- * tables contain all the necessary information.
- */
-extern __inline__ void update_mmu_cache(struct vm_area_struct * vma,
- unsigned long address, pte_t pte)
-{
X }
X
X #define SWP_TYPE(entry) (((entry) >> 2) & 0x7f)
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/proc-armv/processor.h linux/include/asm-arm/proc-armv/processor.h
--- v2.2.7/linux/include/asm-arm/proc-armv/processor.h Tue Dec 22 14:16:58 1998
+++ linux/include/asm-arm/proc-armv/processor.h Sat May 8 11:06:58 1999
@@ -12,8 +12,6 @@


X #ifndef __ASM_PROC_PROCESSOR_H
X #define __ASM_PROC_PROCESSOR_H
X
-#ifdef __KERNEL__
-

X #define KERNEL_STACK_SIZE PAGE_SIZE
X
X struct context_save_struct {
@@ -28,56 +26,18 @@


X unsigned long pc;
X };
X

-#define EXTRA_THREAD_STRUCT \


- struct context_save_struct *save; \
- unsigned long memmap;

+#define INIT_CSS (struct context_save_struct){ SVC_MODE, 0, 0, 0, 0, 0, 0, 0, 0 }
X
-#define EXTRA_THREAD_STRUCT_INIT \
- 0, \
- ((unsigned long) swapper_pg_dir) - PAGE_OFFSET
-


-DECLARE_THREAD_STRUCT;
-
-/*
- * Return saved PC of a blocked thread.
- */
-extern __inline__ unsigned long thread_saved_pc (struct thread_struct *t)
-{
- if (t->save)

- return t->save->pc;


- else
- return 0;
-}
-
-extern __inline__ unsigned long get_css_fp (struct thread_struct *t)
-{
- if (t->save)
- return t->save->fp;
- else
- return 0;
-}
-

-asmlinkage void ret_from_sys_call(void) __asm__ ("ret_from_sys_call");


-
-extern __inline__ void copy_thread_css (struct context_save_struct *save)
-{

- save->cpsr = SVC_MODE;


- save->r4 =
- save->r5 =
- save->r6 =
- save->r7 =
- save->r8 =
- save->r9 =
- save->fp = 0;

- save->pc = (unsigned long) ret_from_sys_call;
-}
+#define EXTRA_THREAD_STRUCT
+#define EXTRA_THREAD_STRUCT_INIT
+#define SWAPPER_PG_DIR (((unsigned long)swapper_pg_dir) - PAGE_OFFSET)


X
X #define start_thread(regs,pc,sp) \
X ({ \

X unsigned long *stack = (unsigned long *)sp; \
X set_fs(USER_DS); \
X memzero(regs->uregs, sizeof(regs->uregs)); \
- if (current->personality == PER_LINUX_32BIT) \
+ if (current->personality & ADDR_LIMIT_32BIT) \
X regs->ARM_cpsr = USR_MODE; \
X else \
X regs->ARM_cpsr = USR26_MODE; \
@@ -92,10 +52,7 @@


X /*
X * NOTE! The task struct and the stack go together
X */
-#define alloc_task_struct() \
- ((struct task_struct *) __get_free_pages(GFP_KERNEL,1))
-#define free_task_struct(p) free_pages((unsigned long)(p),1)
-

-#endif
+#define ll_alloc_task_struct() ((struct task_struct *) __get_free_pages(GFP_KERNEL,1))
+#define ll_free_task_struct(p) free_pages((unsigned long)(p),1)
X
X #endif
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/proc-armv/ptrace.h linux/include/asm-arm/proc-armv/ptrace.h
--- v2.2.7/linux/include/asm-arm/proc-armv/ptrace.h Wed Sep 9 14:51:12 1998
+++ linux/include/asm-arm/proc-armv/ptrace.h Sat May 8 11:06:58 1999
@@ -52,9 +52,14 @@
X #define CC_Z_BIT (1 << 30)
X #define CC_N_BIT (1 << 31)
X
+#if 0 /* GCC/egcs should be able to optimise this, IMHO */
X #define user_mode(regs) \
X ((((regs)->ARM_cpsr & MODE_MASK) == USR_MODE) || \
X (((regs)->ARM_cpsr & MODE_MASK) == USR26_MODE))
+#else
+#define user_mode(regs) \
+ (((regs)->ARM_cpsr & 0xf) == 0)
+#endif
X
X #define processor_mode(regs) \
X ((regs)->ARM_cpsr & MODE_MASK)
@@ -74,8 +79,19 @@


X /* Are the current registers suitable for user mode?
X * (used to maintain security in signal handlers)
X */
-#define valid_user_regs(regs) \
- (user_mode(regs) && ((regs)->ARM_sp & 3) == 0)
+static inline int valid_user_regs(struct pt_regs *regs)
+{

+ if ((regs->ARM_cpsr & 0xf) == 0 ||
+ (regs->ARM_cpsr & (F_BIT|I_BIT)))
+ return 1;
+
+ /*
+ * Force CPSR to something logical...
+ */
+ regs->ARM_cpsr &= (CC_V_BIT|CC_C_BIT|CC_Z_BIT|CC_N_BIT|0x10);


+
+ return 0;
+}
X
X #endif
X

diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/proc-armv/semaphore.h linux/include/asm-arm/proc-armv/semaphore.h
--- v2.2.7/linux/include/asm-arm/proc-armv/semaphore.h Fri Jan 8 22:36:23 1999
+++ linux/include/asm-arm/proc-armv/semaphore.h Sat May 8 11:06:58 1999
@@ -60,6 +60,32 @@
X return temp;
X }
X

+extern inline int down_trylock(struct semaphore *sem)
+{

+ unsigned int cpsr, temp;
+
+ __asm__ __volatile__ ("
+ @ atomic down try lock operation
+ mrs %0, cpsr
+ orr %1, %0, #128 @ disable IRQs
+ bic %0, %0, #0x80000000 @ clear N
+ msr cpsr, %1
+ ldr %1, [%2]
+ subs %1, %1, #1
+ orrmi %0, %0, #0x80000000 @ set N
+ str %1, [%2]
+ msr cpsr, %0
+ movmi r0, %2


+ movpl r0, #0
+ blmi " SYMBOL_NAME_STR(__down_trylock_failed) "

+ mov %1, r0"
+ : "=&r" (cpsr), "=&r" (temp)


+ : "r" (sem)
+ : "r0", "lr", "cc");

+
+ return temp;
+}
+
X /*
X * Note! This is subtle. We jump to wake people up only if
X * the semaphore was negative (== somebody was waiting on it).
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/proc-armv/uaccess.h linux/include/asm-arm/proc-armv/uaccess.h
--- v2.2.7/linux/include/asm-arm/proc-armv/uaccess.h Fri Jan 8 22:36:23 1999
+++ linux/include/asm-arm/proc-armv/uaccess.h Sat May 8 11:06:58 1999
@@ -133,6 +133,7 @@
X " .section .fixup,\"ax\"\n" \
X " .align 2\n" \
X "3: mvn %0, %3\n" \
+ " mov %1, #0\n" \
X " b 2b\n" \
X " .previous\n" \
X " .section __ex_table,\"a\"\n" \
@@ -153,6 +154,7 @@
X " .section .fixup,\"ax\"\n" \
X " .align 2\n" \
X "4: mvn %0, %5\n" \
+ " mov %1, #0\n" \
X " b 3b\n" \
X " .previous\n" \
X " .section __ex_table,\"a\"\n" \
@@ -173,6 +175,7 @@
X " .section .fixup,\"ax\"\n" \
X " .align 2\n" \
X "3: mvn %0, %3\n" \
+ " mov %1, #0\n" \
X " b 2b\n" \
X " .previous\n" \
X " .section __ex_table,\"a\"\n" \
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/proc-fns.h linux/include/asm-arm/proc-fns.h
--- v2.2.7/linux/include/asm-arm/proc-fns.h Wed Sep 9 14:51:12 1998
+++ linux/include/asm-arm/proc-fns.h Sat May 8 11:07:16 1999
@@ -9,6 +9,10 @@
X #include <asm/page.h>
X
X #ifdef __KERNEL__
+
+/* forward-decare task_struct */
+struct task_struct;
+
X /*
X * Don't change this structure
X */
@@ -18,7 +22,7 @@
X *
X * flush caches for task switch
X */
- void (*_switch_to)(void *prev, void *next);
+ struct task_struct *(*_switch_to)(struct task_struct *prev, struct task_struct *next);
X /*
X * get data abort address/flags
X */
@@ -54,10 +58,10 @@
X */
X void (*_flush_cache_entry)(unsigned long address);
X /*
- * flush a virtual address used for a page table
- * note D-cache only!
+ * clean a virtual address range from the
+ * D-cache without flushing the cache.
X */
- void (*_flush_cache_pte)(unsigned long address);
+ void (*_clean_cache_area)(unsigned long start, unsigned long size);
X /*
X * flush a page to RAM
X */
@@ -76,13 +80,17 @@
X */
X void (*_set_pmd)(pmd_t *pmdp, pmd_t pmd);
X /*
+ * Set a PTE
+ */
+ void (*_set_pte)(pte_t *ptep, pte_t pte);
+ /*
X * Special stuff for a reset
X */
X unsigned long (*reset)(void);
X /*
X * flush an icached page
X */
- void (*_flush_icache_area)(unsigned long start, unsigned long end);
+ void (*_flush_icache_area)(unsigned long start, unsigned long size);
X /*
X * write back dirty cached data
X */
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/processor.h linux/include/asm-arm/processor.h
--- v2.2.7/linux/include/asm-arm/processor.h Tue Jan 19 11:32:53 1999
+++ linux/include/asm-arm/processor.h Sat May 8 11:06:58 1999
@@ -7,12 +7,14 @@
X #ifndef __ASM_ARM_PROCESSOR_H
X #define __ASM_ARM_PROCESSOR_H
X
+#define FP_SIZE 35
+
X struct fp_hard_struct {
- unsigned int save[140/4]; /* as yet undefined */
+ unsigned int save[FP_SIZE]; /* as yet undefined */
X };
X
X struct fp_soft_struct {
- unsigned int save[140/4]; /* undefined information */
+ unsigned int save[FP_SIZE]; /* undefined information */
X };
X
X union fp_state {
@@ -22,28 +24,59 @@
X
X typedef unsigned long mm_segment_t; /* domain register */
X
-#define NR_DEBUGS 5
+#ifdef __KERNEL__
X
-#define DECLARE_THREAD_STRUCT \
-struct thread_struct { \
- unsigned long address; /* Address of fault */ \
- unsigned long trap_no; /* Trap number */ \
- unsigned long error_code; /* Error code of trap */ \
- union fp_state fpstate; /* FPE save state */ \
- unsigned long debug[NR_DEBUGS]; /* Debug/ptrace */ \
- EXTRA_THREAD_STRUCT \
-}
+#include <asm/assembler.h>
+
+#define NR_DEBUGS 5
X
X #include <asm/arch/processor.h>
X #include <asm/proc/processor.h>
X
-#define INIT_TSS { \
- 0, \
- 0, \
- 0, \
- { { { 0, }, }, }, \
- { 0, }, \
- EXTRA_THREAD_STRUCT_INIT \
+struct thread_struct {
+ unsigned long address; /* Address of fault */
+ unsigned long trap_no; /* Trap number */
+ unsigned long error_code; /* Error code of trap */
+ union fp_state fpstate; /* FPE save state */
+ unsigned long debug[NR_DEBUGS]; /* Debug/ptrace */
+ struct context_save_struct *save; /* context save */
+ unsigned long memmap; /* page tables */
+ EXTRA_THREAD_STRUCT
+};
+
+#define INIT_MMAP \
+{ &init_mm, 0, 0, NULL, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, 1, NULL, NULL }
+
+#define INIT_TSS { \
+ 0, \
+ 0, \
+ 0, \
+ { { { 0, }, }, }, \
+ { 0, }, \
+ (struct context_save_struct *)0, \
+ SWAPPER_PG_DIR \
+ EXTRA_THREAD_STRUCT_INIT \
+}
+
+/*
+ * Return saved PC of a blocked thread.
+ */
+extern __inline__ unsigned long thread_saved_pc(struct thread_struct *t)
+{
+ return t->save ? t->save->pc & ~PCMASK : 0;
+}
+
+extern __inline__ unsigned long get_css_fp(struct thread_struct *t)
+{
+ return t->save ? t->save->fp : 0;
+}
+
+asmlinkage void ret_from_sys_call(void) __asm__("ret_from_sys_call");
+
+extern __inline__ void init_thread_css(struct context_save_struct *save)
+{
+ *save = INIT_CSS;
+ save->pc |= (unsigned long)ret_from_sys_call;
X }
X
X /* Forward declaration, a strange C thing */
@@ -57,7 +90,12 @@
X #define release_segments(mm) do { } while (0)
X #define forget_segments() do { } while (0)
X
+extern struct task_struct *alloc_task_struct(void);
+extern void free_task_struct(struct task_struct *);
+
X #define init_task (init_task_union.task)
X #define init_stack (init_task_union.stack)
+
+#endif
X
X #endif /* __ASM_ARM_PROCESSOR_H */
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/semaphore-helper.h linux/include/asm-arm/semaphore-helper.h
--- v2.2.7/linux/include/asm-arm/semaphore-helper.h Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/semaphore-helper.h Sat May 8 11:06:58 1999
@@ -0,0 +1,84 @@
+#ifndef ASMARM_SEMAPHORE_HELPER_H
+#define ASMARM_SEMAPHORE_HELPER_H
+
+/*
+ * These two _must_ execute atomically wrt each other.
+ */
+static inline void wake_one_more(struct semaphore * sem)
+{


+ unsigned long flags;
+

+ spin_lock_irqsave(&semaphore_wake_lock, flags);
+ if (atomic_read(&sem->count) <= 0)
+ sem->waking++;
+ spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+}
+
+static inline int waking_non_zero(struct semaphore *sem)


+{
+ unsigned long flags;

+ int ret = 0;
+

+ spin_lock_irqsave(&semaphore_wake_lock, flags);
+ if (sem->waking > 0) {
+ sem->waking--;
+ ret = 1;
+ }
+ spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+ return ret;
+}
+
+/*
+ * waking non zero interruptible
+ * 1 got the lock
+ * 0 go to sleep
+ * -EINTR interrupted
+ *
+ * We must undo the sem->count down_interruptible() increment while we are
+ * protected by the spinlock in order to make this atomic_inc() with the
+ * atomic_read() in wake_one_more(), otherwise we can race. -arca
+ */
+static inline int waking_non_zero_interruptible(struct semaphore *sem,
+ struct task_struct *tsk)


+{
+ unsigned long flags;

+ int ret = 0;
+

+ spin_lock_irqsave(&semaphore_wake_lock, flags);
+ if (sem->waking > 0) {
+ sem->waking--;
+ ret = 1;
+ } else if (signal_pending(tsk)) {
+ atomic_inc(&sem->count);
+ ret = -EINTR;
+ }
+ spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+ return ret;
+}
+
+/*
+ * waking_non_zero_try_lock:
+ * 1 failed to lock
+ * 0 got the lock
+ *
+ * We must undo the sem->count down_interruptible() increment while we are
+ * protected by the spinlock in order to make this atomic_inc() with the
+ * atomic_read() in wake_one_more(), otherwise we can race. -arca
+ */
+static inline int waking_non_zero_trylock(struct semaphore *sem)


+{
+ unsigned long flags;

+ int ret = 1;
+
+ spin_lock_irqsave(&semaphore_wake_lock, flags);
+ if (sem->waking <= 0)
+ atomic_inc(&sem->count);
+ else {
+ sem->waking--;
+ ret = 0;
+ }
+ spin_unlock_irqrestore(&semaphore_wake_lock, flags);


+ return ret;
+}
+

+#endif
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/semaphore.h linux/include/asm-arm/semaphore.h
--- v2.2.7/linux/include/asm-arm/semaphore.h Tue Jan 19 11:32:53 1999
+++ linux/include/asm-arm/semaphore.h Sat May 8 11:06:58 1999
@@ -19,49 +19,15 @@
X
X asmlinkage void __down_failed (void /* special register calling convention */);
X asmlinkage int __down_interruptible_failed (void /* special register calling convention */);
+asmlinkage int __down_failed_trylock(void /* params in registers */);
X asmlinkage void __up_wakeup (void /* special register calling convention */);
X
X extern void __down(struct semaphore * sem);
X extern int __down_interruptible(struct semaphore * sem);
+extern int __down_trylock(struct semaphore * sem);
X extern void __up(struct semaphore * sem);
X
X #define sema_init(sem, val) atomic_set(&((sem)->count), (val))
-
-/*
- * These two _must_ execute atomically wrt each other.
- *
- * This is trivially done with load_locked/store_cond,
- * but on the x86 we need an external synchronizer.
- * Currently this is just the global interrupt lock,
- * bah. Go for a smaller spinlock some day.
- *
- * (On the other hand this shouldn't be in any critical
- * path, so..)
- */
-static inline void wake_one_more(struct semaphore * sem)


-{
- unsigned long flags;

-
- save_flags(flags);
- cli();
- sem->waking++;
- restore_flags(flags);
-}
-
-static inline int waking_non_zero(struct semaphore *sem, struct task_struct *tsk)


-{
- unsigned long flags;

- int ret = 0;
-
- save_flags(flags);
- cli();
- if (sem->waking > 0) {
- sem->waking--;
- ret = 1;
- }
- restore_flags(flags);
- return ret;
-}
X
X #include <asm/proc/semaphore.h>
X
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/system.h linux/include/asm-arm/system.h
--- v2.2.7/linux/include/asm-arm/system.h Tue Dec 22 14:16:58 1998
+++ linux/include/asm-arm/system.h Sat May 8 11:07:16 1999
@@ -1,10 +1,26 @@
X #ifndef __ASM_ARM_SYSTEM_H
X #define __ASM_ARM_SYSTEM_H
X
+#include <linux/kernel.h>
+
+#ifdef __KERNEL__
+
X #include <linux/config.h>
X
+#define __ebsa285_data __attribute__((__section__(".data.ebsa285")))
+#define __netwinder_data __attribute__((__section__(".data.netwinder")))
+
+#ifdef CONFIG_TEXT_SECTIONS
+#define __ebsa285_text __attribute__((__section__(".text.ebsa285")))
+#define __netwinder_text __attribute__((__section__(".text.netwinder")))
+#else
+#define __ebsa285_text
+#define __netwinder_text
+#endif
+
X /* The type of machine we're running on */
-extern unsigned int machine_type;
+extern unsigned int __machine_arch_type;
+
X #define MACH_TYPE_EBSA110 0
X #define MACH_TYPE_RISCPC 1
X #define MACH_TYPE_NEXUSPCI 3
@@ -12,31 +28,101 @@
X #define MACH_TYPE_NETWINDER 5
X #define MACH_TYPE_CATS 6
X #define MACH_TYPE_TBOX 7
+#define MACH_TYPE_CO285 8
+#define MACH_TYPE_CLPS7110 9
+#define MACH_TYPE_ARCHIMEDES 10
+#define MACH_TYPE_A5K 11
+
+/*
+ * Sort out a definition for machine_arch_type
+ * The rules basically are:
+ * 1. If one architecture is selected, then all machine_is_xxx()
+ * are constant.
+ * 2. If two or more architectures are selected, then the selected
+ * machine_is_xxx() are variable, and the unselected machine_is_xxx()
+ * are constant zero.
+ */
+#ifdef CONFIG_ARCH_EBSA110
+# ifdef machine_arch_type
+# undef machine_arch_type
+# define machine_arch_type __machine_arch_type
+# else
+# define machine_arch_type MACH_TYPE_EBSA110
+# endif
+# define machine_is_ebsa110() (machine_arch_type == MACH_TYPE_EBSA110)
+#else
+# define machine_is_ebsa110() (0)
+#endif
+
+#ifdef CONFIG_ARCH_RPC
+# ifdef machine_arch_type
+# undef machine_arch_type
+# define machine_arch_type __machine_arch_type
+# else
+# define machine_arch_type MACH_TYPE_RISCPC
+# endif
+# define machine_is_riscpc() (machine_arch_type == MACH_TYPE_RISCPC)
+#else
+# define machine_is_riscpc() (0)
+#endif
X
X #ifdef CONFIG_ARCH_EBSA285
-#define machine_is_ebsa285() (1)
+# ifdef machine_arch_type
+# undef machine_arch_type
+# define machine_arch_type __machine_arch_type
+# else
+# define machine_arch_type MACH_TYPE_EBSA285
+# endif
+# define machine_is_ebsa285() (machine_arch_type == MACH_TYPE_EBSA285)
X #else
-#define machine_is_ebsa285() (0)
+# define machine_is_ebsa285() (0)
X #endif
X
-#ifdef CONFIG_ARCH_VNC
-#define machine_is_netwinder() (1)
+#ifdef CONFIG_ARCH_NETWINDER
+# ifdef machine_arch_type
+# undef machine_arch_type
+# define machine_arch_type __machine_arch_type
+# else
+# define machine_arch_type MACH_TYPE_NETWINDER
+# endif
+# define machine_is_netwinder() (machine_arch_type == MACH_TYPE_NETWINDER)
X #else
-#define machine_is_netwinder() (0)
+# define machine_is_netwinder() (0)
X #endif
X
-#if defined(CONFIG_CATS)
-#define machine_is_cats() (machine_type == MACH_TYPE_CATS)
+#ifdef CONFIG_CATS
+# ifdef machine_arch_type
+# undef machine_arch_type
+# define machine_arch_type __machine_arch_type
+# else
+# define machine_arch_type MACH_TYPE_CATS
+# endif
+# define machine_is_cats() (machine_arch_type == MACH_TYPE_CATS)
X #else
-#define machine_is_cats() (0)
+# define machine_is_cats() (0)
X #endif
X
-#if 0
-#define machine_is_ebsa285() (machine_type == MACH_TYPE_EBSA285)
-#define machine_is_netwinder() (machine_type == MACH_TYPE_NETWINDER)
+#ifdef CONFIG_ARCH_CO285
+# ifdef machine_arch_type
+# undef machine_arch_type
+# define machine_arch_type __machine_arch_type
+# else
+# define machine_arch_type MACH_TYPE_CO285
+# endif
+# define machine_is_co285() (machine_arch_type == MACH_TYPE_CO285)
+#else
+# define machine_is_co285() (0)
X #endif
X
-#include <linux/kernel.h>
+#ifndef machine_arch_type
+#define machine_arch_type __machine_arch_type
+#endif
+
+/*
+ * task_struct isn't always declared - forward-declare it here.
+ */
+struct task_struct;
+
X #include <asm/proc-fns.h>
X
X extern void arm_malalignedptr(const char *, void *, volatile void *);
@@ -53,7 +139,7 @@
X *
X * `next' and `prev' should be struct task_struct, but it isn't always defined
X */
-#define switch_to(prev,next) processor._switch_to(prev,next)
+#define switch_to(prev,next,last) do { last = processor._switch_to(prev,next); } while (0)
X
X /*
X * Include processor dependent parts
@@ -62,9 +148,12 @@
X #include <asm/arch/system.h>
X
X #define mb() __asm__ __volatile__ ("" : : : "memory")
-#define nop() __asm__ __volatile__("mov r0,r0\n\t");
+#define rmb() mb()
+#define wmb() mb()
+#define nop() __asm__ __volatile__("mov\tr0,r0\t@ nop\n\t");
X
X extern asmlinkage void __backtrace(void);
X
X #endif
X
+#endif
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/unistd.h linux/include/asm-arm/unistd.h
--- v2.2.7/linux/include/asm-arm/unistd.h Fri Jan 8 22:36:23 1999
+++ linux/include/asm-arm/unistd.h Sat May 8 11:06:58 1999
@@ -195,6 +195,9 @@
X #define __NR_capset (__NR_SYSCALL_BASE+185)
X #define __NR_sigaltstack (__NR_SYSCALL_BASE+186)
X #define __NR_sendfile (__NR_SYSCALL_BASE+187)
+ /* 188 reserved */
+ /* 189 reserved */
+#define __NR_vfork (__NR_SYSCALL_BASE+190)
X
X #define __sys2(x) #x
X #define __sys1(x) __sys2(x)
@@ -364,7 +367,7 @@
X
X static inline int _exit(int exitcode)
X {
- extern int sys_exit(int);
+ extern int sys_exit(int) __attribute__((noreturn));
X return sys_exit(exitcode);
X }
X
@@ -393,37 +396,11 @@
X static inline _syscall3(int,execve,const char *,file,char **,argv,char **,envp);
X
X /*
- * This is the mechanism for creating a new kernel thread.
- *
- * NOTE! Only a kernel-only process(ie the swapper or direct descendants
- * who haven't done an "execve()") should use this: it will work within
- * a system call from a "real" process, but the process memory space will
- * not be free'd until both the parent and the child have exited.
+ * Create a new kernel thread
X */
-static inline pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
-{
- long retval;
-
- __asm__ __volatile__("
- mov r0,%1
- mov r1,%2
- "__syscall(clone)"
- teq r0, #0
- bne 1f
- mov r0,%4
- mov lr, pc
- mov pc, %3
- "__syscall(exit)"
-1: mov %0,r0"
- : "=r" (retval)
- : "Ir" (flags | CLONE_VM), "Ir" (NULL), "r" (fn), "Ir" (arg)
- : "r0","r1","r2","r3","lr");


-
- return retval;
-}

+extern pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
X
X #endif
-
X #endif /* __ASM_ARM_UNISTD_H */
X
X
diff -u --recursive --new-file v2.2.7/linux/include/asm-arm/vga.h linux/include/asm-arm/vga.h
--- v2.2.7/linux/include/asm-arm/vga.h Wed Sep 9 14:51:12 1998
+++ linux/include/asm-arm/vga.h Sat May 8 11:06:58 1999
@@ -1,9 +1,10 @@
X #ifndef ASMARM_VGA_H
X #define ASMARM_VGA_H
X
+#include <asm/hardware.h>
X #include <asm/io.h>
X
-#define VGA_MAP_MEM(x) (0xe0000000 + (x))
+#define VGA_MAP_MEM(x) (PCIMEM_BASE + (x))
X
X #define vga_readb(x) (*(x))
X #define vga_writeb(x,y) (*(y) = (x))
diff -u --recursive --new-file v2.2.7/linux/include/asm-i386/bugs.h linux/include/asm-i386/bugs.h
--- v2.2.7/linux/include/asm-i386/bugs.h Fri Jan 1 12:58:21 1999
+++ linux/include/asm-i386/bugs.h Tue May 11 10:35:39 1999


@@ -19,6 +19,7 @@
X

X #include <linux/config.h>
X #include <asm/processor.h>
+#include <asm/msr.h>
X
X #define CONFIG_BUGi386
X
@@ -27,6 +28,11 @@
X boot_cpu_data.hlt_works_ok = 0;
X }
X
+__initfunc(static void mca_pentium(char *s, int *ints))
+{
+ mca_pentium_flag = 1;
+}
+
X __initfunc(static void no_387(char *s, int *ints))
X {
X boot_cpu_data.hard_math = 0;
@@ -61,6 +67,31 @@
X #endif
X return;
X }
+ if (mca_pentium_flag) {
+ /* The IBM Model 95 machines with pentiums lock up on
+ * fpu test, so we avoid it. All pentiums have inbuilt
+ * FPU and thus should use exception 16. We still do
+ * the FDIV test, although I doubt there where ever any
+ * MCA boxes built with non-FDIV-bug cpus.
+ */
+ __asm__("fninit\n\t"
+ "fldl %1\n\t"
+ "fdivl %2\n\t"
+ "fmull %2\n\t"
+ "fldl %1\n\t"
+ "fsubp %%st,%%st(1)\n\t"
+ "fistpl %0\n\t"
+ "fwait\n\t"
+ "fninit"
+ : "=m" (*&boot_cpu_data.fdiv_bug)
+ : "m" (*&x), "m" (*&y));
+ printk("mca-pentium specified, avoiding FPU coupling test... ");
+ if (!boot_cpu_data.fdiv_bug)
+ printk("??? No FDIV bug? Lucky you...\n");
+ else
+ printk("detected FDIV bug though.\n");
+ return;
+ }
X /*
X * check if exception 16 works correctly.. This is truly evil
X * code: it disables the high 8 interrupts to make sure that
@@ -173,10 +204,10 @@
X
X n = K6_BUG_LOOP;
X f_vide = vide;
- __asm__ ("rdtsc" : "=a" (d));
+ rdtscl(d);
X while (n--)
X f_vide();
- __asm__ ("rdtsc" : "=a" (d2));
+ rdtscl(d2);
X d = d2-d;
X
X /* Knock these two lines out if it debugs out ok */
@@ -246,6 +277,7 @@
X ((Cx86_dir0_msb == 5) || (Cx86_dir0_msb == 3))) {
X int eax, dummy;
X unsigned char ccr3, ccr4;
+ __u32 old_cap;
X
X cli();
X ccr3 = getCx86(CX86_CCR3);
@@ -257,8 +289,11 @@
X
X /* we have up to level 1 available on the Cx6x86(L|MX) */
X boot_cpu_data.cpuid_level = 1;
+ /* Need to preserve some externally computed capabilities */
+ old_cap = boot_cpu_data.x86_capability & X86_FEATURE_MTRR;
X cpuid(1, &eax, &dummy, &dummy,
X &boot_cpu_data.x86_capability);
+ boot_cpu_data.x86_capability |= old_cap;
X
X boot_cpu_data.x86 = (eax >> 8) & 15;
X /*
@@ -314,6 +349,24 @@
X }
X
X /*
+ * In setup.c's cyrix_model() we have set the boot_cpu_data.coma_bug
+ * on certain processors that we know contain this bug and now we
+ * enable the workaround for it.
+ */
+
+__initfunc(static void check_cyrix_coma(void))
+{
+ if (boot_cpu_data.coma_bug) {
+ unsigned char ccr1;
+ cli();
+ ccr1 = getCx86 (CX86_CCR1);
+ setCx86 (CX86_CCR1, ccr1 | 0x10);
+ sti();
+ printk("Cyrix processor with \"coma bug\" found, workaround enabled\n");
+ }
+}
+
+/*
X * Check wether we are able to run this kernel safely on SMP.
X *
X * - In order to run on a i386, we need to be compiled for i386
@@ -371,5 +424,6 @@
X check_popad();
X check_amd_k6();
X check_pentium_f00f();
+ check_cyrix_coma();
X system_utsname.machine[1] = '0' + boot_cpu_data.x86;
X }
diff -u --recursive --new-file v2.2.7/linux/include/asm-i386/irq.h linux/include/asm-i386/irq.h
--- v2.2.7/linux/include/asm-i386/irq.h Tue Feb 23 15:21:34 1999
+++ linux/include/asm-i386/irq.h Thu May 6 14:02:34 1999
@@ -29,6 +29,7 @@
X }


X
X extern void disable_irq(unsigned int);

+extern void disable_irq_nosync(unsigned int);


X extern void enable_irq(unsigned int);

X
X #endif /* _ASM_IRQ_H */
diff -u --recursive --new-file v2.2.7/linux/include/asm-i386/msr.h linux/include/asm-i386/msr.h
--- v2.2.7/linux/include/asm-i386/msr.h Wed Dec 31 16:00:00 1969
+++ linux/include/asm-i386/msr.h Thu Apr 29 11:53:41 1999
@@ -0,0 +1,30 @@
+/*
+ * Access to machine-specific registers (available on 586 and better only)
+ * Note: the rd* operations modify the parameters directly (without using
+ * pointer indirection), this allows gcc to optimize better
+ */
+
+#define rdmsr(msr,val1,val2) \
+ __asm__ __volatile__("rdmsr" \
+ : "=a" (val1), "=d" (val2) \
+ : "c" (msr))
+
+#define wrmsr(msr,val1,val2) \
+ __asm__ __volatile__("wrmsr" \
+ : /* no outputs */ \
+ : "c" (msr), "a" (val1), "d" (val2))
+
+#define rdtsc(low,high) \
+ __asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high))
+
+#define rdtscl(low) \
+ __asm__ __volatile__ ("rdtsc" : "=a" (low) : : "edx")
+
+#define rdtscll(val) \
+ __asm__ __volatile__ ("rdtsc" : "=A" (val))
+
+#define rdpmc(counter,low,high) \
+ __asm__ __volatile__("rdpmc" \
+ : "=a" (low), "=d" (high) \
+ : "c" (counter))
+
diff -u --recursive --new-file v2.2.7/linux/include/asm-i386/mtrr.h linux/include/asm-i386/mtrr.h
--- v2.2.7/linux/include/asm-i386/mtrr.h Mon Oct 5 13:13:42 1998
+++ linux/include/asm-i386/mtrr.h Tue May 11 10:37:16 1999
@@ -1,6 +1,6 @@
X /* Generic MTRR (Memory Type Range Register) ioctls.
X
- Copyright (C) 1997-1998 Richard Gooch
+ Copyright (C) 1997-1999 Richard Gooch
X
X This library is free software; you can redistribute it and/or
X modify it under the terms of the GNU Library General Public
@@ -44,10 +44,11 @@
X };
X
X /* These are the various ioctls */
-#define MTRRIOC_ADD_ENTRY _IOW(MTRR_IOCTL_BASE, 0, struct mtrr_sentry)
-#define MTRRIOC_SET_ENTRY _IOW(MTRR_IOCTL_BASE, 1, struct mtrr_sentry)
-#define MTRRIOC_DEL_ENTRY _IOW(MTRR_IOCTL_BASE, 2, struct mtrr_sentry)
+#define MTRRIOC_ADD_ENTRY _IOW(MTRR_IOCTL_BASE, 0, struct mtrr_sentry)
+#define MTRRIOC_SET_ENTRY _IOW(MTRR_IOCTL_BASE, 1, struct mtrr_sentry)
+#define MTRRIOC_DEL_ENTRY _IOW(MTRR_IOCTL_BASE, 2, struct mtrr_sentry)
X #define MTRRIOC_GET_ENTRY _IOWR(MTRR_IOCTL_BASE, 3, struct mtrr_gentry)
+#define MTRRIOC_KILL_ENTRY _IOW(MTRR_IOCTL_BASE, 4, struct mtrr_sentry)
X
X /* These are the region types */
X #define MTRR_TYPE_UNCACHABLE 0
@@ -75,7 +76,7 @@
X #ifdef __KERNEL__
X
X /* The following functions are for use by other drivers */
-# if defined(CONFIG_MTRR) || defined(CONFIG_MTRR_MODULE)
+# ifdef CONFIG_MTRR
X extern int mtrr_add (unsigned long base, unsigned long size,
X unsigned int type, char increment);
X extern int mtrr_del (int reg, unsigned long base, unsigned long size);
diff -u --recursive --new-file v2.2.7/linux/include/asm-i386/processor.h linux/include/asm-i386/processor.h
--- v2.2.7/linux/include/asm-i386/processor.h Tue Jan 19 11:32:53 1999
+++ linux/include/asm-i386/processor.h Tue May 11 10:35:44 1999
@@ -35,6 +35,7 @@
X call */
X int fdiv_bug;
X int f00f_bug;
+ int coma_bug;
X unsigned long loops_per_sec;
X unsigned long *pgd_quick;
X unsigned long *pte_quick;
@@ -119,12 +120,17 @@
X /*
X * Cyrix CPU configuration register indexes
X */
+#define CX86_CCR0 0xc0
+#define CX86_CCR1 0xc1
X #define CX86_CCR2 0xc2
X #define CX86_CCR3 0xc3
X #define CX86_CCR4 0xe8
X #define CX86_CCR5 0xe9
+#define CX86_CCR6 0xea
X #define CX86_DIR0 0xfe
X #define CX86_DIR1 0xff
+#define CX86_ARR_BASE 0xc4
+#define CX86_RCR_BASE 0xdc
X
X /*
X * Cyrix CPU indexed register access macros
@@ -148,6 +154,7 @@
X extern unsigned int machine_id;
X extern unsigned int machine_submodel_id;
X extern unsigned int BIOS_revision;
+extern unsigned int mca_pentium_flag;
X
X /*
X * User space process size: 3GB (default).
diff -u --recursive --new-file v2.2.7/linux/include/asm-i386/system.h linux/include/asm-i386/system.h
--- v2.2.7/linux/include/asm-i386/system.h Mon Dec 28 15:00:53 1998
+++ linux/include/asm-i386/system.h Tue May 11 10:35:42 1999
@@ -9,30 +9,24 @@
X struct task_struct; /* one of the stranger aspects of C forward declarations.. */
X extern void FASTCALL(__switch_to(struct task_struct *prev, struct task_struct *next));
X
-/*
- * We do most of the task switching in C, but we need
- * to do the EIP/ESP switch in assembly..
- */
-#define switch_to(prev,next) do { \
- unsigned long eax, edx, ecx; \
- asm volatile("pushl %%ebx\n\t" \
- "pushl %%esi\n\t" \
+#define switch_to(prev,next,last) do { \
+ asm volatile("pushl %%esi\n\t" \
X "pushl %%edi\n\t" \
X "pushl %%ebp\n\t" \
X "movl %%esp,%0\n\t" /* save ESP */ \
- "movl %5,%%esp\n\t" /* restore ESP */ \
+ "movl %3,%%esp\n\t" /* restore ESP */ \
X "movl $1f,%1\n\t" /* save EIP */ \
- "pushl %6\n\t" /* restore EIP */ \
+ "pushl %4\n\t" /* restore EIP */ \
X "jmp __switch_to\n" \
X "1:\t" \
X "popl %%ebp\n\t" \
X "popl %%edi\n\t" \
X "popl %%esi\n\t" \
- "popl %%ebx" \
X :"=m" (prev->tss.esp),"=m" (prev->tss.eip), \
- "=a" (eax), "=d" (edx), "=c" (ecx) \
+ "=b" (last) \
X :"m" (next->tss.esp),"m" (next->tss.eip), \
- "a" (prev), "d" (next)); \
+ "a" (prev), "d" (next), \
+ "b" (prev)); \
X } while (0)
X
X #define _set_base(addr,base) do { unsigned long __pr; \
diff -u --recursive --new-file v2.2.7/linux/include/asm-i386/timex.h linux/include/asm-i386/timex.h
--- v2.2.7/linux/include/asm-i386/timex.h Mon Mar 29 11:09:12 1999
+++ linux/include/asm-i386/timex.h Tue May 11 10:35:42 1999
@@ -7,6 +7,7 @@
X #define _ASMi386_TIMEX_H
X
X #include <linux/config.h>
+#include <asm/msr.h>
X
X #define CLOCK_TICK_RATE 1193180 /* Underlying HZ */
X #define CLOCK_TICK_FACTOR 20 /* Factor of both 1000000 and CLOCK_TICK_RATE */
@@ -39,7 +40,7 @@
X #else
X unsigned long eax, edx;
X
- __asm__ __volatile__("rdtsc":"=a" (eax), "=d" (edx));
+ rdtsc(eax,edx);
X return eax;
X #endif
X }
diff -u --recursive --new-file v2.2.7/linux/include/asm-m68k/atari_SCCserial.h linux/include/asm-m68k/atari_SCCserial.h
--- v2.2.7/linux/include/asm-m68k/atari_SCCserial.h Tue Jun 23 10:01:28 1998
+++ linux/include/asm-m68k/atari_SCCserial.h Tue May 11 09:57:14 1999
@@ -28,6 +28,8 @@
X #define SCC_BAUD_BASE_NONE 0 /* for not connected or unused
X * clock sources */
X
+#define SCC_BAUD_BASE_M147_PCLK 312500 /* 5 MHz */
+#define SCC_BAUD_BASE_M147 312500 /* 5 MHz */
X #define SCC_BAUD_BASE_MVME_PCLK 781250 /* 12.5 MHz */
X #define SCC_BAUD_BASE_MVME 625000 /* 10.000 MHz */
X #define SCC_BAUD_BASE_BVME_PCLK 781250 /* 12.5 MHz */ /* XXX ??? */
diff -u --recursive --new-file v2.2.7/linux/include/asm-m68k/bootinfo.h linux/include/asm-m68k/bootinfo.h
--- v2.2.7/linux/include/asm-m68k/bootinfo.h Wed Jan 20 23:14:06 1999
+++ linux/include/asm-m68k/bootinfo.h Tue May 11 09:57:14 1999
@@ -219,9 +219,10 @@
X #define AMIGA_BOOTI_VERSION MK_BI_VERSION( 2, 0 )
X #define ATARI_BOOTI_VERSION MK_BI_VERSION( 2, 1 )
X #define MAC_BOOTI_VERSION MK_BI_VERSION( 2, 0 )
+#define MVME147_BOOTI_VERSION MK_BI_VERSION( 2, 0 )
X #define MVME16x_BOOTI_VERSION MK_BI_VERSION( 2, 0 )
X #define BVME6000_BOOTI_VERSION MK_BI_VERSION( 2, 0 )
-
+#define Q40_BOOTI_VERSION MK_BI_VERSION( 2, 0 )
X
X #ifdef BOOTINFO_COMPAT_1_0
X
diff -u --recursive --new-file v2.2.7/linux/include/asm-m68k/dvma.h linux/include/asm-m68k/dvma.h
--- v2.2.7/linux/include/asm-m68k/dvma.h Wed Dec 31 16:00:00 1969
+++ linux/include/asm-m68k/dvma.h Tue May 11 09:57:14 1999
@@ -0,0 +1,165 @@
+/* $Id: dvma.h,v 1.4 1999/03/27 20:23:41 tsbogend Exp $
+ * include/asm-m68k/dma.h
+ *
+ * Copyright 1995 (C) David S. Miller (da...@caip.rutgers.edu)
+ *
+ * Hacked to fit Sun3x needs by Thomas Bogendoerfer
+ */
+
+#ifndef __M68K_DVMA_H
+#define __M68K_DVMA_H
+
+/* Structure to describe the current status of DMA registers on the Sparc */
+struct sparc_dma_registers {
+ __volatile__ unsigned long cond_reg; /* DMA condition register */
+ __volatile__ unsigned long st_addr; /* Start address of this transfer */
+ __volatile__ unsigned long cnt; /* How many bytes to transfer */
+ __volatile__ unsigned long dma_test; /* DMA test register */
+};
+
+/* DVMA chip revisions */
+enum dvma_rev {
+ dvmarev0,
+ dvmaesc1,
+ dvmarev1,
+ dvmarev2,
+ dvmarev3,
+ dvmarevplus,
+ dvmahme
+};
+
+#define DMA_HASCOUNT(rev) ((rev)==dvmaesc1)
+
+/* Linux DMA information structure, filled during probe. */
+struct Linux_SBus_DMA {
+ struct Linux_SBus_DMA *next;
+ struct linux_sbus_device *SBus_dev;
+ struct sparc_dma_registers *regs;
+
+ /* Status, misc info */
+ int node; /* Prom node for this DMA device */
+ int running; /* Are we doing DMA now? */
+ int allocated; /* Are we "owned" by anyone yet? */
+
+ /* Transfer information. */
+ unsigned long addr; /* Start address of current transfer */
+ int nbytes; /* Size of current transfer */
+ int realbytes; /* For splitting up large transfers, etc. */
+
+ /* DMA revision */
+ enum dvma_rev revision;
+};
+
+extern struct Linux_SBus_DMA *dma_chain;
+
+/* Broken hardware... */
+#define DMA_ISBROKEN(dma) ((dma)->revision == dvmarev1)
+#define DMA_ISESC1(dma) ((dma)->revision == dvmaesc1)
+
+/* Fields in the cond_reg register */
+/* First, the version identification bits */
+#define DMA_DEVICE_ID 0xf0000000 /* Device identification bits */
+#define DMA_VERS0 0x00000000 /* Sunray DMA version */
+#define DMA_ESCV1 0x40000000 /* DMA ESC Version 1 */
+#define DMA_VERS1 0x80000000 /* DMA rev 1 */
+#define DMA_VERS2 0xa0000000 /* DMA rev 2 */
+#define DMA_VERHME 0xb0000000 /* DMA hme gate array */
+#define DMA_VERSPLUS 0x90000000 /* DMA rev 1 PLUS */
+
+#define DMA_HNDL_INTR 0x00000001 /* An IRQ needs to be handled */
+#define DMA_HNDL_ERROR 0x00000002 /* We need to take an error */
+#define DMA_FIFO_ISDRAIN 0x0000000c /* The DMA FIFO is draining */
+#define DMA_INT_ENAB 0x00000010 /* Turn on interrupts */
+#define DMA_FIFO_INV 0x00000020 /* Invalidate the FIFO */
+#define DMA_ACC_SZ_ERR 0x00000040 /* The access size was bad */
+#define DMA_FIFO_STDRAIN 0x00000040 /* DMA_VERS1 Drain the FIFO */
+#define DMA_RST_SCSI 0x00000080 /* Reset the SCSI controller */
+#define DMA_RST_ENET DMA_RST_SCSI /* Reset the ENET controller */
+#define DMA_ST_WRITE 0x00000100 /* write from device to memory */
+#define DMA_ENABLE 0x00000200 /* Fire up DMA, handle requests */
+#define DMA_PEND_READ 0x00000400 /* DMA_VERS1/0/PLUS Pending Read */
+#define DMA_ESC_BURST 0x00000800 /* 1=16byte 0=32byte */
+#define DMA_READ_AHEAD 0x00001800 /* DMA read ahead partial longword */
+#define DMA_DSBL_RD_DRN 0x00001000 /* No EC drain on slave reads */
+#define DMA_BCNT_ENAB 0x00002000 /* If on, use the byte counter */
+#define DMA_TERM_CNTR 0x00004000 /* Terminal counter */
+#define DMA_CSR_DISAB 0x00010000 /* No FIFO drains during csr */
+#define DMA_SCSI_DISAB 0x00020000 /* No FIFO drains during reg */
+#define DMA_DSBL_WR_INV 0x00020000 /* No EC inval. on slave writes */
+#define DMA_ADD_ENABLE 0x00040000 /* Special ESC DVMA optimization */
+#define DMA_E_BURST8 0x00040000 /* ENET: SBUS r/w burst size */
+#define DMA_BRST_SZ 0x000c0000 /* SCSI: SBUS r/w burst size */
+#define DMA_BRST64 0x00080000 /* SCSI: 64byte bursts (HME on UltraSparc only) */
+#define DMA_BRST32 0x00040000 /* SCSI: 32byte bursts */
+#define DMA_BRST16 0x00000000 /* SCSI: 16byte bursts */
+#define DMA_BRST0 0x00080000 /* SCSI: no bursts (non-HME gate arrays) */
+#define DMA_ADDR_DISAB 0x00100000 /* No FIFO drains during addr */
+#define DMA_2CLKS 0x00200000 /* Each transfer = 2 clock ticks */
+#define DMA_3CLKS 0x00400000 /* Each transfer = 3 clock ticks */
+#define DMA_EN_ENETAUI DMA_3CLKS /* Put lance into AUI-cable mode */
+#define DMA_CNTR_DISAB 0x00800000 /* No IRQ when DMA_TERM_CNTR set */
+#define DMA_AUTO_NADDR 0x01000000 /* Use "auto nxt addr" feature */
+#define DMA_SCSI_ON 0x02000000 /* Enable SCSI dma */
+#define DMA_PARITY_OFF 0x02000000 /* HME: disable parity checking */
+#define DMA_LOADED_ADDR 0x04000000 /* Address has been loaded */
+#define DMA_LOADED_NADDR 0x08000000 /* Next address has been loaded */
+
+/* Values describing the burst-size property from the PROM */
+#define DMA_BURST1 0x01
+#define DMA_BURST2 0x02
+#define DMA_BURST4 0x04
+#define DMA_BURST8 0x08
+#define DMA_BURST16 0x10
+#define DMA_BURST32 0x20
+#define DMA_BURST64 0x40
+#define DMA_BURSTBITS 0x7f
+
+/* Determine highest possible final transfer address given a base */
+#define DMA_MAXEND(addr) (0x01000000UL-(((unsigned long)(addr))&0x00ffffffUL))
+
+/* Yes, I hack a lot of elisp in my spare time... */
+#define DMA_ERROR_P(regs) ((((regs)->cond_reg) & DMA_HNDL_ERROR))
+#define DMA_IRQ_P(regs) ((((regs)->cond_reg) & (DMA_HNDL_INTR | DMA_HNDL_ERROR)))
+#define DMA_WRITE_P(regs) ((((regs)->cond_reg) & DMA_ST_WRITE))
+#define DMA_OFF(regs) ((((regs)->cond_reg) &= (~DMA_ENABLE)))
+#define DMA_INTSOFF(regs) ((((regs)->cond_reg) &= (~DMA_INT_ENAB)))
+#define DMA_INTSON(regs) ((((regs)->cond_reg) |= (DMA_INT_ENAB)))
+#define DMA_PUNTFIFO(regs) ((((regs)->cond_reg) |= DMA_FIFO_INV))
+#define DMA_SETSTART(regs, addr) ((((regs)->st_addr) = (char *) addr))
+#define DMA_BEGINDMA_W(regs) \
+ ((((regs)->cond_reg |= (DMA_ST_WRITE|DMA_ENABLE|DMA_INT_ENAB))))
+#define DMA_BEGINDMA_R(regs) \
+ ((((regs)->cond_reg |= ((DMA_ENABLE|DMA_INT_ENAB)&(~DMA_ST_WRITE)))))
+
+/* For certain DMA chips, we need to disable ints upon irq entry
+ * and turn them back on when we are done. So in any ESP interrupt
+ * handler you *must* call DMA_IRQ_ENTRY upon entry and DMA_IRQ_EXIT
+ * when leaving the handler. You have been warned...
+ */
+#define DMA_IRQ_ENTRY(dma, dregs) do { \
+ if(DMA_ISBROKEN(dma)) DMA_INTSOFF(dregs); \
+ } while (0)
+
+#define DMA_IRQ_EXIT(dma, dregs) do { \
+ if(DMA_ISBROKEN(dma)) DMA_INTSON(dregs); \
+ } while(0)
+
+/* Reset the friggin' thing... */
+#define DMA_RESET(dma) do { \
+ struct sparc_dma_registers *regs = dma->regs; \
+ /* Let the current FIFO drain itself */ \
+ sparc_dma_pause(regs, (DMA_FIFO_ISDRAIN)); \
+ /* Reset the logic */ \
+ regs->cond_reg |= (DMA_RST_SCSI); /* assert */ \
+ __delay(400); /* let the bits set ;) */ \
+ regs->cond_reg &= ~(DMA_RST_SCSI); /* de-assert */ \
+ sparc_dma_enable_interrupts(regs); /* Re-enable interrupts */ \
+ /* Enable FAST transfers if available */ \
+ if(dma->revision>dvmarev1) regs->cond_reg |= DMA_3CLKS; \
+ dma->running = 0; \
+} while(0)
+
+extern unsigned long dvma_alloc (unsigned long, unsigned long);
+extern void dvma_free (unsigned long, unsigned long);
+
+#endif /* !(__M68K_DVMA_H) */
diff -u --recursive --new-file v2.2.7/linux/include/asm-m68k/floppy.h linux/include/asm-m68k/floppy.h
--- v2.2.7/linux/include/asm-m68k/floppy.h Wed Dec 31 16:00:00 1969
+++ linux/include/asm-m68k/floppy.h Tue May 11 09:57:14 1999
@@ -0,0 +1,239 @@
+/*
+ * Q40 Architecture specific parts of the Floppy driver
+ *


+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.

+ *
+ * Copyright (C) 1999
+ */
+
+#include <asm/io.h>
+
+#include <linux/vmalloc.h>
+
+
+asmlinkage void floppy_hardint(int irq, void *dev_id, struct pt_regs * regs);
+
+#define MAX_DMA_ADDRESS 0x00 /* nothing like that */
+
+extern spinlock_t dma_spin_lock;
+
+static __inline__ unsigned long claim_dma_lock(void)


+{
+ unsigned long flags;

+ spin_lock_irqsave(&dma_spin_lock, flags);


SHAR_EOF
true || echo 'restore of patch-2.2.8 failed'
fi

echo 'End of part 29'
echo 'File patch-2.2.8 is continued in part 30'
echo 30 > _shar_seq_.tmp

Thomas...@ciw.uni-karlsruhe.de

unread,
May 12, 1999, 3:00:00 AM5/12/99
to
Archive-name: v2.2/patch-2.2.8/part30

#!/bin/sh
# this is part 30 of a 33 - part archive


# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.8 continued
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 30; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.8'
else
echo 'x - continuing with patch-2.2.8'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.8' &&

+ return flags;
+}
+
+static __inline__ void release_dma_lock(unsigned long flags)
+{
+ spin_unlock_irqrestore(&dma_spin_lock, flags);
+}
+
+
+
+#define fd_inb(port) inb_p(port)
+#define fd_outb(port,value) outb_p(port,value)
+
+
+#define fd_request_dma() vdma_request_dma(FLOPPY_DMA,"floppy")
+/*#define fd_free_dma() */
+
+
+#define fd_get_dma_residue() vdma_get_dma_residue(FLOPPY_DMA)
+#define fd_dma_mem_alloc(size) vdma_mem_alloc(size)
+#define fd_dma_setup(addr, size, mode, io) vdma_dma_setup(addr, size, mode, io)
+
+
+#define fd_enable_irq() /* nothing... */
+#define fd_disable_irq() /* nothing... */
+#define fd_free_irq() free_irq(FLOPPY_IRQ, NULL)
+
+#define fd_free_dma() /* nothing */
+
+/* No 64k boundary crossing problems on Q40 - no DMA at all */
+#define CROSS_64KB(a,s) (0)
+
+#define DMA_MODE_READ 0x44 /* i386 look-alike */
+#define DMA_MODE_WRITE 0x48
+
+
+static int q40_floppy_init(void)
+{
+ use_virtual_dma =1;
+ /* FLOPPY_IRQ=6; */
+
+ if (MACH_IS_Q40)
+ return 0x3f0;
+ else


+ return -1;
+}
+

+
+
+
+/*
+ * Again, the CMOS information doesn't work on the Q40..
+ */
+#define FLOPPY0_TYPE 6
+#define FLOPPY1_TYPE 0
+
+
+
+
+#define FLOPPY_MOTOR_MASK 0xf0
+
+
+
+
+/* basically PC init + set use_virtual_dma */
+#define FDC1 q40_floppy_init()
+static int FDC2 = -1;
+
+
+#define N_FDC 1
+#define N_DRIVE 8
+
+
+
+/* vdma stuff adapted from asm-i386/floppy.h */
+
+static int virtual_dma_count=0;
+static int virtual_dma_residue=0;
+static char *virtual_dma_addr=0;
+static int virtual_dma_mode=0;
+static int doing_pdma=0;
+
+
+
+static int fd_request_irq(void)
+{
+ return request_irq(FLOPPY_IRQ, floppy_hardint,SA_INTERRUPT,
+ "floppy", NULL);
+}
+
+/*#define SLOW_DOWN do{outb(0,0x80);}while(0)*/
+#define SLOW_DOWN do{int count=1;do{if(!jiffies)break;}while(count-->0);}while(0)


+
+asmlinkage void floppy_hardint(int irq, void *dev_id, struct pt_regs * regs)

+{
+ register unsigned char st;
+
+#undef TRACE_FLPY_INT
+#define NO_FLOPPY_ASSEMBLER
+
+#ifdef TRACE_FLPY_INT
+ static int calls=0;
+ static int bytes=0;
+ static int dma_wait=0;
+#endif
+ if(!doing_pdma) {
+ floppy_interrupt(irq, dev_id, regs);
+ return;
+ }
+
+#ifdef TRACE_FLPY_INT
+ if(!calls)
+ bytes = virtual_dma_count;
+#endif
+
+ {
+ register int lcount;
+ register char *lptr;
+
+ /* serve 1st byte fast: */
+
+ st=1;
+ for(lcount=virtual_dma_count, lptr=virtual_dma_addr;
+ lcount; lcount--, lptr++) {
+ st=inb(virtual_dma_port+4) & 0xa0 ;
+ if(st != 0xa0)
+ break;
+ if(virtual_dma_mode)
+ outb_p(*lptr, virtual_dma_port+5);
+ else
+ *lptr = inb_p(virtual_dma_port+5);
+ }
+
+ virtual_dma_count = lcount;
+ virtual_dma_addr = lptr;
+ st = inb(virtual_dma_port+4);
+ }
+
+#ifdef TRACE_FLPY_INT
+ calls++;
+#endif
+ if(st == 0x20)
+ return;
+ if(!(st & 0x20)) {
+ virtual_dma_residue += virtual_dma_count;
+ virtual_dma_count=0;
+#ifdef TRACE_FLPY_INT
+ printk("count=%x, residue=%x calls=%d bytes=%d dma_wait=%d\n",
+ virtual_dma_count, virtual_dma_residue, calls, bytes,
+ dma_wait);
+ calls = 0;
+ dma_wait=0;
+#endif
+ doing_pdma = 0;
+ floppy_interrupt(irq, dev_id, regs);
+ return;
+ }
+#ifdef TRACE_FLPY_INT
+ if(!virtual_dma_count)
+ dma_wait++;
+#endif
+}
+
+
+
+static int vdma_request_dma(unsigned int dmanr, const char * device_id)


+{
+ return 0;
+}

+
+
+static int vdma_get_dma_residue(unsigned int dummy)
+{
+ return virtual_dma_count + virtual_dma_residue;
+}
+
+
+static unsigned long vdma_mem_alloc(unsigned long size)
+{
+ return (unsigned long) vmalloc(size);
+
+}
+
+static void _fd_dma_mem_free(unsigned long addr, unsigned long size)
+{
+ vfree((void *)addr);
+}
+#define fd_dma_mem_free(addr,size) _fd_dma_mem_free(addr, size)
+
+
+/* choose_dma_mode ???*/
+
+static int vdma_dma_setup(char *addr, unsigned long size, int mode, int io)
+{
+ doing_pdma = 1;
+ virtual_dma_port = io;
+ virtual_dma_mode = (mode == DMA_MODE_WRITE);
+ virtual_dma_addr = addr;
+ virtual_dma_count = size;
+ virtual_dma_residue = 0;


+ return 0;
+}
+
+

+
+static void fd_disable_dma(void)
+{
+ doing_pdma = 0;
+ virtual_dma_residue += virtual_dma_count;
+ virtual_dma_count=0;
+}
+
+
+
diff -u --recursive --new-file v2.2.7/linux/include/asm-m68k/ide.h linux/include/asm-m68k/ide.h
--- v2.2.7/linux/include/asm-m68k/ide.h Wed Jan 20 23:14:06 1999
+++ linux/include/asm-m68k/ide.h Tue May 11 09:57:14 1999
@@ -45,22 +45,38 @@
X #include <asm/macints.h>
X #endif
X
+
+typedef unsigned int q40ide_ioreg_t;
+
+
X typedef unsigned char * ide_ioreg_t;
X
+
X #ifndef MAX_HWIFS
X #define MAX_HWIFS 4 /* same as the other archs */
X #endif
X
-static __inline int ide_default_irq (ide_ioreg_t base)
+int q40ide_default_irq(q40ide_ioreg_t);
+
+static __inline__ int ide_default_irq(ide_ioreg_t base)
X {
- return 0;
+ if (MACH_IS_Q40)
+ return q40ide_default_irq((q40ide_ioreg_t) base);
+ else return 0;
X }
X
+
X /*
X * Can we do this in a generic manner??
X */
+void q40_ide_init_hwif_ports (q40ide_ioreg_t *p, q40ide_ioreg_t base, int *irq);
+
X static __inline__ void ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq)
X {


+#ifdef CONFIG_Q40
+ if (MACH_IS_Q40)

+ return q40_ide_init_hwif_ports((q40ide_ioreg_t *)p,(q40ide_ioreg_t)base,irq);
+#endif
X printk("ide_init_hwif_ports: must not be called\n");
X }
X
@@ -86,6 +102,10 @@
X if (MACH_IS_AMIGA)
X return request_irq(irq, handler, 0, device, dev_id);
X #endif /* CONFIG_AMIGA */


+#ifdef CONFIG_Q40
+ if (MACH_IS_Q40)

+ return request_irq(irq, handler, 0, device, dev_id);
+#endif /* CONFIG_Q40*/
X #ifdef CONFIG_MAC
X if (MACH_IS_MAC)
X #if 0 /* MSch Hack: maybe later we'll call ide_intr without a wrapper */
@@ -103,6 +123,10 @@
X if (MACH_IS_AMIGA)
X free_irq(irq, dev_id);
X #endif /* CONFIG_AMIGA */


+#ifdef CONFIG_Q40
+ if (MACH_IS_Q40)

+ free_irq(irq, dev_id);
+#endif /* CONFIG_Q40*/
X #ifdef CONFIG_MAC
X if (MACH_IS_MAC)
X nubus_free_irq(12);
@@ -119,10 +143,18 @@
X
X static __inline__ void ide_request_region (ide_ioreg_t from, unsigned int extent, const char *name)


X {
+#ifdef CONFIG_Q40
+ if (MACH_IS_Q40)

+ request_region((q40ide_ioreg_t)from,extent,name);
+#endif
X }
X
X static __inline__ void ide_release_region (ide_ioreg_t from, unsigned int extent)


X {
+#ifdef CONFIG_Q40
+ if (MACH_IS_Q40)

+ release_region((q40ide_ioreg_t)from,extent);
+#endif
X }
X
X #undef SUPPORT_SLOW_DATA_PORTS
@@ -131,14 +163,36 @@
X #undef SUPPORT_VLB_SYNC
X #define SUPPORT_VLB_SYNC 0
X
+/* this definition is used only on startup .. */
+#ifndef CONFIG_Q40
X #undef HD_DATA
X #define HD_DATA NULL
+#else
+#ifdef MACH_Q40_ONLY
+#undef HD_DATA
+#define HD_DATA ((ide_ioreg_t)0x1f0)
+#else
+#undef HD_DATA
+#define HD_DATA (MACH_IS_Q40 ? (ide_ioreg_t)0x1f0 : 0)
+#endif
+#endif
+
X
X #define insl(data_reg, buffer, wcount) insw(data_reg, buffer, (wcount)<<1)
X #define outsl(data_reg, buffer, wcount) outsw(data_reg, buffer, (wcount)<<1)
X
+#ifdef CONFIG_Q40
+#ifdef MACH_Q40_ONLY
+#define ADDR_TRANS(_addr_) (Q40_ISA_IO_W(_addr_))
+#else
+#define ADDR_TRANS(_addr_) (MACH_IS_Q40 ? ((unsigned char *)Q40_ISA_IO_W(_addr_)) : (_addr_))
+#endif
+#else
+#define ADDR_TRANS(_addr_) (_addr_)
+#endif
+
X #define insw(port, buf, nr) ({ \
- unsigned char *_port = (unsigned char *)(port); \
+ unsigned char *_port = (unsigned char *) ADDR_TRANS(port); \
X unsigned char *_buf = (buf); \
X int _nr = (nr); \
X unsigned long _tmp; \
@@ -179,7 +233,7 @@
X })
X
X #define outsw(port, buf, nr) ({ \
- unsigned char *_port = (unsigned char *)(port); \
+ unsigned char *_port = (unsigned char *) ADDR_TRANS(port); \
X unsigned char *_buf = (buf); \
X int _nr = (nr); \
X unsigned long _tmp; \
@@ -219,7 +273,7 @@
X } \
X })
X
-#ifdef CONFIG_ATARI
+#if defined(CONFIG_ATARI) || defined(CONFIG_Q40)
X #define insl_swapw(data_reg, buffer, wcount) \
X insw_swapw(data_reg, buffer, (wcount)<<1)
X #define outsl_swapw(data_reg, buffer, wcount) \
@@ -236,7 +290,7 @@
X rolw #8,%/d0; \
X movew %/d0,%/a1@+; \
X dbra %/d6,1b" : \
- : "g" (port), "g" (buf), "g" (nr) \
+ : "g" (ADDR_TRANS(port)), "g" (buf), "g" (nr) \
X : "d0", "a0", "a1", "d6"); \
X else \
X __asm__ __volatile__ \
@@ -270,8 +324,9 @@
X rolw #8,%/d0; \
X movew %/d0,%/a1@+; \
X dbra %/d6,1b" : \
- : "g" (port), "g" (buf), "g" (nr) \
- : "d0", "a0", "a1", "d6")
+ : "g" (ADDR_TRANS(port)), "g" (buf), "g" (nr) \
+ : "d0", "a0", "a1", "d6")
+
X
X #define outsw_swapw(port, buf, nr) \
X if ((nr) % 8) \
@@ -284,7 +339,7 @@
X rolw #8,%/d0; \
X movew %/d0,%/a0@; \
X dbra %/d6,1b" : \
- : "g" (port), "g" (buf), "g" (nr) \
+ : "g" (ADDR_TRANS(port)), "g" (buf), "g" (nr) \
X : "d0", "a0", "a1", "d6"); \
X else \
X __asm__ __volatile__ \
@@ -318,7 +373,7 @@
X rolw #8,%/d0; \
X movew %/d0,%/a0@; \
X dbra %/d6,1b" : \
- : "g" (port), "g" (buf), "g" (nr) \
+ : "g" (ADDR_TRANS(port)), "g" (buf), "g" (nr) \
X : "d0", "a0", "a1", "d6")
X
X #endif /* CONFIG_ATARI */
diff -u --recursive --new-file v2.2.7/linux/include/asm-m68k/keyboard.h linux/include/asm-m68k/keyboard.h
--- v2.2.7/linux/include/asm-m68k/keyboard.h Wed Apr 28 11:37:31 1999
+++ linux/include/asm-m68k/keyboard.h Tue May 11 09:57:14 1999
@@ -16,26 +16,46 @@
X

X #include <asm/machdep.h>
X
+#ifdef CONFIG_Q40

+#include <asm/q40_keyboard.h>
+#endif
+
X static __inline__ int kbd_setkeycode(unsigned int scancode,
X unsigned int keycode)


X {
+#ifdef CONFIG_Q40
+ if (MACH_IS_Q40)

+ return q40kbd_setkeycode(scancode,keycode);
+#endif
X return -EOPNOTSUPP;
X }
X
X static __inline__ int kbd_getkeycode(unsigned int scancode)


X {
+#ifdef CONFIG_Q40
+ if (MACH_IS_Q40)

+ return q40kbd_getkeycode(scancode);
+#endif
X return scancode > 127 ? -EINVAL : scancode;
X }
X
X static __inline__ int kbd_translate(unsigned char scancode,
X unsigned char *keycode, char raw_mode)


X {
+#ifdef CONFIG_Q40
+ if (MACH_IS_Q40)

+ return q40kbd_translate(scancode,keycode,raw_mode);
+#endif
X *keycode = scancode;
X return 1;
X }
X
X static __inline__ char kbd_unexpected_up(unsigned char keycode)


X {
+#ifdef CONFIG_Q40
+ if (MACH_IS_Q40)

+ return q40kbd_unexpected_up(keycode);
+#endif
X return 0200;
X }
X
diff -u --recursive --new-file v2.2.7/linux/include/asm-m68k/mvme147hw.h linux/include/asm-m68k/mvme147hw.h
--- v2.2.7/linux/include/asm-m68k/mvme147hw.h Wed Dec 31 16:00:00 1969
+++ linux/include/asm-m68k/mvme147hw.h Tue May 11 09:57:14 1999
@@ -0,0 +1,110 @@
+#ifndef _MVME147HW_H_
+#define _MVME147HW_H_
+
+typedef struct {
+ unsigned char
+ ctrl,
+ bcd_sec,
+ bcd_min,
+ bcd_hr,
+ bcd_dow,
+ bcd_dom,
+ bcd_mth,
+ bcd_year;
+} MK48T02;
+
+#define RTC_WRITE 0x80
+#define RTC_READ 0x40
+#define RTC_STOP 0x20
+
+#define m147_rtc ((MK48T02 * volatile)0xfffe07f8)
+
+
+struct pcc_regs {
+ volatile u_long dma_tadr;
+ volatile u_long dma_dadr;
+ volatile u_long dma_bcr;
+ volatile u_long dma_hr;
+ volatile u_short t1_preload;
+ volatile u_short t1_count;
+ volatile u_short t2_preload;
+ volatile u_short t2_count;
+ volatile u_char t1_int_cntrl;
+ volatile u_char t1_cntrl;
+ volatile u_char t2_int_cntrl;
+ volatile u_char t2_cntrl;
+ volatile u_char ac_fail;
+ volatile u_char watchdog;
+ volatile u_char lpt_intr;
+ volatile u_char lpt_cntrl;
+ volatile u_char dma_intr;
+ volatile u_char dma_cntrl;
+ volatile u_char bus_error;
+ volatile u_char dma_status;
+ volatile u_char abort;
+ volatile u_char ta_fnctl;
+ volatile u_char serial_cntrl;
+ volatile u_char general_cntrl;
+ volatile u_char lan_cntrl;
+ volatile u_char general_status;
+ volatile u_char scsi_interrupt;
+ volatile u_char slave;
+ volatile u_char soft1_cntrl;
+ volatile u_char int_base;
+ volatile u_char soft2_cntrl;
+ volatile u_char revision_level;
+ volatile u_char lpt_data;
+ volatile u_char lpt_status;
+ };
+
+#define m147_pcc ((struct pcc_regs * volatile)0xfffe1000)
+
+
+#define PCC_INT_ENAB 0x08
+
+#define PCC_TIMER_INT_CLR 0x80
+#define PCC_TIMER_PRELOAD 63936l
+
+#define PCC_LEVEL_ABORT 0x07
+#define PCC_LEVEL_SERIAL 0x04
+#define PCC_LEVEL_ETH 0x04
+#define PCC_LEVEL_TIMER1 0x04
+#define PCC_LEVEL_SCSI_PORT 0x04
+#define PCC_LEVEL_SCSI_DMA 0x04
+
+#define PCC_IRQ_AC_FAIL 0x40
+#define PCC_IRQ_BERR 0x41
+#define PCC_IRQ_ABORT 0x42
+/* #define PCC_IRQ_SERIAL 0x43 */
+#define PCC_IRQ_PRINTER 0x47
+#define PCC_IRQ_TIMER1 0x48
+#define PCC_IRQ_TIMER2 0x49
+#define PCC_IRQ_SOFTWARE1 0x4a
+#define PCC_IRQ_SOFTWARE2 0x4b
+
+
+#define M147_SCC_A_ADDR 0xfffe3002
+#define M147_SCC_B_ADDR 0xfffe3000
+
+#define MVME147_IRQ_SCSI_PORT 0x45
+#define MVME147_IRQ_SCSI_DMA 0x46
+
+/* SCC interrupts, for MVME162 */
+
+#define MVME147_IRQ_TYPE_PRIO 0
+#define MVME147_IRQ_SCC_BASE 0x60
+#define MVME147_IRQ_SCCB_TX 0x60
+#define MVME147_IRQ_SCCB_STAT 0x62
+#define MVME147_IRQ_SCCB_RX 0x64
+#define MVME147_IRQ_SCCB_SPCOND 0x66
+#define MVME147_IRQ_SCCA_TX 0x68
+#define MVME147_IRQ_SCCA_STAT 0x6a
+#define MVME147_IRQ_SCCA_RX 0x6c
+#define MVME147_IRQ_SCCA_SPCOND 0x6e
+
+#define MVME147_LANCE_BASE 0xfffe1800
+#define MVME147_LANCE_IRQ 0x44
+
+#define ETHERNET_ADDRESS 0xfffe0778
+
+#endif
diff -u --recursive --new-file v2.2.7/linux/include/asm-m68k/oplib.h linux/include/asm-m68k/oplib.h
--- v2.2.7/linux/include/asm-m68k/oplib.h Wed Dec 31 16:00:00 1969
+++ linux/include/asm-m68k/oplib.h Tue May 11 09:57:14 1999
@@ -0,0 +1,8 @@
+/*
+ * prototypes for dummy prom_* routines
+ */
+
+extern int prom_getintdefault(int node, char *property, int defval);
+extern int prom_getbool(int node, char *prop);
+extern void prom_printf(char *fmt, ...);
+extern void prom_halt(void) __attribute__ ((noreturn));
diff -u --recursive --new-file v2.2.7/linux/include/asm-m68k/page.h linux/include/asm-m68k/page.h
--- v2.2.7/linux/include/asm-m68k/page.h Wed Jan 20 23:14:06 1999
+++ linux/include/asm-m68k/page.h Tue May 11 09:57:14 1999
@@ -110,7 +110,22 @@


X /* This handles the memory map.. */

X #define PAGE_OFFSET 0
X #define __pa(x) ((unsigned long)(x)-PAGE_OFFSET)
-#define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET))
+/*
+ * A hacky workaround for the problems with mmap() of frame buffer
+ * memory in the lower 16MB physical memoryspace.
+ *
+ * This is a short term solution, we will have to deal properly
+ * with this in 2.3.x.
+ */
+extern inline void *__va(unsigned long physaddr)
+{
+#ifdef CONFIG_AMIGA
+ if (MACH_IS_AMIGA && (physaddr < 16*1024*1024))
+ return (void *)0xffffffff;
+ else
+#endif
+ return (void *)(physaddr+PAGE_OFFSET);
+}
X #define MAP_NR(addr) (__pa(addr) >> PAGE_SHIFT)
X
X #endif /* __KERNEL__ */
diff -u --recursive --new-file v2.2.7/linux/include/asm-m68k/pgtable.h linux/include/asm-m68k/pgtable.h
--- v2.2.7/linux/include/asm-m68k/pgtable.h Tue Mar 23 14:35:48 1999
+++ linux/include/asm-m68k/pgtable.h Tue May 11 09:57:14 1999
@@ -507,6 +507,7 @@
X if (tsk == current) {
X if (CPU_IS_040_OR_060)
X __asm__ __volatile__ (".chip 68040\n\t"
+ "pflushan\n\t"
X "movec %0,%%urp\n\t"
X ".chip 68k"
X : : "r" (tsk->tss.crp[1]));
@@ -514,10 +515,22 @@
X unsigned long tmp;
X __asm__ __volatile__ ("movec %%cacr,%0\n\t"
X "orw #0x0808,%0\n\t"
- "movec %0,%%cacr\n\t"
- "pmove %1,%%crp\n\t"
- : "=d" (tmp)
- : "m" (tsk->tss.crp[0]));
+ "movec %0,%%cacr"
+ : "=d" (tmp));
+ /* For a 030-only kernel, avoid flushing the whole
+ ATC, we only need to flush the user entries.
+ The 68851 does this by itself. Avoid a runtime
+ check here. */
+ __asm__ __volatile__ (
+#ifdef CPU_M68030_ONLY
+ ".chip 68030\n\t"
+ "pmovefd %0,%%crp\n\t"
+ ".chip 68k\n\t"
+ "pflush #0,#4"
+#else
+ "pmove %0,%%crp"
+#endif
+ : : "m" (tsk->tss.crp[0]));
X }
X }
X }
diff -u --recursive --new-file v2.2.7/linux/include/asm-m68k/q40_keyboard.h linux/include/asm-m68k/q40_keyboard.h
--- v2.2.7/linux/include/asm-m68k/q40_keyboard.h Wed Dec 31 16:00:00 1969
+++ linux/include/asm-m68k/q40_keyboard.h Tue May 11 09:57:14 1999
@@ -0,0 +1,54 @@
+/*
+ * linux/include/asm-m68k/q40_keyboard.h
+ *
+ * Created
+ */
+
+/*
+ * This file contains the Q40 specific keyboard definitions
+ */
+
+
+#include <linux/config.h> /* CONFIG_MAGIC_SYSRQ */
+
+
+
+#ifdef __KERNEL__
+
+
+#include <asm/machdep.h>
+
+
+
+extern int q40kbd_setkeycode(unsigned int scancode, unsigned int keycode);
+extern int q40kbd_getkeycode(unsigned int scancode);
+extern int q40kbd_pretranslate(unsigned char scancode, char raw_mode);
+extern int q40kbd_translate(unsigned char scancode, unsigned char *keycode,
+ char raw_mode);
+extern char q40kbd_unexpected_up(unsigned char keycode);
+extern void q40kbd_leds(unsigned char leds);
+extern int q40kbd_is_sysrq(unsigned char keycode);
+extern void q40kbd_init_hw(void);
+extern unsigned char q40kbd_sysrq_xlate[128];
+
+
+#if 0
+#define kbd_setkeycode q40kbd_setkeycode
+#define kbd_getkeycode q40kbd_getkeycode
+#define kbd_pretranslate q40kbd_pretranslate
+#define kbd_translate q40kbd_translate
+#define kbd_unexpected_up q40kbd_unexpected_up
+#define kbd_leds q40kbd_leds
+#define kbd_init_hw q40kbd_init_hw
+#define kbd_is_sysrq q40kbd_is_sysrq
+#define kbd_sysrq_xlate q40kbd_sysrq_xlate
+
+
+#define SYSRQ_KEY 0x54
+#endif
+#endif /* __KERNEL__ */
+
+
+
+
+
diff -u --recursive --new-file v2.2.7/linux/include/asm-m68k/q40_master.h linux/include/asm-m68k/q40_master.h
--- v2.2.7/linux/include/asm-m68k/q40_master.h Wed Dec 31 16:00:00 1969
+++ linux/include/asm-m68k/q40_master.h Tue May 11 09:57:14 1999
@@ -0,0 +1,75 @@
+/*
+ * Q40 master Chip Control
+ * RTC stuff merged for compactnes..
+*/
+
+#if 1
+#define q40_master_addr 0xff000000
+#define q40_rtc_addr 0xff021ffc
+#else
+extern unsigned long q40_master_addr; /* wherever it is mapped ... */
+extern unsigned long q40_rtc_addr;
+#endif
+
+#define IIRQ_REG 0x0 /* internal IRQ reg */
+#define EIRQ_REG 0x4 /* external ... */
+#define KEYCODE_REG 0x1c /* value of received scancode */
+#define DISPLAY_CONTROL_REG 0x18
+#define FRAME_CLEAR_REG 0x24
+
+#define INTERRUPT_REG IIRQ_REG /* "native" ints */
+#define KEY_IRQ_ENABLE_REG 0x08 /**/
+#define KEYBOARD_UNLOCK_REG 0x20 /* clear kb int */
+
+#define SAMPLE_ENABLE_REG 0x14 /* generate SAMPLE ints */
+#define SAMPLE_RATE_REG 0x28
+#define SAMPLE_CLEAR_REG 0x28
+#define SAMPLE_LOW 0x00
+#define SAMPLE_HIGH 0x01
+
+#define FRAME_RATE_REG 0x38 /* generate FRAME ints at 200 HZ rate */
+
+#if 0
+#define SER_ENABLE_REG 0x0c /* allow serial ints to be generated */
+#endif
+#define EXT_ENABLE_REG 0x10 /* ... rest of the ISA ints ... */
+
+#define master_inb(_reg_) (*(((unsigned char *)q40_master_addr)+_reg_))
+#define master_outb(_b_,_reg_) (*(((unsigned char *)q40_master_addr)+_reg_)=(_b_))
+
+
+/* define some Q40 specific ints */
+#include "q40ints.h"
+
+/* RTC defines */
+
+#define Q40_RTC_BASE (q40_rtc_addr)
+
+#define RTC_YEAR (*(unsigned char *)(Q40_RTC_BASE+0))
+#define RTC_MNTH (*(unsigned char *)(Q40_RTC_BASE-4))
+#define RTC_DATE (*(unsigned char *)(Q40_RTC_BASE-8))
+#define RTC_DOW (*(unsigned char *)(Q40_RTC_BASE-12))
+#define RTC_HOUR (*(unsigned char *)(Q40_RTC_BASE-16))
+#define RTC_MINS (*(unsigned char *)(Q40_RTC_BASE-20))
+#define RTC_SECS (*(unsigned char *)(Q40_RTC_BASE-24))
+#define RTC_CTRL (*(unsigned char *)(Q40_RTC_BASE-28))
+
+
+#if 0
+struct RTC_STRUCT{
+ unsigned char bcd_year;
+ unsigned char bcd_mth;
+ unsigned char bcd_dom;
+ unsigned char bcd_dayofweek;
+ unsigned char bcd_hr;
+ unsigned char bcd_min;
+ unsigned char bcd_sec;
+ unsigned char ctrl;
+};
+typedef struct RTC_STRUCT *RtcPtr_t;
+#endif
+
+
+/* some control bits */
+#define RTC_READ 64 /* prepare for reading */
+#define RTC_WRITE 128
diff -u --recursive --new-file v2.2.7/linux/include/asm-m68k/q40ints.h linux/include/asm-m68k/q40ints.h
--- v2.2.7/linux/include/asm-m68k/q40ints.h Wed Dec 31 16:00:00 1969
+++ linux/include/asm-m68k/q40ints.h Tue May 11 09:57:14 1999
@@ -0,0 +1,29 @@
+/*
+ * contains some Q40 related interrupt definitions
+ */
+
+#define Q40_IRQ_MAX (34)
+
+#define Q40_IRQ_TIMER (34)
+#define Q40_IRQ_KEYBOARD (32)
+#define Q40_IRQ_FRAME (33)
+
+
+/* masks for interrupt regiosters*/
+/* internal, IIRQ_REG */
+#define IRQ_KEYB_MASK (2)
+#define IRQ_SER_MASK (1<<2)
+#define IRQ_FRAME_MASK (1<<3)
+#define IRQ_EXT_MASK (1<<4) /* is a EIRQ */
+/* eirq, EIRQ_REG */
+#define IRQ3_MASK (1)
+#define IRQ4_MASK (1<<1)
+#define IRQ5_MASK (1<<2)
+#define IRQ6_MASK (1<<3)
+#define IRQ7_MASK (1<<4)
+#define IRQ10_MASK (1<<5)
+#define IRQ14_MASK (1<<6)
+#define IRQ15_MASK (1<<7)
+
+extern unsigned long q40_probe_irq_on (void);
+extern int q40_probe_irq_off (unsigned long irqs);
diff -u --recursive --new-file v2.2.7/linux/include/asm-m68k/scatterlist.h linux/include/asm-m68k/scatterlist.h
--- v2.2.7/linux/include/asm-m68k/scatterlist.h Wed Apr 23 19:01:27 1997
+++ linux/include/asm-m68k/scatterlist.h Tue May 11 09:57:14 1999
@@ -6,6 +6,14 @@
X char * alt_address; /* Location of actual if address is a
X * dma indirect buffer. NULL otherwise */
X unsigned int length;
+ unsigned long dvma_address;
+};
+
+struct mmu_sglist {
+ char *addr;
+ char *__dont_touch;
+ unsigned int len;
+ unsigned long dvma_addr;
X };
X
X /* This is bogus and should go away. */
diff -u --recursive --new-file v2.2.7/linux/include/asm-m68k/semaphore-helper.h linux/include/asm-m68k/semaphore-helper.h
--- v2.2.7/linux/include/asm-m68k/semaphore-helper.h Wed Dec 31 16:00:00 1969
+++ linux/include/asm-m68k/semaphore-helper.h Tue May 11 09:57:14 1999
@@ -0,0 +1,136 @@
+#ifndef _M68K_SEMAPHORE_HELPER_H
+#define _M68K_SEMAPHORE_HELPER_H
+
+/*
+ * SMP- and interrupt-safe semaphores helper functions.
+ *
+ * (C) Copyright 1996 Linus Torvalds
+ *
+ * m68k version by Andreas Schwab
+ */


+
+/*
+ * These two _must_ execute atomically wrt each other.
+ */
+static inline void wake_one_more(struct semaphore * sem)
+{

+ atomic_inc(&sem->waking);


+}
+
+static inline int waking_non_zero(struct semaphore *sem)
+{

+ int ret;
+#ifndef CONFIG_RMW_INSNS


+ unsigned long flags;
+
+ spin_lock_irqsave(&semaphore_wake_lock, flags);

+ ret = 0;
+ if (atomic_read(&sem->waking) > 0) {
+ atomic_dec(&sem->waking);


+ ret = 1;
+ }
+ spin_unlock_irqrestore(&semaphore_wake_lock, flags);

+#else
+ int tmp1, tmp2;
+
+ __asm__ __volatile__
+ ("1: movel %1,%2\n"
+ " jle 2f\n"
+ " subql #1,%2\n"
+ " casl %1,%2,%3\n"
+ " jne 1b\n"
+ " moveq #1,%0\n"
+ "2:"
+ : "=d" (ret), "=d" (tmp1), "=d" (tmp2)
+ : "m" (sem->waking), "0" (0), "1" (sem->waking));
+#endif
+


+ return ret;
+}
+
+/*

+ * waking_non_zero_interruptible:


+ * 1 got the lock
+ * 0 go to sleep
+ * -EINTR interrupted

+ */
+static inline int waking_non_zero_interruptible(struct semaphore *sem,
+ struct task_struct *tsk)
+{

+ int ret;
+#ifndef CONFIG_RMW_INSNS


+ unsigned long flags;
+
+ spin_lock_irqsave(&semaphore_wake_lock, flags);

+ ret = 0;
+ if (atomic_read(&sem->waking) > 0) {
+ atomic_dec(&sem->waking);


+ ret = 1;
+ } else if (signal_pending(tsk)) {
+ atomic_inc(&sem->count);
+ ret = -EINTR;
+ }
+ spin_unlock_irqrestore(&semaphore_wake_lock, flags);

+#else
+ int tmp1, tmp2;
+
+ __asm__ __volatile__
+ ("1: movel %1,%2\n"
+ " jle 2f\n"
+ " subql #1,%2\n"
+ " casl %1,%2,%3\n"
+ " jne 1b\n"
+ " moveq #1,%0\n"
+ " jra %a4\n"
+ "2:"
+ : "=d" (ret), "=d" (tmp1), "=d" (tmp2)
+ : "m" (sem->waking), "i" (&&next), "0" (0), "1" (sem->waking));
+ if (signal_pending(tsk)) {


+ atomic_inc(&sem->count);
+ ret = -EINTR;
+ }

+next:
+#endif
+


+ return ret;
+}
+
+/*

+ * waking_non_zero_trylock:


+ * 1 failed to lock
+ * 0 got the lock

+ */
+static inline int waking_non_zero_trylock(struct semaphore *sem)
+{

+ int ret;
+#ifndef CONFIG_RMW_INSNS


+ unsigned long flags;
+
+ spin_lock_irqsave(&semaphore_wake_lock, flags);

+ ret = 1;
+ if (atomic_read(&sem->waking) > 0) {
+ atomic_dec(&sem->waking);
+ ret = 0;
+ } else
+ atomic_inc(&sem->count);
+ spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+#else
+ int tmp1, tmp2;
+
+ __asm__ __volatile__
+ ("1: movel %1,%2\n"
+ " jle 2f\n"
+ " subql #1,%2\n"
+ " casl %1,%2,%3\n"
+ " jne 1b\n"
+ " moveq #0,%0\n"
+ "2:"
+ : "=d" (ret), "=d" (tmp1), "=d" (tmp2)
+ : "m" (sem->waking), "0" (1), "1" (sem->waking));
+ if (ret)
+ atomic_inc(&sem->count);
+#endif


+ return ret;
+}
+
+#endif

diff -u --recursive --new-file v2.2.7/linux/include/asm-m68k/semaphore.h linux/include/asm-m68k/semaphore.h
--- v2.2.7/linux/include/asm-m68k/semaphore.h Wed Jan 20 23:14:06 1999
+++ linux/include/asm-m68k/semaphore.h Tue May 11 09:57:14 1999
@@ -3,9 +3,10 @@
X
X #include <linux/config.h>
X #include <linux/linkage.h>
-#include <asm/current.h>
+
X #include <asm/system.h>
X #include <asm/atomic.h>
+#include <asm/spinlock.h>
X
X /*
X * SMP- and interrupt-safe semaphores..


@@ -17,79 +18,25 @@
X

X struct semaphore {
X atomic_t count;
- unsigned long owner, owner_depth;
X atomic_t waking;
X struct wait_queue * wait;
X };
X
-/*
- * Because we want the non-contention case to be
- * fast, we save the stack pointer into the "owner"
- * field, and to get the true task pointer we have
- * to do the bit masking. That moves the masking
- * operation into the slow path.
- */
-#define semaphore_owner(sem) \
- ((struct task_struct *)((2*PAGE_MASK) & (sem)->owner))
-
-#define MUTEX ((struct semaphore) { ATOMIC_INIT(1), 0, 0, ATOMIC_INIT(0), NULL })
-#define MUTEX_LOCKED ((struct semaphore) { ATOMIC_INIT(0), 0, 1, ATOMIC_INIT(0), NULL })
+#define MUTEX ((struct semaphore) { ATOMIC_INIT(1), ATOMIC_INIT(0), NULL })
+#define MUTEX_LOCKED ((struct semaphore) { ATOMIC_INIT(0), ATOMIC_INIT(0), NULL })
X
X asmlinkage void __down_failed(void /* special register calling convention */);
X asmlinkage int __down_failed_interruptible(void /* params in registers */);


+asmlinkage int __down_failed_trylock(void /* params in registers */);

X asmlinkage void __up_wakeup(void /* special register calling convention */);
X
-extern void __down(struct semaphore * sem);
-extern int __down_interruptible(struct semaphore * sem);
-extern void __up(struct semaphore * sem);
+asmlinkage void __down(struct semaphore * sem);
+asmlinkage int __down_interruptible(struct semaphore * sem);
+asmlinkage int __down_trylock(struct semaphore * sem);
+asmlinkage void __up(struct semaphore * sem);
X
X #define sema_init(sem, val) atomic_set(&((sem)->count), val)
X

-static inline void wake_one_more(struct semaphore * sem)
-{

- atomic_inc(&sem->waking);


-}
-
-static inline int waking_non_zero(struct semaphore *sem, struct task_struct *tsk)
-{

-#ifndef CONFIG_RMW_INSNS


- unsigned long flags;
- int ret = 0;
-
- save_flags(flags);
- cli();

- if (atomic_read(&sem->waking) > 0 || (owner_depth && semaphore_owner(sem) == tsk)) {
- sem->owner = (unsigned long)tsk;
- sem->owner_depth++;
- atomic_dec(&sem->waking);


- ret = 1;
- }
- restore_flags(flags);

-#else
- int ret, tmp;
-
- __asm__ __volatile__
- ("1: movel %2,%0\n"
- " jeq 3f\n"
- "2: movel %0,%1\n"
- " subql #1,%1\n"
- " casl %0,%1,%2\n"
- " jeq 3f\n"
- " tstl %0\n"
- " jne 2b\n"
- "3:"
- : "=d" (ret), "=d" (tmp), "=m" (sem->waking));
-
- ret |= ((sem->owner_depth != 0) && (semaphore_owner(sem) == tsk));
- if (ret) {
- sem->owner = (unsigned long)tsk;
- sem->owner_depth++;
- }
-
-#endif
- return ret;
-}
-
X /*
X * This is ugly, but we want the default case to fall through.
X * "down_failed" is a special asm handler that calls the C
@@ -102,8 +49,6 @@
X "| atomic down operation\n\t"
X "subql #1,%0@\n\t"
X "jmi 2f\n\t"
- "movel %%sp,4(%0)\n"
- "movel #1,8(%0)\n\t"
X "1:\n"
X ".section .text.lock,\"ax\"\n"
X ".even\n"
@@ -124,9 +69,6 @@
X "| atomic interruptible down operation\n\t"
X "subql #1,%1@\n\t"
X "jmi 2f\n\t"
- "movel %%sp,4(%1)\n"
- "moveql #1,%0\n"
- "movel %0,8(%1)\n"
X "clrl %0\n"
X "1:\n"
X ".section .text.lock,\"ax\"\n"
@@ -140,6 +82,28 @@
X return result;


X }
X
+extern inline int down_trylock(struct semaphore * sem)
+{

+ register struct semaphore *sem1 __asm__ ("%a1") = sem;
+ register int result __asm__ ("%d0");
+
+ __asm__ __volatile__(
+ "| atomic down trylock operation\n\t"
+ "subql #1,%1@\n\t"
+ "jmi 2f\n\t"
+ "clrl %0\n"
+ "1:\n"
+ ".section .text.lock,\"ax\"\n"
+ ".even\n"
+ "2:\tpea 1b\n\t"
+ "jbra __down_failed_trylock\n"
+ ".previous"
+ : "=d" (result)
+ : "a" (sem1)
+ : "%d0", "memory");
+ return result;


+}
+
X /*
X * Note! This is subtle. We jump to wake people up only if
X * the semaphore was negative (== somebody was waiting on it).

@@ -151,13 +115,13 @@
X register struct semaphore *sem1 __asm__ ("%a1") = sem;
X __asm__ __volatile__(
X "| atomic up operation\n\t"
- "subql #1,8(%0)\n\t"
X "addql #1,%0@\n\t"
X "jle 2f\n"
X "1:\n"
X ".section .text.lock,\"ax\"\n"
X ".even\n"
- "2:\tpea 1b\n\t"
+ "2:\t"
+ "pea 1b\n\t"
X "jbra __up_wakeup\n"
X ".previous"
X : /* no outputs */
diff -u --recursive --new-file v2.2.7/linux/include/asm-m68k/serial.h linux/include/asm-m68k/serial.h
--- v2.2.7/linux/include/asm-m68k/serial.h Thu Nov 12 16:21:24 1998
+++ linux/include/asm-m68k/serial.h Tue May 11 09:57:14 1999
@@ -1,448 +1,84 @@
X /*
- * include/linux/serial.h
+ * include/asm-m68k/serial.h
X *
- * Copyright (C) 1992 by Theodore Ts'o.
- *
- * Redistribution of this file is permitted under the terms of the GNU
- * Public License (GPL)
- */
-
-#ifndef _M68K_SERIAL_H
-#define _M68K_SERIAL_H
-
-
-/* m68k serial port types are numbered from 100 to avoid interference
- * with the PC types (1..4)
- */
-#define PORT_UNKNOWN 0
-#define PORT_8250 1
-#define PORT_16450 2
-#define PORT_16550 3
-#define PORT_16550A 4
-#define PORT_CIRRUS 5
-#define PORT_16650V2 7
-#define PORT_16750 8
-
-#define SER_SCC_NORM 100 /* standard SCC channel */
-#define SER_SCC_DMA 101 /* SCC channel with DMA support */
-#define SER_MFP_CTRL 102 /* standard MFP port with modem control signals */
-#define SER_MFP_BARE 103 /* MFP port without modem controls */
-#define SER_MIDI 104 /* Atari MIDI */
-#define SER_AMIGA 105 /* Amiga built-in serial port */
-#define SER_IOEXT 106 /* Amiga GVP IO-Extender (16c552) */
-#define SER_MFC_III 107 /* Amiga BSC Multiface Card III (MC68681) */
-#define SER_WHIPPET 108 /* Amiga Hisoft Whippet PCMCIA (16c550B) */
-#define SER_SCC_MVME 109 /* MVME162/MVME172 ports */
-#define SER_SCC_MAC 110 /* Macintosh SCC channel */
-#define SER_HPDCA 111 /* HP DCA serial */
-#define SER_SCC_BVME 112 /* BVME6000 ports */
-
-struct serial_struct {
- int type;
- int line;
- int port;
- int irq;
- int flags;
- int xmit_fifo_size;
- int custom_divisor;
- int baud_base;
- unsigned short close_delay;
- char reserved_char[2];
- int hub6;
- unsigned short closing_wait; /* time to wait before closing */
- unsigned short closing_wait2; /* no longer used... */
- int reserved[4];
-};
-
-/*
- * For the close wait times, 0 means wait forever for serial port to
- * flush its output. 65535 means don't wait at all.
- */
-#define ASYNC_CLOSING_WAIT_INF 0
-#define ASYNC_CLOSING_WAIT_NONE 65535
-
-/* This function tables does the abstraction from the underlying
- * hardware:
+ * currently this seems usefull only for a Q40,
+ * its an almost exact copy of ../asm/alpha/serial.h
X *
- * init(): Initialize the port as necessary, set RTS and DTR and
- * enable interrupts. It does not need to set the speed and other
- * parameters, because change_speed() is called, too.
- * deinit(): Stop and shutdown the port (e.g. disable interrupts, ...)
- * enab_tx_int(): Enable or disable the Tx Buffer Empty interrupt
- * independently from other interrupt sources. If the int is
- * enabled, the transmitter should also be restarted, i.e. if there
- * are any chars to be sent, they should be put into the Tx
- * register. The real en/disabling of the interrupt may be a no-op
- * if there is no way to do this or it is too complex. This Tx ints
- * are just disabled to save some interrupts if the transmitter is
- * stopped anyway. But the restarting must be implemented!
- * check_custom_divisor(): Check the given custom divisor for legality
- * and return 0 if OK, non-zero otherwise.
- * change_speed(): Set port speed, character size, number of stop
- * bits and parity from the termios structure. If the user wants
- * to set the speed with a custom divisor, he is required to
- * check the baud_base first!
- * throttle(): Set or clear the RTS line according to 'status'.
- * set_break(): Set or clear the 'Send a Break' flag.
- * get_serial_info(): Fill in the baud_base and custom_divisor
- * fields of a serial_struct. It may also modify other fields, if
- * needed.
- * get_modem_info(): Return the status of RTS, DTR, DCD, RI, DSR and CTS.
- * set_modem_info(): Set the status of RTS and DTR according to
- * 'new_dtr' and 'new_rts', resp. 0 = clear, 1 = set, -1 = don't change
- * ioctl(): Process any port-specific ioctl's. This pointer may be
- * NULL, if the port has no own ioctl's.
- * stop_receive(): Turn off the Rx part of the port, so no more characters
- * will be received. This is called before shutting the port down.
- * trans_empty(): Return !=0 if there are no more characters still to be
- * sent out (Tx buffer register and FIFOs empty)
- * check_open(): Is called before the port is opened. The driver can check
- * if that's ok and return an error code, or keep track of the opening
- * even before init() is called. Use deinit() for matching closing of the
- * port.


- *
- */
-

-struct m68k_async_struct;
-
-typedef struct {
- void (*init)( struct m68k_async_struct *info );
- void (*deinit)( struct m68k_async_struct *info, int leave_dtr );
- void (*enab_tx_int)( struct m68k_async_struct *info, int enab_flag );
- int (*check_custom_divisor)( struct m68k_async_struct *info, int baud_base,
- int divisor );
- void (*change_speed)( struct m68k_async_struct *info );
- void (*throttle)( struct m68k_async_struct *info, int status );
- void (*set_break)( struct m68k_async_struct *info, int break_flag );
- void (*get_serial_info)( struct m68k_async_struct *info,
- struct serial_struct *retinfo );
- unsigned int (*get_modem_info)( struct m68k_async_struct *info );
- int (*set_modem_info)( struct m68k_async_struct *info, int new_dtr,
- int new_rts );
- int (*ioctl)( struct tty_struct *tty, struct file *file,
- struct m68k_async_struct *info, unsigned int cmd,
- unsigned long arg );
- void (*stop_receive)( struct m68k_async_struct *info );
- int (*trans_empty)( struct m68k_async_struct *info );
- int (*check_open)( struct m68k_async_struct *info, struct tty_struct *tty,
- struct file *file );
-} SERIALSWITCH;
-
-/*
- * Definitions for m68k_async_struct (and serial_struct) flags field
X */
-#define ASYNC_HUP_NOTIFY 0x0001 /* Notify getty on hangups and closes
- on the callout port */
-#define ASYNC_FOURPORT 0x0002 /* Set OU1, OUT2 per AST Fourport settings */
-#define ASYNC_SAK 0x0004 /* Secure Attention Key (Orange book) */
-#define ASYNC_SPLIT_TERMIOS 0x0008 /* Separate termios for dialin/callout */
-
-#define ASYNC_SPD_MASK 0x1030
-#define ASYNC_SPD_HI 0x0010 /* Use 56000 instead of 38400 bps */
-
-#define ASYNC_SPD_VHI 0x0020 /* Use 115200 instead of 38400 bps */
-#define ASYNC_SPD_CUST 0x0030 /* Use user-specified divisor */
-
-#define ASYNC_SKIP_TEST 0x0040 /* Skip UART test during autoconfiguration */
-#define ASYNC_AUTO_IRQ 0x0080 /* Do automatic IRQ during autoconfiguration */
-#define ASYNC_SESSION_LOCKOUT 0x0100 /* Lock out cua opens based on session */
-#define ASYNC_PGRP_LOCKOUT 0x0200 /* Lock out cua opens based on pgrp */
-#define ASYNC_CALLOUT_NOHUP 0x0400 /* Don't do hangups for cua device */
-
-#define ASYNC_HARDPPS_CD 0x0800 /* Call hardpps when CD goes high */
-
-#define ASYNC_SPD_SHI 0x1000 /* Use 230400 instead of 38400 bps */
-#define ASYNC_SPD_WARP 0x1010 /* Use 460800 instead of 38400 bps */
-
-#define ASYNC_FLAGS 0x1FFF /* Possible legal async flags */
-#define ASYNC_USR_MASK 0x1430 /* Legal flags that non-privileged
- * users can set or reset */
-
-/* Internal flags used only by drivers/char/m68kserial.c */
-#define ASYNC_INITIALIZED 0x80000000 /* Serial port was initialized */
-#define ASYNC_CALLOUT_ACTIVE 0x40000000 /* Call out device is active */
-#define ASYNC_NORMAL_ACTIVE 0x20000000 /* Normal device is active */
-#define ASYNC_BOOT_AUTOCONF 0x10000000 /* Autoconfigure port on bootup */
-#define ASYNC_CLOSING 0x08000000 /* Serial port is closing */
-#define ASYNC_CTS_FLOW 0x04000000 /* Do CTS flow control */
-#define ASYNC_CHECK_CD 0x02000000 /* i.e., CLOCAL */
-
-#define ASYNC_INTERNAL_FLAGS 0xFF000000 /* Internal flags */
-
-/*
- * Serial input interrupt line counters -- external structure
- * Four lines can interrupt: CTS, DSR, RI, DCD
- */
-struct serial_icounter_struct {
- int cts, dsr, rng, dcd;
- int rx, tx;
- int frame, overrun, parity, brk;
- int buf_overrun;
- int reserved[9];
-};
X
+#include <linux/config.h>
+#if 0
+#define rs_init serial_rs_init
+#define register_serial serial_register_serial
+#define unregister_serial serial_unregister_serial
+#endif
X
-#ifdef __KERNEL__
X /*
- * This is our internal structure for each serial port's state.
- *
- * Many fields are paralleled by the structure used by the serial_struct
- * structure.
+ * This assumes you have a 1.8432 MHz clock for your UART.
X *
- * For definitions of the flags field, see tty.h
- */
-
-#include <linux/termios.h>
-#include <linux/tqueue.h>
-
-#include <linux/config.h> /* for Mac SCC extensions */
-
-#ifdef CONFIG_MAC
-#define NUM_ZSREGS 16
-struct mac_zschannel {
- volatile unsigned char *control;
- volatile unsigned char *data;
-};
-struct m68k_async_private;
-#endif
-
-struct m68k_async_struct {
- int magic;
- int baud_base;
- int port;
- int irq;
- int flags; /* defined in tty.h */
- int hub6; /* HUB6 plus one */
- int type;
- struct tty_struct *tty;
- int read_status_mask;
- int ignore_status_mask;
- int timeout;
- int xmit_fifo_size;
- int custom_divisor;
- int x_char; /* xon/xoff character */
- int close_delay;
- unsigned short closing_wait;
- unsigned short closing_wait2;
- int IER; /* Interrupt Enable Register */
- int MCR; /* Modem control register */
- int MCR_noint; /* MCR with interrupts off */
- unsigned long event;
- unsigned long last_active;
- int line;
- int count; /* # of fd on device */
- int blocked_open; /* # of blocked opens */
- long session; /* Session of opening process */
- long pgrp; /* pgrp of opening process */
- unsigned char *xmit_buf;
- int xmit_head;
- int xmit_tail;
- int xmit_cnt;
- struct tq_struct tqueue;
- struct termios normal_termios;
- struct termios callout_termios;
- struct wait_queue *open_wait;
- struct wait_queue *close_wait;
- struct wait_queue *delta_msr_wait;
- struct async_icount icount; /* kernel counters for the 4 input interrupts */
- struct m68k_async_struct *next_port; /* For the linked list */
- struct m68k_async_struct *prev_port;
- void *board_base; /* board-base address for use with
- boards carrying several UART's,
- like some Amiga boards. */
- unsigned short nr_uarts; /* UART-counter, that indicates
- how many UART's there are on
- the board. If the board has a
- IRQ-register, this can be used
- to check if any of the uarts,
- on the board has requested an
- interrupt, instead of checking
- IRQ-registers on all UART's */
- SERIALSWITCH *sw; /* functions to manage this port */
-#ifdef CONFIG_MAC
- struct m68k_async_private *private;
+ * It'd be nice if someone built a serial card with a 24.576 MHz
+ * clock, since the 16550A is capable of handling a top speed of 1.5
+ * megabits/second; but this requires the faster clock.
+ */
+#define BASE_BAUD ( 1843200 / 16 )
+
+/* Standard COM flags (except for COM4, because of the 8514 problem) */
+#ifdef CONFIG_SERIAL_DETECT_IRQ
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ)
+#define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_AUTO_IRQ)
+#else
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
+#define STD_COM4_FLAGS ASYNC_BOOT_AUTOCONF
X #endif
-};
-
-#ifdef CONFIG_MAC
-struct m68k_async_private {
- struct m68k_async_info *zs_next; /* For IRQ servicing chain */
- struct mac_zschannel *zs_channel; /* Channel registers */
- struct mac_zschannel *zs_chan_a; /* A side registers */
- unsigned char read_reg_zero;
-
- char soft_carrier; /* Use soft carrier on this */
- char break_abort; /* console, process brk/abrt */
- char kgdb_channel; /* Kgdb running on this channel */
- char is_cons; /* Is this our console. */
- unsigned char tx_active; /* character being xmitted */
- unsigned char tx_stopped; /* output is suspended */
-
- /* We need to know the current clock divisor
- * to read the bps rate the chip has currently
- * loaded.
- */
- unsigned char clk_divisor; /* May be 1, 16, 32, or 64 */
- int zs_baud;
-
- /* Current write register values */
- unsigned char curregs[NUM_ZSREGS];
-
- /* Values we need to set next opportunity */
- unsigned char pendregs[NUM_ZSREGS];
-
- char change_needed;
-};
-#endif
-#define SERIAL_MAGIC 0x5301
-
-/*
- * The size of the serial xmit buffer is 1 page, or 4096 bytes
- */
-#define SERIAL_XMIT_SIZE 4096
-
-/*
- * Events are used to schedule things to happen at timer-interrupt
- * time, instead of at rs interrupt time.
- */
-#define RS_EVENT_WRITE_WAKEUP 0
-
-/* number of characters left in xmit buffer before we ask for more */
-#define WAKEUP_CHARS 256
-
-/* Export to allow PCMCIA to use this - Dave Hinds */
-extern int register_serial(struct serial_struct *req);
-extern void unregister_serial(int line);
-extern struct m68k_async_struct rs_table[];
-extern task_queue tq_serial;
-
X
-/*
- * This routine is used by the interrupt handler to schedule
- * processing in the software interrupt portion of the driver.
- */
-static __inline__ void rs_sched_event(struct m68k_async_struct *info, int event)
-{
- info->event |= 1 << event;
- queue_task(&info->tqueue, &tq_serial);
- mark_bh(SERIAL_BH);
-}
-
-static __inline__ void rs_receive_char( struct m68k_async_struct *info,
- int ch, int err )
-{
- struct tty_struct *tty = info->tty;
-
- if (tty->flip.count >= TTY_FLIPBUF_SIZE)
- return;
- tty->flip.count++;
- switch(err) {
- case TTY_BREAK:
- info->icount.brk++;
- if (info->flags & ASYNC_SAK)
- do_SAK(tty);
- break;
- case TTY_PARITY:
- info->icount.parity++;
- break;
- case TTY_OVERRUN:
- info->icount.overrun++;
- break;
- case TTY_FRAME:
- info->icount.frame++;
- break;
- }
- *tty->flip.flag_buf_ptr++ = err;
- *tty->flip.char_buf_ptr++ = ch;
- info->icount.rx++;
- tty_flip_buffer_push(tty);
-}
-
-static __inline__ int rs_get_tx_char( struct m68k_async_struct *info )
-{
- unsigned char ch;
-
- if (info->x_char) {
- ch = info->x_char;
- info->icount.tx++;
- info->x_char = 0;
- return( ch );
- }
-
- if (info->xmit_cnt <= 0 || info->tty->stopped || info->tty->hw_stopped)
- return( -1 );
-
- ch = info->xmit_buf[info->xmit_tail++];
- info->xmit_tail &= SERIAL_XMIT_SIZE - 1;
- info->icount.tx++;
- if (--info->xmit_cnt < WAKEUP_CHARS)
- rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);
- return( ch );
-}
-
-static __inline__ int rs_no_more_tx( struct m68k_async_struct *info )
-{
- return( info->xmit_cnt <= 0 ||
- info->tty->stopped ||
- info->tty->hw_stopped );
-}
-
-static __inline__ void rs_dcd_changed( struct m68k_async_struct *info, int dcd )
-
-{
- /* update input line counter */
- info->icount.dcd++;
- wake_up_interruptible(&info->delta_msr_wait);
-
- if (info->flags & ASYNC_CHECK_CD) {
-#if (defined(SERIAL_DEBUG_OPEN) || defined(SERIAL_DEBUG_INTR))
- printk("ttyS%d CD now %s...", info->line,
- dcd ? "on" : "off");
-#endif
- if (dcd) {
- wake_up_interruptible(&info->open_wait);
- } else if (!((info->flags & ASYNC_CALLOUT_ACTIVE) &&
- (info->flags & ASYNC_CALLOUT_NOHUP))) {
-#ifdef SERIAL_DEBUG_OPEN
- printk("scheduling hangup...");
+#ifdef CONFIG_SERIAL_MANY_PORTS
+#define FOURPORT_FLAGS ASYNC_FOURPORT
+#define ACCENT_FLAGS 0
+#define BOCA_FLAGS 0
X #endif
- if (info->tty)
- tty_hangup(info->tty);


- }
- }
-}
-
-

-void rs_stop( struct tty_struct *tty );
-void rs_start( struct tty_struct *tty );
-
-static __inline__ void rs_check_cts( struct m68k_async_struct *info, int cts )
-{
- /* update input line counter */
- info->icount.cts++;
- wake_up_interruptible(&info->delta_msr_wait);
X
- if ((info->flags & ASYNC_CTS_FLOW) && info->tty) {
- if (info->tty->hw_stopped) {
- if (cts) {
-#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
- printk("CTS tx start...");
+#define STD_SERIAL_PORT_DEFNS \
+ /* UART CLK PORT IRQ FLAGS */ \
+ { 0, BASE_BAUD, 0x3F8, 4, STD_COM_FLAGS }, /* ttyS0 */ \
+ { 0, BASE_BAUD, 0x2F8, 3, STD_COM_FLAGS }, /* ttyS1 */ \
+ { 0, BASE_BAUD, 0x3E8, 4, STD_COM_FLAGS }, /* ttyS2 */ \
+ { 0, BASE_BAUD, 0x2E8, 3, STD_COM4_FLAGS }, /* ttyS3 */
+
+
+#ifdef CONFIG_SERIAL_MANY_PORTS
+#define EXTRA_SERIAL_PORT_DEFNS \
+ { 0, BASE_BAUD, 0x1A0, 9, FOURPORT_FLAGS }, /* ttyS4 */ \
+ { 0, BASE_BAUD, 0x1A8, 9, FOURPORT_FLAGS }, /* ttyS5 */ \
+ { 0, BASE_BAUD, 0x1B0, 9, FOURPORT_FLAGS }, /* ttyS6 */ \
+ { 0, BASE_BAUD, 0x1B8, 9, FOURPORT_FLAGS }, /* ttyS7 */ \
+ { 0, BASE_BAUD, 0x2A0, 5, FOURPORT_FLAGS }, /* ttyS8 */ \
+ { 0, BASE_BAUD, 0x2A8, 5, FOURPORT_FLAGS }, /* ttyS9 */ \
+ { 0, BASE_BAUD, 0x2B0, 5, FOURPORT_FLAGS }, /* ttyS10 */ \
+ { 0, BASE_BAUD, 0x2B8, 5, FOURPORT_FLAGS }, /* ttyS11 */ \
+ { 0, BASE_BAUD, 0x330, 4, ACCENT_FLAGS }, /* ttyS12 */ \
+ { 0, BASE_BAUD, 0x338, 4, ACCENT_FLAGS }, /* ttyS13 */ \
+ { 0, BASE_BAUD, 0x000, 0, 0 }, /* ttyS14 (spare) */ \
+ { 0, BASE_BAUD, 0x000, 0, 0 }, /* ttyS15 (spare) */ \
+ { 0, BASE_BAUD, 0x100, 12, BOCA_FLAGS }, /* ttyS16 */ \
+ { 0, BASE_BAUD, 0x108, 12, BOCA_FLAGS }, /* ttyS17 */ \
+ { 0, BASE_BAUD, 0x110, 12, BOCA_FLAGS }, /* ttyS18 */ \
+ { 0, BASE_BAUD, 0x118, 12, BOCA_FLAGS }, /* ttyS19 */ \
+ { 0, BASE_BAUD, 0x120, 12, BOCA_FLAGS }, /* ttyS20 */ \
+ { 0, BASE_BAUD, 0x128, 12, BOCA_FLAGS }, /* ttyS21 */ \
+ { 0, BASE_BAUD, 0x130, 12, BOCA_FLAGS }, /* ttyS22 */ \
+ { 0, BASE_BAUD, 0x138, 12, BOCA_FLAGS }, /* ttyS23 */ \
+ { 0, BASE_BAUD, 0x140, 12, BOCA_FLAGS }, /* ttyS24 */ \
+ { 0, BASE_BAUD, 0x148, 12, BOCA_FLAGS }, /* ttyS25 */ \
+ { 0, BASE_BAUD, 0x150, 12, BOCA_FLAGS }, /* ttyS26 */ \
+ { 0, BASE_BAUD, 0x158, 12, BOCA_FLAGS }, /* ttyS27 */ \
+ { 0, BASE_BAUD, 0x160, 12, BOCA_FLAGS }, /* ttyS28 */ \
+ { 0, BASE_BAUD, 0x168, 12, BOCA_FLAGS }, /* ttyS29 */ \
+ { 0, BASE_BAUD, 0x170, 12, BOCA_FLAGS }, /* ttyS30 */ \
+ { 0, BASE_BAUD, 0x178, 12, BOCA_FLAGS }, /* ttyS31 */
+#else
+#define EXTRA_SERIAL_PORT_DEFNS
X #endif
- info->tty->hw_stopped = 0;
- rs_start( info->tty );
- rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);


- return;
- }
- } else {

- if (!cts) {
- info->tty->hw_stopped = 1;
- rs_stop( info->tty );


- }
- }
- }
-}
-

-
-#endif /* __KERNEL__ */
X
-#endif /* _M68K_SERIAL_H */
+#define SERIAL_PORT_DFNS \
+ STD_SERIAL_PORT_DEFNS \
+ EXTRA_SERIAL_PORT_DEFNS
diff -u --recursive --new-file v2.2.7/linux/include/asm-m68k/setup.h linux/include/asm-m68k/setup.h
--- v2.2.7/linux/include/asm-m68k/setup.h Wed Jan 20 23:14:06 1999
+++ linux/include/asm-m68k/setup.h Tue May 11 09:57:14 1999
@@ -39,6 +39,8 @@
X #define MACH_MVME16x 7
X #define MACH_BVME6000 8
X #define MACH_HP300 9
+#define MACH_Q40 10
+#define MACH_SUN3X 11


X
X #ifdef __KERNEL__
X

@@ -49,7 +51,9 @@
X #if !defined(CONFIG_AMIGA)
X # define MACH_IS_AMIGA (0)
X #elif defined(CONFIG_ATARI) || defined(CONFIG_MAC) || defined(CONFIG_APOLLO) \
- || defined(CONFIG_MVME16x) || defined(CONFIG_BVME6000) || defined(CONFIG_HP300)
+ || defined(CONFIG_MVME16x) || defined(CONFIG_BVME6000) \
+ || defined(CONFIG_HP300) || defined(CONFIG_Q40) \
+ || defined(CONFIG_SUN3X) || defined(CONFIG_MVME147)
X # define MACH_IS_AMIGA (m68k_machtype == MACH_AMIGA)
X #else
X # define MACH_AMIGA_ONLY
@@ -60,7 +64,9 @@
X #if !defined(CONFIG_ATARI)
X # define MACH_IS_ATARI (0)
X #elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC) || defined(CONFIG_APOLLO) \
- || defined(CONFIG_MVME16x) || defined(CONFIG_BVME6000) || defined(CONFIG_HP300)
+ || defined(CONFIG_MVME16x) || defined(CONFIG_BVME6000) \
+ || defined(CONFIG_HP300) || defined(CONFIG_Q40) \
+ || defined(CONFIG_SUN3X) || defined(CONFIG_MVME147)
X # define MACH_IS_ATARI (m68k_machtype == MACH_ATARI)
X #else
X # define MACH_ATARI_ONLY
@@ -71,7 +77,9 @@
X #if !defined(CONFIG_MAC)
X # define MACH_IS_MAC (0)
X #elif defined(CONFIG_AMIGA) || defined(CONFIG_ATARI) || defined(CONFIG_APOLLO) \
- || defined(CONFIG_HP300) || defined(CONFIG_MVME16x) || defined(CONFIG_BVME6000)
+ || defined(CONFIG_MVME16x) || defined(CONFIG_BVME6000) \
+ || defined(CONFIG_HP300) || defined(CONFIG_Q40) \
+ || defined(CONFIG_SUN3X) || defined(CONFIG_MVME147)
X # define MACH_IS_MAC (m68k_machtype == MACH_MAC)
X #else
X # define MACH_MAC_ONLY
@@ -88,7 +96,9 @@
X #if !defined (CONFIG_APOLLO)
X # define MACH_IS_APOLLO (0)
X #elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC) || defined(CONFIG_ATARI) \
- || defined(CONFIG_MVME16x) || defined(CONFIG_BVME6000) || defined(CONFIG_HP300)
+ || defined(CONFIG_MVME16x) || defined(CONFIG_BVME6000) \
+ || defined(CONFIG_HP300) || defined(CONFIG_Q40) \
+ || defined(CONFIG_SUN3X) || defined(CONFIG_MVME147)
X # define MACH_IS_APOLLO (m68k_machtype == MACH_APOLLO)
X #else
X # define MACH_APOLLO_ONLY
@@ -96,10 +106,25 @@
X # define MACH_TYPE (MACH_APOLLO)
X #endif
X
+#if !defined (CONFIG_MVME147)
+# define MACH_IS_MVME147 (0)
+#elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC) || defined(CONFIG_ATARI) \
+ || defined(CONFIG_APOLLO) || defined(CONFIG_BVME6000) \
+ || defined(CONFIG_HP300) || defined(CONFIG_Q40) \
+ || defined(CONFIG_SUN3X) || defined(CONFIG_MVME16x)
+# define MACH_IS_MVME147 (m68k_machtype == MACH_MVME147)
+#else
+# define MACH_MVME147_ONLY
+# define MACH_IS_MVME147 (1)
+# define MACH_TYPE (MACH_MVME147)
+#endif
+
X #if !defined (CONFIG_MVME16x)
X # define MACH_IS_MVME16x (0)
X #elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC) || defined(CONFIG_ATARI) \
- || defined(CONFIG_APOLLO) || defined(CONFIG_BVME6000) || defined(CONFIG_HP300)
+ || defined(CONFIG_APOLLO) || defined(CONFIG_BVME6000) \
+ || defined(CONFIG_HP300) || defined(CONFIG_Q40) \
+ || defined(CONFIG_SUN3X) || defined(CONFIG_MVME147)
X # define MACH_IS_MVME16x (m68k_machtype == MACH_MVME16x)
X #else
X # define MACH_MVME16x_ONLY
@@ -110,7 +135,9 @@
X #if !defined (CONFIG_BVME6000)
X # define MACH_IS_BVME6000 (0)
X #elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC) || defined(CONFIG_ATARI) \
- || defined(CONFIG_APOLLO) || defined(CONFIG_MVME16x) || defined(CONFIG_HP300)
+ || defined(CONFIG_APOLLO) || defined(CONFIG_MVME16x) \
+ || defined(CONFIG_HP300) || defined(CONFIG_Q40) \
+ || defined(CONFIG_SUN3X) || defined(CONFIG_MVME147)
X # define MACH_IS_BVME6000 (m68k_machtype == MACH_BVME6000)
X #else
X # define MACH_BVME6000_ONLY
@@ -121,12 +148,40 @@
X #if !defined (CONFIG_HP300)
X # define MACH_IS_HP300 (0)
X #elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC) || defined(CONFIG_ATARI) \
- || defined(CONFIG_APOLLO) || defined(CONFIG_MVME16x) || defined(CONFIG_BVME6000)
-# define MAC_IS_HP300 (m68k_machtype == MACH_HP300)
+ || defined(CONFIG_APOLLO) || defined(CONFIG_MVME16x) \
+ || defined(CONFIG_BVME6000) || defined(CONFIG_Q40) \
+ || defined(CONFIG_SUN3X) || defined(CONFIG_MVME147)
+# define MACH_IS_HP300 (m68k_machtype == MACH_HP300)
X #else
X # define MACH_HP300_ONLY
X # define MACH_IS_HP300 (1)
X # define MACH_TYPE (MACH_HP300)
+#endif
+
+#if !defined (CONFIG_Q40)
+# define MACH_IS_Q40 (0)
+#elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC) || defined(CONFIG_ATARI) \
+ || defined(CONFIG_APOLLO) || defined(CONFIG_MVME16x) \
+ || defined(CONFIG_BVME6000) || defined(CONFIG_HP300) \
+ || defined(CONFIG_SUN3X) || defined(CONFIG_MVME147)
+# define MACH_IS_Q40 (m68k_machtype == MACH_Q40)
+#else
+# define MACH_Q40_ONLY
+# define MACH_IS_Q40 (1)
+# define MACH_TYPE (MACH_Q40)
+#endif
+
+#if !defined (CONFIG_SUN3X)
+# define MACH_IS_SUN3X (0)
+#elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC) || defined(CONFIG_ATARI) \
+ || defined(CONFIG_APOLLO) || defined(CONFIG_MVME16x) \
+ || defined(CONFIG_BVME6000) || defined(CONFIG_HP300) \
+ || defined(CONFIG_Q40) || defined(CONFIG_MVME147)
+# define MACH_IS_SUN3X (m68k_machtype == MACH_SUN3X)
+#else
+# define CONFIG_SUN3X_ONLY
+# define MACH_IS_SUN3X (1)
+# define MACH_TYPE (MACH_SUN3X)
X #endif
X
X #ifndef MACH_TYPE
diff -u --recursive --new-file v2.2.7/linux/include/asm-m68k/sun3x.h linux/include/asm-m68k/sun3x.h
--- v2.2.7/linux/include/asm-m68k/sun3x.h Wed Dec 31 16:00:00 1969
+++ linux/include/asm-m68k/sun3x.h Tue May 11 09:57:14 1999
@@ -0,0 +1,24 @@
+#ifndef SUN3X_H
+#define SUN3X_H
+
+/* hardware addresses */
+#define SUN3X_IOMMU 0x60000000
+#define SUN3X_ENAREG 0x61000000
+#define SUN3X_INTREG 0x61001400
+#define SUN3X_DIAGREG 0x61001800
+#define SUN3X_ZS1 0x62000000
+#define SUN3X_ZS2 0x62002000
+#define SUN3X_LANCE 0x65002000
+#define SUN3X_EEPROM 0x64000000
+#define SUN3X_IDPROM 0x640007d8
+#define SUN3X_VIDEO_BASE 0x50000000
+#define SUN3X_VIDEO_P4ID 0x50300000
+#define SUN3X_ESP_BASE 0x66000000
+#define SUN3X_ESP_DMA 0x66001000
+
+/* some NVRAM addresses */
+#define SUN3X_EEPROM_CONS (SUN3X_EEPROM + 0x1f)
+#define SUN3X_EEPROM_PORTA (SUN3X_EEPROM + 0x58)
+#define SUN3X_EEPROM_PORTB (SUN3X_EEPROM + 0x60)
+
+#endif
diff -u --recursive --new-file v2.2.7/linux/include/asm-m68k/system.h linux/include/asm-m68k/system.h
--- v2.2.7/linux/include/asm-m68k/system.h Wed Jan 20 23:14:06 1999
+++ linux/include/asm-m68k/system.h Tue May 11 09:57:14 1999
@@ -43,12 +43,14 @@
X * the mm structures are shared in d2 (to avoid atc flushing).
X */
X asmlinkage void resume(void);
-#define switch_to(prev,next) { \
+#define switch_to(prev,next,last) { \
X register void *_prev __asm__ ("a0") = (prev); \
X register void *_next __asm__ ("a1") = (next); \
+ register void *_last __asm__ ("d1"); \
X __asm__ __volatile__("jbsr " SYMBOL_NAME_STR(resume) \
- : : "a" (_prev), "a" (_next) \
+ : "=d" (_last) : "a" (_prev), "a" (_next) \
X : "d0", "d1", "d2", "d3", "d4", "d5", "a0", "a1"); \
+ (last) = _last; \
X }
X
X #define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
@@ -66,6 +68,8 @@
X #define __cli() __asm__ __volatile__ ("oriw #0x0700,%/sr": : : "memory")
X #define nop() __asm__ __volatile__ ("nop"::)


X #define mb() __asm__ __volatile__ ("" : : :"memory")

+#define rmb() __asm__ __volatile__ ("" : : :"memory")
+#define wmb() __asm__ __volatile__ ("" : : :"memory")
X
X #define __save_flags(x) \
X __asm__ __volatile__("movew %/sr,%0":"=d" (x) : /* no input */ :"memory")
diff -u --recursive --new-file v2.2.7/linux/include/asm-m68k/uaccess.h linux/include/asm-m68k/uaccess.h
--- v2.2.7/linux/include/asm-m68k/uaccess.h Thu Jan 7 15:11:40 1999
+++ linux/include/asm-m68k/uaccess.h Tue May 11 09:57:14 1999
@@ -759,6 +759,10 @@
X #define __copy_from_user(to, from, n) copy_from_user(to, from, n)
X #define __copy_to_user(to, from, n) copy_to_user(to, from, n)
X
+#define copy_to_user_ret(to,from,n,retval) ({ if (copy_to_user(to,from,n)) return retval; })
+
+#define copy_from_user_ret(to,from,n,retval) ({ if (copy_from_user(to,from,n)) return retval; })
+
X /*
X * Copy a null terminated string from userspace.
X */
diff -u --recursive --new-file v2.2.7/linux/include/asm-ppc/adb.h linux/include/asm-ppc/adb.h
--- v2.2.7/linux/include/asm-ppc/adb.h Tue Mar 23 14:35:48 1999
+++ linux/include/asm-ppc/adb.h Thu Apr 29 12:39:01 1999
@@ -21,6 +21,16 @@
X #define ADB_RET_OK 0
X #define ADB_RET_TIMEOUT 3
X
+/* The kind of ADB request. The controller may emulate some
+ of all of those CUDA/PMU packet kinds */
+#define ADB_PACKET 0
+#define CUDA_PACKET 1
+#define ERROR_PACKET 2
+#define TIMER_PACKET 3
+#define POWER_PACKET 4
+#define MACIIC_PACKET 5
+#define PMU_PACKET 6
+
X #ifdef __KERNEL__
X
X struct adb_request {
@@ -41,19 +51,37 @@
X unsigned char id[16];
X };
X
-extern enum adb_hw {
- ADB_NONE, ADB_VIACUDA, ADB_VIAPMU, ADB_MACIO
-} adb_hardware;
-
-extern int (*adb_send_request)(struct adb_request *req, int sync);
-extern int (*adb_autopoll)(int devs);
-extern int (*adb_reset_bus)(void);
+/* Messages sent thru the client_list notifier. You should NOT stop
+ the operation, at least not with this version */
+enum adb_message {
+ ADB_MSG_POWERDOWN, /* Currently called before sleep only */
+ ADB_MSG_PRE_RESET, /* Called before resetting the bus */
+ ADB_MSG_POST_RESET /* Called after resetting the bus (re-do init & register) */
+};
+extern struct notifier_block *adb_client_list;


SHAR_EOF
true || echo 'restore of patch-2.2.8 failed'
fi

echo 'End of part 30'
echo 'File patch-2.2.8 is continued in part 31'
echo 31 > _shar_seq_.tmp

Thomas...@ciw.uni-karlsruhe.de

unread,
May 12, 1999, 3:00:00 AM5/12/99
to
Archive-name: v2.2/patch-2.2.8/part31

#!/bin/sh
# this is part 31 of a 33 - part archive


# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.8 continued
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 31; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.8'
else
echo 'x - continuing with patch-2.2.8'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.8' &&
+

+/* Kind of ADB controller */
+enum adb_hw {
+ ADB_NONE, ADB_VIACUDA, ADB_VIAPMU, ADB_MACIO, ADB_UNKNOWN
+};
+
+/* Definition of a controller */
+extern struct adb_controller {
+ enum adb_hw kind;
+
+ int (*send_request)(struct adb_request *req, int sync);
+ int (*autopoll)(int devs);
+ int (*reset_bus)(void);
+ void (*poll)(void);
+} *adb_controller;
+extern enum adb_hw adb_hardware;
X
X /* Values for adb_request flags */
X #define ADBREQ_REPLY 1 /* expect reply */
X #define ADBREQ_SYNC 2 /* poll until done */
X
X void adb_init(void);
+
X int adb_request(struct adb_request *req, void (*done)(struct adb_request *),
X int flags, int nbytes, ...);
X int adb_register(int default_id,int handler_id,struct adb_ids *ids,
@@ -62,6 +90,10 @@
X
X int adb_try_handler_change(int address, int new_id);
X int adb_get_infos(int address, int *original_address, int *handler_id);
+
+int adb_reset_bus(void);
+
+void adb_poll(void);


X
X #endif /* __KERNEL__ */

X
diff -u --recursive --new-file v2.2.7/linux/include/asm-ppc/cuda.h linux/include/asm-ppc/cuda.h
--- v2.2.7/linux/include/asm-ppc/cuda.h Fri May 8 23:14:56 1998
+++ linux/include/asm-ppc/cuda.h Thu Apr 29 12:39:01 1999
@@ -5,15 +5,6 @@
X * Copyright (C) 1996 Paul Mackerras.
X */
X
-/* First byte sent to or received from CUDA */
-#define ADB_PACKET 0
-#define CUDA_PACKET 1
-#define ERROR_PACKET 2
-#define TIMER_PACKET 3
-#define POWER_PACKET 4
-#define MACIIC_PACKET 5
-#define PMU_PACKET 6
-
X /* CUDA commands (2nd byte) */
X #define CUDA_WARM_START 0
X #define CUDA_AUTOPOLL 1
@@ -41,7 +32,7 @@
X void via_cuda_init(void);
X int cuda_request(struct adb_request *req,
X void (*done)(struct adb_request *), int nbytes, ...);
-int cuda_send_request(struct adb_request *req);
X void cuda_poll(void);
+int cuda_present(void);
X
X #endif /* __KERNEL */
diff -u --recursive --new-file v2.2.7/linux/include/asm-ppc/dma.h linux/include/asm-ppc/dma.h
--- v2.2.7/linux/include/asm-ppc/dma.h Tue Mar 23 14:35:48 1999
+++ linux/include/asm-ppc/dma.h Thu Apr 29 12:39:01 1999
@@ -35,36 +35,9 @@
X /* Doesn't really apply... */
X #define MAX_DMA_ADDRESS 0xFFFFFFFF
X
-#if defined(CONFIG_MACH_SPECIFIC)
-
-#if defined(CONFIG_PREP)
-#define DMA_MODE_READ 0x44
-#define DMA_MODE_WRITE 0x48
-#define ISA_DMA_THRESHOLD 0x00ffffff
-#endif /* CONFIG_PREP */
-
-#if defined(CONFIG_CHRP)
-#define DMA_MODE_READ 0x44
-#define DMA_MODE_WRITE 0x48
-#define ISA_DMA_THRESHOLD ~0L
-#endif /* CONFIG_CHRP */
-
-#ifdef CONFIG_PMAC
-#define DMA_MODE_READ 1
-#define DMA_MODE_WRITE 2
-#define ISA_DMA_THRESHOLD ~0L
-#endif /* CONFIG_PMAC */
-
-#ifdef CONFIG_APUS
-/* This is bogus and should go away. */
-#define ISA_DMA_THRESHOLD (0x00ffffff)
-#endif
-
-#else
X /* in arch/ppc/kernel/setup.c -- Cort */
X extern unsigned long DMA_MODE_WRITE, DMA_MODE_READ;
X extern unsigned long ISA_DMA_THRESHOLD;
-#endif
X
X
X #ifdef HAVE_REALLY_SLOW_DMA_CONTROLLER
@@ -204,7 +177,7 @@
X #define DMA2_EXT_REG 0x4D6
X
X #define DMA_MODE_CASCADE 0xC0 /* pass thru DREQ->HRQ, DACK<-HLDA only */
-#define DMA_AUTOINIT 0x10
+#define DMA_AUTOINIT 0x10
X
X extern spinlock_t dma_spin_lock;
X
@@ -427,9 +400,8 @@
X extern void free_dma(unsigned int dmanr); /* release it again */
X
X #ifdef CONFIG_PCI_QUIRKS
-extern int isa_dma_bridge_buggy;
-#else
-#define isa_dma_bridge_buggy (0)
+extern int isa_dma_bridge_buggy;
+#else
+#define isa_dma_bridge_buggy (0)
X #endif
-
X #endif /* _ASM_DMA_H */
diff -u --recursive --new-file v2.2.7/linux/include/asm-ppc/hardirq.h linux/include/asm-ppc/hardirq.h
--- v2.2.7/linux/include/asm-ppc/hardirq.h Mon Oct 5 13:13:43 1998
+++ linux/include/asm-ppc/hardirq.h Thu Apr 29 12:39:01 1999
@@ -1,22 +1,22 @@
X #ifndef __ASM_HARDIRQ_H
X #define __ASM_HARDIRQ_H
X
-extern unsigned int local_irq_count[NR_CPUS];


+extern unsigned int ppc_local_irq_count[NR_CPUS];

X
X /*
X * Are we in an interrupt context? Either doing bottom half
X * or hardware interrupt processing?
X */
X #define in_interrupt() ({ int __cpu = smp_processor_id(); \
- (local_irq_count[__cpu] + local_bh_count[__cpu] != 0); })
+ (ppc_local_irq_count[__cpu] + ppc_local_bh_count[__cpu] != 0); })
X
X #ifndef __SMP__
X
-#define hardirq_trylock(cpu) (local_irq_count[cpu] == 0)
+#define hardirq_trylock(cpu) (ppc_local_irq_count[cpu] == 0)
X #define hardirq_endlock(cpu) do { } while (0)
X
-#define hardirq_enter(cpu) (local_irq_count[cpu]++)
-#define hardirq_exit(cpu) (local_irq_count[cpu]--)
+#define hardirq_enter(cpu) (ppc_local_irq_count[cpu]++)
+#define hardirq_exit(cpu) (ppc_local_irq_count[cpu]--)
X
X #define synchronize_irq() do { } while (0)
X
@@ -39,14 +39,14 @@
X
X static inline void hardirq_enter(int cpu)
X {
- ++local_irq_count[cpu];
+ ++ppc_local_irq_count[cpu];
X atomic_inc(&global_irq_count);
X }
X
X static inline void hardirq_exit(int cpu)
X {
X atomic_dec(&global_irq_count);
- --local_irq_count[cpu];
+ --ppc_local_irq_count[cpu];
X }
X
X static inline int hardirq_trylock(int cpu)
diff -u --recursive --new-file v2.2.7/linux/include/asm-ppc/ide.h linux/include/asm-ppc/ide.h
--- v2.2.7/linux/include/asm-ppc/ide.h Tue Mar 23 14:35:48 1999
+++ linux/include/asm-ppc/ide.h Thu May 6 23:14:37 1999
@@ -11,17 +11,8 @@
X #ifndef __ASMPPC_IDE_H
X #define __ASMPPC_IDE_H
X
-#include <linux/config.h>
-/*
- * On APUS, nearly everything comes from the m68k file


- * -- Cort
- */

-#ifdef CONFIG_APUS
-#include <linux/hdreg.h>
-#define ide_init_hwif_ports m68k_ide_init_hwif_ports
-#include <asm-m68k/ide.h>
-#undef ide_init_hwif_ports
-#endif /* CONFIG_APUS */
+#include <linux/sched.h>
+#include <asm/processor.h>
X

X #ifndef MAX_HWIFS
X #define MAX_HWIFS 4

@@ -29,6 +20,12 @@
X
X typedef unsigned int ide_ioreg_t;
X
+#ifdef __KERNEL__
+
+#include <linux/hdreg.h>
+#include <linux/ioport.h>
+#include <asm/io.h>
+
X extern int pmac_ide_ports_known;
X extern ide_ioreg_t pmac_ide_regbase[MAX_HWIFS];
X extern int pmac_ide_irq[MAX_HWIFS];
@@ -40,43 +37,42 @@
X extern unsigned int chrp_ide_irq;
X extern void chrp_ide_probe(void);
X
+struct ide_machdep_calls {
+ void (*insw)(ide_ioreg_t port, void *buf, int ns);
+ void (*outsw)(ide_ioreg_t port, void *buf, int ns);
+ int (*default_irq)(ide_ioreg_t base);
+ ide_ioreg_t (*default_io_base)(int index);
+ int (*check_region)(ide_ioreg_t from, unsigned int extent);
+ void (*request_region)(ide_ioreg_t from,


+ unsigned int extent,
+ const char *name);

+ void (*release_region)(ide_ioreg_t from,
+ unsigned int extent);
+ void (*fix_driveid)(struct hd_driveid *id);
+ void (*ide_init_hwif)(ide_ioreg_t *p,
+ ide_ioreg_t base,
+ int *irq);
+
+ int io_base;
+};
+
+extern struct ide_machdep_calls ppc_ide_md;
+
X void ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base, int *irq);
-void prep_ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base, int *irq);
-void mbx_ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base, int *irq);
-void pmac_ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base, int *irq);
-void chrp_ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base, int *irq);
X void ide_insw(ide_ioreg_t port, void *buf, int ns);
X void ide_outsw(ide_ioreg_t port, void *buf, int ns);
+void ppc_generic_ide_fix_driveid(struct hd_driveid *id);
X
X #undef insw
X #define insw(port, buf, ns) do { \
- if ( _machine & (_MACH_chrp|_MACH_mbx) ) \
- ide_insw((port)+_IO_BASE, (buf), (ns)); \
- else if ( _machine & (_MACH_Pmac|_MACH_apus) ) \
- ide_insw((port), (buf), (ns)); \
- else \
- /* this must be the same as insw in io.h!! */ \
- _insw((unsigned short *)((port)+_IO_BASE), (buf), (ns)); \
+ ppc_ide_md.insw((port), (buf), (ns)); \
X } while (0)
X
X #undef outsw
X #define outsw(port, buf, ns) do { \
- if ( _machine & (_MACH_chrp|_MACH_mbx) ) \
- ide_outsw((port)+_IO_BASE, (buf), (ns)); \
- else if ( _machine & (_MACH_Pmac|_MACH_apus) ) \
- ide_outsw((port), (buf), (ns)); \
- else \
- /* this must be the same as outsw in io.h!! */ \
- _outsw((unsigned short *)((port)+_IO_BASE), (buf), (ns)); \
+ ppc_ide_md.outsw((port), (buf), (ns)); \
X } while (0)
X
-#ifndef CONFIG_APUS
-#ifdef __KERNEL__
-
-#include <linux/hdreg.h>
-#include <linux/ioport.h>
-#include <asm/io.h>
-
X #undef SUPPORT_SLOW_DATA_PORTS
X #define SUPPORT_SLOW_DATA_PORTS 0
X #undef SUPPORT_VLB_SYNC
@@ -86,192 +82,41 @@
X
X static __inline__ int ide_default_irq(ide_ioreg_t base)
X {


- if ( _machine == _MACH_Pmac )

- return 0;
- else if ( _machine == _MACH_mbx )
- /* IRQ 14 when in legacy mode on MBX */
- return 14;
- else if ( _machine == _MACH_chrp) {
- if (chrp_ide_ports_known == 0)
- chrp_ide_probe();
- return chrp_ide_irq;
- }
- switch (base) {
- case 0x1f0: return 13;
- case 0x170: return 13;
- case 0x1e8: return 11;
- case 0x168: return 10;


- default:
- return 0;
- }

+ return ppc_ide_md.default_irq(base);
X }
X
X static __inline__ ide_ioreg_t ide_default_io_base(int index)
X {
-#if defined(CONFIG_BLK_DEV_IDE_PMAC)


- if (_machine == _MACH_Pmac) {

- return pmac_ide_regbase[index];
- }
-#endif
- if (_machine == _MACH_mbx) return index;
- if ( _machine == _MACH_chrp ) {
- if (chrp_ide_ports_known == 0)
- chrp_ide_probe();
- return chrp_ide_regbase[index];
- }
- switch (index) {
- case 0: return 0x1f0;
- case 1: return 0x170;
- case 2: return 0x1e8;
- case 3: return 0x168;


- default:
- return 0;
- }

+ return ppc_ide_md.default_io_base(index);
X }
X
X static __inline__ int ide_check_region (ide_ioreg_t from, unsigned int extent)
X {
- if ( (_machine == _MACH_Pmac) || (_machine == _MACH_mbx))
- return 0;
- return check_region(from, extent);
+ return ppc_ide_md.check_region(from, extent);
X }
X

X static __inline__ void ide_request_region (ide_ioreg_t from, unsigned int extent, const char *name)
X {

- if ( (_machine == _MACH_Pmac) || (_machine == _MACH_mbx) )
- return;
- request_region(from, extent, name);
+ ppc_ide_md.request_region(from, extent, name);


X }
X
X static __inline__ void ide_release_region (ide_ioreg_t from, unsigned int extent)
X {

- if ( (_machine == _MACH_Pmac) || (_machine == _MACH_mbx) )
- return;
- release_region(from, extent);
+ ppc_ide_md.release_region(from, extent);
X }
X
-/* Convert the shorts/longs in hd_driveid from little to big endian;
- chars are endian independent, of course, but strings need to be flipped.
- (Despite what it says in drivers/block/ide.h, they come up as little endian...)
- Changes to linux/hdreg.h may require changes here. */
X static __inline__ void ide_fix_driveid (struct hd_driveid *id) {
- if ( _machine & (_MACH_chrp|_MACH_mbx|_MACH_Pmac) ) { \
- int i;
- unsigned short *stringcast;
- id->config = __le16_to_cpu(id->config);
- id->cyls = __le16_to_cpu(id->cyls);
- id->reserved2 = __le16_to_cpu(id->reserved2);
- id->heads = __le16_to_cpu(id->heads);
- id->track_bytes = __le16_to_cpu(id->track_bytes);
- id->sector_bytes = __le16_to_cpu(id->sector_bytes);
- id->sectors = __le16_to_cpu(id->sectors);
- id->vendor0 = __le16_to_cpu(id->vendor0);
- id->vendor1 = __le16_to_cpu(id->vendor1);
- id->vendor2 = __le16_to_cpu(id->vendor2);
- stringcast = (unsigned short *)&id->serial_no[0];
- for (i=0; i<(20/2); i++)
- stringcast[i] = __le16_to_cpu(stringcast[i]);
- id->buf_type = __le16_to_cpu(id->buf_type);
- id->buf_size = __le16_to_cpu(id->buf_size);
- id->ecc_bytes = __le16_to_cpu(id->ecc_bytes);
- stringcast = (unsigned short *)&id->fw_rev[0];
- for (i=0; i<(8/2); i++)
- stringcast[i] = __le16_to_cpu(stringcast[i]);
- stringcast = (unsigned short *)&id->model[0];
- for (i=0; i<(40/2); i++)
- stringcast[i] = __le16_to_cpu(stringcast[i]);
- id->dword_io = __le16_to_cpu(id->dword_io);
- id->reserved50 = __le16_to_cpu(id->reserved50);
- id->field_valid = __le16_to_cpu(id->field_valid);
- id->cur_cyls = __le16_to_cpu(id->cur_cyls);
- id->cur_heads = __le16_to_cpu(id->cur_heads);
- id->cur_sectors = __le16_to_cpu(id->cur_sectors);
- id->cur_capacity0 = __le16_to_cpu(id->cur_capacity0);
- id->cur_capacity1 = __le16_to_cpu(id->cur_capacity1);
- id->lba_capacity = __le32_to_cpu(id->lba_capacity);
- id->dma_1word = __le16_to_cpu(id->dma_1word);
- id->dma_mword = __le16_to_cpu(id->dma_mword);
- id->eide_pio_modes = __le16_to_cpu(id->eide_pio_modes);
- id->eide_dma_min = __le16_to_cpu(id->eide_dma_min);
- id->eide_dma_time = __le16_to_cpu(id->eide_dma_time);
- id->eide_pio = __le16_to_cpu(id->eide_pio);
- id->eide_pio_iordy = __le16_to_cpu(id->eide_pio_iordy);
- id->word69 = __le16_to_cpu(id->word69);
- id->word70 = __le16_to_cpu(id->word70);
- id->word71 = __le16_to_cpu(id->word71);
- id->word72 = __le16_to_cpu(id->word72);
- id->word73 = __le16_to_cpu(id->word73);
- id->word74 = __le16_to_cpu(id->word74);
- id->word75 = __le16_to_cpu(id->word75);
- id->word76 = __le16_to_cpu(id->word76);
- id->word77 = __le16_to_cpu(id->word77);
- id->word78 = __le16_to_cpu(id->word78);
- id->word79 = __le16_to_cpu(id->word79);
- id->word80 = __le16_to_cpu(id->word80);
- id->word81 = __le16_to_cpu(id->word81);
- id->command_sets = __le16_to_cpu(id->command_sets);
- id->word83 = __le16_to_cpu(id->word83);
- id->word84 = __le16_to_cpu(id->word84);
- id->word85 = __le16_to_cpu(id->word85);
- id->word86 = __le16_to_cpu(id->word86);
- id->word87 = __le16_to_cpu(id->word87);
- id->dma_ultra = __le16_to_cpu(id->dma_ultra);
- id->word89 = __le16_to_cpu(id->word89);
- id->word90 = __le16_to_cpu(id->word90);
- id->word91 = __le16_to_cpu(id->word91);
- id->word92 = __le16_to_cpu(id->word92);
- id->word93 = __le16_to_cpu(id->word93);
- id->word94 = __le16_to_cpu(id->word94);
- id->word95 = __le16_to_cpu(id->word95);
- id->word96 = __le16_to_cpu(id->word96);
- id->word97 = __le16_to_cpu(id->word97);
- id->word98 = __le16_to_cpu(id->word98);
- id->word99 = __le16_to_cpu(id->word99);
- id->word100 = __le16_to_cpu(id->word100);
- id->word101 = __le16_to_cpu(id->word101);
- id->word102 = __le16_to_cpu(id->word102);
- id->word103 = __le16_to_cpu(id->word103);
- id->word104 = __le16_to_cpu(id->word104);
- id->word105 = __le16_to_cpu(id->word105);
- id->word106 = __le16_to_cpu(id->word106);
- id->word107 = __le16_to_cpu(id->word107);
- id->word108 = __le16_to_cpu(id->word108);
- id->word109 = __le16_to_cpu(id->word109);
- id->word110 = __le16_to_cpu(id->word110);
- id->word111 = __le16_to_cpu(id->word111);
- id->word112 = __le16_to_cpu(id->word112);
- id->word113 = __le16_to_cpu(id->word113);
- id->word114 = __le16_to_cpu(id->word114);
- id->word115 = __le16_to_cpu(id->word115);
- id->word116 = __le16_to_cpu(id->word116);
- id->word117 = __le16_to_cpu(id->word117);
- id->word118 = __le16_to_cpu(id->word118);
- id->word119 = __le16_to_cpu(id->word119);
- id->word120 = __le16_to_cpu(id->word120);
- id->word121 = __le16_to_cpu(id->word121);
- id->word122 = __le16_to_cpu(id->word122);
- id->word123 = __le16_to_cpu(id->word123);
- id->word124 = __le16_to_cpu(id->word124);
- id->word125 = __le16_to_cpu(id->word125);
- id->word126 = __le16_to_cpu(id->word126);
- id->word127 = __le16_to_cpu(id->word127);
- id->security = __le16_to_cpu(id->security);
- for (i=0; i<127; i++)
- id->reserved[i] = __le16_to_cpu(id->reserved[i]);
- }
+ ppc_ide_md.fix_driveid(id);
X }
X
X #undef inb
-#define inb(port) \
- in_8((unsigned char *)((port) + \
- ((_machine==_MACH_Pmac)? 0: _IO_BASE) ) )
+#define inb(port) in_8((unsigned char *)((port) + ppc_ide_md.io_base))
X #undef inb_p
X #define inb_p(port) inb(port)
X
X #undef outb
X #define outb(val, port) \
- out_8((unsigned char *)((port) + \
- ((_machine==_MACH_Pmac)? 0: _IO_BASE) ), (val) )
+ out_8((unsigned char *)((port) + ppc_ide_md.io_base), (val) )
X #undef outb_p
X #define outb_p(val, port) outb(val, port)
X
@@ -305,6 +150,5 @@
X #define ide_get_lock(lock, hdlr, data) do {} while (0)


X
X #endif /* __KERNEL__ */

-#endif /* CONFIG_APUS */
X
X #endif /* __ASMPPC_IDE_H */
diff -u --recursive --new-file v2.2.7/linux/include/asm-ppc/io.h linux/include/asm-ppc/io.h
--- v2.2.7/linux/include/asm-ppc/io.h Tue Mar 23 14:35:48 1999
+++ linux/include/asm-ppc/io.h Thu Apr 29 12:39:01 1999
@@ -5,8 +5,6 @@
X #include <asm/page.h>
X #include <asm/byteorder.h>
X
-#define KERNELBASE 0xc0000000
-
X #define SIO_CONFIG_RA 0x398
X #define SIO_CONFIG_RD 0x399
X
@@ -18,7 +16,7 @@
X #define CHRP_ISA_MEM_BASE 0xf7000000
X #define CHRP_PCI_DRAM_OFFSET 0
X #define PREP_ISA_IO_BASE 0x80000000
-#define PREP_ISA_MEM_BASE 0xd0000000
+#define PREP_ISA_MEM_BASE 0xc0000000
X #define PREP_PCI_DRAM_OFFSET 0x80000000
X
X #ifdef CONFIG_MBX
@@ -49,7 +47,7 @@
X #define writel(b,addr) ((*(volatile unsigned int *) (addr)) = (b))
X #else
X #define readw(addr) in_le16((volatile unsigned short *)(addr))
-#define readl(addr) in_le32((volatile unsigned *)addr)
+#define readl(addr) in_le32((volatile unsigned *)(addr))
X #define writew(b,addr) out_le16((volatile unsigned short *)(addr),(b))
X #define writel(b,addr) out_le32((volatile unsigned *)(addr),(b))
X #endif
diff -u --recursive --new-file v2.2.7/linux/include/asm-ppc/irq.h linux/include/asm-ppc/irq.h
--- v2.2.7/linux/include/asm-ppc/irq.h Tue Mar 23 14:35:48 1999
+++ linux/include/asm-ppc/irq.h Thu Apr 29 12:39:01 1999
@@ -3,7 +3,7 @@
X #ifndef _ASM_IRQ_H
X #define _ASM_IRQ_H
X
-#include <asm/processor.h> /* for is_prep() */
+#include <asm/machdep.h> /* ppc_md */


X
X extern void disable_irq(unsigned int);

X extern void enable_irq(unsigned int);

@@ -42,7 +42,14 @@
X */
X static __inline__ int irq_cannonicalize(int irq)
X {
- return (((is_prep || is_chrp) && irq == 2) ? 9 : irq);
+ if (ppc_md.irq_cannonicalize)
+ {
+ return ppc_md.irq_cannonicalize(irq);
+ }
+ else


+ {
+ return irq;
+ }

X }
X #endif
X
diff -u --recursive --new-file v2.2.7/linux/include/asm-ppc/keyboard.h linux/include/asm-ppc/keyboard.h
--- v2.2.7/linux/include/asm-ppc/keyboard.h Wed Apr 28 11:37:31 1999
+++ linux/include/asm-ppc/keyboard.h Thu Apr 29 12:39:01 1999
@@ -17,7 +17,7 @@
X
X #include <linux/config.h>
X #include <asm/adb.h>
-
+#include <asm/machdep.h>
X #ifdef CONFIG_APUS
X #include <asm-m68k/keyboard.h>
X #else
@@ -26,132 +26,44 @@
X #define DISABLE_KBD_DURING_INTERRUPTS 0
X #define INIT_KBD
X
-extern int mackbd_setkeycode(unsigned int scancode, unsigned int keycode);
-extern int mackbd_getkeycode(unsigned int scancode);
-extern int mackbd_translate(unsigned char scancode, unsigned char *keycode,
- char raw_mode);
-extern int mackbd_unexpected_up(unsigned char keycode);
-extern void mackbd_leds(unsigned char leds);
-extern void mackbd_init_hw(void);


-
-extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode);
-extern int pckbd_getkeycode(unsigned int scancode);
-extern int pckbd_translate(unsigned char scancode, unsigned char *keycode,
- char raw_mode);
-extern char pckbd_unexpected_up(unsigned char keycode);
-extern void pckbd_leds(unsigned char leds);
-extern void pckbd_init_hw(void);
-

X static inline int kbd_setkeycode(unsigned int scancode, unsigned int keycode)
X {
- if ( is_prep || (_machine == _MACH_mbx) )
- return pckbd_setkeycode(scancode,keycode);
- else if ( is_chrp )
-#ifndef CONFIG_MAC_KEYBOARD
- return pckbd_setkeycode(scancode,keycode);
-#else
- /* I'm not actually sure if it's legal to have a CHRP machine
- * without an ADB controller. In any case, this should really
- * be changed to be a test to see if an ADB _keyboard_ exists
- * (not just a controller), but that's another story for
- * another night.
- */
- if ( adb_hardware == ADB_NONE )
- return pckbd_setkeycode(scancode,keycode);
- else
- return mackbd_setkeycode(scancode,keycode);
-#endif
- else
- return mackbd_setkeycode(scancode,keycode);
+ return ppc_md.kbd_setkeycode(scancode, keycode);
X }
-
-static inline int kbd_getkeycode(unsigned int x)
+
+static inline int kbd_getkeycode(unsigned int scancode)
X {
- if ( is_prep || (_machine == _MACH_mbx) )
- return pckbd_getkeycode(x);
- else if ( is_chrp )
-#ifndef CONFIG_MAC_KEYBOARD
- return pckbd_getkeycode(x);
-#else
- if ( adb_hardware == ADB_NONE )
- return pckbd_getkeycode(x);
- else
- return mackbd_getkeycode(x);
-#endif
- else
- return mackbd_getkeycode(x);
+ return ppc_md.kbd_getkeycode(scancode);
X }
-
+
X static inline int kbd_translate(unsigned char keycode, unsigned char *keycodep,
- char raw_mode)
+ char raw_mode)
X {
- if ( is_prep || (_machine == _MACH_mbx) )
- return pckbd_translate(keycode,keycodep,raw_mode);
- else if ( is_chrp )
-#ifndef CONFIG_MAC_KEYBOARD
- return pckbd_translate(keycode,keycodep,raw_mode);
-#else
- if ( adb_hardware == ADB_NONE )
- return pckbd_translate(keycode,keycodep,raw_mode);
- else
- return mackbd_translate(keycode,keycodep,raw_mode);
-#endif
- else
- return mackbd_translate(keycode,keycodep,raw_mode);
-
+ return ppc_md.kbd_translate(keycode, keycodep, raw_mode);
X }
-
+
X static inline int kbd_unexpected_up(unsigned char keycode)
X {
- if ( is_prep || (_machine == _MACH_mbx) )
- return pckbd_unexpected_up(keycode);
- else if ( is_chrp )
-#ifndef CONFIG_MAC_KEYBOARD
- return pckbd_unexpected_up(keycode);
-#else
- if ( adb_hardware == ADB_NONE )
- return pckbd_unexpected_up(keycode);
- else
- return mackbd_unexpected_up(keycode);
-#endif
- else
- return mackbd_unexpected_up(keycode);
-
+ return ppc_md.kbd_unexpected_up(keycode);
X }
-
+
X static inline void kbd_leds(unsigned char leds)
X {
- if ( is_prep || (_machine == _MACH_mbx) )
- pckbd_leds(leds);
- else if ( is_chrp )
-#ifndef CONFIG_MAC_KEYBOARD
- pckbd_leds(leds);
-#else
- if ( adb_hardware == ADB_NONE )
- pckbd_leds(leds);
- else
- mackbd_leds(leds);
-#endif
- else
- mackbd_leds(leds);
+ ppc_md.kbd_leds(leds);
X }
-
+
X static inline void kbd_init_hw(void)
X {
- if ( is_prep || (_machine == _MACH_mbx) )
- pckbd_init_hw();
- else if ( is_chrp )
-#ifndef CONFIG_MAC_KEYBOARD
- pckbd_init_hw();
+ ppc_md.kbd_init_hw();
+}
+
+#define kbd_sysrq_xlate (ppc_md.kbd_sysrq_xlate)
+
+#ifdef CONFIG_MAC_KEYBOARD
+# define SYSRQ_KEY 0x69
X #else
- if ( adb_hardware == ADB_NONE )
- pckbd_init_hw();
- else
- mackbd_init_hw();
+# define SYSRQ_KEY 0x54
X #endif
- else
- mackbd_init_hw();
-}
X
X #endif /* CONFIG_APUS */
X
diff -u --recursive --new-file v2.2.7/linux/include/asm-ppc/machdep.h linux/include/asm-ppc/machdep.h
--- v2.2.7/linux/include/asm-ppc/machdep.h Thu Aug 6 14:06:33 1998
+++ linux/include/asm-ppc/machdep.h Thu Apr 29 12:39:01 1999
@@ -1,3 +1,4 @@
+
X #ifndef _PPC_MACHDEP_H
X #define _PPC_MACHDEP_H
X
@@ -7,6 +8,69 @@
X #include <asm-m68k/machdep.h>
X #endif
X
-#endif /* _PPC_MACHDEP_H */
+struct pt_regs;
+
+struct machdep_calls {
+ void (*setup_arch)(unsigned long * memory_start_p,
+ unsigned long * memory_end_p);
+ /* Optional, may be NULL. */
+ int (*setup_residual)(char *buffer);
+ /* Optional, may be NULL. */
+ int (*get_cpuinfo)(char *buffer);
+ /* Optional, may be NULL. */
+ unsigned int (*irq_cannonicalize)(unsigned int irq);
+ void (*init_IRQ)(void);
+ void (*do_IRQ)(struct pt_regs *regs, int cpu, int isfake);
+
+ /* A general init function, called by ppc_init in init/main.c.
+ May be NULL. */
+ void (*init)(void);
+
+ void (*restart)(char *cmd);
+ void (*power_off)(void);
+ void (*halt)(void);
+
+ void (*time_init)(void); /* Optional, may be NULL */
+ int (*set_rtc_time)(unsigned long nowtime);
+ unsigned long (*get_rtc_time)(void);
+ void (*calibrate_decr)(void);
X
+ unsigned char (*nvram_read_val)(int addr);
+ void (*nvram_write_val)(int addr, unsigned char val);
X
+/* Tons of keyboard stuff. */
+ int (*kbd_setkeycode)(unsigned int scancode,
+ unsigned int keycode);
+ int (*kbd_getkeycode)(unsigned int scancode);
+ int (*kbd_translate)(unsigned char scancode,
+ unsigned char *keycode,
+ char raw_mode);
+ char (*kbd_unexpected_up)(unsigned char keycode);
+ void (*kbd_leds)(unsigned char leds);
+ void (*kbd_init_hw)(void);
+#ifdef CONFIG_MAGIC_SYSRQ
+ unsigned char *kbd_sysrq_xlate;
+#endif
+
+ /* PCI interfaces */
+ int (*pcibios_read_config_byte)(unsigned char bus,
+ unsigned char dev_fn, unsigned char offset, unsigned char *val);
+ int (*pcibios_read_config_word)(unsigned char bus,
+ unsigned char dev_fn, unsigned char offset, unsigned short *val);
+ int (*pcibios_read_config_dword)(unsigned char bus,
+ unsigned char dev_fn, unsigned char offset, unsigned int *val);
+ int (*pcibios_write_config_byte)(unsigned char bus,
+ unsigned char dev_fn, unsigned char offset, unsigned char val);
+ int (*pcibios_write_config_word)(unsigned char bus,
+ unsigned char dev_fn, unsigned char offset, unsigned short val);
+ int (*pcibios_write_config_dword)(unsigned char bus,
+ unsigned char dev_fn, unsigned char offset, unsigned int val);
+ void (*pcibios_fixup)(void);
+};
+
+extern struct machdep_calls ppc_md;
+extern char cmd_line[512];
+
+extern void setup_pci_ptrs(void);
+
+#endif /* _PPC_MACHDEP_H */
diff -u --recursive --new-file v2.2.7/linux/include/asm-ppc/mk48t59.h linux/include/asm-ppc/mk48t59.h
--- v2.2.7/linux/include/asm-ppc/mk48t59.h Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ppc/mk48t59.h Thu Apr 29 12:39:01 1999


@@ -0,0 +1,35 @@
+/*

+ * Registers for the mk48t59 real-time-clock
+ */
+
+#ifndef _PPC_MK48T59_H
+#define _PPC_MK48T59_H
+
+/* RTC Offsets */
+
+#define MK48T59_RTC_SECONDS 0x1FF9
+#define MK48T59_RTC_MINUTES 0x1FFA
+#define MK48T59_RTC_HOURS 0x1FFB
+#define MK48T59_RTC_DAY_OF_WEEK 0x1FFC
+#define MK48T59_RTC_DAY_OF_MONTH 0x1FFD
+#define MK48T59_RTC_MONTH 0x1FFE
+#define MK48T59_RTC_YEAR 0x1FFF
+
+#define MK48T59_RTC_CONTROLA 0x1FF8
+#define MK48T59_RTC_CA_WRITE 0x80
+#define MK48T59_RTC_CA_READ 0x40
+#define MK48T59_RTC_CA_CALIB_SIGN 0x20
+#define MK48T59_RTC_CA_CALIB_MASK 0x1f
+
+#define MK48T59_RTC_CONTROLB 0x1FF9
+#define MK48T59_RTC_CB_STOP 0x80
+
+#ifndef BCD_TO_BIN
+#define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10)
+#endif
+
+#ifndef BIN_TO_BCD
+#define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10)
+#endif
+
+#endif /* _PPC_MK48T59_H */
diff -u --recursive --new-file v2.2.7/linux/include/asm-ppc/page.h linux/include/asm-ppc/page.h
--- v2.2.7/linux/include/asm-ppc/page.h Tue Mar 23 14:35:48 1999
+++ linux/include/asm-ppc/page.h Thu Apr 29 12:39:01 1999
@@ -9,7 +9,7 @@
X #define PAGE_MASK (~(PAGE_SIZE-1))
X
X #define PAGE_OFFSET 0xc0000000
-
+#define KERNELBASE PAGE_OFFSET
X
X #ifndef __ASSEMBLY__
X #ifdef __KERNEL__
diff -u --recursive --new-file v2.2.7/linux/include/asm-ppc/pgtable.h linux/include/asm-ppc/pgtable.h
--- v2.2.7/linux/include/asm-ppc/pgtable.h Tue Mar 23 14:35:48 1999
+++ linux/include/asm-ppc/pgtable.h Thu Apr 29 12:39:01 1999
@@ -37,6 +37,7 @@
X
X extern unsigned long va_to_phys(unsigned long address);
X extern pte_t *va_to_pte(struct task_struct *tsk, unsigned long address);
+extern unsigned long ioremap_bot, ioremap_base;
X #endif /* __ASSEMBLY__ */
X /*
X * The PowerPC MMU uses a hash table containing PTEs, together with
@@ -95,16 +96,19 @@
X * The vmalloc() routines leaves a hole of 4kB between each vmalloced
X * area for the same reason. ;)
X *
- * The vmalloc_offset MUST be larger than the gap between the bat2 mapping
- * and the size of physical ram. Since the bat2 mapping can be larger than
- * the amount of ram we have vmalloc_offset must ensure that we don't try
- * to allocate areas that don't exist! This value of 64M will only cause
- * problems when we have >128M -- Cort
+ * We no longer map larger than phys RAM with the BATs so we don't have
+ * to worry about the VMALLOC_OFFSET causing problems. We do have to worry
+ * about clashes between our early calls to ioremap() that start growing down
+ * from ioremap_base being run into the VM area allocations (growing upwards
+ * from VMALLOC_START). For this reason we have ioremap_bot to check when
+ * we actually run into our mappings setup in the early boot with the VM
+ * system. This really does become a problem for machines with good amounts
+ * of RAM. -- Cort
X */
-#define VMALLOC_OFFSET (0x4000000) /* 64M */
+#define VMALLOC_OFFSET (0x4000000) /* 64M */
X #define VMALLOC_START ((((long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)))


X #define VMALLOC_VMADDR(x) ((unsigned long)(x))

-#define VMALLOC_END 0xf0000000
+#define VMALLOC_END ioremap_bot
X
X /*
X * Bits in a linux-style PTE. These match the bits in the
diff -u --recursive --new-file v2.2.7/linux/include/asm-ppc/pmu.h linux/include/asm-ppc/pmu.h
--- v2.2.7/linux/include/asm-ppc/pmu.h Tue Mar 23 14:35:48 1999
+++ linux/include/asm-ppc/pmu.h Thu Apr 29 12:39:01 1999
@@ -64,11 +64,12 @@
X #define PMU_IOC_GET_MODEL _IOR('B', 3, sizeof(__u32*))


X
X #ifdef __KERNEL__
+

X void find_via_pmu(void);
X void via_pmu_init(void);
+
X int pmu_request(struct adb_request *req,
X void (*done)(struct adb_request *), int nbytes, ...);
-int pmu_send_request(struct adb_request *req);
X void pmu_poll(void);
X
X void pmu_enable_backlight(int on);
@@ -79,6 +80,7 @@
X void pmu_restart(void);
X void pmu_shutdown(void);
X
+int pmu_present(void);
X int pmu_get_model(void);
X
X /*
diff -u --recursive --new-file v2.2.7/linux/include/asm-ppc/posix_types.h linux/include/asm-ppc/posix_types.h
--- v2.2.7/linux/include/asm-ppc/posix_types.h Tue Mar 23 14:35:48 1999
+++ linux/include/asm-ppc/posix_types.h Thu Apr 29 12:39:01 1999
@@ -43,7 +43,8 @@
X
X #else /* __GNUC__ */
X
-#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ <= 2)


+#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) \

+ || (__GLIBC__ == 2 && __GLIBC_MINOR__ == 0)
X /* With GNU C, use inline functions instead so args are evaluated only once: */
X
X #undef __FD_SET
diff -u --recursive --new-file v2.2.7/linux/include/asm-ppc/prep_nvram.h linux/include/asm-ppc/prep_nvram.h
--- v2.2.7/linux/include/asm-ppc/prep_nvram.h Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ppc/prep_nvram.h Thu Apr 29 12:39:01 1999
@@ -0,0 +1,146 @@
+/*
+ * PreP compliant NVRAM access
+ */
+
+/* Corey Minyard (min...@acm.org) - Stolen from PReP book. Per the
+ license I must say:
+ (C) Copyright (Corey Minyard), (1998). All rights reserved
+ */
+
+/* Structure map for NVRAM on PowerPC Reference Platform */
+/* All fields are either character/byte strings which are valid either
+ endian or they are big-endian numbers.
+
+ There are a number of Date and Time fields which are in RTC format,
+ big-endian. These are stored in UT (GMT).
+
+ For enum's: if given in hex then they are bit significant, i.e. only
+ one bit is on for each enum.
+*/
+#ifndef _PPC_PREP_NVRAM_H
+#define _PPC_PREP_NVRAM_H
+
+#define NVSIZE 4096 /* size of NVRAM */
+#define OSAREASIZE 512 /* size of OSArea space */
+#define CONFSIZE 1024 /* guess at size of Configuration space */
+
+typedef struct _SECURITY {
+ unsigned long BootErrCnt; /* Count of boot password errors */
+ unsigned long ConfigErrCnt; /* Count of config password errors */
+ unsigned long BootErrorDT[2]; /* Date&Time from RTC of last error in pw */
+ unsigned long ConfigErrorDT[2]; /* Date&Time from RTC of last error in pw */
+ unsigned long BootCorrectDT[2]; /* Date&Time from RTC of last correct pw */
+ unsigned long ConfigCorrectDT[2]; /* Date&Time from RTC of last correct pw */
+ unsigned long BootSetDT[2]; /* Date&Time from RTC of last set of pw */
+ unsigned long ConfigSetDT[2]; /* Date&Time from RTC of last set of pw */
+ unsigned char Serial[16]; /* Box serial number */
+} SECURITY;
+
+typedef enum _OS_ID {
+ Unknown = 0,
+ Firmware = 1,
+ AIX = 2,
+ NT = 3,
+ MKOS2 = 4,
+ MKAIX = 5,
+ Taligent = 6,
+ Solaris = 7,
+ MK = 12
+} OS_ID;
+
+typedef struct _ERROR_LOG {
+ unsigned char ErrorLogEntry[40]; /* To be architected */
+} ERROR_LOG;
+
+typedef enum _BOOT_STATUS {
+ BootStarted = 0x01,
+ BootFinished = 0x02,
+ RestartStarted = 0x04,
+ RestartFinished = 0x08,
+ PowerFailStarted = 0x10,
+ PowerFailFinished = 0x20,
+ ProcessorReady = 0x40,
+ ProcessorRunning = 0x80,
+ ProcessorStart = 0x0100
+} BOOT_STATUS;
+
+typedef struct _RESTART_BLOCK {
+ unsigned short Version;
+ unsigned short Revision;
+ unsigned long ResumeReserve1[2];
+ volatile unsigned long BootStatus;
+ unsigned long CheckSum; /* Checksum of RESTART_BLOCK */
+ void * RestartAddress;
+ void * SaveAreaAddr;
+ unsigned long SaveAreaLength;
+} RESTART_BLOCK;
+
+typedef enum _OSAREA_USAGE {
+ Empty = 0,
+ Used = 1
+} OSAREA_USAGE;
+
+typedef enum _PM_MODE {
+ Suspend = 0x80, /* Part of state is in memory */
+ Normal = 0x00 /* No power management in effect */
+} PMMode;
+
+typedef struct _HEADER {
+ unsigned short Size; /* NVRAM size in K(1024) */
+ unsigned char Version; /* Structure map different */
+ unsigned char Revision; /* Structure map the same -may
+ be new values in old fields
+ in other words old code still works */
+ unsigned short Crc1; /* check sum from beginning of nvram to OSArea */
+ unsigned short Crc2; /* check sum of config */
+ unsigned char LastOS; /* OS_ID */
+ unsigned char Endian; /* B if big endian, L if little endian */
+ unsigned char OSAreaUsage; /* OSAREA_USAGE */
+ unsigned char PMMode; /* Shutdown mode */
+ RESTART_BLOCK RestartBlock;
+ SECURITY Security;
+ ERROR_LOG ErrorLog[2];
+
+ /* Global Environment information */
+ void * GEAddress;
+ unsigned long GELength;
+
+ /* Date&Time from RTC of last change to Global Environment */
+ unsigned long GELastWriteDT[2];
+
+ /* Configuration information */
+ void * ConfigAddress;
+ unsigned long ConfigLength;
+
+ /* Date&Time from RTC of last change to Configuration */
+ unsigned long ConfigLastWriteDT[2];
+ unsigned long ConfigCount; /* Count of entries in Configuration */
+
+ /* OS dependent temp area */
+ void * OSAreaAddress;
+ unsigned long OSAreaLength;
+
+ /* Date&Time from RTC of last change to OSAreaArea */
+ unsigned long OSAreaLastWriteDT[2];
+} HEADER;
+
+/* Here is the whole map of the NVRAM */
+typedef struct _NVRAM_MAP {
+ HEADER Header;
+ unsigned char GEArea[NVSIZE-CONFSIZE-OSAREASIZE-sizeof(HEADER)];
+ unsigned char OSArea[OSAREASIZE];
+ unsigned char ConfigArea[CONFSIZE];
+} NVRAM_MAP;
+
+/* Routines to manipulate the NVRAM */
+void init_prep_nvram(void);
+char *prep_nvram_get_var(const char *name);
+char *prep_nvram_first_var(void);
+char *prep_nvram_next_var(char *name);
+
+/* Routines to read and write directly to the NVRAM */
+unsigned char prep_nvram_read_val(int addr);
+void prep_nvram_write_val(int addr,


+ unsigned char val);
+

+#endif /* _PPC_PREP_NVRAM_H */
diff -u --recursive --new-file v2.2.7/linux/include/asm-ppc/processor.h linux/include/asm-ppc/processor.h
--- v2.2.7/linux/include/asm-ppc/processor.h Tue Mar 23 14:35:48 1999
+++ linux/include/asm-ppc/processor.h Tue May 11 08:24:32 1999
@@ -175,67 +175,13 @@
X #define SR15 15
X
X #ifndef __ASSEMBLY__
-/*
- * If we've configured for a specific machine set things
- * up so the compiler can optimize away the other parts.


- * -- Cort
- */

-#ifdef CONFIG_MACH_SPECIFIC
-#ifdef CONFIG_PREP
-#define _machine (_MACH_prep)
-#define is_prep (1)
-#define is_chrp (0)
-#define have_of (0)
-#endif /* CONFIG_PREP */
-
-#ifdef CONFIG_CHRP
-#define _machine (_MACH_chrp)
-#define is_prep (0)
-#define is_chrp (1)
-#define have_of (1)
-#endif /* CONFIG_CHRP */
-
-#ifdef CONFIG_PMAC
-#define _machine (_MACH_Pmac)
-#define is_prep (0)
-#define is_chrp (0)
-#define have_of (1)
-#endif /* CONFIG_PMAC */
-
-#ifdef CONFIG_MBX
-#define _machine (_MACH_mbx)
-#define is_prep (0)
-#define is_chrp (0)
-#define have_of (0)


-#endif /* CONFIG_MBX */
-

-#ifdef CONFIG_FADS
-#define _machine (_MACH_fads)
-#define is_prep (0)
-#define is_chrp (0)
-#define have_of (0)
-#endif /* CONFIG_FADS */
-
-#ifdef CONFIG_APUS
-#define _machine (_MACH_apus)
-#define is_prep (0)
-#define is_chrp (0)
-#define have_of (0)
-#endif /* CONFIG_APUS */
-
-#else /* CONFIG_MACH_SPECIFIC */
-
X extern int _machine;
X
-/* if we're a prep machine */
-#define is_prep (_machine == _MACH_prep)
-
-/* if we're a chrp machine */
-#define is_chrp (_machine == _MACH_chrp)
-


-/* if we have openfirmware */

-extern unsigned long have_of;
-#endif /* CONFIG_MACH_SPECIFIC */
+/* Temporary hacks until we can clean things up better - Corey */
+extern int have_of;
+extern int is_prep;
+extern int is_chrp;
+extern int is_powerplus;
X
X /* what kind of prep workstation we are */
X extern int _prep_type;
@@ -289,7 +235,6 @@
X double fpr[32]; /* Complete floating point set */
X unsigned long fpscr_pad; /* fpr ... fpscr must be contiguous */
X unsigned long fpscr; /* Floating point status */
- unsigned long smp_fork_ret;
X };
X
X #define INIT_SP (sizeof(init_stack) + (unsigned long) &init_stack)
@@ -301,7 +246,7 @@
X (struct pt_regs *)INIT_SP - 1, /* regs */ \
X KERNEL_DS, /*fs*/ \
X 0, /* last_syscall */ \
- {0}, 0, 0, 0 \
+ {0}, 0, 0 \
X }
X
X /*
@@ -338,14 +283,10 @@


X #define init_task (init_task_union.task)
X #define init_stack (init_task_union.stack)

X
+/* In misc.c */
+void _nmask_and_or_msr(unsigned long nmask, unsigned long or_val);
+
X #endif /* ndef ASSEMBLY*/
X
X
X #endif /* __ASM_PPC_PROCESSOR_H */


-
-
-
-
-
-

-
diff -u --recursive --new-file v2.2.7/linux/include/asm-ppc/raven.h linux/include/asm-ppc/raven.h
--- v2.2.7/linux/include/asm-ppc/raven.h Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ppc/raven.h Tue May 11 08:24:32 1999
@@ -0,0 +1,33 @@
+/*
+ * asm-ppc/raven.h -- Raven MPIC chip.
+ *
+ * Copyright (C) 1998 Johnnie Peters
+ *


+ * 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.

+ */
+
+#ifndef _ASMPPC_RAVEN_H
+#define _ASMPPC_RAVEN_H
+
+#define MVME2600_INT_SIO 0
+#define MVME2600_INT_FALCN_ECC_ERR 1
+#define MVME2600_INT_PCI_ETHERNET 2
+#define MVME2600_INT_PCI_SCSI 3
+#define MVME2600_INT_PCI_GRAPHICS 4
+#define MVME2600_INT_PCI_VME0 5
+#define MVME2600_INT_PCI_VME1 6
+#define MVME2600_INT_PCI_VME2 7
+#define MVME2600_INT_PCI_VME3 8
+#define MVME2600_INT_PCI_INTA 9
+#define MVME2600_INT_PCI_INTB 10
+#define MVME2600_INT_PCI_INTC 11
+#define MVME2600_INT_PCI_INTD 12
+#define MVME2600_INT_LM_SIG0 13
+#define MVME2600_INT_LM_SIG1 14
+
+extern struct hw_interrupt_type raven_pic;
+
+extern int raven_init(void);
+#endif _ASMPPC_RAVEN_H
diff -u --recursive --new-file v2.2.7/linux/include/asm-ppc/smp.h linux/include/asm-ppc/smp.h
--- v2.2.7/linux/include/asm-ppc/smp.h Tue Mar 23 14:35:48 1999
+++ linux/include/asm-ppc/smp.h Thu Apr 29 12:39:07 1999
@@ -27,6 +27,7 @@
X
X extern void smp_message_pass(int target, int msg, unsigned long data, int wait);
X extern void smp_store_cpu_info(int id);
+extern void smp_message_recv(void);
X
X #define NO_PROC_ID 0xFF /* No processor magic marker */
X #define PROC_CHANGE_PENALTY 20
diff -u --recursive --new-file v2.2.7/linux/include/asm-ppc/softirq.h linux/include/asm-ppc/softirq.h
--- v2.2.7/linux/include/asm-ppc/softirq.h Tue Mar 23 14:35:48 1999
+++ linux/include/asm-ppc/softirq.h Thu Apr 29 12:39:07 1999
@@ -4,7 +4,7 @@
X #include <asm/atomic.h>
X #include <asm/hardirq.h>
X
-extern unsigned int local_bh_count[NR_CPUS];


+extern unsigned int ppc_local_bh_count[NR_CPUS];

X
X #define get_active_bhs() (bh_mask & bh_active)
X #define clear_active_bhs(x) atomic_clear_mask((x),&bh_active)


@@ -29,6 +29,7 @@
X }
X

X #ifdef __SMP__
+
X /*
X * The locking mechanism for base handlers, to prevent re-entrancy,
X * is entirely private to an implementation, it should not be
@@ -55,7 +56,7 @@
X {
X if (!test_and_set_bit(0,&global_bh_count)) {
X if (atomic_read(&global_bh_lock) == 0) {
- ++local_bh_count[cpu];
+ ++ppc_local_bh_count[cpu];
X return 1;
X }
X clear_bit(0,&global_bh_count);
@@ -65,30 +66,30 @@
X
X static inline void softirq_endlock(int cpu)
X {
- local_bh_count[cpu]--;
+ ppc_local_bh_count[cpu]--;
X clear_bit(0,&global_bh_count);
X }
X
-#else /* __SMP__ */
+#else
X
X extern inline void start_bh_atomic(void)
X {
- local_bh_count[smp_processor_id()]++;
+ ppc_local_bh_count[smp_processor_id()]++;
X barrier();
X }
X
X extern inline void end_bh_atomic(void)
X {
X barrier();
- local_bh_count[smp_processor_id()]--;
+ ppc_local_bh_count[smp_processor_id()]--;
X }
X
X /* These are for the irq's testing the lock */
-#define softirq_trylock(cpu) (local_bh_count[cpu] ? 0 : (local_bh_count[cpu]=1))
-#define softirq_endlock(cpu) (local_bh_count[cpu] = 0)
-#define synchronize_bh() do { } while (0)
+#define softirq_trylock(cpu) (ppc_local_bh_count[cpu] ? 0 : (ppc_local_bh_count[cpu]=1))
+#define softirq_endlock(cpu) (ppc_local_bh_count[cpu] = 0)
+#define synchronize_bh() barrier()
X
-#endif /* __SMP__ */
+#endif /* SMP */
X
X /*
X * These use a mask count to correctly handle
@@ -107,4 +108,4 @@
X bh_mask |= 1 << nr;
X }
X
-#endif
+#endif /* __ASM_SOFTIRQ_H */
diff -u --recursive --new-file v2.2.7/linux/include/asm-ppc/string.h linux/include/asm-ppc/string.h
--- v2.2.7/linux/include/asm-ppc/string.h Sat Aug 16 09:51:09 1997
+++ linux/include/asm-ppc/string.h Thu Apr 29 12:39:07 1999
@@ -14,5 +14,6 @@
X #define __HAVE_ARCH_MEMCHR
X
X extern int strcasecmp(const char *, const char *);
+extern int strncasecmp(const char *, const char *, int);
X
X #endif
diff -u --recursive --new-file v2.2.7/linux/include/asm-ppc/system.h linux/include/asm-ppc/system.h
--- v2.2.7/linux/include/asm-ppc/system.h Tue Mar 23 14:35:48 1999
+++ linux/include/asm-ppc/system.h Tue May 11 08:24:32 1999
@@ -25,6 +25,9 @@
X #define rmb() __asm__ __volatile__ ("sync" : : : "memory")
X #define wmb() __asm__ __volatile__ ("eieio" : : : "memory")
X
+extern void xmon_irq(int, void *, struct pt_regs *);
+extern void xmon(struct pt_regs *excp);
+
X #define __save_flags(flags) ({\
X __asm__ __volatile__ ("mfmsr %0" : "=r" ((flags)) : : "memory"); })
X #define __save_and_cli(flags) ({__save_flags(flags);__cli();})
@@ -38,10 +41,10 @@
X
X extern __inline__ void __restore_flags(unsigned long flags)
X {
- extern atomic_t n_lost_interrupts;
+ extern atomic_t ppc_n_lost_interrupts;


X extern void do_lost_interrupts(unsigned long);
X

- if ((flags & MSR_EE) && atomic_read(&n_lost_interrupts) != 0) {
+ if ((flags & MSR_EE) && atomic_read(&ppc_n_lost_interrupts) != 0) {
X do_lost_interrupts(flags);
X } else {
X __asm__ __volatile__ ("sync; mtmsr %0; isync"
@@ -68,8 +71,8 @@
X extern void pmac_nvram_init(void);
X extern void read_rtc_time(void);
X extern void pmac_find_display(void);
-extern void giveup_fpu(void);
-extern void smp_giveup_fpu(struct task_struct *);
+extern void giveup_fpu(struct task_struct *);
+extern void enable_kernel_fp(void);
X extern void cvt_fd(float *from, double *to, unsigned long *fpscr);
X extern void cvt_df(double *from, float *to, unsigned long *fpscr);
X
@@ -77,11 +80,14 @@
X extern void note_scsi_host(struct device_node *, void *);
X
X struct task_struct;
-extern void switch_to(struct task_struct *prev, struct task_struct *next);
+#define switch_to(prev,next,last) _switch_to((prev),(next),&(last))
+extern void _switch_to(struct task_struct *, struct task_struct *,
+ struct task_struct **);
X
X struct thread_struct;
-extern void _switch(struct thread_struct *prev, struct thread_struct *next,
- unsigned long context);
+extern struct task_struct *_switch(struct thread_struct *prev,
+ struct thread_struct *next,
+ unsigned long context);
X
X struct pt_regs;
X extern void dump_regs(struct pt_regs *);
diff -u --recursive --new-file v2.2.7/linux/include/asm-ppc/vga.h linux/include/asm-ppc/vga.h
--- v2.2.7/linux/include/asm-ppc/vga.h Tue Mar 23 14:35:48 1999
+++ linux/include/asm-ppc/vga.h Thu Apr 29 12:39:07 1999
@@ -46,7 +46,8 @@
X #define scr_memcpyw_from memcpy
X #define scr_memcpyw_to memcpy
X
-#define VGA_MAP_MEM(x) (x + _ISA_MEM_BASE)
+extern unsigned long vgacon_remap_base;
+#define VGA_MAP_MEM(x) (x + vgacon_remap_base)


X #define vga_readb(x) (*(x))
X #define vga_writeb(x,y) (*(y) = (x))

X
diff -u --recursive --new-file v2.2.7/linux/include/asm-sparc/siginfo.h linux/include/asm-sparc/siginfo.h
--- v2.2.7/linux/include/asm-sparc/siginfo.h Wed Apr 28 11:37:31 1999
+++ linux/include/asm-sparc/siginfo.h Wed Apr 28 14:40:07 1999
@@ -1,4 +1,4 @@
-/* $Id: siginfo.h,v 1.3 1998/08/26 10:33:29 davem Exp $
+/* $Id: siginfo.h,v 1.4 1999/04/28 19:45:20 davem Exp $
X * siginfo.c:
X */
X
diff -u --recursive --new-file v2.2.7/linux/include/asm-sparc/smp.h linux/include/asm-sparc/smp.h
--- v2.2.7/linux/include/asm-sparc/smp.h Tue Mar 23 14:35:48 1999
+++ linux/include/asm-sparc/smp.h Tue May 11 08:24:32 1999
@@ -157,6 +157,7 @@
X #endif
X
X #define smp_processor_id() hard_smp_processor_id()
+/* XXX We really need to implement this now. -DaveM */
X extern __inline__ void smp_send_reschedule(int cpu) { }
X extern __inline__ void smp_send_stop(void) { }
X
diff -u --recursive --new-file v2.2.7/linux/include/asm-sparc/system.h linux/include/asm-sparc/system.h
--- v2.2.7/linux/include/asm-sparc/system.h Wed Apr 28 11:37:31 1999
+++ linux/include/asm-sparc/system.h Tue May 11 08:24:32 1999
@@ -1,4 +1,4 @@
-/* $Id: system.h,v 1.73 1999/04/20 13:22:49 anton Exp $ */
+/* $Id: system.h,v 1.74 1999/05/08 03:03:14 davem Exp $ */
X #include <linux/config.h>
X
X #ifndef __SPARC_SYSTEM_H
@@ -84,8 +84,15 @@
X #define SWITCH_DO_LAZY_FPU if(last_task_used_math != next) next->tss.kregs->psr&=~PSR_EF;
X #endif
X
- /* Much care has gone into this code, do not touch it. */
-#define switch_to(prev, next) do { \
+ /* Much care has gone into this code, do not touch it.
+ *
+ * We need to loadup regs l0/l1 for the newly forked child
+ * case because the trap return path relies on those registers
+ * holding certain values, gcc is told that they are clobbered.
+ * Gcc needs registers for 3 values in and 1 value out, so we
+ * clobber every non-fixed-usage register besides l2/l3/o4/o5. -DaveM
+ */
+#define switch_to(prev, next, last) do { \
X __label__ here; \
X register unsigned long task_pc asm("o7"); \
X extern struct task_struct *current_set[NR_CPUS]; \
@@ -103,21 +110,22 @@
X next->mm->cpu_vm_mask |= (1 << smp_processor_id()); \
X task_pc = ((unsigned long) &&here) - 0x8; \
X __asm__ __volatile__( \
+ "mov %%g6, %%g3\n\t" \
X "rd %%psr, %%g4\n\t" \
- "std %%sp, [%%g6 + %3]\n\t" \
+ "std %%sp, [%%g6 + %4]\n\t" \
X "rd %%wim, %%g5\n\t" \
X "wr %%g4, 0x20, %%psr\n\t" \
X "nop\n\t" \
- "std %%g4, [%%g6 + %2]\n\t" \
- "ldd [%1 + %2], %%g4\n\t" \
- "mov %1, %%g6\n\t" \
+ "std %%g4, [%%g6 + %3]\n\t" \
+ "ldd [%2 + %3], %%g4\n\t" \
+ "mov %2, %%g6\n\t" \
X ".globl patchme_store_new_current\n" \
X "patchme_store_new_current:\n\t" \
- "st %1, [%0]\n\t" \
+ "st %2, [%1]\n\t" \
X "wr %%g4, 0x20, %%psr\n\t" \
X "nop\n\t" \
X "nop\n\t" \
- "ldd [%%g6 + %3], %%sp\n\t" \
+ "ldd [%%g6 + %4], %%sp\n\t" \
X "wr %%g5, 0x0, %%wim\n\t" \
X "ldd [%%sp + 0x00], %%l0\n\t" \
X "ldd [%%sp + 0x38], %%i6\n\t" \
@@ -125,11 +133,13 @@
X "nop\n\t" \
X "nop\n\t" \
X "jmpl %%o7 + 0x8, %%g0\n\t" \
- " nop\n\t" : : "r" (&(current_set[hard_smp_processor_id()])), "r" (next), \
+ " mov %%g3, %0\n\t" \
+ : "=&r" (last) \
+ : "r" (&(current_set[hard_smp_processor_id()])), "r" (next), \
X "i" ((const unsigned long)(&((struct task_struct *)0)->tss.kpsr)), \
X "i" ((const unsigned long)(&((struct task_struct *)0)->tss.ksp)), \
X "r" (task_pc) \
- : "g1", "g2", "g3", "g4", "g5", "g7", "l2", "l3", \
+ : "g1", "g2", "g3", "g4", "g5", "g7", "l0", "l1", \
X "l4", "l5", "l6", "l7", "i0", "i1", "i2", "i3", "i4", "i5", "o0", "o1", "o2", \
X "o3"); \
X here: } while(0)
diff -u --recursive --new-file v2.2.7/linux/include/asm-sparc64/mmu_context.h linux/include/asm-sparc64/mmu_context.h
--- v2.2.7/linux/include/asm-sparc64/mmu_context.h Tue Mar 23 14:35:48 1999
+++ linux/include/asm-sparc64/mmu_context.h Tue May 11 08:24:32 1999
@@ -1,4 +1,4 @@
-/* $Id: mmu_context.h,v 1.34 1999/01/11 13:45:44 davem Exp $ */
+/* $Id: mmu_context.h,v 1.35 1999/05/08 03:03:20 davem Exp $ */
X #ifndef __SPARC64_MMU_CONTEXT_H
X #define __SPARC64_MMU_CONTEXT_H
X
@@ -13,7 +13,6 @@
X #ifndef __ASSEMBLY__
X
X extern unsigned long tlb_context_cache;
-extern spinlock_t scheduler_lock;
X extern unsigned long mmu_context_bmap[];
X
X #define CTX_VERSION_SHIFT (PAGE_SHIFT - 3)
@@ -38,11 +37,9 @@
X #define destroy_context(__mm) do { \
X if ((__mm)->context != NO_CONTEXT && \
X atomic_read(&(__mm)->count) == 1) { \
- spin_lock(&scheduler_lock); \
X if (!(((__mm)->context ^ tlb_context_cache) & CTX_VERSION_MASK))\
X clear_bit((__mm)->context & ~(CTX_VERSION_MASK), \
X mmu_context_bmap); \
- spin_unlock(&scheduler_lock); \
X (__mm)->context = NO_CONTEXT; \
X if(current->mm == (__mm)) { \
X current->tss.ctx = 0; \
@@ -126,9 +123,7 @@
X #define activate_context(__tsk) \
X do { flushw_user(); \
X (__tsk)->mm->cpu_vm_mask = 0; \
- spin_lock(&scheduler_lock); \
X __get_mmu_context(__tsk); \
- spin_unlock(&scheduler_lock); \
X (__tsk)->mm->cpu_vm_mask = (1UL<<smp_processor_id()); \
X } while(0)
X
diff -u --recursive --new-file v2.2.7/linux/include/asm-sparc64/system.h linux/include/asm-sparc64/system.h
--- v2.2.7/linux/include/asm-sparc64/system.h Tue Mar 23 14:35:48 1999
+++ linux/include/asm-sparc64/system.h Tue May 11 08:24:32 1999
@@ -1,4 +1,4 @@
-/* $Id: system.h,v 1.48 1999/01/02 16:50:28 davem Exp $ */
+/* $Id: system.h,v 1.50 1999/05/08 03:03:22 davem Exp $ */
X #ifndef __SPARC64_SYSTEM_H
X #define __SPARC64_SYSTEM_H
X
@@ -48,7 +48,7 @@
X ({ unsigned long retval; \
X __asm__ __volatile__("rdpr %%pil, %0\n\t" \
X "wrpr %1, %%pil" \
- : "=r" (retval) \
+ : "=&r" (retval) \
X : "r" (__new_pil) \
X : "memory"); \
X retval; \
@@ -127,21 +127,14 @@
X
X /* See what happens when you design the chip correctly?
X *
- * XXX What we are doing here assumes a lot about gcc reload
- * XXX internals, it heavily risks compiler aborts due to
- * XXX forbidden registers being spilled. Rewrite me... -DaveM
- *
- * SMP NOTE: At first glance it looks like there is a tiny
- * race window here at the end. The possible problem
- * would be if a tlbcachesync MONDO vector got delivered
- * to us right before we set the final %g6 thread reg
- * value. But that is impossible since only the holder
- * of scheduler_lock can send a tlbcachesync MONDO and
- * by definition we hold it right now. Normal tlb
- * flush xcalls can come in, but those are safe and do
- * not reference %g6.
+ * We tell gcc we clobber all non-fixed-usage registers except
+ * for l0/l1. It will use one for 'next' and the other to hold
+ * the output value of 'last'. 'next' is not referenced again
+ * past the invocation of switch_to in the scheduler, so we need
+ * not preserve it's value. Hairy, but it lets us remove 2 loads
+ * and 2 stores in this critical code path. -DaveM
X */
-#define switch_to(prev, next) \
+#define switch_to(prev, next, last) \
X do { if (current->tss.flags & SPARC_FLAG_PERFCTR) { \
X unsigned long __tmp; \
X read_pcr(__tmp); \
@@ -157,26 +150,23 @@
X __get_mmu_context(next); \
X (next)->mm->cpu_vm_mask |= (1UL << smp_processor_id()); \
X __asm__ __volatile__( \
+ "mov %%g6, %%g5\n\t" \
X "wrpr %%g0, 0x95, %%pstate\n\t" \
- "stx %%l0, [%%sp + 2047 + 0x60]\n\t" \
- "stx %%l1, [%%sp + 2047 + 0x68]\n\t" \
X "stx %%i6, [%%sp + 2047 + 0x70]\n\t" \
X "stx %%i7, [%%sp + 2047 + 0x78]\n\t" \
X "rdpr %%wstate, %%o5\n\t" \
- "stx %%o6, [%%g6 + %2]\n\t" \
- "sth %%o5, [%%g6 + %1]\n\t" \
+ "stx %%o6, [%%g6 + %3]\n\t" \
+ "sth %%o5, [%%g6 + %2]\n\t" \
X "rdpr %%cwp, %%o5\n\t" \
- "sth %%o5, [%%g6 + %4]\n\t" \
- "mov %0, %%g6\n\t" \
- "lduh [%0 + %4], %%g1\n\t" \
+ "sth %%o5, [%%g6 + %5]\n\t" \
+ "mov %1, %%g6\n\t" \
+ "lduh [%1 + %5], %%g1\n\t" \
X "wrpr %%g1, %%cwp\n\t" \
- "ldx [%%g6 + %2], %%o6\n\t" \
- "lduh [%%g6 + %1], %%o5\n\t" \
- "lduh [%%g6 + %3], %%o7\n\t" \
+ "ldx [%%g6 + %3], %%o6\n\t" \
+ "lduh [%%g6 + %2], %%o5\n\t" \
+ "lduh [%%g6 + %4], %%o7\n\t" \
X "mov %%g6, %%l2\n\t" \
X "wrpr %%o5, 0x0, %%wstate\n\t" \
- "ldx [%%sp + 2047 + 0x60], %%l0\n\t" \
- "ldx [%%sp + 2047 + 0x68], %%l1\n\t" \
X "ldx [%%sp + 2047 + 0x70], %%i6\n\t" \
X "ldx [%%sp + 2047 + 0x78], %%i7\n\t" \
X "wrpr %%g0, 0x94, %%pstate\n\t" \
@@ -184,8 +174,8 @@
X "wrpr %%g0, 0x96, %%pstate\n\t" \
X "andcc %%o7, 0x100, %%g0\n\t" \
X "bne,pn %%icc, ret_from_syscall\n\t" \
- " nop\n\t" \
- : \
+ " mov %%g5, %0\n\t" \
+ : "=&r" (last) \
X : "r" (next), \
X "i" ((const unsigned long)(&((struct task_struct *)0)->tss.wstate)), \
X "i" ((const unsigned long)(&((struct task_struct *)0)->tss.ksp)), \
diff -u --recursive --new-file v2.2.7/linux/include/asm-sparc64/uaccess.h linux/include/asm-sparc64/uaccess.h
--- v2.2.7/linux/include/asm-sparc64/uaccess.h Sun Nov 8 14:03:11 1998
+++ linux/include/asm-sparc64/uaccess.h Tue May 11 08:24:32 1999
@@ -1,4 +1,4 @@
-/* $Id: uaccess.h,v 1.28 1998/10/11 06:58:34 davem Exp $ */
+/* $Id: uaccess.h,v 1.29 1999/05/08 03:03:25 davem Exp $ */
X #ifndef _ASM_UACCESS_H
X #define _ASM_UACCESS_H
X
@@ -41,12 +41,9 @@
X
X #define segment_eq(a,b) ((a).seg == (b).seg)
X
-extern spinlock_t scheduler_lock;
-
X #define set_fs(val) \
X do { \
X if (current->tss.current_ds.seg != val.seg) { \
- spin_lock(&scheduler_lock); \
X current->tss.current_ds = (val); \
X if (segment_eq((val), KERNEL_DS)) { \
X flushw_user (); \
@@ -56,7 +53,6 @@
X } \
X spitfire_set_secondary_context(current->tss.ctx); \
X __asm__ __volatile__("flush %g6"); \
- spin_unlock(&scheduler_lock); \
X } \
X } while(0)
X
diff -u --recursive --new-file v2.2.7/linux/include/linux/capability.h linux/include/linux/capability.h
--- v2.2.7/linux/include/linux/capability.h Fri Oct 23 22:01:26 1998
+++ linux/include/linux/capability.h Tue May 11 10:35:45 1999
@@ -193,7 +193,6 @@
X /* Allow device administration (mknod)*/
X /* Allow examination and configuration of disk quotas */
X /* Allow configuring the kernel's syslog (printk behaviour) */
-/* Allow sending a signal to any process */
X /* Allow setting the domainname */
X /* Allow setting the hostname */
X /* Allow calling bdflush() */
diff -u --recursive --new-file v2.2.7/linux/include/linux/dcache.h linux/include/linux/dcache.h
--- v2.2.7/linux/include/linux/dcache.h Tue Mar 23 14:35:48 1999
+++ linux/include/linux/dcache.h Sat May 8 17:56:37 1999
@@ -77,7 +77,7 @@
X };
X
X struct dentry_operations {
- int (*d_revalidate)(struct dentry *);
+ int (*d_revalidate)(struct dentry *, int);
X int (*d_hash) (struct dentry *, struct qstr *);
X int (*d_compare) (struct dentry *, struct qstr *, struct qstr *);
X void (*d_delete)(struct dentry *);
diff -u --recursive --new-file v2.2.7/linux/include/linux/fs.h linux/include/linux/fs.h
--- v2.2.7/linux/include/linux/fs.h Wed Apr 28 11:37:31 1999
+++ linux/include/linux/fs.h Tue May 11 10:35:44 1999
@@ -810,6 +810,18 @@
X #define PTR_ERR(ptr) ((long)(ptr))
X #define IS_ERR(ptr) ((unsigned long)(ptr) > (unsigned long)(-1000))
X
+/*
+ * The bitmask for a lookup event:
+ * - follow links at the end
+ * - require a directory
+ * - ending slashes ok even for nonexistent files
+ * - internal "there are more path compnents" flag
+ */
+#define LOOKUP_FOLLOW (1)
+#define LOOKUP_DIRECTORY (2)
+#define LOOKUP_SLASHOK (4)
+#define LOOKUP_CONTINUE (8)
+
X extern struct dentry * lookup_dentry(const char *, struct dentry *, unsigned int);
X extern struct dentry * __namei(const char *, unsigned int);
X
diff -u --recursive --new-file v2.2.7/linux/include/linux/nfs_fs.h linux/include/linux/nfs_fs.h
--- v2.2.7/linux/include/linux/nfs_fs.h Wed Mar 10 15:29:50 1999
+++ linux/include/linux/nfs_fs.h Tue May 11 10:35:46 1999
@@ -181,6 +181,8 @@
X struct nfs_fattr *);
X extern int nfs_refresh_inode(struct inode *, struct nfs_fattr *);
X extern int nfs_revalidate(struct dentry *);
+extern int nfs_open(struct inode *, struct file *);
+extern int nfs_release(struct inode *, struct file *);
X extern int _nfs_revalidate_inode(struct nfs_server *, struct dentry *);


SHAR_EOF
true || echo 'restore of patch-2.2.8 failed'
fi

echo 'End of part 31'
echo 'File patch-2.2.8 is continued in part 32'
echo 32 > _shar_seq_.tmp

Thomas...@ciw.uni-karlsruhe.de

unread,
May 12, 1999, 3:00:00 AM5/12/99
to
Archive-name: v2.2/patch-2.2.8/part32

#!/bin/sh
# this is part 32 of a 33 - part archive


# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.8 continued
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 32; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.8'
else
echo 'x - continuing with patch-2.2.8'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.8' &&

X
X /*
diff -u --recursive --new-file v2.2.7/linux/include/linux/pagemap.h linux/include/linux/pagemap.h
--- v2.2.7/linux/include/linux/pagemap.h Wed Apr 28 11:37:31 1999
+++ linux/include/linux/pagemap.h Tue May 11 10:35:49 1999
@@ -17,6 +17,27 @@
X return PAGE_OFFSET + PAGE_SIZE * (page - mem_map);
X }
X
+/*
+ * The page cache can done in larger chunks than
+ * one page, because it allows for more efficient
+ * throughput (it can then be mapped into user
+ * space in smaller chunks for same flexibility).
+ *
+ * Or rather, it _will_ be done in larger chunks.
+ */
+#define PAGE_CACHE_SHIFT PAGE_SHIFT
+#define PAGE_CACHE_SIZE PAGE_SIZE
+#define PAGE_CACHE_MASK PAGE_MASK
+
+#define page_cache_alloc() __get_free_page(GFP_USER)
+#define page_cache_free(x) free_page(x)
+#define page_cache_release(x) __free_page(x)
+
+/*
+ * From a kernel address, get the "struct page *"
+ */
+#define page_cache_entry(x) (mem_map + MAP_NR(x))
+
X #define PAGE_HASH_BITS 12
X #define PAGE_HASH_SIZE (1 << PAGE_HASH_BITS)
X
diff -u --recursive --new-file v2.2.7/linux/include/linux/parport_pc.h linux/include/linux/parport_pc.h
--- v2.2.7/linux/include/linux/parport_pc.h Fri Oct 23 22:01:27 1998
+++ linux/include/linux/parport_pc.h Tue May 11 10:36:23 1999
@@ -14,8 +14,15 @@
X #define STATUS 0x1
X #define DATA 0
X
+/* Private data for PC low-level driver. */
+struct parport_pc_private {
+ /* Contents of CTR. */
+ unsigned char ctr;
+};
+
X extern int parport_pc_epp_clear_timeout(struct parport *pb);
X
+extern volatile unsigned char parport_pc_ctr;
X
X extern __inline__ void parport_pc_write_epp(struct parport *p, unsigned char d)
X {
@@ -62,19 +69,24 @@
X
X extern __inline__ void parport_pc_write_control(struct parport *p, unsigned char d)


X {
+ struct parport_pc_private *priv = p->private_data;
+ priv->ctr = d;/* update soft copy */
X outb(d, p->base+CONTROL);
X }

X
X extern __inline__ unsigned char parport_pc_read_control(struct parport *p)


X {
- return inb(p->base+CONTROL);
+ struct parport_pc_private *priv = p->private_data;
+ return priv->ctr;
X }

X
X extern __inline__ unsigned char parport_pc_frob_control(struct parport *p, unsigned char mask, unsigned char val)
X {


- unsigned char old = inb(p->base+CONTROL);
- outb(((old & ~mask) ^ val), p->base+CONTROL);
- return old;
+ struct parport_pc_private *priv = p->private_data;
+ unsigned char ctr = priv->ctr;
+ ctr = (ctr & ~mask) ^ val;
+ outb (ctr, p->base+CONTROL);
+ return priv->ctr = ctr; /* update soft copy */
X }

X
X extern __inline__ void parport_pc_write_status(struct parport *p, unsigned char d)
diff -u --recursive --new-file v2.2.7/linux/include/linux/sched.h linux/include/linux/sched.h
--- v2.2.7/linux/include/linux/sched.h Mon Mar 29 11:09:12 1999
+++ linux/include/linux/sched.h Tue May 11 10:35:45 1999
@@ -112,10 +112,10 @@
X * a separate lock).
X */
X extern rwlock_t tasklist_lock;
-extern spinlock_t scheduler_lock;
X extern spinlock_t runqueue_lock;
X
X extern void sched_init(void);
+extern void init_idle(void);
X extern void show_state(void);
X extern void trap_init(void);
X
diff -u --recursive --new-file v2.2.7/linux/include/linux/smp.h linux/include/linux/smp.h
--- v2.2.7/linux/include/linux/smp.h Mon Dec 28 15:00:53 1998
+++ linux/include/linux/smp.h Tue May 11 10:35:44 1999
@@ -42,6 +42,12 @@
X extern void smp_commence(void);
X
X /*
+ * Call a function on all other processors
+ */
+extern int smp_call_function (void (*func) (void *info), void *info,
+ int retry, int wait);
+
+/*
X * True once the per process idle is forked
X */
X extern int smp_threads_ready;
@@ -60,7 +66,7 @@
X * when rebooting
X */
X #define MSG_RESCHEDULE 0x0003 /* Reschedule request from master CPU*/
-#define MSG_MTRR_CHANGE 0x0004 /* Change MTRR */
+#define MSG_CALL_FUNCTION 0x0004 /* Call function on all other CPUs */
X
X #else
X
@@ -68,12 +74,13 @@
X * These macros fold the SMP functionality into a single CPU system
X */
X
-#define smp_num_cpus 1
-#define smp_processor_id() 0
-#define hard_smp_processor_id() 0
-#define smp_threads_ready 1
+#define smp_num_cpus 1
+#define smp_processor_id() 0
+#define hard_smp_processor_id() 0
+#define smp_threads_ready 1
X #define kernel_lock()
-#define cpu_logical_map(cpu) 0
+#define cpu_logical_map(cpu) 0
+#define smp_call_function(func,info,retry,wait)
X
X #endif
X #endif
diff -u --recursive --new-file v2.2.7/linux/include/linux/videodev.h linux/include/linux/videodev.h
--- v2.2.7/linux/include/linux/videodev.h Tue Feb 23 15:21:35 1999
+++ linux/include/linux/videodev.h Fri May 7 11:05:30 1999
@@ -95,6 +95,8 @@
X #define VIDEO_TUNER_LOW 8 /* Uses KHz not MHz */
X #define VIDEO_TUNER_NORM 16 /* Tuner can set norm */
X #define VIDEO_TUNER_STEREO_ON 128 /* Tuner is seeing stereo */
+#define VIDEO_TUNER_RDS_ON 256 /* Tuner is seeing an RDS datastream */
+#define VIDEO_TUNER_MBS_ON 512 /* Tuner is seeing an MBS datastream */
X __u16 mode; /* PAL/NTSC/SECAM/OTHER */
X #define VIDEO_MODE_PAL 0
X #define VIDEO_MODE_NTSC 1
@@ -275,6 +277,7 @@
X #define VID_HARDWARE_GEMTEK 18
X #define VID_HARDWARE_TYPHOON 19
X #define VID_HARDWARE_VINO 20 /* Reserved for SGI Indy Vino */
+#define VID_HARDWARE_CADET 21 /* Cadet radio */
X
X /*
X * Initialiser list
diff -u --recursive --new-file v2.2.7/linux/include/net/tcp.h linux/include/net/tcp.h
--- v2.2.7/linux/include/net/tcp.h Wed Apr 28 11:37:32 1999
+++ linux/include/net/tcp.h Tue May 11 10:36:51 1999
@@ -174,6 +174,7 @@
X struct tcp_func *af_specific;
X struct tcp_bind_bucket *tb;
X struct tcp_tw_bucket *next_death;
+ struct tcp_tw_bucket **pprev_death;
X int death_slot;
X #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
X struct in6_addr v6_daddr;
@@ -714,6 +715,22 @@
X u32 new_win = __tcp_select_window(sk);
X
X return (new_win && (new_win > (cur_win << 1)));
+}
+
+/* Recalculate snd_ssthresh, we want to set it to:
+ *
+ * one half the current congestion window, but no
+ * less than two segments
+ *
+ * We must take into account the current send window
+ * as well, however we keep track of that using different
+ * units so a conversion is necessary. -DaveM
+ */
+extern __inline__ __u32 tcp_recalc_ssthresh(struct tcp_opt *tp)
+{
+ __u32 snd_wnd_packets = tp->snd_wnd / tp->mss_cache;
+
+ return max(min(snd_wnd_packets, tp->snd_cwnd) >> 1, 2);
X }
X
X /* TCP timestamps are only 32-bits, this causes a slight
diff -u --recursive --new-file v2.2.7/linux/include/scsi/sg.h linux/include/scsi/sg.h
--- v2.2.7/linux/include/scsi/sg.h Fri Apr 16 14:47:31 1999
+++ linux/include/scsi/sg.h Fri May 7 11:05:30 1999
@@ -12,10 +12,16 @@
X * Copyright (C) 1998, 1999 Douglas Gilbert
X
X
- Version: 2.1.31 (990327)
+ Version: 2.1.32 (990501)
X This version for later 2.1.x series and 2.2.x kernels
X D. P. Gilbert (dgil...@interlog.com, do...@triode.net.au)
X
+ Changes since 2.1.31 (990327)
+ - add ioctls SG_GET_UNDERRUN_FLAG and _SET_. Change the default
+ to _not_ flag underruns (affects aic7xxx driver)
+ - clean up logging of pointers to use %p (for 64 bit architectures)
+ - rework usage of get_user/copy_to_user family of kernel calls
+ - "disown" scsi_command blocks before releasing them
X Changes since 2.1.30 (990320)
X - memory tweaks: change flags on kmalloc (GFP_KERNEL to GFP_ATOMIC)
X - increase max allowable mid-level pool usage
@@ -113,7 +119,7 @@
X requesting 512KB) and scale them back in the face of ENOMEM errors.
X N.B. Queuing up commands also ties up kernel memory.
X
- More documentation can be found at www.netwinder.org/~dougg
+ More documentation can be found at www.torque.net/sg
X */
X
X #define SG_MAX_SENSE 16 /* too little, unlikely to change in 2.2.x */
@@ -197,6 +203,11 @@
X #define SG_GET_COMMAND_Q 0x2270 /* Yields 0 (queuing off) or 1 (on) */
X #define SG_SET_COMMAND_Q 0x2271 /* Change queuing state with 0 or 1 */
X
+/* Get/set whether DMA underrun will cause an error (DID_ERROR) [this only
+ currently applies to the [much-used] aic7xxx driver) */
+#define SG_GET_UNDERRUN_FLAG 0x2280 /* Yields 0 (don't flag) or 1 (flag) */
+#define SG_SET_UNDERRUN_FLAG 0x2281 /* Change flag underrun state */
+
X
X #define SG_DEFAULT_TIMEOUT (60*HZ) /* HZ == 'jiffies in 1 second' */
X #define SG_DEFAULT_RETRIES 1
@@ -206,6 +217,7 @@
X #define SG_DEF_MERGE_FD 0 /* was 1 -> per device sequencing */
X #define SG_DEF_FORCE_LOW_DMA 0 /* was 1 -> memory below 16MB on i386 */
X #define SG_DEF_FORCE_PACK_ID 0
+#define SG_DEF_UNDERRUN_FLAG 0
X
X /* maximum outstanding requests, write() yields EDOM if exceeded */
X #define SG_MAX_QUEUE 16
diff -u --recursive --new-file v2.2.7/linux/init/main.c linux/init/main.c
--- v2.2.7/linux/init/main.c Wed Apr 28 11:37:32 1999
+++ linux/init/main.c Tue May 11 09:57:14 1999
@@ -46,6 +46,10 @@
X #include <linux/apm_bios.h>
X #endif
X
+#ifdef CONFIG_MAC
+extern void nubus_init(void);
+#endif
+
X /*
X * Versions of gcc older than that listed below may actually compile
X * and link okay, but the end product can have subtle run time bugs.
@@ -74,7 +78,7 @@
X extern void uidcache_init(void);
X extern void mca_init(void);
X extern void sbus_init(void);
-extern void powermac_init(void);
+extern void ppc_init(void);
X extern void sysctl_init(void);
X extern void filescache_init(void);
X extern void signals_init(void);
@@ -354,7 +358,7 @@
X int rows, cols;
X
X #ifdef CONFIG_BLK_DEV_RAM
-extern int rd_doload; /* 1 = load ramdisk, 0 = don't load */
+extern int rd_doload; /* 1 = load ramdisk, 0 = don't load 2 = dual disk */


X extern int rd_prompt; /* 1 = prompt for ramdisk, 0 = don't prompt */

X extern int rd_size; /* Size of the ramdisk(s) */


X extern int rd_image_start; /* starting block # of image */

@@ -578,6 +582,7 @@
X { "no-hlt", no_halt },
X { "no387", no_387 },
X { "reboot=", reboot_setup },
+ { "mca-pentium", mca_pentium },
X #endif
X #ifdef CONFIG_INET
X { "ether=", eth_setup },
@@ -788,7 +793,8 @@
X #endif
X #if defined(CONFIG_A4000T_SCSI) || defined(CONFIG_WARPENGINE_SCSI) \
X || defined(CONFIG_A4091_SCSI) || defined(CONFIG_MVME16x_SCSI) \
- || defined(CONFIG_BVME6000_SCSI)
+ || defined(CONFIG_BVME6000_SCSI) \
+ || defined(CONFIG_BLZ603EPLUS_SCSI)
X { "53c7xx=", ncr53c7xx_setup },
X #endif
X #if defined(CONFIG_A3000_SCSI) || defined(CONFIG_A2091_SCSI) \
@@ -901,7 +907,7 @@
X static void __init load_ramdisk(char *str, int *ints)
X {
X if (ints[0] > 0 && ints[1] >= 0)
- rd_doload = ints[1] & 1;
+ rd_doload = ints[1] & 3;
X }
X
X static void __init prompt_ramdisk(char *str, int *ints)
@@ -1262,7 +1268,7 @@
X sbus_init();
X #endif
X #if defined(CONFIG_PPC)
- powermac_init();
+ ppc_init();
X #endif
X #ifdef CONFIG_MCA
X mca_init();
@@ -1275,6 +1281,9 @@
X #endif
X #ifdef CONFIG_DIO
X dio_init();
+#endif
+#ifdef CONFIG_MAC
+ nubus_init();
X #endif
X
X /* Networking initialization needs a process context */
diff -u --recursive --new-file v2.2.7/linux/ipc/shm.c linux/ipc/shm.c
--- v2.2.7/linux/ipc/shm.c Wed Apr 28 11:37:32 1999
+++ linux/ipc/shm.c Tue May 4 16:58:15 1999
@@ -634,7 +634,7 @@
X
X pte = __pte(shp->shm_pages[idx]);
X if (!pte_present(pte)) {
- unsigned long page = get_free_page(GFP_KERNEL);
+ unsigned long page = get_free_page(GFP_USER);
X if (!page) {
X oom(current);
X return 0;
diff -u --recursive --new-file v2.2.7/linux/kernel/exit.c linux/kernel/exit.c
--- v2.2.7/linux/kernel/exit.c Tue Mar 23 14:35:48 1999
+++ linux/kernel/exit.c Fri Apr 30 08:13:37 1999
@@ -32,9 +32,9 @@
X */
X for (;;) {
X int has_cpu;
- spin_lock(&scheduler_lock);
+ spin_lock_irq(&runqueue_lock);
X has_cpu = p->has_cpu;
- spin_unlock(&scheduler_lock);
+ spin_unlock_irq(&runqueue_lock);
X if (!has_cpu)
X break;
X do {
diff -u --recursive --new-file v2.2.7/linux/kernel/sched.c linux/kernel/sched.c
--- v2.2.7/linux/kernel/sched.c Tue Mar 23 14:35:48 1999
+++ linux/kernel/sched.c Mon May 10 09:55:21 1999
@@ -96,13 +96,156 @@
X
X struct task_struct * task[NR_TASKS] = {&init_task, };
X
+/*
+ * We align per-CPU scheduling data on cacheline boundaries,
+ * to prevent cacheline ping-pong.
+ */
+static union {
+ struct schedule_data {
+ struct task_struct * curr;
+ cycles_t last_schedule;
+ } schedule_data;
+ char __pad [SMP_CACHE_BYTES];
+} aligned_data [NR_CPUS] __cacheline_aligned = { {{&init_task,0}}};
+
+#define cpu_curr(cpu) aligned_data[(cpu)].schedule_data.curr
+
X struct kernel_stat kstat = { 0 };
X
+#ifdef __SMP__
+
+#define idle_task(cpu) (task[cpu_number_map[(cpu)]])
+#define can_schedule(p) (!(p)->has_cpu)
+
+#else
+
+#define idle_task(cpu) (&init_task)
+#define can_schedule(p) (1)
+
+#endif
+
X void scheduling_functions_start_here(void) { }
X
+/*
+ * This is the function that decides how desirable a process is..
+ * You can weigh different processes against each other depending
+ * on what CPU they've run on lately etc to try to handle cache
+ * and TLB miss penalties.
+ *
+ * Return values:
+ * -1000: never select this
+ * 0: out of time, recalculate counters (but it might still be
+ * selected)
+ * +ve: "goodness" value (the larger, the better)
+ * +1000: realtime process, select this.
+ */
+
+static inline int goodness (struct task_struct * prev,
+ struct task_struct * p, int this_cpu)
+{
+ int weight;
+
+ /*
+ * Realtime process, select the first one on the
+ * runqueue (taking priorities within processes
+ * into account).
+ */
+ if (p->policy != SCHED_OTHER) {
+ weight = 1000 + p->rt_priority;
+ goto out;
+ }
+
+ /*
+ * Give the process a first-approximation goodness value
+ * according to the number of clock-ticks it has left.
+ *
+ * Don't do any other calculations if the time slice is
+ * over..
+ */
+ weight = p->counter;
+ if (!weight)
+ goto out;
+
X #ifdef __SMP__
-static void reschedule_idle_slow(struct task_struct * p)
+ /* Give a largish advantage to the same processor... */
+ /* (this is equivalent to penalizing other processors) */
+ if (p->processor == this_cpu)
+ weight += PROC_CHANGE_PENALTY;
+#endif
+
+ /* .. and a slight advantage to the current MM */
+ if (p->mm == prev->mm)
+ weight += 1;
+ weight += p->priority;
+
+out:
+ return weight;
+}
+
+/*
+ * subtle. We want to discard a yielded process only if it's being
+ * considered for a reschedule. Wakeup-time 'queries' of the scheduling
+ * state do not count. Another optimization we do: sched_yield()-ed
+ * processes are runnable (and thus will be considered for scheduling)
+ * right when they are calling schedule(). So the only place we need
+ * to care about SCHED_YIELD is when we calculate the previous process'
+ * goodness ...
+ */
+static inline int prev_goodness (struct task_struct * prev,
+ struct task_struct * p, int this_cpu)
+{
+ if (p->policy & SCHED_YIELD) {
+ p->policy &= ~SCHED_YIELD;
+ return 0;
+ }
+ return goodness(prev, p, this_cpu);
+}
+
+/*
+ * the 'goodness value' of replacing a process on a given CPU.
+ * positive value means 'replace', zero or negative means 'dont'.
+ */
+static inline int preemption_goodness (struct task_struct * prev,
+ struct task_struct * p, int cpu)
+{
+ return goodness(prev, p, cpu) - goodness(prev, prev, cpu);
+}
+
+/*
+ * If there is a dependency between p1 and p2,
+ * don't be too eager to go into the slow schedule.
+ * In particular, if p1 and p2 both want the kernel
+ * lock, there is no point in trying to make them
+ * extremely parallel..
+ *
+ * (No lock - lock_depth < 0)
+ *
+ * There are two additional metrics here:
+ *
+ * first, a 'cutoff' interval, currently 0-200 usecs on
+ * x86 CPUs, depending on the size of the 'SMP-local cache'.
+ * If the current process has longer average timeslices than
+ * this, then we utilize the idle CPU.
+ *
+ * second, if the wakeup comes from a process context,
+ * then the two processes are 'related'. (they form a
+ * 'gang')
+ *
+ * An idle CPU is almost always a bad thing, thus we skip
+ * the idle-CPU utilization only if both these conditions
+ * are true. (ie. a 'process-gang' rescheduling with rather
+ * high frequency should stay on the same CPU).
+ *
+ * [We can switch to something more finegrained in 2.3.]
+ *
+ * do not 'guess' if the to-be-scheduled task is RT.
+ */
+#define related(p1,p2) (((p1)->lock_depth >= 0) && (p2)->lock_depth >= 0) && \
+ (((p2)->policy == SCHED_OTHER) && ((p1)->avg_slice < cacheflush_time))
+
+static inline void reschedule_idle_slow(struct task_struct * p)
X {
+#ifdef __SMP__
X /*
X * (see reschedule_idle() for an explanation first ...)
X *
@@ -124,60 +267,71 @@
X * 2.3. Also we can try to use the avg_slice value to predict
X * 'likely reschedule' events even on other CPUs.]
X */
- int best_cpu = p->processor, this_cpu = smp_processor_id();
- struct task_struct **idle = task, *tsk, *target_tsk;
- int i = smp_num_cpus;
+ int this_cpu = smp_processor_id(), target_cpu;
+ struct task_struct *tsk, *target_tsk;
+ int cpu, best_cpu, weight, best_weight, i;


+ unsigned long flags;
+

+ best_weight = 0; /* prevents negative weight */
+
+ spin_lock_irqsave(&runqueue_lock, flags);
+
+ /*
+ * shortcut if the woken up task's last CPU is
+ * idle now.
+ */
+ best_cpu = p->processor;
+ target_tsk = idle_task(best_cpu);
+ if (cpu_curr(best_cpu) == target_tsk)
+ goto send_now;
X
X target_tsk = NULL;
- do {
- tsk = *idle;
- idle++;
- if (tsk->has_cpu) {
- if (tsk->processor == this_cpu)
- continue;
+ for (i = 0; i < smp_num_cpus; i++) {
+ cpu = cpu_logical_map(i);
+ tsk = cpu_curr(cpu);
+ if (related(tsk, p))
+ goto out_no_target;
+ weight = preemption_goodness(tsk, p, cpu);
+ if (weight > best_weight) {
+ best_weight = weight;
X target_tsk = tsk;
- if (tsk->processor == best_cpu) {
- /*
- * bingo, we couldnt get a better
- * CPU, activate it.
- */
- goto send; /* this one helps GCC ... */
- }
X }
- } while (--i > 0);
+ }
X
X /*
- * found any idle CPU?
+ * found any suitable CPU?
X */
- if (target_tsk) {
-send:
- target_tsk->need_resched = 1;
- smp_send_reschedule(target_tsk->processor);
- return;
- }
+ if (!target_tsk)
+ goto out_no_target;
+
+send_now:
+ target_cpu = target_tsk->processor;
+ target_tsk->need_resched = 1;
+ spin_unlock_irqrestore(&runqueue_lock, flags);
+ /*
+ * the APIC stuff can go outside of the lock because
+ * it uses no task information, only CPU#.
+ */
+ if (target_cpu != this_cpu)
+ smp_send_reschedule(target_cpu);
+ return;
+out_no_target:
+ spin_unlock_irqrestore(&runqueue_lock, flags);
+ return;
+#else /* UP */
+ int this_cpu = smp_processor_id();
+ struct task_struct *tsk;
+
+ tsk = cpu_curr(this_cpu);
+ if (preemption_goodness(tsk, p, this_cpu) > 0)
+ tsk->need_resched = 1;
+#endif


X }
-#endif /* __SMP__ */

X
-/*
- * If there is a dependency between p1 and p2,
- * don't be too eager to go into the slow schedule.
- * In particular, if p1 and p2 both want the kernel
- * lock, there is no point in trying to make them
- * extremely parallel..
- *
- * (No lock - lock_depth < 0)
- */
-#define related(p1,p2) ((p1)->lock_depth >= 0 && (p2)->lock_depth >= 0)
-
-static inline void reschedule_idle(struct task_struct * p)
+static void reschedule_idle(struct task_struct * p)
X {
-
- if (p->policy != SCHED_OTHER || p->counter > current->counter + 3) {
- current->need_resched = 1;
- return;
- }
-
X #ifdef __SMP__
+ int cpu = smp_processor_id();
X /*
X * ("wakeup()" should not be called before we've initialized
X * SMP completely.
@@ -187,35 +341,20 @@
X *
X * SMP rescheduling is done in 2 passes:
X * - pass #1: faster: 'quick decisions'
- * - pass #2: slower: 'lets try and find another CPU'
+ * - pass #2: slower: 'lets try and find a suitable CPU'
X */
X
X /*
- * Pass #1
- *
- * There are two metrics here:
- *
- * first, a 'cutoff' interval, currently 0-200 usecs on
- * x86 CPUs, depending on the size of the 'SMP-local cache'.
- * If the current process has longer average timeslices than
- * this, then we utilize the idle CPU.
- *
- * second, if the wakeup comes from a process context,
- * then the two processes are 'related'. (they form a
- * 'gang')
- *
- * An idle CPU is almost always a bad thing, thus we skip
- * the idle-CPU utilization only if both these conditions
- * are true. (ie. a 'process-gang' rescheduling with rather
- * high frequency should stay on the same CPU).
- *
- * [We can switch to something more finegrained in 2.3.]
+ * Pass #1. (subtle. We might be in the middle of __switch_to, so
+ * to preserve scheduling atomicity we have to use cpu_curr)
X */
- if ((current->avg_slice < cacheflush_time) && related(current, p))
+ if ((p->processor == cpu) && related(cpu_curr(cpu), p))
X return;
-
- reschedule_idle_slow(p);
X #endif /* __SMP__ */
+ /*
+ * Pass #2
+ */
+ reschedule_idle_slow(p);
X }
X
X /*
@@ -291,7 +430,6 @@
X * The run-queue lock locks the parts that actually access
X * and change the run-queues, and have to be interrupt-safe.
X */
-spinlock_t scheduler_lock = SPIN_LOCK_UNLOCKED; /* should be acquired first */
X spinlock_t runqueue_lock = SPIN_LOCK_UNLOCKED; /* second */
X rwlock_t tasklist_lock = RW_LOCK_UNLOCKED; /* third */
X
@@ -307,12 +445,19 @@
X {


X unsigned long flags;
X

+ /*
+ * We want the common case fall through straight, thus the goto.
+ */
X spin_lock_irqsave(&runqueue_lock, flags);
X p->state = TASK_RUNNING;
- if (!p->next_run) {
- add_to_runqueue(p);
- reschedule_idle(p);
- }
+ if (p->next_run)
+ goto out;
+ add_to_runqueue(p);
+ spin_unlock_irqrestore(&runqueue_lock, flags);
+
+ reschedule_idle(p);
+ return;
+out:
X spin_unlock_irqrestore(&runqueue_lock, flags);
X }
X
@@ -324,63 +469,6 @@
X }
X
X /*
- * This is the function that decides how desirable a process is..
- * You can weigh different processes against each other depending
- * on what CPU they've run on lately etc to try to handle cache
- * and TLB miss penalties.
- *
- * Return values:
- * -1000: never select this
- * 0: out of time, recalculate counters (but it might still be
- * selected)
- * +ve: "goodness" value (the larger, the better)
- * +1000: realtime process, select this.
- */
-static inline int goodness(struct task_struct * p, struct task_struct * prev, int this_cpu)
-{
- int policy = p->policy;
- int weight;
-
- if (policy & SCHED_YIELD) {
- p->policy = policy & ~SCHED_YIELD;


- return 0;
- }
-

- /*
- * Realtime process, select the first one on the
- * runqueue (taking priorities within processes
- * into account).
- */
- if (policy != SCHED_OTHER)
- return 1000 + p->rt_priority;
-
- /*
- * Give the process a first-approximation goodness value
- * according to the number of clock-ticks it has left.
- *
- * Don't do any other calculations if the time slice is
- * over..
- */
- weight = p->counter;
- if (weight) {
-
-#ifdef __SMP__
- /* Give a largish advantage to the same processor... */
- /* (this is equivalent to penalizing other processors) */
- if (p->processor == this_cpu)
- weight += PROC_CHANGE_PENALTY;
-#endif
-
- /* .. and a slight advantage to the current thread */
- if (p->mm == prev->mm)
- weight += 1;
- weight += p->priority;
- }
-
- return weight;
-}
-
-/*
X * Event timer code
X */
X #define TVN_BITS 6
@@ -513,18 +601,6 @@
X return ret;


X }
X
-#ifdef __SMP__
-

-#define idle_task (task[cpu_number_map[this_cpu]])
-#define can_schedule(p) (!(p)->has_cpu)
-
-#else
-
-#define idle_task (&init_task)
-#define can_schedule(p) (1)
-
-#endif
-
X signed long schedule_timeout(signed long timeout)
X {
X struct timer_list timer;
@@ -577,60 +653,24 @@
X }
X
X /*
- * This one aligns per-CPU data on cacheline boundaries.
+ * schedule_tail() is getting called from the fork return path. This
+ * cleans up all remaining scheduler things, without impacting the
+ * common case.
X */
-static union {
- struct schedule_data {
- struct task_struct * prev;
- long prevstate;
- cycles_t last_schedule;
- } schedule_data;
- char __pad [SMP_CACHE_BYTES];
-} aligned_data [NR_CPUS] __cacheline_aligned = { {{&init_task,0}}};
-
-
-static inline void __schedule_tail (void)
+static inline void __schedule_tail (struct task_struct *prev)
X {
X #ifdef __SMP__
- struct schedule_data * sched_data;
-
- /*
- * We might have switched CPUs:
- */
- sched_data = & aligned_data[smp_processor_id()].schedule_data;
-
- /*
- * Subtle. In the rare event that we got a wakeup to 'prev' just
- * during the reschedule (this is possible, the scheduler is pretty
- * parallel), we should do another reschedule in the next task's
- * context. schedule() will do the right thing next time around.
- * this is equivalent to 'delaying' the wakeup until the reschedule
- * has finished.
- */
- if (sched_data->prev->state != sched_data->prevstate)
- current->need_resched = 1;
-
- /*
- * Release the previous process ...
- *
- * We have dropped all locks, and we must make sure that we
- * only mark the previous process as no longer having a CPU
- * after all other state has been seen by other CPU's. Thus
- * the write memory barrier!
- */
+ if ((prev->state == TASK_RUNNING) &&
+ (prev != idle_task(smp_processor_id())))
+ reschedule_idle(prev);
X wmb();
- sched_data->prev->has_cpu = 0;
+ prev->has_cpu = 0;


X #endif /* __SMP__ */

X }
X
-/*
- * schedule_tail() is getting called from the fork return path. This
- * cleans up all remaining scheduler things, without impacting the
- * common case.
- */
-void schedule_tail (void)
+void schedule_tail (struct task_struct *prev)
X {
- __schedule_tail();
+ __schedule_tail(prev);
X }
X
X /*
@@ -646,37 +686,38 @@
X asmlinkage void schedule(void)
X {
X struct schedule_data * sched_data;
- struct task_struct * prev, * next;
- int this_cpu;
+ struct task_struct *prev, *next, *p;
+ int this_cpu, c;
X
- run_task_queue(&tq_scheduler);
+ if (tq_scheduler)
+ goto handle_tq_scheduler;
+tq_scheduler_back:
X
X prev = current;
X this_cpu = prev->processor;
- /*
- * 'sched_data' is protected by the fact that we can run
- * only one process per CPU.
- */
- sched_data = & aligned_data[this_cpu].schedule_data;
X
X if (in_interrupt())
X goto scheduling_in_interrupt;
+
X release_kernel_lock(prev, this_cpu);
X
X /* Do "administrative" work here while we don't hold any locks */
- if (bh_active & bh_mask)
- do_bottom_half();
+ if (bh_mask & bh_active)
+ goto handle_bh;
+handle_bh_back:
+
+ /*
+ * 'sched_data' is protected by the fact that we can run
+ * only one process per CPU.
+ */
+ sched_data = & aligned_data[this_cpu].schedule_data;
X
- spin_lock(&scheduler_lock);
X spin_lock_irq(&runqueue_lock);
X
X /* move an exhausted RR process to be last.. */
- prev->need_resched = 0;
-
- if (!prev->counter && prev->policy == SCHED_RR) {
- prev->counter = prev->priority;
- move_last_runqueue(prev);
- }
+ if (prev->policy == SCHED_RR)
+ goto move_rr_last;
+move_rr_back:
X
X switch (prev->state) {
X case TASK_INTERRUPTIBLE:
@@ -688,62 +729,72 @@
X del_from_runqueue(prev);
X case TASK_RUNNING:
X }
+ prev->need_resched = 0;
X
- sched_data->prevstate = prev->state;
+repeat_schedule:
X
-/* this is the scheduler proper: */
- {
- struct task_struct * p = init_task.next_run;
- int c = -1000;
+ /*
+ * this is the scheduler proper:
+ */
X
- /* Default process to select.. */
- next = idle_task;
- if (prev->state == TASK_RUNNING) {
- c = goodness(prev, prev, this_cpu);
- next = prev;
- }
+ p = init_task.next_run;
+ /* Default process to select.. */
+ next = idle_task(this_cpu);
+ c = -1000;
+ if (prev->state == TASK_RUNNING)
+ goto still_running;
+still_running_back:
X
- /*
- * This is subtle.
- * Note how we can enable interrupts here, even
- * though interrupts can add processes to the run-
- * queue. This is because any new processes will
- * be added to the front of the queue, so "p" above
- * is a safe starting point.
- * run-queue deletion and re-ordering is protected by
- * the scheduler lock
- */
- spin_unlock_irq(&runqueue_lock);
+ /*
+ * This is subtle.
+ * Note how we can enable interrupts here, even
+ * though interrupts can add processes to the run-
+ * queue. This is because any new processes will
+ * be added to the front of the queue, so "p" above
+ * is a safe starting point.
+ * run-queue deletion and re-ordering is protected by
+ * the scheduler lock
+ */
X /*
X * Note! there may appear new tasks on the run-queue during this, as
X * interrupts are enabled. However, they will be put on front of the
X * list, so our list starting at "p" is essentially fixed.
X */


- while (p != &init_task) {

- if (can_schedule(p)) {
- int weight = goodness(p, prev, this_cpu);
- if (weight > c)
- c = weight, next = p;
- }
- p = p->next_run;
- }
-
- /* Do we need to re-calculate counters? */
- if (!c) {
- struct task_struct *p;
- read_lock(&tasklist_lock);
- for_each_task(p)
- p->counter = (p->counter >> 1) + p->priority;
- read_unlock(&tasklist_lock);
+ while (p != &init_task) {
+ if (can_schedule(p)) {
+ int weight = goodness(prev, p, this_cpu);
+ if (weight > c)
+ c = weight, next = p;
X }
+ p = p->next_run;
X }
X
+ /* Do we need to re-calculate counters? */
+ if (!c)
+ goto recalculate;
+ /*
+ * from this point on nothing can prevent us from
+ * switching to the next task, save this fact in
+ * sched_data.
+ */
+ sched_data->curr = next;
+#ifdef __SMP__
+ next->has_cpu = 1;
+ next->processor = this_cpu;
+#endif
+ spin_unlock_irq(&runqueue_lock);
+
+ if (prev == next)
+ goto same_process;
+
+#ifdef __SMP__
X /*
X * maintain the per-process 'average timeslice' value.
X * (this has to be recalculated even if we reschedule to
- * the same process) Currently this is only used on SMP:
+ * the same process) Currently this is only used on SMP,
+ * and it's approximate, so we do not have to maintain
+ * it while holding the runqueue spinlock.
X */
-#ifdef __SMP__
X {
X cycles_t t, this_slice;
X
@@ -752,10 +803,11 @@
X sched_data->last_schedule = t;
X
X /*
- * Simple, exponentially fading average calculation:
+ * Exponentially fading average calculation, with
+ * some weight so it doesnt get fooled easily by
+ * smaller irregularities.
X */
- prev->avg_slice = this_slice + prev->avg_slice;
- prev->avg_slice >>= 1;
+ prev->avg_slice = (this_slice*1 + prev->avg_slice*1)/2;
X }
X
X /*
@@ -763,27 +815,55 @@
X * thus we have to lock the previous process from getting
X * rescheduled during switch_to().
X */
- next->processor = this_cpu;
- next->has_cpu = 1;
- spin_unlock(&scheduler_lock);
+


X #endif /* __SMP__ */

- if (prev != next) {
-#ifdef __SMP__
- sched_data->prev = prev;
-#endif
- kstat.context_swtch++;
- get_mmu_context(next);
- switch_to(prev,next);
X
- __schedule_tail();
- }
+ kstat.context_swtch++;
+ get_mmu_context(next);
+ switch_to(prev, next, prev);
+ __schedule_tail(prev);
+
+same_process:
X
X reacquire_kernel_lock(current);
X return;
X
+recalculate:
+ {
+ struct task_struct *p;
+ spin_unlock_irq(&runqueue_lock);
+ read_lock(&tasklist_lock);
+ for_each_task(p)
+ p->counter = (p->counter >> 1) + p->priority;
+ read_unlock(&tasklist_lock);
+ spin_lock_irq(&runqueue_lock);
+ goto repeat_schedule;
+ }
+
+still_running:
+ c = prev_goodness(prev, prev, this_cpu);
+ next = prev;
+ goto still_running_back;
+
+handle_bh:
+ do_bottom_half();
+ goto handle_bh_back;
+
+handle_tq_scheduler:
+ run_task_queue(&tq_scheduler);
+ goto tq_scheduler_back;
+
+move_rr_last:
+ if (!prev->counter) {
+ prev->counter = prev->priority;
+ move_last_runqueue(prev);
+ }
+ goto move_rr_back;
+
X scheduling_in_interrupt:
X printk("Scheduling in interrupt\n");
X *(int *)0 = 0;
+ return;
X }
X
X rwlock_t waitqueue_lock = RW_LOCK_UNLOCKED;
@@ -798,21 +878,42 @@
X */
X void __wake_up(struct wait_queue **q, unsigned int mode)
X {
- struct wait_queue *next;
+ struct task_struct *p;
+ struct wait_queue *head, *next;
+
+ if (!q)
+ goto out;
+ /*
+ * this is safe to be done before the check because it
+ * means no deference, just pointer operations.
+ */
+ head = WAIT_QUEUE_HEAD(q);
X
X read_lock(&waitqueue_lock);
- if (q && (next = *q)) {
- struct wait_queue *head;
+ next = *q;
+ if (!next)
+ goto out_unlock;
X
- head = WAIT_QUEUE_HEAD(q);
- while (next != head) {
- struct task_struct *p = next->task;
- next = next->next;
- if (p->state & mode)
+ while (next != head) {
+ p = next->task;
+ next = next->next;
+ if (p->state & mode) {
+ /*
+ * We can drop the read-lock early if this
+ * is the only/last process.
+ */
+ if (next == head) {
+ read_unlock(&waitqueue_lock);
X wake_up_process(p);
+ goto out;
+ }
+ wake_up_process(p);
X }
X }
+out_unlock:
X read_unlock(&waitqueue_lock);
+out:
+ return;
X }
X
X /*
@@ -942,14 +1043,14 @@
X
X #define SLEEP_ON_HEAD \
X wait.task = current; \
- write_lock_irqsave(&waitqueue_lock, flags); \
+ write_lock_irqsave(&waitqueue_lock,flags); \
X __add_wait_queue(p, &wait); \
X write_unlock(&waitqueue_lock);
X
X #define SLEEP_ON_TAIL \
X write_lock_irq(&waitqueue_lock); \
X __remove_wait_queue(p, &wait); \
- write_unlock_irqrestore(&waitqueue_lock, flags);
+ write_unlock_irqrestore(&waitqueue_lock,flags);
X
X void interruptible_sleep_on(struct wait_queue **p)
X {
@@ -1623,7 +1724,6 @@
X /*
X * We play safe to avoid deadlocks.
X */
- spin_lock(&scheduler_lock);
X spin_lock_irq(&runqueue_lock);
X read_lock(&tasklist_lock);
X
@@ -1671,7 +1771,6 @@
X out_unlock:
X read_unlock(&tasklist_lock);
X spin_unlock_irq(&runqueue_lock);
- spin_unlock(&scheduler_lock);
X
X out_nounlock:
X return retval;
@@ -1746,14 +1845,12 @@
X
X asmlinkage int sys_sched_yield(void)
X {
- spin_lock(&scheduler_lock);
X spin_lock_irq(&runqueue_lock);
X if (current->policy == SCHED_OTHER)
X current->policy |= SCHED_YIELD;
X current->need_resched = 1;
X move_last_runqueue(current);
X spin_unlock_irq(&runqueue_lock);
- spin_unlock(&scheduler_lock);


X return 0;
X }
X

@@ -1930,11 +2027,22 @@
X read_unlock(&tasklist_lock);
X }
X
+void __init init_idle(void)
+{
+ cycles_t t;
+ struct schedule_data * sched_data;
+ sched_data = &aligned_data[smp_processor_id()].schedule_data;
+
+ t = get_cycles();
+ sched_data->curr = current;
+ sched_data->last_schedule = t;
+}
+
X void __init sched_init(void)
X {
X /*
- * We have to do a little magic to get the first
- * process right in SMP mode.
+ * We have to do a little magic to get the first
+ * process right in SMP mode.
X */
X int cpu=hard_smp_processor_id();
X int nr = NR_TASKS;
diff -u --recursive --new-file v2.2.7/linux/kernel/signal.c linux/kernel/signal.c
--- v2.2.7/linux/kernel/signal.c Mon Mar 29 11:09:12 1999
+++ linux/kernel/signal.c Sun May 2 12:23:54 1999
@@ -265,7 +265,7 @@
X && ((sig != SIGCONT) || (current->session != t->session))
X && (current->euid ^ t->suid) && (current->euid ^ t->uid)
X && (current->uid ^ t->suid) && (current->uid ^ t->uid)
- && !capable(CAP_SYS_ADMIN))
+ && !capable(CAP_KILL))
X goto out_nolock;
X
X /* The null signal is a permissions and process existance probe.
diff -u --recursive --new-file v2.2.7/linux/mm/filemap.c linux/mm/filemap.c
--- v2.2.7/linux/mm/filemap.c Tue Mar 23 14:35:48 1999
+++ linux/mm/filemap.c Tue May 11 08:51:13 1999
@@ -34,12 +34,6 @@
X unsigned long page_cache_size = 0;
X struct page * page_hash_table[PAGE_HASH_SIZE];
X
-/*
- * Simple routines for both non-shared and shared mappings.
- */
-
-#define release_page(page) __free_page((page))
-
X /*
X * Define a request structure for outstanding page write requests
X * to the background page io daemon
@@ -83,7 +77,7 @@
X page->prev = NULL;
X remove_page_from_hash_queue(page);
X page->inode = NULL;
- __free_page(page);
+ page_cache_release(page);
X continue;
X }
X }
@@ -115,15 +109,15 @@
X page->prev = NULL;
X remove_page_from_hash_queue(page);
X page->inode = NULL;
- __free_page(page);
+ page_cache_release(page);
X continue;
X }
X p = &page->next;
X offset = start - offset;
X /* partial truncate, clear end of page */
- if (offset < PAGE_SIZE) {
+ if (offset < PAGE_CACHE_SIZE) {
X unsigned long address = page_address(page);
- memset((void *) (offset + address), 0, PAGE_SIZE - offset);
+ memset((void *) (offset + address), 0, PAGE_CACHE_SIZE - offset);
X flush_page_to_ram(address);
X }
X }
@@ -136,7 +130,7 @@
X {
X remove_page_from_hash_queue(page);
X remove_page_from_inode_queue(page);
- __free_page(page);
+ page_cache_release(page);
X }
X
X int shrink_mmap(int priority, int gfp_mask)
@@ -226,9 +220,9 @@
X {
X unsigned long offset, len;
X
- offset = (pos & ~PAGE_MASK);
- pos = pos & PAGE_MASK;
- len = PAGE_SIZE - offset;
+ offset = (pos & ~PAGE_CACHE_MASK);
+ pos = pos & PAGE_CACHE_MASK;
+ len = PAGE_CACHE_SIZE - offset;
X do {
X struct page * page;
X
@@ -238,13 +232,13 @@
X if (page) {
X wait_on_page(page);
X memcpy((void *) (offset + page_address(page)), buf, len);
- release_page(page);
+ page_cache_release(page);
X }
X count -= len;
X buf += len;
- len = PAGE_SIZE;
+ len = PAGE_CACHE_SIZE;
X offset = 0;
- pos += PAGE_SIZE;
+ pos += PAGE_CACHE_SIZE;
X } while (count);
X }
X
@@ -271,10 +265,10 @@
X struct page * page;
X struct page ** hash;
X
- offset &= PAGE_MASK;
+ offset &= PAGE_CACHE_MASK;
X switch (page_cache) {
X case 0:
- page_cache = __get_free_page(GFP_USER);
+ page_cache = page_cache_alloc();
X if (!page_cache)
X break;
X default:
@@ -286,12 +280,12 @@
X /*
X * Ok, add the new page to the hash-queues...
X */
- page = mem_map + MAP_NR(page_cache);
+ page = page_cache_entry(page_cache);
X add_to_page_cache(page, inode, offset, hash);
X inode->i_op->readpage(file, page);
X page_cache = 0;
X }
- release_page(page);
+ page_cache_release(page);
X }
X return page_cache;
X }
@@ -413,7 +407,7 @@
X * performances.
X * Reasonable means, in this context, not too large but not too small.
X * The actual maximum value is:
- * MAX_READAHEAD + PAGE_SIZE = 76k is CONFIG_READA_SMALL is undefined
+ * MAX_READAHEAD + PAGE_CACHE_SIZE = 76k is CONFIG_READA_SMALL is undefined
X * and 32K if defined (4K page size assumed).
X *
X * Asynchronous read-ahead benefits:
@@ -440,7 +434,7 @@
X * ONE seems to be the only reasonable value.
X * - The total memory pool usage for the file access stream.
X * This maximum memory usage is implicitly 2 IO read chunks:
- * 2*(MAX_READAHEAD + PAGE_SIZE) = 156K if CONFIG_READA_SMALL is undefined,
+ * 2*(MAX_READAHEAD + PAGE_CACHE_SIZE) = 156K if CONFIG_READA_SMALL is undefined,
X * 64k if defined (4K page size assumed).
X */
X
@@ -459,7 +453,7 @@
X unsigned long raend;
X int max_readahead = get_max_readahead(inode);
X
- raend = filp->f_raend & PAGE_MASK;
+ raend = filp->f_raend & PAGE_CACHE_MASK;
X max_ahead = 0;
X
X /*
@@ -476,7 +470,7 @@
X if (raend < inode->i_size)
X max_ahead = filp->f_ramax;
X filp->f_rawin = 0;
- filp->f_ralen = PAGE_SIZE;
+ filp->f_ralen = PAGE_CACHE_SIZE;
X if (!max_ahead) {
X filp->f_raend = ppos + filp->f_ralen;
X filp->f_rawin += filp->f_ralen;
@@ -491,17 +485,17 @@
X * it is the moment to try to read ahead asynchronously.
X * We will later force unplug device in order to force asynchronous read IO.
X */
- else if (reada_ok && filp->f_ramax && raend >= PAGE_SIZE &&
+ else if (reada_ok && filp->f_ramax && raend >= PAGE_CACHE_SIZE &&
X ppos <= raend && ppos + filp->f_ralen >= raend) {
X /*
X * Add ONE page to max_ahead in order to try to have about the same IO max size
- * as synchronous read-ahead (MAX_READAHEAD + 1)*PAGE_SIZE.
+ * as synchronous read-ahead (MAX_READAHEAD + 1)*PAGE_CACHE_SIZE.
X * Compute the position of the last page we have tried to read in order to
X * begin to read ahead just at the next page.
X */
- raend -= PAGE_SIZE;
+ raend -= PAGE_CACHE_SIZE;
X if (raend < inode->i_size)
- max_ahead = filp->f_ramax + PAGE_SIZE;
+ max_ahead = filp->f_ramax + PAGE_CACHE_SIZE;
X
X if (max_ahead) {
X filp->f_rawin = filp->f_ralen;
@@ -516,7 +510,7 @@
X */
X ahead = 0;
X while (ahead < max_ahead) {
- ahead += PAGE_SIZE;
+ ahead += PAGE_CACHE_SIZE;
X page_cache = try_to_read_ahead(filp, raend + ahead,
X page_cache);
X }


@@ -538,7 +532,7 @@
X

X filp->f_ralen += ahead;
X filp->f_rawin += filp->f_ralen;
- filp->f_raend = raend + ahead + PAGE_SIZE;
+ filp->f_raend = raend + ahead + PAGE_CACHE_SIZE;
X
X filp->f_ramax += filp->f_ramax;
X
@@ -590,7 +584,7 @@
X page_cache = 0;
X
X pos = *ppos;
- pgpos = pos & PAGE_MASK;
+ pgpos = pos & PAGE_CACHE_MASK;
X /*
X * If the current position is outside the previous read-ahead window,
X * we reset the current read-ahead context and set read ahead max to zero
@@ -614,12 +608,12 @@
X * Then, at least MIN_READAHEAD if read ahead is ok,
X * and at most MAX_READAHEAD in all cases.
X */
- if (pos + desc->count <= (PAGE_SIZE >> 1)) {
+ if (pos + desc->count <= (PAGE_CACHE_SIZE >> 1)) {
X filp->f_ramax = 0;
X } else {
X unsigned long needed;
X
- needed = ((pos + desc->count) & PAGE_MASK) - pgpos;
+ needed = ((pos + desc->count) & PAGE_CACHE_MASK) - pgpos;
X
X if (filp->f_ramax < needed)
X filp->f_ramax = needed;
@@ -639,8 +633,8 @@
X /*
X * Try to find the data in the page cache..
X */
- hash = page_hash(inode, pos & PAGE_MASK);
- page = __find_page(inode, pos & PAGE_MASK, *hash);
+ hash = page_hash(inode, pos & PAGE_CACHE_MASK);
+ page = __find_page(inode, pos & PAGE_CACHE_MASK, *hash);
X if (!page)
X goto no_cached_page;
X
@@ -653,7 +647,7 @@
X * the page has been rewritten.
X */
X if (PageUptodate(page) || PageLocked(page))
- page_cache = generic_file_readahead(reada_ok, filp, inode, pos & PAGE_MASK, page, page_cache);
+ page_cache = generic_file_readahead(reada_ok, filp, inode, pos & PAGE_CACHE_MASK, page, page_cache);
X else if (reada_ok && filp->f_ramax > MIN_READAHEAD)
X filp->f_ramax = MIN_READAHEAD;
X
@@ -670,8 +664,8 @@
X {
X unsigned long offset, nr;
X
- offset = pos & ~PAGE_MASK;
- nr = PAGE_SIZE - offset;
+ offset = pos & ~PAGE_CACHE_MASK;
+ nr = PAGE_CACHE_SIZE - offset;
X if (nr > inode->i_size - pos)
X nr = inode->i_size - pos;
X
@@ -684,7 +678,7 @@
X */
X nr = actor(desc, (const char *) (page_address(page) + offset), nr);
X pos += nr;
- release_page(page);
+ page_cache_release(page);
X if (nr && desc->count)
X continue;
X break;
@@ -696,7 +690,7 @@
X * page..
X */
X if (!page_cache) {
- page_cache = __get_free_page(GFP_USER);
+ page_cache = page_cache_alloc();
X /*
X * That could have slept, so go around to the
X * very beginning..
@@ -710,9 +704,9 @@
X /*
X * Ok, add the new page to the hash-queues...
X */
- page = mem_map + MAP_NR(page_cache);
+ page = page_cache_entry(page_cache);
X page_cache = 0;
- add_to_page_cache(page, inode, pos & PAGE_MASK, hash);
+ add_to_page_cache(page, inode, pos & PAGE_CACHE_MASK, hash);
X
X /*
X * Error handling is tricky. If we get a read error,
@@ -737,7 +731,7 @@
X if (!error)
X goto found_page;
X desc->error = error;
- release_page(page);
+ page_cache_release(page);
X break;
X }
X
@@ -756,7 +750,7 @@
X error = -EIO; /* Some unspecified error occurred.. */
X }
X desc->error = error;
- release_page(page);
+ page_cache_release(page);
X break;
X }
X }
@@ -764,7 +758,7 @@
X *ppos = pos;
X filp->f_reada = 1;
X if (page_cache)
- free_page(page_cache);
+ page_cache_free(page_cache);
X UPDATE_ATIME(inode);
X }
X
@@ -962,7 +956,7 @@
X * extra page -- better to overlap the allocation with the I/O.
X */
X if (no_share && !new_page) {
- new_page = __get_free_page(GFP_USER);
+ new_page = page_cache_alloc();
X if (!new_page)
X goto failure;
X }
@@ -984,7 +978,7 @@
X * of any potential extra pages.
X */
X if (new_page)
- free_page(new_page);
+ page_cache_free(new_page);
X
X flush_page_to_ram(old_page);
X return old_page;
@@ -995,7 +989,7 @@
X */
X copy_page(new_page, old_page);
X flush_page_to_ram(new_page);
- release_page(page);
+ page_cache_release(page);
X return new_page;
X
X no_cached_page:
@@ -1003,14 +997,14 @@
X * Try to read in an entire cluster at once.
X */
X reada = offset;
- reada >>= PAGE_SHIFT + page_cluster;
- reada <<= PAGE_SHIFT + page_cluster;
+ reada >>= PAGE_CACHE_SHIFT + page_cluster;
+ reada <<= PAGE_CACHE_SHIFT + page_cluster;
X
- for (i = 1 << page_cluster; i > 0; --i, reada += PAGE_SIZE)
+ for (i = 1 << page_cluster; i > 0; --i, reada += PAGE_CACHE_SIZE)
X new_page = try_to_read_ahead(file, reada, new_page);
X
X if (!new_page)
- new_page = __get_free_page(GFP_USER);
+ new_page = page_cache_alloc();
X if (!new_page)
X goto no_page;
X
@@ -1027,7 +1021,7 @@
X /*
X * Now, create a new page-cache page from the page we got
X */
- page = mem_map + MAP_NR(new_page);
+ page = page_cache_entry(new_page);
X new_page = 0;
X add_to_page_cache(page, inode, offset, hash);
X
@@ -1061,9 +1055,9 @@
X * mm layer so, possibly freeing the page cache page first.
X */
X failure:
- release_page(page);
+ page_cache_release(page);
X if (new_page)
- free_page(new_page);
+ page_cache_free(new_page);
X no_page:
X return 0;
X }
@@ -1166,7 +1160,7 @@
X set_pte(ptep, pte_mkclean(pte));
X flush_tlb_page(vma, address);
X page = pte_page(pte);
- atomic_inc(&mem_map[MAP_NR(page)].count);
+ atomic_inc(&page_cache_entry(page)->count);
X } else {
X if (pte_none(pte))
X return 0;
@@ -1179,12 +1173,12 @@
X }
X page = pte_page(pte);
X if (!pte_dirty(pte) || flags == MS_INVALIDATE) {
- free_page(page);
+ page_cache_free(page);


X return 0;
X }
X }

X error = filemap_write_page(vma, address - vma->vm_start + vma->vm_offset, page, 1);
- free_page(page);
+ page_cache_free(page);


X return error;
X }
X

@@ -1492,9 +1486,9 @@
X * Try to find the page in the cache. If it isn't there,
X * allocate a free page.
X */
- offset = (pos & ~PAGE_MASK);
- pgpos = pos & PAGE_MASK;
- bytes = PAGE_SIZE - offset;
+ offset = (pos & ~PAGE_CACHE_MASK);
+ pgpos = pos & PAGE_CACHE_MASK;
+ bytes = PAGE_CACHE_SIZE - offset;
X if (bytes > count)
X bytes = count;
X
@@ -1502,13 +1496,13 @@
X page = __find_page(inode, pgpos, *hash);
X if (!page) {
X if (!page_cache) {
- page_cache = __get_free_page(GFP_USER);
+ page_cache = page_cache_alloc();
X if (page_cache)
X continue;
X status = -ENOMEM;
X break;
X }
- page = mem_map + MAP_NR(page_cache);
+ page = page_cache_entry(page_cache);
X add_to_page_cache(page, inode, pgpos, hash);
X page_cache = 0;
X }
@@ -1530,7 +1524,7 @@
X /* Mark it unlocked again and drop the page.. */
X clear_bit(PG_locked, &page->flags);
X wake_up(&page->wait);
- __free_page(page);
+ page_cache_release(page);
X
X if (status < 0)
X break;
@@ -1545,7 +1539,7 @@
X inode->i_size = pos;
X
X if (page_cache)
- free_page(page_cache);
+ page_cache_free(page_cache);
X out:
X return written ? written : status;
X }
@@ -1573,10 +1567,11 @@
X if (!page) {
X if (!new)
X goto out;
- page_cache = get_free_page(GFP_USER);
+ page_cache = page_cache_alloc();
X if (!page_cache)
X goto out;
- page = mem_map + MAP_NR(page_cache);
+ clear_page(page_cache);
+ page = page_cache_entry(page_cache);
X add_to_page_cache(page, inode, offset, hash);
X }
X if (atomic_read(&page->count) != 2)
@@ -1596,7 +1591,7 @@
X */
X void put_cached_page(unsigned long addr)
X {
- struct page * page = mem_map + MAP_NR(addr);
+ struct page * page = page_cache_entry(addr);
X
X if (!test_bit(PG_locked, &page->flags))
X printk("put_cached_page: page not locked!\n");
@@ -1605,7 +1600,7 @@
X atomic_read(&page->count));
X clear_bit(PG_locked, &page->flags);
X wake_up(&page->wait);
- __free_page(page);
+ page_cache_release(page);
X }
X
X
@@ -1637,7 +1632,7 @@
X {
X struct pio_request *p;
X
- atomic_inc(&mem_map[MAP_NR(page)].count);
+ atomic_inc(&page_cache_entry(page)->count);
X
X /*
X * We need to allocate without causing any recursive IO in the
@@ -1726,7 +1721,7 @@
X (const char *) p->page, p->offset);
X up(&inode->i_sem);
X fput(p->file);
- free_page(p->page);
+ page_cache_free(p->page);
X kmem_cache_free(pio_request_cache, p);
X }
X }
diff -u --recursive --new-file v2.2.7/linux/mm/mmap.c linux/mm/mmap.c
--- v2.2.7/linux/mm/mmap.c Fri Apr 16 14:47:31 1999
+++ linux/mm/mmap.c Tue May 4 15:44:38 1999
@@ -176,6 +176,9 @@
X struct vm_area_struct * vma;
X int error;
X
+ if (file && (!file->f_op || !file->f_op->mmap))
+ return -ENODEV;
+
X if ((len = PAGE_ALIGN(len)) == 0)
X return addr;
X
@@ -244,9 +247,6 @@
X * specific mapper. the address has already been validated, but
X * not unmapped, but the maps are removed from the list.
X */
- if (file && (!file->f_op || !file->f_op->mmap))
- return -ENODEV;
-
X vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
X if (!vma)
X return -ENOMEM;
diff -u --recursive --new-file v2.2.7/linux/mm/page_alloc.c linux/mm/page_alloc.c
--- v2.2.7/linux/mm/page_alloc.c Wed Apr 28 11:37:32 1999
+++ linux/mm/page_alloc.c Thu May 6 14:32:06 1999
@@ -419,12 +419,12 @@
X return;
X }
X
- /* The page is unshared, and we want write access. In this
- case, it is safe to tear down the swap cache and give the
- page over entirely to this process. */
-
- if (PageSwapCache(page_map))
- delete_from_swap_cache(page_map);
+ /*
+ * The page is unshared and we're going to dirty it - so tear
+ * down the swap cache and give exclusive access to the page to
+ * this process.
+ */
+ delete_from_swap_cache(page_map);
X set_pte(page_table, pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot))));
X return;
X }
diff -u --recursive --new-file v2.2.7/linux/net/TUNABLE linux/net/TUNABLE
--- v2.2.7/linux/net/TUNABLE Thu Jan 7 15:11:41 1999
+++ linux/net/TUNABLE Mon May 10 13:01:21 1999
@@ -5,10 +5,7 @@
X
X Item Description
X ----------------------------------------------------------------------------
-MAX_SOCKETS Tunable on boot, maximum sockets we will allocate
-NUM_PROTO Maximum loadable address family, will need recompile
X MAX_LINKS Maximum number of netlink minor devices. (1-32)
-MAX_QBYTES Size of a netlink device queue (tunable)
X RIF_TABLE_SIZE Token ring RIF cache size (tunable)
X AARP_HASH_SIZE Size of Appletalk hash table (tunable)
X AX25_DEF_T1 AX.25 parameters. These are all tunable via
@@ -34,18 +31,9 @@
X MAX_HEADER Largest physical header (tunable)
X MAX_ADDR_LEN Largest physical address (tunable)
X SOCK_ARRAY_SIZE IP socket array hash size (tunable)
-ARP_RES_TIME Time we try to resolve (tunable)
-ARP_DEAD_RES_TIME Time the entry stays dead (tunable)
-ARP_MAX_TRIES Maximum tries (tunable)
-ARP_TIMEOUT Timeout on an ARP (tunable)
-ARP_CHECK_INTERVAL Check interval to refresh an arp (tunable)
-ARP_CONFIRM_INTERVAL Confirm poll time (tunable)
-ARP_TABLE_SIZE Hash table size for ARP (tunable)
X IP_MAX_MEMBERSHIPS Largest number of groups per socket (BSD style) (tunable)
X 16 Hard coded constant for amount of room allowed for
X cache align and faster forwarding (tunable)
-IPFRAG_HIGH_THRESH Limit on fragments, we free fragments until we reach
-IPFRAG_LOW_THRESH which provides some breathing space. (tunable)
X IP_FRAG_TIME Time we hold a fragment for. (tunable)
X PORT_MASQ_BEGIN First port reserved for masquerade (tunable)
X PORT_MASQ_END Last port used for masquerade (tunable)
diff -u --recursive --new-file v2.2.7/linux/net/core/iovec.c linux/net/core/iovec.c
--- v2.2.7/linux/net/core/iovec.c Mon Sep 28 10:51:36 1998
+++ linux/net/core/iovec.c Mon May 10 09:55:25 1999
@@ -59,8 +59,15 @@
X goto out;
X m->msg_iov=iov;
X
- for (err = 0, ct = 0; ct < m->msg_iovlen; ct++)
+ for (err = 0, ct = 0; ct < m->msg_iovlen; ct++) {
X err += iov[ct].iov_len;
+ /* Goal is not to verify user data, but to prevent returning
+ negative value, which is interpreted as errno.
+ Overflow is still possible, but it is harmless.
+ */
+ if (err < 0)
+ return -EMSGSIZE;
+ }
X out:
X return err;
X }
diff -u --recursive --new-file v2.2.7/linux/net/core/sock.c linux/net/core/sock.c
--- v2.2.7/linux/net/core/sock.c Mon Mar 29 11:09:12 1999
+++ linux/net/core/sock.c Mon May 10 09:55:25 1999
@@ -7,7 +7,7 @@
X * handler for protocols to use and generic option handler.
X *
X *
- * Version: $Id: sock.c,v 1.79 1999/03/28 10:18:25 davem Exp $
+ * Version: $Id: sock.c,v 1.80 1999/05/08 03:04:34 davem Exp $
X *
X * Authors: Ross Biro, <bi...@leland.Stanford.Edu>
X * Fred N. van Kempen, <wal...@uWalt.NL.Mugnet.ORG>
@@ -944,7 +944,7 @@
X */
X if (current->pgrp != -arg &&
X current->pid != arg &&
- !capable(CAP_NET_ADMIN)) return(-EPERM);
+ !capable(CAP_KILL)) return(-EPERM);
X sk->proc = arg;
X return(0);
X case F_GETOWN:
diff -u --recursive --new-file v2.2.7/linux/net/ipv4/devinet.c linux/net/ipv4/devinet.c
--- v2.2.7/linux/net/ipv4/devinet.c Mon Mar 29 11:09:12 1999
+++ linux/net/ipv4/devinet.c Mon May 10 09:55:25 1999
@@ -1,7 +1,7 @@
X /*
X * NET3 IP device support routines.
X *
- * Version: $Id: devinet.c,v 1.27 1999/03/25 10:04:06 davem Exp $
+ * Version: $Id: devinet.c,v 1.28 1999/05/08 20:00:16 davem Exp $
X *
X * This program is free software; you can redistribute it and/or
X * modify it under the terms of the GNU General Public License
@@ -712,6 +712,7 @@
X ifa->ifa_mask = inet_make_mask(8);
X ifa->ifa_dev = in_dev;
X ifa->ifa_scope = RT_SCOPE_HOST;
+ memcpy(ifa->ifa_label, dev->name, IFNAMSIZ);
X inet_insert_ifa(in_dev, ifa);
X }
X }
diff -u --recursive --new-file v2.2.7/linux/net/ipv4/route.c linux/net/ipv4/route.c
--- v2.2.7/linux/net/ipv4/route.c Wed Apr 28 11:37:32 1999
+++ linux/net/ipv4/route.c Mon May 10 09:55:25 1999
@@ -5,7 +5,7 @@
X *
X * ROUTE - implementation of the IP router.
X *
- * Version: $Id: route.c,v 1.66 1999/04/22 10:07:35 davem Exp $
+ * Version: $Id: route.c,v 1.67 1999/05/08 20:00:20 davem Exp $
X *
X * Authors: Ross Biro, <bi...@leland.Stanford.Edu>
X * Fred N. van Kempen, <wal...@uWalt.NL.Mugnet.ORG>
@@ -1492,13 +1492,16 @@
X return -ENODEV; /* Wrong error code */
X
X if (LOCAL_MCAST(daddr) || daddr == 0xFFFFFFFF) {
- key.src = inet_select_addr(dev_out, 0, RT_SCOPE_LINK);
+ if (!key.src)
+ key.src = inet_select_addr(dev_out, 0, RT_SCOPE_LINK);
X goto make_route;
X }
- if (MULTICAST(daddr))
- key.src = inet_select_addr(dev_out, 0, key.scope);
- else if (!daddr)
- key.src = inet_select_addr(dev_out, 0, RT_SCOPE_HOST);
+ if (!key.src) {
+ if (MULTICAST(daddr))
+ key.src = inet_select_addr(dev_out, 0, key.scope);
+ else if (!daddr)
+ key.src = inet_select_addr(dev_out, 0, RT_SCOPE_HOST);
+ }
X }
X
X if (!key.dst) {
diff -u --recursive --new-file v2.2.7/linux/net/ipv4/tcp_input.c linux/net/ipv4/tcp_input.c
--- v2.2.7/linux/net/ipv4/tcp_input.c Wed Apr 28 11:37:32 1999
+++ linux/net/ipv4/tcp_input.c Mon May 10 09:55:25 1999
@@ -5,7 +5,7 @@
X *
X * Implementation of the Transmission Control Protocol(TCP).
X *
- * Version: $Id: tcp_input.c,v 1.163 1999/04/28 16:08:05 davem Exp $
+ * Version: $Id: tcp_input.c,v 1.164 1999/05/08 21:09:52 davem Exp $
X *
X * Authors: Ross Biro, <bi...@leland.Stanford.Edu>
X * Fred N. van Kempen, <wal...@uWalt.NL.Mugnet.ORG>
@@ -497,8 +497,7 @@
X if (tp->high_seq == 0 || after(ack, tp->high_seq)) {
X tp->dup_acks++;
X if ((tp->fackets_out > 3) || (tp->dup_acks == 3)) {
- tp->snd_ssthresh =
- max(min(tp->snd_wnd, tp->snd_cwnd) >> 1, 2);
+ tp->snd_ssthresh = tcp_recalc_ssthresh(tp);
X tp->snd_cwnd = (tp->snd_ssthresh + 3);
X tp->high_seq = tp->snd_nxt;
X if(!tp->fackets_out)
diff -u --recursive --new-file v2.2.7/linux/net/ipv4/tcp_ipv4.c linux/net/ipv4/tcp_ipv4.c
--- v2.2.7/linux/net/ipv4/tcp_ipv4.c Wed Apr 28 11:37:32 1999
+++ linux/net/ipv4/tcp_ipv4.c Mon May 10 09:55:25 1999
@@ -5,7 +5,7 @@
X *
X * Implementation of the Transmission Control Protocol(TCP).
X *
- * Version: $Id: tcp_ipv4.c,v 1.174 1999/04/28 16:08:19 davem Exp $
+ * Version: $Id: tcp_ipv4.c,v 1.175 1999/05/08 21:09:54 davem Exp $
X *
X * IPv4 specific functions
X *
@@ -819,7 +819,7 @@
X switch (type) {
X case ICMP_SOURCE_QUENCH:
X #ifndef OLD_SOURCE_QUENCH /* This is deprecated */
- tp->snd_ssthresh = max(tp->snd_cwnd >> 1, 2);
+ tp->snd_ssthresh = tcp_recalc_ssthresh(tp);
X tp->snd_cwnd = tp->snd_ssthresh;
X tp->snd_cwnd_cnt = 0;
X tp->high_seq = tp->snd_nxt;
diff -u --recursive --new-file v2.2.7/linux/net/ipv4/tcp_output.c linux/net/ipv4/tcp_output.c
--- v2.2.7/linux/net/ipv4/tcp_output.c Wed Apr 28 11:37:32 1999
+++ linux/net/ipv4/tcp_output.c Mon May 10 09:55:25 1999
@@ -5,7 +5,7 @@
X *
X * Implementation of the Transmission Control Protocol(TCP).
X *
- * Version: $Id: tcp_output.c,v 1.107 1999/04/28 16:08:12 davem Exp $
+ * Version: $Id: tcp_output.c,v 1.108 1999/05/08 21:48:59 davem Exp $
X *
X * Authors: Ross Biro, <bi...@leland.Stanford.Edu>
X * Fred N. van Kempen, <wal...@uWalt.NL.Mugnet.ORG>
@@ -521,24 +521,39 @@
X void tcp_simple_retransmit(struct sock *sk)
X {
X struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
- struct sk_buff *skb;
- unsigned int mss = tcp_current_mss(sk);
+ struct sk_buff *skb, *old_next_skb;
+ unsigned int mss = tcp_current_mss(sk);
X
X /* Don't muck with the congestion window here. */
X tp->dup_acks = 0;
X tp->high_seq = tp->snd_nxt;
- tp->retrans_head = NULL;
+ tp->retrans_head = NULL;
X
X /* Input control flow will see that this was retransmitted
X * and not use it for RTT calculation in the absence of
X * the timestamp option.


SHAR_EOF
true || echo 'restore of patch-2.2.8 failed'
fi

echo 'End of part 32'
echo 'File patch-2.2.8 is continued in part 33'
echo 33 > _shar_seq_.tmp

Thomas...@ciw.uni-karlsruhe.de

unread,
May 12, 1999, 3:00:00 AM5/12/99
to
Archive-name: v2.2/patch-2.2.8/part33

#!/bin/sh
# this is part 33 of a 33 - part archive


# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.8 continued
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 33; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.8'
else
echo 'x - continuing with patch-2.2.8'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.8' &&

X */
- for (skb = skb_peek(&sk->write_queue);
+ for (old_next_skb = skb = skb_peek(&sk->write_queue);
X ((skb != tp->send_head) &&
X (skb != (struct sk_buff *)&sk->write_queue));
- skb = skb->next)
- if (skb->len > mss)
- tcp_retransmit_skb(sk, skb);
+ skb = skb->next) {
+ int resend_skb = 0;
+
+ /* Our goal is to push out the packets which we
+ * sent already, but are being chopped up now to
+ * account for the PMTU information we have.
+ *
+ * As we resend the queue, packets are fragmented
+ * into two pieces, and when we try to send the
+ * second piece it may be collapsed together with
+ * a subsequent packet, and so on. -DaveM
+ */
+ if (old_next_skb != skb || skb->len > mss)
+ resend_skb = 1;
+ old_next_skb = skb->next;
+ if (resend_skb != 0)
+ tcp_retransmit_skb(sk, skb);
+ }
X }
X
X static __inline__ void update_retrans_head(struct sock *sk)
diff -u --recursive --new-file v2.2.7/linux/net/ipv4/tcp_timer.c linux/net/ipv4/tcp_timer.c
--- v2.2.7/linux/net/ipv4/tcp_timer.c Wed Apr 28 11:37:32 1999
+++ linux/net/ipv4/tcp_timer.c Mon May 10 09:55:25 1999


@@ -5,7 +5,7 @@
X *
X * Implementation of the Transmission Control Protocol(TCP).
X *

- * Version: $Id: tcp_timer.c,v 1.60 1999/04/28 16:08:21 davem Exp $
+ * Version: $Id: tcp_timer.c,v 1.62 1999/05/08 21:09:55 davem Exp $


X *
X * Authors: Ross Biro, <bi...@leland.Stanford.Edu>
X * Fred N. van Kempen, <wal...@uWalt.NL.Mugnet.ORG>

@@ -317,48 +317,47 @@
X void tcp_tw_schedule(struct tcp_tw_bucket *tw)
X {
X int slot = (tcp_tw_death_row_slot - 1) & (TCP_TWKILL_SLOTS - 1);
+ struct tcp_tw_bucket **tpp = &tcp_tw_death_row[slot];
+
+ if((tw->next_death = *tpp) != NULL)
+ (*tpp)->pprev_death = &tw->next_death;
+ *tpp = tw;
+ tw->pprev_death = tpp;
X
X tw->death_slot = slot;
- tw->next_death = tcp_tw_death_row[slot];
- tcp_tw_death_row[slot] = tw;
+
X tcp_inc_slow_timer(TCP_SLT_TWKILL);
X }
X
X /* Happens rarely if at all, no care about scalability here. */
X void tcp_tw_reschedule(struct tcp_tw_bucket *tw)
X {
- struct tcp_tw_bucket *walk;
- int slot = tw->death_slot;
+ struct tcp_tw_bucket **tpp;
+ int slot;
+
+ if(tw->next_death)
+ tw->next_death->pprev_death = tw->pprev_death;
+ *tw->pprev_death = tw->next_death;
+ tw->pprev_death = NULL;
X
- walk = tcp_tw_death_row[slot];
- if(walk == tw) {
- tcp_tw_death_row[slot] = tw->next_death;
- } else {
- while(walk->next_death != tw)
- walk = walk->next_death;
- walk->next_death = tw->next_death;
- }
X slot = (tcp_tw_death_row_slot - 1) & (TCP_TWKILL_SLOTS - 1);
+ tpp = &tcp_tw_death_row[slot];
+ if((tw->next_death = *tpp) != NULL)
+ (*tpp)->pprev_death = &tw->next_death;
+ *tpp = tw;
+ tw->pprev_death = tpp;
+
X tw->death_slot = slot;
- tw->next_death = tcp_tw_death_row[slot];
- tcp_tw_death_row[slot] = tw;
X /* Timer was incremented when we first entered the table. */
X }
X
X /* This is for handling early-kills of TIME_WAIT sockets. */
X void tcp_tw_deschedule(struct tcp_tw_bucket *tw)
X {
- struct tcp_tw_bucket *walk;
- int slot = tw->death_slot;
-
- walk = tcp_tw_death_row[slot];
- if(walk == tw) {
- tcp_tw_death_row[slot] = tw->next_death;
- } else {
- while(walk->next_death != tw)
- walk = walk->next_death;
- walk->next_death = tw->next_death;
- }
+ if(tw->next_death)
+ tw->next_death->pprev_death = tw->pprev_death;
+ *tw->pprev_death = tw->next_death;
+ tw->pprev_death = NULL;
X tcp_dec_slow_timer(TCP_SLT_TWKILL);
X }
X
@@ -478,7 +477,7 @@
X * means it must be an accurate representation of our current
X * sending rate _and_ the snd_wnd.
X */
- tp->snd_ssthresh = max(min(tp->snd_wnd, tp->snd_cwnd) >> 1, 2);


+ tp->snd_ssthresh = tcp_recalc_ssthresh(tp);

X tp->snd_cwnd_cnt = 0;

X tp->snd_cwnd = 1;
X }
diff -u --recursive --new-file v2.2.7/linux/net/ipv4/udp.c linux/net/ipv4/udp.c
--- v2.2.7/linux/net/ipv4/udp.c Tue Mar 23 14:35:48 1999
+++ linux/net/ipv4/udp.c Mon May 10 09:55:25 1999


@@ -5,7 +5,7 @@
X *

X * The User Datagram Protocol (UDP).
X *
- * Version: $Id: udp.c,v 1.65 1999/03/21 05:22:49 davem Exp $
+ * Version: $Id: udp.c,v 1.66 1999/05/08 20:00:25 davem Exp $


X *
X * Authors: Ross Biro, <bi...@leland.Stanford.Edu>
X * Fred N. van Kempen, <wal...@uWalt.NL.Mugnet.ORG>

@@ -955,7 +955,7 @@
X * Error for blocking case is chosen to masquerade
X * as some normal condition.
X */
- return (msg->msg_flags&MSG_DONTWAIT) ? -EAGAIN : -EHOSTUNREACH;
+ return (flags&MSG_DONTWAIT) ? -EAGAIN : -EHOSTUNREACH;
X #endif
X }
X
diff -u --recursive --new-file v2.2.7/linux/net/ipv6/udp.c linux/net/ipv6/udp.c
--- v2.2.7/linux/net/ipv6/udp.c Wed Apr 28 11:37:32 1999
+++ linux/net/ipv6/udp.c Mon May 10 09:55:25 1999


@@ -7,7 +7,7 @@
X *

X * Based on linux/ipv4/udp.c
X *
- * $Id: udp.c,v 1.39 1999/04/22 10:07:47 davem Exp $
+ * $Id: udp.c,v 1.40 1999/05/08 20:00:32 davem Exp $


X *
X * This program is free software; you can redistribute it and/or
X * modify it under the terms of the GNU General Public License

@@ -381,7 +381,7 @@
X /* Error for blocking case is chosen to masquerade
X as some normal condition.
X */
- err = (msg->msg_flags&MSG_DONTWAIT) ? -EAGAIN : -EHOSTUNREACH;
+ err = (flags&MSG_DONTWAIT) ? -EAGAIN : -EHOSTUNREACH;
X udp_stats_in6.UdpInErrors++;
X goto out_free;
X }
@@ -398,7 +398,7 @@
X /* Error for blocking case is chosen to masquerade
X as some normal condition.
X */
- err = (msg->msg_flags&MSG_DONTWAIT) ? -EAGAIN : -EHOSTUNREACH;
+ err = (flags&MSG_DONTWAIT) ? -EAGAIN : -EHOSTUNREACH;
X udp_stats_in6.UdpInErrors++;
X goto out_free;
X }
diff -u --recursive --new-file v2.2.7/linux/net/irda/ircomm/ircomm_common.c linux/net/irda/ircomm/ircomm_common.c
--- v2.2.7/linux/net/irda/ircomm/ircomm_common.c Wed Apr 28 11:37:32 1999
+++ linux/net/irda/ircomm/ircomm_common.c Thu May 6 16:40:53 1999
@@ -147,13 +147,7 @@
X };
X
X #ifdef CONFIG_PROC_FS
-extern struct proc_dir_entry proc_irda;
-struct proc_dir_entry proc_ircomm = {
- 0, 6, "ircomm",
- S_IFREG | S_IRUGO, 1, 0, 0,
- 0, NULL,
- &ircomm_proc_read,
-};
+extern struct proc_dir_entry *proc_irda;
X #endif
X
X static void (*state[])( struct ircomm_cb *self, IRCOMM_EVENT event,
@@ -229,7 +223,7 @@
X */
X
X #ifdef CONFIG_PROC_FS
- proc_register( &proc_irda, &proc_ircomm);
+ create_proc_entry("ircomm", 0, proc_irda)->get_info = ircomm_proc_read;
X #endif /* CONFIG_PROC_FS */
X
X
@@ -267,7 +261,7 @@
X }
X
X #ifdef CONFIG_PROC_FS
- proc_unregister( &proc_irda, proc_ircomm.low_ino);
+ remove_proc_entry("ircomm", proc_irda);
X #endif /* CONFIG_PROC_FS */
X }
X #endif /* MODULE */
diff -u --recursive --new-file v2.2.7/linux/net/irda/irlan/irlan_common.c linux/net/irda/irlan/irlan_common.c
--- v2.2.7/linux/net/irda/irlan/irlan_common.c Wed Apr 28 11:37:32 1999
+++ linux/net/irda/irlan/irlan_common.c Thu May 6 16:40:53 1999
@@ -99,15 +99,8 @@
X static int irlan_proc_read(char *buf, char **start, off_t offset, int len,
X int unused);
X
-extern struct proc_dir_entry proc_irda;
-
-struct proc_dir_entry proc_irlan = {
- 0, 5, "irlan",
- S_IFREG | S_IRUGO, 1, 0, 0,
- 0, NULL,
- &irlan_proc_read,
-};
-#endif /* CONFIG_PROC_FS */
+extern struct proc_dir_entry *proc_irda;
+#endif
X
X void irlan_watchdog_timer_expired(unsigned long data)
X {
@@ -188,7 +181,7 @@
X return -ENOMEM;
X }
X #ifdef CONFIG_PROC_FS
- proc_register(&proc_irda, &proc_irlan);
+ create_proc_entry("irlan", 0, proc_irda)->get_info = irlan_proc_read;
X #endif /* CONFIG_PROC_FS */
X
X DEBUG(4, __FUNCTION__ "()\n");
@@ -224,7 +217,7 @@
X irlmp_unregister_service(skey);
X
X #ifdef CONFIG_PROC_FS
- proc_unregister(&proc_irda, proc_irlan.low_ino);
+ remove_proc_entry("irlan", proc_irda);
X #endif /* CONFIG_PROC_FS */
X /*
X * Delete hashbin and close all irlan client instances in it
diff -u --recursive --new-file v2.2.7/linux/net/irda/irlpt/irlpt_cli.c linux/net/irda/irlpt/irlpt_cli.c
--- v2.2.7/linux/net/irda/irlpt/irlpt_cli.c Wed Apr 28 11:37:32 1999
+++ linux/net/irda/irlpt/irlpt_cli.c Thu May 6 16:40:53 1999
@@ -157,14 +157,7 @@


X return len;
X }
X

-struct proc_dir_entry proc_irlpt_client = {
- 0, 12, "irlpt_client",
- S_IFREG | S_IRUGO, 1, 0, 0,
- 0, NULL /* ops -- default to array */,
- &irlpt_client_proc_read /* get_info */,
-};
-
-extern struct proc_dir_entry proc_irda;
+extern struct proc_dir_entry *proc_irda;
X
X #endif /* CONFIG_PROC_FS */
X
@@ -193,7 +186,8 @@
X NULL);
X
X #ifdef CONFIG_PROC_FS
- proc_register( &proc_irda, &proc_irlpt_client);
+ create_proc_entry("irlpt_client", 0, proc_irda)->get_info
+ = irlpt_client_proc_read;
X #endif /* CONFIG_PROC_FS */
X
X DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n");
@@ -219,7 +213,7 @@
X hashbin_delete( irlpt_clients, (FREE_FUNC) irlpt_client_close);
X
X #ifdef CONFIG_PROC_FS
- proc_unregister( &proc_irda, proc_irlpt_client.low_ino);
+ remove_proc_entry("irlpt_client", proc_irda);
X #endif
X
X DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n");
diff -u --recursive --new-file v2.2.7/linux/net/irda/irlpt/irlpt_srvr.c linux/net/irda/irlpt/irlpt_srvr.c
--- v2.2.7/linux/net/irda/irlpt/irlpt_srvr.c Fri Apr 16 14:47:31 1999
+++ linux/net/irda/irlpt/irlpt_srvr.c Thu May 6 16:40:53 1999
@@ -160,14 +160,7 @@


X return len;
X }
X

-extern struct proc_dir_entry proc_irda;
-
-struct proc_dir_entry proc_irlpt_server = {
- 0, 12, "irlpt_server",
- S_IFREG | S_IRUGO, 1, 0, 0,
- 0, NULL /* ops -- default to array */,
- &irlpt_server_proc_read /* get_info */,
-};
+extern struct proc_dir_entry *proc_irda;
X
X #endif /* CONFIG_PROC_FS */
X
@@ -215,7 +208,8 @@
X register_irlpt_server();
X
X #ifdef CONFIG_PROC_FS
- proc_register( &proc_irda, &proc_irlpt_server);
+ create_proc_entry("irlpt_server", 0, proc_irda)->get_info
+ = irlpt_server_proc_read;
X #endif /* CONFIG_PROC_FS */
X
X DEBUG( irlpt_server_debug, __FUNCTION__ " -->\n");
@@ -248,7 +242,7 @@
X kfree(irlpt_server);
X
X #ifdef CONFIG_PROC_FS
- proc_unregister( &proc_irda, proc_irlpt_server.low_ino);
+ remove_proc_entry("irlpt_server", proc_irda);
X #endif
X
X DEBUG( irlpt_server_debug, __FUNCTION__ " -->\n");
diff -u --recursive --new-file v2.2.7/linux/net/irda/irproc.c linux/net/irda/irproc.c
--- v2.2.7/linux/net/irda/irproc.c Fri Apr 16 14:47:31 1999
+++ linux/net/irda/irproc.c Mon May 10 13:01:21 1999
@@ -32,11 +32,6 @@
X #include <net/irda/irlap.h>
X #include <net/irda/irlmp.h>
X
-static int proc_irda_lookup(struct inode * dir, struct dentry *dentry);
-
-static int proc_irda_readdir(struct file *filp, void *dirent,
- filldir_t filldir);
-
X extern int irda_device_proc_read(char *buf, char **start, off_t offset,
X int len, int unused);
X extern int irlap_proc_read(char *buf, char **start, off_t offset, int len,
@@ -50,9 +45,6 @@
X extern int discovery_proc_read(char *buf, char **start, off_t offset, int len,
X int unused);
X
-static int proc_discovery_read(char *buf, char **start, off_t offset, int len,
- int unused);
-
X enum irda_directory_inos {
X PROC_IRDA_LAP = 1,
X PROC_IRDA_LMP,
@@ -63,121 +55,26 @@
X PROC_IRDA_IRIAS
X };
X
-static struct file_operations proc_irda_dir_operations = {
- NULL, /* lseek - default */
- NULL, /* read - bad */
- NULL, /* write - bad */
- proc_irda_readdir, /* readdir */
- NULL, /* select - default */
- NULL, /* ioctl - default */
- NULL, /* mmap */
- NULL, /* no special open code */


- NULL, /* no special release code */

- NULL /* can't fsync */
-};
-
-/*
- * proc directories can do almost nothing..
- */
-struct inode_operations proc_irda_dir_inode_operations = {
- &proc_irda_dir_operations, /* default net directory file-ops */
- NULL, /* create */
- proc_irda_lookup,
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* bmap */
- NULL, /* truncate */
- NULL /* permission */
+struct irda_entry {
+ char *name;
+ int (*fn)(char*,char**,off_t,int,int);
X };
X
-struct proc_dir_entry proc_irda = {
- 0, 4, "irda",
- S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0,
- 0, &proc_irda_dir_inode_operations,
- NULL, NULL,
- NULL,
- NULL, NULL
-};
+struct proc_dir_entry *proc_irda;
X
+static struct irda_entry dir[] = {
X #if 0
-struct proc_dir_entry proc_lpt = {
- 0, 3, "lpt",
- S_IFREG | S_IRUGO, 1, 0, 0,
- 0, NULL /* ops -- default to array */,
- &irlpt_proc_read /* get_info */,
-};
+ {"lpt", irlpt_proc_read},
X #endif
-
-struct proc_dir_entry proc_discovery = {
- 0, 9, "discovery",
- S_IFREG | S_IRUGO, 1, 0, 0,
- 0, NULL /* ops -- default to array */,
- &discovery_proc_read /* get_info */,
+ {"discovery", discovery_proc_read},
+ {"irda_device", irda_device_proc_read},
+ {"irttp", irttp_proc_read},
+ {"irlmp", irlmp_proc_read},
+ {"irlap", irlap_proc_read},
+ {"irias", irias_proc_read},
X };
X
-struct proc_dir_entry proc_irda_device = {
- 0, 11, "irda_device",
- S_IFREG | S_IRUGO, 1, 0, 0,
- 0, NULL,
- &irda_device_proc_read,
-};
-
-struct proc_dir_entry proc_ttp = {
- 0, 5, "irttp",
- S_IFREG | S_IRUGO, 1, 0, 0,
- 0, NULL /* ops -- default to array */,
- &irttp_proc_read /* get_info */,
-};
-
-struct proc_dir_entry proc_lmp = {
- 0, 5, "irlmp",
- S_IFREG | S_IRUGO, 1, 0, 0,
- 0, NULL /* ops -- default to array */,
- &irlmp_proc_read /* get_info */,
-};
-
-struct proc_dir_entry proc_lap = {
- 0, 5, "irlap",
- S_IFREG | S_IRUGO, 1, 0, 0,
- 0, NULL /* ops -- default to array */,
- &irlap_proc_read /* get_info */,
-};
-
-struct proc_dir_entry proc_ias = {
- 0, 5, "irias",
- S_IFREG | S_IRUGO, 1, 0, 0,
- 0, NULL /* ops -- default to array */,
- &irias_proc_read /* get_info */,
-};
-
-/*
- * Function proc_delete_dentry (dentry)
- *
- * Copy of proc/root.c because this function is invisible to the irda
- * module
- *
- */
-static void proc_delete_dentry(struct dentry * dentry)
-{
- d_drop(dentry);
-}
-
-static struct dentry_operations proc_dentry_operations =
-{
- NULL, /* revalidate */
- NULL, /* d_hash */
- NULL, /* d_compare */
- proc_delete_dentry /* d_delete(struct dentry *) */
-};
+#define IRDA_ENTRIES_NUM (sizeof(dir)/sizeof(dir[0]))
X
X /*
X * Function irda_proc_register (void)
@@ -186,16 +83,13 @@
X *
X */
X void irda_proc_register(void) {
- proc_net_register(&proc_irda);
+ int i;
+ proc_irda = create_proc_entry("net/irda", S_IFDIR, NULL);
X #ifdef MODULE
- proc_irda.fill_inode = &irda_proc_modcount;
+ proc_irda->fill_inode = &irda_proc_modcount;
X #endif /* MODULE */
- proc_register(&proc_irda, &proc_lap);
- proc_register(&proc_irda, &proc_lmp);
- proc_register(&proc_irda, &proc_ttp);
- proc_register(&proc_irda, &proc_ias);
- proc_register(&proc_irda, &proc_irda_device);
- proc_register(&proc_irda, &proc_discovery);
+ for (i=0;i<IRDA_ENTRIES_NUM;i++)
+ create_proc_entry(dir[i].name,0,proc_irda)->get_info=dir[i].fn;
X }
X
X /*
@@ -205,116 +99,8 @@
X *
X */
X void irda_proc_unregister(void) {
- proc_unregister(&proc_irda, proc_discovery.low_ino);
- proc_unregister(&proc_irda, proc_irda_device.low_ino);
- proc_unregister(&proc_irda, proc_ias.low_ino);
- proc_unregister(&proc_irda, proc_ttp.low_ino);
- proc_unregister(&proc_irda, proc_lmp.low_ino);
- proc_unregister(&proc_irda, proc_lap.low_ino);
- proc_unregister(proc_net, proc_irda.low_ino);
-}
-
-/*
- * Function proc_irda_lookup (dir, dentry)
- *
- * This is a copy of proc_lookup from the linux-2.2.x kernel
- *
- */
-int proc_irda_lookup(struct inode * dir, struct dentry *dentry)
-{
- struct inode *inode;
- struct proc_dir_entry * de;
- int error;
-
- error = -ENOTDIR;


- if (!dir || !S_ISDIR(dir->i_mode))

- goto out;
-
- error = -ENOENT;
- inode = NULL;
- de = (struct proc_dir_entry *) dir->u.generic_ip;
- if (de) {
- for (de = de->subdir; de ; de = de->next) {
- if (!de || !de->low_ino)
- continue;
- if (de->namelen != dentry->d_name.len)
- continue;
- if (!memcmp(dentry->d_name.name, de->name, de->namelen)) {
- int ino = de->low_ino | (dir->i_ino & ~(0xffff));
- error = -EINVAL;
- inode = proc_get_inode(dir->i_sb, ino, de);
- break;
- }
- }
- }
-
- if (inode) {
- dentry->d_op = &proc_dentry_operations;
- d_add(dentry, inode);
- error = 0;
- }
-out:
- return error;
-}
-
-/*
- * Function proc_irda_readdir (filp, dirent, filldir)
- *
- * This is a copy from linux/fs/proc because the function is invisible
- * to the irda module
- *
- */
-static int proc_irda_readdir(struct file *filp, void *dirent,
- filldir_t filldir)
-{
- struct proc_dir_entry * de;
- unsigned int ino;
X int i;
-
- struct inode *inode = filp->f_dentry->d_inode;
- if (!inode || !S_ISDIR(inode->i_mode))
- return -ENOTDIR;
- ino = inode->i_ino;
- de = (struct proc_dir_entry *) inode->u.generic_ip;
- if (!de)
- return -EINVAL;
- i = filp->f_pos;
- switch (i) {
- case 0:
- if (filldir(dirent, ".", 1, i, ino) < 0)
- return 0;
- i++;
- filp->f_pos++;
- /* fall through */
- case 1:
- if (filldir(dirent, "..", 2, i, de->parent->low_ino) < 0)
- return 0;
- i++;
- filp->f_pos++;
- /* fall through */
- default:
- ino &= ~0xffff;
- de = de->subdir;
- i -= 2;
- for (;;) {
- if (!de)
- return 1;
- if (!i)
- break;
- de = de->next;
- i--;
- }
-
- do {
- if (filldir(dirent, de->name, de->namelen, filp->f_pos,
- ino | de->low_ino) < 0)
- return 0;
- filp->f_pos++;
- de = de->next;
- } while (de);
- }
- return 1;
+ for (i=0;i<IRDA_ENTRIES_NUM;i++)
+ remove_proc_entry(dir[i].name, proc_irda);
+ remove_proc_entry("net/irda", NULL);
X }
-
-
-
diff -u --recursive --new-file v2.2.7/linux/net/sunrpc/sched.c linux/net/sunrpc/sched.c
--- v2.2.7/linux/net/sunrpc/sched.c Wed Mar 10 15:29:53 1999
+++ linux/net/sunrpc/sched.c Fri May 7 11:19:11 1999
@@ -174,6 +174,7 @@
X printk(KERN_ERR "RPC: task w/ running timer in rpc_make_runnable!!\n");
X return;
X }
+ task->tk_flags |= RPC_TASK_RUNNING;
X if (RPC_IS_ASYNC(task)) {
X int status;
X status = rpc_add_wait_queue(&schedq, task);
@@ -186,7 +187,6 @@
X } else {
X wake_up(&task->tk_wait);
X }
- task->tk_flags |= RPC_TASK_RUNNING;
X }
X
X
@@ -447,7 +447,10 @@
X task->tk_pid);
X if (current->pid == rpciod_pid)
X printk(KERN_ERR "RPC: rpciod waiting on sync task!\n");
- sleep_on(&task->tk_wait);
+
+ sti();
+ __wait_event(task->tk_wait, RPC_IS_RUNNING(task));
+ cli();
X
X /*
X * When the task received a signal, remove from
diff -u --recursive --new-file v2.2.7/linux/net/sunrpc/svcsock.c linux/net/sunrpc/svcsock.c
--- v2.2.7/linux/net/sunrpc/svcsock.c Tue Mar 23 14:35:48 1999
+++ linux/net/sunrpc/svcsock.c Tue May 4 10:29:07 1999
@@ -249,7 +249,8 @@
X msg.msg_namelen = sizeof(rqstp->rq_addr);
X msg.msg_iov = iov;
X msg.msg_iovlen = nr;
- msg.msg_control = 0;
+ msg.msg_control = NULL;
+ msg.msg_controllen = 0;
X
X #if LINUX_VERSION_CODE >= 0x020100
X msg.msg_flags = MSG_DONTWAIT;
@@ -308,7 +309,8 @@
X msg.msg_namelen = sizeof(rqstp->rq_addr);
X msg.msg_iov = iov;
X msg.msg_iovlen = nr;
- msg.msg_control = 0;
+ msg.msg_control = NULL;
+ msg.msg_controllen = 0;
X
X #if LINUX_VERSION_CODE >= 0x020100
X msg.msg_flags = MSG_DONTWAIT;
diff -u --recursive --new-file v2.2.7/linux/net/sunrpc/xprt.c linux/net/sunrpc/xprt.c
--- v2.2.7/linux/net/sunrpc/xprt.c Tue Mar 23 14:35:48 1999
+++ linux/net/sunrpc/xprt.c Tue May 4 10:29:07 1999
@@ -200,6 +200,7 @@
X msg.msg_name = (struct sockaddr *) &xprt->addr;
X msg.msg_namelen = sizeof(xprt->addr);
X msg.msg_control = NULL;
+ msg.msg_controllen = 0;
X
X /* Dont repeat bytes */
X
@@ -256,6 +257,7 @@
X msg.msg_name = &sin;
X msg.msg_namelen = sizeof(sin);
X msg.msg_control = NULL;
+ msg.msg_controllen = 0;
X
X oldfs = get_fs(); set_fs(get_ds());
X result = sock_recvmsg(sock, &msg, len, MSG_DONTWAIT);
@@ -268,6 +270,7 @@
X msg.msg_name = &sin;
X msg.msg_namelen = sizeof(sin);
X msg.msg_control = NULL;
+ msg.msg_controllen = 0;
X
X oldfs = get_fs(); set_fs(get_ds());
X result = sock->ops->recvmsg(sock, &msg, len, 1, 0, &alen);
diff -u --recursive --new-file v2.2.7/linux/net/unix/af_unix.c linux/net/unix/af_unix.c
--- v2.2.7/linux/net/unix/af_unix.c Mon Mar 29 11:09:12 1999
+++ linux/net/unix/af_unix.c Mon May 10 09:55:25 1999
@@ -8,7 +8,7 @@


X * as published by the Free Software Foundation; either version
X * 2 of the License, or (at your option) any later version.

X *
- * Version: $Id: af_unix.c,v 1.75 1999/03/22 05:02:45 davem Exp $
+ * Version: $Id: af_unix.c,v 1.76 1999/05/08 05:54:55 davem Exp $
X *
X * Fixes:
X * Linus Torvalds : Assorted bug cures.
@@ -322,7 +322,7 @@
X {
X if (sk->type==SOCK_STREAM && unix_our_peer(sk, skpair))
X {
- skpair->state_change(skpair);
+ skpair->data_ready(skpair,0);
X skpair->shutdown=SHUTDOWN_MASK; /* No more writes*/
X }
X unix_unlock(skpair); /* It may now die */
@@ -1409,7 +1409,10 @@
X if (mode&SEND_SHUTDOWN)
X peer_mode |= RCV_SHUTDOWN;
X other->shutdown |= peer_mode;
- other->state_change(other);
+ if (peer_mode&RCV_SHUTDOWN)
+ other->data_ready(other,0);
+ else
+ other->state_change(other);
X }
X }
X return 0;
diff -u --recursive --new-file v2.2.7/linux/scripts/Menuconfig linux/scripts/Menuconfig
--- v2.2.7/linux/scripts/Menuconfig Tue Feb 23 15:21:36 1999
+++ linux/scripts/Menuconfig Sun May 2 09:51:16 1999
@@ -193,7 +193,7 @@
X else if [ "$3" = "m" ]; then
X mod_bool "$1" "$2"
X else
- define_bool "$2" "$n"
+ define_bool "$2" n
X fi; fi
X }
X
diff -u --recursive --new-file v2.2.7/linux/scripts/tkgen.c linux/scripts/tkgen.c
--- v2.2.7/linux/scripts/tkgen.c Tue Feb 23 15:21:36 1999
+++ linux/scripts/tkgen.c Sun May 2 09:51:16 1999
@@ -930,8 +930,11 @@
X
X case token_hex:
X case token_int:
+ printf( "set %s %s\n", cfg->optionname, cfg->value ? cfg->value : "0");
+ break;
+
X case token_string:
- printf( "set %s %s\n", cfg->optionname, cfg->value );
+ printf( "set %s \"%s\"\n", cfg->optionname, cfg->value ? cfg->value : "");
X break;
X }
X }
diff -u --recursive --new-file v2.2.7/linux/scripts/tkparse.c linux/scripts/tkparse.c
--- v2.2.7/linux/scripts/tkparse.c Tue Feb 23 15:21:36 1999
+++ linux/scripts/tkparse.c Sun May 2 09:51:16 1999
@@ -496,10 +496,15 @@
X
X case token_hex:
X case token_int:
- case token_string:
X pnt = get_qstring ( pnt, &cfg->label );
X pnt = get_string ( pnt, &cfg->optionname );
X pnt = get_string ( pnt, &cfg->value );
+ break;
+
+ case token_string:
+ pnt = get_qstring ( pnt, &cfg->label );
+ pnt = get_string ( pnt, &cfg->optionname );
+ pnt = get_qstring ( pnt, &cfg->value );
X break;
X
X case token_if:


SHAR_EOF
true || echo 'restore of patch-2.2.8 failed'

echo 'File patch-2.2.8 is complete' &&
chmod 644 patch-2.2.8 ||


echo 'restore of patch-2.2.8 failed'

Cksum="`cksum < 'patch-2.2.8'`"
if ! test "1861375263 1865967" = "$Cksum"
then
echo 'patch-2.2.8: original Checksum 1861375263 1865967, current one' "$Cksum"
rm -f _shar_wnt_.tmp
rm -f _shar_seq_.tmp
exit 1
fi
rm -f _shar_wnt_.tmp
fi
rm -f _shar_seq_.tmp
echo 'You have unpacked the last part.'

0 new messages