]> git.neil.brown.name Git - history.git/commitdiff
Import 2.3.12pre2 2.3.12pre2
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:26:22 +0000 (15:26 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:26:22 +0000 (15:26 -0500)
73 files changed:
Makefile
arch/alpha/config.in
arch/arm/kernel/setup.c
arch/arm/mm/fault-common.c
arch/i386/config.in
arch/i386/kernel/setup.c
arch/i386/math-emu/fpu_entry.c
arch/i386/math-emu/fpu_system.h
arch/m68k/atari/stram.c
arch/m68k/kernel/process.c
arch/m68k/kernel/setup.c
arch/m68k/mm/fault.c
arch/mips/config.in
arch/mips/mm/fault.c
arch/ppc/config.in
arch/ppc/kernel/apus_setup.c
arch/ppc/kernel/idle.c
arch/ppc/kernel/setup.c
arch/ppc/kernel/smp.c
arch/ppc/mm/fault.c
arch/ppc/mm/init.c
arch/sparc/ap1000/apmmu.c
arch/sparc/kernel/setup.c
arch/sparc/kernel/sun4d_smp.c
arch/sparc/kernel/sun4m_smp.c
arch/sparc/mm/fault.c
arch/sparc/mm/srmmu.c
arch/sparc/mm/sun4c.c
arch/sparc64/config.in
arch/sparc64/kernel/setup.c
arch/sparc64/mm/fault.c
drivers/Makefile
drivers/char/ppdev.c
drivers/misc/BUGS-parport [deleted file]
drivers/misc/Config.in [deleted file]
drivers/misc/Makefile [deleted file]
drivers/misc/TODO-parport [deleted file]
drivers/misc/multiface.h [deleted file]
drivers/misc/parport_amiga.c [deleted file]
drivers/misc/parport_arc.c [deleted file]
drivers/misc/parport_atari.c [deleted file]
drivers/misc/parport_ax.c [deleted file]
drivers/misc/parport_daisy.c [deleted file]
drivers/misc/parport_ieee1284.c [deleted file]
drivers/misc/parport_ieee1284_ops.c [deleted file]
drivers/misc/parport_init.c [deleted file]
drivers/misc/parport_mfc3.c [deleted file]
drivers/misc/parport_pc.c [deleted file]
drivers/misc/parport_probe.c [deleted file]
drivers/misc/parport_procfs.c [deleted file]
drivers/misc/parport_share.c [deleted file]
drivers/parport/BUGS-parport [new file with mode: 0644]
drivers/parport/Config.in [new file with mode: 0644]
drivers/parport/Makefile [new file with mode: 0644]
drivers/parport/TODO-parport [new file with mode: 0644]
drivers/parport/daisy.c [new file with mode: 0644]
drivers/parport/ieee1284.c [new file with mode: 0644]
drivers/parport/ieee1284_ops.c [new file with mode: 0644]
drivers/parport/init.c [new file with mode: 0644]
drivers/parport/multiface.h [new file with mode: 0644]
drivers/parport/parport_amiga.c [new file with mode: 0644]
drivers/parport/parport_arc.c [new file with mode: 0644]
drivers/parport/parport_atari.c [new file with mode: 0644]
drivers/parport/parport_ax.c [new file with mode: 0644]
drivers/parport/parport_mfc3.c [new file with mode: 0644]
drivers/parport/parport_pc.c [new file with mode: 0644]
drivers/parport/probe.c [new file with mode: 0644]
drivers/parport/procfs.c [new file with mode: 0644]
drivers/parport/share.c [new file with mode: 0644]
fs/proc/array.c
fs/proc/link.c
include/asm-i386/semaphore.h
lib/vsprintf.c

index 429bcedf0d112a6f19b7272d69e2cd981e290c4e..8c5a43cd6e0fa117b309c3b1c29b231516a5321d 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -111,7 +111,7 @@ FILESYSTEMS =fs/filesystems.a
 NETWORKS       =net/network.a
 DRIVERS                =drivers/block/block.a \
                 drivers/char/char.a \
-                drivers/misc/misc.a
+                drivers/parport/parport.a
 LIBS           =$(TOPDIR)/lib/lib.a
 SUBDIRS                =kernel drivers mm fs net ipc lib
 
index eb9752970c7974400e9b6fda5d4ffb4fd1d15394..0c00ff22f106a6a5f3777c0f039e72beddad3e06 100644 (file)
@@ -188,7 +188,7 @@ tristate 'Kernel support for a.out (ECOFF) binaries' CONFIG_BINFMT_AOUT
 tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
 tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
 tristate 'Kernel support for Linux/Intel ELF binaries' CONFIG_BINFMT_EM86
-source drivers/misc/Config.in
+source drivers/parpor/Config.in
 endmenu
 
 source drivers/pnp/Config.in
index 4cec8cd03215353cd66a27c4fbabcc5b6dc3bb99..1555278fd5c77d49f5d705b85a58cf4ad14571aa 100644 (file)
@@ -297,10 +297,10 @@ setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigned long * mem
 
        setup_processor();
 
-       init_task.mm->start_code = TASK_SIZE;
-       init_task.mm->end_code   = TASK_SIZE + (unsigned long) &_etext;
-       init_task.mm->end_data   = TASK_SIZE + (unsigned long) &_edata;
-       init_task.mm->brk        = TASK_SIZE + (unsigned long) &_end;
+       init_mm.start_code = TASK_SIZE;
+       init_mm.end_code         = TASK_SIZE + (unsigned long) &_etext;
+       init_mm.end_data         = TASK_SIZE + (unsigned long) &_edata;
+       init_mm.brk      = TASK_SIZE + (unsigned long) &_end;
 
        /*
         * Add your machine dependencies here
index 1251525dac59a358b32b3c2760f188fd0de1c899..219fb34a94e615db4c972ce91fb3e1d5a7bcb164 100644 (file)
@@ -106,7 +106,7 @@ static void do_page_fault(unsigned long addr, int mode, struct pt_regs *regs)
         * If we're in an interrupt or have no user
         * context, we must not take the fault..
         */
-       if (in_interrupt() || mm == &init_mm)
+       if (in_interrupt() || !mm)
                goto no_context;
 
        down(&mm->mmap_sem);
index 56b3fd802fc25b8810300e750096a21a32a88e0b..ae094896a74175400e8ec281933fc805cfc3b7c7 100644 (file)
@@ -92,7 +92,7 @@ tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT
 tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
 tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
 
-source drivers/misc/Config.in
+source drivers/parport/Config.in
 
 bool 'Advanced Power Management BIOS support' CONFIG_APM
 if [ "$CONFIG_APM" = "y" ]; then
index 38e301275a97d3f55f8b051c6f3a2a3b808e0306..120454c6cd373a918302ec58d4ee95ebf258683d 100644 (file)
@@ -313,10 +313,10 @@ __initfunc(void setup_arch(char **cmdline_p,
        if (!MOUNT_ROOT_RDONLY)
                root_mountflags &= ~MS_RDONLY;
        memory_start = (unsigned long) &_end;
-       init_task.mm->start_code = PAGE_OFFSET;
-       init_task.mm->end_code = (unsigned long) &_etext;
-       init_task.mm->end_data = (unsigned long) &_edata;
-       init_task.mm->brk = (unsigned long) &_end;
+       init_mm.start_code = PAGE_OFFSET;
+       init_mm.end_code = (unsigned long) &_etext;
+       init_mm.end_data = (unsigned long) &_edata;
+       init_mm.brk = (unsigned long) &_end;
 
        /* Save unparsed command line copy for /proc/cmdline */
        memcpy(saved_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
@@ -354,7 +354,7 @@ __initfunc(void setup_arch(char **cmdline_p,
        *to = '\0';
        *cmdline_p = command_line;
 
-#define VMALLOC_RESERVE        (64 << 20)      /* 64MB for vmalloc */
+#define VMALLOC_RESERVE        (128 << 20)     /* 128MB for vmalloc and initrd */
 #define MAXMEM ((unsigned long)(-PAGE_OFFSET-VMALLOC_RESERVE))
 
        if (memory_end > MAXMEM)
index 1c5d30e1db394dac9b1aed518a3069228e6b5fbb..9e1484836f3aa3ddf9858cba11db797faa758ac7 100644 (file)
@@ -283,8 +283,8 @@ do_another_FPU_instruction:
          FPU_EIP = FPU_ORIG_EIP;       /* Point to current FPU instruction. */
 
          RE_ENTRANT_CHECK_OFF;
-         current->tss.trap_no = 16;
-         current->tss.error_code = 0;
+         current->thread.trap_no = 16;
+         current->thread.error_code = 0;
          send_sig(SIGFPE, current, 1);
          return;
        }
@@ -662,8 +662,8 @@ static int valid_prefix(u_char *Byte, u_char **fpu_eip,
 void math_abort(struct info * info, unsigned int signal)
 {
        FPU_EIP = FPU_ORIG_EIP;
-       current->tss.trap_no = 16;
-       current->tss.error_code = 0;
+       current->thread.trap_no = 16;
+       current->thread.error_code = 0;
        send_sig(signal,current,1);
        RE_ENTRANT_CHECK_OFF;
        __asm__("movl %0,%%esp ; ret": :"g" (((long) info)-4));
index 1571b2f381745ff742491b806f7bb8d744290121..3cda85f6515aae443e3cf633590d02f53c32bc83 100644 (file)
@@ -33,7 +33,7 @@
 #define SEG_EXPAND_DOWN(s)     (((s).b & ((1 << 11) | (1 << 10))) \
                                 == (1 << 10))
 
-#define I387                   (current->tss.i387)
+#define I387                   (current->thread.i387)
 #define FPU_info               (I387.soft.info)
 
 #define FPU_CS                 (*(unsigned short *) &(FPU_info->___cs))
index cade2173ab1251fd8f8dd26677745dd9d6ba1db2..f398f731050e387de4b065381c0dc71569265c60 100644 (file)
@@ -805,7 +805,7 @@ static void unswap_process(struct mm_struct * mm, unsigned long entry,
        /*
         * Go through process' page directory.
         */
-       if (!mm || mm == &init_mm)
+       if (!mm)
                return;
        for (vma = mm->mmap; vma; vma = vma->vm_next) {
                pgd_t * pgd = pgd_offset(mm, vma->vm_start);
index 97f3bd15134dcbba1f1724cb5d0649f7e820b1e4..cb5e5f781565b554afad16ca5e73a8333a26bb86 100644 (file)
@@ -43,7 +43,7 @@ static struct fs_struct init_fs = INIT_FS;
 static struct file * init_fd_array[NR_OPEN] = { NULL, };
 static struct files_struct init_files = INIT_FILES;
 static struct signal_struct init_signals = INIT_SIGNALS;
-struct mm_struct init_mm = INIT_MM;
+struct mm_struct init_mm = INIT_MM(init_mm);
 
 union task_union init_task_union
        __attribute__((section("init_task"), aligned(2*PAGE_SIZE)))
index 39dcd9c15ae60ab7a0e93337ccb75972ba93d11b..b9124eda7e0ad970d4f94c4ad750ce4aa6b0b60e 100644 (file)
@@ -213,10 +213,10 @@ __initfunc(void setup_arch(char **cmdline_p, unsigned long * memory_start_p,
                asm __volatile__ ("frestore %0" : : "m" (zero));
        }
 
-       init_task.mm->start_code = PAGE_OFFSET;
-       init_task.mm->end_code = (unsigned long) &_etext;
-       init_task.mm->end_data = (unsigned long) &_edata;
-       init_task.mm->brk = (unsigned long) &_end;
+       init_mm.start_code = PAGE_OFFSET;
+       init_mm.end_code = (unsigned long) &_etext;
+       init_mm.end_data = (unsigned long) &_edata;
+       init_mm.brk = (unsigned long) &_end;
 
        *cmdline_p = m68k_command_line;
        memcpy(saved_command_line, *cmdline_p, CL_SIZE);
index ef1b855bd72b0fb019d65504e43732b3935a5ed6..7ae87b23f5f8b453a100ca78e739f80d280732e0 100644 (file)
@@ -49,7 +49,7 @@ asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
         * If we're in an interrupt or have no user
         * context, we must not take the fault..
         */
-       if (in_interrupt() || mm == &init_mm)
+       if (in_interrupt() || !mm)
                goto no_context;
 
        down(&mm->mmap_sem);
index ea48cabb7606c3a2807cb40762cacef53e728022..2170bde85bea6a1358843265768e6afae4adc82d 100644 (file)
@@ -93,7 +93,7 @@ bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT
 bool 'Sysctl support' CONFIG_SYSCTL
 
 if [ "$CONFIG_SGI" != "y" -a "$CONFIG_DECSTATION" != "y" -a "$CONFIG_BAGET_MIPS" != "y" ]; then
-source drivers/misc/Config.in
+source drivers/parport/Config.in
 fi
 endmenu
 
index efc59dee6f2233439295d018745d701163008d4f..2389c0b86ba8ddd713f8cd978ecb60f9a703eda6 100644 (file)
@@ -55,7 +55,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long write,
         * If we're in an interrupt or have no user
         * context, we must not take the fault..
         */
-       if (in_interrupt() || mm == &init_mm)
+       if (in_interrupt() || !mm)
                goto no_context;
 #if 0
        printk("[%s:%d:%08lx:%ld:%08lx]\n", current->comm, current->pid,
index 3336277f9d04de6ef43c213b7c3b7cfd94f5cd4e..416d1c57b58f26cf657cbbed956eee7d46deeeb4 100644 (file)
@@ -66,7 +66,7 @@ define_bool CONFIG_BINFMT_ELF y
 define_bool CONFIG_KERNEL_ELF y
 tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
 
-source drivers/misc/Config.in
+source drivers/parport/Config.in
 
 bool 'Support for VGA Console' CONFIG_VGA_CONSOLE
 bool 'Support for frame buffer devices' CONFIG_FB
index 2540e09111fcffff1d9e76f4ab5b52749cb559ca..0ee33bb49656902501aea09c3b13e92b3f936c94 100644 (file)
@@ -345,7 +345,7 @@ void kernel_set_cachemode( unsigned long address, unsigned long size,
        {
                pte_t *pte;
 
-               pte = my_find_pte(init_task.mm, address);
+               pte = my_find_pte(&init_mm, address);
                if ( !pte )
                {
                        printk("pte NULL in kernel_set_cachemode()\n");
@@ -354,7 +354,7 @@ void kernel_set_cachemode( unsigned long address, unsigned long size,
 
                 pte_val (*pte) &= mask;
                 pte_val (*pte) |= flags;
-                flush_tlb_page(find_vma(init_task.mm,address),address);
+                flush_tlb_page(find_vma(&init_mm,address),address);
 
                address += PAGE_SIZE;
        }
index 51246d32e6a96cd14d0664b2cb6a222e4a339251..a5a935c5d8a5dbba7eeeced24258fe2a12258729 100644 (file)
@@ -227,7 +227,7 @@ void zero_paged(void)
                /*
                 * Make the page no cache so we don't blow our cache with 0's
                 */
-               pte = find_pte(init_task.mm, pageptr);
+               pte = find_pte(&init_mm, pageptr);
                if ( !pte )
                {
                        printk("pte NULL in zero_paged()\n");
@@ -235,7 +235,7 @@ void zero_paged(void)
                }
                
                pte_uncache(*pte);
-               flush_tlb_page(find_vma(init_task.mm,pageptr),pageptr);
+               flush_tlb_page(find_vma(&init_mm,pageptr),pageptr);
                /*
                 * Important here to not take time away from real processes.
                 */
@@ -260,7 +260,7 @@ void zero_paged(void)
                
                /* turn cache on for this page */
                pte_cache(*pte);
-               flush_tlb_page(find_vma(init_task.mm,pageptr),pageptr);
+               flush_tlb_page(find_vma(&init_mm,pageptr),pageptr);
                /* atomically add this page to the list */
                asm (   "101:lwarx  %0,0,%1\n"  /* reserve zero_cache */
                        "    stw    %0,0(%2)\n" /* update *pageptr */
index 181a72d37807981481edd3e31fdf657588dd4044..ee3ace0a2088d8a44432f2178cbde5704779588c 100644 (file)
@@ -527,10 +527,10 @@ __initfunc(void setup_arch(char **cmdline_p,
        /* reboot on panic */   
        panic_timeout = 180;
        
-       init_task.mm->start_code = PAGE_OFFSET;
-       init_task.mm->end_code = (unsigned long) _etext;
-       init_task.mm->end_data = (unsigned long) _edata;
-       init_task.mm->brk = (unsigned long) klimit;     
+       init_mm.start_code = PAGE_OFFSET;
+       init_mm.end_code = (unsigned long) _etext;
+       init_mm.end_data = (unsigned long) _edata;
+       init_mm.brk = (unsigned long) klimit;   
 
        /* Save unparsed command line copy for /proc/cmdline */
        strcpy(saved_command_line, cmd_line);
index ee48d5bef38c0eac9210d4ffd40b3d4752fa77de..18c94c00ae668a7a8587767b2286a9bda68de01c 100644 (file)
@@ -403,7 +403,7 @@ void __init smp_callin(void)
 #if 0
        current->mm->mmap->vm_page_prot = PAGE_SHARED;
        current->mm->mmap->vm_start = PAGE_OFFSET;
-       current->mm->mmap->vm_end = init_task.mm->mmap->vm_end;
+       current->mm->mmap->vm_end = init_mm.mmap->vm_end;
 #endif
        cpu_callin_map[current->processor] = 1;
        while(!smp_commenced)
index fde053df9b4039c130e03a2571255c96c2e372ed..e2f02135f548a25e6c629cd9c619ecf8248afe58 100644 (file)
@@ -82,7 +82,7 @@ void do_page_fault(struct pt_regs *regs, unsigned long address,
                        return;
        }
 #endif
-       if (in_interrupt()) {
+       if (in_interrupt() || !mm) {
                static int complained;
                if (complained < 20) {
                        ++complained;
index f4524bc3dcb1a53ceee671e5d054ad8b160f7e17..ec390724ccf3a84d8c03e5a0197345d28ca6e164 100644 (file)
@@ -444,11 +444,11 @@ unsigned long iopa(unsigned long addr)
 #endif /* CONFIG_APUS */
 #endif /* CONFIG_8xx */
        /* Do we have a page table? */
-       if (init_task.mm->pgd == NULL)
+       if (init_mm.pgd == NULL)
                return 0;
 
        /* Use upper 10 bits of addr to index the first level map */
-       pd = (pmd_t *) (init_task.mm->pgd + (addr >> PGDIR_SHIFT));
+       pd = (pmd_t *) (init_mm.pgd + (addr >> PGDIR_SHIFT));
        if (pmd_none(*pd))
                return 0;
 
index e07b4f4b193aa9a455f1fc69e0bceaeb67824be3..0140cde35d03fac69236b4f8c8c62b456ec52a41 100644 (file)
@@ -295,7 +295,7 @@ static inline unsigned long apmmu_hwprobe(unsigned long vaddr)
 
 static inline void apmmu_uncache_page(unsigned long addr)
 {
-       pgd_t *pgdp = apmmu_pgd_offset(init_task.mm, addr);
+       pgd_t *pgdp = apmmu_pgd_offset(&init_mm, addr);
        pmd_t *pmdp;
        pte_t *ptep;
 
@@ -316,7 +316,7 @@ static inline void apmmu_uncache_page(unsigned long addr)
 
 static inline void apmmu_recache_page(unsigned long addr)
 {
-       pgd_t *pgdp = apmmu_pgd_offset(init_task.mm, addr);
+       pgd_t *pgdp = apmmu_pgd_offset(&init_mm, addr);
        pmd_t *pmdp;
        pte_t *ptep;
 
@@ -782,7 +782,7 @@ __initfunc(static inline void apmmu_allocate_ptable_skeleton(unsigned long start
        pte_t *ptep;
 
        while(start < end) {
-               pgdp = apmmu_pgd_offset(init_task.mm, start);
+               pgdp = apmmu_pgd_offset(&init_mm, start);
                if(apmmu_pgd_none(*pgdp)) {
                        pmdp = sparc_init_alloc(&mempool, APMMU_PMD_TABLE_SIZE);
                        apmmu_early_pgd_set(pgdp, pmdp);
@@ -804,7 +804,7 @@ __initfunc(static void make_page(unsigned virt_page, unsigned phys_page, unsigne
        pte_t *ptep;
        unsigned start = virt_page<<12;
 
-       pgdp = apmmu_pgd_offset(init_task.mm, start);
+       pgdp = apmmu_pgd_offset(&init_mm, start);
        if(apmmu_pgd_none(*pgdp)) {
                pmdp = sparc_init_alloc(&mempool, APMMU_PMD_TABLE_SIZE);
                apmmu_early_pgd_set(pgdp, pmdp);
@@ -824,7 +824,7 @@ __initfunc(static void make_large_page(unsigned virt_page, unsigned phys_page, u
        pgd_t *pgdp;
        unsigned start = virt_page<<12;
 
-       pgdp = apmmu_pgd_offset(init_task.mm, start);
+       pgdp = apmmu_pgd_offset(&init_mm, start);
        *pgdp = __pgd((phys_page<<8) | prot);
 }
 
@@ -907,7 +907,7 @@ __initfunc(static void map_kernel(void))
                make_large_page((KERNBASE+phys)>>12,
                                (phys>>12),
                                APMMU_CACHE|APMMU_PRIV|APMMU_VALID);
-       init_task.mm->mmap->vm_start = page_offset = KERNBASE;
+       init_mm.mmap->vm_start = page_offset = KERNBASE;
        stack_top = page_offset - PAGE_SIZE;
 }
 
index 1e22e086e48d95e249f5c66b8828c45b85feffc8..35a01567197c73eb6fe796aacac9bb1c96dcceff 100644 (file)
@@ -489,10 +489,10 @@ __initfunc(void setup_arch(char **cmdline_p,
 
 
        /* Due to stack alignment restrictions and assumptions... */
-       init_task.mm->mmap->vm_page_prot = PAGE_SHARED;
-       init_task.mm->mmap->vm_start = KERNBASE;
-       init_task.mm->mmap->vm_end = *memory_end_p;
-       init_task.mm->context = (unsigned long) NO_CONTEXT;
+       init_mm.mmap->vm_page_prot = PAGE_SHARED;
+       init_mm.mmap->vm_start = KERNBASE;
+       init_mm.mmap->vm_end = *memory_end_p;
+       init_mm.context = (unsigned long) NO_CONTEXT;
        init_task.tss.kregs = &fake_swapper_regs;
 
        if (serial_console)
index 64ef31bbb4fb5232919762358fd29e0fd1dbe5ec..bde7e58fa6b4af5b52728634be5b5c5728151f8f 100644 (file)
@@ -131,7 +131,7 @@ __initfunc(void smp4d_callin(void))
        
        current->mm->mmap->vm_page_prot = PAGE_SHARED;
        current->mm->mmap->vm_start = PAGE_OFFSET;
-       current->mm->mmap->vm_end = init_task.mm->mmap->vm_end;
+       current->mm->mmap->vm_end = init_mm.mmap->vm_end;
        
        local_flush_cache_all();
        local_flush_tlb_all();
index 3fb1044f4db85c43b6855fa66ffc87de2fb4de18..71466723d64fbf6e7488d4198a62fbfeef1aef72 100644 (file)
@@ -109,7 +109,7 @@ __initfunc(void smp4m_callin(void))
                             : "memory" /* paranoid */);
        current->mm->mmap->vm_page_prot = PAGE_SHARED;
        current->mm->mmap->vm_start = PAGE_OFFSET;
-       current->mm->mmap->vm_end = init_task.mm->mmap->vm_end;
+       current->mm->mmap->vm_end = init_mm.mmap->vm_end;
        
        while(!smp_commenced)
                barrier();
index 0f1f3d983069959ce1ca0c15eacb12012cbc9ed8..fab4084581c8db8c51edd438a839c821050ff169 100644 (file)
@@ -205,7 +205,7 @@ asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write,
         * If we're in an interrupt or have no user
         * context, we must not take the fault..
         */
-        if (in_interrupt() || mm == &init_mm)
+        if (in_interrupt() || !mm)
                 goto do_kernel_fault;
 
        down(&mm->mmap_sem);
index 66d3c535de217200b1ef3094ea38cb0e9fb8cd99..51979a6a05552b1a118f55d1b55132836e4480b8 100644 (file)
@@ -846,7 +846,7 @@ void srmmu_mapioaddr(unsigned long physaddr, unsigned long virt_addr, int bus_ty
        unsigned long tmp;
 
        physaddr &= PAGE_MASK;
-       pgdp = srmmu_pgd_offset(init_task.mm, virt_addr);
+       pgdp = srmmu_pgd_offset(&init_mm, virt_addr);
        pmdp = pmd_offset(pgdp, virt_addr);
        ptep = pte_offset(pmdp, virt_addr);
        tmp = (physaddr >> 4) | SRMMU_ET_PTE;
@@ -871,7 +871,7 @@ void srmmu_unmapioaddr(unsigned long virt_addr)
        pmd_t *pmdp;
        pte_t *ptep;
 
-       pgdp = srmmu_pgd_offset(init_task.mm, virt_addr);
+       pgdp = srmmu_pgd_offset(&init_mm, virt_addr);
        pmdp = pmd_offset(pgdp, virt_addr);
        ptep = pte_offset(pmdp, virt_addr);
 
@@ -1476,7 +1476,7 @@ static inline void srmmu_allocate_ptable_skeleton(unsigned long start, unsigned
        pte_t *ptep;
 
        while(start < end) {
-               pgdp = srmmu_pgd_offset(init_task.mm, start);
+               pgdp = srmmu_pgd_offset(&init_mm, start);
                if(srmmu_pgd_none(*pgdp)) {
                        pmdp = sparc_init_alloc(&mempool, SRMMU_PMD_TABLE_SIZE);
                        srmmu_early_pgd_set(pgdp, pmdp);
@@ -1526,7 +1526,7 @@ __initfunc(void srmmu_inherit_prom_mappings(unsigned long start,unsigned long en
                                what = 2;
                }
     
-               pgdp = srmmu_pgd_offset(init_task.mm, start);
+               pgdp = srmmu_pgd_offset(&init_mm, start);
                if(what == 2) {
                        *pgdp = __pgd(prompte);
                        start += SRMMU_PGDIR_SIZE;
@@ -1626,7 +1626,7 @@ __initfunc(void srmmu_end_memory(unsigned long memory_size, unsigned long *end_m
 /* Create a third-level SRMMU 16MB page mapping. */
 __initfunc(static void do_large_mapping(unsigned long vaddr, unsigned long phys_base))
 {
-       pgd_t *pgdp = srmmu_pgd_offset(init_task.mm, vaddr);
+       pgd_t *pgdp = srmmu_pgd_offset(&init_mm, vaddr);
        unsigned long big_pte;
 
        MKTRACE(("dlm[v<%08lx>-->p<%08lx>]", vaddr, phys_base));
@@ -1840,7 +1840,7 @@ check_and_return:
                }
        }
        MKTRACE(("success\n"));
-       init_task.mm->mmap->vm_start = page_offset = low_base;
+       init_mm.mmap->vm_start = page_offset = low_base;
        stack_top = page_offset - PAGE_SIZE;
        BTFIXUPSET_SETHI(page_offset, low_base);
        BTFIXUPSET_SETHI(stack_top, page_offset - PAGE_SIZE);
index c6bf02fc01c81df29e247ce58ba72de0458c77fb..7d825cc5c2574577ef60f54ee963c2664f661207 100644 (file)
@@ -1560,7 +1560,7 @@ __initfunc(static unsigned long sun4c_init_lock_areas(unsigned long start_mem))
        memset((void *) start_mem, 0, bitmap_size);
        start_mem += bitmap_size;
 
-       sun4c_kstack_vma.vm_mm = init_task.mm;
+       sun4c_kstack_vma.vm_mm = &init_mm;
        sun4c_kstack_vma.vm_start = sun4c_taskstack_start;
        sun4c_kstack_vma.vm_end = sun4c_taskstack_end;
        sun4c_kstack_vma.vm_page_prot = PAGE_SHARED;
index e03e9b4279a06c8920726dd89e6dbf155ee8eba8..bff486931f31d5ad00357c63b101d33d54e8da5d 100644 (file)
@@ -68,7 +68,7 @@ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
 fi
 
 if [ "$CONFIG_PCI" = "y" ]; then
-  source drivers/misc/Config.in
+  source drivers/parport/Config.in
   dep_tristate '  Parallel printer support' CONFIG_PRINTER $CONFIG_PARPORT
   tristate 'SUNW,envctrl support' CONFIG_ENVCTRL
 fi
index d5e980ebf15426fc78d3cb3000225da5bbcb08ec..d47cd82df9c7240a993059c6044a102930b9b680 100644 (file)
@@ -531,10 +531,10 @@ __initfunc(void setup_arch(char **cmdline_p,
 #endif 
 
        /* Due to stack alignment restrictions and assumptions... */
-       init_task.mm->mmap->vm_page_prot = PAGE_SHARED;
-       init_task.mm->mmap->vm_start = PAGE_OFFSET;
-       init_task.mm->mmap->vm_end = *memory_end_p;
-       init_task.mm->context = (unsigned long) NO_CONTEXT;
+       init_mm.mmap->vm_page_prot = PAGE_SHARED;
+       init_mm.mmap->vm_start = PAGE_OFFSET;
+       init_mm.mmap->vm_end = *memory_end_p;
+       init_mm.context = (unsigned long) NO_CONTEXT;
        init_task.tss.kregs = &fake_swapper_regs;
 
 #ifdef CONFIG_IP_PNP
index 04aa8284e6638b8bbd580c3b3c75f2b385e19474..7eae02a125ddcd7c1dc201c1b8ca5f89c023200b 100644 (file)
@@ -154,7 +154,7 @@ asmlinkage void do_sparc64_fault(struct pt_regs *regs, unsigned long address, in
         * If we're in an interrupt or have no user
         * context, we must not take the fault..
         */
-       if (in_interrupt() || mm == &init_mm)
+       if (in_interrupt() || !mm)
                goto do_kernel_fault;
 
        down(&mm->mmap_sem);
index e516fe27dc06f34159d9c7f67f56f658fc82c57e..f9f067ad9c3a412317149575b8500e52f5638461 100644 (file)
@@ -7,7 +7,7 @@
 #
 # Note 2! The CFLAGS definitions are now in the main makefile.
 
-SUB_DIRS     := block char net misc sound
+SUB_DIRS     := block char net parport sound
 MOD_SUB_DIRS := $(SUB_DIRS)
 ALL_SUB_DIRS := $(SUB_DIRS) pci sgi scsi sbus cdrom isdn pnp i2o \
                                macintosh video dio zorro fc4 usb \
index 4a24bf1e3a86b9a08e4de5af272179f872cc9dd0..27fa2fe205522fb8517fb3fe408368351da568df 100644 (file)
@@ -11,7 +11,7 @@
  * as published by the Free Software Foundation; either version
  * 2 of the License, or (at your option) any later version.
  *
- * A /dev/parportxy device node represents an arbitrary device ('y')
+ * A /dev/parportx device node represents an arbitrary device
  * on port 'x'.  The following operations are possible:
  *
  * open                do nothing, set up default IEEE 1284 protocol to be COMPAT
diff --git a/drivers/misc/BUGS-parport b/drivers/misc/BUGS-parport
deleted file mode 100644 (file)
index 2329add..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-Currently known (or at least suspected) bugs in parport:
-
-o lp doesn't allow you to read status while printing is in progress.
-
-See <URL:http://www.cyberelk.demon.co.uk/parport.html>.
diff --git a/drivers/misc/Config.in b/drivers/misc/Config.in
deleted file mode 100644 (file)
index e2d96d0..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-#
-# For a description of the syntax of this configuration file,
-# see the Configure script.
-#
-# Parport configuration.
-#
-
-tristate 'Parallel port support' CONFIG_PARPORT
-if [ "$CONFIG_PARPORT" != "n" ]; then
-  dep_tristate '   PC-style hardware' CONFIG_PARPORT_PC $CONFIG_PARPORT
-  if [ "$CONFIG_PARPORT_PC" != "n" ]; then
-    bool '   Use FIFO/DMA if available' CONFIG_PARPORT_PC_FIFO
-  fi
-  if [ "$CONFIG_ARM" = "y" ]; then
-    dep_tristate '   Archimedes hardware' CONFIG_PARPORT_ARC $CONFIG_PARPORT
-  fi
-  if [ "$CONFIG_AMIGA" = "y" ]; 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
-  else
-    define_bool CONFIG_PARPORT_AMIGA n
-    define_bool CONFIG_PARPORT_MFC3 n
-  fi
-  if [ "$CONFIG_ATARI" = "y" ]; then
-    dep_tristate '   Atari hardware' CONFIG_PARPORT_ATARI $CONFIG_PARPORT
-  else
-    define_bool CONFIG_PARPORT_ATARI n
-  fi
-
-  # If exactly one hardware type is selected then parport will optimise away
-  # support for loading any others.  Defeat this if the user is keen.
-  bool '   Support foreign hardware' CONFIG_PARPORT_OTHER
-
-  bool '   IEEE 1284 transfer modes' CONFIG_PARPORT_1284
-fi
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
deleted file mode 100644 (file)
index 505a9d1..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-#
-# Makefile for the kernel miscellaneous drivers.
-#
-# 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 inherited from the
-# parent makes..
-#
-# Note 3! Parport is the Borg.  We have assimilated some other
-# drivers in the `char', `net' and `scsi' directories, but left them
-# there to allay suspicion.
-
-SUB_DIRS     := 
-MOD_SUB_DIRS := $(SUB_DIRS)
-ALL_SUB_DIRS := $(SUB_DIRS)
-
-L_TARGET := misc.a
-MX_OBJS  :=
-LX_OBJS  := 
-MI_OBJS  :=
-MIX_OBJS :=
-
-ifeq ($(CONFIG_PARPORT),y)
-  L_OBJS += parport_share.o parport_ieee1284.o parport_ieee1284_ops.o \
-            parport_procfs.o
-
-  ifeq ($(CONFIG_PARPORT_1284),y)
-    L_OBJS += parport_daisy.o parport_probe.o
-  endif
-
-  ifeq ($(CONFIG_PARPORT_PC),y)
-    LX_OBJS += parport_pc.o
-  else
-    ifeq ($(CONFIG_PARPORT_PC),m)
-      M_OBJS += parport_pc.o
-    endif
-  endif
-  ifeq ($(CONFIG_PARPORT_AX),y)
-    LX_OBJS += parport_ax.o
-  else
-    ifeq ($(CONFIG_PARPORT_AX),m)
-      M_OBJS += parport_ax.o
-    endif
-  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
-  LX_OBJS += parport_init.o
-else
-  ifeq ($(CONFIG_PARPORT),m)
-    MI_OBJS += parport_share.o parport_ieee1284.o parport_ieee1284_ops.o
-    ifeq ($(CONFIG_PARPORT_1284),y)
-      MI_OBJS += parport_daisy.o parport_probe.o
-    endif
-    ifneq ($(CONFIG_PROC_FS),n) 
-      MI_OBJS += parport_procfs.o
-    endif
-    MIX_OBJS += parport_init.o
-    M_OBJS += parport.o
-  endif
-  ifeq ($(CONFIG_PARPORT_PC),m)
-    M_OBJS += parport_pc.o
-  endif
-  ifeq ($(CONFIG_PARPORT_AX),m)
-    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
-  endif
-endif
-
-include $(TOPDIR)/Rules.make
-
-# Special rule to build the composite parport.o module
-parport.o: $(MI_OBJS) $(MIX_OBJS)
-       $(LD) $(LD_RFLAG) -r -o $@ $(MI_OBJS) $(MIX_OBJS)
diff --git a/drivers/misc/TODO-parport b/drivers/misc/TODO-parport
deleted file mode 100644 (file)
index bf91351..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-Things to be done.
-
-0. Fix the bugs (see BUGS-parport).
-
-1. Proper documentation.
-
-2. A better lp.c:
-
-   a) ECP support would be nice.  This can only work if both the port and
-      the printer support it.
-
-   b) Handle status readback automatically.  IEEE1284 printers can post status
-      bits when they have something to say.  We should read out and deal 
-      with (maybe just log) whatever the printer wants to tell the world.
-
-3. Support more hardware (eg m68k, Sun bpp).
-
-4. A better PLIP (make use of bidirectional/ECP/EPP ports).
-
-See <URL:http://www.cyberelk.demon.co.uk/parport.html>.
diff --git a/drivers/misc/multiface.h b/drivers/misc/multiface.h
deleted file mode 100644 (file)
index 56769dd..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#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 (dorchain@mpi-sb.mpg.de)
- *
- */
-
-#define PIA_REG_PADWIDTH 255
-
-#define DUARTBASE 0x0000
-#define PITBASE   0x0100
-#define ROMBASE   0x0200
-#define PIABASE   0x4000
-
-#endif
-
diff --git a/drivers/misc/parport_amiga.c b/drivers/misc/parport_amiga.c
deleted file mode 100644 (file)
index eebd44c..0000000
+++ /dev/null
@@ -1,312 +0,0 @@
-/* Low-level parallel port routines for the Amiga buildin port
- *
- * Author: Joerg Dorchain <dorchain@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)
-{
-       /* 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_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,
-
-
-       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);
-               if (request_irq(IRQ_AMIGA_CIAA_FLG, amiga_interrupt, 0,
-                               p->name, p)) {
-                       parport_unregister_port (p);
-                       return 0;
-               }
-
-               if (parport_probe_hook)
-                       (*parport_probe_hook)(p);
-
-               parport_announce_port (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 (p->irq != PARPORT_IRQ_NONE)
-               free_irq(IRQ_AMIGA_CIAA_FLG, p);
-       parport_proc_unregister(this_port);
-       parport_unregister_port(this_port);
-}
-#endif
-
-
diff --git a/drivers/misc/parport_arc.c b/drivers/misc/parport_arc.c
deleted file mode 100644 (file)
index 8cba7a6..0000000
+++ /dev/null
@@ -1,160 +0,0 @@
-/* Low-level parallel port routines for Archimedes onboard hardware
- *
- * Author: Phil Blundell <Philip.Blundell@pobox.com>
- */
-
-/* This driver is for the parallel port hardware found on Acorn's old
- * range of Archimedes machines.  The A5000 and newer systems have PC-style
- * I/O hardware and should use the parport_pc driver instead.
- *
- * The Acorn printer port hardware is very simple.  There is a single 8-bit
- * write-only latch for the data port and control/status bits are handled
- * with various auxilliary input and output lines.  The port is not
- * bidirectional, does not support any modes other than SPP, and has only
- * a subset of the standard printer control lines connected.
- */
-
-#include <linux/threads.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/kernel.h>
-#include <linux/malloc.h>
-#include <linux/parport.h>
-
-#include <asm/ptrace.h>
-#include <asm/io.h>
-#include <asm/arch/oldlatches.h>
-#include <asm/arch/irqs.h>
-
-#define DATA_ADDRESS    0x3350010
-
-/* This is equivalent to the above and only used for request_region. */
-#define PORT_BASE       0x80000000 | ((DATA_ADDRESS - IO_BASE) >> 2)
-
-/* The hardware can't read from the data latch, so we must use a soft
-   copy. */
-static unsigned char data_copy;
-
-/* These are pretty simple. We know the irq is never shared and the
-   kernel does all the magic that's required. */
-static void arc_enable_irq(struct parport *p)
-{
-       enable_irq(p->irq);
-}
-
-static void arc_disable_irq(struct parport *p)
-{
-       disable_irq(p->irq);
-}
-
-static void arc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-       parport_generic_irq(irq, (struct parport *) dev_id, regs);
-}
-
-static void arc_write_data(struct parport *p, unsigned char data)
-{
-       data_copy = data;
-       outb_t(data, DATA_LATCH);
-}
-
-static unsigned char arc_read_data(struct parport *p)
-{
-       return data_copy;
-}
-
-static void arc_inc_use_count(void)
-{
-#ifdef MODULE
-       MOD_INC_USE_COUNT;
-#endif
-}
-
-static void arc_dec_use_count(void)
-{
-#ifdef MODULE
-       MOD_DEC_USE_COUNT;
-#endif
-}
-
-static void arc_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_arc_ops = 
-{
-       arc_write_data,
-       arc_read_data,
-
-       arc_write_control,
-       arc_read_control,
-       arc_frob_control,
-
-       arc_read_status,
-
-       arc_enable_irq,
-       arc_disable_irq,
-
-       arc_data_forward,
-       arc_data_reverse,
-
-       arc_interrupt,
-
-       arc_init_state,
-       arc_save_state,
-       arc_restore_state,
-
-       arc_inc_use_count,
-       arc_dec_use_count,
-       arc_fill_inode,
-
-       parport_ieee1284_epp_write_data,
-       parport_ieee1284_epp_read_data,
-       parport_ieee1284_epp_write_addr,
-       parport_ieee1284_epp_read_addr,
-
-       parport_ieee1284_ecp_write_data,
-       parport_ieee1284_ecp_read_data,
-       parport_ieee1284_ecp_write_addr,
-       
-       parport_ieee1284_write_compat,
-       parport_ieee1284_read_nibble,
-       parport_ieee1284_read_byte,
-};
-
-/* --- Initialisation code -------------------------------- */
-
-int parport_arc_init(void)
-{
-       /* Archimedes hardware provides only one port, at a fixed address */
-       struct parport *p;
-
-       if (check_region(PORT_BASE, 1))
-               return 0;
-
-       p = parport_register_port (PORT_BASE, IRQ_PRINTERACK,
-                                  PARPORT_DMA_NONE, &parport_arc_ops);
-
-       if (!p)
-               return 0;
-
-       p->modes = PARPORT_MODE_ARCSPP;
-       p->size = 1;
-
-       printk(KERN_INFO "%s: Archimedes on-board port, using irq %d\n",
-              p->irq);
-       parport_proc_register(p);
-
-       /* Tell the high-level drivers about the port. */
-       parport_announce_port (p);
-
-       return 1;
-}
diff --git a/drivers/misc/parport_atari.c b/drivers/misc/parport_atari.c
deleted file mode 100644 (file)
index 1222130..0000000
+++ /dev/null
@@ -1,251 +0,0 @@
-/* Low-level parallel port routines for the Atari builtin port
- *
- * Author: Andreas Schwab <schwab@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_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 */
-
-       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;
-               if (request_irq(IRQ_MFP_BUSY, parport_atari_interrupt,
-                               IRQ_TYPE_SLOW, p->name, p)) {
-                       parport_unregister_port (p);
-                       return 0;
-               }
-
-               this_port = p;
-               printk(KERN_INFO "%s: Atari built-in port using irq\n", p->name);
-               parport_proc_register(p);
-
-               parport_announce_port (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 (p->irq != PARPORT_IRQ_NONE)
-               free_irq(IRQ_MFP_BUSY, p);
-       parport_proc_unregister(this_port);
-       parport_unregister_port(this_port);
-}
-#endif
diff --git a/drivers/misc/parport_ax.c b/drivers/misc/parport_ax.c
deleted file mode 100644 (file)
index dfa057f..0000000
+++ /dev/null
@@ -1,600 +0,0 @@
-/* $Id: parport_ax.c,v 1.20 1999/07/03 08:56:21 davem Exp $
- * Parallel-port routines for Sun Ultra/AX architecture
- * 
- * Author: Eddie C. Dost <ecd@skynet.be>
- *
- * based on work by:
- *          Phil Blundell <Philip.Blundell@pobox.com>
- *          Tim Waugh <tim@cyberelk.demon.co.uk>
- *         Jose Renau <renau@acm.org>
- *          David Campbell <campbell@tirian.che.curtin.edu.au>
- *          Grant Guenther <grant@torque.net>
- */
-
-#include <linux/string.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/kernel.h>
-#include <linux/malloc.h>
-#include <linux/init.h>
-
-#include <linux/parport.h>
-
-#include <asm/ptrace.h>
-#include <linux/interrupt.h>
-
-#include <asm/io.h>
-#include <asm/ebus.h>
-#include <asm/ns87303.h>
-#include <asm/irq.h>
-
-
-/*
- * Define this if you have Devices which don't support short
- * host read/write cycles.
- */
-#undef HAVE_SLOW_DEVICES
-
-
-#define DATA           0x00
-#define STATUS         0x01
-#define CONTROL                0x02
-#define EPPADDR                0x03
-#define EPPDATA                0x04
-
-#define CFIFO          0x400
-#define DFIFO          0x400
-#define TFIFO          0x400
-#define CONFIGA                0x400
-#define CONFIGB                0x401
-#define ECONTROL       0x402
-
-static void parport_ax_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-       parport_generic_irq(irq, (struct parport *) dev_id, regs);
-}
-
-void
-parport_ax_write_epp(struct parport *p, unsigned char d)
-{
-       outb(d, p->base + EPPDATA);
-}
-
-unsigned char
-parport_ax_read_epp(struct parport *p)
-{
-       return inb(p->base + EPPDATA);
-}
-
-void
-parport_ax_write_epp_addr(struct parport *p, unsigned char d)
-{
-       outb(d, p->base + EPPADDR);
-}
-
-unsigned char
-parport_ax_read_epp_addr(struct parport *p)
-{
-       return inb(p->base + EPPADDR);
-}
-
-int parport_ax_epp_clear_timeout(struct parport *pb);
-
-int 
-parport_ax_check_epp_timeout(struct parport *p)
-{
-       if (!(inb(p->base+STATUS) & 1))
-               return 0;
-       parport_ax_epp_clear_timeout(p);
-       return 1;
-}
-
-unsigned char
-parport_ax_read_configb(struct parport *p)
-{
-       return inb(p->base + CONFIGB);
-}
-
-void
-parport_ax_write_data(struct parport *p, unsigned char d)
-{
-       outb(d, p->base + DATA);
-}
-
-unsigned char
-parport_ax_read_data(struct parport *p)
-{
-       return inb(p->base + DATA);
-}
-
-void
-parport_ax_write_control(struct parport *p, unsigned char d)
-{
-       outb(d, p->base + CONTROL);
-}
-
-unsigned char
-parport_ax_read_control(struct parport *p)
-{
-       return inb(p->base + CONTROL);
-}
-
-unsigned char
-parport_ax_frob_control(struct parport *p, unsigned char mask,  unsigned char val)
-{
-       unsigned char old = inb(p->base + CONTROL);
-       outb(((old & ~mask) ^ val), p->base + CONTROL);
-       return old;
-}
-
-void
-parport_ax_write_status(struct parport *p, unsigned char d)
-{
-       outb(d, p->base + STATUS);
-}
-
-unsigned char
-parport_ax_read_status(struct parport *p)
-{
-       return inb(p->base + STATUS);
-}
-
-void
-parport_ax_write_econtrol(struct parport *p, unsigned char d)
-{
-       outb(d, p->base + ECONTROL);
-}
-
-unsigned char
-parport_ax_read_econtrol(struct parport *p)
-{
-       return inb(p->base + ECONTROL);
-}
-
-unsigned char
-parport_ax_frob_econtrol(struct parport *p, unsigned char mask, unsigned char val)
-{
-       unsigned char old = inb(p->base + ECONTROL);
-       outb(((old & ~mask) ^ val), p->base + ECONTROL);
-       return old;
-}
-
-void
-parport_ax_change_mode(struct parport *p, int m)
-{
-       /* FIXME */
-       parport_ax_frob_econtrol(p, 0xe0, m << 5);
-}
-
-void
-parport_ax_write_fifo(struct parport *p, unsigned char v)
-{
-       outb(v, p->base + DFIFO);
-}
-
-unsigned char
-parport_ax_read_fifo(struct parport *p)
-{
-       return inb(p->base + DFIFO);
-}
-
-void
-parport_ax_disable_irq(struct parport *p)
-{
-       struct linux_ebus_dma *dma = p->private_data;
-       unsigned int dcsr;
-
-       dcsr = readl((unsigned long)&dma->dcsr);
-       dcsr &= ~(EBUS_DCSR_INT_EN);
-       writel(dcsr, (unsigned long)&dma->dcsr);
-}
-
-void
-parport_ax_enable_irq(struct parport *p)
-{
-       struct linux_ebus_dma *dma = p->private_data;
-       unsigned int dcsr;
-
-       dcsr = readl((unsigned long)&dma->dcsr);
-       dcsr |= EBUS_DCSR_INT_EN;
-       writel(dcsr, (unsigned long)&dma->dcsr);
-}
-
-void
-parport_ax_init_state(struct pardevice *dev, struct parport_state *s)
-{
-       struct linux_ebus_dma *dma = dev->port->private_data;
-
-       s->u.ax.ctr = 0xc | (dev->irq_func ? 0x10 : 0x0);
-       s->u.ax.ecr = 0x0;
-
-       if (dev->irq_func)
-               s->u.ax.dcsr = (readl((unsigned long)&dma->dcsr)
-                               | EBUS_DCSR_INT_EN);
-       else
-               s->u.ax.dcsr = (readl((unsigned long)&dma->dcsr)
-                               & ~EBUS_DCSR_INT_EN);
-}
-
-void
-parport_ax_save_state(struct parport *p, struct parport_state *s)
-{
-       struct linux_ebus_dma *dma = p->private_data;
-
-       s->u.ax.ctr = parport_ax_read_control(p);
-       s->u.ax.ecr = parport_ax_read_econtrol(p);
-       s->u.ax.dcsr = readl((unsigned long)&dma->dcsr);
-}
-
-void
-parport_ax_restore_state(struct parport *p, struct parport_state *s)
-{
-       struct linux_ebus_dma *dma = p->private_data;
-
-       parport_ax_write_control(p, s->u.ax.ctr);
-       parport_ax_write_econtrol(p, s->u.ax.ecr);
-       writel(s->u.ax.dcsr, (unsigned long)&dma->dcsr);
-}
-
-void
-parport_ax_inc_use_count(void)
-{
-#ifdef MODULE
-       MOD_INC_USE_COUNT;
-#endif
-}
-
-void
-parport_ax_dec_use_count(void)
-{
-#ifdef MODULE
-       MOD_DEC_USE_COUNT;
-#endif
-}
-
-static void parport_ax_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_ax_ops = 
-{
-       parport_ax_write_data,
-       parport_ax_read_data,
-
-       parport_ax_write_control,
-       parport_ax_read_control,
-       parport_ax_frob_control,
-
-       parport_ax_read_status,
-
-       parport_ax_enable_irq,
-       parport_ax_disable_irq,
-
-       parport_ax_data_forward,
-       parport_ax_data_reverse,
-
-       parport_ax_interrupt,
-
-       parport_ax_init_state,
-       parport_ax_save_state,
-       parport_ax_restore_state,
-
-       parport_ax_inc_use_count,
-       parport_ax_dec_use_count,
-       parport_ax_fill_inode,
-
-       parport_ieee1284_epp_write_data,
-       parport_ieee1284_epp_read_data,
-       parport_ieee1284_epp_write_addr,
-       parport_ieee1284_epp_read_addr,
-
-       parport_ieee1284_ecp_write_data,
-       parport_ieee1284_ecp_read_data,
-       parport_ieee1284_ecp_write_addr,
-
-       parport_ieee1284_write_compat,
-       parport_ieee1284_read_nibble,
-       parport_ieee1284_read_byte,
-};
-
-
-/******************************************************
- *  MODE detection section:
- */
-
-/*
- * Clear TIMEOUT BIT in EPP MODE
- */
-int parport_ax_epp_clear_timeout(struct parport *pb)
-{
-       unsigned char r;
-
-       if (!(parport_ax_read_status(pb) & 0x01))
-               return 1;
-
-       /* To clear timeout some chips require double read */
-       parport_ax_read_status(pb);
-       r = parport_ax_read_status(pb);
-       parport_ax_write_status(pb, r | 0x01); /* Some reset by writing 1 */
-       parport_ax_write_status(pb, r & 0xfe); /* Others by writing 0 */
-       r = parport_ax_read_status(pb);
-
-       return !(r & 0x01);
-}
-
-/* Check for ECP
- *
- * Old style XT ports alias io ports every 0x400, hence accessing ECONTROL
- * on these cards actually accesses the CTR.
- *
- * Modern cards don't do this but reading from ECONTROL will return 0xff
- * regardless of what is written here if the card does NOT support
- * ECP.
- *
- * We will write 0x2c to ECONTROL and 0xcc to CTR since both of these
- * values are "safe" on the CTR since bits 6-7 of CTR are unused.
- */
-static int parport_ECR_present(struct parport *pb)
-{
-       unsigned int r;
-       unsigned char octr = pb->ops->read_control(pb), 
-         oecr = pb->ops->read_econtrol(pb);
-
-       r = pb->ops->read_control(pb);  
-       if ((pb->ops->read_econtrol(pb) & 0x3) == (r & 0x3)) {
-               pb->ops->write_control(pb, r ^ 0x2 ); /* Toggle bit 1 */
-
-               r = pb->ops->read_control(pb);  
-               if ((pb->ops->read_econtrol(pb) & 0x2) == (r & 0x2)) {
-                       pb->ops->write_control(pb, octr);
-                       return 0; /* Sure that no ECONTROL register exists */
-               }
-       }
-       
-       if ((pb->ops->read_econtrol(pb) & 0x3 ) != 0x1)
-               return 0;
-
-       pb->ops->write_econtrol(pb, 0x34);
-       if (pb->ops->read_econtrol(pb) != 0x35)
-               return 0;
-
-       pb->ops->write_econtrol(pb, oecr);
-       pb->ops->write_control(pb, octr);
-       
-       return PARPORT_MODE_PCECR;
-}
-
-static int parport_ECP_supported(struct parport *pb)
-{
-       int i;
-       unsigned char oecr = pb->ops->read_econtrol(pb);
-       
-       /* If there is no ECONTROL, we have no hope of supporting ECP. */
-       if (!(pb->modes & PARPORT_MODE_PCECR))
-               return 0;
-
-       /*
-        * Using LGS chipset it uses ECONTROL register, but
-        * it doesn't support ECP or FIFO MODE
-        */
-       
-       pb->ops->write_econtrol(pb, 0xc0); /* TEST FIFO */
-       for (i=0; i < 1024 && (pb->ops->read_econtrol(pb) & 0x01); i++)
-               pb->ops->write_fifo(pb, 0xaa);
-
-       pb->ops->write_econtrol(pb, oecr);
-       return (i == 1024) ? 0 : PARPORT_MODE_PCECP;
-}
-
-/* Detect PS/2 support.
- *
- * Bit 5 (0x20) sets the PS/2 data direction; setting this high
- * allows us to read data from the data lines.  In theory we would get back
- * 0xff but any peripheral attached to the port may drag some or all of the
- * lines down to zero.  So if we get back anything that isn't the contents
- * of the data register we deem PS/2 support to be present. 
- *
- * Some SPP ports have "half PS/2" ability - you can't turn off the line
- * drivers, but an external peripheral with sufficiently beefy drivers of
- * its own can overpower them and assert its own levels onto the bus, from
- * where they can then be read back as normal.  Ports with this property
- * and the right type of device attached are likely to fail the SPP test,
- * (as they will appear to have stuck bits) and so the fact that they might
- * be misdetected here is rather academic. 
- */
-
-static int parport_PS2_supported(struct parport *pb)
-{
-       int ok = 0;
-       unsigned char octr = pb->ops->read_control(pb);
-  
-       pb->ops->write_control(pb, octr | 0x20);  /* try to tri-state buffer */
-       
-       pb->ops->write_data(pb, 0x55);
-       if (pb->ops->read_data(pb) != 0x55) ok++;
-
-       pb->ops->write_data(pb, 0xaa);
-       if (pb->ops->read_data(pb) != 0xaa) ok++;
-       
-       pb->ops->write_control(pb, octr);          /* cancel input mode */
-
-       return ok ? PARPORT_MODE_PCPS2 : 0;
-}
-
-static int parport_ECPPS2_supported(struct parport *pb)
-{
-       int mode;
-       unsigned char oecr = pb->ops->read_econtrol(pb);
-
-       if (!(pb->modes & PARPORT_MODE_PCECR))
-               return 0;
-       
-       pb->ops->write_econtrol(pb, 0x20);
-       
-       mode = parport_PS2_supported(pb);
-
-       pb->ops->write_econtrol(pb, oecr);
-       return mode ? PARPORT_MODE_PCECPPS2 : 0;
-}
-
-#define printmode(x)                                   \
-{                                                      \
-       if (p->modes & PARPORT_MODE_PC##x) {            \
-               printk("%s%s", f ? "," : "", #x);       \
-               f++;                                    \
-       }                                               \
-}
-
-int
-init_one_port(struct linux_ebus_device *dev)
-{
-       struct parport tmpport, *p;
-       unsigned long base;
-       unsigned long config;
-       unsigned char tmp;
-       int irq, dma;
-
-       /* Pointer to NS87303 Configuration Registers */
-       config = dev->base_address[1];
-
-       /* Setup temporary access to Device operations */
-       tmpport.base = dev->base_address[0];
-       tmpport.ops = &parport_ax_ops;
-
-       /* Enable ECP mode, set bit 2 of the CTR first */
-       tmpport.ops->write_control(&tmpport, 0x04);
-       tmp = ns87303_readb(config, PCR);
-       tmp |= (PCR_EPP_IEEE | PCR_ECP_ENABLE | PCR_ECP_CLK_ENA);
-       ns87303_writeb(config, PCR, tmp);
-
-       /* LPT CTR bit 5 controls direction of parallel port */
-       tmp = ns87303_readb(config, PTR);
-       tmp |= PTR_LPT_REG_DIR;
-       ns87303_writeb(config, PTR, tmp);
-
-       /* Configure IRQ to Push Pull, Level Low */
-       tmp = ns87303_readb(config, PCR);
-       tmp &= ~(PCR_IRQ_ODRAIN);
-       tmp |= PCR_IRQ_POLAR;
-       ns87303_writeb(config, PCR, tmp);
-
-#ifndef HAVE_SLOW_DEVICES
-       /* Enable Zero Wait State for ECP */
-       tmp = ns87303_readb(config, FCR);
-       tmp |= FCR_ZWS_ENA;
-       ns87303_writeb(config, FCR, tmp);
-#endif
-
-       /*
-        * Now continue initializing the port
-        */
-       base = dev->base_address[0];
-       irq = dev->irqs[0];
-       dma = PARPORT_DMA_AUTO;
-
-       if (!(p = parport_register_port(base, irq, dma, &parport_ax_ops)))
-               return 0;
-
-       /* Save away pointer to our EBus DMA */
-       p->private_data = (void *)dev->base_address[2];
-
-       p->modes = PARPORT_MODE_PCSPP | parport_PS2_supported(p);
-       if (!check_region(p->base + 0x400, 3)) {
-               p->modes |= parport_ECR_present(p);
-               p->modes |= parport_ECP_supported(p);
-               p->modes |= parport_ECPPS2_supported(p);
-       }
-       p->size = 3;
-
-       if (p->dma == PARPORT_DMA_AUTO)
-               p->dma = (p->modes & PARPORT_MODE_PCECP) ? 0 : PARPORT_DMA_NONE;
-
-       printk(KERN_INFO "%s: PC-style at 0x%lx", p->name, p->base);
-       if (p->irq != PARPORT_IRQ_NONE)
-               printk(", irq %s", __irq_itoa(p->irq));
-       if (p->dma != PARPORT_DMA_NONE)
-               printk(", dma %d", p->dma);
-       printk(" [");
-       {
-               int f = 0;
-               printmode(SPP);
-               printmode(PS2);
-               printmode(ECP);
-               printmode(ECPPS2);
-       }
-       printk("]\n");
-       parport_proc_register(p);
-
-       if (p->irq != PARPORT_IRQ_NONE)
-               if ((err = request_irq(p->irq, parport_ax_interrupt,
-                                      0, p->name, p)) != 0)
-                       return 0;               /* @@@ FIXME */
-
-       request_region(p->base, p->size, p->name);
-       if (p->modes & PARPORT_MODE_PCECR)
-               request_region(p->base+0x400, 3, p->name);
-       request_region((unsigned long)p->private_data,
-                      sizeof(struct linux_ebus_dma), p->name);
-
-       p->ops->write_control(p, 0x0c);
-       p->ops->write_data(p, 0);
-
-       /* Tell the high-level drivers about the port. */
-       parport_announce_port (p);
-
-       return 1;
-}
-
-EXPORT_NO_SYMBOLS;
-
-#ifdef MODULE
-int init_module(void)
-#else
-__initfunc(int parport_ax_init(void))
-#endif
-{
-       struct linux_ebus *ebus;
-       struct linux_ebus_device *edev;
-       int count = 0;
-
-       for_each_ebus(ebus) {
-               for_each_ebusdev(edev, ebus) {
-                       if (!strcmp(edev->prom_name, "ecpp"))
-                               count += init_one_port(edev);
-               }
-       }
-       return count ? 0 : -ENODEV;
-}
-
-#ifdef MODULE
-void
-cleanup_module(void)
-{
-       struct parport *p = parport_enumerate(), *tmp;
-       while (p) {
-               tmp = p->next;
-               if (p->modes & PARPORT_MODE_PCSPP) { 
-                       if (p->irq != PARPORT_IRQ_NONE) {
-                               parport_ax_disable_irq(p);
-                               free_irq(p->irq, p);
-                       }
-                       release_region(p->base, p->size);
-                       if (p->modes & PARPORT_MODE_PCECR)
-                               release_region(p->base+0x400, 3);
-                       release_region((unsigned long)p->private_data,
-                                      sizeof(struct linux_ebus_dma));
-                       parport_proc_unregister(p);
-                       parport_unregister_port(p);
-               }
-               p = tmp;
-       }
-}
-#endif
diff --git a/drivers/misc/parport_daisy.c b/drivers/misc/parport_daisy.c
deleted file mode 100644 (file)
index 830d9d4..0000000
+++ /dev/null
@@ -1,473 +0,0 @@
-/*
- * IEEE 1284.3 Parallel port daisy chain and multiplexor code
- * 
- * Copyright (C) 1999  Tim Waugh <tim@cyberelk.demon.co.uk>
- *
- * 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.
- *
- * ??-12-1998: Initial implementation.
- * 31-01-1999: Make port-cloning transparent.
- * 13-02-1999: Move DeviceID technique from parport_probe.
- * 13-03-1999: Get DeviceID from non-IEEE 1284.3 devices too.
- *
- */
-
-#include <linux/parport.h>
-#include <linux/delay.h>
-#include <asm/uaccess.h>
-
-#define DEBUG /* undef me for production */
-
-#ifdef DEBUG
-#define DPRINTK(stuff...) printk (stuff)
-#else
-#define DPRINTK(stuff...)
-#endif
-
-static struct daisydev {
-       struct daisydev *next;
-       struct parport *port;
-       int daisy;
-       int devnum;
-} *topology = NULL;
-
-static int numdevs = 0;
-
-/* Forward-declaration of lower-level functions. */
-static int mux_present (struct parport *port);
-static int num_mux_ports (struct parport *port);
-static int select_port (struct parport *port);
-static int assign_addrs (struct parport *port);
-
-/* Add a device to the discovered topology. */
-static void add_dev (int devnum, struct parport *port, int daisy)
-{
-       struct daisydev *newdev;
-       newdev = kmalloc (GFP_KERNEL, sizeof (struct daisydev));
-       if (newdev) {
-               newdev->port = port;
-               newdev->daisy = daisy;
-               newdev->devnum = devnum;
-               newdev->next = topology;
-               if (!topology || topology->devnum >= devnum)
-                       topology = newdev;
-               else {
-                       struct daisydev *prev = topology;
-                       while (prev->next && prev->next->devnum < devnum)
-                               prev = prev->next;
-                       newdev->next = prev->next;
-                       prev->next = newdev;
-               }
-       }
-}
-
-/* Clone a parport (actually, make an alias). */
-static struct parport *clone_parport (struct parport *real, int muxport)
-{
-       struct parport *extra = parport_register_port (real->base,
-                                                      real->irq,
-                                                      real->dma,
-                                                      real->ops);
-       if (extra) {
-               extra->portnum = real->portnum;
-               extra->physport = real;
-               extra->muxport = muxport;
-       }
-
-       return extra;
-}
-
-/* Discover the IEEE1284.3 topology on a port -- muxes and daisy chains. */
-int parport_daisy_init (struct parport *port)
-{
-       char *deviceid;
-       static const char *th[] = { /*0*/"th", "st", "nd", "rd", "th" };
-       int num_ports;
-       int i;
-
-       /* Because this is called before any other devices exist,
-        * we don't have to claim exclusive access.  */
-
-       /* If mux present on normal port, need to create new
-        * parports for each extra port. */
-       if (port->muxport < 0 && mux_present (port) &&
-           /* don't be fooled: a mux must have 2 or 4 ports. */
-           ((num_ports = num_mux_ports (port)) == 2 || num_ports == 4)) {
-               /* Leave original as port zero. */
-               port->muxport = 0;
-               printk (KERN_INFO
-                       "%s: 1st (default) port of %d-way multiplexor\n",
-                       port->name, num_ports);
-               for (i = 1; i < num_ports; i++) {
-                       /* Clone the port. */
-                       struct parport *extra = clone_parport (port, i);
-                       if (!extra) {
-                               if (signal_pending (current))
-                                       break;
-
-                               schedule ();
-                               continue;
-                       }
-
-                       printk (KERN_INFO
-                               "%s: %d%s port of %d-way multiplexor on %s\n",
-                               extra->name, i + 1, th[i + 1], num_ports,
-                               port->name);
-
-                       /* Analyse that port too.  We won't recurse
-                          forever because of the 'port->muxport < 0'
-                          test above. */
-                       parport_announce_port (extra);
-               }
-       }
-
-       if (port->muxport >= 0)
-               select_port (port);
-
-       parport_daisy_deselect_all (port);
-       assign_addrs (port);
-
-       /* Count the potential legacy device at the end. */
-       add_dev (numdevs++, port, -1);
-
-       /* Find out the legacy device's IEEE 1284 device ID. */
-       deviceid = kmalloc (1000, GFP_KERNEL);
-       if (deviceid) {
-               parport_device_id (numdevs - 1, deviceid, 1000);
-               kfree (deviceid);
-       }
-
-       return 0;
-}
-
-/* Forget about devices on a physical port. */
-void parport_daisy_fini (struct parport *port)
-{
-       struct daisydev *dev, *prev = topology;
-       while (prev && prev->port == port)
-               prev = topology = topology->next;
-
-       while (prev) {
-               dev = prev->next;
-               if (dev && dev->port == port)
-                       prev->next = dev->next;
-
-               prev = prev->next;
-       }
-
-       /* Gaps in the numbering could be handled better.  How should
-           someone enumerate through all IEEE1284.3 devices in the
-           topology?. */
-       if (!topology) numdevs = 0;
-       return; }
-
-/* Find a device by canonical device number. */
-struct pardevice *parport_open (int devnum, const char *name,
-                               int (*pf) (void *), void (*kf) (void *),
-                               void (*irqf) (int, void *, struct pt_regs *),
-                               int flags, void *handle)
-{
-       struct parport *port = parport_enumerate ();
-       struct pardevice *dev;
-       int portnum;
-       int muxnum;
-       int daisynum;
-
-       if (parport_device_coords (devnum,  &portnum, &muxnum, &daisynum))
-               return NULL;
-
-       while (port && ((port->portnum != portnum) ||
-                       (port->muxport != muxnum)))
-               port = port->next;
-
-       if (!port)
-               /* No corresponding parport. */
-               return NULL;
-
-       dev = parport_register_device (port, name, pf, kf,
-                                      irqf, flags, handle);
-       if (dev)
-               dev->daisy = daisynum;
-
-       /* Check that there really is a device to select. */
-       if (daisynum >= 0) {
-               int selected;
-               parport_claim_or_block (dev);
-               selected = port->daisy;
-               parport_release (dev);
-
-               if (selected != port->daisy) {
-                       /* No corresponding device. */
-                       parport_unregister_device (dev);
-                       return NULL;
-               }
-       }
-
-       return dev;
-}
-
-/* The converse of parport_open. */
-void parport_close (struct pardevice *dev)
-{
-       parport_unregister_device (dev);
-}
-
-/* Convert device coordinates into a canonical device number. */
-int parport_device_num (int parport, int mux, int daisy)
-{
-       struct daisydev *dev = topology;
-
-       while (dev && dev->port->portnum != parport &&
-              dev->port->muxport != mux && dev->daisy != daisy)
-               dev = dev->next;
-
-       if (!dev)
-               return -ENXIO;
-
-       return dev->devnum;
-}
-
-/* Convert a canonical device number into device coordinates. */
-int parport_device_coords (int devnum, int *parport, int *mux, int *daisy)
-{
-       struct daisydev *dev = topology;
-
-       while (dev && dev->devnum != devnum)
-               dev = dev->next;
-
-       if (!dev)
-               return -ENXIO;
-
-       if (parport) *parport = dev->port->portnum;
-       if (mux) *mux = dev->port->muxport;
-       if (daisy) *daisy = dev->daisy;
-       return 0;
-}
-
-/* Send a daisy-chain-style CPP command packet. */
-static int cpp_daisy (struct parport *port, int cmd)
-{
-       unsigned char s;
-
-       parport_write_data (port, 0xaa); udelay (2);
-       parport_write_data (port, 0x55); udelay (2);
-       parport_write_data (port, 0x00); udelay (2);
-       parport_write_data (port, 0xff); udelay (2);
-       s = parport_read_status (port) & (PARPORT_STATUS_BUSY
-                                         | PARPORT_STATUS_PAPEROUT
-                                         | PARPORT_STATUS_SELECT
-                                         | PARPORT_STATUS_ERROR);
-       if (s != (PARPORT_STATUS_BUSY
-                 | PARPORT_STATUS_PAPEROUT
-                 | PARPORT_STATUS_SELECT
-                 | PARPORT_STATUS_ERROR)) {
-               DPRINTK (KERN_DEBUG "%s: cpp_daisy: aa5500ff(%02x)\n",
-                        port->name, s);
-               return -ENXIO;
-       }
-
-       parport_write_data (port, 0x87); udelay (2);
-       s = parport_read_status (port) & (PARPORT_STATUS_BUSY
-                                         | PARPORT_STATUS_PAPEROUT
-                                         | PARPORT_STATUS_SELECT
-                                         | PARPORT_STATUS_ERROR);
-       if (s != (PARPORT_STATUS_SELECT | PARPORT_STATUS_ERROR)) {
-               DPRINTK (KERN_DEBUG "%s: cpp_daisy: aa5500ff87(%02x)\n",
-                        port->name, s);
-               return -ENXIO;
-       }
-
-       parport_write_data (port, 0x78); udelay (2);
-       parport_write_data (port, cmd); udelay (2);
-       parport_frob_control (port,
-                             PARPORT_CONTROL_STROBE,
-                             PARPORT_CONTROL_STROBE);
-       udelay (1);
-       parport_frob_control (port, PARPORT_CONTROL_STROBE, 0);
-       udelay (1);
-       s = parport_read_status (port);
-       parport_write_data (port, 0xff); udelay (2);
-
-       return s;
-}
-
-/* Send a mux-style CPP command packet. */
-static int cpp_mux (struct parport *port, int cmd)
-{
-       unsigned char s;
-       int rc;
-
-       parport_write_data (port, 0xaa); udelay (2);
-       parport_write_data (port, 0x55); udelay (2);
-       parport_write_data (port, 0xf0); udelay (2);
-       parport_write_data (port, 0x0f); udelay (2);
-       parport_write_data (port, 0x52); udelay (2);
-       parport_write_data (port, 0xad); udelay (2);
-       parport_write_data (port, cmd); udelay (2);
-
-       s = parport_read_status (port);
-       if (!(s & PARPORT_STATUS_ACK)) {
-               DPRINTK (KERN_DEBUG "%s: cpp_mux: aa55f00f52ad%02x(%02x)\n",
-                        port->name, cmd, s);
-               return -EIO;
-       }
-
-       rc = (((s & PARPORT_STATUS_SELECT   ? 1 : 0) << 0) |
-             ((s & PARPORT_STATUS_PAPEROUT ? 1 : 0) << 1) |
-             ((s & PARPORT_STATUS_BUSY     ? 0 : 1) << 2) |
-             ((s & PARPORT_STATUS_ERROR    ? 0 : 1) << 3));
-
-       return rc;
-}
-
-void parport_daisy_deselect_all (struct parport *port)
-{
-       cpp_daisy (port, 0x30);
-}
-
-int parport_daisy_select (struct parport *port, int daisy, int mode)
-{
-       /* mode is currently ignored. FIXME? */
-       return cpp_daisy (port, 0xe0 + daisy) & PARPORT_STATUS_ERROR;
-}
-
-static int mux_present (struct parport *port)
-{
-       return cpp_mux (port, 0x51) == 3;
-}
-
-static int num_mux_ports (struct parport *port)
-{
-       return cpp_mux (port, 0x58);
-}
-
-static int select_port (struct parport *port)
-{
-       int muxport = port->muxport;
-       return cpp_mux (port, 0x60 + muxport) == muxport;
-}
-
-static int assign_addrs (struct parport *port)
-{
-       unsigned char s, last_dev;
-       unsigned char daisy;
-       int thisdev = numdevs;
-       char *deviceid;
-
-       parport_write_data (port, 0xaa); udelay (2);
-       parport_write_data (port, 0x55); udelay (2);
-       parport_write_data (port, 0x00); udelay (2);
-       parport_write_data (port, 0xff); udelay (2);
-       s = parport_read_status (port) & (PARPORT_STATUS_BUSY
-                                         | PARPORT_STATUS_PAPEROUT
-                                         | PARPORT_STATUS_SELECT
-                                         | PARPORT_STATUS_ERROR);
-       if (s != (PARPORT_STATUS_BUSY
-                 | PARPORT_STATUS_PAPEROUT
-                 | PARPORT_STATUS_SELECT
-                 | PARPORT_STATUS_ERROR)) {
-               DPRINTK (KERN_DEBUG "%s: assign_addrs: aa5500ff(%02x)\n",
-                        port->name, s);
-               return -ENXIO;
-       }
-
-       parport_write_data (port, 0x87); udelay (2);
-       s = parport_read_status (port) & (PARPORT_STATUS_BUSY
-                                         | PARPORT_STATUS_PAPEROUT
-                                         | PARPORT_STATUS_SELECT
-                                         | PARPORT_STATUS_ERROR);
-       if (s != (PARPORT_STATUS_SELECT | PARPORT_STATUS_ERROR)) {
-               DPRINTK (KERN_DEBUG "%s: assign_addrs: aa5500ff87(%02x)\n",
-                        port->name, s);
-               return -ENXIO;
-       }
-
-       parport_write_data (port, 0x78); udelay (2);
-       last_dev = 0; /* We've just been speaking to a device, so we
-                        know there must be at least _one_ out there. */
-
-       for (daisy = 0; daisy < 4; daisy++) {
-               parport_write_data (port, daisy);
-               udelay (2);
-               parport_frob_control (port,
-                                     PARPORT_CONTROL_STROBE,
-                                     PARPORT_CONTROL_STROBE);
-               udelay (1);
-               parport_frob_control (port, PARPORT_CONTROL_STROBE, 0);
-               udelay (1);
-
-               if (last_dev)
-                       /* No more devices. */
-                       break;
-
-               last_dev = !(parport_read_status (port)
-                            & PARPORT_STATUS_BUSY);
-
-               add_dev (numdevs++, port, daisy);
-       }
-
-       parport_write_data (port, 0xff); udelay (2);
-       DPRINTK (KERN_DEBUG "%s: Found %d daisy-chained devices\n", port->name,
-               numdevs - thisdev);
-
-       /* Ask the new devices to introduce themselves. */
-       deviceid = kmalloc (1000, GFP_KERNEL);
-       if (!deviceid) return 0;
-
-       for (daisy = 0; thisdev < numdevs; thisdev++, daisy++)
-               parport_device_id (thisdev, deviceid, 1000);
-
-       kfree (deviceid);
-       return 0;
-}
-
-/* Find a device with a particular manufacturer and model string,
-   starting from a given device number.  Like the PCI equivalent,
-   'from' itself is skipped. */
-int parport_find_device (const char *mfg, const char *mdl, int from)
-{
-       struct daisydev *d = topology; /* sorted by devnum */
-
-       /* Find where to start. */
-       while (d && d->devnum <= from)
-               d = d->next;
-
-       /* Search. */
-       while (d) {
-               struct parport_device_info *info;
-               info = &d->port->probe_info[1 + d->daisy];
-               if ((!mfg || !strcmp (mfg, info->mfr)) &&
-                   (!mdl || !strcmp (mdl, info->model)))
-                       break;
-
-               d = d->next;
-       }
-
-       if (d)
-               return d->devnum;
-
-       return -1;
-}
-
-/* Find a device in a particular class.  Like the PCI equivalent,
-   'from' itself is skipped. */
-int parport_find_class (parport_device_class cls, int from)
-{
-       struct daisydev *d = topology; /* sorted by devnum */
-
-       /* Find where to start. */
-       while (d && d->devnum <= from)
-               d = d->next;
-
-       /* Search. */
-       while (d && d->port->probe_info[1 + d->daisy].class != cls)
-               d = d->next;
-
-       if (d)
-               return d->devnum;
-
-       return -1;
-}
diff --git a/drivers/misc/parport_ieee1284.c b/drivers/misc/parport_ieee1284.c
deleted file mode 100644 (file)
index de7a269..0000000
+++ /dev/null
@@ -1,545 +0,0 @@
-/* $Id: parport_ieee1284.c,v 1.4 1997/10/19 21:37:21 philip Exp $
- * IEEE-1284 implementation for parport.
- *
- * Authors: Phil Blundell <Philip.Blundell@pobox.com>
- *          Carsten Gross <carsten@sol.wohnheim.uni-ulm.de>
- *         Jose Renau <renau@acm.org>
- *          Tim Waugh <tim@cyberelk.demon.co.uk> (largely rewritten)
- *
- * This file is responsible for IEEE 1284 negotiation, and for handing
- * read/write requests to low-level drivers.
- */
-
-#include <linux/config.h>
-#include <linux/threads.h>
-#include <linux/parport.h>
-#include <linux/delay.h>
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-
-#undef DEBUG /* undef me for production */
-
-#ifdef CONFIG_LP_CONSOLE
-#undef DEBUG /* Don't want a garbled console */
-#endif
-
-#ifdef DEBUG
-#define DPRINTK(stuff...) printk (stuff)
-#else
-#define DPRINTK(stuff...)
-#endif
-
-/* Make parport_wait_peripheral wake up.
- * It will be useful to call this from an interrupt handler. */
-void parport_ieee1284_wakeup (struct parport *port)
-{
-       up (&port->physport->ieee1284.irq);
-}
-
-static struct parport *port_from_cookie[PARPORT_MAX];
-static void timeout_waiting_on_port (unsigned long cookie)
-{
-       parport_ieee1284_wakeup (port_from_cookie[cookie % PARPORT_MAX]);
-}
-
-/* Wait for a parport_ieee1284_wakeup.
- * 0:      success
- * <0:     error (exit as soon as possible)
- * >0:     timed out
- */
-int parport_wait_event (struct parport *port, signed long timeout)
-{
-       int ret;
-       struct timer_list timer;
-
-       if (!port->physport->cad->timeout)
-               /* Zero timeout is special, and we can't down() the
-                  semaphore. */
-               return 1;
-
-       init_timer (&timer);
-       timer.expires = jiffies + timeout;
-       timer.function = timeout_waiting_on_port;
-       port_from_cookie[port->number % PARPORT_MAX] = port;
-       timer.data = port->number;
-
-       add_timer (&timer);
-       ret = down_interruptible (&port->physport->ieee1284.irq);
-       if (!del_timer (&timer) && !ret)
-               /* Timed out. */
-               ret = 1;
-
-       return ret;
-}
-
-/* Wait for Status line(s) to change in 35 ms - see IEEE1284-1994 page 24 to
- * 25 for this. After this time we can create a timeout because the
- * peripheral doesn't conform to IEEE1284.  We want to save CPU time: we are
- * waiting a maximum time of 500 us busy (this is for speed).  If there is
- * not the right answer in this time, we call schedule and other processes
- * are able to eat the time up to 40ms.
- */ 
-
-int parport_wait_peripheral(struct parport *port,
-                           unsigned char mask, 
-                           unsigned char result)
-{
-       int counter;
-       long deadline;
-       unsigned char status;
-
-       counter = port->physport->spintime; /* usecs of fast polling */
-       if (!port->physport->cad->timeout)
-               /* A zero timeout is "special": busy wait for the
-                  entire 35ms. */
-               counter = 35000;
-
-       /* Fast polling.
-        *
-        * This should be adjustable.
-        * How about making a note (in the device structure) of how long
-        * it takes, so we know for next time?
-        */
-       for (counter /= 5; counter > 0; counter--) {
-               status = parport_read_status (port);
-               if ((status & mask) == result)
-                       return 0;
-               if (signal_pending (current))
-                       return -EINTR;
-               if (current->need_resched)
-                       break;
-               udelay(5);
-       }
-
-       if (!port->physport->cad->timeout)
-               /* We may be in an interrupt handler, so we can't poll
-                * slowly anyway. */
-               return 1;
-
-       /* 40ms of slow polling. */
-       deadline = jiffies + (HZ + 24) / 25;
-       while (time_before (jiffies, deadline)) {
-               int ret;
-
-               if (signal_pending (current))
-                       return -EINTR;
-
-               /* Wait for 10ms (or until an interrupt occurs if
-                * the handler is set) */
-               if ((ret = parport_wait_event (port, (HZ + 99) / 100)) < 0)
-                       return ret;
-
-               status = parport_read_status (port);
-               if ((status & mask) == result)
-                       return 0;
-
-               if (!ret) {
-                       /* parport_wait_event didn't time out, but the
-                        * peripheral wasn't actually ready either.
-                        * Wait for another 10ms. */
-                       current->state = TASK_INTERRUPTIBLE;
-                       schedule_timeout ((HZ+ 99) / 100);
-               }
-       }
-
-       return 1;
-}
-
-#ifdef CONFIG_PARPORT_1284
-/* Terminate a negotiated mode. */
-static void parport_ieee1284_terminate (struct parport *port)
-{
-       port = port->physport;
-
-       port->ieee1284.phase = IEEE1284_PH_TERMINATE;
-
-       /* EPP terminates differently. */
-       switch (port->ieee1284.mode) {
-       case IEEE1284_MODE_EPP:
-       case IEEE1284_MODE_EPPSL:
-       case IEEE1284_MODE_EPPSWE:
-               /* Terminate from EPP mode. */
-
-               /* Event 68: Set nInit low */
-               parport_frob_control (port,
-                                     PARPORT_CONTROL_INIT,
-                                     PARPORT_CONTROL_INIT);
-               udelay (50);
-
-               /* Event 69: Set nInit high, nSelectIn low */
-               parport_frob_control (port,
-                                     PARPORT_CONTROL_SELECT,
-                                     PARPORT_CONTROL_SELECT);
-               break;
-               
-       default:
-               /* Terminate from all other modes. */
-
-               /* Event 22: Set nSelectIn low, nAutoFd high */
-               parport_frob_control (port,
-                                     PARPORT_CONTROL_SELECT
-                                     | PARPORT_CONTROL_AUTOFD,
-                                     PARPORT_CONTROL_SELECT);
-
-               /* Event 24: nAck goes low */
-               parport_wait_peripheral (port, PARPORT_STATUS_ACK, 0);
-
-               /* Event 25: Set nAutoFd low */
-               parport_frob_control (port,
-                                     PARPORT_CONTROL_AUTOFD,
-                                     PARPORT_CONTROL_AUTOFD);
-
-               /* Event 27: nAck goes high */
-               parport_wait_peripheral (port,
-                                        PARPORT_STATUS_ACK, 
-                                        PARPORT_STATUS_ACK);
-
-               /* Event 29: Set nAutoFd high */
-               parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0);
-       }
-
-       port->ieee1284.mode = IEEE1284_MODE_COMPAT;
-       port->ieee1284.phase = IEEE1284_PH_FWD_IDLE;
-
-       DPRINTK (KERN_DEBUG "%s: In compatibility (forward idle) mode\n",
-                port->name);
-}              
-#endif /* IEEE1284 support */
-
-/* Negotiate an IEEE 1284 mode.
- * return values are:
- *   0 - handshake OK; IEEE1284 peripheral and mode available
- *  -1 - handshake failed; peripheral is not compliant (or none present)
- *   1 - handshake OK; IEEE1284 peripheral present but mode not available
- */
-int parport_negotiate (struct parport *port, int mode)
-{
-#ifndef CONFIG_PARPORT_1284
-       if (mode == IEEE1284_MODE_COMPAT)
-               return 0;
-       printk (KERN_ERR "parport: IEEE1284 not supported in this kernel\n");
-       return -1;
-#else
-       int m = mode & ~IEEE1284_ADDR;
-       unsigned char xflag;
-
-       port = port->physport;
-
-       /* Is there anything to do? */
-       if (port->ieee1284.mode == mode)
-               return 0;
-
-       /* Is the difference just an address-or-not bit? */
-       if ((port->ieee1284.mode & ~IEEE1284_ADDR) == (mode & ~IEEE1284_ADDR)){
-               port->ieee1284.mode = mode;
-               return 0;
-       }
-
-       /* Go to compability forward idle mode */
-       if (port->ieee1284.mode != IEEE1284_MODE_COMPAT)
-               parport_ieee1284_terminate (port);
-
-       if (mode == IEEE1284_MODE_COMPAT)
-               /* Compatibility mode: no negotiation. */
-               return 0; 
-
-       switch (mode) {
-       case IEEE1284_MODE_ECPSWE:
-               m = IEEE1284_MODE_ECP;
-               break;
-       case IEEE1284_MODE_EPPSL:
-       case IEEE1284_MODE_EPPSWE:
-               m = IEEE1284_MODE_EPP;
-               break;
-       case IEEE1284_MODE_BECP:
-               return -ENOSYS; /* FIXME (implement BECP) */
-       }
-
-       port->ieee1284.phase = IEEE1284_PH_NEGOTIATION;
-
-       /* Start off with nStrobe and nAutoFd high, and nSelectIn low */
-       parport_frob_control (port,
-                             PARPORT_CONTROL_STROBE
-                             | PARPORT_CONTROL_AUTOFD
-                             | PARPORT_CONTROL_SELECT,
-                             PARPORT_CONTROL_SELECT);
-       udelay(1);
-
-       /* Event 0: Set data */
-       parport_write_data (port, m);
-       udelay (400); /* Shouldn't need to wait this long. */
-
-       /* Event 1: Set nSelectIn high, nAutoFd low */
-       parport_frob_control (port,
-                             PARPORT_CONTROL_SELECT
-                             | PARPORT_CONTROL_AUTOFD,
-                             PARPORT_CONTROL_AUTOFD);
-
-       /* Event 2: PError, Select, nFault go high, nAck goes low */
-       if (parport_wait_peripheral (port,
-                                    PARPORT_STATUS_ERROR
-                                    | PARPORT_STATUS_SELECT
-                                    | PARPORT_STATUS_PAPEROUT
-                                    | PARPORT_STATUS_ACK,
-                                    PARPORT_STATUS_ERROR
-                                    | PARPORT_STATUS_SELECT
-                                    | PARPORT_STATUS_PAPEROUT)) {
-               /* Timeout */
-               parport_frob_control (port,
-                                     PARPORT_CONTROL_SELECT
-                                     | PARPORT_CONTROL_AUTOFD,
-                                     PARPORT_CONTROL_SELECT);
-               DPRINTK (KERN_DEBUG
-                        "%s: Peripheral not IEEE1284 compliant (0x%02X)\n",
-                        port->name, parport_read_status (port));
-               port->ieee1284.phase = IEEE1284_PH_FWD_IDLE;
-               return -1; /* Not IEEE1284 compliant */
-       }
-
-       /* Event 3: Set nStrobe low */
-       parport_frob_control (port,
-                             PARPORT_CONTROL_STROBE,
-                             PARPORT_CONTROL_STROBE);
-
-       /* Event 4: Set nStrobe and nAutoFd high */
-       udelay (5);
-       parport_frob_control (port,
-                             PARPORT_CONTROL_STROBE
-                             | PARPORT_CONTROL_AUTOFD,
-                             0);
-
-       /* Event 6: nAck goes high */
-       if (parport_wait_peripheral (port,
-                                    PARPORT_STATUS_ACK
-                                    | PARPORT_STATUS_PAPEROUT,
-                                    PARPORT_STATUS_ACK)) {
-               if (parport_read_status (port) & PARPORT_STATUS_ACK)
-                       printk (KERN_DEBUG
-                               "%s: working around buggy peripheral: tell "
-                               "Tim what make it is\n", port->name);
-               DPRINTK (KERN_DEBUG
-                        "%s: Mode 0x%02x not supported? (0x%02x)\n",
-                        port->name, mode, port->ops->read_status (port));
-               parport_ieee1284_terminate (port);
-               return 1;
-       }
-
-       xflag = parport_read_status (port) & PARPORT_STATUS_SELECT;
-
-       /* xflag should be high for all modes other than nibble (0). */
-       if (mode && !xflag) {
-               /* Mode not supported. */
-               DPRINTK (KERN_DEBUG "%s: Mode 0x%02x not supported\n",
-                        port->name, mode);
-               parport_ieee1284_terminate (port);
-               return 1;
-       }
-
-       /* Mode is supported */
-       DPRINTK (KERN_DEBUG "%s: In mode 0x%02x\n", port->name, mode);
-       port->ieee1284.mode = mode;
-
-       /* But ECP is special */
-       if (mode & IEEE1284_MODE_ECP) {
-               port->ieee1284.phase = IEEE1284_PH_ECP_SETUP;
-
-               /* Event 30: Set nAutoFd low */
-               parport_frob_control (port,
-                                     PARPORT_CONTROL_AUTOFD,
-                                     PARPORT_CONTROL_AUTOFD);
-
-               /* Event 31: PError goes high. */
-               parport_wait_peripheral (port,
-                                        PARPORT_STATUS_PAPEROUT,
-                                        PARPORT_STATUS_PAPEROUT);
-               /* (Should check that this works..) */
-
-               port->ieee1284.phase = IEEE1284_PH_FWD_IDLE;
-               DPRINTK (KERN_DEBUG "%s: ECP direction: forward\n",
-                        port->name);
-       } else switch (mode) {
-       case IEEE1284_MODE_NIBBLE:
-       case IEEE1284_MODE_BYTE:
-               port->ieee1284.phase = IEEE1284_PH_REV_IDLE;
-               break;
-       default:
-               port->ieee1284.phase = IEEE1284_PH_FWD_IDLE;
-       }
-
-
-       return 0;
-#endif /* IEEE1284 support */
-}
-
-/* Acknowledge that the peripheral has data available.
- * Events 18-20, in order to get from Reverse Idle phase
- * to Host Busy Data Available.
- * This will most likely be called from an interrupt.
- * Returns zero if data was available.
- */
-#ifdef CONFIG_PARPORT_1284
-static int parport_ieee1284_ack_data_avail (struct parport *port)
-{
-       if (parport_read_status (port) & PARPORT_STATUS_ERROR)
-               /* Event 18 didn't happen. */
-               return -1;
-
-       /* Event 20: nAutoFd goes high. */
-       port->ops->frob_control (port, PARPORT_CONTROL_AUTOFD, 0);
-       port->ieee1284.phase = IEEE1284_PH_HBUSY_DAVAIL;
-       return 0;
-}
-#endif /* IEEE1284 support */
-
-/* Handle an interrupt. */
-void parport_ieee1284_interrupt (int which, void *handle, struct pt_regs *regs)
-{
-       struct parport *port = handle;
-       parport_ieee1284_wakeup (port);
-
-#ifdef CONFIG_PARPORT_1284
-       if (port->ieee1284.phase == IEEE1284_PH_REV_IDLE) {
-               /* An interrupt in this phase means that data
-                * is now available. */
-               DPRINTK (KERN_DEBUG "%s: Data available\n", port->name);
-               parport_ieee1284_ack_data_avail (port);
-       }
-#endif /* IEEE1284 support */
-}
-
-/* Write a block of data. */
-ssize_t parport_write (struct parport *port, const void *buffer, size_t len)
-{
-#ifndef CONFIG_PARPORT_1284
-       return port->ops->compat_write_data (port, buffer, len, 0);
-#else
-       ssize_t retval;
-       int mode = port->ieee1284.mode;
-       int addr = mode & IEEE1284_ADDR;
-       size_t (*fn) (struct parport *, const void *, size_t, int);
-
-       /* Ignore the device-ID-request bit and the address bit. */
-       mode &= ~(IEEE1284_DEVICEID | IEEE1284_ADDR);
-
-       /* Use the mode we're in. */
-       switch (mode) {
-       case IEEE1284_MODE_NIBBLE:
-               parport_negotiate (port, IEEE1284_MODE_COMPAT);
-       case IEEE1284_MODE_COMPAT:
-               DPRINTK (KERN_DEBUG "%s: Using compatibility mode\n",
-                        port->name);
-               fn = port->ops->compat_write_data;
-               break;
-
-       case IEEE1284_MODE_EPP:
-               DPRINTK (KERN_DEBUG "%s: Using EPP mode\n", port->name);
-               if (addr)
-                       fn = port->ops->epp_write_addr;
-               else
-                       fn = port->ops->epp_write_data;
-               break;
-
-       case IEEE1284_MODE_ECP:
-       case IEEE1284_MODE_ECPRLE:
-               DPRINTK (KERN_DEBUG "%s: Using ECP mode\n", port->name);
-               if (addr)
-                       fn = port->ops->ecp_write_addr;
-               else
-                       fn = port->ops->ecp_write_data;
-               break;
-
-       case IEEE1284_MODE_ECPSWE:
-               DPRINTK (KERN_DEBUG "%s: Using software-emulated ECP mode\n",
-                        port->name);
-               /* The caller has specified that it must be emulated,
-                * even if we have ECP hardware! */
-               if (addr)
-                       fn = parport_ieee1284_ecp_write_addr;
-               else
-                       fn = parport_ieee1284_ecp_write_data;
-               break;
-
-       default:
-               DPRINTK (KERN_DEBUG "%s: Unknown mode 0x%02x\n", port->name,
-                       port->ieee1284.mode);
-               return -ENOSYS;
-       }
-
-       retval = (*fn) (port, buffer, len, 0);
-       DPRINTK (KERN_DEBUG "%s: wrote %d/%d bytes\n", port->name, retval,
-                len);
-       return retval;
-#endif /* IEEE1284 support */
-}
-
-/* Read a block of data. */
-ssize_t parport_read (struct parport *port, void *buffer, size_t len)
-{
-#ifndef CONFIG_PARPORT_1284
-       printk (KERN_ERR "parport: IEEE1284 not supported in this kernel\n");
-       return -ENODEV;
-#else
-       int mode = port->physport->ieee1284.mode;
-       int addr = mode & IEEE1284_ADDR;
-       size_t (*fn) (struct parport *, void *, size_t, int);
-
-       /* Ignore the device-ID-request bit and the address bit. */
-       mode &= ~(IEEE1284_DEVICEID | IEEE1284_ADDR);
-
-       /* Use the mode we're in. */
-       switch (mode) {
-       case IEEE1284_MODE_COMPAT:
-               if (parport_negotiate (port, IEEE1284_MODE_NIBBLE))
-                       return -EIO;
-       case IEEE1284_MODE_NIBBLE:
-               DPRINTK (KERN_DEBUG "%s: Using nibble mode\n", port->name);
-               fn = port->ops->nibble_read_data;
-               break;
-
-       case IEEE1284_MODE_BYTE:
-               DPRINTK (KERN_DEBUG "%s: Using byte mode\n", port->name);
-               fn = port->ops->byte_read_data;
-               break;
-
-       case IEEE1284_MODE_EPP:
-               DPRINTK (KERN_DEBUG "%s: Using EPP mode\n", port->name);
-               if (addr)
-                       fn = port->ops->epp_read_addr;
-               else
-                       fn = port->ops->epp_read_data;
-               break;
-
-       case IEEE1284_MODE_ECP:
-       case IEEE1284_MODE_ECPRLE:
-               DPRINTK (KERN_DEBUG "%s: Using ECP mode\n", port->name);
-               fn = port->ops->ecp_read_data;
-               break;
-
-       case IEEE1284_MODE_ECPSWE:
-               DPRINTK (KERN_DEBUG "%s: Using software-emulated ECP mode\n",
-                        port->name);
-               fn = parport_ieee1284_ecp_read_data;
-               break;
-
-       default:
-               DPRINTK (KERN_DEBUG "%s: Unknown mode 0x%02x\n", port->name,
-                        port->physport->ieee1284.mode);
-               return -ENOSYS;
-       }
-
-       return (*fn) (port, buffer, len, 0);
-#endif /* IEEE1284 support */
-}
-
-/* Set the amount of time we wait while nothing's happening. */
-long parport_set_timeout (struct pardevice *dev, long inactivity)
-{
-       long int old = dev->timeout;
-
-       dev->timeout = inactivity;
-
-       if (dev->port->physport->cad == dev)
-               parport_ieee1284_wakeup (dev->port);
-
-       return old;
-}
diff --git a/drivers/misc/parport_ieee1284_ops.c b/drivers/misc/parport_ieee1284_ops.c
deleted file mode 100644 (file)
index 4fbeba6..0000000
+++ /dev/null
@@ -1,848 +0,0 @@
-/* IEEE-1284 operations for parport.
- *
- * This file is for generic IEEE 1284 operations.  The idea is that
- * they are used by the low-level drivers.  If they have a special way
- * of doing something, they can provide their own routines (and put
- * the function pointers in port->ops); if not, they can just use these
- * as a fallback.
- *
- * Note: Make no assumptions about hardware or architecture in this file!
- *
- * Author: Tim Waugh <tim@cyberelk.demon.co.uk>
- */
-
-#include <linux/config.h>
-#include <linux/parport.h>
-#include <linux/delay.h>
-#include <asm/uaccess.h>
-
-#define DEBUG /* undef me for production */
-
-#ifdef CONFIG_LP_CONSOLE
-#undef DEBUG /* Don't want a garbled console */
-#endif
-
-#ifdef DEBUG
-#define DPRINTK(stuff...) printk (stuff)
-#else
-#define DPRINTK(stuff...)
-#endif
-
-/***                                *
- * One-way data transfer functions. *
- *                                ***/
-
-static inline
-int polling (struct pardevice *dev)
-{
-       return dev->port->irq == PARPORT_IRQ_NONE;
-}
-
-/* Compatibility mode. */
-size_t parport_ieee1284_write_compat (struct parport *port,
-                                     const void *buffer, size_t len,
-                                     int flags)
-{
-       ssize_t count = 0;
-       const unsigned char *addr = buffer;
-       unsigned char byte;
-       struct pardevice *dev = port->physport->cad;
-       unsigned char ctl = (PARPORT_CONTROL_SELECT
-                            | PARPORT_CONTROL_INIT);
-
-       if (port->irq != PARPORT_IRQ_NONE)
-               parport_enable_irq (port);
-
-       port->physport->ieee1284.phase = IEEE1284_PH_FWD_DATA;
-       while (count < len) {
-               long expire = jiffies + dev->timeout;
-               long wait = (HZ + 99) / 100;
-               unsigned char mask = (PARPORT_STATUS_ERROR
-                                     | PARPORT_STATUS_BUSY);
-               unsigned char val = (PARPORT_STATUS_ERROR
-                                    | PARPORT_STATUS_BUSY);
-               int i;
-
-               /* Write the character to the data lines. */
-               byte = *addr++;
-               parport_write_data (port, byte);
-               udelay (1);
-
-               /* Wait until the peripheral's ready */
-               do {
-                       /* Is the peripheral ready yet? */
-                       if (!parport_wait_peripheral (port, mask, val))
-                               /* Skip the loop */
-                               goto ready;
-
-                       /* Is the peripheral upset? */
-                       if ((parport_read_status (port) &
-                            (PARPORT_STATUS_PAPEROUT |
-                             PARPORT_STATUS_SELECT |
-                             PARPORT_STATUS_ERROR))
-                           != (PARPORT_STATUS_SELECT |
-                               PARPORT_STATUS_ERROR))
-                               /* If nFault is asserted (i.e. no
-                                * error) and PAPEROUT and SELECT are
-                                * just red herrings, give the driver
-                                * a chance to check it's happy with
-                                * that before continuing. */
-                               goto stop;
-
-                       /* Have we run out of time? */
-                       if (!time_before (jiffies, expire))
-                               break;
-
-                       /* Yield the port for a while.  If this is the
-                           first time around the loop, don't let go of
-                           the port.  This way, we find out if we have
-                           our interrupt handler called. */
-                       if (count && polling (dev)) {
-                               parport_release (dev);
-                               current->state = TASK_INTERRUPTIBLE;
-                               schedule_timeout (wait);
-                               parport_claim_or_block (dev);
-                       }
-                       else
-                               /* We must have the device claimed here */
-                               parport_wait_event (port, wait);
-
-                       /* Is there a signal pending? */
-                       if (signal_pending (current))
-                               goto stop;
-
-                       /* Wait longer next time. */
-                       wait *= 2;
-               } while (time_before (jiffies, expire));
-
-               DPRINTK (KERN_DEBUG "%s: Timed out\n", port->name);
-               break;
-
-       ready:
-               /* Clear out previous irqs. */
-               while (!down_trylock (&port->physport->ieee1284.irq));
-
-               /* Pulse strobe. */
-               parport_write_control (port, ctl | PARPORT_CONTROL_STROBE);
-               udelay (1); /* strobe */
-
-               parport_write_control (port, ctl);
-               udelay (1); /* hold */
-
-               /* Wait until it's received (up to 20us). */
-               for (i = 0; i < 20; i++) {
-                       if (!down_trylock (&port->physport->ieee1284.irq) ||
-                           !(parport_read_status (port) & PARPORT_STATUS_ACK))
-                               break;
-                       udelay (1);
-               }
-
-               count++;
-
-                /* Let another process run if it needs to. */
-               if (time_before (jiffies, expire))
-                       if (!parport_yield_blocking (dev)
-                           && current->need_resched)
-                               schedule ();
-       }
- stop:
-       port->physport->ieee1284.phase = IEEE1284_PH_FWD_IDLE;
-
-       return count;
-}
-
-/* Nibble mode. */
-size_t parport_ieee1284_read_nibble (struct parport *port, 
-                                    void *buffer, size_t len,
-                                    int flags)
-{
-#ifndef CONFIG_PARPORT_1284
-       return 0;
-#else
-       unsigned char *buf = buffer;
-       int i;
-       unsigned char byte = 0;
-
-       len *= 2; /* in nibbles */
-       for (i=0; i < len; i++) {
-               unsigned char nibble;
-
-               /* Does the error line indicate end of data? */
-               if (((i & 1) == 0) &&
-                   (parport_read_status(port) & PARPORT_STATUS_ERROR)) {
-                       port->physport->ieee1284.phase = IEEE1284_PH_HBUSY_DNA;
-                       DPRINTK (KERN_DEBUG
-                               "%s: No more nibble data (%d bytes)\n",
-                               port->name, i/2);
-
-                       /* Go to reverse idle phase. */
-                       parport_frob_control (port,
-                                             PARPORT_CONTROL_AUTOFD,
-                                             PARPORT_CONTROL_AUTOFD);
-                       port->physport->ieee1284.phase = IEEE1284_PH_REV_IDLE;
-                       break;
-               }
-
-               /* Event 7: Set nAutoFd low. */
-               parport_frob_control (port,
-                                     PARPORT_CONTROL_AUTOFD,
-                                     PARPORT_CONTROL_AUTOFD);
-
-               /* Event 9: nAck goes low. */
-               port->ieee1284.phase = IEEE1284_PH_REV_DATA;
-               if (parport_wait_peripheral (port,
-                                            PARPORT_STATUS_ACK, 0)) {
-                       /* Timeout -- no more data? */
-                       DPRINTK (KERN_DEBUG
-                                "%s: Nibble timeout at event 9 (%d bytes)\n",
-                                port->name, i/2);
-                       break;
-               }
-
-
-               /* Read a nibble. */
-               nibble = parport_read_status (port) >> 3;
-               nibble &= ~8;
-               if ((nibble & 0x10) == 0)
-                       nibble |= 8;
-               nibble &= 0xf;
-
-               /* Event 10: Set nAutoFd high. */
-               parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0);
-
-               /* Event 11: nAck goes high. */
-               if (parport_wait_peripheral (port,
-                                            PARPORT_STATUS_ACK,
-                                            PARPORT_STATUS_ACK)) {
-                       /* Timeout -- no more data? */
-                       DPRINTK (KERN_DEBUG
-                                "%s: Nibble timeout at event 11\n",
-                                port->name);
-                       break;
-               }
-
-               if (i & 1) {
-                       /* Second nibble */
-                       byte |= nibble << 4;
-                       *buf++ = byte;
-               } else 
-                       byte = nibble;
-       }
-
-       i /= 2; /* i is now in bytes */
-
-       if (i == len) {
-               /* Read the last nibble without checking data avail. */
-               port = port->physport;
-               if (parport_read_status (port) & PARPORT_STATUS_ERROR)
-                       port->ieee1284.phase = IEEE1284_PH_HBUSY_DNA;
-               else
-                       port->ieee1284.phase = IEEE1284_PH_HBUSY_DAVAIL;
-       }
-
-       return i;
-#endif /* IEEE1284 support */
-}
-
-/* Byte mode. */
-size_t parport_ieee1284_read_byte (struct parport *port,
-                                  void *buffer, size_t len,
-                                  int flags)
-{
-#ifndef CONFIG_PARPORT_1284
-       return 0;
-#else
-       unsigned char *buf = buffer;
-       ssize_t count = 0;
-
-       for (count = 0; count < len; count++) {
-               unsigned char byte;
-
-               /* Data available? */
-               if (parport_read_status (port) & PARPORT_STATUS_ERROR) {
-                       port->physport->ieee1284.phase = IEEE1284_PH_HBUSY_DNA;
-                       DPRINTK (KERN_DEBUG
-                                "%s: No more byte data (%d bytes)\n",
-                                port->name, count);
-
-                       /* Go to reverse idle phase. */
-                       parport_frob_control (port,
-                                             PARPORT_CONTROL_AUTOFD,
-                                             PARPORT_CONTROL_AUTOFD);
-                       port->physport->ieee1284.phase = IEEE1284_PH_REV_IDLE;
-                       break;
-               }
-
-               /* Event 7: Set nAutoFd low. */
-               parport_frob_control (port,
-                                     PARPORT_CONTROL_AUTOFD,
-                                     PARPORT_CONTROL_AUTOFD);
-
-               /* Event 9: nAck goes low. */
-               port->physport->ieee1284.phase = IEEE1284_PH_REV_DATA;
-               if (parport_wait_peripheral (port,
-                                            PARPORT_STATUS_ACK,
-                                            0)) {
-                       /* Timeout -- no more data? */
-                       parport_frob_control (port, PARPORT_CONTROL_AUTOFD,
-                                                0);
-                       DPRINTK (KERN_DEBUG "%s: Byte timeout at event 9\n",
-                                port->name);
-                       break;
-               }
-
-               byte = parport_read_data (port);
-               *buf++ = byte;
-
-               /* Event 10: Set nAutoFd high */
-               parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0);
-
-               /* Event 11: nAck goes high. */
-               if (parport_wait_peripheral (port,
-                                            PARPORT_STATUS_ACK,
-                                            PARPORT_STATUS_ACK)) {
-                       /* Timeout -- no more data? */
-                       DPRINTK (KERN_DEBUG "%s: Byte timeout at event 11\n",
-                                port->name);
-                       break;
-               }
-
-               /* Event 16: Set nStrobe low. */
-               parport_frob_control (port,
-                                     PARPORT_CONTROL_STROBE,
-                                     PARPORT_CONTROL_STROBE);
-               udelay (5);
-
-               /* Event 17: Set nStrobe high. */
-               parport_frob_control (port, PARPORT_CONTROL_STROBE, 0);
-       }
-
-       if (count == len) {
-               /* Read the last byte without checking data avail. */
-               port = port->physport;
-               if (parport_read_status (port) & PARPORT_STATUS_ERROR)
-                       port->ieee1284.phase = IEEE1284_PH_HBUSY_DNA;
-               else
-                       port->ieee1284.phase = IEEE1284_PH_HBUSY_DAVAIL;
-       }
-
-       return count;
-#endif /* IEEE1284 support */
-}
-
-/***              *
- * ECP Functions. *
- *              ***/
-
-#ifdef CONFIG_PARPORT_1284
-
-static inline
-int ecp_forward_to_reverse (struct parport *port)
-{
-       int retval;
-
-       /* Event 38: Set nAutoFd low */
-       parport_frob_control (port,
-                             PARPORT_CONTROL_AUTOFD,
-                             PARPORT_CONTROL_AUTOFD);
-       parport_data_reverse (port);
-       udelay (5);
-
-       /* Event 39: Set nInit low to initiate bus reversal */
-       parport_frob_control (port,
-                             PARPORT_CONTROL_INIT,
-                             PARPORT_CONTROL_INIT);
-
-       /* Event 40: PError goes low */
-       retval = parport_wait_peripheral (port,
-                                         PARPORT_STATUS_PAPEROUT, 0);
-
-       if (!retval) {
-               DPRINTK (KERN_DEBUG "%s: ECP direction: reverse\n",
-                        port->name);
-               port->ieee1284.phase = IEEE1284_PH_REV_IDLE;
-       }
-
-       return retval;
-}
-
-static inline
-int ecp_reverse_to_forward (struct parport *port)
-{
-       int retval;
-
-       /* Event 47: Set nInit high */
-       parport_frob_control (port,
-                             PARPORT_CONTROL_INIT,
-                             PARPORT_CONTROL_INIT);
-       parport_data_reverse (port);
-
-       /* Event 49: PError goes high */
-       retval = parport_wait_peripheral (port,
-                                         PARPORT_STATUS_PAPEROUT,
-                                         PARPORT_STATUS_PAPEROUT);
-
-       if (!retval) {
-               parport_data_forward (port);
-               DPRINTK (KERN_DEBUG "%s: ECP direction: forward\n",
-                        port->name);
-               port->ieee1284.phase = IEEE1284_PH_FWD_IDLE;
-       }
-
-       return retval;
-}
-
-#endif /* IEEE1284 support */
-
-/* ECP mode, forward channel, data. */
-size_t parport_ieee1284_ecp_write_data (struct parport *port,
-                                       const void *buffer, size_t len,
-                                       int flags)
-{
-#ifndef CONFIG_PARPORT_1284
-       return 0;
-#else
-       const unsigned char *buf = buffer;
-       size_t written;
-       int ctl = parport_read_control (port) & ~PARPORT_CONTROL_AUTOFD;
-       int retry;
-
-       port = port->physport;
-
-       if (port->ieee1284.phase != IEEE1284_PH_FWD_IDLE)
-               if (ecp_reverse_to_forward (port))
-                       return 0;
-
-       port->ieee1284.phase = IEEE1284_PH_FWD_DATA;
-
-       /* HostAck high (data, not command) */
-       parport_write_control (port, ctl);
-       for (written = 0; written < len; written++, buf++) {
-               long expire = jiffies + port->cad->timeout;
-               unsigned char byte;
-
-               byte = *buf;
-       try_again:
-               parport_write_data (port, byte);
-               parport_write_control (port, ctl | PARPORT_CONTROL_STROBE);
-               udelay (5);
-               for (retry = 0; retry < 100; retry++) {
-                       if (!parport_wait_peripheral (port,
-                                                     PARPORT_STATUS_BUSY, 0))
-                               goto success;
-
-                       if (signal_pending (current)) {
-                               parport_write_control (port, ctl);
-                               break;
-                       }
-               }
-
-               /* Time for Host Transfer Recovery (page 41 of IEEE1284) */
-               DPRINTK (KERN_DEBUG "%s: ECP transfer stalled!\n", port->name);
-
-               parport_write_control (port, ctl | PARPORT_CONTROL_INIT);
-               udelay (50);
-               if (parport_read_status (port) & PARPORT_STATUS_PAPEROUT) {
-                       /* It's buggered. */
-                       parport_write_control (port, ctl);
-                       break;
-               }
-
-               parport_write_control (port, ctl);
-               udelay (50);
-               if (!(parport_read_status (port) & PARPORT_STATUS_PAPEROUT))
-                       break;
-
-               DPRINTK (KERN_DEBUG "%s: Host transfer recovered\n",
-                        port->name);
-
-               if (time_after_eq (jiffies, expire)) break;
-               goto try_again;
-       success:
-               parport_write_control (port, ctl);
-               udelay (5);
-               if (parport_wait_peripheral (port,
-                                            PARPORT_STATUS_BUSY,
-                                            PARPORT_STATUS_BUSY))
-                       /* Peripheral hasn't accepted the data. */
-                       break;
-       }
-
-       port->ieee1284.phase = IEEE1284_PH_FWD_IDLE;
-
-       return written;
-#endif /* IEEE1284 support */
-}
-
-/* ECP mode, reverse channel, data. */
-size_t parport_ieee1284_ecp_read_data (struct parport *port,
-                                      void *buffer, size_t len, int flags)
-{
-#ifndef CONFIG_PARPORT_1284
-       return 0;
-#else
-       struct pardevice *dev = port->cad;
-       unsigned char *buf = buffer;
-       int rle_count = 0; /* shut gcc up */
-       int rle = 0;
-       ssize_t count = 0;
-
-       port = port->physport;
-
-       if (port->ieee1284.phase != IEEE1284_PH_REV_IDLE)
-               if (ecp_forward_to_reverse (port))
-                       return 0;
-
-       port->ieee1284.phase = IEEE1284_PH_REV_DATA;
-
-       /* Set HostAck low to start accepting data. */
-       parport_frob_control (port, PARPORT_CONTROL_AUTOFD,
-                             PARPORT_CONTROL_AUTOFD);
-       while (count < len) {
-               long expire = jiffies + dev->timeout;
-               unsigned char byte;
-               int command;
-
-               /* Event 43: Peripheral sets nAck low. It can take as
-                   long as it wants. */
-               while (parport_wait_peripheral (port,
-                                               PARPORT_STATUS_ACK,
-                                               PARPORT_STATUS_ACK)) {
-                       /* The peripheral hasn't given us data in
-                          35ms.  If we have data to give back to the
-                          caller, do it now. */
-                       if (count)
-                               goto out;
-
-                       /* If we've used up all the time we were allowed,
-                          give up altogether. */
-                       if (!time_before (jiffies, expire))
-                               goto out;
-
-                       /* Yield the port for a while. */
-                       if (count && polling (dev)) {
-                               parport_release (dev);
-                               current->state = TASK_INTERRUPTIBLE;
-                               schedule_timeout ((HZ + 99) / 25);
-                               parport_claim_or_block (dev);
-                       }
-                       else
-                               /* We must have the device claimed here. */
-                               parport_wait_event (port, (HZ + 99) / 25);
-
-                       /* Is there a signal pending? */
-                       if (signal_pending (current))
-                               goto out;
-               }
-
-               /* Is this a command? */
-               if (rle)
-                       /* The last byte was a run-length count, so
-                           this can't be as well. */
-                       command = 0;
-               else
-                       command = (parport_read_status (port) &
-                                  PARPORT_STATUS_BUSY) ? 1 : 0;
-
-               /* Read the data. */
-               byte = parport_read_data (port);
-
-               /* If this is a channel command, rather than an RLE
-                   command or a normal data byte, don't accept it. */
-               if (command) {
-                       if (byte & 0x80) {
-                               DPRINTK (KERN_DEBUG "%s: stopping short at "
-                                        "channel command (%02x)\n",
-                                        port->name, byte);
-                               goto out;
-                       }
-                       else if (port->ieee1284.mode != IEEE1284_MODE_ECPRLE)
-                               DPRINTK (KERN_DEBUG "%s: device illegally "
-                                        "using RLE; accepting anyway\n",
-                                        port->name);
-
-                       rle_count = byte + 1;
-
-                       /* Are we allowed to read that many bytes? */
-                       if (rle_count > (len - count)) {
-                               DPRINTK (KERN_DEBUG "%s: leaving %d RLE bytes "
-                                        "for next time\n", port->name,
-                                        rle_count);
-                               break;
-                       }
-
-                       rle = 1;
-               }
-
-               /* Event 44: Set HostAck high, acknowledging handshake. */
-               parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0);
-
-               /* Event 45: The peripheral has 35ms to set nAck high. */
-               if (parport_wait_peripheral (port, PARPORT_STATUS_ACK, 0)) {
-                       /* It's gone wrong.  Return what data we have
-                           to the caller. */
-                       DPRINTK (KERN_DEBUG "ECP read timed out at 45\n");
-
-                       if (command)
-                               printk (KERN_WARNING
-                                       "%s: command ignored (%02x)\n",
-                                       port->name, byte);
-
-                       break;
-               }
-
-               /* Event 46: Set HostAck low and accept the data. */
-               parport_frob_control (port,
-                                     PARPORT_CONTROL_AUTOFD,
-                                     PARPORT_CONTROL_AUTOFD);
-
-               /* If we just read a run-length count, fetch the data. */
-               if (command)
-                       continue;
-
-               /* If this is the byte after a run-length count, decompress. */
-               if (rle) {
-                       rle = 0;
-                       memset (buf, byte, rle_count);
-                       buf += rle_count;
-                       count += rle_count;
-                       DPRINTK (KERN_DEBUG "%s: decompressed to %d bytes\n",
-                                port->name, rle_count);
-               }
-               else
-                       /* Normal data byte. */
-                       *buf++ = byte, count++;
-       }
-
- out:
-       return count;
-#endif /* IEEE1284 support */
-}
-
-/* ECP mode, forward channel, commands. */
-size_t parport_ieee1284_ecp_write_addr (struct parport *port,
-                                       const void *buffer, size_t len,
-                                       int flags)
-{
-#ifndef CONFIG_PARPORT_1284
-       return 0;
-#else
-       const unsigned char *buf = buffer;
-       size_t written;
-       int ctl = parport_read_control (port) | PARPORT_CONTROL_AUTOFD;
-       int retry;
-
-       port = port->physport;
-
-       if (port->ieee1284.phase != IEEE1284_PH_FWD_IDLE)
-               if (ecp_reverse_to_forward (port))
-                       return 0;
-
-       port->ieee1284.phase = IEEE1284_PH_FWD_DATA;
-
-       /* HostAck low (command, not data) */
-       parport_write_control (port, ctl);
-       for (written = 0; written < len; written++, buf++) {
-               long expire = jiffies + port->cad->timeout;
-               unsigned char byte;
-
-               byte = *buf;
-       try_again:
-               parport_write_data (port, byte);
-               parport_write_control (port, ctl | PARPORT_CONTROL_STROBE);
-               udelay (5);
-               for (retry = 0; retry < 100; retry++) {
-                       if (!parport_wait_peripheral (port,
-                                                     PARPORT_STATUS_BUSY, 0))
-                               goto success;
-
-                       if (signal_pending (current)) {
-                               parport_write_control (port, ctl);
-                               break;
-                       }
-               }
-
-               /* Time for Host Transfer Recovery (page 41 of IEEE1284) */
-               DPRINTK (KERN_DEBUG "%s: ECP transfer stalled!\n", port->name);
-
-               parport_write_control (port, ctl | PARPORT_CONTROL_INIT);
-               udelay (50);
-               if (parport_read_status (port) & PARPORT_STATUS_PAPEROUT) {
-                       /* It's buggered. */
-                       parport_write_control (port, ctl);
-                       break;
-               }
-
-               parport_write_control (port, ctl);
-               udelay (50);
-               if (!(parport_read_status (port) & PARPORT_STATUS_PAPEROUT))
-                       break;
-
-               DPRINTK (KERN_DEBUG "%s: Host transfer recovered\n",
-                        port->name);
-
-               if (time_after_eq (jiffies, expire)) break;
-               goto try_again;
-       success:
-               parport_write_control (port, ctl);
-               udelay (5);
-               if (parport_wait_peripheral (port,
-                                            PARPORT_STATUS_BUSY,
-                                            PARPORT_STATUS_BUSY))
-                       /* Peripheral hasn't accepted the data. */
-                       break;
-       }
-
-       port->ieee1284.phase = IEEE1284_PH_FWD_IDLE;
-
-       return written;
-#endif /* IEEE1284 support */
-}
-
-/***              *
- * EPP functions. *
- *              ***/
-
-/* EPP mode, forward channel, data. */
-size_t parport_ieee1284_epp_write_data (struct parport *port,
-                                       const void *buffer, size_t len,
-                                       int flags)
-{
-       /* This is untested */
-       unsigned char *bp = (unsigned char *) buffer;
-       size_t ret = 0;
-
-       parport_frob_control (port,
-                             PARPORT_CONTROL_STROBE |
-                             PARPORT_CONTROL_AUTOFD |
-                             PARPORT_CONTROL_SELECT,
-                             PARPORT_CONTROL_STROBE |
-                             PARPORT_CONTROL_SELECT);
-       port->ops->data_forward (port);
-       for (; len > 0; len--, bp++) {
-               parport_write_data (port, *bp);
-
-               if (parport_wait_peripheral (port, PARPORT_STATUS_BUSY,
-                                            PARPORT_STATUS_BUSY))
-                       break;
-
-               /* Strobe data */
-               parport_frob_control (port, PARPORT_CONTROL_AUTOFD,
-                                     PARPORT_CONTROL_AUTOFD);
-
-               if (parport_wait_peripheral (port, PARPORT_STATUS_BUSY, 0))
-                       break;
-
-               parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0);
-               ret++;
-       }
-
-       return ret;
-}
-
-/* EPP mode, reverse channel, data. */
-size_t parport_ieee1284_epp_read_data (struct parport *port,
-                                      void *buffer, size_t len,
-                                      int flags)
-{
-       /* This is untested. */
-       unsigned char *bp = (unsigned char *) buffer;
-       unsigned ret = 0;
-
-       parport_frob_control (port,
-                             PARPORT_CONTROL_STROBE |
-                             PARPORT_CONTROL_AUTOFD |
-                             PARPORT_CONTROL_SELECT, 0);
-       port->ops->data_reverse (port);
-       for (; len > 0; len--, bp++) {
-               if (parport_wait_peripheral (port, PARPORT_STATUS_BUSY,
-                                            PARPORT_STATUS_BUSY))
-                       break;
-
-               parport_frob_control (port, PARPORT_CONTROL_AUTOFD,
-                                     PARPORT_CONTROL_AUTOFD);
-
-               if (parport_wait_peripheral (port, PARPORT_STATUS_BUSY, 0))
-                       break;
-
-               *bp = parport_read_data (port);
-
-               parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0);
-               ret++;
-       }
-       port->ops->data_forward (port);
-
-       return ret;
-}
-
-/* EPP mode, forward channel, addresses. */
-size_t parport_ieee1284_epp_write_addr (struct parport *port,
-                                       const void *buffer, size_t len,
-                                       int flags)
-{
-       /* This is untested */
-       unsigned char *bp = (unsigned char *) buffer;
-       size_t ret = 0;
-
-       parport_frob_control (port,
-                             PARPORT_CONTROL_STROBE |
-                             PARPORT_CONTROL_SELECT |
-                             PARPORT_CONTROL_AUTOFD,
-                             PARPORT_CONTROL_STROBE |
-                             PARPORT_CONTROL_SELECT);
-       port->ops->data_forward (port);
-       for (; len > 0; len--, bp++) {
-               parport_write_data (port, *bp);
-
-               if (parport_wait_peripheral (port, PARPORT_STATUS_BUSY,
-                                            PARPORT_STATUS_BUSY))
-                       break;
-
-               /* Strobe data */
-               parport_frob_control (port, PARPORT_CONTROL_SELECT,
-                                     PARPORT_CONTROL_SELECT);
-
-               if (parport_wait_peripheral (port, PARPORT_STATUS_BUSY, 0))
-                       break;
-
-               parport_frob_control (port, PARPORT_CONTROL_SELECT, 0);
-               ret++;
-       }
-
-       return ret;
-}
-
-/* EPP mode, reverse channel, addresses. */
-size_t parport_ieee1284_epp_read_addr (struct parport *port,
-                                      void *buffer, size_t len,
-                                      int flags)
-{
-       /* This is untested. */
-       unsigned char *bp = (unsigned char *) buffer;
-       unsigned ret = 0;
-
-       parport_frob_control (port,
-                             PARPORT_CONTROL_STROBE |
-                             PARPORT_CONTROL_SELECT |
-                             PARPORT_CONTROL_AUTOFD, 0);
-       port->ops->data_reverse (port);
-       for (; len > 0; len--, bp++) {
-               if (parport_wait_peripheral (port, PARPORT_STATUS_BUSY,
-                                            PARPORT_STATUS_BUSY))
-                       break;
-
-               parport_frob_control (port, PARPORT_CONTROL_SELECT,
-                                     PARPORT_CONTROL_SELECT);
-
-               if (parport_wait_peripheral (port, PARPORT_STATUS_BUSY, 0))
-                       break;
-
-               *bp = parport_read_data (port);
-
-               parport_frob_control (port, PARPORT_CONTROL_SELECT, 0);
-               ret++;
-       }
-       port->ops->data_forward (port);
-
-       return ret;
-}
diff --git a/drivers/misc/parport_init.c b/drivers/misc/parport_init.c
deleted file mode 100644 (file)
index e4912b4..0000000
+++ /dev/null
@@ -1,210 +0,0 @@
-/* Parallel-port initialisation code.
- * 
- * Authors: David Campbell <campbell@torque.net>
- *          Tim Waugh <tim@cyberelk.demon.co.uk>
- *         Jose Renau <renau@acm.org>
- *
- * based on work by Grant Guenther <grant@torque.net>
- *              and Philip Blundell <Philip.Blundell@pobox.com>
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/threads.h>
-
-#include <linux/parport.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/malloc.h>
-#include <linux/init.h>
-
-#ifndef MODULE
-static int io[PARPORT_MAX+1] __initdata = { [0 ... PARPORT_MAX] = 0 };
-static int io_hi[PARPORT_MAX+1] __initdata = { [0 ... PARPORT_MAX] = 0 };
-static int irq[PARPORT_MAX] __initdata = { [0 ... PARPORT_MAX-1] = PARPORT_IRQ_PROBEONLY };
-static int dma[PARPORT_MAX] __initdata = { [0 ... PARPORT_MAX-1] = PARPORT_DMA_NONE };
-
-extern int parport_pc_init(int *io, int *io_hi, int *irq, int *dma);
-extern int parport_ax_init(void);
-
-static int parport_setup_ptr __initdata = 0;
-
-__initfunc(void parport_setup(char *str, int *ints))
-{
-       if (ints[0] == 0) {
-               if (str && !strncmp(str, "auto", 4)) {
-                       irq[0] = PARPORT_IRQ_AUTO;
-                       dma[0] = PARPORT_DMA_AUTO;
-               }
-               else if (str)
-                       printk (KERN_ERR "parport: `%s': huh?\n", str);
-               else
-                       printk (KERN_ERR "parport: parport=.. what?\n");
-               
-               return;
-       }
-       else if (ints[1] == 0) {
-               /* Disable parport if "parport=0" in cmdline */
-               io[0] = PARPORT_DISABLE; 
-               return;
-       }
-
-       if (parport_setup_ptr < PARPORT_MAX) {
-               char *sep;
-               io[parport_setup_ptr] = ints[1];
-               irq[parport_setup_ptr] = PARPORT_IRQ_NONE;
-               dma[parport_setup_ptr] = PARPORT_DMA_NONE;
-               if (ints[0] > 1) {
-                       irq[parport_setup_ptr] = ints[2];
-                       if (ints[0] > 2) {
-                               dma[parport_setup_ptr] = ints[3];
-                               goto done;
-                       }
-
-                       if (str == NULL)
-                               goto done;
-
-                       goto dma_from_str;
-               }
-               else if (str == NULL)
-                       goto done;
-               else if (!strncmp(str, "auto", 4))
-                       irq[parport_setup_ptr] = PARPORT_IRQ_AUTO;
-               else if (strncmp(str, "none", 4) != 0) {
-                       printk(KERN_ERR "parport: bad irq `%s'\n", str);
-                       return;
-               }
-
-               if ((sep = strchr(str, ',')) == NULL) goto done;
-               str = sep+1;
-       dma_from_str:
-               if (!strncmp(str, "auto", 4))
-                       dma[parport_setup_ptr] = PARPORT_DMA_AUTO;
-               else if (strncmp(str, "none", 4) != 0) {
-                       char *ep;
-                       dma[parport_setup_ptr] = simple_strtoul(str, &ep, 0);
-                       if (ep == str) {
-                               printk(KERN_ERR "parport: bad dma `%s'\n",
-                                      str);
-                               return;
-                       }
-               }
-       done:
-               parport_setup_ptr++;
-       } else
-               printk(KERN_ERR "parport=%s ignored, too many ports\n", str);
-}
-#endif
-
-#ifdef MODULE
-int init_module(void)
-{
-#ifdef CONFIG_SYSCTL
-       parport_default_proc_register ();
-#endif
-       return 0;
-}
-
-void cleanup_module(void)
-{
-#ifdef CONFIG_SYSCTL
-       parport_default_proc_unregister ();
-#endif
-}
-
-#else
-
-__initfunc(int parport_init(void))
-{
-       if (io[0] == PARPORT_DISABLE) 
-               return 1;
-
-#ifdef CONFIG_SYSCTL
-       parport_default_proc_register ();
-#endif
-
-#ifdef CONFIG_PARPORT_PC
-       parport_pc_init(io, io_hi, irq, dma);
-#endif
-#ifdef CONFIG_PARPORT_AX
-       parport_ax_init();
-#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
-#ifdef CONFIG_PARPORT_ARC
-       parport_arc_init();
-#endif
-       return 0;
-}
-#endif
-
-/* Exported symbols for modules. */
-
-EXPORT_SYMBOL(parport_claim);
-EXPORT_SYMBOL(parport_claim_or_block);
-EXPORT_SYMBOL(parport_release);
-EXPORT_SYMBOL(parport_register_port);
-EXPORT_SYMBOL(parport_announce_port);
-EXPORT_SYMBOL(parport_unregister_port);
-EXPORT_SYMBOL(parport_register_driver);
-EXPORT_SYMBOL(parport_unregister_driver);
-EXPORT_SYMBOL(parport_register_device);
-EXPORT_SYMBOL(parport_unregister_device);
-EXPORT_SYMBOL(parport_enumerate);
-EXPORT_SYMBOL(parport_negotiate);
-EXPORT_SYMBOL(parport_write);
-EXPORT_SYMBOL(parport_read);
-EXPORT_SYMBOL(parport_ieee1284_wakeup);
-EXPORT_SYMBOL(parport_wait_peripheral);
-EXPORT_SYMBOL(parport_wait_event);
-EXPORT_SYMBOL(parport_set_timeout);
-EXPORT_SYMBOL(parport_ieee1284_interrupt);
-EXPORT_SYMBOL(parport_ieee1284_ecp_write_data);
-EXPORT_SYMBOL(parport_ieee1284_ecp_read_data);
-EXPORT_SYMBOL(parport_ieee1284_ecp_write_addr);
-EXPORT_SYMBOL(parport_ieee1284_write_compat);
-EXPORT_SYMBOL(parport_ieee1284_read_nibble);
-EXPORT_SYMBOL(parport_ieee1284_read_byte);
-EXPORT_SYMBOL(parport_ieee1284_epp_write_data);
-EXPORT_SYMBOL(parport_ieee1284_epp_read_data);
-EXPORT_SYMBOL(parport_ieee1284_epp_write_addr);
-EXPORT_SYMBOL(parport_ieee1284_epp_read_addr);
-EXPORT_SYMBOL(parport_proc_register);
-EXPORT_SYMBOL(parport_proc_unregister);
-EXPORT_SYMBOL(parport_device_proc_register);
-EXPORT_SYMBOL(parport_device_proc_unregister);
-EXPORT_SYMBOL(parport_default_proc_register);
-EXPORT_SYMBOL(parport_default_proc_unregister);
-EXPORT_SYMBOL(parport_parse_irqs);
-EXPORT_SYMBOL(parport_parse_dmas);
-#ifdef CONFIG_PARPORT_1284
-EXPORT_SYMBOL(parport_open);
-EXPORT_SYMBOL(parport_close);
-EXPORT_SYMBOL(parport_device_id);
-EXPORT_SYMBOL(parport_device_num);
-EXPORT_SYMBOL(parport_device_coords);
-EXPORT_SYMBOL(parport_daisy_deselect_all);
-EXPORT_SYMBOL(parport_daisy_select);
-EXPORT_SYMBOL(parport_daisy_init);
-#endif
-
-void inc_parport_count(void)
-{
-#ifdef MODULE
-       MOD_INC_USE_COUNT;
-#endif
-}
-
-void dec_parport_count(void)
-{
-#ifdef MODULE
-       MOD_DEC_USE_COUNT;
-#endif
-}
diff --git a/drivers/misc/parport_mfc3.c b/drivers/misc/parport_mfc3.c
deleted file mode 100644 (file)
index 1acb52a..0000000
+++ /dev/null
@@ -1,414 +0,0 @@
-/* Low-level parallel port routines for the Multiface 3 card
- *
- * Author: Joerg Dorchain <dorchain@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 int mfc3_claim_resources(struct parport *p)
-{
-DPRINTK("claim_resources\n");
-}
-
-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);
-
-                                       if (p->irq != PARPORT_IRQ_NONE)
-                                               if (use_cnt++ == 0)
-                                                       if (request_irq(IRQ_AMIGA_PORTS, mfc3_interrupt, 0, p->name, &pp_mfc3_ops))
-                                                               use_cnt--;
-
-                                       if (parport_probe_hook)
-                                               (*parport_probe_hook)(p);
-                                       zorro_config_board(key, 0);
-                                       p->private_data = (void *)key;
-                                       parport_announce_port (p);
-                               }
-                       }
-               }
-       }
-       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 (p->irq != PARPORT_IRQ_NONE) 
-                               if (--use_cnt == 0) 
-                       free_irq(IRQ_AMIGA_PORTS, &pp_mfc3_ops);
-                       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 --git a/drivers/misc/parport_pc.c b/drivers/misc/parport_pc.c
deleted file mode 100644 (file)
index 788e1b3..0000000
+++ /dev/null
@@ -1,1904 +0,0 @@
-/* Low-level parallel-port routines for 8255-based PC-style hardware.
- * 
- * Authors: Phil Blundell <Philip.Blundell@pobox.com>
- *          Tim Waugh <tim@cyberelk.demon.co.uk>
- *         Jose Renau <renau@acm.org>
- *          David Campbell <campbell@torque.net>
- *          Andrea Arcangeli
- *
- * based on work by Grant Guenther <grant@torque.net> and Phil Blundell.
- *
- * Cleaned up include files - Russell King <linux@arm.uk.linux.org>
- * DMA support - Bert De Jonghe <bert@sophis.be>
- * Better EPP probing - Carlos Henrique Bauer <chbauer@acm.org>
- */
-
-/* This driver should work with any hardware that is broadly compatible
- * with that in the IBM PC.  This applies to the majority of integrated
- * I/O chipsets that are commonly available.  The expected register
- * layout is:
- *
- *     base+0          data
- *     base+1          status
- *     base+2          control
- *
- * In addition, there are some optional registers:
- *
- *     base+3          EPP address
- *     base+4          EPP data
- *     base+0x400      ECP config A
- *     base+0x401      ECP config B
- *     base+0x402      ECP control
- *
- * All registers are 8 bits wide and read/write.  If your hardware differs
- * only in register addresses (eg because your registers are on 32-bit
- * word boundaries) then you can alter the constants in parport_pc.h to
- * accomodate this.
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/kernel.h>
-#include <linux/malloc.h>
-#include <linux/pci.h>
-#include <linux/sysctl.h>
-
-#include <asm/io.h>
-#include <asm/dma.h>
-#include <asm/uaccess.h>
-
-#include <linux/parport.h>
-#include <linux/parport_pc.h>
-
-/* Maximum number of ports to support.  It is useless to set this greater
-   than PARPORT_MAX (in <linux/parport.h>).  */
-#define PARPORT_PC_MAX_PORTS  8
-
-/* ECR modes */
-#define ECR_SPP 00
-#define ECR_PS2 01
-#define ECR_PPF 02
-#define ECR_ECP 03
-#define ECR_EPP 04
-#define ECR_VND 05
-#define ECR_TST 06
-#define ECR_CNF 07
-
-static int user_specified __initdata = 0;
-
-/* frob_control, but for ECR */
-static void frob_econtrol (struct parport *pb, unsigned char m,
-                          unsigned char v)
-{
-       outb ((inb (ECONTROL (pb)) & ~m) ^ v, ECONTROL (pb));
-}
-
-#ifdef CONFIG_PARPORT_1284
-/* Safely change the mode bits in the ECR */
-static int change_mode(struct parport *p, int m)
-{
-       const struct parport_pc_private *priv = p->physport->private_data;
-       int ecr = ECONTROL(p);
-       unsigned char oecr;
-       int mode;
-
-       if (!priv->ecr) {
-               printk (KERN_DEBUG "change_mode: but there's no ECR!\n");
-               return 0;
-       }
-
-       /* Bits <7:5> contain the mode. */
-       oecr = inb (ecr);
-       mode = (oecr >> 5) & 0x7;
-       if (mode == m) return 0;
-       if (mode && m)
-               /* We have to go through mode 000 */
-               change_mode (p, ECR_SPP);
-
-       if (m < 2 && !(parport_read_control (p) & 0x20)) {
-               /* This mode resets the FIFO, so we may
-                * have to wait for it to drain first. */
-               long expire = jiffies + p->physport->cad->timeout;
-               int counter;
-               switch (mode) {
-               case ECR_PPF: /* Parallel Port FIFO mode */
-               case ECR_ECP: /* ECP Parallel Port mode */
-                       /* Busy wait for 200us */
-                       for (counter = 0; counter < 40; counter++) {
-                               if (inb (ECONTROL (p)) & 0x01)
-                                       break;
-                               if (signal_pending (current)) break;
-                               udelay (5);
-                       }
-
-                       /* Poll slowly. */
-                       while (!(inb (ECONTROL (p)) & 0x01)) {
-                               if (time_after_eq (jiffies, expire))
-                                       /* The FIFO is stuck. */
-                                       return -EBUSY;
-                               current->state = TASK_INTERRUPTIBLE;
-                               schedule_timeout ((HZ + 99) / 100);
-                               if (signal_pending (current))
-                                       break;
-                       }
-               }
-       }
-
-       /* Set the mode. */
-       oecr &= ~(7 << 5);
-       oecr |= m << 5;
-       outb (oecr, ecr);
-       return 0;
-}
-
-/* Find FIFO lossage; FIFO is reset */
-static int get_fifo_residue (struct parport *p)
-{
-       int residue;
-       int cnfga;
-       const struct parport_pc_private *priv = p->physport->private_data;
-
-       /* Prevent further data transfer. */
-       parport_frob_control (p,
-                             PARPORT_CONTROL_STROBE,
-                             PARPORT_CONTROL_STROBE);
-
-       /* Adjust for the contents of the FIFO. */
-       for (residue = priv->fifo_depth; ; residue--) {
-               if (inb (ECONTROL (p)) & 0x2)
-                               /* Full up. */
-                       break;
-
-               outb (0, FIFO (p));
-       }
-
-       printk (KERN_DEBUG "%s: %d PWords were left in FIFO\n", p->name,
-               residue);
-
-       /* Reset the FIFO. */
-       frob_econtrol (p, 0xe0, 0x20);
-       parport_frob_control (p, PARPORT_CONTROL_STROBE, 0);
-
-       /* Now change to config mode and clean up. FIXME */
-       frob_econtrol (p, 0xe0, 0xe0);
-       cnfga = inb (CONFIGA (p));
-       printk (KERN_DEBUG "%s: cnfgA contains 0x%02x\n", p->name, cnfga);
-
-       if (!(cnfga & (1<<2))) {
-               printk (KERN_DEBUG "%s: Accounting for extra byte\n", p->name);
-               residue++;
-       }
-
-       /* Don't care about partial PWords until support is added for
-        * PWord != 1 byte. */
-
-       /* Back to PS2 mode. */
-       frob_econtrol (p, 0xe0, 0x20);
-
-       return residue;
-}
-
-#endif /* IEEE 1284 support */
-
-/*
- * Clear TIMEOUT BIT in EPP MODE
- *
- * This is also used in SPP detection.
- */
-static int clear_epp_timeout(struct parport *pb)
-{
-       unsigned char r;
-
-       if (!(parport_pc_read_status(pb) & 0x01))
-               return 1;
-
-       /* To clear timeout some chips require double read */
-       parport_pc_read_status(pb);
-       r = parport_pc_read_status(pb);
-       outb (r | 0x01, STATUS (pb)); /* Some reset by writing 1 */
-       outb (r & 0xfe, STATUS (pb)); /* Others by writing 0 */
-       r = parport_pc_read_status(pb);
-
-       return !(r & 0x01);
-}
-
-/*
- * Access functions.
- *
- * These aren't static because they may be used by the parport_xxx_yyy
- * macros.  extern __inline__ versions of several of these are in
- * parport_pc.h.
- */
-
-static void parport_pc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-       parport_generic_irq(irq, (struct parport *) dev_id, regs);
-}
-
-void parport_pc_write_data(struct parport *p, unsigned char d)
-{
-       outb (d, DATA (p));
-}
-
-unsigned char parport_pc_read_data(struct parport *p)
-{
-       return inb (DATA (p));
-}
-
-unsigned char __frob_control (struct parport *p, unsigned char mask,
-                             unsigned char val)
-{
-       struct parport_pc_private *priv = p->physport->private_data;
-       unsigned char ctr = priv->ctr;
-       ctr = (ctr & ~mask) ^ val;
-       ctr &= priv->ctr_writable; /* only write writable bits. */
-       outb (ctr, CONTROL (p));
-       return priv->ctr = ctr; /* update soft copy */
-}
-
-void parport_pc_write_control(struct parport *p, unsigned char d)
-{
-       const unsigned char wm = (PARPORT_CONTROL_STROBE |
-                                 PARPORT_CONTROL_AUTOFD |
-                                 PARPORT_CONTROL_INIT |
-                                 PARPORT_CONTROL_SELECT);
-
-       /* Take this out when drivers have adapted to the newer interface. */
-       if (d & 0x20) {
-                       printk (KERN_DEBUG "%s (%s): use data_reverse for this!\n",
-                                       p->name, p->cad->name);
-                       parport_pc_data_reverse (p);
-       }
-
-       __frob_control (p, wm, d & wm);
-}
-
-unsigned char parport_pc_read_control(struct parport *p)
-{
-       const struct parport_pc_private *priv = p->physport->private_data;
-       return priv->ctr; /* Use soft copy */
-}
-
-unsigned char parport_pc_frob_control (struct parport *p, unsigned char mask,
-                                      unsigned char val)
-{
-       const unsigned char wm = (PARPORT_CONTROL_STROBE |
-                                 PARPORT_CONTROL_AUTOFD |
-                                 PARPORT_CONTROL_INIT |
-                                 PARPORT_CONTROL_SELECT);
-
-       /* Take this out when drivers have adapted to the newer interface. */
-       if (mask & 0x20) {
-                       printk (KERN_DEBUG "%s (%s): use data_reverse for this!\n",
-                                       p->name, p->cad->name);
-                       parport_pc_data_reverse (p);
-       }
-
-       /* Restrict mask and val to control lines. */
-       mask &= wm;
-       val &= wm;
-
-       return __frob_control (p, mask, val);
-}
-
-unsigned char parport_pc_read_status(struct parport *p)
-{
-       return inb (STATUS (p));
-}
-
-void parport_pc_disable_irq(struct parport *p)
-{
-       __frob_control (p, 0x10, 0);
-}
-
-void parport_pc_enable_irq(struct parport *p)
-{
-       __frob_control (p, 0x10, 0x10);
-}
-
-void parport_pc_data_forward (struct parport *p)
-{
-       __frob_control (p, 0x20, 0);
-}
-
-void parport_pc_data_reverse (struct parport *p)
-{
-       __frob_control (p, 0x20, 0x20);
-}
-
-void parport_pc_init_state(struct pardevice *dev, struct parport_state *s)
-{
-       s->u.pc.ctr = 0xc | (dev->irq_func ? 0x10 : 0x0);
-       s->u.pc.ecr = 0x24;
-}
-
-void parport_pc_save_state(struct parport *p, struct parport_state *s)
-{
-       const struct parport_pc_private *priv = p->physport->private_data;
-       s->u.pc.ctr = inb (CONTROL (p));
-       if (priv->ecr)
-               s->u.pc.ecr = inb (ECONTROL (p));
-}
-
-void parport_pc_restore_state(struct parport *p, struct parport_state *s)
-{
-       const struct parport_pc_private *priv = p->physport->private_data;
-       outb (s->u.pc.ctr, CONTROL (p));
-       if (priv->ecr)
-               outb (s->u.pc.ecr, ECONTROL (p));
-}
-
-#ifdef CONFIG_PARPORT_1284
-static size_t parport_pc_epp_read_data (struct parport *port, void *buf,
-                                       size_t length, int flags)
-{
-       size_t got = 0;
-       for (; got < length; got++) {
-               *((char*)buf)++ = inb (EPPDATA(port));
-               if (inb (STATUS(port)) & 0x01) {
-                       clear_epp_timeout (port);
-                       break;
-               }
-       }
-
-       return got;
-}
-
-static size_t parport_pc_epp_write_data (struct parport *port, const void *buf,
-                                        size_t length, int flags)
-{
-       size_t written = 0;
-       for (; written < length; written++) {
-               outb (*((char*)buf)++, EPPDATA(port));
-               if (inb (STATUS(port)) & 0x01) {
-                       clear_epp_timeout (port);
-                       break;
-               }
-       }
-
-       return written;
-}
-
-static size_t parport_pc_epp_read_addr (struct parport *port, void *buf,
-                                       size_t length, int flags)
-{
-       size_t got = 0;
-       for (; got < length; got++) {
-               *((char*)buf)++ = inb (EPPADDR (port));
-               if (inb (STATUS (port)) & 0x01) {
-                       clear_epp_timeout (port);
-                       break;
-               }
-       }
-
-       return got;
-}
-
-static size_t parport_pc_epp_write_addr (struct parport *port,
-                                        const void *buf, size_t length,
-                                        int flags)
-{
-       size_t written = 0;
-       for (; written < length; written++) {
-               outb (*((char*)buf)++, EPPADDR (port));
-               if (inb (STATUS (port)) & 0x01) {
-                       clear_epp_timeout (port);
-                       break;
-               }
-       }
-
-       return written;
-}
-
-static size_t parport_pc_ecpepp_read_data (struct parport *port, void *buf,
-                                          size_t length, int flags)
-{
-       size_t got;
-
-       frob_econtrol (port, 0xe0, ECR_EPP << 5);
-       got = parport_pc_epp_read_data (port, buf, length, flags);
-       frob_econtrol (port, 0xe0, ECR_PS2 << 5);
-
-       return got;
-}
-
-static size_t parport_pc_ecpepp_write_data (struct parport *port,
-                                           const void *buf, size_t length,
-                                           int flags)
-{
-       size_t written;
-
-       frob_econtrol (port, 0xe0, ECR_EPP << 5);
-       written = parport_pc_epp_write_data (port, buf, length, flags);
-       frob_econtrol (port, 0xe0, ECR_PS2 << 5);
-
-       return written;
-}
-
-static size_t parport_pc_ecpepp_read_addr (struct parport *port, void *buf,
-                                          size_t length, int flags)
-{
-       size_t got;
-
-       frob_econtrol (port, 0xe0, ECR_EPP << 5);
-       got = parport_pc_epp_read_addr (port, buf, length, flags);
-       frob_econtrol (port, 0xe0, ECR_PS2 << 5);
-
-       return got;
-}
-
-static size_t parport_pc_ecpepp_write_addr (struct parport *port,
-                                           const void *buf, size_t length,
-                                           int flags)
-{
-       size_t written;
-
-       frob_econtrol (port, 0xe0, ECR_EPP << 5);
-       written = parport_pc_epp_write_addr (port, buf, length, flags);
-       frob_econtrol (port, 0xe0, ECR_PS2 << 5);
-
-       return written;
-}
-#endif /* IEEE 1284 support */
-
-#ifdef CONFIG_PARPORT_PC_FIFO
-static size_t parport_pc_fifo_write_block_pio (struct parport *port,
-                                              const void *buf, size_t length)
-{
-       int ret = 0;
-       const unsigned char *bufp = buf;
-       size_t left = length;
-       long expire = jiffies + port->physport->cad->timeout;
-       const int fifo = FIFO (port);
-       int poll_for = 8; /* 80 usecs */
-       const struct parport_pc_private *priv = port->physport->private_data;
-       const int fifo_depth = priv->fifo_depth;
-
-       port = port->physport;
-
-       /* We don't want to be interrupted every character. */
-       parport_pc_disable_irq (port);
-       frob_econtrol (port, (1<<4), (1<<4)); /* nErrIntrEn */
-
-       /* Forward mode. */
-       parport_pc_data_forward (port);
-
-       while (left) {
-               unsigned char byte;
-               unsigned char ecrval = inb (ECONTROL (port));
-               int i = 0;
-
-               if (current->need_resched && time_before (jiffies, expire))
-                       /* Can't yield the port. */
-                       schedule ();
-
-               /* Anyone else waiting for the port? */
-               if (port->waithead) {
-                       printk (KERN_DEBUG "Somebody wants the port\n");
-                       break;
-               }
-
-               if (ecrval & 0x02) {
-                       /* FIFO is full. Wait for interrupt. */
-
-                       /* Clear serviceIntr */
-                       outb (ecrval & ~(1<<2), ECONTROL (port));
-               false_alarm:
-                       ret = parport_wait_event (port, HZ);
-                       if (ret < 0) break;
-                       ret = 0;
-                       if (!time_before (jiffies, expire)) {
-                               /* Timed out. */
-                               printk (KERN_DEBUG "Timed out\n");
-                               break;
-                       }
-                       ecrval = inb (ECONTROL (port));
-                       if (!(ecrval & (1<<2))) {
-                               if (current->need_resched &&
-                                   time_before (jiffies, expire))
-                                       schedule ();
-
-                               goto false_alarm;
-                       }
-
-                       continue;
-               }
-
-               /* Can't fail now. */
-               expire = jiffies + port->cad->timeout;
-
-       poll:
-               if (signal_pending (current))
-                       break;
-
-               if (ecrval & 0x01) {
-                       /* FIFO is empty. Blast it full. */
-                       const int n = left < fifo_depth ? left : fifo_depth;
-                       outsb (fifo, bufp, n);
-                       bufp += n;
-                       left -= n;
-
-                       /* Adjust the poll time. */
-                       if (i < (poll_for - 2)) poll_for--;
-                       continue;
-               } else if (i++ < poll_for) {
-                       udelay (10);
-                       ecrval = inb (ECONTROL (port));
-                       goto poll;
-               }
-
-               /* Half-full (call me an optimist) */
-               byte = *bufp++;
-               outb (byte, fifo);
-               left--;
-        }
-
-       return length - left;
-}
-
-static size_t parport_pc_fifo_write_block_dma (struct parport *port,
-                                              const void *buf, size_t length)
-{
-       int ret = 0;
-       unsigned long dmaflag;
-       size_t left  = length;
-       const struct parport_pc_private *priv = port->physport->private_data;
-
-       port = port->physport;
-
-       /* We don't want to be interrupted every character. */
-       parport_pc_disable_irq (port);
-       frob_econtrol (port, (1<<4), (1<<4)); /* nErrIntrEn */
-
-       /* Forward mode. */
-       parport_pc_data_forward (port);
-
-       while (left) {
-               long expire = jiffies + port->physport->cad->timeout;
-
-               size_t count = left;
-
-               if (count > PAGE_SIZE)
-                       count = PAGE_SIZE;
-
-               memcpy(priv->dma_buf, buf, count);
-
-               dmaflag = claim_dma_lock();
-               disable_dma(port->dma);
-               clear_dma_ff(port->dma);
-               set_dma_mode(port->dma, DMA_MODE_WRITE);
-               set_dma_addr(port->dma, virt_to_bus((volatile char *) priv->dma_buf));
-               set_dma_count(port->dma, count);
-
-               /* Set DMA mode */
-               frob_econtrol (port, 1<<3, 1<<3);
-
-               /* Clear serviceIntr */
-               frob_econtrol (port, 1<<2, 0);
-
-               enable_dma(port->dma);
-               release_dma_lock(dmaflag);
-
-               /* assume DMA will be successful */
-               left -= count;
-               buf  += count;
-
-               /* Wait for interrupt. */
-       false_alarm:
-               ret = parport_wait_event (port, HZ);
-               if (ret < 0) break;
-               ret = 0;
-               if (!time_before (jiffies, expire)) {
-                       /* Timed out. */
-                       printk (KERN_DEBUG "Timed out\n");
-                       break;
-               }
-               /* Is serviceIntr set? */
-               if (!(inb (ECONTROL (port)) & (1<<2))) {
-                       if (current->need_resched)
-                               schedule ();
-
-                       goto false_alarm;
-               }
-
-               dmaflag = claim_dma_lock();
-               disable_dma(port->dma);
-               clear_dma_ff(port->dma);
-               count = get_dma_residue(port->dma);
-               release_dma_lock(dmaflag);
-
-               if (current->need_resched)
-                       /* Can't yield the port. */
-                       schedule ();
-
-               /* Anyone else waiting for the port? */
-               if (port->waithead) {
-                       printk (KERN_DEBUG "Somebody wants the port\n");
-                       break;
-               }
-
-               /* update for possible DMA residue ! */
-               buf  -= count;
-               left += count;
-       }
-
-       /* Maybe got here through break, so adjust for DMA residue! */
-       dmaflag = claim_dma_lock();
-       disable_dma(port->dma);
-       clear_dma_ff(port->dma);
-       left += get_dma_residue(port->dma);
-       release_dma_lock(dmaflag);
-
-       /* Turn off DMA mode */
-       frob_econtrol (port, 1<<3, 0);
-
-       return length - left;
-}
-
-/* Parallel Port FIFO mode (ECP chipsets) */
-size_t parport_pc_compat_write_block_pio (struct parport *port,
-                                         const void *buf, size_t length,
-                                         int flags)
-{
-       size_t written;
-
-       /* Special case: a timeout of zero means we cannot call schedule(). */
-       if (!port->physport->cad->timeout)
-               return parport_ieee1284_write_compat (port, buf,
-                                                     length, flags);
-
-       /* Set up parallel port FIFO mode.*/
-       change_mode (port, ECR_PPF); /* Parallel port FIFO */
-       parport_pc_data_forward (port);
-       port->physport->ieee1284.phase = IEEE1284_PH_FWD_DATA;
-
-       /* Write the data to the FIFO. */
-       if (port->dma != PARPORT_DMA_NONE)
-               written = parport_pc_fifo_write_block_dma (port, buf, length);
-       else
-               written = parport_pc_fifo_write_block_pio (port, buf, length);
-
-       /* Finish up. */
-       if (change_mode (port, ECR_PS2) == -EBUSY) {
-               const struct parport_pc_private *priv = 
-                       port->physport->private_data;
-
-               printk (KERN_DEBUG "%s: FIFO is stuck\n", port->name);
-
-               /* Prevent further data transfer. */
-               parport_frob_control (port,
-                                     PARPORT_CONTROL_STROBE,
-                                     PARPORT_CONTROL_STROBE);
-
-               /* Adjust for the contents of the FIFO. */
-               for (written -= priv->fifo_depth; ; written++) {
-                       if (inb (ECONTROL (port)) & 0x2)
-                               /* Full up. */
-                               break;
-
-                       outb (0, FIFO (port));
-               }
-
-               /* Reset the FIFO. */
-               frob_econtrol (port, 0xe0, 0);
-
-               /* De-assert strobe. */
-               parport_frob_control (port, PARPORT_CONTROL_STROBE, 0);
-       }
-
-       parport_wait_peripheral (port,
-                                PARPORT_STATUS_BUSY,
-                                PARPORT_STATUS_BUSY);
-       port->physport->ieee1284.phase = IEEE1284_PH_FWD_IDLE;
-
-       return written;
-}
-
-/* ECP */
-#ifdef CONFIG_PARPORT_1284
-size_t parport_pc_ecp_write_block_pio (struct parport *port,
-                                      const void *buf, size_t length,
-                                      int flags)
-{
-       size_t written;
-
-       /* Special case: a timeout of zero means we cannot call schedule(). */
-       if (!port->physport->cad->timeout)
-               return parport_ieee1284_ecp_write_data (port, buf,
-                                                       length, flags);
-
-       /* Switch to forward mode if necessary. */
-       if (port->physport->ieee1284.phase != IEEE1284_PH_FWD_IDLE) {
-               /* Event 47: Set nInit high. */
-               parport_frob_control (port, PARPORT_CONTROL_INIT, 0);
-
-               /* Event 40: PError goes high. */
-               parport_wait_peripheral (port,
-                                        PARPORT_STATUS_PAPEROUT,
-                                        PARPORT_STATUS_PAPEROUT);
-       }
-
-       /* Set up ECP parallel port mode.*/
-       change_mode (port, ECR_ECP); /* ECP FIFO */
-       parport_pc_data_forward (port);
-       port->physport->ieee1284.phase = IEEE1284_PH_FWD_DATA;
-
-       /* Write the data to the FIFO. */
-       if (port->dma != PARPORT_DMA_NONE)
-               written = parport_pc_fifo_write_block_dma (port, buf, length);
-       else
-               written = parport_pc_fifo_write_block_pio (port, buf, length);
-
-       /* Finish up. */
-       if (change_mode (port, ECR_PS2) == -EBUSY) {
-               const struct parport_pc_private *priv =
-                       port->physport->private_data;
-
-               printk (KERN_DEBUG "%s: FIFO is stuck\n", port->name);
-
-               /* Prevent further data transfer. */
-               parport_frob_control (port,
-                                     PARPORT_CONTROL_STROBE,
-                                     PARPORT_CONTROL_STROBE);
-
-               /* Adjust for the contents of the FIFO. */
-               for (written -= priv->fifo_depth; ; written++) {
-                       if (inb (ECONTROL (port)) & 0x2)
-                               /* Full up. */
-                               break;
-
-                       outb (0, FIFO (port));
-               }
-
-               /* Reset the FIFO. */
-               frob_econtrol (port, 0xe0, 0);
-               parport_frob_control (port, PARPORT_CONTROL_STROBE, 0);
-
-               /* Host transfer recovery. */
-               parport_frob_control (port,
-                                     PARPORT_CONTROL_INIT,
-                                     PARPORT_CONTROL_INIT);
-               parport_pc_data_reverse (port);
-               parport_wait_peripheral (port, PARPORT_STATUS_PAPEROUT, 0);
-               parport_frob_control (port, PARPORT_CONTROL_INIT, 0);
-               parport_wait_peripheral (port,
-                                        PARPORT_STATUS_PAPEROUT,
-                                        PARPORT_STATUS_PAPEROUT);
-       }
-
-       parport_wait_peripheral (port,
-                                PARPORT_STATUS_BUSY, 
-                                PARPORT_STATUS_BUSY);
-       port->physport->ieee1284.phase = IEEE1284_PH_FWD_IDLE;
-
-       return written;
-}
-
-size_t parport_pc_ecp_read_block_pio (struct parport *port,
-                                     void *buf, size_t length, int flags)
-{
-       size_t left = length;
-       size_t fifofull;
-       const int fifo = FIFO(port);
-       const struct parport_pc_private *priv = port->physport->private_data;
-       const int fifo_depth = priv->fifo_depth;
-       char *bufp = buf;
-
-       port = port->physport;
-
-       /* Special case: a timeout of zero means we cannot call schedule(). */
-       if (!port->cad->timeout)
-               return parport_ieee1284_ecp_read_data (port, buf,
-                                                      length, flags);
-
-       fifofull = fifo_depth;
-       if (port->ieee1284.mode == IEEE1284_MODE_ECPRLE)
-               /* If the peripheral is allowed to send RLE compressed
-                * data, it is possible for a byte to expand to 128
-                * bytes in the FIFO. */
-               fifofull = 128;
-
-       /* If the caller wants less than a full FIFO's worth of data,
-        * go through software emulation.  Otherwise we may have to through
-        * away data. */
-       if (length < fifofull)
-               return parport_ieee1284_ecp_read_data (port, buf,
-                                                      length, flags);
-
-       /* Switch to reverse mode if necessary. */
-       if (port->ieee1284.phase != IEEE1284_PH_REV_IDLE) {
-               /* Event 38: Set nAutoFd low */
-               parport_frob_control (port,
-                                     PARPORT_CONTROL_AUTOFD,
-                                     PARPORT_CONTROL_AUTOFD);
-               parport_pc_data_reverse (port);
-               udelay (5);
-
-               /* Event 39: Set nInit low to initiate bus reversal */
-               parport_frob_control (port,
-                                     PARPORT_CONTROL_INIT,
-                                     PARPORT_CONTROL_INIT);
-
-               /* Event 40: PError goes low */
-               parport_wait_peripheral (port, PARPORT_STATUS_PAPEROUT, 0);
-       }
-
-       /* Set up ECP parallel port mode.*/
-       change_mode (port, ECR_ECP); /* ECP FIFO */
-       parport_pc_data_reverse (port);
-       port->ieee1284.phase = IEEE1284_PH_REV_DATA;
-
-       /* Do the transfer. */
-       while (left > fifofull) {
-               int ret;
-               long int expire = jiffies + port->cad->timeout;
-               unsigned char ecrval = inb (ECONTROL (port));
-
-               if (current->need_resched && time_before (jiffies, expire))
-                       /* Can't yield the port. */
-                       schedule ();
-
-               /* At this point, the FIFO may already be full.
-                * Ideally, we'd be able to tell the port to hold on
-                * for a second while we empty the FIFO, and we'd be
-                * able to ensure that no data is lost.  I'm not sure
-                * that's the case. :-(  It might be that you can play
-                * games with STB, as in the forward case; someone should
-                * look at a datasheet. */
-
-               if (ecrval & 0x01) {
-                       /* FIFO is empty. Wait for interrupt. */
-
-                       /* Anyone else waiting for the port? */
-                       if (port->waithead) {
-                               printk (KERN_DEBUG
-                                       "Somebody wants the port\n");
-                               break;
-                       }
-
-                       /* Clear serviceIntr */
-                       outb (ecrval & ~(1<<2), ECONTROL (port));
-               false_alarm:
-                       ret = parport_wait_event (port, HZ);
-                       if (ret < 0) break;
-                       ret = 0;
-                       if (!time_before (jiffies, expire)) {
-                               /* Timed out. */
-                               printk (KERN_DEBUG "Timed out\n");
-                               break;
-                       }
-                       ecrval = inb (ECONTROL (port));
-                       if (!(ecrval & (1<<2))) {
-                               if (current->need_resched &&
-                                   time_before (jiffies, expire))
-                                       schedule ();
-
-                               goto false_alarm;
-                       }
-
-                       continue;
-               }
-
-               if (ecrval & 0x02) {
-                       /* FIFO is full. */
-                       insb (fifo, bufp, fifo_depth);
-                       bufp += fifo_depth;
-                       left -= fifo_depth;
-                       continue;
-               }
-
-               *bufp++ = inb (fifo);
-               left--;
-       }
-
-       /* Finish up. */
-       if (change_mode (port, ECR_PS2) == -EBUSY) {
-               int lost = get_fifo_residue (port);
-               printk (KERN_DEBUG "%s: DATA LOSS (%d bytes)!\n", port->name,
-                       lost);
-       }
-
-       port->ieee1284.phase = IEEE1284_PH_REV_IDLE;
-
-       return length - left;
-}
-
-#endif /* IEEE 1284 support */
-
-#endif /* Allowed to use FIFO/DMA */
-
-void parport_pc_inc_use_count(void)
-{
-#ifdef MODULE
-       MOD_INC_USE_COUNT;
-#endif
-}
-
-void parport_pc_dec_use_count(void)
-{
-#ifdef MODULE
-       MOD_DEC_USE_COUNT;
-#endif
-}
-
-static void parport_pc_fill_inode(struct inode *inode, int fill)
-{
-       /* Is this still needed? -tim */
-#ifdef MODULE
-       if (fill)
-               MOD_INC_USE_COUNT;
-       else
-               MOD_DEC_USE_COUNT;
-#endif
-}
-
-struct parport_operations parport_pc_ops = 
-{
-       parport_pc_write_data,
-       parport_pc_read_data,
-
-       parport_pc_write_control,
-       parport_pc_read_control,
-       parport_pc_frob_control,
-
-       parport_pc_read_status,
-
-       parport_pc_enable_irq,
-       parport_pc_disable_irq,
-
-       parport_pc_data_forward,
-       parport_pc_data_reverse,
-
-       parport_pc_interrupt,
-       parport_pc_init_state,
-       parport_pc_save_state,
-       parport_pc_restore_state,
-
-       parport_pc_inc_use_count,
-       parport_pc_dec_use_count,
-       parport_pc_fill_inode,
-
-       parport_ieee1284_epp_write_data,
-       parport_ieee1284_epp_read_data,
-       parport_ieee1284_epp_write_addr,
-       parport_ieee1284_epp_read_addr,
-
-       parport_ieee1284_ecp_write_data,
-       parport_ieee1284_ecp_read_data,
-       parport_ieee1284_ecp_write_addr,
-
-       parport_ieee1284_write_compat,
-       parport_ieee1284_read_nibble,
-       parport_ieee1284_read_byte,
-};
-
-/* --- Mode detection ------------------------------------- */
-
-/*
- * Checks for port existence, all ports support SPP MODE
- */
-static int __init parport_SPP_supported(struct parport *pb)
-{
-       unsigned char r, w;
-
-       /*
-        * first clear an eventually pending EPP timeout 
-        * I (sailer@ife.ee.ethz.ch) have an SMSC chipset
-        * that does not even respond to SPP cycles if an EPP
-        * timeout is pending
-        */
-       clear_epp_timeout(pb);
-
-       /* Do a simple read-write test to make sure the port exists. */
-       w = 0xc;
-       outb (w, CONTROL (pb));
-
-       /* Is there a control register that we can read from?  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 (CONTROL (pb));
-       if ((r & 0xf) == w) {
-               w = 0xe;
-               outb (w, CONTROL (pb));
-               r = inb (CONTROL (pb));
-               outb (0xc, CONTROL (pb));
-               if ((r & 0xf) == 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, 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;
-
-       return 0;
-}
-
-/* Check for ECR
- *
- * Old style XT ports alias io ports every 0x400, hence accessing ECR
- * on these cards actually accesses the CTR.
- *
- * Modern cards don't do this but reading from ECR will return 0xff
- * regardless of what is written here if the card does NOT support
- * ECP.
- *
- * We first check to see if ECR is the same as CTR.  If not, the low
- * two bits of ECR aren't writable, so we check by writing ECR and
- * reading it back to see if it's what we expect.
- */
-static int __init parport_ECR_present(struct parport *pb)
-{
-       struct parport_pc_private *priv = pb->private_data;
-       unsigned char r = 0xc;
-
-       priv->ecr = 0;
-       outb (r, CONTROL (pb));
-       if ((inb (ECONTROL (pb)) & 0x3) == (r & 0x3)) {
-               outb (r ^ 0x2, CONTROL (pb)); /* Toggle bit 1 */
-
-               r = inb (CONTROL (pb));
-               if ((inb (ECONTROL (pb)) & 0x2) == (r & 0x2))
-                       goto no_reg; /* Sure that no ECR register exists */
-       }
-       
-       if ((inb (ECONTROL (pb)) & 0x3 ) != 0x1)
-               goto no_reg;
-
-       outb (0x34, ECONTROL (pb));
-       if (inb (ECONTROL (pb)) != 0x35)
-               goto no_reg;
-
-       priv->ecr = 1;
-       outb (0xc, CONTROL (pb));
-       
-       /* Go to mode 000 */
-       frob_econtrol (pb, 0xe0, ECR_SPP << 5);
-
-       return 1;
-
- no_reg:
-       outb (0xc, CONTROL (pb));
-       return 0; 
-}
-
-#ifdef CONFIG_PARPORT_1284
-/* Detect PS/2 support.
- *
- * Bit 5 (0x20) sets the PS/2 data direction; setting this high
- * allows us to read data from the data lines.  In theory we would get back
- * 0xff but any peripheral attached to the port may drag some or all of the
- * lines down to zero.  So if we get back anything that isn't the contents
- * of the data register we deem PS/2 support to be present. 
- *
- * Some SPP ports have "half PS/2" ability - you can't turn off the line
- * drivers, but an external peripheral with sufficiently beefy drivers of
- * its own can overpower them and assert its own levels onto the bus, from
- * where they can then be read back as normal.  Ports with this property
- * and the right type of device attached are likely to fail the SPP test,
- * (as they will appear to have stuck bits) and so the fact that they might
- * be misdetected here is rather academic. 
- */
-
-static int __init parport_PS2_supported(struct parport *pb)
-{
-       int ok = 0;
-  
-       clear_epp_timeout(pb);
-
-       /* try to tri-state the buffer */
-       parport_pc_data_reverse (pb);
-       
-       parport_pc_write_data(pb, 0x55);
-       if (parport_pc_read_data(pb) != 0x55) ok++;
-
-       parport_pc_write_data(pb, 0xaa);
-       if (parport_pc_read_data(pb) != 0xaa) ok++;
-
-       /* cancel input mode */
-       parport_pc_data_forward (pb);
-
-       if (ok)
-               pb->modes |= PARPORT_MODE_TRISTATE;
-       else {
-               struct parport_pc_private *priv = pb->private_data;
-               priv->ctr_writable &= ~0x20;
-       }
-
-       return ok;
-}
-
-static int __init parport_ECP_supported(struct parport *pb)
-{
-       int i;
-       int config;
-       int pword;
-       struct parport_pc_private *priv = pb->private_data;
-
-       /* If there is no ECR, we have no hope of supporting ECP. */
-       if (!priv->ecr)
-               return 0;
-
-       /* Find out FIFO depth */
-       outb (ECR_SPP << 5, ECONTROL (pb)); /* Reset FIFO */
-       outb (ECR_TST << 5, ECONTROL (pb)); /* TEST FIFO */
-       for (i=0; i < 1024 && !(inb (ECONTROL (pb)) & 0x02); i++)
-               outb (0xaa, FIFO (pb));
-
-       /*
-        * Using LGS chipset it uses ECR register, but
-        * it doesn't support ECP or FIFO MODE
-        */
-       if (i == 1024) {
-               outb (ECR_SPP << 5, ECONTROL (pb));
-               return 0;
-       }
-
-       priv->fifo_depth = i;
-       printk (KERN_INFO "0x%lx: FIFO is %d bytes\n", pb->base, i);
-
-       /* Find out writeIntrThreshold */
-       frob_econtrol (pb, 1<<2, 1<<2);
-       frob_econtrol (pb, 1<<2, 0);
-       for (i = 1; i <= priv->fifo_depth; i++) {
-               inb (FIFO (pb));
-               udelay (50);
-               if (inb (ECONTROL (pb)) & (1<<2))
-                       break;
-       }
-
-       if (i <= priv->fifo_depth)
-               printk (KERN_INFO "0x%lx: writeIntrThreshold is %d\n",
-                       pb->base, i);
-       else
-               /* Number of bytes we know we can write if we get an
-                   interrupt. */
-               i = 0;
-
-       priv->writeIntrThreshold = i;
-
-       /* Find out readIntrThreshold */
-       frob_econtrol (pb, 0xe0, ECR_PS2 << 5); /* Reset FIFO */
-       parport_pc_data_reverse (pb);
-       frob_econtrol (pb, 0xe0, ECR_TST << 5); /* Test FIFO */
-       frob_econtrol (pb, 1<<2, 1<<2);
-       frob_econtrol (pb, 1<<2, 0);
-       for (i = 1; i <= priv->fifo_depth; i++) {
-               outb (0xaa, FIFO (pb));
-               if (inb (ECONTROL (pb)) & (1<<2))
-                       break;
-       }
-
-       if (i <= priv->fifo_depth)
-               printk (KERN_INFO "0x%lx: readIntrThreshold is %d\n",
-                       pb->base, i);
-       else
-               /* Number of bytes we can read if we get an interrupt. */
-               i = 0;
-
-       priv->readIntrThreshold = i;
-
-       outb (ECR_SPP << 5, ECONTROL (pb)); /* Reset FIFO */
-       outb (0xf4, ECONTROL (pb)); /* Configuration mode */
-       config = inb (FIFO (pb));
-       pword = (config >> 4) & 0x7;
-       switch (pword) {
-       case 0:
-               pword = 2;
-               printk (KERN_WARNING "0x%lx: Unsupported pword size!\n",
-                       pb->base);
-               break;
-       case 2:
-               pword = 4;
-               printk (KERN_WARNING "0x%lx: Unsupported pword size!\n",
-                       pb->base);
-               break;
-       default:
-               printk (KERN_WARNING "0x%lx: Unknown implementation ID\n",
-                       pb->base);
-               /* Assume 1 */
-       case 1:
-               pword = 1;
-       }
-       priv->pword = pword;
-       printk (KERN_DEBUG "0x%lx: PWord is %d bits\n", pb->base, 8 * pword);
-
-       config = inb (CONFIGB (pb));
-       printk (KERN_DEBUG "0x%lx: Interrupts are ISA-%s\n", pb->base,
-               config & 0x80 ? "Level" : "Pulses");
-
-       if (!(config & 0x40)) {
-               printk (KERN_WARNING "0x%lx: IRQ conflict!\n", pb->base);
-               pb->irq = PARPORT_IRQ_NONE;
-       }
-
-       /* Go back to mode 000 */
-       frob_econtrol (pb, 0xe0, ECR_SPP << 5);
-       pb->modes |= PARPORT_MODE_ECP;
-
-       return 1;
-}
-
-static int __init parport_ECPPS2_supported(struct parport *pb)
-{
-       const struct parport_pc_private *priv = pb->private_data;
-       int result;
-       unsigned char oecr;
-
-       if (!priv->ecr)
-               return 0;
-
-       oecr = inb (ECONTROL (pb));
-       outb (ECR_PS2 << 5, ECONTROL (pb));
-       
-       result = parport_PS2_supported(pb);
-
-       outb (oecr, ECONTROL (pb));
-       return result;
-}
-
-/* EPP mode detection  */
-
-static int __init parport_EPP_supported(struct parport *pb)
-{
-       const struct parport_pc_private *priv = pb->private_data;
-
-       /*
-        * Theory:
-        *      Bit 0 of STR is the EPP timeout bit, this bit is 0
-        *      when EPP is possible and is set high when an EPP timeout
-        *      occurs (EPP uses the HALT line to stop the CPU while it does
-        *      the byte transfer, an EPP timeout occurs if the attached
-        *      device fails to respond after 10 micro seconds).
-        *
-        *      This bit is cleared by either reading it (National Semi)
-        *      or writing a 1 to the bit (SMC, UMC, WinBond), others ???
-        *      This bit is always high in non EPP modes.
-        */
-
-       /* If EPP timeout bit clear then EPP available */
-       if (!clear_epp_timeout(pb))
-               return 0;  /* No way to clear timeout */
-
-       /* Check for Intel bug. */
-       if (priv->ecr) {
-               unsigned char i;
-               for (i = 0x00; i < 0x80; i += 0x20) {
-                       outb (i, ECONTROL (pb));
-                       if (clear_epp_timeout (pb))
-                               /* Phony EPP in ECP. */
-                               return 0;
-               }
-       }
-
-       pb->modes |= PARPORT_MODE_EPP;
-
-       /* Set up access functions to use EPP hardware. */
-       parport_pc_ops.epp_read_data = parport_pc_epp_read_data;
-       parport_pc_ops.epp_write_data = parport_pc_epp_write_data;
-       parport_pc_ops.epp_read_addr = parport_pc_epp_read_addr;
-       parport_pc_ops.epp_write_addr = parport_pc_epp_write_addr;
-
-       return 1;
-}
-
-static int __init parport_ECPEPP_supported(struct parport *pb)
-{
-       struct parport_pc_private *priv = pb->private_data;
-       int result;
-       unsigned char oecr;
-
-       if (!priv->ecr)
-               return 0;
-
-       oecr = inb (ECONTROL (pb));
-       /* Search for SMC style EPP+ECP mode */
-       outb (0x80, ECONTROL (pb));
-       
-       result = parport_EPP_supported(pb);
-
-       outb (oecr, ECONTROL (pb));
-
-       if (result) {
-               /* Set up access functions to use ECP+EPP hardware. */
-               parport_pc_ops.epp_read_data = parport_pc_ecpepp_read_data;
-               parport_pc_ops.epp_write_data = parport_pc_ecpepp_write_data;
-               parport_pc_ops.epp_read_addr = parport_pc_ecpepp_read_addr;
-               parport_pc_ops.epp_write_addr = parport_pc_ecpepp_write_addr;
-       }
-
-       return result;
-}
-
-#else /* No IEEE 1284 support */
-
-/* Don't bother probing for modes we know we won't use. */
-static int __init parport_PS2_supported(struct parport *pb) { return 0; }
-static int __init parport_ECP_supported(struct parport *pb) { return 0; }
-static int __init parport_EPP_supported(struct parport *pb) { return 0; }
-static int __init parport_ECPEPP_supported(struct parport *pb) { return 0; }
-static int __init parport_ECPPS2_supported(struct parport *pb) { return 0; }
-
-#endif /* No IEEE 1284 support */
-
-/* --- IRQ detection -------------------------------------- */
-
-/* Only if supports ECP mode */
-static int __init programmable_irq_support(struct parport *pb)
-{
-       int irq, intrLine;
-       unsigned char oecr = inb (ECONTROL (pb));
-       static const int lookup[8] = {
-               PARPORT_IRQ_NONE, 7, 9, 10, 11, 14, 15, 5
-       };
-
-       outb (ECR_CNF << 5, ECONTROL (pb)); /* Configuration MODE */
-
-       intrLine = (inb (CONFIGB (pb)) >> 3) & 0x07;
-       irq = lookup[intrLine];
-
-       outb (oecr, ECONTROL (pb));
-       return irq;
-}
-
-static int __init irq_probe_ECP(struct parport *pb)
-{
-       int i;
-       unsigned long irqs;
-
-       sti();
-       irqs = probe_irq_on();
-               
-       outb (ECR_SPP << 5, ECONTROL (pb)); /* Reset FIFO */
-       outb ((ECR_TST << 5) | 0x04, ECONTROL (pb));
-       outb (ECR_TST << 5, ECONTROL (pb));
-
-       /* If Full FIFO sure that writeIntrThreshold is generated */
-       for (i=0; i < 1024 && !(inb (ECONTROL (pb)) & 0x02) ; i++) 
-               outb (0xaa, FIFO (pb));
-               
-       pb->irq = probe_irq_off(irqs);
-       outb (ECR_SPP << 5, ECONTROL (pb));
-
-       if (pb->irq <= 0)
-               pb->irq = PARPORT_IRQ_NONE;
-
-       return pb->irq;
-}
-
-/*
- * This detection seems that only works in National Semiconductors
- * This doesn't work in SMC, LGS, and Winbond 
- */
-static int __init irq_probe_EPP(struct parport *pb)
-{
-#ifndef ADVANCED_DETECT
-       return PARPORT_IRQ_NONE;
-#else
-       int irqs;
-       unsigned char oecr;
-
-       if (pb->modes & PARPORT_MODE_PCECR)
-               oecr = inb (ECONTROL (pb));
-
-       sti();
-       irqs = probe_irq_on();
-
-       if (pb->modes & PARPORT_MODE_PCECR)
-               frob_econtrol (pb, 0x10, 0x10);
-       
-       clear_epp_timeout(pb);
-       parport_pc_frob_control (pb, 0x20, 0x20);
-       parport_pc_frob_control (pb, 0x10, 0x10);
-       clear_epp_timeout(pb);
-
-       /* Device isn't expecting an EPP read
-        * and generates an IRQ.
-        */
-       parport_pc_read_epp(pb);
-       udelay(20);
-
-       pb->irq = probe_irq_off (irqs);
-       if (pb->modes & PARPORT_MODE_PCECR)
-               outb (oecr, ECONTROL (pb));
-       parport_pc_write_control(pb, 0xc);
-
-       if (pb->irq <= 0)
-               pb->irq = PARPORT_IRQ_NONE;
-
-       return pb->irq;
-#endif /* Advanced detection */
-}
-
-static int __init irq_probe_SPP(struct parport *pb)
-{
-       /* Don't even try to do this. */
-       return PARPORT_IRQ_NONE;
-}
-
-/* We will attempt to share interrupt requests since other devices
- * such as sound cards and network cards seem to like using the
- * printer IRQs.
- *
- * When ECP is available we can autoprobe for IRQs.
- * NOTE: If we can autoprobe it, we can register the IRQ.
- */
-static int __init parport_irq_probe(struct parport *pb)
-{
-       const struct parport_pc_private *priv = pb->private_data;
-
-       if (priv->ecr) {
-               pb->irq = programmable_irq_support(pb);
-               if (pb->irq != PARPORT_IRQ_NONE)
-                       goto out;
-       }
-
-       if (pb->modes & PARPORT_MODE_ECP)
-               pb->irq = irq_probe_ECP(pb);
-
-       if (pb->irq == PARPORT_IRQ_NONE && priv->ecr &&
-           (pb->modes & PARPORT_MODE_EPP))
-               pb->irq = irq_probe_EPP(pb);
-
-       clear_epp_timeout(pb);
-
-       if (pb->irq == PARPORT_IRQ_NONE && (pb->modes & PARPORT_MODE_EPP))
-               pb->irq = irq_probe_EPP(pb);
-
-       clear_epp_timeout(pb);
-
-       if (pb->irq == PARPORT_IRQ_NONE)
-               pb->irq = irq_probe_SPP(pb);
-
-out:
-       return pb->irq;
-}
-
-/* --- DMA detection -------------------------------------- */
-
-/* Only if supports ECP mode */
-static int __init programmable_dma_support (struct parport *p)
-{
-       unsigned char oecr = inb (ECONTROL (p));
-       int dma;
-
-       frob_econtrol (p, 0xe0, ECR_CNF << 5);
-       
-       dma = inb (CONFIGB(p)) & 0x03;
-       if (!dma)
-               dma = PARPORT_DMA_NONE;
-
-       outb (oecr, ECONTROL (p));
-       return dma;
-}
-
-static int __init parport_dma_probe (struct parport *p)
-{
-       const struct parport_pc_private *priv = p->private_data;
-       if (priv->ecr)
-               p->dma = programmable_dma_support(p);
-
-       return p->dma;
-}
-
-/* --- Initialisation code -------------------------------- */
-
-static int __init probe_one_port(unsigned long int base,
-                                unsigned long int base_hi,
-                                int irq, int dma)
-{
-       struct parport_pc_private *priv;
-       struct parport tmp;
-       struct parport *p = &tmp;
-       int probedirq = PARPORT_IRQ_NONE;
-       if (check_region(base, 3)) return 0;
-       priv = kmalloc (sizeof (struct parport_pc_private), GFP_KERNEL);
-       if (!priv) {
-               printk (KERN_DEBUG "parport (0x%lx): no memory!\n", base);
-               return 0;
-       }
-       priv->ctr = 0xc;
-       priv->ctr_writable = 0xff;
-       priv->ecr = 0;
-       priv->fifo_depth = 0;
-       priv->dma_buf = 0;
-       p->base = base;
-       p->base_hi = base_hi;
-       p->irq = irq;
-       p->dma = dma;
-       p->modes = PARPORT_MODE_PCSPP;
-       p->ops = &parport_pc_ops;
-       p->private_data = priv;
-       p->physport = p;
-       if (base_hi && !check_region(base_hi,3)) {
-               parport_ECR_present(p);
-               parport_ECP_supported(p);
-               parport_ECPPS2_supported(p);
-       }
-       if (base != 0x3bc) {
-               if (!check_region(base+0x3, 5)) {
-                       parport_EPP_supported(p);
-                       if (!(p->modes & PARPORT_MODE_EPP))
-                               parport_ECPEPP_supported(p);
-               }
-       }
-       if (!parport_SPP_supported (p)) {
-               /* No port. */
-               kfree (priv);
-               return 0;
-       }
-
-       parport_PS2_supported (p);
-
-       if (!(p = parport_register_port(base, PARPORT_IRQ_NONE,
-                                                                       PARPORT_DMA_NONE, &parport_pc_ops))) {
-               kfree (priv);
-               return 0;
-       }
-
-       p->base_hi = base_hi;
-       p->modes = tmp.modes;
-       p->size = (p->modes & PARPORT_MODE_EPP)?8:3;
-       p->private_data = priv;
-
-       printk(KERN_INFO "%s: PC-style at 0x%lx", p->name, p->base);
-       if (p->base_hi && (p->modes & PARPORT_MODE_ECP))
-               printk(" (0x%lx)", p->base_hi);
-       p->irq = irq;
-       p->dma = dma;
-       if (p->irq == PARPORT_IRQ_AUTO) {
-               p->irq = PARPORT_IRQ_NONE;
-               parport_irq_probe(p);
-       } else if (p->irq == PARPORT_IRQ_PROBEONLY) {
-               p->irq = PARPORT_IRQ_NONE;
-               parport_irq_probe(p);
-               probedirq = p->irq;
-               p->irq = PARPORT_IRQ_NONE;
-       }
-       if (p->irq != PARPORT_IRQ_NONE) {
-               printk(", irq %d", p->irq);
-
-               if (p->dma == PARPORT_DMA_AUTO) {
-                       p->dma = PARPORT_DMA_NONE;
-                       parport_dma_probe(p);
-               }
-       }
-       if (p->dma == PARPORT_DMA_AUTO)         
-               p->dma = PARPORT_DMA_NONE;
-       if (p->dma != PARPORT_DMA_NONE) 
-               printk(", dma %d", p->dma);
-
-#ifdef CONFIG_PARPORT_PC_FIFO
-       if (priv->fifo_depth > 0 && p->irq != PARPORT_IRQ_NONE) {
-               parport_pc_ops.compat_write_data =
-                       parport_pc_compat_write_block_pio;
-#ifdef CONFIG_PARPORT_1284
-               parport_pc_ops.ecp_write_data =
-                       parport_pc_ecp_write_block_pio;
-#endif /* IEEE 1284 support */
-               if (p->dma != PARPORT_DMA_NONE)
-                       p->modes |= PARPORT_MODE_DMA;
-               printk(", using FIFO");
-       }
-#endif /* Allowed to use FIFO/DMA */
-
-       printk(" [");
-#define printmode(x) {if(p->modes&PARPORT_MODE_##x){printk("%s%s",f?",":"",#x);f++;}}
-       {
-               int f = 0;
-               printmode(PCSPP);
-               printmode(TRISTATE);
-               printmode(COMPAT)
-               printmode(EPP);
-               printmode(ECP);
-               printmode(DMA);
-       }
-#undef printmode
-       printk("]\n");
-       if (probedirq != PARPORT_IRQ_NONE) 
-               printk("%s: irq %d detected\n", p->name, probedirq);
-       parport_proc_register(p);
-
-       request_region (p->base, 3, p->name);
-       if (p->size > 3)
-               request_region (p->base + 3, p->size - 3, p->name);
-       if (p->modes & PARPORT_MODE_ECP)
-               request_region (p->base_hi, 3, p->name);
-
-       if (p->irq != PARPORT_IRQ_NONE) {
-               if (request_irq (p->irq, parport_pc_interrupt,
-                                0, p->name, p)) {
-                       printk (KERN_WARNING "%s: irq %d in use, "
-                               "resorting to polled operation\n",
-                               p->name, p->irq);
-                       p->irq = PARPORT_IRQ_NONE;
-                       p->dma = PARPORT_DMA_NONE;
-               }
-
-               if (p->dma != PARPORT_DMA_NONE) {
-                       if (request_dma (p->dma, p->name)) {
-                               printk (KERN_WARNING "%s: dma %d in use, "
-                                       "resorting to PIO operation\n",
-                                       p->name, p->dma);
-                               p->dma = PARPORT_DMA_NONE;
-                       } else {
-                               priv->dma_buf = (char *) __get_dma_pages(GFP_KERNEL, 1);
-                               if (! priv->dma_buf) {
-                                       printk (KERN_WARNING "%s: "
-                                               "cannot get buffer for DMA, "
-                                               "resorting to PIO operation\n",
-                                               p->name);
-                                       free_dma(p->dma);
-                                       p->dma = PARPORT_DMA_NONE;
-                               }
-                       }
-               }
-       }
-
-       /* Done probing.  Now put the port into a sensible start-up state.
-        * SELECT | INIT also puts IEEE1284-compliant devices into
-        * compatibility mode. */
-       if (p->modes & PARPORT_MODE_ECP)
-               /*
-                * Put the ECP detected port in PS2 mode.
-                */
-               outb (0x24, ECONTROL (p));
-
-       parport_pc_write_data(p, 0);
-       parport_pc_data_forward (p);
-       parport_pc_write_control(p, PARPORT_CONTROL_SELECT);
-       udelay (50);
-       parport_pc_write_control(p,
-                                PARPORT_CONTROL_SELECT
-                                | PARPORT_CONTROL_INIT);
-       udelay (50);
-
-       /* Now that we've told the sharing engine about the port, and
-          found out its characteristics, let the high-level drivers
-          know about it. */
-       parport_announce_port (p);
-
-       return 1;
-}
-
-/* Look for PCI parallel port cards. */
-static int __init parport_pc_init_pci (int irq, int dma)
-{
-/* These need to go in pci.h: */
-#ifndef PCI_VENDOR_ID_SIIG
-#define PCI_VENDOR_ID_SIIG              0x131f
-#define PCI_DEVICE_ID_SIIG_1S1P_10x_550 0x1010
-#define PCI_DEVICE_ID_SIIG_1S1P_10x_650 0x1011
-#define PCI_DEVICE_ID_SIIG_1S1P_10x_850 0x1012
-#define PCI_DEVICE_ID_SIIG_1P_10x       0x1020
-#define PCI_DEVICE_ID_SIIG_2P_10x       0x1021
-#define PCI_DEVICE_ID_SIIG_2S1P_10x_550 0x1034
-#define PCI_DEVICE_ID_SIIG_2S1P_10x_650 0x1035
-#define PCI_DEVICE_ID_SIIG_2S1P_10x_850 0x1036
-#define PCI_DEVICE_ID_SIIG_1P_20x       0x2020
-#define PCI_DEVICE_ID_SIIG_2P_20x       0x2021
-#define PCI_DEVICE_ID_SIIG_2P1S_20x_550 0x2040
-#define PCI_DEVICE_ID_SIIG_2P1S_20x_650 0x2041
-#define PCI_DEVICE_ID_SIIG_2P1S_20x_850 0x2042
-#define PCI_DEVICE_ID_SIIG_1S1P_20x_550 0x2010
-#define PCI_DEVICE_ID_SIIG_1S1P_20x_650 0x2011
-#define PCI_DEVICE_ID_SIIG_1S1P_20x_850 0x2012
-#define PCI_DEVICE_ID_SIIG_2S1P_20x_550 0x2060
-#define PCI_DEVICE_ID_SIIG_2S1P_20x_650 0x2061
-#define PCI_DEVICE_ID_SIIG_2S1P_20x_850 0x2062
-#define PCI_VENDOR_ID_LAVA              0x1407
-#define PCI_DEVICE_ID_LAVA_PARALLEL     0x8000
-#define PCI_DEVICE_ID_LAVA_DUAL_PAR_A   0x8001 /* The Lava Dual Parallel is */
-#define PCI_DEVICE_ID_LAVA_DUAL_PAR_B   0x8002 /* two PCI devices on a card */
-#endif
-
-       struct {
-               unsigned int vendor;
-               unsigned int device;
-               unsigned int numports;
-               struct {
-                       unsigned int lo;
-                       unsigned int hi; /* -ve if not there */
-               } addr[4];
-       } cards[] = {
-               { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_550, 1,
-                 { { 3, 4 }, } },
-               { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_650, 1,
-                 { { 3, 4 }, } },
-               { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_850, 1,
-                 { { 3, 4 }, } },
-               { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1P_10x, 1,
-                 { { 2, 3 }, } },
-               { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P_10x, 2,
-                 { { 2, 3 }, { 4, 5 }, } },
-               { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_550, 1,
-                 { { 4, 5 }, } },
-               { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_650, 1,
-                 { { 4, 5 }, } },
-               { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_850, 1,
-                 { { 4, 5 }, } },
-               { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1P_20x, 1,
-                 { { 0, 1 }, } },
-               { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P_20x, 2,
-                 { { 0, 1 }, { 2, 3 }, } },
-               { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_550, 2,
-                 { { 1, 2 }, { 3, 4 }, } },
-               { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_650, 2,
-                 { { 1, 2 }, { 3, 4 }, } },
-               { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_850, 2,
-                 { { 1, 2 }, { 3, 4 }, } },
-               { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_550, 1,
-                 { { 1, 2 }, } },
-               { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_650, 1,
-                 { { 1, 2 }, } },
-               { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_850, 1,
-                 { { 1, 2 }, } },
-               { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_550, 1,
-                 { { 2, 3 }, } },
-               { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_650, 1,
-                 { { 2, 3 }, } },
-               { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_850, 1,
-                 { { 2, 3 }, } },
-               { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_PARALLEL, 1,
-                 { { 0, -1 }, } },
-               { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_DUAL_PAR_A, 1,
-                 { { 0, -1 }, } },
-               { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_DUAL_PAR_B, 1,
-                 { { 0, -1 }, } },
-               { 0, }
-       };
-
-       int count = 0;
-       int i;
-
-       if (!pci_present ())
-               return 0;
-
-       for (i = 0; cards[i].vendor; i++) {
-               struct pci_dev *pcidev = NULL;
-               while ((pcidev = pci_find_device (cards[i].vendor,
-                                                 cards[i].device,
-                                                 pcidev)) != NULL) {
-                       int n;
-                       for (n = 0; n < cards[i].numports; n++) {
-                               int lo = cards[i].addr[n].lo;
-                               int hi = cards[i].addr[n].hi;
-                               int io_lo = pcidev->base_address[lo];
-                               int io_hi = ((hi < 0) ? 0 :
-                                            pcidev->base_address[hi]);
-                               io_lo &= PCI_BASE_ADDRESS_IO_MASK;
-                               io_hi &= PCI_BASE_ADDRESS_IO_MASK;
-                               count += probe_one_port (io_lo, io_hi,
-                                                        irq, dma);
-                       }
-               }
-       }
-
-       return count;
-}
-
-int __init parport_pc_init(int *io, int *io_hi, int *irq, int *dma)
-{
-       int count = 0, i = 0;
-       if (io && *io) {
-               /* Only probe the ports we were given. */
-               user_specified = 1;
-               do {
-                       if (!*io_hi) *io_hi = 0x400 + *io;
-                       count += probe_one_port(*(io++), *(io_hi++),
-                                               *(irq++), *(dma++));
-               } while (*io && (++i < PARPORT_PC_MAX_PORTS));
-       } else {
-               /* Probe all the likely ports. */
-               count += probe_one_port(0x3bc, 0x7bc, irq[0], dma[0]);
-               count += probe_one_port(0x378, 0x778, irq[0], dma[0]);
-               count += probe_one_port(0x278, 0x678, irq[0], dma[0]);
-               count += parport_pc_init_pci (irq[0], dma[0]);
-       }
-
-       return count;
-}
-
-#ifdef MODULE
-static int io[PARPORT_PC_MAX_PORTS+1] = { [0 ... PARPORT_PC_MAX_PORTS] = 0 };
-static int io_hi[PARPORT_PC_MAX_PORTS+1] = { [0 ... PARPORT_PC_MAX_PORTS] = 0 };
-static int dmaval[PARPORT_PC_MAX_PORTS] = { [0 ... PARPORT_PC_MAX_PORTS-1] = PARPORT_DMA_AUTO };
-static int irqval[PARPORT_PC_MAX_PORTS] = { [0 ... PARPORT_PC_MAX_PORTS-1] = PARPORT_IRQ_PROBEONLY };
-static const char *irq[PARPORT_PC_MAX_PORTS] = { NULL, };
-static const char *dma[PARPORT_PC_MAX_PORTS] = { NULL, };
-MODULE_PARM(io, "1-" __MODULE_STRING(PARPORT_PC_MAX_PORTS) "i");
-MODULE_PARM(io_hi, "1-" __MODULE_STRING(PARPORT_PC_MAX_PORTS) "i");
-MODULE_PARM(irq, "1-" __MODULE_STRING(PARPORT_PC_MAX_PORTS) "s");
-MODULE_PARM(dma, "1-" __MODULE_STRING(PARPORT_PC_MAX_PORTS) "s");
-
-int init_module(void)
-{      
-       /* Work out how many ports we have, then get parport_share to parse
-          the irq values. */
-       unsigned int i;
-       for (i = 0; i < PARPORT_PC_MAX_PORTS && io[i]; i++);
-       if (i) {
-               if (parport_parse_irqs(i, irq, irqval)) return 1;
-               if (parport_parse_dmas(i, dma, dmaval)) return 1;
-       }
-       else {
-               /* The user can make us use any IRQs or DMAs we find. */
-               int val;
-
-               if (irq[0] && !parport_parse_irqs (1, irq, &val))
-                       switch (val) {
-                       case PARPORT_IRQ_NONE:
-                       case PARPORT_IRQ_AUTO:
-                               irqval[0] = val;
-                       }
-
-               if (dma[0] && !parport_parse_dmas (1, dma, &val))
-                       switch (val) {
-                       case PARPORT_DMA_NONE:
-                       case PARPORT_DMA_AUTO:
-                               dmaval[0] = val;
-                       }
-       }
-
-       return (parport_pc_init(io, io_hi, irqval, dmaval)?0:1);
-}
-
-void cleanup_module(void)
-{
-       struct parport *p = parport_enumerate(), *tmp;
-       while (p) {
-               tmp = p->next;
-               if (p->modes & PARPORT_MODE_PCSPP) { 
-                       struct parport_pc_private *priv = p->private_data;
-                       if (p->dma != PARPORT_DMA_NONE)
-                               free_dma(p->dma);
-                       if (p->irq != PARPORT_IRQ_NONE)
-                               free_irq(p->irq, p);
-                       release_region(p->base, 3);
-                       if (p->size > 3);
-                               release_region(p->base + 3, p->size - 3);
-                       if (p->modes & PARPORT_MODE_ECP)
-                               release_region(p->base_hi, 3);
-                       parport_proc_unregister(p);
-                       if (priv->dma_buf)
-                               free_page((unsigned long) priv->dma_buf);
-                       kfree (p->private_data);
-                       parport_unregister_port(p);
-               }
-               p = tmp;
-       }
-}
-#endif
diff --git a/drivers/misc/parport_probe.c b/drivers/misc/parport_probe.c
deleted file mode 100644 (file)
index a3c24c9..0000000
+++ /dev/null
@@ -1,212 +0,0 @@
-/* $Id: parport_probe.c,v 1.1 1999/07/03 08:56:17 davem Exp $
- * Parallel port device probing code
- *
- * Authors:    Carsten Gross, carsten@sol.wohnheim.uni-ulm.de
- *             Philip Blundell <Philip.Blundell@pobox.com>
- */
-
-#include <linux/parport.h>
-#include <linux/ctype.h>
-#include <asm/uaccess.h>
-
-static struct {
-       char *token;
-       char *descr;
-} classes[] = {
-       { "",            "Legacy device" },
-       { "PRINTER",     "Printer" },
-       { "MODEM",       "Modem" },
-       { "NET",         "Network device" },
-       { "HDC",         "Hard disk" },
-       { "PCMCIA",      "PCMCIA" },
-       { "MEDIA",       "Multimedia device" },
-       { "FDC",         "Floppy disk" },
-       { "PORTS",       "Ports" },
-       { "SCANNER",     "Scanner" },
-       { "DIGICAM",     "Digital camera" },
-       { "",            "Unknown device" },
-       { "",            "Unspecified" },
-       { "SCSIADAPTER", "SCSI adapter" },
-       { NULL,          NULL }
-};
-
-static void pretty_print(struct parport *port, int device)
-{
-       struct parport_device_info *info = &port->probe_info[device + 1];
-
-       printk(KERN_INFO "%s", port->name);
-
-       if (device >= 0)
-               printk (" (addr %d)", device);
-
-       printk (": %s", classes[info->class].descr);
-       if (info->class)
-               printk(", %s %s", info->mfr, info->model);
-
-       printk("\n");
-}
-
-static char *strdup(char *str)
-{
-       int n = strlen(str)+1;
-       char *s = kmalloc(n, GFP_KERNEL);
-       if (!s) return NULL;
-       return strcpy(s, str);
-}
-
-static void parse_data(struct parport *port, int device, char *str)
-{
-       char *txt = kmalloc(strlen(str)+1, GFP_KERNEL);
-       char *p = txt, *q;
-       int guessed_class = PARPORT_CLASS_UNSPEC;
-       struct parport_device_info *info = &port->probe_info[device + 1];
-
-       if (!txt) {
-               printk("%s probe: memory squeeze\n", port->name);
-               return;
-       }
-       strcpy(txt, str);
-       while (p) {
-               char *sep;
-               q = strchr(p, ';');
-               if (q) *q = 0;
-               sep = strchr(p, ':');
-               if (sep) {
-                       char *u = p;
-                       *(sep++) = 0;
-                       while (*u) {
-                               *u = toupper(*u);
-                               u++;
-                       }
-                       if (!strcmp(p, "MFG") || !strcmp(p, "MANUFACTURER")) {
-                               if (info->mfr)
-                                       kfree (info->mfr);
-                               info->mfr = strdup(sep);
-                       } else if (!strcmp(p, "MDL") || !strcmp(p, "MODEL")) {
-                               if (info->model)
-                                       kfree (info->model);
-                               info->model = strdup(sep);
-                       } else if (!strcmp(p, "CLS") || !strcmp(p, "CLASS")) {
-                               int i;
-                               if (info->class_name)
-                                       kfree (info->class_name);
-                               info->class_name = strdup(sep);
-                               for (u = sep; *u; u++)
-                                       *u = toupper(*u);
-                               for (i = 0; classes[i].token; i++) {
-                                       if (!strcmp(classes[i].token, sep)) {
-                                               info->class = i;
-                                               goto rock_on;
-                                       }
-                               }
-                               printk(KERN_WARNING "%s probe: warning, class '%s' not understood.\n", port->name, sep);
-                               info->class = PARPORT_CLASS_OTHER;
-                       } else if (!strcmp(p, "CMD") ||
-                                  !strcmp(p, "COMMAND SET")) {
-                               if (info->cmdset)
-                                       kfree (info->cmdset);
-                               info->cmdset = strdup(sep);
-                               /* if it speaks printer language, it's
-                                  probably a printer */
-                               if (strstr(sep, "PJL") || strstr(sep, "PCL"))
-                                       guessed_class = PARPORT_CLASS_PRINTER;
-                       } else if (!strcmp(p, "DES") || !strcmp(p, "DESCRIPTION")) {
-                               if (info->description)
-                                       kfree (info->description);
-                               info->description = strdup(sep);
-                       }
-               }
-       rock_on:
-               if (q) p = q+1; else p=NULL;
-       }
-
-       /* If the device didn't tell us its class, maybe we have managed to
-          guess one from the things it did say. */
-       if (info->class == PARPORT_CLASS_UNSPEC)
-               info->class = guessed_class;
-
-       pretty_print (port, device);
-
-       kfree(txt);
-}
-
-/* Get Std 1284 Device ID. */
-ssize_t parport_device_id (int devnum, char *buffer, size_t len)
-{
-       ssize_t retval = -ENXIO;
-       struct pardevice *dev = parport_open (devnum, "Device ID probe",
-                                             NULL, NULL, NULL, 0, NULL);
-       if (!dev)
-               return -ENXIO;
-
-       parport_claim_or_block (dev);
-
-       /* Negotiate to compatibility mode, and then to device ID mode.
-        * (This is in case we are already in device ID mode.) */
-       parport_negotiate (dev->port, IEEE1284_MODE_COMPAT);
-       retval = parport_negotiate (dev->port,
-                                   IEEE1284_MODE_NIBBLE | IEEE1284_DEVICEID);
-
-       if (!retval) {
-               int idlen;
-               unsigned char length[2];
-               mm_segment_t oldfs = get_fs ();
-               set_fs (get_ds ());
-
-               /* First two bytes are MSB,LSB of inclusive length. */
-               retval = parport_read (dev->port, length, 2);
-
-               if (retval != 2) goto restore_fs;
-
-               idlen = (length[0] << 8) + length[1] - 2;
-               if (idlen < len)
-                       len = idlen;
-               retval = parport_read (dev->port, buffer, len);
-
-               if (retval != len) {
-                       printk (KERN_DEBUG "%s: only read %d of %d ID bytes\n",
-                               dev->port->name, retval, len);
-                       goto restore_fs;
-               }
-
-               /* Some printer manufacturers mistakenly believe that
-                   the length field is supposed to be _exclusive_. */
-               /* In addition, there are broken devices out there
-                   that don't even finish off with a semi-colon. */
-               if (idlen == len && buffer[len - 1] != ';') {
-                       ssize_t diff;
-                       diff = parport_read (dev->port, buffer + len, 2);
-                       retval += diff;
-
-                       if (diff)
-                               printk (KERN_DEBUG
-                                       "%s: device reported incorrect "
-                                       "length field (%d, should be %d)\n",
-                                       dev->port->name, idlen, retval);
-                       else {
-                               /* One semi-colon short of a device ID. */
-                               buffer[len++] = ';';
-                               buffer[len] = '\0';
-                               printk (KERN_DEBUG "%s: faking semi-colon\n",
-                                       dev->port->name);
-
-                               /* If we get here, I don't think we
-                                   need to worry about the possible
-                                   standard violation of having read
-                                   more than we were told to.  The
-                                   device is non-compliant anyhow. */
-                       }
-               }
-
-       restore_fs:
-               set_fs (oldfs);
-               parport_negotiate (dev->port, IEEE1284_MODE_COMPAT);
-       }
-       parport_release (dev);
-
-       if (retval > 0)
-               parse_data (dev->port, dev->daisy, buffer);
-
-       parport_close (dev);
-       return retval;
-}
diff --git a/drivers/misc/parport_procfs.c b/drivers/misc/parport_procfs.c
deleted file mode 100644 (file)
index 0c7be43..0000000
+++ /dev/null
@@ -1,434 +0,0 @@
-/* Sysctl interface for parport devices.
- * 
- * Authors: David Campbell <campbell@torque.net>
- *          Tim Waugh <tim@cyberelk.demon.co.uk>
- *          Philip Blundell <philb@gnu.org>
- *          Andrea Arcangeli
- *          Riccardo Facchetti <fizban@tin.it>
- *
- * based on work by Grant Guenther <grant@torque.net>
- *              and Philip Blundell
- *
- * Cleaned up include files - Russell King <linux@arm.uk.linux.org>
- */
-
-#include <linux/string.h>
-#include <linux/config.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/malloc.h>
-#include <linux/parport.h>
-#include <linux/ctype.h>
-#include <linux/sysctl.h>
-
-#include <asm/uaccess.h>
-
-#ifdef CONFIG_SYSCTL
-
-
-static int do_active_device(ctl_table *table, int write, struct file *filp,
-                     void *result, size_t *lenp)
-{
-       struct parport *port = (struct parport *)table->extra1;
-       char buffer[256];
-       struct pardevice *dev;
-       int len = 0;
-
-       if (write)              /* can't happen anyway */
-               return -EACCES;
-
-       if (filp->f_pos) {
-               *lenp = 0;
-               return 0;
-       }
-       
-       for (dev = port->devices; dev ; dev = dev->next) {
-               if(dev == port->cad) {
-                       len += sprintf(buffer, "%s\n", dev->name);
-               }
-       }
-
-       if(!len) {
-               len += sprintf(buffer, "%s\n", "none");
-       }
-
-       if (len > *lenp)
-               len = *lenp;
-       else
-               *lenp = len;
-
-       filp->f_pos += len;
-
-       return copy_to_user(result, buffer, len) ? -EFAULT : 0;
-}
-
-#ifdef CONFIG_PARPORT_1284
-static int do_autoprobe(ctl_table *table, int write, struct file *filp,
-                       void *result, size_t *lenp)
-{
-       struct parport_device_info *info = table->extra2;
-       const char *str;
-       char buffer[256];
-       int len = 0;
-
-       if (write) /* permissions stop this */
-               return -EACCES;
-
-       if (filp->f_pos) {
-               *lenp = 0;
-               return 0;
-       }
-       
-       if ((str = info->class_name) != NULL)
-               len += sprintf (buffer + len, "CLASS:%s;\n", str);
-
-       if ((str = info->model) != NULL)
-               len += sprintf (buffer + len, "MODEL:%s;\n", str);
-
-       if ((str = info->mfr) != NULL)
-               len += sprintf (buffer + len, "MANUFACTURER:%s;\n", str);
-
-       if ((str = info->description) != NULL)
-               len += sprintf (buffer + len, "DESCRIPTION:%s;\n", str);
-
-       if ((str = info->cmdset) != NULL)
-               len += sprintf (buffer + len, "COMMAND SET:%s;\n", str);
-
-       if (len > *lenp)
-               len = *lenp;
-       else
-               *lenp = len;
-
-       filp->f_pos += len;
-
-       return copy_to_user (result, buffer, len) ? -EFAULT : 0;
-}
-#endif /* IEEE1284.3 support. */
-
-static int do_hardware(ctl_table *table, int write, struct file *filp,
-                      void *result, size_t *lenp)
-{
-       struct parport *port = (struct parport *)table->extra1;
-       char buffer[256];
-       int len = 0;
-
-       if (filp->f_pos) {
-               *lenp = 0;
-               return 0;
-       }
-       
-       if (write)              /* can't happen anyway */
-               return -EACCES;
-       
-       len += sprintf(buffer+len, "base:\t0x%lx", port->base);
-       if (port->base_hi)
-               len += sprintf(buffer+len, " (0x%lx)", port->base_hi);
-       buffer[len++] = '\n';
-
-       if (port->irq == PARPORT_IRQ_NONE) {
-               len += sprintf(buffer+len, "irq:\tnone\n");
-       } else {
-#ifdef __sparc__
-               len += sprintf(buffer+len, "irq:\t%s\n", 
-                              __irq_itoa(port->irq));
-#else
-               len += sprintf(buffer+len, "irq:\t%d\n", port->irq);
-#endif
-       }
-
-       if (port->dma == PARPORT_DMA_NONE)
-               len += sprintf(buffer+len, "dma:\tnone\n");
-       else
-               len += sprintf(buffer+len, "dma:\t%d\n", port->dma);
-
-       len += sprintf(buffer+len, "modes:\t");
-       {
-#define printmode(x) {if(port->modes&PARPORT_MODE_##x){len+=sprintf(buffer+len,"%s%s",f?",":"",#x);f++;}}
-               int f = 0;
-               printmode(PCSPP);
-               printmode(TRISTATE);
-               printmode(COMPAT);
-               printmode(EPP);
-               printmode(ECP);
-               printmode(DMA);
-#undef printmode
-       }
-       buffer[len++] = '\n';
-
-       if (len > *lenp)
-               len = *lenp;
-       else
-               *lenp = len;
-
-       filp->f_pos += len;
-
-       return copy_to_user(result, buffer, len) ? -EFAULT : 0;
-}
-
-#define PARPORT_PORT_DIR(child) { 0, NULL, NULL, 0, 0555, child }
-#define PARPORT_PARPORT_DIR(child) { DEV_PARPORT, "parport", \
-                                     NULL, 0, 0555, child }
-#define PARPORT_DEV_DIR(child) { CTL_DEV, "dev", NULL, 0, 0555, child }
-#define PARPORT_DEVICES_ROOT_DIR  { DEV_PARPORT_DEVICES, "devices", \
-                                    NULL, 0, 0555, NULL }
-
-
-struct parport_sysctl_table {
-       struct ctl_table_header *sysctl_header;
-       ctl_table vars[9];
-       ctl_table device_dir[2];
-       ctl_table port_dir[2];
-       ctl_table parport_dir[2];
-       ctl_table dev_dir[2];
-};
-
-static const struct parport_sysctl_table parport_sysctl_template = {
-       NULL,
-        {
-               { DEV_PARPORT_SPINTIME, "spintime",
-                 NULL, sizeof(int), 0644, NULL,
-                 &proc_dointvec },
-               { DEV_PARPORT_HARDWARE, "hardware",
-                 NULL, 0, 0444, NULL,
-                 &do_hardware },
-               PARPORT_DEVICES_ROOT_DIR,
-#ifdef CONFIG_PARPORT_1284
-               { DEV_PARPORT_AUTOPROBE, "autoprobe",
-                 NULL, 0, 0444, NULL,
-                 &do_autoprobe },
-               { DEV_PARPORT_AUTOPROBE + 1, "autoprobe0",
-                NULL, 0, 0444, NULL,
-                &do_autoprobe },
-               { DEV_PARPORT_AUTOPROBE + 2, "autoprobe1",
-                 NULL, 0, 0444, NULL,
-                 &do_autoprobe },
-               { DEV_PARPORT_AUTOPROBE + 3, "autoprobe2",
-                 NULL, 0, 0444, NULL,
-                 &do_autoprobe },
-               { DEV_PARPORT_AUTOPROBE + 4, "autoprobe3",
-                 NULL, 0, 0444, NULL,
-                 &do_autoprobe },
-#endif /* IEEE 1284 support */
-               {0}
-       },
-       { {DEV_PARPORT_DEVICES_ACTIVE, "active", NULL, 0, 444, NULL,
-         &do_active_device }, {0}},
-       { PARPORT_PORT_DIR(NULL), {0}},
-       { PARPORT_PARPORT_DIR(NULL), {0}},
-       { PARPORT_DEV_DIR(NULL), {0}}
-};
-
-struct parport_device_sysctl_table
-{
-       struct ctl_table_header *sysctl_header;
-       ctl_table vars[2];
-       ctl_table device_dir[2];
-       ctl_table devices_root_dir[2];
-       ctl_table port_dir[2];
-       ctl_table parport_dir[2];
-       ctl_table dev_dir[2];
-};
-
-static const struct parport_device_sysctl_table
-parport_device_sysctl_template = {
-       NULL,
-       {
-               { DEV_PARPORT_DEVICE_TIMESLICE, "timeslice",
-                 NULL, sizeof(int), 0644, NULL,
-                 &proc_dointvec },
-       },
-       { {0, NULL, NULL, 0, 0555, NULL}, {0}},
-       { PARPORT_DEVICES_ROOT_DIR, {0}},
-       { PARPORT_PORT_DIR(NULL), {0}},
-       { PARPORT_PARPORT_DIR(NULL), {0}},
-       { PARPORT_DEV_DIR(NULL), {0}}
-};
-
-struct parport_default_sysctl_table
-{
-       struct ctl_table_header *sysctl_header;
-       ctl_table vars[3];
-        ctl_table default_dir[2];
-       ctl_table parport_dir[2];
-       ctl_table dev_dir[2];
-};
-
-extern unsigned long parport_default_timeslice;
-extern int parport_default_spintime;
-
-static struct parport_default_sysctl_table
-parport_default_sysctl_table = {
-       NULL,
-       {
-               { DEV_PARPORT_DEFAULT_TIMESLICE, "timeslice",
-                 &parport_default_timeslice,
-                 sizeof(parport_default_timeslice), 0644, NULL,
-                 &proc_dointvec },
-               { DEV_PARPORT_DEFAULT_SPINTIME, "spintime",
-                 &parport_default_spintime,
-                 sizeof(parport_default_timeslice), 0644, NULL,
-                 &proc_dointvec },
-               {0}
-       },
-       { { DEV_PARPORT_DEFAULT, "default", NULL, 0, 0555,
-           parport_default_sysctl_table.vars },{0}},
-       {
-       PARPORT_PARPORT_DIR(parport_default_sysctl_table.default_dir), 
-       {0}},
-       { PARPORT_DEV_DIR(parport_default_sysctl_table.parport_dir), {0}}
-};
-
-
-int parport_proc_register(struct parport *port)
-{
-       struct parport_sysctl_table *t;
-       int i;
-
-       t = kmalloc(sizeof(*t), GFP_KERNEL);
-       if (t == NULL)
-               return -ENOMEM;
-       memcpy(t, &parport_sysctl_template, sizeof(*t));
-
-       t->device_dir[0].extra1 = port;
-
-       for (i = 0; i < 8; i++)
-               t->vars[i].extra1 = port;
-
-       t->vars[0].data = &port->spintime;
-       t->vars[2].child = t->device_dir;
-       
-       for (i = 0; i < 5; i++)
-               t->vars[3 + i].extra2 = &port->probe_info[i];
-
-       t->port_dir[0].procname = port->name;
-       t->port_dir[0].ctl_name = port->number + 1; /* nb 0 isn't legal here */
-
-       t->port_dir[0].child = t->vars;
-       t->parport_dir[0].child = t->port_dir;
-       t->dev_dir[0].child = t->parport_dir;
-
-       t->sysctl_header = register_sysctl_table(t->dev_dir, 0);
-       if (t->sysctl_header == NULL) {
-               kfree(t);
-               t = NULL;
-       }
-       port->sysctl_table = t;
-       return 0;
-}
-
-int parport_proc_unregister(struct parport *port)
-{
-       if (port->sysctl_table) {
-               struct parport_sysctl_table *t = port->sysctl_table;
-               port->sysctl_table = NULL;
-               unregister_sysctl_table(t->sysctl_header);
-               kfree(t);
-       }
-       return 0;
-}
-
-int parport_device_proc_register(struct pardevice *device)
-{
-       struct parport_device_sysctl_table *t;
-       struct parport * port = device->port;
-       
-       t = kmalloc(sizeof(*t), GFP_KERNEL);
-       if (t == NULL)
-               return -ENOMEM;
-       memcpy(t, &parport_device_sysctl_template, sizeof(*t));
-
-       t->dev_dir[0].child = t->parport_dir;
-       t->parport_dir[0].child = t->port_dir;
-       t->port_dir[0].procname = port->name;
-       t->port_dir[0].ctl_name = port->number + 1; /* nb 0 isn't legal here */
-       t->port_dir[0].child = t->devices_root_dir;
-       t->devices_root_dir[0].child = t->device_dir;
-
-#ifdef CONFIG_PARPORT_1284
-
-       t->device_dir[0].ctl_name =
-               parport_device_num(port->number, port->muxport,
-                                  device->daisy)
-               + 1;  /* nb 0 isn't legal here */ 
-
-#else /* No IEEE 1284 support */
-
-       /* parport_device_num isn't available. */
-       t->device_dir[0].ctl_name = 1;
-       
-#endif /* IEEE 1284 support or not */
-
-       t->device_dir[0].procname = device->name;
-       t->device_dir[0].extra1 = device;
-       t->device_dir[0].child = t->vars;
-       t->vars[0].data = &device->timeslice;
-
-       t->sysctl_header = register_sysctl_table(t->dev_dir, 0);
-       if (t->sysctl_header == NULL) {
-               kfree(t);
-               t = NULL;
-       }
-       device->sysctl_table = t;
-       return 0;
-}
-
-int parport_device_proc_unregister(struct pardevice *device)
-{
-       if (device->sysctl_table) {
-               struct parport_device_sysctl_table *t = device->sysctl_table;
-               device->sysctl_table = NULL;
-               unregister_sysctl_table(t->sysctl_header);
-               kfree(t);
-       }
-       return 0;
-}
-
-int parport_default_proc_register(void)
-{
-       parport_default_sysctl_table.sysctl_header =
-               register_sysctl_table(parport_default_sysctl_table.dev_dir, 0);
-       return 0;
-}
-
-int parport_default_proc_unregister(void)
-{
-       if (parport_default_sysctl_table.sysctl_header) {
-               unregister_sysctl_table(parport_default_sysctl_table.
-                                       sysctl_header);
-               parport_default_sysctl_table.sysctl_header = NULL;
-       }
-       return 0;
-}
-
-#else /* no sysctl */
-
-int parport_proc_register(struct parport *pp)
-{
-       return 0;
-}
-
-int parport_proc_unregister(struct parport *pp)
-{
-       return 0;
-}
-
-int parport_device_proc_register(struct pardevice *device)
-{
-       return 0;
-}
-
-int parport_device_proc_unregister(struct pardevice *device)
-{
-       return 0;
-}
-
-int parport_default_proc_register (void)
-{
-       return 0;
-}
-
-int parport_default_proc_unregister (void)
-{
-       return 0;
-}
-#endif
diff --git a/drivers/misc/parport_share.c b/drivers/misc/parport_share.c
deleted file mode 100644 (file)
index e26a476..0000000
+++ /dev/null
@@ -1,602 +0,0 @@
-/* $Id: parport_share.c,v 1.15 1998/01/11 12:06:17 philip Exp $
- * Parallel-port resource manager code.
- * 
- * Authors: David Campbell <campbell@tirian.che.curtin.edu.au>
- *          Tim Waugh <tim@cyberelk.demon.co.uk>
- *          Jose Renau <renau@acm.org>
- *          Philip Blundell <philb@gnu.org>
- *         Andrea Arcangeli
- *
- * based on work by Grant Guenther <grant@torque.net>
- *          and Philip Blundell
- */
-
-#undef PARPORT_DEBUG_SHARING           /* undef for production */
-
-#include <linux/config.h>
-#include <linux/string.h>
-#include <linux/threads.h>
-#include <linux/parport.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/kernel.h>
-#include <linux/malloc.h>
-#include <linux/sched.h>
-
-#include <asm/spinlock.h>
-#include <asm/irq.h>
-
-#undef PARPORT_PARANOID
-
-#define PARPORT_DEFAULT_TIMESLICE      (HZ/5)
-
-unsigned long parport_default_timeslice = PARPORT_DEFAULT_TIMESLICE;
-int parport_default_spintime =  DEFAULT_SPIN_TIME;
-
-static struct parport *portlist = NULL, *portlist_tail = NULL;
-spinlock_t parportlist_lock = SPIN_LOCK_UNLOCKED;
-
-static struct parport_driver *driver_chain = NULL;
-spinlock_t driverlist_lock = SPIN_LOCK_UNLOCKED;
-
-static void call_driver_chain(int attach, struct parport *port)
-{
-       struct parport_driver *drv;
-
-       for (drv = driver_chain; drv; drv = drv->next) {
-               if (attach)
-                       drv->attach (port);
-               else
-                       drv->detach (port);
-       }
-}
-
-int parport_register_driver (struct parport_driver *drv)
-{
-       struct parport *port;
-
-       spin_lock (&driverlist_lock);
-       drv->next = driver_chain;
-       driver_chain = drv;
-       spin_unlock (&driverlist_lock);
-
-       for (port = portlist; port; port = port->next)
-               drv->attach (port);
-
-       return 0;
-}
-
-void parport_unregister_driver (struct parport_driver *arg)
-{
-       struct parport_driver *drv = driver_chain, *olddrv = NULL;
-
-       while (drv) {
-               if (drv == arg) {
-                       spin_lock (&driverlist_lock);
-                       if (olddrv)
-                               olddrv->next = drv->next;
-                       else
-                               driver_chain = drv->next;
-                       spin_unlock (&driverlist_lock);
-                       return;
-               }
-               olddrv = drv;
-               drv = drv->next;
-       }
-}
-
-/* Return a list of all the ports we know about. */
-struct parport *parport_enumerate(void)
-{
-       return portlist;
-}
-
-struct parport *parport_register_port(unsigned long base, int irq, int dma,
-                                     struct parport_operations *ops)
-{
-       struct parport *tmp;
-       int portnum;
-       int device;
-       char *name;
-
-       tmp = kmalloc(sizeof(struct parport), GFP_KERNEL);
-       if (!tmp) {
-               printk(KERN_WARNING "parport: memory squeeze\n");
-               return NULL;
-       }
-
-       /* Search for the lowest free parport number. */
-       for (portnum = 0; ; portnum++) {
-               struct parport *itr = portlist;
-               while (itr) {
-                       if (itr->number == portnum)
-                               /* No good, already used. */
-                               break;
-                       else
-                               itr = itr->next;
-               }
-
-               if (itr == NULL)
-                       /* Got to the end of the list. */
-                       break;
-       }
-       
-       /* Init our structure */
-       memset(tmp, 0, sizeof(struct parport));
-       tmp->base = base;
-       tmp->irq = irq;
-       tmp->dma = dma;
-       tmp->muxport = tmp->daisy = tmp->muxsel = -1;
-       tmp->modes = 0;
-       tmp->next = NULL;
-       tmp->devices = tmp->cad = NULL;
-       tmp->flags = 0;
-       tmp->ops = ops;
-       tmp->portnum = tmp->number = portnum;
-       tmp->physport = tmp;
-       memset (tmp->probe_info, 0, 5 * sizeof (struct parport_device_info));
-       tmp->cad_lock = RW_LOCK_UNLOCKED;
-       spin_lock_init(&tmp->waitlist_lock);
-       spin_lock_init(&tmp->pardevice_lock);
-       tmp->ieee1284.mode = IEEE1284_MODE_COMPAT;
-       tmp->ieee1284.phase = IEEE1284_PH_FWD_IDLE;
-       init_MUTEX_LOCKED (&tmp->ieee1284.irq); /* actually a semaphore at 0 */
-       tmp->spintime = parport_default_spintime;
-
-       name = kmalloc(15, GFP_KERNEL);
-       if (!name) {
-               printk(KERN_ERR "parport: memory squeeze\n");
-               kfree(tmp);
-               return NULL;
-       }
-       sprintf(name, "parport%d", portnum);
-       tmp->name = name;
-
-       /*
-        * Chain the entry to our list.
-        *
-        * This function must not run from an irq handler so we don' t need
-        * to clear irq on the local CPU. -arca
-        */
-       spin_lock(&parportlist_lock);
-       if (portlist_tail)
-               portlist_tail->next = tmp;
-       portlist_tail = tmp;
-       if (!portlist)
-               portlist = tmp;
-       spin_unlock(&parportlist_lock);
-
-       for (device = 0; device < 5; device++)
-               /* assume the worst */
-               tmp->probe_info[device].class = PARPORT_CLASS_LEGACY;
-
-       tmp->waithead = tmp->waittail = NULL;
-
-       return tmp;
-}
-
-void parport_announce_port (struct parport *port)
-{
-#ifdef CONFIG_PARPORT_1284
-       /* Analyse the IEEE1284.3 topology of the port. */
-       parport_daisy_init (port);
-#endif
-
-       /* Let drivers know that a new port has arrived. */
-       call_driver_chain (1, port);
-}
-
-void parport_unregister_port(struct parport *port)
-{
-       struct parport *p;
-       int d;
-
-       /* Spread the word. */
-       call_driver_chain (0, port);
-
-#ifdef CONFIG_PARPORT_1284
-       /* Forget the IEEE1284.3 topology of the port. */
-       parport_daisy_fini (port);
-#endif
-
-       spin_lock(&parportlist_lock);
-       if (portlist == port) {
-               if ((portlist = port->next) == NULL)
-                       portlist_tail = NULL;
-       } else {
-               for (p = portlist; (p != NULL) && (p->next != port); 
-                    p=p->next);
-               if (p) {
-                       if ((p->next = port->next) == NULL)
-                               portlist_tail = p;
-               }
-               else printk (KERN_WARNING
-                            "%s not found in port list!\n", port->name);
-       }
-       spin_unlock(&parportlist_lock);
-
-       for (d = 0; d < 5; d++) {
-               if (port->probe_info[d].class_name)
-                       kfree (port->probe_info[d].class_name);
-               if (port->probe_info[d].mfr)
-                       kfree (port->probe_info[d].mfr);
-               if (port->probe_info[d].model)
-                       kfree (port->probe_info[d].model);
-               if (port->probe_info[d].cmdset)
-                       kfree (port->probe_info[d].cmdset);
-               if (port->probe_info[d].description)
-                       kfree (port->probe_info[d].description);
-       }
-
-       kfree(port->name);
-       kfree(port);
-}
-
-struct pardevice *parport_register_device(struct parport *port, const char *name,
-                         int (*pf)(void *), void (*kf)(void *),
-                         void (*irq_func)(int, void *, struct pt_regs *), 
-                         int flags, void *handle)
-{
-       struct pardevice *tmp;
-
-       if (port->physport->flags & PARPORT_FLAG_EXCL) {
-               /* An exclusive device is registered. */
-               printk (KERN_DEBUG "%s: no more devices allowed\n",
-                       port->name);
-               return NULL;
-       }
-
-       if (flags & PARPORT_DEV_LURK) {
-               if (!pf || !kf) {
-                       printk(KERN_INFO "%s: refused to register lurking device (%s) without callbacks\n", port->name, name);
-                       return NULL;
-               }
-       }
-
-       tmp = kmalloc(sizeof(struct pardevice), GFP_KERNEL);
-       if (tmp == NULL) {
-               printk(KERN_WARNING "%s: memory squeeze, couldn't register %s.\n", port->name, name);
-               return NULL;
-       }
-
-       tmp->state = kmalloc(sizeof(struct parport_state), GFP_KERNEL);
-       if (tmp->state == NULL) {
-               printk(KERN_WARNING "%s: memory squeeze, couldn't register %s.\n", port->name, name);
-               kfree(tmp);
-               return NULL;
-       }
-
-       tmp->name = name;
-       tmp->port = port;
-       tmp->daisy = -1;
-       tmp->preempt = pf;
-       tmp->wakeup = kf;
-       tmp->private = handle;
-       tmp->flags = flags;
-       tmp->irq_func = irq_func;
-       tmp->waiting = 0;
-       tmp->timeout = 5 * HZ;
-
-       /* Chain this onto the list */
-       tmp->prev = NULL;
-       /*
-        * This function must not run from an irq handler so we don' t need
-        * to clear irq on the local CPU. -arca
-        */
-       spin_lock(&port->physport->pardevice_lock);
-
-       if (flags & PARPORT_DEV_EXCL) {
-               if (port->physport->devices) {
-                       spin_unlock (&port->physport->pardevice_lock);
-                       kfree (tmp->state);
-                       kfree (tmp);
-                       printk (KERN_DEBUG
-                               "%s: cannot grant exclusive access for "
-                               "device %s\n", port->name, name);
-                       return NULL;
-               }
-               port->flags |= PARPORT_FLAG_EXCL;
-       }
-
-       tmp->next = port->physport->devices;
-       if (port->physport->devices)
-               port->physport->devices->prev = tmp;
-       port->physport->devices = tmp;
-       spin_unlock(&port->physport->pardevice_lock);
-
-       inc_parport_count();
-       port->ops->inc_use_count();
-
-       init_waitqueue_head(&tmp->wait_q);
-       tmp->timeslice = parport_default_timeslice;
-       tmp->waitnext = tmp->waitprev = NULL;
-
-       /*
-        * This has to be run as last thing since init_state may need other
-        * pardevice fields. -arca
-        */
-       port->ops->init_state(tmp, tmp->state);
-       parport_device_proc_register(tmp);
-       return tmp;
-}
-
-void parport_unregister_device(struct pardevice *dev)
-{
-       struct parport *port;
-
-#ifdef PARPORT_PARANOID
-       if (dev == NULL) {
-               printk(KERN_ERR "parport_unregister_device: passed NULL\n");
-               return;
-       }
-#endif
-
-       parport_device_proc_unregister(dev);
-
-       port = dev->port->physport;
-
-       if (port->cad == dev) {
-               printk(KERN_DEBUG "%s: %s forgot to release port\n",
-                      port->name, dev->name);
-               parport_release (dev);
-       }
-
-       spin_lock(&port->pardevice_lock);
-       if (dev->next)
-               dev->next->prev = dev->prev;
-       if (dev->prev)
-               dev->prev->next = dev->next;
-       else
-               port->devices = dev->next;
-
-       if (dev->flags & PARPORT_DEV_EXCL)
-               port->flags &= ~PARPORT_FLAG_EXCL;
-
-       spin_unlock(&port->pardevice_lock);
-
-       kfree(dev->state);
-       kfree(dev);
-
-       dec_parport_count();
-       port->ops->dec_use_count();
-}
-
-int parport_claim(struct pardevice *dev)
-{
-       struct pardevice *oldcad;
-       struct parport *port = dev->port->physport;
-       unsigned long flags;
-
-       if (port->cad == dev) {
-               printk(KERN_INFO "%s: %s already owner\n",
-                      dev->port->name,dev->name);
-               return 0;
-       }
-
-try_again:
-       /* Preempt any current device */
-       if ((oldcad = port->cad) != NULL) {
-               if (oldcad->preempt) {
-                       if (oldcad->preempt(oldcad->private))
-                               goto blocked;
-                       port->ops->save_state(port, dev->state);
-               } else
-                       goto blocked;
-
-               if (port->cad != oldcad) {
-                       printk(KERN_WARNING 
-                              "%s: %s released port when preempted!\n",
-                              port->name, oldcad->name);
-                       if (port->cad)
-                               goto blocked;
-               }
-       }
-
-       /* Can't fail from now on, so mark ourselves as no longer waiting.  */
-       if (dev->waiting & 1) {
-               dev->waiting = 0;
-
-               /* Take ourselves out of the wait list again.  */
-               spin_lock_irqsave (&port->waitlist_lock, flags);
-               if (dev->waitprev)
-                       dev->waitprev->waitnext = dev->waitnext;
-               else
-                       port->waithead = dev->waitnext;
-               if (dev->waitnext)
-                       dev->waitnext->waitprev = dev->waitprev;
-               else
-                       port->waittail = dev->waitprev;
-               spin_unlock_irqrestore (&port->waitlist_lock, flags);
-               dev->waitprev = dev->waitnext = NULL;
-       }
-
-       /* Now we do the change of devices */
-       write_lock_irqsave(&port->cad_lock, flags);
-       port->cad = dev;
-       write_unlock_irqrestore(&port->cad_lock, flags);
-
-#ifdef CONFIG_PARPORT_1284
-       /* If it's a mux port, select it. */
-       if (dev->port->muxport >= 0) {
-               /* FIXME */
-               port->muxsel = dev->port->muxport;
-       }
-
-       /* If it's a daisy chain device, select it. */
-       if (dev->daisy >= 0) {
-               /* This could be lazier. */
-               if (!parport_daisy_select (port, dev->daisy,
-                                          IEEE1284_MODE_COMPAT))
-                       port->daisy = dev->daisy;
-       }
-#endif /* IEEE1284.3 support */
-
-       /* Restore control registers */
-       port->ops->restore_state(port, dev->state);
-       dev->time = jiffies;
-       return 0;
-
-blocked:
-       /* If this is the first time we tried to claim the port, register an
-          interest.  This is only allowed for devices sleeping in
-          parport_claim_or_block(), or those with a wakeup function.  */
-       if (dev->waiting & 2 || dev->wakeup) {
-               spin_lock_irqsave (&port->waitlist_lock, flags);
-               if (port->cad == NULL) {
-                       /* The port got released in the meantime. */
-                       spin_unlock_irqrestore (&port->waitlist_lock, flags);
-                       goto try_again;
-               }
-               if (test_and_set_bit(0, &dev->waiting) == 0) {
-                       /* First add ourselves to the end of the wait list. */
-                       dev->waitnext = NULL;
-                       dev->waitprev = port->waittail;
-                       if (port->waittail) {
-                               port->waittail->waitnext = dev;
-                               port->waittail = dev;
-                       } else
-                               port->waithead = port->waittail = dev;
-               }
-               spin_unlock_irqrestore (&port->waitlist_lock, flags);
-       }
-       return -EAGAIN;
-}
-
-int parport_claim_or_block(struct pardevice *dev)
-{
-       int r;
-
-       /* Signal to parport_claim() that we can wait even without a
-          wakeup function.  */
-       dev->waiting = 2;
-
-       /* Try to claim the port.  If this fails, we need to sleep.  */
-       r = parport_claim(dev);
-       if (r == -EAGAIN) {
-               unsigned long flags;
-#ifdef PARPORT_DEBUG_SHARING
-               printk(KERN_DEBUG "%s: parport_claim() returned -EAGAIN\n", dev->name);
-#endif
-               save_flags (flags);
-               cli();
-               /* If dev->waiting is clear now, an interrupt
-                  gave us the port and we would deadlock if we slept.  */
-               if (dev->waiting) {
-                       sleep_on(&dev->wait_q);
-                       r = 1;
-               } else {
-                       r = 0;
-#ifdef PARPORT_DEBUG_SHARING
-                       printk(KERN_DEBUG "%s: didn't sleep in parport_claim_or_block()\n",
-                              dev->name);
-#endif
-               }
-               restore_flags(flags);
-#ifdef PARPORT_DEBUG_SHARING
-               if (dev->port->physport->cad != dev)
-                       printk(KERN_DEBUG "%s: exiting parport_claim_or_block "
-                              "but %s owns port!\n", dev->name,
-                              dev->port->physport->cad ?
-                              dev->port->physport->cad->name:"nobody");
-#endif
-       }
-       dev->waiting = 0;
-       return r;
-}
-
-void parport_release(struct pardevice *dev)
-{
-       struct parport *port = dev->port->physport;
-       struct pardevice *pd;
-       unsigned long flags;
-
-       /* Make sure that dev is the current device */
-       if (port->cad != dev) {
-               printk(KERN_WARNING "%s: %s tried to release parport "
-                      "when not owner\n", port->name, dev->name);
-               return;
-       }
-
-#ifdef CONFIG_PARPORT_1284
-       /* If this is on a mux port, deselect it. */
-       if (dev->port->muxport >= 0) {
-               /* FIXME */
-               port->muxsel = -1;
-       }
-
-       /* If this is a daisy device, deselect it. */
-       if (dev->daisy >= 0) {
-               parport_daisy_deselect_all (port);
-               port->daisy = -1;
-       }
-#endif
-
-       write_lock_irqsave(&port->cad_lock, flags);
-       port->cad = NULL;
-       write_unlock_irqrestore(&port->cad_lock, flags);
-
-       /* Save control registers */
-       port->ops->save_state(port, dev->state);
-
-       /* If anybody is waiting, find out who's been there longest and
-          then wake them up. (Note: no locking required) */
-       for (pd = port->waithead; pd; pd = pd->waitnext) {
-               if (pd->waiting & 2) { /* sleeping in claim_or_block */
-                       parport_claim(pd);
-                       if (waitqueue_active(&pd->wait_q))
-                               wake_up(&pd->wait_q);
-                       return;
-               } else if (pd->wakeup) {
-                       pd->wakeup(pd->private);
-                       if (dev->port->cad)
-                               return;
-               } else {
-                       printk(KERN_ERR "%s: don't know how to wake %s\n", port->name, pd->name);
-               }
-       }
-
-       /* Nobody was waiting, so walk the list to see if anyone is
-          interested in being woken up.  */
-       for (pd = port->devices; (port->cad == NULL) && pd; pd = pd->next) {
-               if (pd->wakeup && pd != dev)
-                       pd->wakeup(pd->private);
-       }
-}
-
-static int parport_parse_params (int nports, const char *str[], int val[],
-                                int automatic, int none)
-{
-       unsigned int i;
-       for (i = 0; i < nports && str[i]; i++) {
-               if (!strncmp(str[i], "auto", 4))
-                       val[i] = automatic;
-               else if (!strncmp(str[i], "none", 4))
-                       val[i] = none;
-               else {
-                       char *ep;
-                       unsigned long r = simple_strtoul(str[i], &ep, 0);
-                       if (ep != str[i])
-                               val[i] = r;
-                       else {
-                               printk("parport: bad specifier `%s'\n", str[i]);
-                               return -1;
-                       }
-               }
-       }
-
-       return 0;
-}
-
-int parport_parse_irqs(int nports, const char *irqstr[], int irqval[])
-{
-       return parport_parse_params (nports, irqstr, irqval, PARPORT_IRQ_AUTO,
-                                    PARPORT_IRQ_NONE);
-}
-
-int parport_parse_dmas(int nports, const char *dmastr[], int dmaval[])
-{
-       return parport_parse_params (nports, dmastr, dmaval, PARPORT_DMA_AUTO,
-                                    PARPORT_DMA_NONE);
-}
diff --git a/drivers/parport/BUGS-parport b/drivers/parport/BUGS-parport
new file mode 100644 (file)
index 0000000..2329add
--- /dev/null
@@ -0,0 +1,5 @@
+Currently known (or at least suspected) bugs in parport:
+
+o lp doesn't allow you to read status while printing is in progress.
+
+See <URL:http://www.cyberelk.demon.co.uk/parport.html>.
diff --git a/drivers/parport/Config.in b/drivers/parport/Config.in
new file mode 100644 (file)
index 0000000..e2d96d0
--- /dev/null
@@ -0,0 +1,37 @@
+#
+# For a description of the syntax of this configuration file,
+# see the Configure script.
+#
+# Parport configuration.
+#
+
+tristate 'Parallel port support' CONFIG_PARPORT
+if [ "$CONFIG_PARPORT" != "n" ]; then
+  dep_tristate '   PC-style hardware' CONFIG_PARPORT_PC $CONFIG_PARPORT
+  if [ "$CONFIG_PARPORT_PC" != "n" ]; then
+    bool '   Use FIFO/DMA if available' CONFIG_PARPORT_PC_FIFO
+  fi
+  if [ "$CONFIG_ARM" = "y" ]; then
+    dep_tristate '   Archimedes hardware' CONFIG_PARPORT_ARC $CONFIG_PARPORT
+  fi
+  if [ "$CONFIG_AMIGA" = "y" ]; 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
+  else
+    define_bool CONFIG_PARPORT_AMIGA n
+    define_bool CONFIG_PARPORT_MFC3 n
+  fi
+  if [ "$CONFIG_ATARI" = "y" ]; then
+    dep_tristate '   Atari hardware' CONFIG_PARPORT_ATARI $CONFIG_PARPORT
+  else
+    define_bool CONFIG_PARPORT_ATARI n
+  fi
+
+  # If exactly one hardware type is selected then parport will optimise away
+  # support for loading any others.  Defeat this if the user is keen.
+  bool '   Support foreign hardware' CONFIG_PARPORT_OTHER
+
+  bool '   IEEE 1284 transfer modes' CONFIG_PARPORT_1284
+fi
diff --git a/drivers/parport/Makefile b/drivers/parport/Makefile
new file mode 100644 (file)
index 0000000..4149ce1
--- /dev/null
@@ -0,0 +1,101 @@
+#
+# Makefile for the kernel miscellaneous drivers.
+#
+# 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 inherited from the
+# parent makes..
+#
+# Note 3! Parport is the Borg.  We have assimilated some other
+# drivers in the `char', `net' and `scsi' directories, but left them
+# there to allay suspicion.
+
+SUB_DIRS     := 
+MOD_SUB_DIRS := $(SUB_DIRS)
+ALL_SUB_DIRS := $(SUB_DIRS)
+
+L_TARGET := parport.a
+MX_OBJS  :=
+LX_OBJS  := 
+MI_OBJS  :=
+MIX_OBJS :=
+
+ifeq ($(CONFIG_PARPORT),y)
+  L_OBJS += share.o ieee1284.o ieee1284_ops.o procfs.o
+
+  ifeq ($(CONFIG_PARPORT_1284),y)
+    L_OBJS += daisy.o probe.o
+  endif
+
+  ifeq ($(CONFIG_PARPORT_PC),y)
+    LX_OBJS += parport_pc.o
+  else
+    ifeq ($(CONFIG_PARPORT_PC),m)
+      M_OBJS += parport_pc.o
+    endif
+  endif
+  ifeq ($(CONFIG_PARPORT_AX),y)
+    LX_OBJS += parport_ax.o
+  else
+    ifeq ($(CONFIG_PARPORT_AX),m)
+      M_OBJS += parport_ax.o
+    endif
+  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
+  LX_OBJS += init.o
+else
+  ifeq ($(CONFIG_PARPORT),m)
+    MI_OBJS += share.o ieee1284.o ieee1284_ops.o
+    ifeq ($(CONFIG_PARPORT_1284),y)
+      MI_OBJS += daisy.o probe.o
+    endif
+    ifneq ($(CONFIG_PROC_FS),n) 
+      MI_OBJS += procfs.o
+    endif
+    MIX_OBJS += init.o
+    M_OBJS += parport.o
+  endif
+  ifeq ($(CONFIG_PARPORT_PC),m)
+    M_OBJS += parport_pc.o
+  endif
+  ifeq ($(CONFIG_PARPORT_AX),m)
+    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
+  endif
+endif
+
+include $(TOPDIR)/Rules.make
+
+# Special rule to build the composite parport.o module
+parport.o: $(MI_OBJS) $(MIX_OBJS)
+       $(LD) $(LD_RFLAG) -r -o $@ $(MI_OBJS) $(MIX_OBJS)
diff --git a/drivers/parport/TODO-parport b/drivers/parport/TODO-parport
new file mode 100644 (file)
index 0000000..bf91351
--- /dev/null
@@ -0,0 +1,20 @@
+Things to be done.
+
+0. Fix the bugs (see BUGS-parport).
+
+1. Proper documentation.
+
+2. A better lp.c:
+
+   a) ECP support would be nice.  This can only work if both the port and
+      the printer support it.
+
+   b) Handle status readback automatically.  IEEE1284 printers can post status
+      bits when they have something to say.  We should read out and deal 
+      with (maybe just log) whatever the printer wants to tell the world.
+
+3. Support more hardware (eg m68k, Sun bpp).
+
+4. A better PLIP (make use of bidirectional/ECP/EPP ports).
+
+See <URL:http://www.cyberelk.demon.co.uk/parport.html>.
diff --git a/drivers/parport/daisy.c b/drivers/parport/daisy.c
new file mode 100644 (file)
index 0000000..830d9d4
--- /dev/null
@@ -0,0 +1,473 @@
+/*
+ * IEEE 1284.3 Parallel port daisy chain and multiplexor code
+ * 
+ * Copyright (C) 1999  Tim Waugh <tim@cyberelk.demon.co.uk>
+ *
+ * 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.
+ *
+ * ??-12-1998: Initial implementation.
+ * 31-01-1999: Make port-cloning transparent.
+ * 13-02-1999: Move DeviceID technique from parport_probe.
+ * 13-03-1999: Get DeviceID from non-IEEE 1284.3 devices too.
+ *
+ */
+
+#include <linux/parport.h>
+#include <linux/delay.h>
+#include <asm/uaccess.h>
+
+#define DEBUG /* undef me for production */
+
+#ifdef DEBUG
+#define DPRINTK(stuff...) printk (stuff)
+#else
+#define DPRINTK(stuff...)
+#endif
+
+static struct daisydev {
+       struct daisydev *next;
+       struct parport *port;
+       int daisy;
+       int devnum;
+} *topology = NULL;
+
+static int numdevs = 0;
+
+/* Forward-declaration of lower-level functions. */
+static int mux_present (struct parport *port);
+static int num_mux_ports (struct parport *port);
+static int select_port (struct parport *port);
+static int assign_addrs (struct parport *port);
+
+/* Add a device to the discovered topology. */
+static void add_dev (int devnum, struct parport *port, int daisy)
+{
+       struct daisydev *newdev;
+       newdev = kmalloc (GFP_KERNEL, sizeof (struct daisydev));
+       if (newdev) {
+               newdev->port = port;
+               newdev->daisy = daisy;
+               newdev->devnum = devnum;
+               newdev->next = topology;
+               if (!topology || topology->devnum >= devnum)
+                       topology = newdev;
+               else {
+                       struct daisydev *prev = topology;
+                       while (prev->next && prev->next->devnum < devnum)
+                               prev = prev->next;
+                       newdev->next = prev->next;
+                       prev->next = newdev;
+               }
+       }
+}
+
+/* Clone a parport (actually, make an alias). */
+static struct parport *clone_parport (struct parport *real, int muxport)
+{
+       struct parport *extra = parport_register_port (real->base,
+                                                      real->irq,
+                                                      real->dma,
+                                                      real->ops);
+       if (extra) {
+               extra->portnum = real->portnum;
+               extra->physport = real;
+               extra->muxport = muxport;
+       }
+
+       return extra;
+}
+
+/* Discover the IEEE1284.3 topology on a port -- muxes and daisy chains. */
+int parport_daisy_init (struct parport *port)
+{
+       char *deviceid;
+       static const char *th[] = { /*0*/"th", "st", "nd", "rd", "th" };
+       int num_ports;
+       int i;
+
+       /* Because this is called before any other devices exist,
+        * we don't have to claim exclusive access.  */
+
+       /* If mux present on normal port, need to create new
+        * parports for each extra port. */
+       if (port->muxport < 0 && mux_present (port) &&
+           /* don't be fooled: a mux must have 2 or 4 ports. */
+           ((num_ports = num_mux_ports (port)) == 2 || num_ports == 4)) {
+               /* Leave original as port zero. */
+               port->muxport = 0;
+               printk (KERN_INFO
+                       "%s: 1st (default) port of %d-way multiplexor\n",
+                       port->name, num_ports);
+               for (i = 1; i < num_ports; i++) {
+                       /* Clone the port. */
+                       struct parport *extra = clone_parport (port, i);
+                       if (!extra) {
+                               if (signal_pending (current))
+                                       break;
+
+                               schedule ();
+                               continue;
+                       }
+
+                       printk (KERN_INFO
+                               "%s: %d%s port of %d-way multiplexor on %s\n",
+                               extra->name, i + 1, th[i + 1], num_ports,
+                               port->name);
+
+                       /* Analyse that port too.  We won't recurse
+                          forever because of the 'port->muxport < 0'
+                          test above. */
+                       parport_announce_port (extra);
+               }
+       }
+
+       if (port->muxport >= 0)
+               select_port (port);
+
+       parport_daisy_deselect_all (port);
+       assign_addrs (port);
+
+       /* Count the potential legacy device at the end. */
+       add_dev (numdevs++, port, -1);
+
+       /* Find out the legacy device's IEEE 1284 device ID. */
+       deviceid = kmalloc (1000, GFP_KERNEL);
+       if (deviceid) {
+               parport_device_id (numdevs - 1, deviceid, 1000);
+               kfree (deviceid);
+       }
+
+       return 0;
+}
+
+/* Forget about devices on a physical port. */
+void parport_daisy_fini (struct parport *port)
+{
+       struct daisydev *dev, *prev = topology;
+       while (prev && prev->port == port)
+               prev = topology = topology->next;
+
+       while (prev) {
+               dev = prev->next;
+               if (dev && dev->port == port)
+                       prev->next = dev->next;
+
+               prev = prev->next;
+       }
+
+       /* Gaps in the numbering could be handled better.  How should
+           someone enumerate through all IEEE1284.3 devices in the
+           topology?. */
+       if (!topology) numdevs = 0;
+       return; }
+
+/* Find a device by canonical device number. */
+struct pardevice *parport_open (int devnum, const char *name,
+                               int (*pf) (void *), void (*kf) (void *),
+                               void (*irqf) (int, void *, struct pt_regs *),
+                               int flags, void *handle)
+{
+       struct parport *port = parport_enumerate ();
+       struct pardevice *dev;
+       int portnum;
+       int muxnum;
+       int daisynum;
+
+       if (parport_device_coords (devnum,  &portnum, &muxnum, &daisynum))
+               return NULL;
+
+       while (port && ((port->portnum != portnum) ||
+                       (port->muxport != muxnum)))
+               port = port->next;
+
+       if (!port)
+               /* No corresponding parport. */
+               return NULL;
+
+       dev = parport_register_device (port, name, pf, kf,
+                                      irqf, flags, handle);
+       if (dev)
+               dev->daisy = daisynum;
+
+       /* Check that there really is a device to select. */
+       if (daisynum >= 0) {
+               int selected;
+               parport_claim_or_block (dev);
+               selected = port->daisy;
+               parport_release (dev);
+
+               if (selected != port->daisy) {
+                       /* No corresponding device. */
+                       parport_unregister_device (dev);
+                       return NULL;
+               }
+       }
+
+       return dev;
+}
+
+/* The converse of parport_open. */
+void parport_close (struct pardevice *dev)
+{
+       parport_unregister_device (dev);
+}
+
+/* Convert device coordinates into a canonical device number. */
+int parport_device_num (int parport, int mux, int daisy)
+{
+       struct daisydev *dev = topology;
+
+       while (dev && dev->port->portnum != parport &&
+              dev->port->muxport != mux && dev->daisy != daisy)
+               dev = dev->next;
+
+       if (!dev)
+               return -ENXIO;
+
+       return dev->devnum;
+}
+
+/* Convert a canonical device number into device coordinates. */
+int parport_device_coords (int devnum, int *parport, int *mux, int *daisy)
+{
+       struct daisydev *dev = topology;
+
+       while (dev && dev->devnum != devnum)
+               dev = dev->next;
+
+       if (!dev)
+               return -ENXIO;
+
+       if (parport) *parport = dev->port->portnum;
+       if (mux) *mux = dev->port->muxport;
+       if (daisy) *daisy = dev->daisy;
+       return 0;
+}
+
+/* Send a daisy-chain-style CPP command packet. */
+static int cpp_daisy (struct parport *port, int cmd)
+{
+       unsigned char s;
+
+       parport_write_data (port, 0xaa); udelay (2);
+       parport_write_data (port, 0x55); udelay (2);
+       parport_write_data (port, 0x00); udelay (2);
+       parport_write_data (port, 0xff); udelay (2);
+       s = parport_read_status (port) & (PARPORT_STATUS_BUSY
+                                         | PARPORT_STATUS_PAPEROUT
+                                         | PARPORT_STATUS_SELECT
+                                         | PARPORT_STATUS_ERROR);
+       if (s != (PARPORT_STATUS_BUSY
+                 | PARPORT_STATUS_PAPEROUT
+                 | PARPORT_STATUS_SELECT
+                 | PARPORT_STATUS_ERROR)) {
+               DPRINTK (KERN_DEBUG "%s: cpp_daisy: aa5500ff(%02x)\n",
+                        port->name, s);
+               return -ENXIO;
+       }
+
+       parport_write_data (port, 0x87); udelay (2);
+       s = parport_read_status (port) & (PARPORT_STATUS_BUSY
+                                         | PARPORT_STATUS_PAPEROUT
+                                         | PARPORT_STATUS_SELECT
+                                         | PARPORT_STATUS_ERROR);
+       if (s != (PARPORT_STATUS_SELECT | PARPORT_STATUS_ERROR)) {
+               DPRINTK (KERN_DEBUG "%s: cpp_daisy: aa5500ff87(%02x)\n",
+                        port->name, s);
+               return -ENXIO;
+       }
+
+       parport_write_data (port, 0x78); udelay (2);
+       parport_write_data (port, cmd); udelay (2);
+       parport_frob_control (port,
+                             PARPORT_CONTROL_STROBE,
+                             PARPORT_CONTROL_STROBE);
+       udelay (1);
+       parport_frob_control (port, PARPORT_CONTROL_STROBE, 0);
+       udelay (1);
+       s = parport_read_status (port);
+       parport_write_data (port, 0xff); udelay (2);
+
+       return s;
+}
+
+/* Send a mux-style CPP command packet. */
+static int cpp_mux (struct parport *port, int cmd)
+{
+       unsigned char s;
+       int rc;
+
+       parport_write_data (port, 0xaa); udelay (2);
+       parport_write_data (port, 0x55); udelay (2);
+       parport_write_data (port, 0xf0); udelay (2);
+       parport_write_data (port, 0x0f); udelay (2);
+       parport_write_data (port, 0x52); udelay (2);
+       parport_write_data (port, 0xad); udelay (2);
+       parport_write_data (port, cmd); udelay (2);
+
+       s = parport_read_status (port);
+       if (!(s & PARPORT_STATUS_ACK)) {
+               DPRINTK (KERN_DEBUG "%s: cpp_mux: aa55f00f52ad%02x(%02x)\n",
+                        port->name, cmd, s);
+               return -EIO;
+       }
+
+       rc = (((s & PARPORT_STATUS_SELECT   ? 1 : 0) << 0) |
+             ((s & PARPORT_STATUS_PAPEROUT ? 1 : 0) << 1) |
+             ((s & PARPORT_STATUS_BUSY     ? 0 : 1) << 2) |
+             ((s & PARPORT_STATUS_ERROR    ? 0 : 1) << 3));
+
+       return rc;
+}
+
+void parport_daisy_deselect_all (struct parport *port)
+{
+       cpp_daisy (port, 0x30);
+}
+
+int parport_daisy_select (struct parport *port, int daisy, int mode)
+{
+       /* mode is currently ignored. FIXME? */
+       return cpp_daisy (port, 0xe0 + daisy) & PARPORT_STATUS_ERROR;
+}
+
+static int mux_present (struct parport *port)
+{
+       return cpp_mux (port, 0x51) == 3;
+}
+
+static int num_mux_ports (struct parport *port)
+{
+       return cpp_mux (port, 0x58);
+}
+
+static int select_port (struct parport *port)
+{
+       int muxport = port->muxport;
+       return cpp_mux (port, 0x60 + muxport) == muxport;
+}
+
+static int assign_addrs (struct parport *port)
+{
+       unsigned char s, last_dev;
+       unsigned char daisy;
+       int thisdev = numdevs;
+       char *deviceid;
+
+       parport_write_data (port, 0xaa); udelay (2);
+       parport_write_data (port, 0x55); udelay (2);
+       parport_write_data (port, 0x00); udelay (2);
+       parport_write_data (port, 0xff); udelay (2);
+       s = parport_read_status (port) & (PARPORT_STATUS_BUSY
+                                         | PARPORT_STATUS_PAPEROUT
+                                         | PARPORT_STATUS_SELECT
+                                         | PARPORT_STATUS_ERROR);
+       if (s != (PARPORT_STATUS_BUSY
+                 | PARPORT_STATUS_PAPEROUT
+                 | PARPORT_STATUS_SELECT
+                 | PARPORT_STATUS_ERROR)) {
+               DPRINTK (KERN_DEBUG "%s: assign_addrs: aa5500ff(%02x)\n",
+                        port->name, s);
+               return -ENXIO;
+       }
+
+       parport_write_data (port, 0x87); udelay (2);
+       s = parport_read_status (port) & (PARPORT_STATUS_BUSY
+                                         | PARPORT_STATUS_PAPEROUT
+                                         | PARPORT_STATUS_SELECT
+                                         | PARPORT_STATUS_ERROR);
+       if (s != (PARPORT_STATUS_SELECT | PARPORT_STATUS_ERROR)) {
+               DPRINTK (KERN_DEBUG "%s: assign_addrs: aa5500ff87(%02x)\n",
+                        port->name, s);
+               return -ENXIO;
+       }
+
+       parport_write_data (port, 0x78); udelay (2);
+       last_dev = 0; /* We've just been speaking to a device, so we
+                        know there must be at least _one_ out there. */
+
+       for (daisy = 0; daisy < 4; daisy++) {
+               parport_write_data (port, daisy);
+               udelay (2);
+               parport_frob_control (port,
+                                     PARPORT_CONTROL_STROBE,
+                                     PARPORT_CONTROL_STROBE);
+               udelay (1);
+               parport_frob_control (port, PARPORT_CONTROL_STROBE, 0);
+               udelay (1);
+
+               if (last_dev)
+                       /* No more devices. */
+                       break;
+
+               last_dev = !(parport_read_status (port)
+                            & PARPORT_STATUS_BUSY);
+
+               add_dev (numdevs++, port, daisy);
+       }
+
+       parport_write_data (port, 0xff); udelay (2);
+       DPRINTK (KERN_DEBUG "%s: Found %d daisy-chained devices\n", port->name,
+               numdevs - thisdev);
+
+       /* Ask the new devices to introduce themselves. */
+       deviceid = kmalloc (1000, GFP_KERNEL);
+       if (!deviceid) return 0;
+
+       for (daisy = 0; thisdev < numdevs; thisdev++, daisy++)
+               parport_device_id (thisdev, deviceid, 1000);
+
+       kfree (deviceid);
+       return 0;
+}
+
+/* Find a device with a particular manufacturer and model string,
+   starting from a given device number.  Like the PCI equivalent,
+   'from' itself is skipped. */
+int parport_find_device (const char *mfg, const char *mdl, int from)
+{
+       struct daisydev *d = topology; /* sorted by devnum */
+
+       /* Find where to start. */
+       while (d && d->devnum <= from)
+               d = d->next;
+
+       /* Search. */
+       while (d) {
+               struct parport_device_info *info;
+               info = &d->port->probe_info[1 + d->daisy];
+               if ((!mfg || !strcmp (mfg, info->mfr)) &&
+                   (!mdl || !strcmp (mdl, info->model)))
+                       break;
+
+               d = d->next;
+       }
+
+       if (d)
+               return d->devnum;
+
+       return -1;
+}
+
+/* Find a device in a particular class.  Like the PCI equivalent,
+   'from' itself is skipped. */
+int parport_find_class (parport_device_class cls, int from)
+{
+       struct daisydev *d = topology; /* sorted by devnum */
+
+       /* Find where to start. */
+       while (d && d->devnum <= from)
+               d = d->next;
+
+       /* Search. */
+       while (d && d->port->probe_info[1 + d->daisy].class != cls)
+               d = d->next;
+
+       if (d)
+               return d->devnum;
+
+       return -1;
+}
diff --git a/drivers/parport/ieee1284.c b/drivers/parport/ieee1284.c
new file mode 100644 (file)
index 0000000..de7a269
--- /dev/null
@@ -0,0 +1,545 @@
+/* $Id: parport_ieee1284.c,v 1.4 1997/10/19 21:37:21 philip Exp $
+ * IEEE-1284 implementation for parport.
+ *
+ * Authors: Phil Blundell <Philip.Blundell@pobox.com>
+ *          Carsten Gross <carsten@sol.wohnheim.uni-ulm.de>
+ *         Jose Renau <renau@acm.org>
+ *          Tim Waugh <tim@cyberelk.demon.co.uk> (largely rewritten)
+ *
+ * This file is responsible for IEEE 1284 negotiation, and for handing
+ * read/write requests to low-level drivers.
+ */
+
+#include <linux/config.h>
+#include <linux/threads.h>
+#include <linux/parport.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+
+#undef DEBUG /* undef me for production */
+
+#ifdef CONFIG_LP_CONSOLE
+#undef DEBUG /* Don't want a garbled console */
+#endif
+
+#ifdef DEBUG
+#define DPRINTK(stuff...) printk (stuff)
+#else
+#define DPRINTK(stuff...)
+#endif
+
+/* Make parport_wait_peripheral wake up.
+ * It will be useful to call this from an interrupt handler. */
+void parport_ieee1284_wakeup (struct parport *port)
+{
+       up (&port->physport->ieee1284.irq);
+}
+
+static struct parport *port_from_cookie[PARPORT_MAX];
+static void timeout_waiting_on_port (unsigned long cookie)
+{
+       parport_ieee1284_wakeup (port_from_cookie[cookie % PARPORT_MAX]);
+}
+
+/* Wait for a parport_ieee1284_wakeup.
+ * 0:      success
+ * <0:     error (exit as soon as possible)
+ * >0:     timed out
+ */
+int parport_wait_event (struct parport *port, signed long timeout)
+{
+       int ret;
+       struct timer_list timer;
+
+       if (!port->physport->cad->timeout)
+               /* Zero timeout is special, and we can't down() the
+                  semaphore. */
+               return 1;
+
+       init_timer (&timer);
+       timer.expires = jiffies + timeout;
+       timer.function = timeout_waiting_on_port;
+       port_from_cookie[port->number % PARPORT_MAX] = port;
+       timer.data = port->number;
+
+       add_timer (&timer);
+       ret = down_interruptible (&port->physport->ieee1284.irq);
+       if (!del_timer (&timer) && !ret)
+               /* Timed out. */
+               ret = 1;
+
+       return ret;
+}
+
+/* Wait for Status line(s) to change in 35 ms - see IEEE1284-1994 page 24 to
+ * 25 for this. After this time we can create a timeout because the
+ * peripheral doesn't conform to IEEE1284.  We want to save CPU time: we are
+ * waiting a maximum time of 500 us busy (this is for speed).  If there is
+ * not the right answer in this time, we call schedule and other processes
+ * are able to eat the time up to 40ms.
+ */ 
+
+int parport_wait_peripheral(struct parport *port,
+                           unsigned char mask, 
+                           unsigned char result)
+{
+       int counter;
+       long deadline;
+       unsigned char status;
+
+       counter = port->physport->spintime; /* usecs of fast polling */
+       if (!port->physport->cad->timeout)
+               /* A zero timeout is "special": busy wait for the
+                  entire 35ms. */
+               counter = 35000;
+
+       /* Fast polling.
+        *
+        * This should be adjustable.
+        * How about making a note (in the device structure) of how long
+        * it takes, so we know for next time?
+        */
+       for (counter /= 5; counter > 0; counter--) {
+               status = parport_read_status (port);
+               if ((status & mask) == result)
+                       return 0;
+               if (signal_pending (current))
+                       return -EINTR;
+               if (current->need_resched)
+                       break;
+               udelay(5);
+       }
+
+       if (!port->physport->cad->timeout)
+               /* We may be in an interrupt handler, so we can't poll
+                * slowly anyway. */
+               return 1;
+
+       /* 40ms of slow polling. */
+       deadline = jiffies + (HZ + 24) / 25;
+       while (time_before (jiffies, deadline)) {
+               int ret;
+
+               if (signal_pending (current))
+                       return -EINTR;
+
+               /* Wait for 10ms (or until an interrupt occurs if
+                * the handler is set) */
+               if ((ret = parport_wait_event (port, (HZ + 99) / 100)) < 0)
+                       return ret;
+
+               status = parport_read_status (port);
+               if ((status & mask) == result)
+                       return 0;
+
+               if (!ret) {
+                       /* parport_wait_event didn't time out, but the
+                        * peripheral wasn't actually ready either.
+                        * Wait for another 10ms. */
+                       current->state = TASK_INTERRUPTIBLE;
+                       schedule_timeout ((HZ+ 99) / 100);
+               }
+       }
+
+       return 1;
+}
+
+#ifdef CONFIG_PARPORT_1284
+/* Terminate a negotiated mode. */
+static void parport_ieee1284_terminate (struct parport *port)
+{
+       port = port->physport;
+
+       port->ieee1284.phase = IEEE1284_PH_TERMINATE;
+
+       /* EPP terminates differently. */
+       switch (port->ieee1284.mode) {
+       case IEEE1284_MODE_EPP:
+       case IEEE1284_MODE_EPPSL:
+       case IEEE1284_MODE_EPPSWE:
+               /* Terminate from EPP mode. */
+
+               /* Event 68: Set nInit low */
+               parport_frob_control (port,
+                                     PARPORT_CONTROL_INIT,
+                                     PARPORT_CONTROL_INIT);
+               udelay (50);
+
+               /* Event 69: Set nInit high, nSelectIn low */
+               parport_frob_control (port,
+                                     PARPORT_CONTROL_SELECT,
+                                     PARPORT_CONTROL_SELECT);
+               break;
+               
+       default:
+               /* Terminate from all other modes. */
+
+               /* Event 22: Set nSelectIn low, nAutoFd high */
+               parport_frob_control (port,
+                                     PARPORT_CONTROL_SELECT
+                                     | PARPORT_CONTROL_AUTOFD,
+                                     PARPORT_CONTROL_SELECT);
+
+               /* Event 24: nAck goes low */
+               parport_wait_peripheral (port, PARPORT_STATUS_ACK, 0);
+
+               /* Event 25: Set nAutoFd low */
+               parport_frob_control (port,
+                                     PARPORT_CONTROL_AUTOFD,
+                                     PARPORT_CONTROL_AUTOFD);
+
+               /* Event 27: nAck goes high */
+               parport_wait_peripheral (port,
+                                        PARPORT_STATUS_ACK, 
+                                        PARPORT_STATUS_ACK);
+
+               /* Event 29: Set nAutoFd high */
+               parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0);
+       }
+
+       port->ieee1284.mode = IEEE1284_MODE_COMPAT;
+       port->ieee1284.phase = IEEE1284_PH_FWD_IDLE;
+
+       DPRINTK (KERN_DEBUG "%s: In compatibility (forward idle) mode\n",
+                port->name);
+}              
+#endif /* IEEE1284 support */
+
+/* Negotiate an IEEE 1284 mode.
+ * return values are:
+ *   0 - handshake OK; IEEE1284 peripheral and mode available
+ *  -1 - handshake failed; peripheral is not compliant (or none present)
+ *   1 - handshake OK; IEEE1284 peripheral present but mode not available
+ */
+int parport_negotiate (struct parport *port, int mode)
+{
+#ifndef CONFIG_PARPORT_1284
+       if (mode == IEEE1284_MODE_COMPAT)
+               return 0;
+       printk (KERN_ERR "parport: IEEE1284 not supported in this kernel\n");
+       return -1;
+#else
+       int m = mode & ~IEEE1284_ADDR;
+       unsigned char xflag;
+
+       port = port->physport;
+
+       /* Is there anything to do? */
+       if (port->ieee1284.mode == mode)
+               return 0;
+
+       /* Is the difference just an address-or-not bit? */
+       if ((port->ieee1284.mode & ~IEEE1284_ADDR) == (mode & ~IEEE1284_ADDR)){
+               port->ieee1284.mode = mode;
+               return 0;
+       }
+
+       /* Go to compability forward idle mode */
+       if (port->ieee1284.mode != IEEE1284_MODE_COMPAT)
+               parport_ieee1284_terminate (port);
+
+       if (mode == IEEE1284_MODE_COMPAT)
+               /* Compatibility mode: no negotiation. */
+               return 0; 
+
+       switch (mode) {
+       case IEEE1284_MODE_ECPSWE:
+               m = IEEE1284_MODE_ECP;
+               break;
+       case IEEE1284_MODE_EPPSL:
+       case IEEE1284_MODE_EPPSWE:
+               m = IEEE1284_MODE_EPP;
+               break;
+       case IEEE1284_MODE_BECP:
+               return -ENOSYS; /* FIXME (implement BECP) */
+       }
+
+       port->ieee1284.phase = IEEE1284_PH_NEGOTIATION;
+
+       /* Start off with nStrobe and nAutoFd high, and nSelectIn low */
+       parport_frob_control (port,
+                             PARPORT_CONTROL_STROBE
+                             | PARPORT_CONTROL_AUTOFD
+                             | PARPORT_CONTROL_SELECT,
+                             PARPORT_CONTROL_SELECT);
+       udelay(1);
+
+       /* Event 0: Set data */
+       parport_write_data (port, m);
+       udelay (400); /* Shouldn't need to wait this long. */
+
+       /* Event 1: Set nSelectIn high, nAutoFd low */
+       parport_frob_control (port,
+                             PARPORT_CONTROL_SELECT
+                             | PARPORT_CONTROL_AUTOFD,
+                             PARPORT_CONTROL_AUTOFD);
+
+       /* Event 2: PError, Select, nFault go high, nAck goes low */
+       if (parport_wait_peripheral (port,
+                                    PARPORT_STATUS_ERROR
+                                    | PARPORT_STATUS_SELECT
+                                    | PARPORT_STATUS_PAPEROUT
+                                    | PARPORT_STATUS_ACK,
+                                    PARPORT_STATUS_ERROR
+                                    | PARPORT_STATUS_SELECT
+                                    | PARPORT_STATUS_PAPEROUT)) {
+               /* Timeout */
+               parport_frob_control (port,
+                                     PARPORT_CONTROL_SELECT
+                                     | PARPORT_CONTROL_AUTOFD,
+                                     PARPORT_CONTROL_SELECT);
+               DPRINTK (KERN_DEBUG
+                        "%s: Peripheral not IEEE1284 compliant (0x%02X)\n",
+                        port->name, parport_read_status (port));
+               port->ieee1284.phase = IEEE1284_PH_FWD_IDLE;
+               return -1; /* Not IEEE1284 compliant */
+       }
+
+       /* Event 3: Set nStrobe low */
+       parport_frob_control (port,
+                             PARPORT_CONTROL_STROBE,
+                             PARPORT_CONTROL_STROBE);
+
+       /* Event 4: Set nStrobe and nAutoFd high */
+       udelay (5);
+       parport_frob_control (port,
+                             PARPORT_CONTROL_STROBE
+                             | PARPORT_CONTROL_AUTOFD,
+                             0);
+
+       /* Event 6: nAck goes high */
+       if (parport_wait_peripheral (port,
+                                    PARPORT_STATUS_ACK
+                                    | PARPORT_STATUS_PAPEROUT,
+                                    PARPORT_STATUS_ACK)) {
+               if (parport_read_status (port) & PARPORT_STATUS_ACK)
+                       printk (KERN_DEBUG
+                               "%s: working around buggy peripheral: tell "
+                               "Tim what make it is\n", port->name);
+               DPRINTK (KERN_DEBUG
+                        "%s: Mode 0x%02x not supported? (0x%02x)\n",
+                        port->name, mode, port->ops->read_status (port));
+               parport_ieee1284_terminate (port);
+               return 1;
+       }
+
+       xflag = parport_read_status (port) & PARPORT_STATUS_SELECT;
+
+       /* xflag should be high for all modes other than nibble (0). */
+       if (mode && !xflag) {
+               /* Mode not supported. */
+               DPRINTK (KERN_DEBUG "%s: Mode 0x%02x not supported\n",
+                        port->name, mode);
+               parport_ieee1284_terminate (port);
+               return 1;
+       }
+
+       /* Mode is supported */
+       DPRINTK (KERN_DEBUG "%s: In mode 0x%02x\n", port->name, mode);
+       port->ieee1284.mode = mode;
+
+       /* But ECP is special */
+       if (mode & IEEE1284_MODE_ECP) {
+               port->ieee1284.phase = IEEE1284_PH_ECP_SETUP;
+
+               /* Event 30: Set nAutoFd low */
+               parport_frob_control (port,
+                                     PARPORT_CONTROL_AUTOFD,
+                                     PARPORT_CONTROL_AUTOFD);
+
+               /* Event 31: PError goes high. */
+               parport_wait_peripheral (port,
+                                        PARPORT_STATUS_PAPEROUT,
+                                        PARPORT_STATUS_PAPEROUT);
+               /* (Should check that this works..) */
+
+               port->ieee1284.phase = IEEE1284_PH_FWD_IDLE;
+               DPRINTK (KERN_DEBUG "%s: ECP direction: forward\n",
+                        port->name);
+       } else switch (mode) {
+       case IEEE1284_MODE_NIBBLE:
+       case IEEE1284_MODE_BYTE:
+               port->ieee1284.phase = IEEE1284_PH_REV_IDLE;
+               break;
+       default:
+               port->ieee1284.phase = IEEE1284_PH_FWD_IDLE;
+       }
+
+
+       return 0;
+#endif /* IEEE1284 support */
+}
+
+/* Acknowledge that the peripheral has data available.
+ * Events 18-20, in order to get from Reverse Idle phase
+ * to Host Busy Data Available.
+ * This will most likely be called from an interrupt.
+ * Returns zero if data was available.
+ */
+#ifdef CONFIG_PARPORT_1284
+static int parport_ieee1284_ack_data_avail (struct parport *port)
+{
+       if (parport_read_status (port) & PARPORT_STATUS_ERROR)
+               /* Event 18 didn't happen. */
+               return -1;
+
+       /* Event 20: nAutoFd goes high. */
+       port->ops->frob_control (port, PARPORT_CONTROL_AUTOFD, 0);
+       port->ieee1284.phase = IEEE1284_PH_HBUSY_DAVAIL;
+       return 0;
+}
+#endif /* IEEE1284 support */
+
+/* Handle an interrupt. */
+void parport_ieee1284_interrupt (int which, void *handle, struct pt_regs *regs)
+{
+       struct parport *port = handle;
+       parport_ieee1284_wakeup (port);
+
+#ifdef CONFIG_PARPORT_1284
+       if (port->ieee1284.phase == IEEE1284_PH_REV_IDLE) {
+               /* An interrupt in this phase means that data
+                * is now available. */
+               DPRINTK (KERN_DEBUG "%s: Data available\n", port->name);
+               parport_ieee1284_ack_data_avail (port);
+       }
+#endif /* IEEE1284 support */
+}
+
+/* Write a block of data. */
+ssize_t parport_write (struct parport *port, const void *buffer, size_t len)
+{
+#ifndef CONFIG_PARPORT_1284
+       return port->ops->compat_write_data (port, buffer, len, 0);
+#else
+       ssize_t retval;
+       int mode = port->ieee1284.mode;
+       int addr = mode & IEEE1284_ADDR;
+       size_t (*fn) (struct parport *, const void *, size_t, int);
+
+       /* Ignore the device-ID-request bit and the address bit. */
+       mode &= ~(IEEE1284_DEVICEID | IEEE1284_ADDR);
+
+       /* Use the mode we're in. */
+       switch (mode) {
+       case IEEE1284_MODE_NIBBLE:
+               parport_negotiate (port, IEEE1284_MODE_COMPAT);
+       case IEEE1284_MODE_COMPAT:
+               DPRINTK (KERN_DEBUG "%s: Using compatibility mode\n",
+                        port->name);
+               fn = port->ops->compat_write_data;
+               break;
+
+       case IEEE1284_MODE_EPP:
+               DPRINTK (KERN_DEBUG "%s: Using EPP mode\n", port->name);
+               if (addr)
+                       fn = port->ops->epp_write_addr;
+               else
+                       fn = port->ops->epp_write_data;
+               break;
+
+       case IEEE1284_MODE_ECP:
+       case IEEE1284_MODE_ECPRLE:
+               DPRINTK (KERN_DEBUG "%s: Using ECP mode\n", port->name);
+               if (addr)
+                       fn = port->ops->ecp_write_addr;
+               else
+                       fn = port->ops->ecp_write_data;
+               break;
+
+       case IEEE1284_MODE_ECPSWE:
+               DPRINTK (KERN_DEBUG "%s: Using software-emulated ECP mode\n",
+                        port->name);
+               /* The caller has specified that it must be emulated,
+                * even if we have ECP hardware! */
+               if (addr)
+                       fn = parport_ieee1284_ecp_write_addr;
+               else
+                       fn = parport_ieee1284_ecp_write_data;
+               break;
+
+       default:
+               DPRINTK (KERN_DEBUG "%s: Unknown mode 0x%02x\n", port->name,
+                       port->ieee1284.mode);
+               return -ENOSYS;
+       }
+
+       retval = (*fn) (port, buffer, len, 0);
+       DPRINTK (KERN_DEBUG "%s: wrote %d/%d bytes\n", port->name, retval,
+                len);
+       return retval;
+#endif /* IEEE1284 support */
+}
+
+/* Read a block of data. */
+ssize_t parport_read (struct parport *port, void *buffer, size_t len)
+{
+#ifndef CONFIG_PARPORT_1284
+       printk (KERN_ERR "parport: IEEE1284 not supported in this kernel\n");
+       return -ENODEV;
+#else
+       int mode = port->physport->ieee1284.mode;
+       int addr = mode & IEEE1284_ADDR;
+       size_t (*fn) (struct parport *, void *, size_t, int);
+
+       /* Ignore the device-ID-request bit and the address bit. */
+       mode &= ~(IEEE1284_DEVICEID | IEEE1284_ADDR);
+
+       /* Use the mode we're in. */
+       switch (mode) {
+       case IEEE1284_MODE_COMPAT:
+               if (parport_negotiate (port, IEEE1284_MODE_NIBBLE))
+                       return -EIO;
+       case IEEE1284_MODE_NIBBLE:
+               DPRINTK (KERN_DEBUG "%s: Using nibble mode\n", port->name);
+               fn = port->ops->nibble_read_data;
+               break;
+
+       case IEEE1284_MODE_BYTE:
+               DPRINTK (KERN_DEBUG "%s: Using byte mode\n", port->name);
+               fn = port->ops->byte_read_data;
+               break;
+
+       case IEEE1284_MODE_EPP:
+               DPRINTK (KERN_DEBUG "%s: Using EPP mode\n", port->name);
+               if (addr)
+                       fn = port->ops->epp_read_addr;
+               else
+                       fn = port->ops->epp_read_data;
+               break;
+
+       case IEEE1284_MODE_ECP:
+       case IEEE1284_MODE_ECPRLE:
+               DPRINTK (KERN_DEBUG "%s: Using ECP mode\n", port->name);
+               fn = port->ops->ecp_read_data;
+               break;
+
+       case IEEE1284_MODE_ECPSWE:
+               DPRINTK (KERN_DEBUG "%s: Using software-emulated ECP mode\n",
+                        port->name);
+               fn = parport_ieee1284_ecp_read_data;
+               break;
+
+       default:
+               DPRINTK (KERN_DEBUG "%s: Unknown mode 0x%02x\n", port->name,
+                        port->physport->ieee1284.mode);
+               return -ENOSYS;
+       }
+
+       return (*fn) (port, buffer, len, 0);
+#endif /* IEEE1284 support */
+}
+
+/* Set the amount of time we wait while nothing's happening. */
+long parport_set_timeout (struct pardevice *dev, long inactivity)
+{
+       long int old = dev->timeout;
+
+       dev->timeout = inactivity;
+
+       if (dev->port->physport->cad == dev)
+               parport_ieee1284_wakeup (dev->port);
+
+       return old;
+}
diff --git a/drivers/parport/ieee1284_ops.c b/drivers/parport/ieee1284_ops.c
new file mode 100644 (file)
index 0000000..4fbeba6
--- /dev/null
@@ -0,0 +1,848 @@
+/* IEEE-1284 operations for parport.
+ *
+ * This file is for generic IEEE 1284 operations.  The idea is that
+ * they are used by the low-level drivers.  If they have a special way
+ * of doing something, they can provide their own routines (and put
+ * the function pointers in port->ops); if not, they can just use these
+ * as a fallback.
+ *
+ * Note: Make no assumptions about hardware or architecture in this file!
+ *
+ * Author: Tim Waugh <tim@cyberelk.demon.co.uk>
+ */
+
+#include <linux/config.h>
+#include <linux/parport.h>
+#include <linux/delay.h>
+#include <asm/uaccess.h>
+
+#define DEBUG /* undef me for production */
+
+#ifdef CONFIG_LP_CONSOLE
+#undef DEBUG /* Don't want a garbled console */
+#endif
+
+#ifdef DEBUG
+#define DPRINTK(stuff...) printk (stuff)
+#else
+#define DPRINTK(stuff...)
+#endif
+
+/***                                *
+ * One-way data transfer functions. *
+ *                                ***/
+
+static inline
+int polling (struct pardevice *dev)
+{
+       return dev->port->irq == PARPORT_IRQ_NONE;
+}
+
+/* Compatibility mode. */
+size_t parport_ieee1284_write_compat (struct parport *port,
+                                     const void *buffer, size_t len,
+                                     int flags)
+{
+       ssize_t count = 0;
+       const unsigned char *addr = buffer;
+       unsigned char byte;
+       struct pardevice *dev = port->physport->cad;
+       unsigned char ctl = (PARPORT_CONTROL_SELECT
+                            | PARPORT_CONTROL_INIT);
+
+       if (port->irq != PARPORT_IRQ_NONE)
+               parport_enable_irq (port);
+
+       port->physport->ieee1284.phase = IEEE1284_PH_FWD_DATA;
+       while (count < len) {
+               long expire = jiffies + dev->timeout;
+               long wait = (HZ + 99) / 100;
+               unsigned char mask = (PARPORT_STATUS_ERROR
+                                     | PARPORT_STATUS_BUSY);
+               unsigned char val = (PARPORT_STATUS_ERROR
+                                    | PARPORT_STATUS_BUSY);
+               int i;
+
+               /* Write the character to the data lines. */
+               byte = *addr++;
+               parport_write_data (port, byte);
+               udelay (1);
+
+               /* Wait until the peripheral's ready */
+               do {
+                       /* Is the peripheral ready yet? */
+                       if (!parport_wait_peripheral (port, mask, val))
+                               /* Skip the loop */
+                               goto ready;
+
+                       /* Is the peripheral upset? */
+                       if ((parport_read_status (port) &
+                            (PARPORT_STATUS_PAPEROUT |
+                             PARPORT_STATUS_SELECT |
+                             PARPORT_STATUS_ERROR))
+                           != (PARPORT_STATUS_SELECT |
+                               PARPORT_STATUS_ERROR))
+                               /* If nFault is asserted (i.e. no
+                                * error) and PAPEROUT and SELECT are
+                                * just red herrings, give the driver
+                                * a chance to check it's happy with
+                                * that before continuing. */
+                               goto stop;
+
+                       /* Have we run out of time? */
+                       if (!time_before (jiffies, expire))
+                               break;
+
+                       /* Yield the port for a while.  If this is the
+                           first time around the loop, don't let go of
+                           the port.  This way, we find out if we have
+                           our interrupt handler called. */
+                       if (count && polling (dev)) {
+                               parport_release (dev);
+                               current->state = TASK_INTERRUPTIBLE;
+                               schedule_timeout (wait);
+                               parport_claim_or_block (dev);
+                       }
+                       else
+                               /* We must have the device claimed here */
+                               parport_wait_event (port, wait);
+
+                       /* Is there a signal pending? */
+                       if (signal_pending (current))
+                               goto stop;
+
+                       /* Wait longer next time. */
+                       wait *= 2;
+               } while (time_before (jiffies, expire));
+
+               DPRINTK (KERN_DEBUG "%s: Timed out\n", port->name);
+               break;
+
+       ready:
+               /* Clear out previous irqs. */
+               while (!down_trylock (&port->physport->ieee1284.irq));
+
+               /* Pulse strobe. */
+               parport_write_control (port, ctl | PARPORT_CONTROL_STROBE);
+               udelay (1); /* strobe */
+
+               parport_write_control (port, ctl);
+               udelay (1); /* hold */
+
+               /* Wait until it's received (up to 20us). */
+               for (i = 0; i < 20; i++) {
+                       if (!down_trylock (&port->physport->ieee1284.irq) ||
+                           !(parport_read_status (port) & PARPORT_STATUS_ACK))
+                               break;
+                       udelay (1);
+               }
+
+               count++;
+
+                /* Let another process run if it needs to. */
+               if (time_before (jiffies, expire))
+                       if (!parport_yield_blocking (dev)
+                           && current->need_resched)
+                               schedule ();
+       }
+ stop:
+       port->physport->ieee1284.phase = IEEE1284_PH_FWD_IDLE;
+
+       return count;
+}
+
+/* Nibble mode. */
+size_t parport_ieee1284_read_nibble (struct parport *port, 
+                                    void *buffer, size_t len,
+                                    int flags)
+{
+#ifndef CONFIG_PARPORT_1284
+       return 0;
+#else
+       unsigned char *buf = buffer;
+       int i;
+       unsigned char byte = 0;
+
+       len *= 2; /* in nibbles */
+       for (i=0; i < len; i++) {
+               unsigned char nibble;
+
+               /* Does the error line indicate end of data? */
+               if (((i & 1) == 0) &&
+                   (parport_read_status(port) & PARPORT_STATUS_ERROR)) {
+                       port->physport->ieee1284.phase = IEEE1284_PH_HBUSY_DNA;
+                       DPRINTK (KERN_DEBUG
+                               "%s: No more nibble data (%d bytes)\n",
+                               port->name, i/2);
+
+                       /* Go to reverse idle phase. */
+                       parport_frob_control (port,
+                                             PARPORT_CONTROL_AUTOFD,
+                                             PARPORT_CONTROL_AUTOFD);
+                       port->physport->ieee1284.phase = IEEE1284_PH_REV_IDLE;
+                       break;
+               }
+
+               /* Event 7: Set nAutoFd low. */
+               parport_frob_control (port,
+                                     PARPORT_CONTROL_AUTOFD,
+                                     PARPORT_CONTROL_AUTOFD);
+
+               /* Event 9: nAck goes low. */
+               port->ieee1284.phase = IEEE1284_PH_REV_DATA;
+               if (parport_wait_peripheral (port,
+                                            PARPORT_STATUS_ACK, 0)) {
+                       /* Timeout -- no more data? */
+                       DPRINTK (KERN_DEBUG
+                                "%s: Nibble timeout at event 9 (%d bytes)\n",
+                                port->name, i/2);
+                       break;
+               }
+
+
+               /* Read a nibble. */
+               nibble = parport_read_status (port) >> 3;
+               nibble &= ~8;
+               if ((nibble & 0x10) == 0)
+                       nibble |= 8;
+               nibble &= 0xf;
+
+               /* Event 10: Set nAutoFd high. */
+               parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0);
+
+               /* Event 11: nAck goes high. */
+               if (parport_wait_peripheral (port,
+                                            PARPORT_STATUS_ACK,
+                                            PARPORT_STATUS_ACK)) {
+                       /* Timeout -- no more data? */
+                       DPRINTK (KERN_DEBUG
+                                "%s: Nibble timeout at event 11\n",
+                                port->name);
+                       break;
+               }
+
+               if (i & 1) {
+                       /* Second nibble */
+                       byte |= nibble << 4;
+                       *buf++ = byte;
+               } else 
+                       byte = nibble;
+       }
+
+       i /= 2; /* i is now in bytes */
+
+       if (i == len) {
+               /* Read the last nibble without checking data avail. */
+               port = port->physport;
+               if (parport_read_status (port) & PARPORT_STATUS_ERROR)
+                       port->ieee1284.phase = IEEE1284_PH_HBUSY_DNA;
+               else
+                       port->ieee1284.phase = IEEE1284_PH_HBUSY_DAVAIL;
+       }
+
+       return i;
+#endif /* IEEE1284 support */
+}
+
+/* Byte mode. */
+size_t parport_ieee1284_read_byte (struct parport *port,
+                                  void *buffer, size_t len,
+                                  int flags)
+{
+#ifndef CONFIG_PARPORT_1284
+       return 0;
+#else
+       unsigned char *buf = buffer;
+       ssize_t count = 0;
+
+       for (count = 0; count < len; count++) {
+               unsigned char byte;
+
+               /* Data available? */
+               if (parport_read_status (port) & PARPORT_STATUS_ERROR) {
+                       port->physport->ieee1284.phase = IEEE1284_PH_HBUSY_DNA;
+                       DPRINTK (KERN_DEBUG
+                                "%s: No more byte data (%d bytes)\n",
+                                port->name, count);
+
+                       /* Go to reverse idle phase. */
+                       parport_frob_control (port,
+                                             PARPORT_CONTROL_AUTOFD,
+                                             PARPORT_CONTROL_AUTOFD);
+                       port->physport->ieee1284.phase = IEEE1284_PH_REV_IDLE;
+                       break;
+               }
+
+               /* Event 7: Set nAutoFd low. */
+               parport_frob_control (port,
+                                     PARPORT_CONTROL_AUTOFD,
+                                     PARPORT_CONTROL_AUTOFD);
+
+               /* Event 9: nAck goes low. */
+               port->physport->ieee1284.phase = IEEE1284_PH_REV_DATA;
+               if (parport_wait_peripheral (port,
+                                            PARPORT_STATUS_ACK,
+                                            0)) {
+                       /* Timeout -- no more data? */
+                       parport_frob_control (port, PARPORT_CONTROL_AUTOFD,
+                                                0);
+                       DPRINTK (KERN_DEBUG "%s: Byte timeout at event 9\n",
+                                port->name);
+                       break;
+               }
+
+               byte = parport_read_data (port);
+               *buf++ = byte;
+
+               /* Event 10: Set nAutoFd high */
+               parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0);
+
+               /* Event 11: nAck goes high. */
+               if (parport_wait_peripheral (port,
+                                            PARPORT_STATUS_ACK,
+                                            PARPORT_STATUS_ACK)) {
+                       /* Timeout -- no more data? */
+                       DPRINTK (KERN_DEBUG "%s: Byte timeout at event 11\n",
+                                port->name);
+                       break;
+               }
+
+               /* Event 16: Set nStrobe low. */
+               parport_frob_control (port,
+                                     PARPORT_CONTROL_STROBE,
+                                     PARPORT_CONTROL_STROBE);
+               udelay (5);
+
+               /* Event 17: Set nStrobe high. */
+               parport_frob_control (port, PARPORT_CONTROL_STROBE, 0);
+       }
+
+       if (count == len) {
+               /* Read the last byte without checking data avail. */
+               port = port->physport;
+               if (parport_read_status (port) & PARPORT_STATUS_ERROR)
+                       port->ieee1284.phase = IEEE1284_PH_HBUSY_DNA;
+               else
+                       port->ieee1284.phase = IEEE1284_PH_HBUSY_DAVAIL;
+       }
+
+       return count;
+#endif /* IEEE1284 support */
+}
+
+/***              *
+ * ECP Functions. *
+ *              ***/
+
+#ifdef CONFIG_PARPORT_1284
+
+static inline
+int ecp_forward_to_reverse (struct parport *port)
+{
+       int retval;
+
+       /* Event 38: Set nAutoFd low */
+       parport_frob_control (port,
+                             PARPORT_CONTROL_AUTOFD,
+                             PARPORT_CONTROL_AUTOFD);
+       parport_data_reverse (port);
+       udelay (5);
+
+       /* Event 39: Set nInit low to initiate bus reversal */
+       parport_frob_control (port,
+                             PARPORT_CONTROL_INIT,
+                             PARPORT_CONTROL_INIT);
+
+       /* Event 40: PError goes low */
+       retval = parport_wait_peripheral (port,
+                                         PARPORT_STATUS_PAPEROUT, 0);
+
+       if (!retval) {
+               DPRINTK (KERN_DEBUG "%s: ECP direction: reverse\n",
+                        port->name);
+               port->ieee1284.phase = IEEE1284_PH_REV_IDLE;
+       }
+
+       return retval;
+}
+
+static inline
+int ecp_reverse_to_forward (struct parport *port)
+{
+       int retval;
+
+       /* Event 47: Set nInit high */
+       parport_frob_control (port,
+                             PARPORT_CONTROL_INIT,
+                             PARPORT_CONTROL_INIT);
+       parport_data_reverse (port);
+
+       /* Event 49: PError goes high */
+       retval = parport_wait_peripheral (port,
+                                         PARPORT_STATUS_PAPEROUT,
+                                         PARPORT_STATUS_PAPEROUT);
+
+       if (!retval) {
+               parport_data_forward (port);
+               DPRINTK (KERN_DEBUG "%s: ECP direction: forward\n",
+                        port->name);
+               port->ieee1284.phase = IEEE1284_PH_FWD_IDLE;
+       }
+
+       return retval;
+}
+
+#endif /* IEEE1284 support */
+
+/* ECP mode, forward channel, data. */
+size_t parport_ieee1284_ecp_write_data (struct parport *port,
+                                       const void *buffer, size_t len,
+                                       int flags)
+{
+#ifndef CONFIG_PARPORT_1284
+       return 0;
+#else
+       const unsigned char *buf = buffer;
+       size_t written;
+       int ctl = parport_read_control (port) & ~PARPORT_CONTROL_AUTOFD;
+       int retry;
+
+       port = port->physport;
+
+       if (port->ieee1284.phase != IEEE1284_PH_FWD_IDLE)
+               if (ecp_reverse_to_forward (port))
+                       return 0;
+
+       port->ieee1284.phase = IEEE1284_PH_FWD_DATA;
+
+       /* HostAck high (data, not command) */
+       parport_write_control (port, ctl);
+       for (written = 0; written < len; written++, buf++) {
+               long expire = jiffies + port->cad->timeout;
+               unsigned char byte;
+
+               byte = *buf;
+       try_again:
+               parport_write_data (port, byte);
+               parport_write_control (port, ctl | PARPORT_CONTROL_STROBE);
+               udelay (5);
+               for (retry = 0; retry < 100; retry++) {
+                       if (!parport_wait_peripheral (port,
+                                                     PARPORT_STATUS_BUSY, 0))
+                               goto success;
+
+                       if (signal_pending (current)) {
+                               parport_write_control (port, ctl);
+                               break;
+                       }
+               }
+
+               /* Time for Host Transfer Recovery (page 41 of IEEE1284) */
+               DPRINTK (KERN_DEBUG "%s: ECP transfer stalled!\n", port->name);
+
+               parport_write_control (port, ctl | PARPORT_CONTROL_INIT);
+               udelay (50);
+               if (parport_read_status (port) & PARPORT_STATUS_PAPEROUT) {
+                       /* It's buggered. */
+                       parport_write_control (port, ctl);
+                       break;
+               }
+
+               parport_write_control (port, ctl);
+               udelay (50);
+               if (!(parport_read_status (port) & PARPORT_STATUS_PAPEROUT))
+                       break;
+
+               DPRINTK (KERN_DEBUG "%s: Host transfer recovered\n",
+                        port->name);
+
+               if (time_after_eq (jiffies, expire)) break;
+               goto try_again;
+       success:
+               parport_write_control (port, ctl);
+               udelay (5);
+               if (parport_wait_peripheral (port,
+                                            PARPORT_STATUS_BUSY,
+                                            PARPORT_STATUS_BUSY))
+                       /* Peripheral hasn't accepted the data. */
+                       break;
+       }
+
+       port->ieee1284.phase = IEEE1284_PH_FWD_IDLE;
+
+       return written;
+#endif /* IEEE1284 support */
+}
+
+/* ECP mode, reverse channel, data. */
+size_t parport_ieee1284_ecp_read_data (struct parport *port,
+                                      void *buffer, size_t len, int flags)
+{
+#ifndef CONFIG_PARPORT_1284
+       return 0;
+#else
+       struct pardevice *dev = port->cad;
+       unsigned char *buf = buffer;
+       int rle_count = 0; /* shut gcc up */
+       int rle = 0;
+       ssize_t count = 0;
+
+       port = port->physport;
+
+       if (port->ieee1284.phase != IEEE1284_PH_REV_IDLE)
+               if (ecp_forward_to_reverse (port))
+                       return 0;
+
+       port->ieee1284.phase = IEEE1284_PH_REV_DATA;
+
+       /* Set HostAck low to start accepting data. */
+       parport_frob_control (port, PARPORT_CONTROL_AUTOFD,
+                             PARPORT_CONTROL_AUTOFD);
+       while (count < len) {
+               long expire = jiffies + dev->timeout;
+               unsigned char byte;
+               int command;
+
+               /* Event 43: Peripheral sets nAck low. It can take as
+                   long as it wants. */
+               while (parport_wait_peripheral (port,
+                                               PARPORT_STATUS_ACK,
+                                               PARPORT_STATUS_ACK)) {
+                       /* The peripheral hasn't given us data in
+                          35ms.  If we have data to give back to the
+                          caller, do it now. */
+                       if (count)
+                               goto out;
+
+                       /* If we've used up all the time we were allowed,
+                          give up altogether. */
+                       if (!time_before (jiffies, expire))
+                               goto out;
+
+                       /* Yield the port for a while. */
+                       if (count && polling (dev)) {
+                               parport_release (dev);
+                               current->state = TASK_INTERRUPTIBLE;
+                               schedule_timeout ((HZ + 99) / 25);
+                               parport_claim_or_block (dev);
+                       }
+                       else
+                               /* We must have the device claimed here. */
+                               parport_wait_event (port, (HZ + 99) / 25);
+
+                       /* Is there a signal pending? */
+                       if (signal_pending (current))
+                               goto out;
+               }
+
+               /* Is this a command? */
+               if (rle)
+                       /* The last byte was a run-length count, so
+                           this can't be as well. */
+                       command = 0;
+               else
+                       command = (parport_read_status (port) &
+                                  PARPORT_STATUS_BUSY) ? 1 : 0;
+
+               /* Read the data. */
+               byte = parport_read_data (port);
+
+               /* If this is a channel command, rather than an RLE
+                   command or a normal data byte, don't accept it. */
+               if (command) {
+                       if (byte & 0x80) {
+                               DPRINTK (KERN_DEBUG "%s: stopping short at "
+                                        "channel command (%02x)\n",
+                                        port->name, byte);
+                               goto out;
+                       }
+                       else if (port->ieee1284.mode != IEEE1284_MODE_ECPRLE)
+                               DPRINTK (KERN_DEBUG "%s: device illegally "
+                                        "using RLE; accepting anyway\n",
+                                        port->name);
+
+                       rle_count = byte + 1;
+
+                       /* Are we allowed to read that many bytes? */
+                       if (rle_count > (len - count)) {
+                               DPRINTK (KERN_DEBUG "%s: leaving %d RLE bytes "
+                                        "for next time\n", port->name,
+                                        rle_count);
+                               break;
+                       }
+
+                       rle = 1;
+               }
+
+               /* Event 44: Set HostAck high, acknowledging handshake. */
+               parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0);
+
+               /* Event 45: The peripheral has 35ms to set nAck high. */
+               if (parport_wait_peripheral (port, PARPORT_STATUS_ACK, 0)) {
+                       /* It's gone wrong.  Return what data we have
+                           to the caller. */
+                       DPRINTK (KERN_DEBUG "ECP read timed out at 45\n");
+
+                       if (command)
+                               printk (KERN_WARNING
+                                       "%s: command ignored (%02x)\n",
+                                       port->name, byte);
+
+                       break;
+               }
+
+               /* Event 46: Set HostAck low and accept the data. */
+               parport_frob_control (port,
+                                     PARPORT_CONTROL_AUTOFD,
+                                     PARPORT_CONTROL_AUTOFD);
+
+               /* If we just read a run-length count, fetch the data. */
+               if (command)
+                       continue;
+
+               /* If this is the byte after a run-length count, decompress. */
+               if (rle) {
+                       rle = 0;
+                       memset (buf, byte, rle_count);
+                       buf += rle_count;
+                       count += rle_count;
+                       DPRINTK (KERN_DEBUG "%s: decompressed to %d bytes\n",
+                                port->name, rle_count);
+               }
+               else
+                       /* Normal data byte. */
+                       *buf++ = byte, count++;
+       }
+
+ out:
+       return count;
+#endif /* IEEE1284 support */
+}
+
+/* ECP mode, forward channel, commands. */
+size_t parport_ieee1284_ecp_write_addr (struct parport *port,
+                                       const void *buffer, size_t len,
+                                       int flags)
+{
+#ifndef CONFIG_PARPORT_1284
+       return 0;
+#else
+       const unsigned char *buf = buffer;
+       size_t written;
+       int ctl = parport_read_control (port) | PARPORT_CONTROL_AUTOFD;
+       int retry;
+
+       port = port->physport;
+
+       if (port->ieee1284.phase != IEEE1284_PH_FWD_IDLE)
+               if (ecp_reverse_to_forward (port))
+                       return 0;
+
+       port->ieee1284.phase = IEEE1284_PH_FWD_DATA;
+
+       /* HostAck low (command, not data) */
+       parport_write_control (port, ctl);
+       for (written = 0; written < len; written++, buf++) {
+               long expire = jiffies + port->cad->timeout;
+               unsigned char byte;
+
+               byte = *buf;
+       try_again:
+               parport_write_data (port, byte);
+               parport_write_control (port, ctl | PARPORT_CONTROL_STROBE);
+               udelay (5);
+               for (retry = 0; retry < 100; retry++) {
+                       if (!parport_wait_peripheral (port,
+                                                     PARPORT_STATUS_BUSY, 0))
+                               goto success;
+
+                       if (signal_pending (current)) {
+                               parport_write_control (port, ctl);
+                               break;
+                       }
+               }
+
+               /* Time for Host Transfer Recovery (page 41 of IEEE1284) */
+               DPRINTK (KERN_DEBUG "%s: ECP transfer stalled!\n", port->name);
+
+               parport_write_control (port, ctl | PARPORT_CONTROL_INIT);
+               udelay (50);
+               if (parport_read_status (port) & PARPORT_STATUS_PAPEROUT) {
+                       /* It's buggered. */
+                       parport_write_control (port, ctl);
+                       break;
+               }
+
+               parport_write_control (port, ctl);
+               udelay (50);
+               if (!(parport_read_status (port) & PARPORT_STATUS_PAPEROUT))
+                       break;
+
+               DPRINTK (KERN_DEBUG "%s: Host transfer recovered\n",
+                        port->name);
+
+               if (time_after_eq (jiffies, expire)) break;
+               goto try_again;
+       success:
+               parport_write_control (port, ctl);
+               udelay (5);
+               if (parport_wait_peripheral (port,
+                                            PARPORT_STATUS_BUSY,
+                                            PARPORT_STATUS_BUSY))
+                       /* Peripheral hasn't accepted the data. */
+                       break;
+       }
+
+       port->ieee1284.phase = IEEE1284_PH_FWD_IDLE;
+
+       return written;
+#endif /* IEEE1284 support */
+}
+
+/***              *
+ * EPP functions. *
+ *              ***/
+
+/* EPP mode, forward channel, data. */
+size_t parport_ieee1284_epp_write_data (struct parport *port,
+                                       const void *buffer, size_t len,
+                                       int flags)
+{
+       /* This is untested */
+       unsigned char *bp = (unsigned char *) buffer;
+       size_t ret = 0;
+
+       parport_frob_control (port,
+                             PARPORT_CONTROL_STROBE |
+                             PARPORT_CONTROL_AUTOFD |
+                             PARPORT_CONTROL_SELECT,
+                             PARPORT_CONTROL_STROBE |
+                             PARPORT_CONTROL_SELECT);
+       port->ops->data_forward (port);
+       for (; len > 0; len--, bp++) {
+               parport_write_data (port, *bp);
+
+               if (parport_wait_peripheral (port, PARPORT_STATUS_BUSY,
+                                            PARPORT_STATUS_BUSY))
+                       break;
+
+               /* Strobe data */
+               parport_frob_control (port, PARPORT_CONTROL_AUTOFD,
+                                     PARPORT_CONTROL_AUTOFD);
+
+               if (parport_wait_peripheral (port, PARPORT_STATUS_BUSY, 0))
+                       break;
+
+               parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0);
+               ret++;
+       }
+
+       return ret;
+}
+
+/* EPP mode, reverse channel, data. */
+size_t parport_ieee1284_epp_read_data (struct parport *port,
+                                      void *buffer, size_t len,
+                                      int flags)
+{
+       /* This is untested. */
+       unsigned char *bp = (unsigned char *) buffer;
+       unsigned ret = 0;
+
+       parport_frob_control (port,
+                             PARPORT_CONTROL_STROBE |
+                             PARPORT_CONTROL_AUTOFD |
+                             PARPORT_CONTROL_SELECT, 0);
+       port->ops->data_reverse (port);
+       for (; len > 0; len--, bp++) {
+               if (parport_wait_peripheral (port, PARPORT_STATUS_BUSY,
+                                            PARPORT_STATUS_BUSY))
+                       break;
+
+               parport_frob_control (port, PARPORT_CONTROL_AUTOFD,
+                                     PARPORT_CONTROL_AUTOFD);
+
+               if (parport_wait_peripheral (port, PARPORT_STATUS_BUSY, 0))
+                       break;
+
+               *bp = parport_read_data (port);
+
+               parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0);
+               ret++;
+       }
+       port->ops->data_forward (port);
+
+       return ret;
+}
+
+/* EPP mode, forward channel, addresses. */
+size_t parport_ieee1284_epp_write_addr (struct parport *port,
+                                       const void *buffer, size_t len,
+                                       int flags)
+{
+       /* This is untested */
+       unsigned char *bp = (unsigned char *) buffer;
+       size_t ret = 0;
+
+       parport_frob_control (port,
+                             PARPORT_CONTROL_STROBE |
+                             PARPORT_CONTROL_SELECT |
+                             PARPORT_CONTROL_AUTOFD,
+                             PARPORT_CONTROL_STROBE |
+                             PARPORT_CONTROL_SELECT);
+       port->ops->data_forward (port);
+       for (; len > 0; len--, bp++) {
+               parport_write_data (port, *bp);
+
+               if (parport_wait_peripheral (port, PARPORT_STATUS_BUSY,
+                                            PARPORT_STATUS_BUSY))
+                       break;
+
+               /* Strobe data */
+               parport_frob_control (port, PARPORT_CONTROL_SELECT,
+                                     PARPORT_CONTROL_SELECT);
+
+               if (parport_wait_peripheral (port, PARPORT_STATUS_BUSY, 0))
+                       break;
+
+               parport_frob_control (port, PARPORT_CONTROL_SELECT, 0);
+               ret++;
+       }
+
+       return ret;
+}
+
+/* EPP mode, reverse channel, addresses. */
+size_t parport_ieee1284_epp_read_addr (struct parport *port,
+                                      void *buffer, size_t len,
+                                      int flags)
+{
+       /* This is untested. */
+       unsigned char *bp = (unsigned char *) buffer;
+       unsigned ret = 0;
+
+       parport_frob_control (port,
+                             PARPORT_CONTROL_STROBE |
+                             PARPORT_CONTROL_SELECT |
+                             PARPORT_CONTROL_AUTOFD, 0);
+       port->ops->data_reverse (port);
+       for (; len > 0; len--, bp++) {
+               if (parport_wait_peripheral (port, PARPORT_STATUS_BUSY,
+                                            PARPORT_STATUS_BUSY))
+                       break;
+
+               parport_frob_control (port, PARPORT_CONTROL_SELECT,
+                                     PARPORT_CONTROL_SELECT);
+
+               if (parport_wait_peripheral (port, PARPORT_STATUS_BUSY, 0))
+                       break;
+
+               *bp = parport_read_data (port);
+
+               parport_frob_control (port, PARPORT_CONTROL_SELECT, 0);
+               ret++;
+       }
+       port->ops->data_forward (port);
+
+       return ret;
+}
diff --git a/drivers/parport/init.c b/drivers/parport/init.c
new file mode 100644 (file)
index 0000000..e4912b4
--- /dev/null
@@ -0,0 +1,210 @@
+/* Parallel-port initialisation code.
+ * 
+ * Authors: David Campbell <campbell@torque.net>
+ *          Tim Waugh <tim@cyberelk.demon.co.uk>
+ *         Jose Renau <renau@acm.org>
+ *
+ * based on work by Grant Guenther <grant@torque.net>
+ *              and Philip Blundell <Philip.Blundell@pobox.com>
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/threads.h>
+
+#include <linux/parport.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/malloc.h>
+#include <linux/init.h>
+
+#ifndef MODULE
+static int io[PARPORT_MAX+1] __initdata = { [0 ... PARPORT_MAX] = 0 };
+static int io_hi[PARPORT_MAX+1] __initdata = { [0 ... PARPORT_MAX] = 0 };
+static int irq[PARPORT_MAX] __initdata = { [0 ... PARPORT_MAX-1] = PARPORT_IRQ_PROBEONLY };
+static int dma[PARPORT_MAX] __initdata = { [0 ... PARPORT_MAX-1] = PARPORT_DMA_NONE };
+
+extern int parport_pc_init(int *io, int *io_hi, int *irq, int *dma);
+extern int parport_ax_init(void);
+
+static int parport_setup_ptr __initdata = 0;
+
+__initfunc(void parport_setup(char *str, int *ints))
+{
+       if (ints[0] == 0) {
+               if (str && !strncmp(str, "auto", 4)) {
+                       irq[0] = PARPORT_IRQ_AUTO;
+                       dma[0] = PARPORT_DMA_AUTO;
+               }
+               else if (str)
+                       printk (KERN_ERR "parport: `%s': huh?\n", str);
+               else
+                       printk (KERN_ERR "parport: parport=.. what?\n");
+               
+               return;
+       }
+       else if (ints[1] == 0) {
+               /* Disable parport if "parport=0" in cmdline */
+               io[0] = PARPORT_DISABLE; 
+               return;
+       }
+
+       if (parport_setup_ptr < PARPORT_MAX) {
+               char *sep;
+               io[parport_setup_ptr] = ints[1];
+               irq[parport_setup_ptr] = PARPORT_IRQ_NONE;
+               dma[parport_setup_ptr] = PARPORT_DMA_NONE;
+               if (ints[0] > 1) {
+                       irq[parport_setup_ptr] = ints[2];
+                       if (ints[0] > 2) {
+                               dma[parport_setup_ptr] = ints[3];
+                               goto done;
+                       }
+
+                       if (str == NULL)
+                               goto done;
+
+                       goto dma_from_str;
+               }
+               else if (str == NULL)
+                       goto done;
+               else if (!strncmp(str, "auto", 4))
+                       irq[parport_setup_ptr] = PARPORT_IRQ_AUTO;
+               else if (strncmp(str, "none", 4) != 0) {
+                       printk(KERN_ERR "parport: bad irq `%s'\n", str);
+                       return;
+               }
+
+               if ((sep = strchr(str, ',')) == NULL) goto done;
+               str = sep+1;
+       dma_from_str:
+               if (!strncmp(str, "auto", 4))
+                       dma[parport_setup_ptr] = PARPORT_DMA_AUTO;
+               else if (strncmp(str, "none", 4) != 0) {
+                       char *ep;
+                       dma[parport_setup_ptr] = simple_strtoul(str, &ep, 0);
+                       if (ep == str) {
+                               printk(KERN_ERR "parport: bad dma `%s'\n",
+                                      str);
+                               return;
+                       }
+               }
+       done:
+               parport_setup_ptr++;
+       } else
+               printk(KERN_ERR "parport=%s ignored, too many ports\n", str);
+}
+#endif
+
+#ifdef MODULE
+int init_module(void)
+{
+#ifdef CONFIG_SYSCTL
+       parport_default_proc_register ();
+#endif
+       return 0;
+}
+
+void cleanup_module(void)
+{
+#ifdef CONFIG_SYSCTL
+       parport_default_proc_unregister ();
+#endif
+}
+
+#else
+
+__initfunc(int parport_init(void))
+{
+       if (io[0] == PARPORT_DISABLE) 
+               return 1;
+
+#ifdef CONFIG_SYSCTL
+       parport_default_proc_register ();
+#endif
+
+#ifdef CONFIG_PARPORT_PC
+       parport_pc_init(io, io_hi, irq, dma);
+#endif
+#ifdef CONFIG_PARPORT_AX
+       parport_ax_init();
+#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
+#ifdef CONFIG_PARPORT_ARC
+       parport_arc_init();
+#endif
+       return 0;
+}
+#endif
+
+/* Exported symbols for modules. */
+
+EXPORT_SYMBOL(parport_claim);
+EXPORT_SYMBOL(parport_claim_or_block);
+EXPORT_SYMBOL(parport_release);
+EXPORT_SYMBOL(parport_register_port);
+EXPORT_SYMBOL(parport_announce_port);
+EXPORT_SYMBOL(parport_unregister_port);
+EXPORT_SYMBOL(parport_register_driver);
+EXPORT_SYMBOL(parport_unregister_driver);
+EXPORT_SYMBOL(parport_register_device);
+EXPORT_SYMBOL(parport_unregister_device);
+EXPORT_SYMBOL(parport_enumerate);
+EXPORT_SYMBOL(parport_negotiate);
+EXPORT_SYMBOL(parport_write);
+EXPORT_SYMBOL(parport_read);
+EXPORT_SYMBOL(parport_ieee1284_wakeup);
+EXPORT_SYMBOL(parport_wait_peripheral);
+EXPORT_SYMBOL(parport_wait_event);
+EXPORT_SYMBOL(parport_set_timeout);
+EXPORT_SYMBOL(parport_ieee1284_interrupt);
+EXPORT_SYMBOL(parport_ieee1284_ecp_write_data);
+EXPORT_SYMBOL(parport_ieee1284_ecp_read_data);
+EXPORT_SYMBOL(parport_ieee1284_ecp_write_addr);
+EXPORT_SYMBOL(parport_ieee1284_write_compat);
+EXPORT_SYMBOL(parport_ieee1284_read_nibble);
+EXPORT_SYMBOL(parport_ieee1284_read_byte);
+EXPORT_SYMBOL(parport_ieee1284_epp_write_data);
+EXPORT_SYMBOL(parport_ieee1284_epp_read_data);
+EXPORT_SYMBOL(parport_ieee1284_epp_write_addr);
+EXPORT_SYMBOL(parport_ieee1284_epp_read_addr);
+EXPORT_SYMBOL(parport_proc_register);
+EXPORT_SYMBOL(parport_proc_unregister);
+EXPORT_SYMBOL(parport_device_proc_register);
+EXPORT_SYMBOL(parport_device_proc_unregister);
+EXPORT_SYMBOL(parport_default_proc_register);
+EXPORT_SYMBOL(parport_default_proc_unregister);
+EXPORT_SYMBOL(parport_parse_irqs);
+EXPORT_SYMBOL(parport_parse_dmas);
+#ifdef CONFIG_PARPORT_1284
+EXPORT_SYMBOL(parport_open);
+EXPORT_SYMBOL(parport_close);
+EXPORT_SYMBOL(parport_device_id);
+EXPORT_SYMBOL(parport_device_num);
+EXPORT_SYMBOL(parport_device_coords);
+EXPORT_SYMBOL(parport_daisy_deselect_all);
+EXPORT_SYMBOL(parport_daisy_select);
+EXPORT_SYMBOL(parport_daisy_init);
+#endif
+
+void inc_parport_count(void)
+{
+#ifdef MODULE
+       MOD_INC_USE_COUNT;
+#endif
+}
+
+void dec_parport_count(void)
+{
+#ifdef MODULE
+       MOD_DEC_USE_COUNT;
+#endif
+}
diff --git a/drivers/parport/multiface.h b/drivers/parport/multiface.h
new file mode 100644 (file)
index 0000000..56769dd
--- /dev/null
@@ -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 (dorchain@mpi-sb.mpg.de)
+ *
+ */
+
+#define PIA_REG_PADWIDTH 255
+
+#define DUARTBASE 0x0000
+#define PITBASE   0x0100
+#define ROMBASE   0x0200
+#define PIABASE   0x4000
+
+#endif
+
diff --git a/drivers/parport/parport_amiga.c b/drivers/parport/parport_amiga.c
new file mode 100644 (file)
index 0000000..eebd44c
--- /dev/null
@@ -0,0 +1,312 @@
+/* Low-level parallel port routines for the Amiga buildin port
+ *
+ * Author: Joerg Dorchain <dorchain@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)
+{
+       /* 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_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,
+
+
+       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);
+               if (request_irq(IRQ_AMIGA_CIAA_FLG, amiga_interrupt, 0,
+                               p->name, p)) {
+                       parport_unregister_port (p);
+                       return 0;
+               }
+
+               if (parport_probe_hook)
+                       (*parport_probe_hook)(p);
+
+               parport_announce_port (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 (p->irq != PARPORT_IRQ_NONE)
+               free_irq(IRQ_AMIGA_CIAA_FLG, p);
+       parport_proc_unregister(this_port);
+       parport_unregister_port(this_port);
+}
+#endif
+
+
diff --git a/drivers/parport/parport_arc.c b/drivers/parport/parport_arc.c
new file mode 100644 (file)
index 0000000..8cba7a6
--- /dev/null
@@ -0,0 +1,160 @@
+/* Low-level parallel port routines for Archimedes onboard hardware
+ *
+ * Author: Phil Blundell <Philip.Blundell@pobox.com>
+ */
+
+/* This driver is for the parallel port hardware found on Acorn's old
+ * range of Archimedes machines.  The A5000 and newer systems have PC-style
+ * I/O hardware and should use the parport_pc driver instead.
+ *
+ * The Acorn printer port hardware is very simple.  There is a single 8-bit
+ * write-only latch for the data port and control/status bits are handled
+ * with various auxilliary input and output lines.  The port is not
+ * bidirectional, does not support any modes other than SPP, and has only
+ * a subset of the standard printer control lines connected.
+ */
+
+#include <linux/threads.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/malloc.h>
+#include <linux/parport.h>
+
+#include <asm/ptrace.h>
+#include <asm/io.h>
+#include <asm/arch/oldlatches.h>
+#include <asm/arch/irqs.h>
+
+#define DATA_ADDRESS    0x3350010
+
+/* This is equivalent to the above and only used for request_region. */
+#define PORT_BASE       0x80000000 | ((DATA_ADDRESS - IO_BASE) >> 2)
+
+/* The hardware can't read from the data latch, so we must use a soft
+   copy. */
+static unsigned char data_copy;
+
+/* These are pretty simple. We know the irq is never shared and the
+   kernel does all the magic that's required. */
+static void arc_enable_irq(struct parport *p)
+{
+       enable_irq(p->irq);
+}
+
+static void arc_disable_irq(struct parport *p)
+{
+       disable_irq(p->irq);
+}
+
+static void arc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+       parport_generic_irq(irq, (struct parport *) dev_id, regs);
+}
+
+static void arc_write_data(struct parport *p, unsigned char data)
+{
+       data_copy = data;
+       outb_t(data, DATA_LATCH);
+}
+
+static unsigned char arc_read_data(struct parport *p)
+{
+       return data_copy;
+}
+
+static void arc_inc_use_count(void)
+{
+#ifdef MODULE
+       MOD_INC_USE_COUNT;
+#endif
+}
+
+static void arc_dec_use_count(void)
+{
+#ifdef MODULE
+       MOD_DEC_USE_COUNT;
+#endif
+}
+
+static void arc_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_arc_ops = 
+{
+       arc_write_data,
+       arc_read_data,
+
+       arc_write_control,
+       arc_read_control,
+       arc_frob_control,
+
+       arc_read_status,
+
+       arc_enable_irq,
+       arc_disable_irq,
+
+       arc_data_forward,
+       arc_data_reverse,
+
+       arc_interrupt,
+
+       arc_init_state,
+       arc_save_state,
+       arc_restore_state,
+
+       arc_inc_use_count,
+       arc_dec_use_count,
+       arc_fill_inode,
+
+       parport_ieee1284_epp_write_data,
+       parport_ieee1284_epp_read_data,
+       parport_ieee1284_epp_write_addr,
+       parport_ieee1284_epp_read_addr,
+
+       parport_ieee1284_ecp_write_data,
+       parport_ieee1284_ecp_read_data,
+       parport_ieee1284_ecp_write_addr,
+       
+       parport_ieee1284_write_compat,
+       parport_ieee1284_read_nibble,
+       parport_ieee1284_read_byte,
+};
+
+/* --- Initialisation code -------------------------------- */
+
+int parport_arc_init(void)
+{
+       /* Archimedes hardware provides only one port, at a fixed address */
+       struct parport *p;
+
+       if (check_region(PORT_BASE, 1))
+               return 0;
+
+       p = parport_register_port (PORT_BASE, IRQ_PRINTERACK,
+                                  PARPORT_DMA_NONE, &parport_arc_ops);
+
+       if (!p)
+               return 0;
+
+       p->modes = PARPORT_MODE_ARCSPP;
+       p->size = 1;
+
+       printk(KERN_INFO "%s: Archimedes on-board port, using irq %d\n",
+              p->irq);
+       parport_proc_register(p);
+
+       /* Tell the high-level drivers about the port. */
+       parport_announce_port (p);
+
+       return 1;
+}
diff --git a/drivers/parport/parport_atari.c b/drivers/parport/parport_atari.c
new file mode 100644 (file)
index 0000000..1222130
--- /dev/null
@@ -0,0 +1,251 @@
+/* Low-level parallel port routines for the Atari builtin port
+ *
+ * Author: Andreas Schwab <schwab@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_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 */
+
+       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;
+               if (request_irq(IRQ_MFP_BUSY, parport_atari_interrupt,
+                               IRQ_TYPE_SLOW, p->name, p)) {
+                       parport_unregister_port (p);
+                       return 0;
+               }
+
+               this_port = p;
+               printk(KERN_INFO "%s: Atari built-in port using irq\n", p->name);
+               parport_proc_register(p);
+
+               parport_announce_port (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 (p->irq != PARPORT_IRQ_NONE)
+               free_irq(IRQ_MFP_BUSY, p);
+       parport_proc_unregister(this_port);
+       parport_unregister_port(this_port);
+}
+#endif
diff --git a/drivers/parport/parport_ax.c b/drivers/parport/parport_ax.c
new file mode 100644 (file)
index 0000000..dfa057f
--- /dev/null
@@ -0,0 +1,600 @@
+/* $Id: parport_ax.c,v 1.20 1999/07/03 08:56:21 davem Exp $
+ * Parallel-port routines for Sun Ultra/AX architecture
+ * 
+ * Author: Eddie C. Dost <ecd@skynet.be>
+ *
+ * based on work by:
+ *          Phil Blundell <Philip.Blundell@pobox.com>
+ *          Tim Waugh <tim@cyberelk.demon.co.uk>
+ *         Jose Renau <renau@acm.org>
+ *          David Campbell <campbell@tirian.che.curtin.edu.au>
+ *          Grant Guenther <grant@torque.net>
+ */
+
+#include <linux/string.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/malloc.h>
+#include <linux/init.h>
+
+#include <linux/parport.h>
+
+#include <asm/ptrace.h>
+#include <linux/interrupt.h>
+
+#include <asm/io.h>
+#include <asm/ebus.h>
+#include <asm/ns87303.h>
+#include <asm/irq.h>
+
+
+/*
+ * Define this if you have Devices which don't support short
+ * host read/write cycles.
+ */
+#undef HAVE_SLOW_DEVICES
+
+
+#define DATA           0x00
+#define STATUS         0x01
+#define CONTROL                0x02
+#define EPPADDR                0x03
+#define EPPDATA                0x04
+
+#define CFIFO          0x400
+#define DFIFO          0x400
+#define TFIFO          0x400
+#define CONFIGA                0x400
+#define CONFIGB                0x401
+#define ECONTROL       0x402
+
+static void parport_ax_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+       parport_generic_irq(irq, (struct parport *) dev_id, regs);
+}
+
+void
+parport_ax_write_epp(struct parport *p, unsigned char d)
+{
+       outb(d, p->base + EPPDATA);
+}
+
+unsigned char
+parport_ax_read_epp(struct parport *p)
+{
+       return inb(p->base + EPPDATA);
+}
+
+void
+parport_ax_write_epp_addr(struct parport *p, unsigned char d)
+{
+       outb(d, p->base + EPPADDR);
+}
+
+unsigned char
+parport_ax_read_epp_addr(struct parport *p)
+{
+       return inb(p->base + EPPADDR);
+}
+
+int parport_ax_epp_clear_timeout(struct parport *pb);
+
+int 
+parport_ax_check_epp_timeout(struct parport *p)
+{
+       if (!(inb(p->base+STATUS) & 1))
+               return 0;
+       parport_ax_epp_clear_timeout(p);
+       return 1;
+}
+
+unsigned char
+parport_ax_read_configb(struct parport *p)
+{
+       return inb(p->base + CONFIGB);
+}
+
+void
+parport_ax_write_data(struct parport *p, unsigned char d)
+{
+       outb(d, p->base + DATA);
+}
+
+unsigned char
+parport_ax_read_data(struct parport *p)
+{
+       return inb(p->base + DATA);
+}
+
+void
+parport_ax_write_control(struct parport *p, unsigned char d)
+{
+       outb(d, p->base + CONTROL);
+}
+
+unsigned char
+parport_ax_read_control(struct parport *p)
+{
+       return inb(p->base + CONTROL);
+}
+
+unsigned char
+parport_ax_frob_control(struct parport *p, unsigned char mask,  unsigned char val)
+{
+       unsigned char old = inb(p->base + CONTROL);
+       outb(((old & ~mask) ^ val), p->base + CONTROL);
+       return old;
+}
+
+void
+parport_ax_write_status(struct parport *p, unsigned char d)
+{
+       outb(d, p->base + STATUS);
+}
+
+unsigned char
+parport_ax_read_status(struct parport *p)
+{
+       return inb(p->base + STATUS);
+}
+
+void
+parport_ax_write_econtrol(struct parport *p, unsigned char d)
+{
+       outb(d, p->base + ECONTROL);
+}
+
+unsigned char
+parport_ax_read_econtrol(struct parport *p)
+{
+       return inb(p->base + ECONTROL);
+}
+
+unsigned char
+parport_ax_frob_econtrol(struct parport *p, unsigned char mask, unsigned char val)
+{
+       unsigned char old = inb(p->base + ECONTROL);
+       outb(((old & ~mask) ^ val), p->base + ECONTROL);
+       return old;
+}
+
+void
+parport_ax_change_mode(struct parport *p, int m)
+{
+       /* FIXME */
+       parport_ax_frob_econtrol(p, 0xe0, m << 5);
+}
+
+void
+parport_ax_write_fifo(struct parport *p, unsigned char v)
+{
+       outb(v, p->base + DFIFO);
+}
+
+unsigned char
+parport_ax_read_fifo(struct parport *p)
+{
+       return inb(p->base + DFIFO);
+}
+
+void
+parport_ax_disable_irq(struct parport *p)
+{
+       struct linux_ebus_dma *dma = p->private_data;
+       unsigned int dcsr;
+
+       dcsr = readl((unsigned long)&dma->dcsr);
+       dcsr &= ~(EBUS_DCSR_INT_EN);
+       writel(dcsr, (unsigned long)&dma->dcsr);
+}
+
+void
+parport_ax_enable_irq(struct parport *p)
+{
+       struct linux_ebus_dma *dma = p->private_data;
+       unsigned int dcsr;
+
+       dcsr = readl((unsigned long)&dma->dcsr);
+       dcsr |= EBUS_DCSR_INT_EN;
+       writel(dcsr, (unsigned long)&dma->dcsr);
+}
+
+void
+parport_ax_init_state(struct pardevice *dev, struct parport_state *s)
+{
+       struct linux_ebus_dma *dma = dev->port->private_data;
+
+       s->u.ax.ctr = 0xc | (dev->irq_func ? 0x10 : 0x0);
+       s->u.ax.ecr = 0x0;
+
+       if (dev->irq_func)
+               s->u.ax.dcsr = (readl((unsigned long)&dma->dcsr)
+                               | EBUS_DCSR_INT_EN);
+       else
+               s->u.ax.dcsr = (readl((unsigned long)&dma->dcsr)
+                               & ~EBUS_DCSR_INT_EN);
+}
+
+void
+parport_ax_save_state(struct parport *p, struct parport_state *s)
+{
+       struct linux_ebus_dma *dma = p->private_data;
+
+       s->u.ax.ctr = parport_ax_read_control(p);
+       s->u.ax.ecr = parport_ax_read_econtrol(p);
+       s->u.ax.dcsr = readl((unsigned long)&dma->dcsr);
+}
+
+void
+parport_ax_restore_state(struct parport *p, struct parport_state *s)
+{
+       struct linux_ebus_dma *dma = p->private_data;
+
+       parport_ax_write_control(p, s->u.ax.ctr);
+       parport_ax_write_econtrol(p, s->u.ax.ecr);
+       writel(s->u.ax.dcsr, (unsigned long)&dma->dcsr);
+}
+
+void
+parport_ax_inc_use_count(void)
+{
+#ifdef MODULE
+       MOD_INC_USE_COUNT;
+#endif
+}
+
+void
+parport_ax_dec_use_count(void)
+{
+#ifdef MODULE
+       MOD_DEC_USE_COUNT;
+#endif
+}
+
+static void parport_ax_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_ax_ops = 
+{
+       parport_ax_write_data,
+       parport_ax_read_data,
+
+       parport_ax_write_control,
+       parport_ax_read_control,
+       parport_ax_frob_control,
+
+       parport_ax_read_status,
+
+       parport_ax_enable_irq,
+       parport_ax_disable_irq,
+
+       parport_ax_data_forward,
+       parport_ax_data_reverse,
+
+       parport_ax_interrupt,
+
+       parport_ax_init_state,
+       parport_ax_save_state,
+       parport_ax_restore_state,
+
+       parport_ax_inc_use_count,
+       parport_ax_dec_use_count,
+       parport_ax_fill_inode,
+
+       parport_ieee1284_epp_write_data,
+       parport_ieee1284_epp_read_data,
+       parport_ieee1284_epp_write_addr,
+       parport_ieee1284_epp_read_addr,
+
+       parport_ieee1284_ecp_write_data,
+       parport_ieee1284_ecp_read_data,
+       parport_ieee1284_ecp_write_addr,
+
+       parport_ieee1284_write_compat,
+       parport_ieee1284_read_nibble,
+       parport_ieee1284_read_byte,
+};
+
+
+/******************************************************
+ *  MODE detection section:
+ */
+
+/*
+ * Clear TIMEOUT BIT in EPP MODE
+ */
+int parport_ax_epp_clear_timeout(struct parport *pb)
+{
+       unsigned char r;
+
+       if (!(parport_ax_read_status(pb) & 0x01))
+               return 1;
+
+       /* To clear timeout some chips require double read */
+       parport_ax_read_status(pb);
+       r = parport_ax_read_status(pb);
+       parport_ax_write_status(pb, r | 0x01); /* Some reset by writing 1 */
+       parport_ax_write_status(pb, r & 0xfe); /* Others by writing 0 */
+       r = parport_ax_read_status(pb);
+
+       return !(r & 0x01);
+}
+
+/* Check for ECP
+ *
+ * Old style XT ports alias io ports every 0x400, hence accessing ECONTROL
+ * on these cards actually accesses the CTR.
+ *
+ * Modern cards don't do this but reading from ECONTROL will return 0xff
+ * regardless of what is written here if the card does NOT support
+ * ECP.
+ *
+ * We will write 0x2c to ECONTROL and 0xcc to CTR since both of these
+ * values are "safe" on the CTR since bits 6-7 of CTR are unused.
+ */
+static int parport_ECR_present(struct parport *pb)
+{
+       unsigned int r;
+       unsigned char octr = pb->ops->read_control(pb), 
+         oecr = pb->ops->read_econtrol(pb);
+
+       r = pb->ops->read_control(pb);  
+       if ((pb->ops->read_econtrol(pb) & 0x3) == (r & 0x3)) {
+               pb->ops->write_control(pb, r ^ 0x2 ); /* Toggle bit 1 */
+
+               r = pb->ops->read_control(pb);  
+               if ((pb->ops->read_econtrol(pb) & 0x2) == (r & 0x2)) {
+                       pb->ops->write_control(pb, octr);
+                       return 0; /* Sure that no ECONTROL register exists */
+               }
+       }
+       
+       if ((pb->ops->read_econtrol(pb) & 0x3 ) != 0x1)
+               return 0;
+
+       pb->ops->write_econtrol(pb, 0x34);
+       if (pb->ops->read_econtrol(pb) != 0x35)
+               return 0;
+
+       pb->ops->write_econtrol(pb, oecr);
+       pb->ops->write_control(pb, octr);
+       
+       return PARPORT_MODE_PCECR;
+}
+
+static int parport_ECP_supported(struct parport *pb)
+{
+       int i;
+       unsigned char oecr = pb->ops->read_econtrol(pb);
+       
+       /* If there is no ECONTROL, we have no hope of supporting ECP. */
+       if (!(pb->modes & PARPORT_MODE_PCECR))
+               return 0;
+
+       /*
+        * Using LGS chipset it uses ECONTROL register, but
+        * it doesn't support ECP or FIFO MODE
+        */
+       
+       pb->ops->write_econtrol(pb, 0xc0); /* TEST FIFO */
+       for (i=0; i < 1024 && (pb->ops->read_econtrol(pb) & 0x01); i++)
+               pb->ops->write_fifo(pb, 0xaa);
+
+       pb->ops->write_econtrol(pb, oecr);
+       return (i == 1024) ? 0 : PARPORT_MODE_PCECP;
+}
+
+/* Detect PS/2 support.
+ *
+ * Bit 5 (0x20) sets the PS/2 data direction; setting this high
+ * allows us to read data from the data lines.  In theory we would get back
+ * 0xff but any peripheral attached to the port may drag some or all of the
+ * lines down to zero.  So if we get back anything that isn't the contents
+ * of the data register we deem PS/2 support to be present. 
+ *
+ * Some SPP ports have "half PS/2" ability - you can't turn off the line
+ * drivers, but an external peripheral with sufficiently beefy drivers of
+ * its own can overpower them and assert its own levels onto the bus, from
+ * where they can then be read back as normal.  Ports with this property
+ * and the right type of device attached are likely to fail the SPP test,
+ * (as they will appear to have stuck bits) and so the fact that they might
+ * be misdetected here is rather academic. 
+ */
+
+static int parport_PS2_supported(struct parport *pb)
+{
+       int ok = 0;
+       unsigned char octr = pb->ops->read_control(pb);
+  
+       pb->ops->write_control(pb, octr | 0x20);  /* try to tri-state buffer */
+       
+       pb->ops->write_data(pb, 0x55);
+       if (pb->ops->read_data(pb) != 0x55) ok++;
+
+       pb->ops->write_data(pb, 0xaa);
+       if (pb->ops->read_data(pb) != 0xaa) ok++;
+       
+       pb->ops->write_control(pb, octr);          /* cancel input mode */
+
+       return ok ? PARPORT_MODE_PCPS2 : 0;
+}
+
+static int parport_ECPPS2_supported(struct parport *pb)
+{
+       int mode;
+       unsigned char oecr = pb->ops->read_econtrol(pb);
+
+       if (!(pb->modes & PARPORT_MODE_PCECR))
+               return 0;
+       
+       pb->ops->write_econtrol(pb, 0x20);
+       
+       mode = parport_PS2_supported(pb);
+
+       pb->ops->write_econtrol(pb, oecr);
+       return mode ? PARPORT_MODE_PCECPPS2 : 0;
+}
+
+#define printmode(x)                                   \
+{                                                      \
+       if (p->modes & PARPORT_MODE_PC##x) {            \
+               printk("%s%s", f ? "," : "", #x);       \
+               f++;                                    \
+       }                                               \
+}
+
+int
+init_one_port(struct linux_ebus_device *dev)
+{
+       struct parport tmpport, *p;
+       unsigned long base;
+       unsigned long config;
+       unsigned char tmp;
+       int irq, dma;
+
+       /* Pointer to NS87303 Configuration Registers */
+       config = dev->base_address[1];
+
+       /* Setup temporary access to Device operations */
+       tmpport.base = dev->base_address[0];
+       tmpport.ops = &parport_ax_ops;
+
+       /* Enable ECP mode, set bit 2 of the CTR first */
+       tmpport.ops->write_control(&tmpport, 0x04);
+       tmp = ns87303_readb(config, PCR);
+       tmp |= (PCR_EPP_IEEE | PCR_ECP_ENABLE | PCR_ECP_CLK_ENA);
+       ns87303_writeb(config, PCR, tmp);
+
+       /* LPT CTR bit 5 controls direction of parallel port */
+       tmp = ns87303_readb(config, PTR);
+       tmp |= PTR_LPT_REG_DIR;
+       ns87303_writeb(config, PTR, tmp);
+
+       /* Configure IRQ to Push Pull, Level Low */
+       tmp = ns87303_readb(config, PCR);
+       tmp &= ~(PCR_IRQ_ODRAIN);
+       tmp |= PCR_IRQ_POLAR;
+       ns87303_writeb(config, PCR, tmp);
+
+#ifndef HAVE_SLOW_DEVICES
+       /* Enable Zero Wait State for ECP */
+       tmp = ns87303_readb(config, FCR);
+       tmp |= FCR_ZWS_ENA;
+       ns87303_writeb(config, FCR, tmp);
+#endif
+
+       /*
+        * Now continue initializing the port
+        */
+       base = dev->base_address[0];
+       irq = dev->irqs[0];
+       dma = PARPORT_DMA_AUTO;
+
+       if (!(p = parport_register_port(base, irq, dma, &parport_ax_ops)))
+               return 0;
+
+       /* Save away pointer to our EBus DMA */
+       p->private_data = (void *)dev->base_address[2];
+
+       p->modes = PARPORT_MODE_PCSPP | parport_PS2_supported(p);
+       if (!check_region(p->base + 0x400, 3)) {
+               p->modes |= parport_ECR_present(p);
+               p->modes |= parport_ECP_supported(p);
+               p->modes |= parport_ECPPS2_supported(p);
+       }
+       p->size = 3;
+
+       if (p->dma == PARPORT_DMA_AUTO)
+               p->dma = (p->modes & PARPORT_MODE_PCECP) ? 0 : PARPORT_DMA_NONE;
+
+       printk(KERN_INFO "%s: PC-style at 0x%lx", p->name, p->base);
+       if (p->irq != PARPORT_IRQ_NONE)
+               printk(", irq %s", __irq_itoa(p->irq));
+       if (p->dma != PARPORT_DMA_NONE)
+               printk(", dma %d", p->dma);
+       printk(" [");
+       {
+               int f = 0;
+               printmode(SPP);
+               printmode(PS2);
+               printmode(ECP);
+               printmode(ECPPS2);
+       }
+       printk("]\n");
+       parport_proc_register(p);
+
+       if (p->irq != PARPORT_IRQ_NONE)
+               if ((err = request_irq(p->irq, parport_ax_interrupt,
+                                      0, p->name, p)) != 0)
+                       return 0;               /* @@@ FIXME */
+
+       request_region(p->base, p->size, p->name);
+       if (p->modes & PARPORT_MODE_PCECR)
+               request_region(p->base+0x400, 3, p->name);
+       request_region((unsigned long)p->private_data,
+                      sizeof(struct linux_ebus_dma), p->name);
+
+       p->ops->write_control(p, 0x0c);
+       p->ops->write_data(p, 0);
+
+       /* Tell the high-level drivers about the port. */
+       parport_announce_port (p);
+
+       return 1;
+}
+
+EXPORT_NO_SYMBOLS;
+
+#ifdef MODULE
+int init_module(void)
+#else
+__initfunc(int parport_ax_init(void))
+#endif
+{
+       struct linux_ebus *ebus;
+       struct linux_ebus_device *edev;
+       int count = 0;
+
+       for_each_ebus(ebus) {
+               for_each_ebusdev(edev, ebus) {
+                       if (!strcmp(edev->prom_name, "ecpp"))
+                               count += init_one_port(edev);
+               }
+       }
+       return count ? 0 : -ENODEV;
+}
+
+#ifdef MODULE
+void
+cleanup_module(void)
+{
+       struct parport *p = parport_enumerate(), *tmp;
+       while (p) {
+               tmp = p->next;
+               if (p->modes & PARPORT_MODE_PCSPP) { 
+                       if (p->irq != PARPORT_IRQ_NONE) {
+                               parport_ax_disable_irq(p);
+                               free_irq(p->irq, p);
+                       }
+                       release_region(p->base, p->size);
+                       if (p->modes & PARPORT_MODE_PCECR)
+                               release_region(p->base+0x400, 3);
+                       release_region((unsigned long)p->private_data,
+                                      sizeof(struct linux_ebus_dma));
+                       parport_proc_unregister(p);
+                       parport_unregister_port(p);
+               }
+               p = tmp;
+       }
+}
+#endif
diff --git a/drivers/parport/parport_mfc3.c b/drivers/parport/parport_mfc3.c
new file mode 100644 (file)
index 0000000..1acb52a
--- /dev/null
@@ -0,0 +1,414 @@
+/* Low-level parallel port routines for the Multiface 3 card
+ *
+ * Author: Joerg Dorchain <dorchain@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 int mfc3_claim_resources(struct parport *p)
+{
+DPRINTK("claim_resources\n");
+}
+
+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);
+
+                                       if (p->irq != PARPORT_IRQ_NONE)
+                                               if (use_cnt++ == 0)
+                                                       if (request_irq(IRQ_AMIGA_PORTS, mfc3_interrupt, 0, p->name, &pp_mfc3_ops))
+                                                               use_cnt--;
+
+                                       if (parport_probe_hook)
+                                               (*parport_probe_hook)(p);
+                                       zorro_config_board(key, 0);
+                                       p->private_data = (void *)key;
+                                       parport_announce_port (p);
+                               }
+                       }
+               }
+       }
+       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 (p->irq != PARPORT_IRQ_NONE) 
+                               if (--use_cnt == 0) 
+                       free_irq(IRQ_AMIGA_PORTS, &pp_mfc3_ops);
+                       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 --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c
new file mode 100644 (file)
index 0000000..788e1b3
--- /dev/null
@@ -0,0 +1,1904 @@
+/* Low-level parallel-port routines for 8255-based PC-style hardware.
+ * 
+ * Authors: Phil Blundell <Philip.Blundell@pobox.com>
+ *          Tim Waugh <tim@cyberelk.demon.co.uk>
+ *         Jose Renau <renau@acm.org>
+ *          David Campbell <campbell@torque.net>
+ *          Andrea Arcangeli
+ *
+ * based on work by Grant Guenther <grant@torque.net> and Phil Blundell.
+ *
+ * Cleaned up include files - Russell King <linux@arm.uk.linux.org>
+ * DMA support - Bert De Jonghe <bert@sophis.be>
+ * Better EPP probing - Carlos Henrique Bauer <chbauer@acm.org>
+ */
+
+/* This driver should work with any hardware that is broadly compatible
+ * with that in the IBM PC.  This applies to the majority of integrated
+ * I/O chipsets that are commonly available.  The expected register
+ * layout is:
+ *
+ *     base+0          data
+ *     base+1          status
+ *     base+2          control
+ *
+ * In addition, there are some optional registers:
+ *
+ *     base+3          EPP address
+ *     base+4          EPP data
+ *     base+0x400      ECP config A
+ *     base+0x401      ECP config B
+ *     base+0x402      ECP control
+ *
+ * All registers are 8 bits wide and read/write.  If your hardware differs
+ * only in register addresses (eg because your registers are on 32-bit
+ * word boundaries) then you can alter the constants in parport_pc.h to
+ * accomodate this.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/malloc.h>
+#include <linux/pci.h>
+#include <linux/sysctl.h>
+
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/uaccess.h>
+
+#include <linux/parport.h>
+#include <linux/parport_pc.h>
+
+/* Maximum number of ports to support.  It is useless to set this greater
+   than PARPORT_MAX (in <linux/parport.h>).  */
+#define PARPORT_PC_MAX_PORTS  8
+
+/* ECR modes */
+#define ECR_SPP 00
+#define ECR_PS2 01
+#define ECR_PPF 02
+#define ECR_ECP 03
+#define ECR_EPP 04
+#define ECR_VND 05
+#define ECR_TST 06
+#define ECR_CNF 07
+
+static int user_specified __initdata = 0;
+
+/* frob_control, but for ECR */
+static void frob_econtrol (struct parport *pb, unsigned char m,
+                          unsigned char v)
+{
+       outb ((inb (ECONTROL (pb)) & ~m) ^ v, ECONTROL (pb));
+}
+
+#ifdef CONFIG_PARPORT_1284
+/* Safely change the mode bits in the ECR */
+static int change_mode(struct parport *p, int m)
+{
+       const struct parport_pc_private *priv = p->physport->private_data;
+       int ecr = ECONTROL(p);
+       unsigned char oecr;
+       int mode;
+
+       if (!priv->ecr) {
+               printk (KERN_DEBUG "change_mode: but there's no ECR!\n");
+               return 0;
+       }
+
+       /* Bits <7:5> contain the mode. */
+       oecr = inb (ecr);
+       mode = (oecr >> 5) & 0x7;
+       if (mode == m) return 0;
+       if (mode && m)
+               /* We have to go through mode 000 */
+               change_mode (p, ECR_SPP);
+
+       if (m < 2 && !(parport_read_control (p) & 0x20)) {
+               /* This mode resets the FIFO, so we may
+                * have to wait for it to drain first. */
+               long expire = jiffies + p->physport->cad->timeout;
+               int counter;
+               switch (mode) {
+               case ECR_PPF: /* Parallel Port FIFO mode */
+               case ECR_ECP: /* ECP Parallel Port mode */
+                       /* Busy wait for 200us */
+                       for (counter = 0; counter < 40; counter++) {
+                               if (inb (ECONTROL (p)) & 0x01)
+                                       break;
+                               if (signal_pending (current)) break;
+                               udelay (5);
+                       }
+
+                       /* Poll slowly. */
+                       while (!(inb (ECONTROL (p)) & 0x01)) {
+                               if (time_after_eq (jiffies, expire))
+                                       /* The FIFO is stuck. */
+                                       return -EBUSY;
+                               current->state = TASK_INTERRUPTIBLE;
+                               schedule_timeout ((HZ + 99) / 100);
+                               if (signal_pending (current))
+                                       break;
+                       }
+               }
+       }
+
+       /* Set the mode. */
+       oecr &= ~(7 << 5);
+       oecr |= m << 5;
+       outb (oecr, ecr);
+       return 0;
+}
+
+/* Find FIFO lossage; FIFO is reset */
+static int get_fifo_residue (struct parport *p)
+{
+       int residue;
+       int cnfga;
+       const struct parport_pc_private *priv = p->physport->private_data;
+
+       /* Prevent further data transfer. */
+       parport_frob_control (p,
+                             PARPORT_CONTROL_STROBE,
+                             PARPORT_CONTROL_STROBE);
+
+       /* Adjust for the contents of the FIFO. */
+       for (residue = priv->fifo_depth; ; residue--) {
+               if (inb (ECONTROL (p)) & 0x2)
+                               /* Full up. */
+                       break;
+
+               outb (0, FIFO (p));
+       }
+
+       printk (KERN_DEBUG "%s: %d PWords were left in FIFO\n", p->name,
+               residue);
+
+       /* Reset the FIFO. */
+       frob_econtrol (p, 0xe0, 0x20);
+       parport_frob_control (p, PARPORT_CONTROL_STROBE, 0);
+
+       /* Now change to config mode and clean up. FIXME */
+       frob_econtrol (p, 0xe0, 0xe0);
+       cnfga = inb (CONFIGA (p));
+       printk (KERN_DEBUG "%s: cnfgA contains 0x%02x\n", p->name, cnfga);
+
+       if (!(cnfga & (1<<2))) {
+               printk (KERN_DEBUG "%s: Accounting for extra byte\n", p->name);
+               residue++;
+       }
+
+       /* Don't care about partial PWords until support is added for
+        * PWord != 1 byte. */
+
+       /* Back to PS2 mode. */
+       frob_econtrol (p, 0xe0, 0x20);
+
+       return residue;
+}
+
+#endif /* IEEE 1284 support */
+
+/*
+ * Clear TIMEOUT BIT in EPP MODE
+ *
+ * This is also used in SPP detection.
+ */
+static int clear_epp_timeout(struct parport *pb)
+{
+       unsigned char r;
+
+       if (!(parport_pc_read_status(pb) & 0x01))
+               return 1;
+
+       /* To clear timeout some chips require double read */
+       parport_pc_read_status(pb);
+       r = parport_pc_read_status(pb);
+       outb (r | 0x01, STATUS (pb)); /* Some reset by writing 1 */
+       outb (r & 0xfe, STATUS (pb)); /* Others by writing 0 */
+       r = parport_pc_read_status(pb);
+
+       return !(r & 0x01);
+}
+
+/*
+ * Access functions.
+ *
+ * These aren't static because they may be used by the parport_xxx_yyy
+ * macros.  extern __inline__ versions of several of these are in
+ * parport_pc.h.
+ */
+
+static void parport_pc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+       parport_generic_irq(irq, (struct parport *) dev_id, regs);
+}
+
+void parport_pc_write_data(struct parport *p, unsigned char d)
+{
+       outb (d, DATA (p));
+}
+
+unsigned char parport_pc_read_data(struct parport *p)
+{
+       return inb (DATA (p));
+}
+
+unsigned char __frob_control (struct parport *p, unsigned char mask,
+                             unsigned char val)
+{
+       struct parport_pc_private *priv = p->physport->private_data;
+       unsigned char ctr = priv->ctr;
+       ctr = (ctr & ~mask) ^ val;
+       ctr &= priv->ctr_writable; /* only write writable bits. */
+       outb (ctr, CONTROL (p));
+       return priv->ctr = ctr; /* update soft copy */
+}
+
+void parport_pc_write_control(struct parport *p, unsigned char d)
+{
+       const unsigned char wm = (PARPORT_CONTROL_STROBE |
+                                 PARPORT_CONTROL_AUTOFD |
+                                 PARPORT_CONTROL_INIT |
+                                 PARPORT_CONTROL_SELECT);
+
+       /* Take this out when drivers have adapted to the newer interface. */
+       if (d & 0x20) {
+                       printk (KERN_DEBUG "%s (%s): use data_reverse for this!\n",
+                                       p->name, p->cad->name);
+                       parport_pc_data_reverse (p);
+       }
+
+       __frob_control (p, wm, d & wm);
+}
+
+unsigned char parport_pc_read_control(struct parport *p)
+{
+       const struct parport_pc_private *priv = p->physport->private_data;
+       return priv->ctr; /* Use soft copy */
+}
+
+unsigned char parport_pc_frob_control (struct parport *p, unsigned char mask,
+                                      unsigned char val)
+{
+       const unsigned char wm = (PARPORT_CONTROL_STROBE |
+                                 PARPORT_CONTROL_AUTOFD |
+                                 PARPORT_CONTROL_INIT |
+                                 PARPORT_CONTROL_SELECT);
+
+       /* Take this out when drivers have adapted to the newer interface. */
+       if (mask & 0x20) {
+                       printk (KERN_DEBUG "%s (%s): use data_reverse for this!\n",
+                                       p->name, p->cad->name);
+                       parport_pc_data_reverse (p);
+       }
+
+       /* Restrict mask and val to control lines. */
+       mask &= wm;
+       val &= wm;
+
+       return __frob_control (p, mask, val);
+}
+
+unsigned char parport_pc_read_status(struct parport *p)
+{
+       return inb (STATUS (p));
+}
+
+void parport_pc_disable_irq(struct parport *p)
+{
+       __frob_control (p, 0x10, 0);
+}
+
+void parport_pc_enable_irq(struct parport *p)
+{
+       __frob_control (p, 0x10, 0x10);
+}
+
+void parport_pc_data_forward (struct parport *p)
+{
+       __frob_control (p, 0x20, 0);
+}
+
+void parport_pc_data_reverse (struct parport *p)
+{
+       __frob_control (p, 0x20, 0x20);
+}
+
+void parport_pc_init_state(struct pardevice *dev, struct parport_state *s)
+{
+       s->u.pc.ctr = 0xc | (dev->irq_func ? 0x10 : 0x0);
+       s->u.pc.ecr = 0x24;
+}
+
+void parport_pc_save_state(struct parport *p, struct parport_state *s)
+{
+       const struct parport_pc_private *priv = p->physport->private_data;
+       s->u.pc.ctr = inb (CONTROL (p));
+       if (priv->ecr)
+               s->u.pc.ecr = inb (ECONTROL (p));
+}
+
+void parport_pc_restore_state(struct parport *p, struct parport_state *s)
+{
+       const struct parport_pc_private *priv = p->physport->private_data;
+       outb (s->u.pc.ctr, CONTROL (p));
+       if (priv->ecr)
+               outb (s->u.pc.ecr, ECONTROL (p));
+}
+
+#ifdef CONFIG_PARPORT_1284
+static size_t parport_pc_epp_read_data (struct parport *port, void *buf,
+                                       size_t length, int flags)
+{
+       size_t got = 0;
+       for (; got < length; got++) {
+               *((char*)buf)++ = inb (EPPDATA(port));
+               if (inb (STATUS(port)) & 0x01) {
+                       clear_epp_timeout (port);
+                       break;
+               }
+       }
+
+       return got;
+}
+
+static size_t parport_pc_epp_write_data (struct parport *port, const void *buf,
+                                        size_t length, int flags)
+{
+       size_t written = 0;
+       for (; written < length; written++) {
+               outb (*((char*)buf)++, EPPDATA(port));
+               if (inb (STATUS(port)) & 0x01) {
+                       clear_epp_timeout (port);
+                       break;
+               }
+       }
+
+       return written;
+}
+
+static size_t parport_pc_epp_read_addr (struct parport *port, void *buf,
+                                       size_t length, int flags)
+{
+       size_t got = 0;
+       for (; got < length; got++) {
+               *((char*)buf)++ = inb (EPPADDR (port));
+               if (inb (STATUS (port)) & 0x01) {
+                       clear_epp_timeout (port);
+                       break;
+               }
+       }
+
+       return got;
+}
+
+static size_t parport_pc_epp_write_addr (struct parport *port,
+                                        const void *buf, size_t length,
+                                        int flags)
+{
+       size_t written = 0;
+       for (; written < length; written++) {
+               outb (*((char*)buf)++, EPPADDR (port));
+               if (inb (STATUS (port)) & 0x01) {
+                       clear_epp_timeout (port);
+                       break;
+               }
+       }
+
+       return written;
+}
+
+static size_t parport_pc_ecpepp_read_data (struct parport *port, void *buf,
+                                          size_t length, int flags)
+{
+       size_t got;
+
+       frob_econtrol (port, 0xe0, ECR_EPP << 5);
+       got = parport_pc_epp_read_data (port, buf, length, flags);
+       frob_econtrol (port, 0xe0, ECR_PS2 << 5);
+
+       return got;
+}
+
+static size_t parport_pc_ecpepp_write_data (struct parport *port,
+                                           const void *buf, size_t length,
+                                           int flags)
+{
+       size_t written;
+
+       frob_econtrol (port, 0xe0, ECR_EPP << 5);
+       written = parport_pc_epp_write_data (port, buf, length, flags);
+       frob_econtrol (port, 0xe0, ECR_PS2 << 5);
+
+       return written;
+}
+
+static size_t parport_pc_ecpepp_read_addr (struct parport *port, void *buf,
+                                          size_t length, int flags)
+{
+       size_t got;
+
+       frob_econtrol (port, 0xe0, ECR_EPP << 5);
+       got = parport_pc_epp_read_addr (port, buf, length, flags);
+       frob_econtrol (port, 0xe0, ECR_PS2 << 5);
+
+       return got;
+}
+
+static size_t parport_pc_ecpepp_write_addr (struct parport *port,
+                                           const void *buf, size_t length,
+                                           int flags)
+{
+       size_t written;
+
+       frob_econtrol (port, 0xe0, ECR_EPP << 5);
+       written = parport_pc_epp_write_addr (port, buf, length, flags);
+       frob_econtrol (port, 0xe0, ECR_PS2 << 5);
+
+       return written;
+}
+#endif /* IEEE 1284 support */
+
+#ifdef CONFIG_PARPORT_PC_FIFO
+static size_t parport_pc_fifo_write_block_pio (struct parport *port,
+                                              const void *buf, size_t length)
+{
+       int ret = 0;
+       const unsigned char *bufp = buf;
+       size_t left = length;
+       long expire = jiffies + port->physport->cad->timeout;
+       const int fifo = FIFO (port);
+       int poll_for = 8; /* 80 usecs */
+       const struct parport_pc_private *priv = port->physport->private_data;
+       const int fifo_depth = priv->fifo_depth;
+
+       port = port->physport;
+
+       /* We don't want to be interrupted every character. */
+       parport_pc_disable_irq (port);
+       frob_econtrol (port, (1<<4), (1<<4)); /* nErrIntrEn */
+
+       /* Forward mode. */
+       parport_pc_data_forward (port);
+
+       while (left) {
+               unsigned char byte;
+               unsigned char ecrval = inb (ECONTROL (port));
+               int i = 0;
+
+               if (current->need_resched && time_before (jiffies, expire))
+                       /* Can't yield the port. */
+                       schedule ();
+
+               /* Anyone else waiting for the port? */
+               if (port->waithead) {
+                       printk (KERN_DEBUG "Somebody wants the port\n");
+                       break;
+               }
+
+               if (ecrval & 0x02) {
+                       /* FIFO is full. Wait for interrupt. */
+
+                       /* Clear serviceIntr */
+                       outb (ecrval & ~(1<<2), ECONTROL (port));
+               false_alarm:
+                       ret = parport_wait_event (port, HZ);
+                       if (ret < 0) break;
+                       ret = 0;
+                       if (!time_before (jiffies, expire)) {
+                               /* Timed out. */
+                               printk (KERN_DEBUG "Timed out\n");
+                               break;
+                       }
+                       ecrval = inb (ECONTROL (port));
+                       if (!(ecrval & (1<<2))) {
+                               if (current->need_resched &&
+                                   time_before (jiffies, expire))
+                                       schedule ();
+
+                               goto false_alarm;
+                       }
+
+                       continue;
+               }
+
+               /* Can't fail now. */
+               expire = jiffies + port->cad->timeout;
+
+       poll:
+               if (signal_pending (current))
+                       break;
+
+               if (ecrval & 0x01) {
+                       /* FIFO is empty. Blast it full. */
+                       const int n = left < fifo_depth ? left : fifo_depth;
+                       outsb (fifo, bufp, n);
+                       bufp += n;
+                       left -= n;
+
+                       /* Adjust the poll time. */
+                       if (i < (poll_for - 2)) poll_for--;
+                       continue;
+               } else if (i++ < poll_for) {
+                       udelay (10);
+                       ecrval = inb (ECONTROL (port));
+                       goto poll;
+               }
+
+               /* Half-full (call me an optimist) */
+               byte = *bufp++;
+               outb (byte, fifo);
+               left--;
+        }
+
+       return length - left;
+}
+
+static size_t parport_pc_fifo_write_block_dma (struct parport *port,
+                                              const void *buf, size_t length)
+{
+       int ret = 0;
+       unsigned long dmaflag;
+       size_t left  = length;
+       const struct parport_pc_private *priv = port->physport->private_data;
+
+       port = port->physport;
+
+       /* We don't want to be interrupted every character. */
+       parport_pc_disable_irq (port);
+       frob_econtrol (port, (1<<4), (1<<4)); /* nErrIntrEn */
+
+       /* Forward mode. */
+       parport_pc_data_forward (port);
+
+       while (left) {
+               long expire = jiffies + port->physport->cad->timeout;
+
+               size_t count = left;
+
+               if (count > PAGE_SIZE)
+                       count = PAGE_SIZE;
+
+               memcpy(priv->dma_buf, buf, count);
+
+               dmaflag = claim_dma_lock();
+               disable_dma(port->dma);
+               clear_dma_ff(port->dma);
+               set_dma_mode(port->dma, DMA_MODE_WRITE);
+               set_dma_addr(port->dma, virt_to_bus((volatile char *) priv->dma_buf));
+               set_dma_count(port->dma, count);
+
+               /* Set DMA mode */
+               frob_econtrol (port, 1<<3, 1<<3);
+
+               /* Clear serviceIntr */
+               frob_econtrol (port, 1<<2, 0);
+
+               enable_dma(port->dma);
+               release_dma_lock(dmaflag);
+
+               /* assume DMA will be successful */
+               left -= count;
+               buf  += count;
+
+               /* Wait for interrupt. */
+       false_alarm:
+               ret = parport_wait_event (port, HZ);
+               if (ret < 0) break;
+               ret = 0;
+               if (!time_before (jiffies, expire)) {
+                       /* Timed out. */
+                       printk (KERN_DEBUG "Timed out\n");
+                       break;
+               }
+               /* Is serviceIntr set? */
+               if (!(inb (ECONTROL (port)) & (1<<2))) {
+                       if (current->need_resched)
+                               schedule ();
+
+                       goto false_alarm;
+               }
+
+               dmaflag = claim_dma_lock();
+               disable_dma(port->dma);
+               clear_dma_ff(port->dma);
+               count = get_dma_residue(port->dma);
+               release_dma_lock(dmaflag);
+
+               if (current->need_resched)
+                       /* Can't yield the port. */
+                       schedule ();
+
+               /* Anyone else waiting for the port? */
+               if (port->waithead) {
+                       printk (KERN_DEBUG "Somebody wants the port\n");
+                       break;
+               }
+
+               /* update for possible DMA residue ! */
+               buf  -= count;
+               left += count;
+       }
+
+       /* Maybe got here through break, so adjust for DMA residue! */
+       dmaflag = claim_dma_lock();
+       disable_dma(port->dma);
+       clear_dma_ff(port->dma);
+       left += get_dma_residue(port->dma);
+       release_dma_lock(dmaflag);
+
+       /* Turn off DMA mode */
+       frob_econtrol (port, 1<<3, 0);
+
+       return length - left;
+}
+
+/* Parallel Port FIFO mode (ECP chipsets) */
+size_t parport_pc_compat_write_block_pio (struct parport *port,
+                                         const void *buf, size_t length,
+                                         int flags)
+{
+       size_t written;
+
+       /* Special case: a timeout of zero means we cannot call schedule(). */
+       if (!port->physport->cad->timeout)
+               return parport_ieee1284_write_compat (port, buf,
+                                                     length, flags);
+
+       /* Set up parallel port FIFO mode.*/
+       change_mode (port, ECR_PPF); /* Parallel port FIFO */
+       parport_pc_data_forward (port);
+       port->physport->ieee1284.phase = IEEE1284_PH_FWD_DATA;
+
+       /* Write the data to the FIFO. */
+       if (port->dma != PARPORT_DMA_NONE)
+               written = parport_pc_fifo_write_block_dma (port, buf, length);
+       else
+               written = parport_pc_fifo_write_block_pio (port, buf, length);
+
+       /* Finish up. */
+       if (change_mode (port, ECR_PS2) == -EBUSY) {
+               const struct parport_pc_private *priv = 
+                       port->physport->private_data;
+
+               printk (KERN_DEBUG "%s: FIFO is stuck\n", port->name);
+
+               /* Prevent further data transfer. */
+               parport_frob_control (port,
+                                     PARPORT_CONTROL_STROBE,
+                                     PARPORT_CONTROL_STROBE);
+
+               /* Adjust for the contents of the FIFO. */
+               for (written -= priv->fifo_depth; ; written++) {
+                       if (inb (ECONTROL (port)) & 0x2)
+                               /* Full up. */
+                               break;
+
+                       outb (0, FIFO (port));
+               }
+
+               /* Reset the FIFO. */
+               frob_econtrol (port, 0xe0, 0);
+
+               /* De-assert strobe. */
+               parport_frob_control (port, PARPORT_CONTROL_STROBE, 0);
+       }
+
+       parport_wait_peripheral (port,
+                                PARPORT_STATUS_BUSY,
+                                PARPORT_STATUS_BUSY);
+       port->physport->ieee1284.phase = IEEE1284_PH_FWD_IDLE;
+
+       return written;
+}
+
+/* ECP */
+#ifdef CONFIG_PARPORT_1284
+size_t parport_pc_ecp_write_block_pio (struct parport *port,
+                                      const void *buf, size_t length,
+                                      int flags)
+{
+       size_t written;
+
+       /* Special case: a timeout of zero means we cannot call schedule(). */
+       if (!port->physport->cad->timeout)
+               return parport_ieee1284_ecp_write_data (port, buf,
+                                                       length, flags);
+
+       /* Switch to forward mode if necessary. */
+       if (port->physport->ieee1284.phase != IEEE1284_PH_FWD_IDLE) {
+               /* Event 47: Set nInit high. */
+               parport_frob_control (port, PARPORT_CONTROL_INIT, 0);
+
+               /* Event 40: PError goes high. */
+               parport_wait_peripheral (port,
+                                        PARPORT_STATUS_PAPEROUT,
+                                        PARPORT_STATUS_PAPEROUT);
+       }
+
+       /* Set up ECP parallel port mode.*/
+       change_mode (port, ECR_ECP); /* ECP FIFO */
+       parport_pc_data_forward (port);
+       port->physport->ieee1284.phase = IEEE1284_PH_FWD_DATA;
+
+       /* Write the data to the FIFO. */
+       if (port->dma != PARPORT_DMA_NONE)
+               written = parport_pc_fifo_write_block_dma (port, buf, length);
+       else
+               written = parport_pc_fifo_write_block_pio (port, buf, length);
+
+       /* Finish up. */
+       if (change_mode (port, ECR_PS2) == -EBUSY) {
+               const struct parport_pc_private *priv =
+                       port->physport->private_data;
+
+               printk (KERN_DEBUG "%s: FIFO is stuck\n", port->name);
+
+               /* Prevent further data transfer. */
+               parport_frob_control (port,
+                                     PARPORT_CONTROL_STROBE,
+                                     PARPORT_CONTROL_STROBE);
+
+               /* Adjust for the contents of the FIFO. */
+               for (written -= priv->fifo_depth; ; written++) {
+                       if (inb (ECONTROL (port)) & 0x2)
+                               /* Full up. */
+                               break;
+
+                       outb (0, FIFO (port));
+               }
+
+               /* Reset the FIFO. */
+               frob_econtrol (port, 0xe0, 0);
+               parport_frob_control (port, PARPORT_CONTROL_STROBE, 0);
+
+               /* Host transfer recovery. */
+               parport_frob_control (port,
+                                     PARPORT_CONTROL_INIT,
+                                     PARPORT_CONTROL_INIT);
+               parport_pc_data_reverse (port);
+               parport_wait_peripheral (port, PARPORT_STATUS_PAPEROUT, 0);
+               parport_frob_control (port, PARPORT_CONTROL_INIT, 0);
+               parport_wait_peripheral (port,
+                                        PARPORT_STATUS_PAPEROUT,
+                                        PARPORT_STATUS_PAPEROUT);
+       }
+
+       parport_wait_peripheral (port,
+                                PARPORT_STATUS_BUSY, 
+                                PARPORT_STATUS_BUSY);
+       port->physport->ieee1284.phase = IEEE1284_PH_FWD_IDLE;
+
+       return written;
+}
+
+size_t parport_pc_ecp_read_block_pio (struct parport *port,
+                                     void *buf, size_t length, int flags)
+{
+       size_t left = length;
+       size_t fifofull;
+       const int fifo = FIFO(port);
+       const struct parport_pc_private *priv = port->physport->private_data;
+       const int fifo_depth = priv->fifo_depth;
+       char *bufp = buf;
+
+       port = port->physport;
+
+       /* Special case: a timeout of zero means we cannot call schedule(). */
+       if (!port->cad->timeout)
+               return parport_ieee1284_ecp_read_data (port, buf,
+                                                      length, flags);
+
+       fifofull = fifo_depth;
+       if (port->ieee1284.mode == IEEE1284_MODE_ECPRLE)
+               /* If the peripheral is allowed to send RLE compressed
+                * data, it is possible for a byte to expand to 128
+                * bytes in the FIFO. */
+               fifofull = 128;
+
+       /* If the caller wants less than a full FIFO's worth of data,
+        * go through software emulation.  Otherwise we may have to through
+        * away data. */
+       if (length < fifofull)
+               return parport_ieee1284_ecp_read_data (port, buf,
+                                                      length, flags);
+
+       /* Switch to reverse mode if necessary. */
+       if (port->ieee1284.phase != IEEE1284_PH_REV_IDLE) {
+               /* Event 38: Set nAutoFd low */
+               parport_frob_control (port,
+                                     PARPORT_CONTROL_AUTOFD,
+                                     PARPORT_CONTROL_AUTOFD);
+               parport_pc_data_reverse (port);
+               udelay (5);
+
+               /* Event 39: Set nInit low to initiate bus reversal */
+               parport_frob_control (port,
+                                     PARPORT_CONTROL_INIT,
+                                     PARPORT_CONTROL_INIT);
+
+               /* Event 40: PError goes low */
+               parport_wait_peripheral (port, PARPORT_STATUS_PAPEROUT, 0);
+       }
+
+       /* Set up ECP parallel port mode.*/
+       change_mode (port, ECR_ECP); /* ECP FIFO */
+       parport_pc_data_reverse (port);
+       port->ieee1284.phase = IEEE1284_PH_REV_DATA;
+
+       /* Do the transfer. */
+       while (left > fifofull) {
+               int ret;
+               long int expire = jiffies + port->cad->timeout;
+               unsigned char ecrval = inb (ECONTROL (port));
+
+               if (current->need_resched && time_before (jiffies, expire))
+                       /* Can't yield the port. */
+                       schedule ();
+
+               /* At this point, the FIFO may already be full.
+                * Ideally, we'd be able to tell the port to hold on
+                * for a second while we empty the FIFO, and we'd be
+                * able to ensure that no data is lost.  I'm not sure
+                * that's the case. :-(  It might be that you can play
+                * games with STB, as in the forward case; someone should
+                * look at a datasheet. */
+
+               if (ecrval & 0x01) {
+                       /* FIFO is empty. Wait for interrupt. */
+
+                       /* Anyone else waiting for the port? */
+                       if (port->waithead) {
+                               printk (KERN_DEBUG
+                                       "Somebody wants the port\n");
+                               break;
+                       }
+
+                       /* Clear serviceIntr */
+                       outb (ecrval & ~(1<<2), ECONTROL (port));
+               false_alarm:
+                       ret = parport_wait_event (port, HZ);
+                       if (ret < 0) break;
+                       ret = 0;
+                       if (!time_before (jiffies, expire)) {
+                               /* Timed out. */
+                               printk (KERN_DEBUG "Timed out\n");
+                               break;
+                       }
+                       ecrval = inb (ECONTROL (port));
+                       if (!(ecrval & (1<<2))) {
+                               if (current->need_resched &&
+                                   time_before (jiffies, expire))
+                                       schedule ();
+
+                               goto false_alarm;
+                       }
+
+                       continue;
+               }
+
+               if (ecrval & 0x02) {
+                       /* FIFO is full. */
+                       insb (fifo, bufp, fifo_depth);
+                       bufp += fifo_depth;
+                       left -= fifo_depth;
+                       continue;
+               }
+
+               *bufp++ = inb (fifo);
+               left--;
+       }
+
+       /* Finish up. */
+       if (change_mode (port, ECR_PS2) == -EBUSY) {
+               int lost = get_fifo_residue (port);
+               printk (KERN_DEBUG "%s: DATA LOSS (%d bytes)!\n", port->name,
+                       lost);
+       }
+
+       port->ieee1284.phase = IEEE1284_PH_REV_IDLE;
+
+       return length - left;
+}
+
+#endif /* IEEE 1284 support */
+
+#endif /* Allowed to use FIFO/DMA */
+
+void parport_pc_inc_use_count(void)
+{
+#ifdef MODULE
+       MOD_INC_USE_COUNT;
+#endif
+}
+
+void parport_pc_dec_use_count(void)
+{
+#ifdef MODULE
+       MOD_DEC_USE_COUNT;
+#endif
+}
+
+static void parport_pc_fill_inode(struct inode *inode, int fill)
+{
+       /* Is this still needed? -tim */
+#ifdef MODULE
+       if (fill)
+               MOD_INC_USE_COUNT;
+       else
+               MOD_DEC_USE_COUNT;
+#endif
+}
+
+struct parport_operations parport_pc_ops = 
+{
+       parport_pc_write_data,
+       parport_pc_read_data,
+
+       parport_pc_write_control,
+       parport_pc_read_control,
+       parport_pc_frob_control,
+
+       parport_pc_read_status,
+
+       parport_pc_enable_irq,
+       parport_pc_disable_irq,
+
+       parport_pc_data_forward,
+       parport_pc_data_reverse,
+
+       parport_pc_interrupt,
+       parport_pc_init_state,
+       parport_pc_save_state,
+       parport_pc_restore_state,
+
+       parport_pc_inc_use_count,
+       parport_pc_dec_use_count,
+       parport_pc_fill_inode,
+
+       parport_ieee1284_epp_write_data,
+       parport_ieee1284_epp_read_data,
+       parport_ieee1284_epp_write_addr,
+       parport_ieee1284_epp_read_addr,
+
+       parport_ieee1284_ecp_write_data,
+       parport_ieee1284_ecp_read_data,
+       parport_ieee1284_ecp_write_addr,
+
+       parport_ieee1284_write_compat,
+       parport_ieee1284_read_nibble,
+       parport_ieee1284_read_byte,
+};
+
+/* --- Mode detection ------------------------------------- */
+
+/*
+ * Checks for port existence, all ports support SPP MODE
+ */
+static int __init parport_SPP_supported(struct parport *pb)
+{
+       unsigned char r, w;
+
+       /*
+        * first clear an eventually pending EPP timeout 
+        * I (sailer@ife.ee.ethz.ch) have an SMSC chipset
+        * that does not even respond to SPP cycles if an EPP
+        * timeout is pending
+        */
+       clear_epp_timeout(pb);
+
+       /* Do a simple read-write test to make sure the port exists. */
+       w = 0xc;
+       outb (w, CONTROL (pb));
+
+       /* Is there a control register that we can read from?  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 (CONTROL (pb));
+       if ((r & 0xf) == w) {
+               w = 0xe;
+               outb (w, CONTROL (pb));
+               r = inb (CONTROL (pb));
+               outb (0xc, CONTROL (pb));
+               if ((r & 0xf) == 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, 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;
+
+       return 0;
+}
+
+/* Check for ECR
+ *
+ * Old style XT ports alias io ports every 0x400, hence accessing ECR
+ * on these cards actually accesses the CTR.
+ *
+ * Modern cards don't do this but reading from ECR will return 0xff
+ * regardless of what is written here if the card does NOT support
+ * ECP.
+ *
+ * We first check to see if ECR is the same as CTR.  If not, the low
+ * two bits of ECR aren't writable, so we check by writing ECR and
+ * reading it back to see if it's what we expect.
+ */
+static int __init parport_ECR_present(struct parport *pb)
+{
+       struct parport_pc_private *priv = pb->private_data;
+       unsigned char r = 0xc;
+
+       priv->ecr = 0;
+       outb (r, CONTROL (pb));
+       if ((inb (ECONTROL (pb)) & 0x3) == (r & 0x3)) {
+               outb (r ^ 0x2, CONTROL (pb)); /* Toggle bit 1 */
+
+               r = inb (CONTROL (pb));
+               if ((inb (ECONTROL (pb)) & 0x2) == (r & 0x2))
+                       goto no_reg; /* Sure that no ECR register exists */
+       }
+       
+       if ((inb (ECONTROL (pb)) & 0x3 ) != 0x1)
+               goto no_reg;
+
+       outb (0x34, ECONTROL (pb));
+       if (inb (ECONTROL (pb)) != 0x35)
+               goto no_reg;
+
+       priv->ecr = 1;
+       outb (0xc, CONTROL (pb));
+       
+       /* Go to mode 000 */
+       frob_econtrol (pb, 0xe0, ECR_SPP << 5);
+
+       return 1;
+
+ no_reg:
+       outb (0xc, CONTROL (pb));
+       return 0; 
+}
+
+#ifdef CONFIG_PARPORT_1284
+/* Detect PS/2 support.
+ *
+ * Bit 5 (0x20) sets the PS/2 data direction; setting this high
+ * allows us to read data from the data lines.  In theory we would get back
+ * 0xff but any peripheral attached to the port may drag some or all of the
+ * lines down to zero.  So if we get back anything that isn't the contents
+ * of the data register we deem PS/2 support to be present. 
+ *
+ * Some SPP ports have "half PS/2" ability - you can't turn off the line
+ * drivers, but an external peripheral with sufficiently beefy drivers of
+ * its own can overpower them and assert its own levels onto the bus, from
+ * where they can then be read back as normal.  Ports with this property
+ * and the right type of device attached are likely to fail the SPP test,
+ * (as they will appear to have stuck bits) and so the fact that they might
+ * be misdetected here is rather academic. 
+ */
+
+static int __init parport_PS2_supported(struct parport *pb)
+{
+       int ok = 0;
+  
+       clear_epp_timeout(pb);
+
+       /* try to tri-state the buffer */
+       parport_pc_data_reverse (pb);
+       
+       parport_pc_write_data(pb, 0x55);
+       if (parport_pc_read_data(pb) != 0x55) ok++;
+
+       parport_pc_write_data(pb, 0xaa);
+       if (parport_pc_read_data(pb) != 0xaa) ok++;
+
+       /* cancel input mode */
+       parport_pc_data_forward (pb);
+
+       if (ok)
+               pb->modes |= PARPORT_MODE_TRISTATE;
+       else {
+               struct parport_pc_private *priv = pb->private_data;
+               priv->ctr_writable &= ~0x20;
+       }
+
+       return ok;
+}
+
+static int __init parport_ECP_supported(struct parport *pb)
+{
+       int i;
+       int config;
+       int pword;
+       struct parport_pc_private *priv = pb->private_data;
+
+       /* If there is no ECR, we have no hope of supporting ECP. */
+       if (!priv->ecr)
+               return 0;
+
+       /* Find out FIFO depth */
+       outb (ECR_SPP << 5, ECONTROL (pb)); /* Reset FIFO */
+       outb (ECR_TST << 5, ECONTROL (pb)); /* TEST FIFO */
+       for (i=0; i < 1024 && !(inb (ECONTROL (pb)) & 0x02); i++)
+               outb (0xaa, FIFO (pb));
+
+       /*
+        * Using LGS chipset it uses ECR register, but
+        * it doesn't support ECP or FIFO MODE
+        */
+       if (i == 1024) {
+               outb (ECR_SPP << 5, ECONTROL (pb));
+               return 0;
+       }
+
+       priv->fifo_depth = i;
+       printk (KERN_INFO "0x%lx: FIFO is %d bytes\n", pb->base, i);
+
+       /* Find out writeIntrThreshold */
+       frob_econtrol (pb, 1<<2, 1<<2);
+       frob_econtrol (pb, 1<<2, 0);
+       for (i = 1; i <= priv->fifo_depth; i++) {
+               inb (FIFO (pb));
+               udelay (50);
+               if (inb (ECONTROL (pb)) & (1<<2))
+                       break;
+       }
+
+       if (i <= priv->fifo_depth)
+               printk (KERN_INFO "0x%lx: writeIntrThreshold is %d\n",
+                       pb->base, i);
+       else
+               /* Number of bytes we know we can write if we get an
+                   interrupt. */
+               i = 0;
+
+       priv->writeIntrThreshold = i;
+
+       /* Find out readIntrThreshold */
+       frob_econtrol (pb, 0xe0, ECR_PS2 << 5); /* Reset FIFO */
+       parport_pc_data_reverse (pb);
+       frob_econtrol (pb, 0xe0, ECR_TST << 5); /* Test FIFO */
+       frob_econtrol (pb, 1<<2, 1<<2);
+       frob_econtrol (pb, 1<<2, 0);
+       for (i = 1; i <= priv->fifo_depth; i++) {
+               outb (0xaa, FIFO (pb));
+               if (inb (ECONTROL (pb)) & (1<<2))
+                       break;
+       }
+
+       if (i <= priv->fifo_depth)
+               printk (KERN_INFO "0x%lx: readIntrThreshold is %d\n",
+                       pb->base, i);
+       else
+               /* Number of bytes we can read if we get an interrupt. */
+               i = 0;
+
+       priv->readIntrThreshold = i;
+
+       outb (ECR_SPP << 5, ECONTROL (pb)); /* Reset FIFO */
+       outb (0xf4, ECONTROL (pb)); /* Configuration mode */
+       config = inb (FIFO (pb));
+       pword = (config >> 4) & 0x7;
+       switch (pword) {
+       case 0:
+               pword = 2;
+               printk (KERN_WARNING "0x%lx: Unsupported pword size!\n",
+                       pb->base);
+               break;
+       case 2:
+               pword = 4;
+               printk (KERN_WARNING "0x%lx: Unsupported pword size!\n",
+                       pb->base);
+               break;
+       default:
+               printk (KERN_WARNING "0x%lx: Unknown implementation ID\n",
+                       pb->base);
+               /* Assume 1 */
+       case 1:
+               pword = 1;
+       }
+       priv->pword = pword;
+       printk (KERN_DEBUG "0x%lx: PWord is %d bits\n", pb->base, 8 * pword);
+
+       config = inb (CONFIGB (pb));
+       printk (KERN_DEBUG "0x%lx: Interrupts are ISA-%s\n", pb->base,
+               config & 0x80 ? "Level" : "Pulses");
+
+       if (!(config & 0x40)) {
+               printk (KERN_WARNING "0x%lx: IRQ conflict!\n", pb->base);
+               pb->irq = PARPORT_IRQ_NONE;
+       }
+
+       /* Go back to mode 000 */
+       frob_econtrol (pb, 0xe0, ECR_SPP << 5);
+       pb->modes |= PARPORT_MODE_ECP;
+
+       return 1;
+}
+
+static int __init parport_ECPPS2_supported(struct parport *pb)
+{
+       const struct parport_pc_private *priv = pb->private_data;
+       int result;
+       unsigned char oecr;
+
+       if (!priv->ecr)
+               return 0;
+
+       oecr = inb (ECONTROL (pb));
+       outb (ECR_PS2 << 5, ECONTROL (pb));
+       
+       result = parport_PS2_supported(pb);
+
+       outb (oecr, ECONTROL (pb));
+       return result;
+}
+
+/* EPP mode detection  */
+
+static int __init parport_EPP_supported(struct parport *pb)
+{
+       const struct parport_pc_private *priv = pb->private_data;
+
+       /*
+        * Theory:
+        *      Bit 0 of STR is the EPP timeout bit, this bit is 0
+        *      when EPP is possible and is set high when an EPP timeout
+        *      occurs (EPP uses the HALT line to stop the CPU while it does
+        *      the byte transfer, an EPP timeout occurs if the attached
+        *      device fails to respond after 10 micro seconds).
+        *
+        *      This bit is cleared by either reading it (National Semi)
+        *      or writing a 1 to the bit (SMC, UMC, WinBond), others ???
+        *      This bit is always high in non EPP modes.
+        */
+
+       /* If EPP timeout bit clear then EPP available */
+       if (!clear_epp_timeout(pb))
+               return 0;  /* No way to clear timeout */
+
+       /* Check for Intel bug. */
+       if (priv->ecr) {
+               unsigned char i;
+               for (i = 0x00; i < 0x80; i += 0x20) {
+                       outb (i, ECONTROL (pb));
+                       if (clear_epp_timeout (pb))
+                               /* Phony EPP in ECP. */
+                               return 0;
+               }
+       }
+
+       pb->modes |= PARPORT_MODE_EPP;
+
+       /* Set up access functions to use EPP hardware. */
+       parport_pc_ops.epp_read_data = parport_pc_epp_read_data;
+       parport_pc_ops.epp_write_data = parport_pc_epp_write_data;
+       parport_pc_ops.epp_read_addr = parport_pc_epp_read_addr;
+       parport_pc_ops.epp_write_addr = parport_pc_epp_write_addr;
+
+       return 1;
+}
+
+static int __init parport_ECPEPP_supported(struct parport *pb)
+{
+       struct parport_pc_private *priv = pb->private_data;
+       int result;
+       unsigned char oecr;
+
+       if (!priv->ecr)
+               return 0;
+
+       oecr = inb (ECONTROL (pb));
+       /* Search for SMC style EPP+ECP mode */
+       outb (0x80, ECONTROL (pb));
+       
+       result = parport_EPP_supported(pb);
+
+       outb (oecr, ECONTROL (pb));
+
+       if (result) {
+               /* Set up access functions to use ECP+EPP hardware. */
+               parport_pc_ops.epp_read_data = parport_pc_ecpepp_read_data;
+               parport_pc_ops.epp_write_data = parport_pc_ecpepp_write_data;
+               parport_pc_ops.epp_read_addr = parport_pc_ecpepp_read_addr;
+               parport_pc_ops.epp_write_addr = parport_pc_ecpepp_write_addr;
+       }
+
+       return result;
+}
+
+#else /* No IEEE 1284 support */
+
+/* Don't bother probing for modes we know we won't use. */
+static int __init parport_PS2_supported(struct parport *pb) { return 0; }
+static int __init parport_ECP_supported(struct parport *pb) { return 0; }
+static int __init parport_EPP_supported(struct parport *pb) { return 0; }
+static int __init parport_ECPEPP_supported(struct parport *pb) { return 0; }
+static int __init parport_ECPPS2_supported(struct parport *pb) { return 0; }
+
+#endif /* No IEEE 1284 support */
+
+/* --- IRQ detection -------------------------------------- */
+
+/* Only if supports ECP mode */
+static int __init programmable_irq_support(struct parport *pb)
+{
+       int irq, intrLine;
+       unsigned char oecr = inb (ECONTROL (pb));
+       static const int lookup[8] = {
+               PARPORT_IRQ_NONE, 7, 9, 10, 11, 14, 15, 5
+       };
+
+       outb (ECR_CNF << 5, ECONTROL (pb)); /* Configuration MODE */
+
+       intrLine = (inb (CONFIGB (pb)) >> 3) & 0x07;
+       irq = lookup[intrLine];
+
+       outb (oecr, ECONTROL (pb));
+       return irq;
+}
+
+static int __init irq_probe_ECP(struct parport *pb)
+{
+       int i;
+       unsigned long irqs;
+
+       sti();
+       irqs = probe_irq_on();
+               
+       outb (ECR_SPP << 5, ECONTROL (pb)); /* Reset FIFO */
+       outb ((ECR_TST << 5) | 0x04, ECONTROL (pb));
+       outb (ECR_TST << 5, ECONTROL (pb));
+
+       /* If Full FIFO sure that writeIntrThreshold is generated */
+       for (i=0; i < 1024 && !(inb (ECONTROL (pb)) & 0x02) ; i++) 
+               outb (0xaa, FIFO (pb));
+               
+       pb->irq = probe_irq_off(irqs);
+       outb (ECR_SPP << 5, ECONTROL (pb));
+
+       if (pb->irq <= 0)
+               pb->irq = PARPORT_IRQ_NONE;
+
+       return pb->irq;
+}
+
+/*
+ * This detection seems that only works in National Semiconductors
+ * This doesn't work in SMC, LGS, and Winbond 
+ */
+static int __init irq_probe_EPP(struct parport *pb)
+{
+#ifndef ADVANCED_DETECT
+       return PARPORT_IRQ_NONE;
+#else
+       int irqs;
+       unsigned char oecr;
+
+       if (pb->modes & PARPORT_MODE_PCECR)
+               oecr = inb (ECONTROL (pb));
+
+       sti();
+       irqs = probe_irq_on();
+
+       if (pb->modes & PARPORT_MODE_PCECR)
+               frob_econtrol (pb, 0x10, 0x10);
+       
+       clear_epp_timeout(pb);
+       parport_pc_frob_control (pb, 0x20, 0x20);
+       parport_pc_frob_control (pb, 0x10, 0x10);
+       clear_epp_timeout(pb);
+
+       /* Device isn't expecting an EPP read
+        * and generates an IRQ.
+        */
+       parport_pc_read_epp(pb);
+       udelay(20);
+
+       pb->irq = probe_irq_off (irqs);
+       if (pb->modes & PARPORT_MODE_PCECR)
+               outb (oecr, ECONTROL (pb));
+       parport_pc_write_control(pb, 0xc);
+
+       if (pb->irq <= 0)
+               pb->irq = PARPORT_IRQ_NONE;
+
+       return pb->irq;
+#endif /* Advanced detection */
+}
+
+static int __init irq_probe_SPP(struct parport *pb)
+{
+       /* Don't even try to do this. */
+       return PARPORT_IRQ_NONE;
+}
+
+/* We will attempt to share interrupt requests since other devices
+ * such as sound cards and network cards seem to like using the
+ * printer IRQs.
+ *
+ * When ECP is available we can autoprobe for IRQs.
+ * NOTE: If we can autoprobe it, we can register the IRQ.
+ */
+static int __init parport_irq_probe(struct parport *pb)
+{
+       const struct parport_pc_private *priv = pb->private_data;
+
+       if (priv->ecr) {
+               pb->irq = programmable_irq_support(pb);
+               if (pb->irq != PARPORT_IRQ_NONE)
+                       goto out;
+       }
+
+       if (pb->modes & PARPORT_MODE_ECP)
+               pb->irq = irq_probe_ECP(pb);
+
+       if (pb->irq == PARPORT_IRQ_NONE && priv->ecr &&
+           (pb->modes & PARPORT_MODE_EPP))
+               pb->irq = irq_probe_EPP(pb);
+
+       clear_epp_timeout(pb);
+
+       if (pb->irq == PARPORT_IRQ_NONE && (pb->modes & PARPORT_MODE_EPP))
+               pb->irq = irq_probe_EPP(pb);
+
+       clear_epp_timeout(pb);
+
+       if (pb->irq == PARPORT_IRQ_NONE)
+               pb->irq = irq_probe_SPP(pb);
+
+out:
+       return pb->irq;
+}
+
+/* --- DMA detection -------------------------------------- */
+
+/* Only if supports ECP mode */
+static int __init programmable_dma_support (struct parport *p)
+{
+       unsigned char oecr = inb (ECONTROL (p));
+       int dma;
+
+       frob_econtrol (p, 0xe0, ECR_CNF << 5);
+       
+       dma = inb (CONFIGB(p)) & 0x03;
+       if (!dma)
+               dma = PARPORT_DMA_NONE;
+
+       outb (oecr, ECONTROL (p));
+       return dma;
+}
+
+static int __init parport_dma_probe (struct parport *p)
+{
+       const struct parport_pc_private *priv = p->private_data;
+       if (priv->ecr)
+               p->dma = programmable_dma_support(p);
+
+       return p->dma;
+}
+
+/* --- Initialisation code -------------------------------- */
+
+static int __init probe_one_port(unsigned long int base,
+                                unsigned long int base_hi,
+                                int irq, int dma)
+{
+       struct parport_pc_private *priv;
+       struct parport tmp;
+       struct parport *p = &tmp;
+       int probedirq = PARPORT_IRQ_NONE;
+       if (check_region(base, 3)) return 0;
+       priv = kmalloc (sizeof (struct parport_pc_private), GFP_KERNEL);
+       if (!priv) {
+               printk (KERN_DEBUG "parport (0x%lx): no memory!\n", base);
+               return 0;
+       }
+       priv->ctr = 0xc;
+       priv->ctr_writable = 0xff;
+       priv->ecr = 0;
+       priv->fifo_depth = 0;
+       priv->dma_buf = 0;
+       p->base = base;
+       p->base_hi = base_hi;
+       p->irq = irq;
+       p->dma = dma;
+       p->modes = PARPORT_MODE_PCSPP;
+       p->ops = &parport_pc_ops;
+       p->private_data = priv;
+       p->physport = p;
+       if (base_hi && !check_region(base_hi,3)) {
+               parport_ECR_present(p);
+               parport_ECP_supported(p);
+               parport_ECPPS2_supported(p);
+       }
+       if (base != 0x3bc) {
+               if (!check_region(base+0x3, 5)) {
+                       parport_EPP_supported(p);
+                       if (!(p->modes & PARPORT_MODE_EPP))
+                               parport_ECPEPP_supported(p);
+               }
+       }
+       if (!parport_SPP_supported (p)) {
+               /* No port. */
+               kfree (priv);
+               return 0;
+       }
+
+       parport_PS2_supported (p);
+
+       if (!(p = parport_register_port(base, PARPORT_IRQ_NONE,
+                                                                       PARPORT_DMA_NONE, &parport_pc_ops))) {
+               kfree (priv);
+               return 0;
+       }
+
+       p->base_hi = base_hi;
+       p->modes = tmp.modes;
+       p->size = (p->modes & PARPORT_MODE_EPP)?8:3;
+       p->private_data = priv;
+
+       printk(KERN_INFO "%s: PC-style at 0x%lx", p->name, p->base);
+       if (p->base_hi && (p->modes & PARPORT_MODE_ECP))
+               printk(" (0x%lx)", p->base_hi);
+       p->irq = irq;
+       p->dma = dma;
+       if (p->irq == PARPORT_IRQ_AUTO) {
+               p->irq = PARPORT_IRQ_NONE;
+               parport_irq_probe(p);
+       } else if (p->irq == PARPORT_IRQ_PROBEONLY) {
+               p->irq = PARPORT_IRQ_NONE;
+               parport_irq_probe(p);
+               probedirq = p->irq;
+               p->irq = PARPORT_IRQ_NONE;
+       }
+       if (p->irq != PARPORT_IRQ_NONE) {
+               printk(", irq %d", p->irq);
+
+               if (p->dma == PARPORT_DMA_AUTO) {
+                       p->dma = PARPORT_DMA_NONE;
+                       parport_dma_probe(p);
+               }
+       }
+       if (p->dma == PARPORT_DMA_AUTO)         
+               p->dma = PARPORT_DMA_NONE;
+       if (p->dma != PARPORT_DMA_NONE) 
+               printk(", dma %d", p->dma);
+
+#ifdef CONFIG_PARPORT_PC_FIFO
+       if (priv->fifo_depth > 0 && p->irq != PARPORT_IRQ_NONE) {
+               parport_pc_ops.compat_write_data =
+                       parport_pc_compat_write_block_pio;
+#ifdef CONFIG_PARPORT_1284
+               parport_pc_ops.ecp_write_data =
+                       parport_pc_ecp_write_block_pio;
+#endif /* IEEE 1284 support */
+               if (p->dma != PARPORT_DMA_NONE)
+                       p->modes |= PARPORT_MODE_DMA;
+               printk(", using FIFO");
+       }
+#endif /* Allowed to use FIFO/DMA */
+
+       printk(" [");
+#define printmode(x) {if(p->modes&PARPORT_MODE_##x){printk("%s%s",f?",":"",#x);f++;}}
+       {
+               int f = 0;
+               printmode(PCSPP);
+               printmode(TRISTATE);
+               printmode(COMPAT)
+               printmode(EPP);
+               printmode(ECP);
+               printmode(DMA);
+       }
+#undef printmode
+       printk("]\n");
+       if (probedirq != PARPORT_IRQ_NONE) 
+               printk("%s: irq %d detected\n", p->name, probedirq);
+       parport_proc_register(p);
+
+       request_region (p->base, 3, p->name);
+       if (p->size > 3)
+               request_region (p->base + 3, p->size - 3, p->name);
+       if (p->modes & PARPORT_MODE_ECP)
+               request_region (p->base_hi, 3, p->name);
+
+       if (p->irq != PARPORT_IRQ_NONE) {
+               if (request_irq (p->irq, parport_pc_interrupt,
+                                0, p->name, p)) {
+                       printk (KERN_WARNING "%s: irq %d in use, "
+                               "resorting to polled operation\n",
+                               p->name, p->irq);
+                       p->irq = PARPORT_IRQ_NONE;
+                       p->dma = PARPORT_DMA_NONE;
+               }
+
+               if (p->dma != PARPORT_DMA_NONE) {
+                       if (request_dma (p->dma, p->name)) {
+                               printk (KERN_WARNING "%s: dma %d in use, "
+                                       "resorting to PIO operation\n",
+                                       p->name, p->dma);
+                               p->dma = PARPORT_DMA_NONE;
+                       } else {
+                               priv->dma_buf = (char *) __get_dma_pages(GFP_KERNEL, 1);
+                               if (! priv->dma_buf) {
+                                       printk (KERN_WARNING "%s: "
+                                               "cannot get buffer for DMA, "
+                                               "resorting to PIO operation\n",
+                                               p->name);
+                                       free_dma(p->dma);
+                                       p->dma = PARPORT_DMA_NONE;
+                               }
+                       }
+               }
+       }
+
+       /* Done probing.  Now put the port into a sensible start-up state.
+        * SELECT | INIT also puts IEEE1284-compliant devices into
+        * compatibility mode. */
+       if (p->modes & PARPORT_MODE_ECP)
+               /*
+                * Put the ECP detected port in PS2 mode.
+                */
+               outb (0x24, ECONTROL (p));
+
+       parport_pc_write_data(p, 0);
+       parport_pc_data_forward (p);
+       parport_pc_write_control(p, PARPORT_CONTROL_SELECT);
+       udelay (50);
+       parport_pc_write_control(p,
+                                PARPORT_CONTROL_SELECT
+                                | PARPORT_CONTROL_INIT);
+       udelay (50);
+
+       /* Now that we've told the sharing engine about the port, and
+          found out its characteristics, let the high-level drivers
+          know about it. */
+       parport_announce_port (p);
+
+       return 1;
+}
+
+/* Look for PCI parallel port cards. */
+static int __init parport_pc_init_pci (int irq, int dma)
+{
+/* These need to go in pci.h: */
+#ifndef PCI_VENDOR_ID_SIIG
+#define PCI_VENDOR_ID_SIIG              0x131f
+#define PCI_DEVICE_ID_SIIG_1S1P_10x_550 0x1010
+#define PCI_DEVICE_ID_SIIG_1S1P_10x_650 0x1011
+#define PCI_DEVICE_ID_SIIG_1S1P_10x_850 0x1012
+#define PCI_DEVICE_ID_SIIG_1P_10x       0x1020
+#define PCI_DEVICE_ID_SIIG_2P_10x       0x1021
+#define PCI_DEVICE_ID_SIIG_2S1P_10x_550 0x1034
+#define PCI_DEVICE_ID_SIIG_2S1P_10x_650 0x1035
+#define PCI_DEVICE_ID_SIIG_2S1P_10x_850 0x1036
+#define PCI_DEVICE_ID_SIIG_1P_20x       0x2020
+#define PCI_DEVICE_ID_SIIG_2P_20x       0x2021
+#define PCI_DEVICE_ID_SIIG_2P1S_20x_550 0x2040
+#define PCI_DEVICE_ID_SIIG_2P1S_20x_650 0x2041
+#define PCI_DEVICE_ID_SIIG_2P1S_20x_850 0x2042
+#define PCI_DEVICE_ID_SIIG_1S1P_20x_550 0x2010
+#define PCI_DEVICE_ID_SIIG_1S1P_20x_650 0x2011
+#define PCI_DEVICE_ID_SIIG_1S1P_20x_850 0x2012
+#define PCI_DEVICE_ID_SIIG_2S1P_20x_550 0x2060
+#define PCI_DEVICE_ID_SIIG_2S1P_20x_650 0x2061
+#define PCI_DEVICE_ID_SIIG_2S1P_20x_850 0x2062
+#define PCI_VENDOR_ID_LAVA              0x1407
+#define PCI_DEVICE_ID_LAVA_PARALLEL     0x8000
+#define PCI_DEVICE_ID_LAVA_DUAL_PAR_A   0x8001 /* The Lava Dual Parallel is */
+#define PCI_DEVICE_ID_LAVA_DUAL_PAR_B   0x8002 /* two PCI devices on a card */
+#endif
+
+       struct {
+               unsigned int vendor;
+               unsigned int device;
+               unsigned int numports;
+               struct {
+                       unsigned int lo;
+                       unsigned int hi; /* -ve if not there */
+               } addr[4];
+       } cards[] = {
+               { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_550, 1,
+                 { { 3, 4 }, } },
+               { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_650, 1,
+                 { { 3, 4 }, } },
+               { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_850, 1,
+                 { { 3, 4 }, } },
+               { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1P_10x, 1,
+                 { { 2, 3 }, } },
+               { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P_10x, 2,
+                 { { 2, 3 }, { 4, 5 }, } },
+               { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_550, 1,
+                 { { 4, 5 }, } },
+               { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_650, 1,
+                 { { 4, 5 }, } },
+               { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_850, 1,
+                 { { 4, 5 }, } },
+               { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1P_20x, 1,
+                 { { 0, 1 }, } },
+               { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P_20x, 2,
+                 { { 0, 1 }, { 2, 3 }, } },
+               { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_550, 2,
+                 { { 1, 2 }, { 3, 4 }, } },
+               { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_650, 2,
+                 { { 1, 2 }, { 3, 4 }, } },
+               { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_850, 2,
+                 { { 1, 2 }, { 3, 4 }, } },
+               { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_550, 1,
+                 { { 1, 2 }, } },
+               { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_650, 1,
+                 { { 1, 2 }, } },
+               { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_850, 1,
+                 { { 1, 2 }, } },
+               { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_550, 1,
+                 { { 2, 3 }, } },
+               { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_650, 1,
+                 { { 2, 3 }, } },
+               { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_850, 1,
+                 { { 2, 3 }, } },
+               { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_PARALLEL, 1,
+                 { { 0, -1 }, } },
+               { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_DUAL_PAR_A, 1,
+                 { { 0, -1 }, } },
+               { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_DUAL_PAR_B, 1,
+                 { { 0, -1 }, } },
+               { 0, }
+       };
+
+       int count = 0;
+       int i;
+
+       if (!pci_present ())
+               return 0;
+
+       for (i = 0; cards[i].vendor; i++) {
+               struct pci_dev *pcidev = NULL;
+               while ((pcidev = pci_find_device (cards[i].vendor,
+                                                 cards[i].device,
+                                                 pcidev)) != NULL) {
+                       int n;
+                       for (n = 0; n < cards[i].numports; n++) {
+                               int lo = cards[i].addr[n].lo;
+                               int hi = cards[i].addr[n].hi;
+                               int io_lo = pcidev->base_address[lo];
+                               int io_hi = ((hi < 0) ? 0 :
+                                            pcidev->base_address[hi]);
+                               io_lo &= PCI_BASE_ADDRESS_IO_MASK;
+                               io_hi &= PCI_BASE_ADDRESS_IO_MASK;
+                               count += probe_one_port (io_lo, io_hi,
+                                                        irq, dma);
+                       }
+               }
+       }
+
+       return count;
+}
+
+int __init parport_pc_init(int *io, int *io_hi, int *irq, int *dma)
+{
+       int count = 0, i = 0;
+       if (io && *io) {
+               /* Only probe the ports we were given. */
+               user_specified = 1;
+               do {
+                       if (!*io_hi) *io_hi = 0x400 + *io;
+                       count += probe_one_port(*(io++), *(io_hi++),
+                                               *(irq++), *(dma++));
+               } while (*io && (++i < PARPORT_PC_MAX_PORTS));
+       } else {
+               /* Probe all the likely ports. */
+               count += probe_one_port(0x3bc, 0x7bc, irq[0], dma[0]);
+               count += probe_one_port(0x378, 0x778, irq[0], dma[0]);
+               count += probe_one_port(0x278, 0x678, irq[0], dma[0]);
+               count += parport_pc_init_pci (irq[0], dma[0]);
+       }
+
+       return count;
+}
+
+#ifdef MODULE
+static int io[PARPORT_PC_MAX_PORTS+1] = { [0 ... PARPORT_PC_MAX_PORTS] = 0 };
+static int io_hi[PARPORT_PC_MAX_PORTS+1] = { [0 ... PARPORT_PC_MAX_PORTS] = 0 };
+static int dmaval[PARPORT_PC_MAX_PORTS] = { [0 ... PARPORT_PC_MAX_PORTS-1] = PARPORT_DMA_AUTO };
+static int irqval[PARPORT_PC_MAX_PORTS] = { [0 ... PARPORT_PC_MAX_PORTS-1] = PARPORT_IRQ_PROBEONLY };
+static const char *irq[PARPORT_PC_MAX_PORTS] = { NULL, };
+static const char *dma[PARPORT_PC_MAX_PORTS] = { NULL, };
+MODULE_PARM(io, "1-" __MODULE_STRING(PARPORT_PC_MAX_PORTS) "i");
+MODULE_PARM(io_hi, "1-" __MODULE_STRING(PARPORT_PC_MAX_PORTS) "i");
+MODULE_PARM(irq, "1-" __MODULE_STRING(PARPORT_PC_MAX_PORTS) "s");
+MODULE_PARM(dma, "1-" __MODULE_STRING(PARPORT_PC_MAX_PORTS) "s");
+
+int init_module(void)
+{      
+       /* Work out how many ports we have, then get parport_share to parse
+          the irq values. */
+       unsigned int i;
+       for (i = 0; i < PARPORT_PC_MAX_PORTS && io[i]; i++);
+       if (i) {
+               if (parport_parse_irqs(i, irq, irqval)) return 1;
+               if (parport_parse_dmas(i, dma, dmaval)) return 1;
+       }
+       else {
+               /* The user can make us use any IRQs or DMAs we find. */
+               int val;
+
+               if (irq[0] && !parport_parse_irqs (1, irq, &val))
+                       switch (val) {
+                       case PARPORT_IRQ_NONE:
+                       case PARPORT_IRQ_AUTO:
+                               irqval[0] = val;
+                       }
+
+               if (dma[0] && !parport_parse_dmas (1, dma, &val))
+                       switch (val) {
+                       case PARPORT_DMA_NONE:
+                       case PARPORT_DMA_AUTO:
+                               dmaval[0] = val;
+                       }
+       }
+
+       return (parport_pc_init(io, io_hi, irqval, dmaval)?0:1);
+}
+
+void cleanup_module(void)
+{
+       struct parport *p = parport_enumerate(), *tmp;
+       while (p) {
+               tmp = p->next;
+               if (p->modes & PARPORT_MODE_PCSPP) { 
+                       struct parport_pc_private *priv = p->private_data;
+                       if (p->dma != PARPORT_DMA_NONE)
+                               free_dma(p->dma);
+                       if (p->irq != PARPORT_IRQ_NONE)
+                               free_irq(p->irq, p);
+                       release_region(p->base, 3);
+                       if (p->size > 3);
+                               release_region(p->base + 3, p->size - 3);
+                       if (p->modes & PARPORT_MODE_ECP)
+                               release_region(p->base_hi, 3);
+                       parport_proc_unregister(p);
+                       if (priv->dma_buf)
+                               free_page((unsigned long) priv->dma_buf);
+                       kfree (p->private_data);
+                       parport_unregister_port(p);
+               }
+               p = tmp;
+       }
+}
+#endif
diff --git a/drivers/parport/probe.c b/drivers/parport/probe.c
new file mode 100644 (file)
index 0000000..a3c24c9
--- /dev/null
@@ -0,0 +1,212 @@
+/* $Id: parport_probe.c,v 1.1 1999/07/03 08:56:17 davem Exp $
+ * Parallel port device probing code
+ *
+ * Authors:    Carsten Gross, carsten@sol.wohnheim.uni-ulm.de
+ *             Philip Blundell <Philip.Blundell@pobox.com>
+ */
+
+#include <linux/parport.h>
+#include <linux/ctype.h>
+#include <asm/uaccess.h>
+
+static struct {
+       char *token;
+       char *descr;
+} classes[] = {
+       { "",            "Legacy device" },
+       { "PRINTER",     "Printer" },
+       { "MODEM",       "Modem" },
+       { "NET",         "Network device" },
+       { "HDC",         "Hard disk" },
+       { "PCMCIA",      "PCMCIA" },
+       { "MEDIA",       "Multimedia device" },
+       { "FDC",         "Floppy disk" },
+       { "PORTS",       "Ports" },
+       { "SCANNER",     "Scanner" },
+       { "DIGICAM",     "Digital camera" },
+       { "",            "Unknown device" },
+       { "",            "Unspecified" },
+       { "SCSIADAPTER", "SCSI adapter" },
+       { NULL,          NULL }
+};
+
+static void pretty_print(struct parport *port, int device)
+{
+       struct parport_device_info *info = &port->probe_info[device + 1];
+
+       printk(KERN_INFO "%s", port->name);
+
+       if (device >= 0)
+               printk (" (addr %d)", device);
+
+       printk (": %s", classes[info->class].descr);
+       if (info->class)
+               printk(", %s %s", info->mfr, info->model);
+
+       printk("\n");
+}
+
+static char *strdup(char *str)
+{
+       int n = strlen(str)+1;
+       char *s = kmalloc(n, GFP_KERNEL);
+       if (!s) return NULL;
+       return strcpy(s, str);
+}
+
+static void parse_data(struct parport *port, int device, char *str)
+{
+       char *txt = kmalloc(strlen(str)+1, GFP_KERNEL);
+       char *p = txt, *q;
+       int guessed_class = PARPORT_CLASS_UNSPEC;
+       struct parport_device_info *info = &port->probe_info[device + 1];
+
+       if (!txt) {
+               printk("%s probe: memory squeeze\n", port->name);
+               return;
+       }
+       strcpy(txt, str);
+       while (p) {
+               char *sep;
+               q = strchr(p, ';');
+               if (q) *q = 0;
+               sep = strchr(p, ':');
+               if (sep) {
+                       char *u = p;
+                       *(sep++) = 0;
+                       while (*u) {
+                               *u = toupper(*u);
+                               u++;
+                       }
+                       if (!strcmp(p, "MFG") || !strcmp(p, "MANUFACTURER")) {
+                               if (info->mfr)
+                                       kfree (info->mfr);
+                               info->mfr = strdup(sep);
+                       } else if (!strcmp(p, "MDL") || !strcmp(p, "MODEL")) {
+                               if (info->model)
+                                       kfree (info->model);
+                               info->model = strdup(sep);
+                       } else if (!strcmp(p, "CLS") || !strcmp(p, "CLASS")) {
+                               int i;
+                               if (info->class_name)
+                                       kfree (info->class_name);
+                               info->class_name = strdup(sep);
+                               for (u = sep; *u; u++)
+                                       *u = toupper(*u);
+                               for (i = 0; classes[i].token; i++) {
+                                       if (!strcmp(classes[i].token, sep)) {
+                                               info->class = i;
+                                               goto rock_on;
+                                       }
+                               }
+                               printk(KERN_WARNING "%s probe: warning, class '%s' not understood.\n", port->name, sep);
+                               info->class = PARPORT_CLASS_OTHER;
+                       } else if (!strcmp(p, "CMD") ||
+                                  !strcmp(p, "COMMAND SET")) {
+                               if (info->cmdset)
+                                       kfree (info->cmdset);
+                               info->cmdset = strdup(sep);
+                               /* if it speaks printer language, it's
+                                  probably a printer */
+                               if (strstr(sep, "PJL") || strstr(sep, "PCL"))
+                                       guessed_class = PARPORT_CLASS_PRINTER;
+                       } else if (!strcmp(p, "DES") || !strcmp(p, "DESCRIPTION")) {
+                               if (info->description)
+                                       kfree (info->description);
+                               info->description = strdup(sep);
+                       }
+               }
+       rock_on:
+               if (q) p = q+1; else p=NULL;
+       }
+
+       /* If the device didn't tell us its class, maybe we have managed to
+          guess one from the things it did say. */
+       if (info->class == PARPORT_CLASS_UNSPEC)
+               info->class = guessed_class;
+
+       pretty_print (port, device);
+
+       kfree(txt);
+}
+
+/* Get Std 1284 Device ID. */
+ssize_t parport_device_id (int devnum, char *buffer, size_t len)
+{
+       ssize_t retval = -ENXIO;
+       struct pardevice *dev = parport_open (devnum, "Device ID probe",
+                                             NULL, NULL, NULL, 0, NULL);
+       if (!dev)
+               return -ENXIO;
+
+       parport_claim_or_block (dev);
+
+       /* Negotiate to compatibility mode, and then to device ID mode.
+        * (This is in case we are already in device ID mode.) */
+       parport_negotiate (dev->port, IEEE1284_MODE_COMPAT);
+       retval = parport_negotiate (dev->port,
+                                   IEEE1284_MODE_NIBBLE | IEEE1284_DEVICEID);
+
+       if (!retval) {
+               int idlen;
+               unsigned char length[2];
+               mm_segment_t oldfs = get_fs ();
+               set_fs (get_ds ());
+
+               /* First two bytes are MSB,LSB of inclusive length. */
+               retval = parport_read (dev->port, length, 2);
+
+               if (retval != 2) goto restore_fs;
+
+               idlen = (length[0] << 8) + length[1] - 2;
+               if (idlen < len)
+                       len = idlen;
+               retval = parport_read (dev->port, buffer, len);
+
+               if (retval != len) {
+                       printk (KERN_DEBUG "%s: only read %d of %d ID bytes\n",
+                               dev->port->name, retval, len);
+                       goto restore_fs;
+               }
+
+               /* Some printer manufacturers mistakenly believe that
+                   the length field is supposed to be _exclusive_. */
+               /* In addition, there are broken devices out there
+                   that don't even finish off with a semi-colon. */
+               if (idlen == len && buffer[len - 1] != ';') {
+                       ssize_t diff;
+                       diff = parport_read (dev->port, buffer + len, 2);
+                       retval += diff;
+
+                       if (diff)
+                               printk (KERN_DEBUG
+                                       "%s: device reported incorrect "
+                                       "length field (%d, should be %d)\n",
+                                       dev->port->name, idlen, retval);
+                       else {
+                               /* One semi-colon short of a device ID. */
+                               buffer[len++] = ';';
+                               buffer[len] = '\0';
+                               printk (KERN_DEBUG "%s: faking semi-colon\n",
+                                       dev->port->name);
+
+                               /* If we get here, I don't think we
+                                   need to worry about the possible
+                                   standard violation of having read
+                                   more than we were told to.  The
+                                   device is non-compliant anyhow. */
+                       }
+               }
+
+       restore_fs:
+               set_fs (oldfs);
+               parport_negotiate (dev->port, IEEE1284_MODE_COMPAT);
+       }
+       parport_release (dev);
+
+       if (retval > 0)
+               parse_data (dev->port, dev->daisy, buffer);
+
+       parport_close (dev);
+       return retval;
+}
diff --git a/drivers/parport/procfs.c b/drivers/parport/procfs.c
new file mode 100644 (file)
index 0000000..0c7be43
--- /dev/null
@@ -0,0 +1,434 @@
+/* Sysctl interface for parport devices.
+ * 
+ * Authors: David Campbell <campbell@torque.net>
+ *          Tim Waugh <tim@cyberelk.demon.co.uk>
+ *          Philip Blundell <philb@gnu.org>
+ *          Andrea Arcangeli
+ *          Riccardo Facchetti <fizban@tin.it>
+ *
+ * based on work by Grant Guenther <grant@torque.net>
+ *              and Philip Blundell
+ *
+ * Cleaned up include files - Russell King <linux@arm.uk.linux.org>
+ */
+
+#include <linux/string.h>
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/malloc.h>
+#include <linux/parport.h>
+#include <linux/ctype.h>
+#include <linux/sysctl.h>
+
+#include <asm/uaccess.h>
+
+#ifdef CONFIG_SYSCTL
+
+
+static int do_active_device(ctl_table *table, int write, struct file *filp,
+                     void *result, size_t *lenp)
+{
+       struct parport *port = (struct parport *)table->extra1;
+       char buffer[256];
+       struct pardevice *dev;
+       int len = 0;
+
+       if (write)              /* can't happen anyway */
+               return -EACCES;
+
+       if (filp->f_pos) {
+               *lenp = 0;
+               return 0;
+       }
+       
+       for (dev = port->devices; dev ; dev = dev->next) {
+               if(dev == port->cad) {
+                       len += sprintf(buffer, "%s\n", dev->name);
+               }
+       }
+
+       if(!len) {
+               len += sprintf(buffer, "%s\n", "none");
+       }
+
+       if (len > *lenp)
+               len = *lenp;
+       else
+               *lenp = len;
+
+       filp->f_pos += len;
+
+       return copy_to_user(result, buffer, len) ? -EFAULT : 0;
+}
+
+#ifdef CONFIG_PARPORT_1284
+static int do_autoprobe(ctl_table *table, int write, struct file *filp,
+                       void *result, size_t *lenp)
+{
+       struct parport_device_info *info = table->extra2;
+       const char *str;
+       char buffer[256];
+       int len = 0;
+
+       if (write) /* permissions stop this */
+               return -EACCES;
+
+       if (filp->f_pos) {
+               *lenp = 0;
+               return 0;
+       }
+       
+       if ((str = info->class_name) != NULL)
+               len += sprintf (buffer + len, "CLASS:%s;\n", str);
+
+       if ((str = info->model) != NULL)
+               len += sprintf (buffer + len, "MODEL:%s;\n", str);
+
+       if ((str = info->mfr) != NULL)
+               len += sprintf (buffer + len, "MANUFACTURER:%s;\n", str);
+
+       if ((str = info->description) != NULL)
+               len += sprintf (buffer + len, "DESCRIPTION:%s;\n", str);
+
+       if ((str = info->cmdset) != NULL)
+               len += sprintf (buffer + len, "COMMAND SET:%s;\n", str);
+
+       if (len > *lenp)
+               len = *lenp;
+       else
+               *lenp = len;
+
+       filp->f_pos += len;
+
+       return copy_to_user (result, buffer, len) ? -EFAULT : 0;
+}
+#endif /* IEEE1284.3 support. */
+
+static int do_hardware(ctl_table *table, int write, struct file *filp,
+                      void *result, size_t *lenp)
+{
+       struct parport *port = (struct parport *)table->extra1;
+       char buffer[256];
+       int len = 0;
+
+       if (filp->f_pos) {
+               *lenp = 0;
+               return 0;
+       }
+       
+       if (write)              /* can't happen anyway */
+               return -EACCES;
+       
+       len += sprintf(buffer+len, "base:\t0x%lx", port->base);
+       if (port->base_hi)
+               len += sprintf(buffer+len, " (0x%lx)", port->base_hi);
+       buffer[len++] = '\n';
+
+       if (port->irq == PARPORT_IRQ_NONE) {
+               len += sprintf(buffer+len, "irq:\tnone\n");
+       } else {
+#ifdef __sparc__
+               len += sprintf(buffer+len, "irq:\t%s\n", 
+                              __irq_itoa(port->irq));
+#else
+               len += sprintf(buffer+len, "irq:\t%d\n", port->irq);
+#endif
+       }
+
+       if (port->dma == PARPORT_DMA_NONE)
+               len += sprintf(buffer+len, "dma:\tnone\n");
+       else
+               len += sprintf(buffer+len, "dma:\t%d\n", port->dma);
+
+       len += sprintf(buffer+len, "modes:\t");
+       {
+#define printmode(x) {if(port->modes&PARPORT_MODE_##x){len+=sprintf(buffer+len,"%s%s",f?",":"",#x);f++;}}
+               int f = 0;
+               printmode(PCSPP);
+               printmode(TRISTATE);
+               printmode(COMPAT);
+               printmode(EPP);
+               printmode(ECP);
+               printmode(DMA);
+#undef printmode
+       }
+       buffer[len++] = '\n';
+
+       if (len > *lenp)
+               len = *lenp;
+       else
+               *lenp = len;
+
+       filp->f_pos += len;
+
+       return copy_to_user(result, buffer, len) ? -EFAULT : 0;
+}
+
+#define PARPORT_PORT_DIR(child) { 0, NULL, NULL, 0, 0555, child }
+#define PARPORT_PARPORT_DIR(child) { DEV_PARPORT, "parport", \
+                                     NULL, 0, 0555, child }
+#define PARPORT_DEV_DIR(child) { CTL_DEV, "dev", NULL, 0, 0555, child }
+#define PARPORT_DEVICES_ROOT_DIR  { DEV_PARPORT_DEVICES, "devices", \
+                                    NULL, 0, 0555, NULL }
+
+
+struct parport_sysctl_table {
+       struct ctl_table_header *sysctl_header;
+       ctl_table vars[9];
+       ctl_table device_dir[2];
+       ctl_table port_dir[2];
+       ctl_table parport_dir[2];
+       ctl_table dev_dir[2];
+};
+
+static const struct parport_sysctl_table parport_sysctl_template = {
+       NULL,
+        {
+               { DEV_PARPORT_SPINTIME, "spintime",
+                 NULL, sizeof(int), 0644, NULL,
+                 &proc_dointvec },
+               { DEV_PARPORT_HARDWARE, "hardware",
+                 NULL, 0, 0444, NULL,
+                 &do_hardware },
+               PARPORT_DEVICES_ROOT_DIR,
+#ifdef CONFIG_PARPORT_1284
+               { DEV_PARPORT_AUTOPROBE, "autoprobe",
+                 NULL, 0, 0444, NULL,
+                 &do_autoprobe },
+               { DEV_PARPORT_AUTOPROBE + 1, "autoprobe0",
+                NULL, 0, 0444, NULL,
+                &do_autoprobe },
+               { DEV_PARPORT_AUTOPROBE + 2, "autoprobe1",
+                 NULL, 0, 0444, NULL,
+                 &do_autoprobe },
+               { DEV_PARPORT_AUTOPROBE + 3, "autoprobe2",
+                 NULL, 0, 0444, NULL,
+                 &do_autoprobe },
+               { DEV_PARPORT_AUTOPROBE + 4, "autoprobe3",
+                 NULL, 0, 0444, NULL,
+                 &do_autoprobe },
+#endif /* IEEE 1284 support */
+               {0}
+       },
+       { {DEV_PARPORT_DEVICES_ACTIVE, "active", NULL, 0, 444, NULL,
+         &do_active_device }, {0}},
+       { PARPORT_PORT_DIR(NULL), {0}},
+       { PARPORT_PARPORT_DIR(NULL), {0}},
+       { PARPORT_DEV_DIR(NULL), {0}}
+};
+
+struct parport_device_sysctl_table
+{
+       struct ctl_table_header *sysctl_header;
+       ctl_table vars[2];
+       ctl_table device_dir[2];
+       ctl_table devices_root_dir[2];
+       ctl_table port_dir[2];
+       ctl_table parport_dir[2];
+       ctl_table dev_dir[2];
+};
+
+static const struct parport_device_sysctl_table
+parport_device_sysctl_template = {
+       NULL,
+       {
+               { DEV_PARPORT_DEVICE_TIMESLICE, "timeslice",
+                 NULL, sizeof(int), 0644, NULL,
+                 &proc_dointvec },
+       },
+       { {0, NULL, NULL, 0, 0555, NULL}, {0}},
+       { PARPORT_DEVICES_ROOT_DIR, {0}},
+       { PARPORT_PORT_DIR(NULL), {0}},
+       { PARPORT_PARPORT_DIR(NULL), {0}},
+       { PARPORT_DEV_DIR(NULL), {0}}
+};
+
+struct parport_default_sysctl_table
+{
+       struct ctl_table_header *sysctl_header;
+       ctl_table vars[3];
+        ctl_table default_dir[2];
+       ctl_table parport_dir[2];
+       ctl_table dev_dir[2];
+};
+
+extern unsigned long parport_default_timeslice;
+extern int parport_default_spintime;
+
+static struct parport_default_sysctl_table
+parport_default_sysctl_table = {
+       NULL,
+       {
+               { DEV_PARPORT_DEFAULT_TIMESLICE, "timeslice",
+                 &parport_default_timeslice,
+                 sizeof(parport_default_timeslice), 0644, NULL,
+                 &proc_dointvec },
+               { DEV_PARPORT_DEFAULT_SPINTIME, "spintime",
+                 &parport_default_spintime,
+                 sizeof(parport_default_timeslice), 0644, NULL,
+                 &proc_dointvec },
+               {0}
+       },
+       { { DEV_PARPORT_DEFAULT, "default", NULL, 0, 0555,
+           parport_default_sysctl_table.vars },{0}},
+       {
+       PARPORT_PARPORT_DIR(parport_default_sysctl_table.default_dir), 
+       {0}},
+       { PARPORT_DEV_DIR(parport_default_sysctl_table.parport_dir), {0}}
+};
+
+
+int parport_proc_register(struct parport *port)
+{
+       struct parport_sysctl_table *t;
+       int i;
+
+       t = kmalloc(sizeof(*t), GFP_KERNEL);
+       if (t == NULL)
+               return -ENOMEM;
+       memcpy(t, &parport_sysctl_template, sizeof(*t));
+
+       t->device_dir[0].extra1 = port;
+
+       for (i = 0; i < 8; i++)
+               t->vars[i].extra1 = port;
+
+       t->vars[0].data = &port->spintime;
+       t->vars[2].child = t->device_dir;
+       
+       for (i = 0; i < 5; i++)
+               t->vars[3 + i].extra2 = &port->probe_info[i];
+
+       t->port_dir[0].procname = port->name;
+       t->port_dir[0].ctl_name = port->number + 1; /* nb 0 isn't legal here */
+
+       t->port_dir[0].child = t->vars;
+       t->parport_dir[0].child = t->port_dir;
+       t->dev_dir[0].child = t->parport_dir;
+
+       t->sysctl_header = register_sysctl_table(t->dev_dir, 0);
+       if (t->sysctl_header == NULL) {
+               kfree(t);
+               t = NULL;
+       }
+       port->sysctl_table = t;
+       return 0;
+}
+
+int parport_proc_unregister(struct parport *port)
+{
+       if (port->sysctl_table) {
+               struct parport_sysctl_table *t = port->sysctl_table;
+               port->sysctl_table = NULL;
+               unregister_sysctl_table(t->sysctl_header);
+               kfree(t);
+       }
+       return 0;
+}
+
+int parport_device_proc_register(struct pardevice *device)
+{
+       struct parport_device_sysctl_table *t;
+       struct parport * port = device->port;
+       
+       t = kmalloc(sizeof(*t), GFP_KERNEL);
+       if (t == NULL)
+               return -ENOMEM;
+       memcpy(t, &parport_device_sysctl_template, sizeof(*t));
+
+       t->dev_dir[0].child = t->parport_dir;
+       t->parport_dir[0].child = t->port_dir;
+       t->port_dir[0].procname = port->name;
+       t->port_dir[0].ctl_name = port->number + 1; /* nb 0 isn't legal here */
+       t->port_dir[0].child = t->devices_root_dir;
+       t->devices_root_dir[0].child = t->device_dir;
+
+#ifdef CONFIG_PARPORT_1284
+
+       t->device_dir[0].ctl_name =
+               parport_device_num(port->number, port->muxport,
+                                  device->daisy)
+               + 1;  /* nb 0 isn't legal here */ 
+
+#else /* No IEEE 1284 support */
+
+       /* parport_device_num isn't available. */
+       t->device_dir[0].ctl_name = 1;
+       
+#endif /* IEEE 1284 support or not */
+
+       t->device_dir[0].procname = device->name;
+       t->device_dir[0].extra1 = device;
+       t->device_dir[0].child = t->vars;
+       t->vars[0].data = &device->timeslice;
+
+       t->sysctl_header = register_sysctl_table(t->dev_dir, 0);
+       if (t->sysctl_header == NULL) {
+               kfree(t);
+               t = NULL;
+       }
+       device->sysctl_table = t;
+       return 0;
+}
+
+int parport_device_proc_unregister(struct pardevice *device)
+{
+       if (device->sysctl_table) {
+               struct parport_device_sysctl_table *t = device->sysctl_table;
+               device->sysctl_table = NULL;
+               unregister_sysctl_table(t->sysctl_header);
+               kfree(t);
+       }
+       return 0;
+}
+
+int parport_default_proc_register(void)
+{
+       parport_default_sysctl_table.sysctl_header =
+               register_sysctl_table(parport_default_sysctl_table.dev_dir, 0);
+       return 0;
+}
+
+int parport_default_proc_unregister(void)
+{
+       if (parport_default_sysctl_table.sysctl_header) {
+               unregister_sysctl_table(parport_default_sysctl_table.
+                                       sysctl_header);
+               parport_default_sysctl_table.sysctl_header = NULL;
+       }
+       return 0;
+}
+
+#else /* no sysctl */
+
+int parport_proc_register(struct parport *pp)
+{
+       return 0;
+}
+
+int parport_proc_unregister(struct parport *pp)
+{
+       return 0;
+}
+
+int parport_device_proc_register(struct pardevice *device)
+{
+       return 0;
+}
+
+int parport_device_proc_unregister(struct pardevice *device)
+{
+       return 0;
+}
+
+int parport_default_proc_register (void)
+{
+       return 0;
+}
+
+int parport_default_proc_unregister (void)
+{
+       return 0;
+}
+#endif
diff --git a/drivers/parport/share.c b/drivers/parport/share.c
new file mode 100644 (file)
index 0000000..e26a476
--- /dev/null
@@ -0,0 +1,602 @@
+/* $Id: parport_share.c,v 1.15 1998/01/11 12:06:17 philip Exp $
+ * Parallel-port resource manager code.
+ * 
+ * Authors: David Campbell <campbell@tirian.che.curtin.edu.au>
+ *          Tim Waugh <tim@cyberelk.demon.co.uk>
+ *          Jose Renau <renau@acm.org>
+ *          Philip Blundell <philb@gnu.org>
+ *         Andrea Arcangeli
+ *
+ * based on work by Grant Guenther <grant@torque.net>
+ *          and Philip Blundell
+ */
+
+#undef PARPORT_DEBUG_SHARING           /* undef for production */
+
+#include <linux/config.h>
+#include <linux/string.h>
+#include <linux/threads.h>
+#include <linux/parport.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/malloc.h>
+#include <linux/sched.h>
+
+#include <asm/spinlock.h>
+#include <asm/irq.h>
+
+#undef PARPORT_PARANOID
+
+#define PARPORT_DEFAULT_TIMESLICE      (HZ/5)
+
+unsigned long parport_default_timeslice = PARPORT_DEFAULT_TIMESLICE;
+int parport_default_spintime =  DEFAULT_SPIN_TIME;
+
+static struct parport *portlist = NULL, *portlist_tail = NULL;
+spinlock_t parportlist_lock = SPIN_LOCK_UNLOCKED;
+
+static struct parport_driver *driver_chain = NULL;
+spinlock_t driverlist_lock = SPIN_LOCK_UNLOCKED;
+
+static void call_driver_chain(int attach, struct parport *port)
+{
+       struct parport_driver *drv;
+
+       for (drv = driver_chain; drv; drv = drv->next) {
+               if (attach)
+                       drv->attach (port);
+               else
+                       drv->detach (port);
+       }
+}
+
+int parport_register_driver (struct parport_driver *drv)
+{
+       struct parport *port;
+
+       spin_lock (&driverlist_lock);
+       drv->next = driver_chain;
+       driver_chain = drv;
+       spin_unlock (&driverlist_lock);
+
+       for (port = portlist; port; port = port->next)
+               drv->attach (port);
+
+       return 0;
+}
+
+void parport_unregister_driver (struct parport_driver *arg)
+{
+       struct parport_driver *drv = driver_chain, *olddrv = NULL;
+
+       while (drv) {
+               if (drv == arg) {
+                       spin_lock (&driverlist_lock);
+                       if (olddrv)
+                               olddrv->next = drv->next;
+                       else
+                               driver_chain = drv->next;
+                       spin_unlock (&driverlist_lock);
+                       return;
+               }
+               olddrv = drv;
+               drv = drv->next;
+       }
+}
+
+/* Return a list of all the ports we know about. */
+struct parport *parport_enumerate(void)
+{
+       return portlist;
+}
+
+struct parport *parport_register_port(unsigned long base, int irq, int dma,
+                                     struct parport_operations *ops)
+{
+       struct parport *tmp;
+       int portnum;
+       int device;
+       char *name;
+
+       tmp = kmalloc(sizeof(struct parport), GFP_KERNEL);
+       if (!tmp) {
+               printk(KERN_WARNING "parport: memory squeeze\n");
+               return NULL;
+       }
+
+       /* Search for the lowest free parport number. */
+       for (portnum = 0; ; portnum++) {
+               struct parport *itr = portlist;
+               while (itr) {
+                       if (itr->number == portnum)
+                               /* No good, already used. */
+                               break;
+                       else
+                               itr = itr->next;
+               }
+
+               if (itr == NULL)
+                       /* Got to the end of the list. */
+                       break;
+       }
+       
+       /* Init our structure */
+       memset(tmp, 0, sizeof(struct parport));
+       tmp->base = base;
+       tmp->irq = irq;
+       tmp->dma = dma;
+       tmp->muxport = tmp->daisy = tmp->muxsel = -1;
+       tmp->modes = 0;
+       tmp->next = NULL;
+       tmp->devices = tmp->cad = NULL;
+       tmp->flags = 0;
+       tmp->ops = ops;
+       tmp->portnum = tmp->number = portnum;
+       tmp->physport = tmp;
+       memset (tmp->probe_info, 0, 5 * sizeof (struct parport_device_info));
+       tmp->cad_lock = RW_LOCK_UNLOCKED;
+       spin_lock_init(&tmp->waitlist_lock);
+       spin_lock_init(&tmp->pardevice_lock);
+       tmp->ieee1284.mode = IEEE1284_MODE_COMPAT;
+       tmp->ieee1284.phase = IEEE1284_PH_FWD_IDLE;
+       init_MUTEX_LOCKED (&tmp->ieee1284.irq); /* actually a semaphore at 0 */
+       tmp->spintime = parport_default_spintime;
+
+       name = kmalloc(15, GFP_KERNEL);
+       if (!name) {
+               printk(KERN_ERR "parport: memory squeeze\n");
+               kfree(tmp);
+               return NULL;
+       }
+       sprintf(name, "parport%d", portnum);
+       tmp->name = name;
+
+       /*
+        * Chain the entry to our list.
+        *
+        * This function must not run from an irq handler so we don' t need
+        * to clear irq on the local CPU. -arca
+        */
+       spin_lock(&parportlist_lock);
+       if (portlist_tail)
+               portlist_tail->next = tmp;
+       portlist_tail = tmp;
+       if (!portlist)
+               portlist = tmp;
+       spin_unlock(&parportlist_lock);
+
+       for (device = 0; device < 5; device++)
+               /* assume the worst */
+               tmp->probe_info[device].class = PARPORT_CLASS_LEGACY;
+
+       tmp->waithead = tmp->waittail = NULL;
+
+       return tmp;
+}
+
+void parport_announce_port (struct parport *port)
+{
+#ifdef CONFIG_PARPORT_1284
+       /* Analyse the IEEE1284.3 topology of the port. */
+       parport_daisy_init (port);
+#endif
+
+       /* Let drivers know that a new port has arrived. */
+       call_driver_chain (1, port);
+}
+
+void parport_unregister_port(struct parport *port)
+{
+       struct parport *p;
+       int d;
+
+       /* Spread the word. */
+       call_driver_chain (0, port);
+
+#ifdef CONFIG_PARPORT_1284
+       /* Forget the IEEE1284.3 topology of the port. */
+       parport_daisy_fini (port);
+#endif
+
+       spin_lock(&parportlist_lock);
+       if (portlist == port) {
+               if ((portlist = port->next) == NULL)
+                       portlist_tail = NULL;
+       } else {
+               for (p = portlist; (p != NULL) && (p->next != port); 
+                    p=p->next);
+               if (p) {
+                       if ((p->next = port->next) == NULL)
+                               portlist_tail = p;
+               }
+               else printk (KERN_WARNING
+                            "%s not found in port list!\n", port->name);
+       }
+       spin_unlock(&parportlist_lock);
+
+       for (d = 0; d < 5; d++) {
+               if (port->probe_info[d].class_name)
+                       kfree (port->probe_info[d].class_name);
+               if (port->probe_info[d].mfr)
+                       kfree (port->probe_info[d].mfr);
+               if (port->probe_info[d].model)
+                       kfree (port->probe_info[d].model);
+               if (port->probe_info[d].cmdset)
+                       kfree (port->probe_info[d].cmdset);
+               if (port->probe_info[d].description)
+                       kfree (port->probe_info[d].description);
+       }
+
+       kfree(port->name);
+       kfree(port);
+}
+
+struct pardevice *parport_register_device(struct parport *port, const char *name,
+                         int (*pf)(void *), void (*kf)(void *),
+                         void (*irq_func)(int, void *, struct pt_regs *), 
+                         int flags, void *handle)
+{
+       struct pardevice *tmp;
+
+       if (port->physport->flags & PARPORT_FLAG_EXCL) {
+               /* An exclusive device is registered. */
+               printk (KERN_DEBUG "%s: no more devices allowed\n",
+                       port->name);
+               return NULL;
+       }
+
+       if (flags & PARPORT_DEV_LURK) {
+               if (!pf || !kf) {
+                       printk(KERN_INFO "%s: refused to register lurking device (%s) without callbacks\n", port->name, name);
+                       return NULL;
+               }
+       }
+
+       tmp = kmalloc(sizeof(struct pardevice), GFP_KERNEL);
+       if (tmp == NULL) {
+               printk(KERN_WARNING "%s: memory squeeze, couldn't register %s.\n", port->name, name);
+               return NULL;
+       }
+
+       tmp->state = kmalloc(sizeof(struct parport_state), GFP_KERNEL);
+       if (tmp->state == NULL) {
+               printk(KERN_WARNING "%s: memory squeeze, couldn't register %s.\n", port->name, name);
+               kfree(tmp);
+               return NULL;
+       }
+
+       tmp->name = name;
+       tmp->port = port;
+       tmp->daisy = -1;
+       tmp->preempt = pf;
+       tmp->wakeup = kf;
+       tmp->private = handle;
+       tmp->flags = flags;
+       tmp->irq_func = irq_func;
+       tmp->waiting = 0;
+       tmp->timeout = 5 * HZ;
+
+       /* Chain this onto the list */
+       tmp->prev = NULL;
+       /*
+        * This function must not run from an irq handler so we don' t need
+        * to clear irq on the local CPU. -arca
+        */
+       spin_lock(&port->physport->pardevice_lock);
+
+       if (flags & PARPORT_DEV_EXCL) {
+               if (port->physport->devices) {
+                       spin_unlock (&port->physport->pardevice_lock);
+                       kfree (tmp->state);
+                       kfree (tmp);
+                       printk (KERN_DEBUG
+                               "%s: cannot grant exclusive access for "
+                               "device %s\n", port->name, name);
+                       return NULL;
+               }
+               port->flags |= PARPORT_FLAG_EXCL;
+       }
+
+       tmp->next = port->physport->devices;
+       if (port->physport->devices)
+               port->physport->devices->prev = tmp;
+       port->physport->devices = tmp;
+       spin_unlock(&port->physport->pardevice_lock);
+
+       inc_parport_count();
+       port->ops->inc_use_count();
+
+       init_waitqueue_head(&tmp->wait_q);
+       tmp->timeslice = parport_default_timeslice;
+       tmp->waitnext = tmp->waitprev = NULL;
+
+       /*
+        * This has to be run as last thing since init_state may need other
+        * pardevice fields. -arca
+        */
+       port->ops->init_state(tmp, tmp->state);
+       parport_device_proc_register(tmp);
+       return tmp;
+}
+
+void parport_unregister_device(struct pardevice *dev)
+{
+       struct parport *port;
+
+#ifdef PARPORT_PARANOID
+       if (dev == NULL) {
+               printk(KERN_ERR "parport_unregister_device: passed NULL\n");
+               return;
+       }
+#endif
+
+       parport_device_proc_unregister(dev);
+
+       port = dev->port->physport;
+
+       if (port->cad == dev) {
+               printk(KERN_DEBUG "%s: %s forgot to release port\n",
+                      port->name, dev->name);
+               parport_release (dev);
+       }
+
+       spin_lock(&port->pardevice_lock);
+       if (dev->next)
+               dev->next->prev = dev->prev;
+       if (dev->prev)
+               dev->prev->next = dev->next;
+       else
+               port->devices = dev->next;
+
+       if (dev->flags & PARPORT_DEV_EXCL)
+               port->flags &= ~PARPORT_FLAG_EXCL;
+
+       spin_unlock(&port->pardevice_lock);
+
+       kfree(dev->state);
+       kfree(dev);
+
+       dec_parport_count();
+       port->ops->dec_use_count();
+}
+
+int parport_claim(struct pardevice *dev)
+{
+       struct pardevice *oldcad;
+       struct parport *port = dev->port->physport;
+       unsigned long flags;
+
+       if (port->cad == dev) {
+               printk(KERN_INFO "%s: %s already owner\n",
+                      dev->port->name,dev->name);
+               return 0;
+       }
+
+try_again:
+       /* Preempt any current device */
+       if ((oldcad = port->cad) != NULL) {
+               if (oldcad->preempt) {
+                       if (oldcad->preempt(oldcad->private))
+                               goto blocked;
+                       port->ops->save_state(port, dev->state);
+               } else
+                       goto blocked;
+
+               if (port->cad != oldcad) {
+                       printk(KERN_WARNING 
+                              "%s: %s released port when preempted!\n",
+                              port->name, oldcad->name);
+                       if (port->cad)
+                               goto blocked;
+               }
+       }
+
+       /* Can't fail from now on, so mark ourselves as no longer waiting.  */
+       if (dev->waiting & 1) {
+               dev->waiting = 0;
+
+               /* Take ourselves out of the wait list again.  */
+               spin_lock_irqsave (&port->waitlist_lock, flags);
+               if (dev->waitprev)
+                       dev->waitprev->waitnext = dev->waitnext;
+               else
+                       port->waithead = dev->waitnext;
+               if (dev->waitnext)
+                       dev->waitnext->waitprev = dev->waitprev;
+               else
+                       port->waittail = dev->waitprev;
+               spin_unlock_irqrestore (&port->waitlist_lock, flags);
+               dev->waitprev = dev->waitnext = NULL;
+       }
+
+       /* Now we do the change of devices */
+       write_lock_irqsave(&port->cad_lock, flags);
+       port->cad = dev;
+       write_unlock_irqrestore(&port->cad_lock, flags);
+
+#ifdef CONFIG_PARPORT_1284
+       /* If it's a mux port, select it. */
+       if (dev->port->muxport >= 0) {
+               /* FIXME */
+               port->muxsel = dev->port->muxport;
+       }
+
+       /* If it's a daisy chain device, select it. */
+       if (dev->daisy >= 0) {
+               /* This could be lazier. */
+               if (!parport_daisy_select (port, dev->daisy,
+                                          IEEE1284_MODE_COMPAT))
+                       port->daisy = dev->daisy;
+       }
+#endif /* IEEE1284.3 support */
+
+       /* Restore control registers */
+       port->ops->restore_state(port, dev->state);
+       dev->time = jiffies;
+       return 0;
+
+blocked:
+       /* If this is the first time we tried to claim the port, register an
+          interest.  This is only allowed for devices sleeping in
+          parport_claim_or_block(), or those with a wakeup function.  */
+       if (dev->waiting & 2 || dev->wakeup) {
+               spin_lock_irqsave (&port->waitlist_lock, flags);
+               if (port->cad == NULL) {
+                       /* The port got released in the meantime. */
+                       spin_unlock_irqrestore (&port->waitlist_lock, flags);
+                       goto try_again;
+               }
+               if (test_and_set_bit(0, &dev->waiting) == 0) {
+                       /* First add ourselves to the end of the wait list. */
+                       dev->waitnext = NULL;
+                       dev->waitprev = port->waittail;
+                       if (port->waittail) {
+                               port->waittail->waitnext = dev;
+                               port->waittail = dev;
+                       } else
+                               port->waithead = port->waittail = dev;
+               }
+               spin_unlock_irqrestore (&port->waitlist_lock, flags);
+       }
+       return -EAGAIN;
+}
+
+int parport_claim_or_block(struct pardevice *dev)
+{
+       int r;
+
+       /* Signal to parport_claim() that we can wait even without a
+          wakeup function.  */
+       dev->waiting = 2;
+
+       /* Try to claim the port.  If this fails, we need to sleep.  */
+       r = parport_claim(dev);
+       if (r == -EAGAIN) {
+               unsigned long flags;
+#ifdef PARPORT_DEBUG_SHARING
+               printk(KERN_DEBUG "%s: parport_claim() returned -EAGAIN\n", dev->name);
+#endif
+               save_flags (flags);
+               cli();
+               /* If dev->waiting is clear now, an interrupt
+                  gave us the port and we would deadlock if we slept.  */
+               if (dev->waiting) {
+                       sleep_on(&dev->wait_q);
+                       r = 1;
+               } else {
+                       r = 0;
+#ifdef PARPORT_DEBUG_SHARING
+                       printk(KERN_DEBUG "%s: didn't sleep in parport_claim_or_block()\n",
+                              dev->name);
+#endif
+               }
+               restore_flags(flags);
+#ifdef PARPORT_DEBUG_SHARING
+               if (dev->port->physport->cad != dev)
+                       printk(KERN_DEBUG "%s: exiting parport_claim_or_block "
+                              "but %s owns port!\n", dev->name,
+                              dev->port->physport->cad ?
+                              dev->port->physport->cad->name:"nobody");
+#endif
+       }
+       dev->waiting = 0;
+       return r;
+}
+
+void parport_release(struct pardevice *dev)
+{
+       struct parport *port = dev->port->physport;
+       struct pardevice *pd;
+       unsigned long flags;
+
+       /* Make sure that dev is the current device */
+       if (port->cad != dev) {
+               printk(KERN_WARNING "%s: %s tried to release parport "
+                      "when not owner\n", port->name, dev->name);
+               return;
+       }
+
+#ifdef CONFIG_PARPORT_1284
+       /* If this is on a mux port, deselect it. */
+       if (dev->port->muxport >= 0) {
+               /* FIXME */
+               port->muxsel = -1;
+       }
+
+       /* If this is a daisy device, deselect it. */
+       if (dev->daisy >= 0) {
+               parport_daisy_deselect_all (port);
+               port->daisy = -1;
+       }
+#endif
+
+       write_lock_irqsave(&port->cad_lock, flags);
+       port->cad = NULL;
+       write_unlock_irqrestore(&port->cad_lock, flags);
+
+       /* Save control registers */
+       port->ops->save_state(port, dev->state);
+
+       /* If anybody is waiting, find out who's been there longest and
+          then wake them up. (Note: no locking required) */
+       for (pd = port->waithead; pd; pd = pd->waitnext) {
+               if (pd->waiting & 2) { /* sleeping in claim_or_block */
+                       parport_claim(pd);
+                       if (waitqueue_active(&pd->wait_q))
+                               wake_up(&pd->wait_q);
+                       return;
+               } else if (pd->wakeup) {
+                       pd->wakeup(pd->private);
+                       if (dev->port->cad)
+                               return;
+               } else {
+                       printk(KERN_ERR "%s: don't know how to wake %s\n", port->name, pd->name);
+               }
+       }
+
+       /* Nobody was waiting, so walk the list to see if anyone is
+          interested in being woken up.  */
+       for (pd = port->devices; (port->cad == NULL) && pd; pd = pd->next) {
+               if (pd->wakeup && pd != dev)
+                       pd->wakeup(pd->private);
+       }
+}
+
+static int parport_parse_params (int nports, const char *str[], int val[],
+                                int automatic, int none)
+{
+       unsigned int i;
+       for (i = 0; i < nports && str[i]; i++) {
+               if (!strncmp(str[i], "auto", 4))
+                       val[i] = automatic;
+               else if (!strncmp(str[i], "none", 4))
+                       val[i] = none;
+               else {
+                       char *ep;
+                       unsigned long r = simple_strtoul(str[i], &ep, 0);
+                       if (ep != str[i])
+                               val[i] = r;
+                       else {
+                               printk("parport: bad specifier `%s'\n", str[i]);
+                               return -1;
+                       }
+               }
+       }
+
+       return 0;
+}
+
+int parport_parse_irqs(int nports, const char *irqstr[], int irqval[])
+{
+       return parport_parse_params (nports, irqstr, irqval, PARPORT_IRQ_AUTO,
+                                    PARPORT_IRQ_NONE);
+}
+
+int parport_parse_dmas(int nports, const char *dmastr[], int dmaval[])
+{
+       return parport_parse_params (nports, dmastr, dmaval, PARPORT_DMA_AUTO,
+                                    PARPORT_DMA_NONE);
+}
index fcf20389d7745fec36f6fd041a33c33ca9e8dd4a..bc4ca74d6b6ccd0f659b2f3dc982b039315e5229 100644 (file)
@@ -743,10 +743,11 @@ static inline char * task_mem(struct task_struct *p, char *buffer)
        struct mm_struct * mm = p->mm;
 
        if (mm) {
-               struct vm_area_struct * vma = mm->mmap;
+               struct vm_area_struct * vma;
                unsigned long data = 0, stack = 0;
                unsigned long exec = 0, lib = 0;
 
+               down(&mm->mmap_sem);
                for (vma = mm->mmap; vma; vma = vma->vm_next) {
                        unsigned long len = (vma->vm_end - vma->vm_start) >> 10;
                        if (!vma->vm_file) {
@@ -763,7 +764,7 @@ static inline char * task_mem(struct task_struct *p, char *buffer)
                                        continue;
                                lib += len;
                        }
-               }       
+               }
                buffer += sprintf(buffer,
                        "VmSize:\t%8lu kB\n"
                        "VmLck:\t%8lu kB\n"
@@ -777,6 +778,7 @@ static inline char * task_mem(struct task_struct *p, char *buffer)
                        mm->rss << (PAGE_SHIFT-10),
                        data - stack, stack,
                        exec - lib, lib);
+               up(&mm->mmap_sem);
        }
        return buffer;
 }
index 6f5c63ec3359e88b81d8cdf645660111cdbee90c..6a856f29f9c9b02f2e6389da8b8eb51e499eb414 100644 (file)
@@ -104,15 +104,18 @@ static struct dentry * proc_follow_link(struct dentry *dentry,
                        struct vm_area_struct * vma;
                        if (!p->mm)
                                goto out_unlock;
+                       down(&p->mm->mmap_sem);
                        vma = p->mm->mmap;
                        while (vma) {
                                if ((vma->vm_flags & VM_EXECUTABLE) && 
                                    vma->vm_file) {
                                        result = vma->vm_file->f_dentry;
+                                       up(&p->mm->mmap_sem);
                                        goto out_dget;
                                }
                                vma = vma->vm_next;
                        }
+                       up(&p->mm->mmap_sem);
                        goto out_unlock;
                }
                default:
index 870fad7b2815e431f64fdeed4c9fb3c658262e9a..56c72335860d3160e6bce126ddbd864b4aaf4735 100644 (file)
  *                    potential and subtle race discovered by Ulrich Schmid
  *                    in down_interruptible(). Since I started to play here I
  *                    also implemented the `trylock' semaphore operation.
+ *          1999-07-02 Artur Skawina <skawina@geocities.com>
+ *                     Optimized "0(ecx)" -> "(ecx)" (the assembler does not
+ *                     do this). Changed calling sequences from push/jmp to
+ *                     traditional call/ret.
  *
  * If you would like to see an analysis of this implementation, please
  * ftp to gcom.com and download the file
@@ -112,12 +116,12 @@ extern inline void down(struct semaphore * sem)
 #ifdef __SMP__
                "lock ; "
 #endif
-               "decl 0(%0)\n\t"
+               "decl (%0)\n\t"     /* --sem->count */
                "js 2f\n"
                "1:\n"
                ".section .text.lock,\"ax\"\n"
-               "2:\tpushl $1b\n\t"
-               "jmp __down_failed\n"
+               "2:\tcall __down_failed\n\t"
+               "jmp 1b\n"
                ".previous"
                :/* no outputs */
                :"c" (sem)
@@ -137,13 +141,13 @@ extern inline int down_interruptible(struct semaphore * sem)
 #ifdef __SMP__
                "lock ; "
 #endif
-               "decl 0(%1)\n\t"
+               "decl (%1)\n\t"     /* --sem->count */
                "js 2f\n\t"
                "xorl %0,%0\n"
                "1:\n"
                ".section .text.lock,\"ax\"\n"
-               "2:\tpushl $1b\n\t"
-               "jmp __down_failed_interruptible\n"
+               "2:\tcall __down_failed_interruptible\n\t"
+               "jmp 1b\n"
                ".previous"
                :"=a" (result)
                :"c" (sem)
@@ -164,13 +168,13 @@ extern inline int down_trylock(struct semaphore * sem)
 #ifdef __SMP__
                "lock ; "
 #endif
-               "decl 0(%1)\n\t"
+               "decl (%1)\n\t"     /* --sem->count */
                "js 2f\n\t"
                "xorl %0,%0\n"
                "1:\n"
                ".section .text.lock,\"ax\"\n"
-               "2:\tpushl $1b\n\t"
-               "jmp __down_failed_trylock\n"
+               "2:\tcall __down_failed_trylock\n\t"
+               "jmp 1b\n"
                ".previous"
                :"=a" (result)
                :"c" (sem)
@@ -194,12 +198,12 @@ extern inline void up(struct semaphore * sem)
 #ifdef __SMP__
                "lock ; "
 #endif
-               "incl 0(%0)\n\t"
+               "incl (%0)\n\t"     /* ++sem->count */
                "jle 2f\n"
                "1:\n"
                ".section .text.lock,\"ax\"\n"
-               "2:\tpushl $1b\n\t"
-               "jmp __up_wakeup\n"
+               "2:\tcall __up_wakeup\n\t"
+               "jmp 1b\n"
                ".previous"
                :/* no outputs */
                :"c" (sem)
index 48959e3a88f08505af8618eb3435bc17bf7c6715..54904a2c879c686106201051300574b263f278c6 100644 (file)
@@ -156,7 +156,9 @@ int vsprintf(char *buf, const char *fmt, va_list args)
        int precision;          /* min. # of digits for integers; max
                                   number of chars for from string */
        int qualifier;          /* 'h', 'l', or 'L' for integer fields */
+                               /* 'z' support added 23/7/1999 S.H.    */
 
+       
        for (str=buf ; *fmt ; ++fmt) {
                if (*fmt != '%') {
                        *str++ = *fmt;
@@ -206,7 +208,7 @@ int vsprintf(char *buf, const char *fmt, va_list args)
 
                /* get the conversion qualifier */
                qualifier = -1;
-               if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') {
+               if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt =='z') {
                        qualifier = *fmt;
                        ++fmt;
                }
@@ -255,6 +257,9 @@ int vsprintf(char *buf, const char *fmt, va_list args)
                        if (qualifier == 'l') {
                                long * ip = va_arg(args, long *);
                                *ip = (str - buf);
+                       } else if (qualifier == 'z') {
+                               size_t * ip = va_arg(args, size_t *);
+                               *ip = (str - buf);
                        } else {
                                int * ip = va_arg(args, int *);
                                *ip = (str - buf);
@@ -292,6 +297,8 @@ int vsprintf(char *buf, const char *fmt, va_list args)
                }
                if (qualifier == 'l')
                        num = va_arg(args, unsigned long);
+               else if (qualifier == 'z')
+                       num = va_arg(args, size_t);
                else if (qualifier == 'h') {
                        num = (unsigned short) va_arg(args, int);
                        if (flags & SIGN)