]> git.neil.brown.name Git - history.git/commitdiff
Import 2.3.13 2.3.13
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:26:50 +0000 (15:26 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:26:50 +0000 (15:26 -0500)
226 files changed:
Documentation/Configure.help
Documentation/networking/multicast.txt
Documentation/sysrq.txt
MAINTAINERS
arch/i386/kernel/smp.c
arch/m68k/apollo/config.c
arch/m68k/apollo/dn_debug.c
arch/m68k/atari/joystick.c
arch/m68k/atari/stram.c
arch/m68k/bvme6000/config.c
arch/m68k/config.in
arch/m68k/kernel/entry.S
arch/m68k/kernel/m68k_defs.c
arch/m68k/kernel/m68k_ksyms.c
arch/m68k/kernel/process.c
arch/m68k/kernel/ptrace.c
arch/m68k/kernel/signal.c
arch/m68k/kernel/traps.c
arch/m68k/mac/adb-bus.c
arch/m68k/mm/fault.c
arch/m68k/mm/init.c
arch/m68k/mm/memory.c
arch/m68k/mvme147/config.c
arch/m68k/mvme16x/config.c
arch/m68k/q40/config.c
arch/m68k/vmlinux.lds
arch/ppc/kernel/apus_setup.c
arch/ppc/kernel/ppc_ksyms.c
arch/sparc/mm/srmmu.c
arch/sparc64/kernel/ioctl32.c
drivers/block/README.buddha [new file with mode: 0644]
drivers/block/acsi.c
drivers/block/acsi_slm.c
drivers/block/ataflop.c
drivers/block/ide-cd.c
drivers/block/ide-pci.c
drivers/block/ide-pmac.c
drivers/block/ide.c
drivers/block/linear.c
drivers/block/ll_rw_blk.c
drivers/block/md.c
drivers/block/ns87415.c
drivers/block/ps2esdi.c
drivers/block/q40ide.c [new file with mode: 0644]
drivers/block/rd.c
drivers/block/rz1000.c
drivers/block/trm290.c
drivers/block/xd.c
drivers/block/z2ram.c
drivers/cdrom/cdrom.c
drivers/char/amikeyb.c
drivers/char/cyclades.c
drivers/char/dn_keyb.c
drivers/char/dsp56k.c
drivers/char/isicom.c
drivers/char/istallion.c
drivers/char/lp.c
drivers/char/lp_intern.c
drivers/char/lp_m68k.c
drivers/char/macmouse.c [deleted file]
drivers/char/mem.c
drivers/char/misc.c
drivers/char/q40_keyb.c [new file with mode: 0644]
drivers/char/raw.c
drivers/macintosh/mac_keyb.c
drivers/macintosh/macserial.c
drivers/macintosh/nvram.c
drivers/net/Makefile
drivers/net/Space.c
drivers/net/ariadne2.c
drivers/net/atari_bionet.c
drivers/net/atari_pamsnet.c
drivers/net/eepro100.c
drivers/net/macsonic.c [new file with mode: 0644]
drivers/net/mvme147.c [new file with mode: 0644]
drivers/net/ptifddi.c
drivers/net/rrunner.c
drivers/net/sktr.c
drivers/net/sonic.h
drivers/net/sunhme.c
drivers/net/sunlance.c
drivers/parport/parport_amiga.c
drivers/parport/parport_atari.c
drivers/parport/parport_pc.c
drivers/pci/proc.c
drivers/scsi/53c7,8xx.c
drivers/scsi/53c7xx.c
drivers/scsi/AM53C974.c
drivers/scsi/NCR5380.c
drivers/scsi/NCR53c406a.c
drivers/scsi/README.st
drivers/scsi/eata.c
drivers/scsi/fdomain.c
drivers/scsi/g_NCR5380.c
drivers/scsi/gdth.c
drivers/scsi/hosts.c
drivers/scsi/ini9100u.c
drivers/scsi/inia100.c
drivers/scsi/megaraid.c
drivers/scsi/pas16.c
drivers/scsi/sr.c
drivers/scsi/st.c
drivers/scsi/st_options.h
drivers/scsi/t128.c
drivers/scsi/tmscsim.c
drivers/scsi/u14-34f.c
drivers/scsi/wd33c93.c
drivers/scsi/wd33c93.h
drivers/sound/Config.in
drivers/sound/Makefile
drivers/sound/esssolo1.c [new file with mode: 0644]
drivers/usb/Config.in
drivers/usb/Makefile
drivers/usb/audio.c
drivers/usb/hub.c
drivers/usb/uhci-debug.c
drivers/usb/uhci.c
drivers/usb/uhci.h
drivers/usb/usb.c
drivers/usb/usb.h
drivers/usb/uss720.c [new file with mode: 0644]
drivers/video/Config.in
drivers/video/Makefile
drivers/video/S3triofb.c
drivers/video/acornfb.c
drivers/video/amifb.c
drivers/video/atafb.c
drivers/video/aty.h
drivers/video/atyfb.c
drivers/video/cgfourteenfb.c
drivers/video/cgsixfb.c
drivers/video/cgthreefb.c
drivers/video/chipsfb.c
drivers/video/clgenfb.c
drivers/video/controlfb.c
drivers/video/creatorfb.c
drivers/video/cyber2000fb.c
drivers/video/cyberfb.c
drivers/video/cyberfb.h
drivers/video/dummycon.c
drivers/video/fbcon.c
drivers/video/fbmem.c
drivers/video/fm2fb.c
drivers/video/g364fb.c
drivers/video/hpfb.c
drivers/video/igafb.c
drivers/video/imsttfb.c
drivers/video/macfb.c
drivers/video/matroxfb.c
drivers/video/mdacon.c
drivers/video/offb.c
drivers/video/platinumfb.c
drivers/video/pm2fb.c
drivers/video/promcon.c
drivers/video/q40fb.c
drivers/video/retz3fb.c
drivers/video/sbusfb.c
drivers/video/sgivwfb.c
drivers/video/skeletonfb.c
drivers/video/tcxfb.c
drivers/video/valkyriefb.c
drivers/video/vesafb.c
drivers/video/vfb.c
drivers/video/vga16fb.c
drivers/video/vgacon.c
drivers/video/virgefb.c
fs/buffer.c
fs/fat/buffer.c
fs/fat/cache.c
fs/fat/cvf.c
fs/fat/dir.c
fs/fat/fatfs_syms.c
fs/fat/file.c
fs/fat/inode.c
fs/fat/misc.c
fs/minix/bitmap.c
fs/minix/namei.c
fs/minix/truncate.c
fs/msdos/namei.c
fs/ncpfs/dir.c
fs/ncpfs/inode.c
fs/umsdos/Makefile
fs/umsdos/check.c
fs/umsdos/dir.c
fs/umsdos/emd.c
fs/umsdos/file.c [deleted file]
fs/umsdos/inode.c
fs/umsdos/symlink.c
fs/vfat/namei.c
include/asm-m68k/cache.h
include/asm-m68k/hardirq.h
include/asm-m68k/irq.h
include/asm-m68k/mmu_context.h
include/asm-m68k/page.h
include/asm-m68k/pgtable.h
include/asm-m68k/processor.h
include/asm-m68k/resource.h
include/asm-m68k/semaphore.h
include/asm-m68k/softirq.h
include/asm-m68k/spinlock.h
include/asm-m68k/system.h
include/asm-m68k/unistd.h
include/asm-sparc64/ide.h
include/asm-sparc64/parport.h
include/linux/fat_cvf.h
include/linux/fb.h
include/linux/fs.h
include/linux/hfmodem.h [deleted file]
include/linux/minix_fs.h
include/linux/mm.h
include/linux/msdos_fs.h
include/linux/msdos_fs_i.h
include/linux/parport.h
include/linux/slab.h
include/linux/swap.h
include/linux/umsdos_fs.h
kernel/ksyms.c
kernel/resource.c
mm/filemap.c
mm/memory.c
mm/page_alloc.c
mm/page_io.c
mm/slab.c
mm/swap_state.c
mm/swapfile.c
mm/vmscan.c

index 667944cb0e284fdfd75a87fd4698258fa0544988..35fdb50311bb9ebfb4703646f7c1f3ae5d1ec432 100644 (file)
@@ -3538,6 +3538,13 @@ CONFIG_SCC_DELAY
 ### Don't know what's going on here.
 ###
 #
+YAM driver for AX.25
+CONFIG_YAM
+  Support for the YAM modem on serial port. If you want to compile this
+  as a module ( = code which can be inserted in and removed from the
+  running kernel whenever you want), say M here and read
+  Documentation/modules.txt.
+
 BAYCOM picpar and par96 driver for AX.25
 CONFIG_BAYCOM_PAR
   This is a driver for Baycom style simple amateur radio modems that
@@ -5345,26 +5352,6 @@ CONFIG_X25_ASY
   say M here and read Documentation/modules.txt. The module will be
   called x25_asy.o. If unsure, say N.
 
-Shortwave radio modem driver
-CONFIG_HFMODEM
-  This experimental driver is used by a package (to be released)
-  that implements the shortwave radio protocols RTTY, Sitor (Amtor),
-  Pactor 1 and GTOR using a standard PC sound card. If unsure,
-  say N.
-
-Shortwave radio modem driver support for Sound Blaster and compatible cards
-CONFIG_HFMODEM_SBC
-  This option enables the hfmodem driver to use Sound Blaster and
-  compatible cards. It requires a 16bit capable card, i.e.
-  SB16 or better, or ESS1688 or newer.
-
-Shortwave radio modem driver support for WSS and Crystal cards
-CONFIG_HFMODEM_WSS
-  This option enables the hfmodem driver to use WindowsSoundSystem
-  compatible cards. These cards feature a codec chip from either
-  Analog Devices (such as AD1848, AD1845) or Crystal Semiconductors
-  (such as CS4248, CS423x).
-
 PLIP (parallel port) support
 CONFIG_PLIP
   PLIP (Parallel Line Internet Protocol) is used to create a
@@ -9430,7 +9417,7 @@ CONFIG_RTC
 
   If you run Linux on a multiprocessor machine and said Y to
   "Symmetric Multi Processing" above, you should say Y here to read
-  and set the RTC clock in an SMP compatible fashion.
+  and set the RTC in an SMP compatible fashion.
 
   If you think you have a use for such a device (such as periodic data
   sampling), then say Y here, and read Documentation/rtc.txt for
@@ -11981,6 +11968,11 @@ CONFIG_USB_ACM
   mknod /dev/ttyACM2 c 166 2
   mknod /dev/ttyACM3 c 166 3
 
+USS720 parport driver
+CONFIG_USB_USS720
+  This driver is for USB parallel port adapters that use the USS-720
+  chip.
+
 USB /proc filesystem entry support (Preliminary)
 CONFIG_USB_PROC
   This reports USB drivers and devices in the /proc filesystem.
@@ -12140,7 +12132,7 @@ CONFIG_PPDEV
 # LocalWords:  KERNNAME kname ktype kernelname Kerneltype KERNTYPE Alt RX mdafb
 # LocalWords:  dataless kerneltype SYSNAME Comtrol Rocketport palmtop fbset EGS
 # LocalWords:  nvram SYSRQ SysRq PrintScreen sysrq NVRAMs NvRAM Shortwave RTTY
-# LocalWords:  HFMODEM shortwave Sitor Amtor Pactor GTOR hfmodem hayes TX TMOUT
+# LocalWords:  hayes TX TMOUT
 # LocalWords:  IDEPCI IDEDMA idedma PDC pdc TRM trm raidtools luthien nuclecu
 # LocalWords:  unam mx miguel koobera uic EMUL solaris pp ieee lpsg co DMAs TOS
 # LocalWords:  BLDCONFIG preloading jumperless BOOTINIT modutils multipath GRE
index 2bd6fd9ba7a7f4cbe8b6817fcafd1a3f75bb5b91..d426f36dbadc7716f86dd26f89c4eb41efd8938f 100644 (file)
@@ -1,11 +1,13 @@
-Behaviour of cards under Multicast. This is how they currently 
-behave not what the hardware can do - i.e. the lance driver doesn't
-use its filter, even though the code for loading it is in the DEC
-lance based driver.
+Behaviour of Cards Under Multicast
+==================================
 
-The following multicast requirements are needed
+This is how they currently behave, not what the hardware can do--for example,
+the Lance driver doesn't use its filter, even though the code for loading
+it is in the DEC Lance-based driver.
+
+The following are requirements for multicasting 
 -----------------------------------------------
-Appletalk      Multicast       hardware filtering not important but
+AppleTalk      Multicast       hardware filtering not important but
                                 avoid cards only doing promisc
 IP-Multicast   Multicast       hardware filters really help
 IP-MRoute      AllMulti        hardware filters are of no help
index 40bce4fd7ccf5ec72fc842165647a60271f008a1..ab8676fafe505af14e2427b38a793e63f2af2236 100644 (file)
@@ -9,8 +9,8 @@ regardless of whatever else it is doing, unless it is completely locked up.
 
 *  How do I enable the magic SysRQ key?
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-You need to say yes to 'Magic SysRq key (CONFIG_MAGIC_SYSRQ)' when
-configuring the kernel. This option is only available it 2.1.x or later
+You need to say "yes" to 'Magic SysRq key (CONFIG_MAGIC_SYSRQ)' when
+configuring the kernel. This option is only available in 2.1.x or later
 kernels.
 
 *  How do I use the magic SysRQ key?
index bec26c8da42c3be9fdcdc7d6516c430c61be70a3..7ab5c19b4bca7cb4829e6381921090acc2d7f371 100644 (file)
@@ -706,11 +706,6 @@ L: linux-scsi@vger.rutgers.edu
 W:     http://www.torque.net/sg
 S:     Maintained
 
-SCSI GENERIC
-L:     linux-scsi@vger.rutgers.edu
-M:     douglas.gilbert@rbcds.com
-S:     Maintained
-
 SCSI SUBSYSTEM
 L:     linux-scsi@vger.rutgers.edu
 S:     Unmaintained
index a13575425a4068f08d6877c7a5a8684df1b52029..968ecd69302f0409cff564c47e9096561cc4b081 100644 (file)
@@ -1244,6 +1244,7 @@ void __init smp_boot_cpus(void)
                io_apic_irqs = 0;
 #endif
                cpu_online_map = cpu_present_map;
+               smp_num_cpus = 1;
                goto smp_done;
        }
 
index 4c620f23ec69c58db9b3cb66f069b4e5fb8bb292..e3b54b40e40c4405c39c9bb2e87a94bff6b89c14 100644 (file)
@@ -1,4 +1,3 @@
-#include <stdarg.h>
 #include <linux/config.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
index cba26779a9eec18a88bd19c759aaca800cbfd258..734902fbfc17075f58e32466b30b22de32ccea58 100644 (file)
@@ -1,4 +1,3 @@
-#include <stdarg.h>
 
 #define DN_DEBUG_BUFFER_BASE 0x82800000
 #define DN_DEBUG_BUFFER_SIZE 8*1024*1024
index ba5dbcd98b8e5d53828dcec9056bab3856ea3ef7..e2cd384fd08c22c0a94cbc1e0093d92218d6d84e 100644 (file)
@@ -134,7 +134,8 @@ __initfunc(int atari_joystick_init(void))
 {
     joystick[0].active = joystick[1].active = 0;
     joystick[0].ready = joystick[1].ready = 0;
-    joystick[0].wait = joystick[1].wait = NULL;
+    init_waitqueue_head(&joystick[0].wait);
+    init_waitqueue_head(&joystick[1].wait);
 
     if (register_chrdev(MAJOR_NR, "Joystick", &atari_joystick_fops))
        printk("unable to get major %d for joystick devices\n", MAJOR_NR);
index f398f731050e387de4b065381c0dc71569265c60..eabc6bc9c90f86fec97065cb9b29e4cf8f23c363 100644 (file)
@@ -200,7 +200,7 @@ static struct swap_info_struct *stram_swap_info;
 static int stram_swap_type;
 
 /* Semaphore for get_stram_region.  */
-static struct semaphore stram_swap_sem = MUTEX;
+static DECLARE_MUTEX(stram_swap_sem);
 
 /* major and minor device number of the ST-RAM device; for the major, we use
  * the same as Amiga z2ram, which is really similar and impossible on Atari,
@@ -346,12 +346,11 @@ void __init atari_stram_reserve_pages(unsigned long start_mem)
                                 "swap=%08lx-%08lx\n", swap_start, swap_end );
                
                /* reserve some amount of memory for maintainance of
-                * swapping itself: 1 page for the lockmap, and one page
-                * for each 2048 (PAGE_SIZE/2) swap pages. (2 bytes for
-                * each page) */
+                * swapping itself: one page for each 2048 (PAGE_SIZE/2)
+                * swap pages. (2 bytes for each page) */
                swap_data = start_mem;
-               start_mem += (((SWAP_NR(swap_end) + PAGE_SIZE/2 - 1)
-                              >> (PAGE_SHIFT-1)) + 1) << PAGE_SHIFT;
+               start_mem += ((SWAP_NR(swap_end) + PAGE_SIZE/2 - 1)
+                             >> (PAGE_SHIFT-1)) << PAGE_SHIFT;
                /* correct swap_start if necessary */
                if (swap_start == swap_data)
                        swap_start = start_mem;
@@ -610,8 +609,7 @@ static int __init swap_init(unsigned long start_mem, unsigned long swap_data)
        p->flags        = SWP_USED;
        p->swap_file    = &fake_dentry[0];
        p->swap_device  = 0;
-       p->swap_lockmap = (unsigned char *)(swap_data);
-       p->swap_map     = (unsigned short *)(swap_data + PAGE_SIZE);
+       p->swap_map     = (unsigned short *)swap_data;
        p->cluster_nr   = 0;
        p->next         = -1;
        p->prio         = 0x7ff0;       /* a rather high priority, but not the higest
@@ -624,9 +622,6 @@ static int __init swap_init(unsigned long start_mem, unsigned long swap_data)
        stram_open( &swap_inode, MAGIC_FILE_P );
        p->max = SWAP_NR(swap_end);
 
-       /* initialize lockmap */
-       memset( p->swap_lockmap, 0, PAGE_SIZE );
-
        /* initialize swap_map: set regions that are already allocated or belong
         * to kernel data space to SWAP_MAP_BAD, otherwise to free */
        j = 0; /* # of free pages */
index fc1b5627f859fc461c034972c856a6b68ee42e52..ca522ea25ecc4c8bcb500025813ff973116d53a5 100644 (file)
@@ -14,7 +14,6 @@
  * for more details.
  */
 
-#include <stdarg.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
index a8dacc904c557bf33d097ea58b78f5dea43d5d4b..f1143d34f7f171cdaece77a4f6512f454dfcb11b 100644 (file)
@@ -100,7 +100,7 @@ fi
 bool '/proc/hardware support' CONFIG_PROC_HARDWARE
 
 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-  tristate 'Parallel port support (EXPERIMENTAL, disables old lp driver!)' CONFIG_PARPORT
+  tristate 'Parallel port support (EXPERIMENTAL)' CONFIG_PARPORT
   if [ "$CONFIG_PARPORT" != "n" ]; then
     if [ "$CONFIG_AMIGA" != "n" ]; then
       dep_tristate '   Amiga builtin port' CONFIG_PARPORT_AMIGA $CONFIG_PARPORT
@@ -118,6 +118,10 @@ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
   if [ "$CONFIG_ATARI" == "y" ]; then
     dep_tristate '    Atari builtin port' CONFIG_PARPORT_ATARI $CONFIG_PARPORT
   fi
+  dep_tristate 'Parallel printer support' CONFIG_PRINTER $CONFIG_PARPORT
+  if [ "$CONFIG_PRINTER" != "n" ]; then
+    bool '  Support IEEE1284 status readback' CONFIG_PRINTER_READBACK
+  fi
 fi
 
 
@@ -318,25 +322,23 @@ if [ "$CONFIG_ATARI" = "y" ]; then
   define_bool CONFIG_NVRAM y
 fi
 
-if [ "$CONFIG_PARPORT" = "n" ]; then
-  tristate 'Parallel printer support' CONFIG_M68K_PRINTER
-  if [ "$CONFIG_ZORRO" = "y" ]; then
-    dep_tristate 'Multiface Card III parallel support' CONFIG_MULTIFACE_III_LP $CONFIG_M68K_PRINTER
-  fi
-else
-  dep_tristate 'Parallel printer support' CONFIG_PRINTER $CONFIG_PARPORT
-  if [ "$CONFIG_PRINTER" != "n" ]; then
-    bool '  Support IEEE1284 status readback' CONFIG_PRINTER_READBACK
-  fi
-fi   
 if [ "$CONFIG_AMIGA" = "y" ]; then
   tristate 'Amiga mouse support' CONFIG_AMIGAMOUSE
+  if [ "$CONFIG_AMIGAMOUSE" != "n" ]; then
+    define_bool CONFIG_MOUSE y
+  fi
 fi
 if [ "$CONFIG_ATARI" = "y" ]; then
   tristate 'Atari mouse support' CONFIG_ATARIMOUSE
+  if [ "$CONFIG_ATARIMOUSE" != "n" ]; then
+    define_bool CONFIG_MOUSE y
+  fi
 fi
 if [ "$CONFIG_MAC" = "y" ]; then
    bool 'Mac ADB mouse support' CONFIG_ADBMOUSE
+  if [ "$CONFIG_ADBMOUSE" != "n" ]; then
+    define_bool CONFIG_MOUSE y
+  fi
 fi
 if [ "$CONFIG_ATARI" = "y" ]; then
   tristate 'Atari MFP serial support' CONFIG_ATARI_MFPSER
@@ -374,6 +376,9 @@ if [ "$CONFIG_SUN3X" = "y" ]; then
   if [ "$CONFIG_SUN3X_ZS" = "y" ]; then
     bool 'Sun keyboard support' CONFIG_SUN_KEYBOARD
     bool 'Sun mouse support' CONFIG_SUN_MOUSE
+    if [ "$CONFIG_SUN_MOUSE" != "n" ]; then
+      define_bool CONFIG_MOUSE y
+    fi
     define_bool CONFIG_SBUS y
     define_bool CONFIG_SBUSCHAR y
     define_bool CONFIG_SUN_SERIAL y
index 61482c3a86544021e6d45d10b69d99c607be934b..2bdab4be75e816aa3105f42914c5aaa380a88450 100644 (file)
@@ -67,7 +67,7 @@ ENTRY(trap)
 
 ENTRY(reschedule)
        | save top of frame
-       movel   %sp,%curptr@(TASK_TSS+TSS_ESP0)
+       movel   %sp,%curptr@(TASK_THREAD+THREAD_ESP0)
 
        pea     SYMBOL_NAME(ret_from_exception)
        jmp     SYMBOL_NAME(schedule)
@@ -89,6 +89,16 @@ do_trace:
        SAVE_SWITCH_STACK
        jbsr    SYMBOL_NAME(syscall_trace)
 
+       | After a fork we jump here directly from resume,
+       | so that %d1 contains the previous task
+       | Theoretically only needed on SMP, but let's watch
+       | what happens in schedule_tail() in future...
+ENTRY(ret_from_fork)
+       movel   %d1,%sp@-
+       jsr     SYMBOL_NAME(schedule_tail)
+       addql   #4,%sp
+       jra     SYMBOL_NAME(ret_from_exception)
+
 SYMBOL_NAME_LABEL(ret_from_signal)
        RESTORE_SWITCH_STACK
        addql   #4,%sp
@@ -100,7 +110,7 @@ ENTRY(system_call)
 
        GET_CURRENT(%d0)
        | save top of frame
-       movel   %sp,%curptr@(TASK_TSS+TSS_ESP0)
+       movel   %sp,%curptr@(TASK_THREAD+THREAD_ESP0)
 
        cmpl    #NR_syscalls,%d2
        jcc     badsys
@@ -118,8 +128,10 @@ SYMBOL_NAME_LABEL(ret_from_exception)
        andw    #ALLOWINT,%sr
        tstl    %curptr@(TASK_NEEDRESCHED)
        jne     SYMBOL_NAME(reschedule)
+#if 0
        cmpl    #SYMBOL_NAME(task),%curptr      | task[0] cannot have signals
        jeq     2f
+#endif
                                        | check for delayed trace
        bclr    #PF_DTRACE_BIT,%curptr@(TASK_FLAGS+PF_DTRACE_OFF)
        jne     do_delayed_trace
@@ -265,25 +277,25 @@ SYMBOL_NAME_LABEL(resume)
         */
 
        /* save sr */
-       movew   %sr,%a0@(TASK_TSS+TSS_SR)
+       movew   %sr,%a0@(TASK_THREAD+THREAD_SR)
 
        /* save fs (sfc,%dfc) (may be pointing to kernel memory) */
        movec   %sfc,%d0
-       movew   %d0,%a0@(TASK_TSS+TSS_FS)
+       movew   %d0,%a0@(TASK_THREAD+THREAD_FS)
 
        /* save usp */
        /* it is better to use a movel here instead of a movew 8*) */
        movec   %usp,%d0
-       movel   %d0,%a0@(TASK_TSS+TSS_USP)
+       movel   %d0,%a0@(TASK_THREAD+THREAD_USP)
 
        /* save non-scratch registers on stack */
        SAVE_SWITCH_STACK
 
        /* save current kernel stack pointer */
-       movel   %sp,%a0@(TASK_TSS+TSS_KSP)
+       movel   %sp,%a0@(TASK_THREAD+THREAD_KSP)
 
        /* save floating point context */
-       fsave   %a0@(TASK_TSS+TSS_FPSTATE)
+       fsave   %a0@(TASK_THREAD+THREAD_FPSTATE)
 
 #if defined(CONFIG_M68060)
 #if !defined(CPU_M68060_ONLY)
@@ -291,18 +303,18 @@ SYMBOL_NAME_LABEL(resume)
        beqs    1f
 #endif
        /* The 060 FPU keeps status in bits 15-8 of the first longword */
-       tstb    %a0@(TASK_TSS+TSS_FPSTATE+2)
+       tstb    %a0@(TASK_THREAD+THREAD_FPSTATE+2)
        jeq     3f
 #if !defined(CPU_M68060_ONLY)
        jra     2f
 #endif
 #endif /* CONFIG_M68060 */
 #if !defined(CPU_M68060_ONLY)
-1:     tstb    %a0@(TASK_TSS+TSS_FPSTATE)
+1:     tstb    %a0@(TASK_THREAD+THREAD_FPSTATE)
        jeq     3f
 #endif
-2:     fmovemx %fp0-%fp7,%a0@(TASK_TSS+TSS_FPREG)
-       fmoveml %fpcr/%fpsr/%fpiar,%a0@(TASK_TSS+TSS_FPCNTL)
+2:     fmovemx %fp0-%fp7,%a0@(TASK_THREAD+THREAD_FPREG)
+       fmoveml %fpcr/%fpsr/%fpiar,%a0@(TASK_THREAD+THREAD_FPCNTL)
 3:
        /* Return previous task in %d1 */
        movel   %curptr,%d1
@@ -310,69 +322,6 @@ SYMBOL_NAME_LABEL(resume)
        /* switch to new task (a1 contains new task) */
        movel   %a1,%curptr
 
-       /* Skip address space switching if they are the same. */
-       movel   %a0@(TASK_MM),%d0
-       cmpl    %a1@(TASK_MM),%d0
-       jeq     4f
-
-#if defined(CPU_M68020_OR_M68030) && defined(CPU_M68040_OR_M68060)
-       /* 68040 or 68060 ? */
-       tstl    SYMBOL_NAME(m68k_is040or060)
-       bnes    1f
-#endif
-#if defined(CPU_M68020_OR_M68030)
-       /*
-        * switch address space
-        */
-
-       /* flush MC68030/MC68020 caches (they are virtually addressed) */
-       movec   %cacr,%d0
-       oriw    #LFLUSH_I_AND_D,%d0
-       movec   %d0,%cacr
-
-       /* switch the root pointer */
-#ifdef CPU_M68030_ONLY
-       .chip   68030
-       pmovefd %a1@(TASK_TSS+TSS_CRP),%crp
-       .chip   68k
-       pflush  #0,#4
-#else
-       pmove   %a1@(TASK_TSS+TSS_CRP),%crp
-#endif
-#endif
-
-#if defined(CPU_M68020_OR_M68030) && defined(CPU_M68040_OR_M68060)
-       jra     2f      /* skip m68040 stuff */
-1:
-#endif
-#if defined(CPU_M68040_OR_M68060)
-       /*
-        * switch address space
-        */
-       .chip   68040
-
-       /* flush address translation cache (user entries) */
-       pflushan
-
-       /* switch the root pointer */
-       movel   %a1@(TASK_TSS+TSS_CRP+4),%d0
-       movec   %d0,%urp
-
-#if defined (CONFIG_M68060)
-       /* is it a '060 ? */
-#if !defined(CPU_M68060_ONLY)
-       btst    #3,SYMBOL_NAME(m68k_cputype)+3
-       beqs    2f
-#endif
-       /* clear user entries in the branch cache */
-       movec   %cacr,%d0
-       orl     #0x00200000,%d0
-       movec   %d0,%cacr
-#endif /* CONFIG_M68060 */
-       .chip   68k
-#endif /* CPU_M68040_OR_M68060 */
-2:
-4:
        /* restore floating point context */
 
 #if defined(CONFIG_M68060)
@@ -381,37 +330,37 @@ SYMBOL_NAME_LABEL(resume)
        beqs    1f
 #endif
        /* The 060 FPU keeps status in bits 15-8 of the first longword */
-       tstb    %a1@(TASK_TSS+TSS_FPSTATE+2)
+       tstb    %a1@(TASK_THREAD+THREAD_FPSTATE+2)
        jeq     3f
 #if !defined(CPU_M68060_ONLY)
        jra     2f
 #endif
 #endif /* CONFIG_M68060 */
 #if !defined(CPU_M68060_ONLY)
-1:     tstb    %a1@(TASK_TSS+TSS_FPSTATE)
+1:     tstb    %a1@(TASK_THREAD+THREAD_FPSTATE)
        jeq     3f
 #endif 
-2:     fmovemx %a1@(TASK_TSS+TSS_FPREG),%fp0-%fp7
-       fmoveml %a1@(TASK_TSS+TSS_FPCNTL),%fpcr/%fpsr/%fpiar
-3:     frestore %a1@(TASK_TSS+TSS_FPSTATE)
+2:     fmovemx %a1@(TASK_THREAD+THREAD_FPREG),%fp0-%fp7
+       fmoveml %a1@(TASK_THREAD+THREAD_FPCNTL),%fpcr/%fpsr/%fpiar
+3:     frestore %a1@(TASK_THREAD+THREAD_FPSTATE)
 
        /* restore the kernel stack pointer */
-       movel   %a1@(TASK_TSS+TSS_KSP),%sp
+       movel   %a1@(TASK_THREAD+THREAD_KSP),%sp
 
        /* restore non-scratch registers */
        RESTORE_SWITCH_STACK
 
        /* restore user stack pointer */
-       movel   %a1@(TASK_TSS+TSS_USP),%a0
+       movel   %a1@(TASK_THREAD+THREAD_USP),%a0
        movel   %a0,%usp
 
        /* restore fs (sfc,%dfc) */
-       movew   %a1@(TASK_TSS+TSS_FS),%a0
+       movew   %a1@(TASK_THREAD+THREAD_FS),%a0
        movec   %a0,%sfc
        movec   %a0,%dfc
 
        /* restore status register */
-       movew   %a1@(TASK_TSS+TSS_SR),%sr
+       movew   %a1@(TASK_THREAD+THREAD_SR),%sr
 
        rts
 
@@ -530,7 +479,7 @@ SYMBOL_NAME_LABEL(sys_call_table)
        .long SYMBOL_NAME(sys_ni_syscall)
        .long SYMBOL_NAME(sys_ni_syscall)       /* iopl for i386 */ /* 110 */
        .long SYMBOL_NAME(sys_vhangup)
-       .long SYMBOL_NAME(sys_idle)
+       .long SYMBOL_NAME(sys_ni_syscall)       /* obsolete idle() syscall */
        .long SYMBOL_NAME(sys_ni_syscall)       /* vm86old for i386 */
        .long SYMBOL_NAME(sys_wait4)
        .long SYMBOL_NAME(sys_swapoff)          /* 115 */
index e2e6715e7ad7bd2d58c1d558c9ada863be889c67..47cffcfa91979dbdfe1365b72428cfc441304129 100644 (file)
@@ -26,25 +26,34 @@ int main(void)
        DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags));
        DEFINE(TASK_SIGPENDING, offsetof(struct task_struct, sigpending));
        DEFINE(TASK_NEEDRESCHED, offsetof(struct task_struct, need_resched));
-       DEFINE(TASK_TSS, offsetof(struct task_struct, tss));
+       DEFINE(TASK_THREAD, offsetof(struct task_struct, thread));
        DEFINE(TASK_MM, offsetof(struct task_struct, mm));
+       DEFINE(TASK_ACTIVE_MM, offsetof(struct task_struct, active_mm));
 
        /* offsets into the thread struct */
-       DEFINE(TSS_KSP, offsetof(struct thread_struct, ksp));
-       DEFINE(TSS_USP, offsetof(struct thread_struct, usp));
-       DEFINE(TSS_SR, offsetof(struct thread_struct, sr));
-       DEFINE(TSS_FS, offsetof(struct thread_struct, fs));
-       DEFINE(TSS_CRP, offsetof(struct thread_struct, crp));
-       DEFINE(TSS_ESP0, offsetof(struct thread_struct, esp0));
-       DEFINE(TSS_FPREG, offsetof(struct thread_struct, fp));
-       DEFINE(TSS_FPCNTL, offsetof(struct thread_struct, fpcntl));
-       DEFINE(TSS_FPSTATE, offsetof(struct thread_struct, fpstate));
+       DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp));
+       DEFINE(THREAD_USP, offsetof(struct thread_struct, usp));
+       DEFINE(THREAD_SR, offsetof(struct thread_struct, sr));
+       DEFINE(THREAD_FS, offsetof(struct thread_struct, fs));
+       DEFINE(THREAD_CRP, offsetof(struct thread_struct, crp));
+       DEFINE(THREAD_ESP0, offsetof(struct thread_struct, esp0));
+       DEFINE(THREAD_FPREG, offsetof(struct thread_struct, fp));
+       DEFINE(THREAD_FPCNTL, offsetof(struct thread_struct, fpcntl));
+       DEFINE(THREAD_FPSTATE, offsetof(struct thread_struct, fpstate));
 
        /* offsets into the pt_regs */
        DEFINE(PT_D0, offsetof(struct pt_regs, d0));
        DEFINE(PT_ORIG_D0, offsetof(struct pt_regs, orig_d0));
+       DEFINE(PT_D1, offsetof(struct pt_regs, d1));
+       DEFINE(PT_D2, offsetof(struct pt_regs, d2));
+       DEFINE(PT_D3, offsetof(struct pt_regs, d3));
+       DEFINE(PT_D4, offsetof(struct pt_regs, d4));
+       DEFINE(PT_D5, offsetof(struct pt_regs, d5));
+       DEFINE(PT_A0, offsetof(struct pt_regs, a0));
+       DEFINE(PT_A1, offsetof(struct pt_regs, a1));
+       DEFINE(PT_A2, offsetof(struct pt_regs, a2));
+       DEFINE(PT_PC, offsetof(struct pt_regs, pc));
        DEFINE(PT_SR, offsetof(struct pt_regs, sr));
-
        /* bitfields are a bit difficult */
        DEFINE(PT_VECTOR, offsetof(struct pt_regs, pc) + 4);
 
@@ -69,6 +78,12 @@ int main(void)
        DEFINE(FBCON_FONT_DESC_DATA, offsetof(struct fbcon_font_desc, data));
        DEFINE(FBCON_FONT_DESC_PREF, offsetof(struct fbcon_font_desc, pref));
 
+       /* signal defines */
+       DEFINE(SIGSEGV, SIGSEGV);
+       DEFINE(SEGV_MAPERR, SEGV_MAPERR);
+       DEFINE(SIGTRAP, SIGTRAP);
+       DEFINE(TRAP_TRACE, TRAP_TRACE);
+
        /* offsets into the custom struct */
        DEFINE(CUSTOMBASE, &custom);
        DEFINE(C_INTENAR, offsetof(struct CUSTOM, intenar));
index 5aae5953cc7dd0f0d78e7cf31699e8fdce07c16a..14ae0a266192a2faf2b59e21634a186c5931b719 100644 (file)
@@ -55,8 +55,6 @@ EXPORT_SYMBOL(enable_irq);
 EXPORT_SYMBOL(disable_irq);
 EXPORT_SYMBOL(kernel_set_cachemode);
 EXPORT_SYMBOL(kernel_thread);
-EXPORT_SYMBOL(register_serial);
-EXPORT_SYMBOL(unregister_serial);
 
 /* Networking helper routines. */
 EXPORT_SYMBOL(csum_partial_copy);
index a57def1937d74219c706365f79d7e2d3ea2633ff..ff4819b9aa3705eb05276db68679d496879668c6 100644 (file)
@@ -45,35 +45,47 @@ static struct signal_struct init_signals = INIT_SIGNALS;
 struct mm_struct init_mm = INIT_MM(init_mm);
 
 union task_union init_task_union
-       __attribute__((section("init_task"), aligned(2*PAGE_SIZE)))
-       = { task: INIT_TASK };
+__attribute__((section("init_task"), aligned(THREAD_SIZE)))
+       = { task: INIT_TASK(init_task_union.task) };
+
+asmlinkage void ret_from_fork(void);
 
-asmlinkage void ret_from_exception(void);
 
 /*
  * The idle loop on an m68k..
  */
-asmlinkage int sys_idle(void)
+static void default_idle(void)
 {
-       if (current->pid != 0)
-               return -EPERM;
-
-       /* endless idle loop with no priority at all */
-       current->priority = 0;
-       current->counter = -100;
-       for (;;) {
+       while(1) {
                if (!current->need_resched)
-#if defined(CONFIG_ATARI) && !defined(CONFIG_AMIGA) && !defined(CONFIG_MAC)
+#ifdef MACH_ATARI_ONLY
                        /* block out HSYNC on the atari (falcon) */
                        __asm__("stop #0x2200" : : : "cc");
-#else /* portable version */
+#else
                        __asm__("stop #0x2000" : : : "cc");
-#endif /* machine compilation types */ 
+#endif
                schedule();
                check_pgt_cache();
        }
 }
 
+void (*idle)(void) = default_idle;
+
+/*
+ * The idle thread. There's no useful work to be
+ * done, so just try to conserve power and have a
+ * low exit latency (ie sit in a loop waiting for
+ * somebody to say that they'd like to reschedule)
+ */
+void cpu_idle(void)
+{
+       /* endless idle loop with no priority at all */
+       init_idle();
+       current->priority = 0;
+       current->counter = -100;
+       idle();
+}
+
 void machine_restart(char * __unused)
 {
        if (mach_reset)
@@ -148,7 +160,7 @@ void flush_thread(void)
 {
        unsigned long zero = 0;
        set_fs(USER_DS);
-       current->tss.fs = __USER_DS;
+       current->thread.fs = __USER_DS;
        asm volatile (".chip 68k/68881\n\t"
                      "frestore %0@\n\t"
                      ".chip 68k" : : "a" (&zero));
@@ -191,7 +203,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
        struct switch_stack * childstack, *stack;
        unsigned long stack_offset, *retp;
 
-       stack_offset = 2*PAGE_SIZE - sizeof(struct pt_regs);
+       stack_offset = THREAD_SIZE - sizeof(struct pt_regs);
        childregs = (struct pt_regs *) ((unsigned long) p + stack_offset);
 
        *childregs = *regs;
@@ -202,26 +214,26 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
 
        childstack = ((struct switch_stack *) childregs) - 1;
        *childstack = *stack;
-       childstack->retpc = (unsigned long) ret_from_exception;
+       childstack->retpc = (unsigned long)ret_from_fork;
 
-       p->tss.usp = usp;
-       p->tss.ksp = (unsigned long)childstack;
+       p->thread.usp = usp;
+       p->thread.ksp = (unsigned long)childstack;
        /*
         * Must save the current SFC/DFC value, NOT the value when
         * the parent was last descheduled - RGH  10-08-96
         */
-       p->tss.fs = get_fs().seg;
+       p->thread.fs = get_fs().seg;
 
        /* Copy the current fpu state */
-       asm volatile ("fsave %0" : : "m" (p->tss.fpstate[0]) : "memory");
+       asm volatile ("fsave %0" : : "m" (p->thread.fpstate[0]) : "memory");
 
-       if (!CPU_IS_060 ? p->tss.fpstate[0] : p->tss.fpstate[2])
+       if (!CPU_IS_060 ? p->thread.fpstate[0] : p->thread.fpstate[2])
          asm volatile ("fmovemx %/fp0-%/fp7,%0\n\t"
                        "fmoveml %/fpiar/%/fpcr/%/fpsr,%1"
-                       : : "m" (p->tss.fp[0]), "m" (p->tss.fpcntl[0])
+                       : : "m" (p->thread.fp[0]), "m" (p->thread.fpcntl[0])
                        : "memory");
        /* Restore the state in case the fpu was busy */
-       asm volatile ("frestore %0" : : "m" (p->tss.fpstate[0]));
+       asm volatile ("frestore %0" : : "m" (p->thread.fpstate[0]));
 
        return 0;
 }
@@ -230,7 +242,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
 
 int dump_fpu (struct pt_regs *regs, struct user_m68kfp_struct *fpu)
 {
-  char fpustate[216];
+       char fpustate[216];
 
   /* First dump the fpu context to avoid protocol violation.  */
   asm volatile ("fsave %0" :: "m" (fpustate[0]) : "memory");
index 86e225362d89c6f66f59431d9bedf0d175ba6da8..9d72d90b5264d2b4ca910197fc812718ba9c8c2c 100644 (file)
@@ -37,7 +37,7 @@
 /* sets the trace bits. */
 #define TRACE_BITS 0x8000
 
-/* Find the stack offset for a register, relative to tss.esp0. */
+/* Find the stack offset for a register, relative to thread.esp0. */
 #define PT_REG(reg)    ((long)&((struct pt_regs *)0)->reg)
 #define SW_REG(reg)    ((long)&((struct switch_stack *)0)->reg \
                         - sizeof(struct switch_stack))
@@ -60,9 +60,9 @@ static inline long get_reg(struct task_struct *task, int regno)
        unsigned long *addr;
 
        if (regno == PT_USP)
-               addr = &task->tss.usp;
+               addr = &task->thread.usp;
        else if (regno < sizeof(regoff)/sizeof(regoff[0]))
-               addr = (unsigned long *)(task->tss.esp0 + regoff[regno]);
+               addr = (unsigned long *)(task->thread.esp0 + regoff[regno]);
        else
                return 0;
        return *addr;
@@ -77,9 +77,9 @@ static inline int put_reg(struct task_struct *task, int regno,
        unsigned long *addr;
 
        if (regno == PT_USP)
-               addr = &task->tss.usp;
+               addr = &task->thread.usp;
        else if (regno < sizeof(regoff)/sizeof(regoff[0]))
-               addr = (unsigned long *) (task->tss.esp0 + regoff[regno]);
+               addr = (unsigned long *) (task->thread.esp0 + regoff[regno]);
        else
                return -1;
        *addr = data;
@@ -386,7 +386,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                                        tmp >>= 16;
                        }
                        else if (addr >= 21 && addr < 49)
-                               tmp = child->tss.fp[addr - 21];
+                               tmp = child->thread.fp[addr - 21];
                        else
                                goto out;
                        ret = put_user(tmp,(unsigned long *) data);
@@ -423,7 +423,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                        }
                        if (addr >= 21 && addr < 48)
                        {
-                               child->tss.fp[addr - 21] = data;
+                               child->thread.fp[addr - 21] = data;
                                ret = 0;
                        }
                        goto out;
@@ -544,7 +544,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
 
                case PTRACE_GETFPREGS: { /* Get the child FPU state. */
                        ret = 0;
-                       if (copy_to_user((void *)data, &child->tss.fp,
+                       if (copy_to_user((void *)data, &child->thread.fp,
                                         sizeof(struct user_m68kfp_struct)))
                                ret = -EFAULT;
                        goto out;
@@ -552,7 +552,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
 
                case PTRACE_SETFPREGS: { /* Set the child FPU state. */
                        ret = 0;
-                       if (copy_from_user(&child->tss.fp, (void *)data,
+                       if (copy_from_user(&child->thread.fp, (void *)data,
                                           sizeof(struct user_m68kfp_struct)))
                                ret = -EFAULT;
                        goto out;
index dfb6d50fd9da3c443795813a2350516e54f7923c..d6302cb28c73c08e6a3461354542cd15e61b3700 100644 (file)
@@ -156,6 +156,9 @@ sys_sigaltstack(const stack_t *uss, stack_t *uoss)
 
 /*
  * Do a signal return; undo the signal stack.
+ *
+ * Keep the return code on the stack quadword aligned!
+ * That makes the cache flush below easier.
  */
 
 struct sigframe
@@ -175,9 +178,9 @@ struct rt_sigframe
        int sig;
        struct siginfo *pinfo;
        void *puc;
+       char retcode[8];
        struct siginfo info;
        struct ucontext uc;
-       char retcode[8];
 };
 
 
@@ -478,7 +481,7 @@ asmlinkage int do_sigreturn(unsigned long __unused)
        struct switch_stack *sw = (struct switch_stack *) &__unused;
        struct pt_regs *regs = (struct pt_regs *) (sw + 1);
        unsigned long usp = rdusp();
-       struct sigframe *frame = (struct sigframe *)(usp - 24);
+       struct sigframe *frame = (struct sigframe *)(usp - 4);
        sigset_t set;
        int d0;
 
@@ -677,25 +680,6 @@ static inline void push_cache (unsigned long vaddr)
                                      "cpushl %%bc,(%0)\n\t"
                                      ".chip 68k"
                                      : : "a" (temp));
-               if (((vaddr + 8) ^ vaddr) & ~15) {
-                       if (((vaddr + 8) ^ vaddr) & PAGE_MASK)
-                               __asm__ __volatile__ (".chip 68040\n\t"
-                                                     "nop\n\t"
-                                                     "ptestr (%1)\n\t"
-                                                     "movec %%mmusr,%0\n\t"
-                                                     ".chip 68k"
-                                                     : "=r" (temp)
-                                                     : "a" (vaddr + 8));
-
-                       temp &= PAGE_MASK;
-                       temp |= (vaddr + 8) & ~PAGE_MASK;
-
-                       __asm__ __volatile__ (".chip 68040\n\t"
-                                             "nop\n\t"
-                                             "cpushl %%bc,(%0)\n\t"
-                                             ".chip 68k"
-                                             : : "a" (temp));
-               }
        }
        else if (CPU_IS_060) {
                unsigned long temp;
@@ -708,18 +692,6 @@ static inline void push_cache (unsigned long vaddr)
                                      "cpushl %%bc,(%0)\n\t"
                                      ".chip 68k"
                                      : : "a" (temp));
-               if (((vaddr + 8) ^ vaddr) & ~15) {
-                       if (((vaddr + 8) ^ vaddr) & PAGE_MASK)
-                               __asm__ __volatile__ (".chip 68060\n\t"
-                                                     "plpar (%0)\n\t"
-                                                     ".chip 68k"
-                                                     : "=a" (temp)
-                                                     : "0" (vaddr + 8));
-                       __asm__ __volatile__ (".chip 68060\n\t"
-                                             "cpushl %%bc,(%0)\n\t"
-                                             ".chip 68k"
-                                             : : "a" (temp));
-               }
        }
        else {
                /*
@@ -797,11 +769,9 @@ static void setup_frame (int sig, struct k_sigaction *ka,
 
        /* Set up to return from userspace.  */
        err |= __put_user(frame->retcode, &frame->pretcode);
-       /* addaw #20,sp */
-       err |= __put_user(0xdefc0014, (long *)(frame->retcode + 0));
        /* moveq #,d0; trap #0 */
        err |= __put_user(0x70004e40 + (__NR_sigreturn << 16),
-                         (long *)(frame->retcode + 4));
+                         (long *)(frame->retcode));
 
        if (err)
                goto give_sigsegv;
@@ -881,10 +851,10 @@ static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
 
        /* Set up to return from userspace.  */
        err |= __put_user(frame->retcode, &frame->pretcode);
-       /* movel #,d0; trap #0 */
-       err |= __put_user(0x203c, (short *)(frame->retcode + 0));
-       err |= __put_user(__NR_rt_sigreturn, (long *)(frame->retcode + 2));
-       err |= __put_user(0x4e40, (short *)(frame->retcode + 6));
+       /* moveq #,d0; notb d0; trap #0 */
+       err |= __put_user(0x70004600 + ((__NR_rt_sigreturn ^ 0xff) << 16),
+                         (long *)(frame->retcode + 0));
+       err |= __put_user(0x4e40, (short *)(frame->retcode + 4));
 
        if (err)
                goto give_sigsegv;
@@ -964,11 +934,10 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
        if (ka->sa.sa_flags & SA_ONESHOT)
                ka->sa.sa_handler = SIG_DFL;
 
-       if (!(ka->sa.sa_flags & SA_NODEFER)) {
-               sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+       sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+       if (!(ka->sa.sa_flags & SA_NODEFER))
                sigaddset(&current->blocked,sig);
-               recalc_sigpending(current);
-       }
+       recalc_sigpending(current);
 }
 
 /*
@@ -985,7 +954,7 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
        siginfo_t info;
        struct k_sigaction *ka;
 
-       current->tss.esp0 = (unsigned long) regs;
+       current->thread.esp0 = (unsigned long) regs;
 
        if (!oldset)
                oldset = &current->blocked;
@@ -1090,6 +1059,7 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
 
                        default:
                                sigaddset(&current->signal, signr);
+                               recalc_sigpending(current);
                                current->flags |= PF_SIGNALED;
                                do_exit(exit_code);
                                /* NOTREACHED */
index 1f07014b2260e8d22710db2027df29dc90027a2c..f895ad5e73d2543eec35f003d6ea563d1bcf70e5 100644 (file)
@@ -648,7 +648,7 @@ asmlinkage void buserr_c(struct frame *fp)
 {
        /* Only set esp0 if coming from user mode */
        if (user_mode(&fp->ptregs))
-               current->tss.esp0 = (unsigned long) fp;
+               current->thread.esp0 = (unsigned long) fp;
 
 #if DEBUG
        printk ("*** Bus Error *** Format is %x\n", fp->ptregs.format);
index 5f0f792aa94d8be05b6e90ae92f2fa68fc5a6482..9f630a1bcc7fddc9421f5199185ed708012103c5 100644 (file)
@@ -13,7 +13,6 @@
  *     MSch (1/98) Integrated start of IIsi driver by Robert Thompson
  */
  
-#include <stdarg.h>
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/miscdevice.h>
index 7ae87b23f5f8b453a100ca78e739f80d280732e0..c66db065246b389f5e6db62cf737eca6228877c1 100644 (file)
@@ -36,7 +36,7 @@ asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
        struct mm_struct *mm = current->mm;
        struct vm_area_struct * vma;
        unsigned long fixup;
-       int write;
+       int write, fault;
 
 #ifdef DEBUG
        printk ("regs->sr=%#x, regs->pc=%#lx, address=%#lx, %ld, %p\n",
@@ -44,7 +44,6 @@ asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
                current->mm->pgd);
 #endif
 
-
        /*
         * If we're in an interrupt or have no user
         * context, we must not take the fault..
@@ -100,7 +99,10 @@ good_area:
         * make sure we exit gracefully rather than endlessly redo
         * the fault.
         */
-       if (!handle_mm_fault(current, vma, address, write))
+       fault = handle_mm_fault(current, vma, address, write);
+       if (fault < 0)
+               goto out_of_memory;
+       if (!fault)
                goto do_sigbus;
 
        /* There seems to be a missing invalidate somewhere in do_no_page.
@@ -160,6 +162,13 @@ no_context:
  * We ran out of memory, or some other thing happened to us that made
  * us unable to handle the page fault gracefully.
  */
+out_of_memory:
+       up(&mm->mmap_sem);
+       printk("VM: killing process %s\n", current->comm);
+       if (error_code & 4)
+               do_exit(SIGKILL);
+       goto no_context;
+
 do_sigbus:
        up(&mm->mmap_sem);
 
index 91409cd28387342773ea82e3450d7ed4a7856260..1b4a54d077c28291694b8cf2abb39df744febc24 100644 (file)
@@ -28,8 +28,6 @@
 #include <asm/atari_stram.h>
 #endif
 
-#undef DEBUG
-
 extern void die_if_kernel(char *,struct pt_regs *,long);
 extern void show_net_buffers(void);
 
@@ -94,12 +92,12 @@ void show_mem(void)
            reserved++;
        else if (PageSwapCache(mem_map+i))
            cached++;
-       else if (!atomic_read(&mem_map[i].count))
+       else if (!page_count(mem_map+i))
            free++;
-       else if (atomic_read(&mem_map[i].count) == 1)
+       else if (page_count(mem_map+i) == 1)
            nonshared++;
        else
-           shared += atomic_read(&mem_map[i].count) - 1;
+           shared += page_count(mem_map+i) - 1;
     }
     printk("%d pages of RAM\n",total);
     printk("%d free pages\n",free);
@@ -138,6 +136,7 @@ __initfunc(static pte_t * kernel_page_table(unsigned long *memavailp))
 }
 
 static pmd_t *last_pgtable __initdata = NULL;
+static pmd_t *zero_pgtable __initdata = NULL;
 
 __initfunc(static pmd_t * kernel_ptr_table(unsigned long *memavailp))
 {
@@ -183,7 +182,7 @@ map_chunk (unsigned long addr, long size, unsigned long *memavailp))
 {
 #define PTRTREESIZE (256*1024)
 #define ROOTTREESIZE (32*1024*1024)
-       static unsigned long virtaddr = 0;
+       static unsigned long virtaddr = PAGE_OFFSET;
        unsigned long physaddr;
        pgd_t *pgd_dir;
        pmd_t *pmd_dir;
@@ -235,7 +234,8 @@ map_chunk (unsigned long addr, long size, unsigned long *memavailp))
 #ifdef DEBUG
                                printk ("[zero map]");
 #endif
-                               pte_dir = (pte_t *)kernel_ptr_table(memavailp);
+                               zero_pgtable = kernel_ptr_table(memavailp);
+                               pte_dir = (pte_t *)zero_pgtable;
                                pmd_dir->pmd[0] = virt_to_phys(pte_dir) |
                                        _PAGE_TABLE | _PAGE_ACCESSED;
                                pte_val(*pte_dir++) = 0;
@@ -352,38 +352,6 @@ __initfunc(unsigned long paging_init(unsigned long start_mem,
        start_mem += PAGE_SIZE;
        memset((void *)empty_zero_page, 0, PAGE_SIZE);
 
-       /* 
-        * allocate the "swapper" page directory and
-        * record in task 0 (swapper) tss 
-        */
-       init_mm.pgd = (pgd_t *)kernel_ptr_table(&start_mem);
-       memset (init_mm.pgd, 0, sizeof(pgd_t)*PTRS_PER_PGD);
-
-       /* setup CPU root pointer for swapper task */
-       task[0]->tss.crp[0] = 0x80000000 | _PAGE_TABLE;
-       task[0]->tss.crp[1] = virt_to_phys(init_mm.pgd);
-
-#ifdef DEBUG
-       printk ("task 0 pagedir at %p virt, %#lx phys\n",
-               swapper_pg_dir, task[0]->tss.crp[1]);
-#endif
-
-       if (CPU_IS_040_OR_060)
-               asm __volatile__ (".chip 68040\n\t"
-                                 "movec %0,%%urp\n\t"
-                                 ".chip 68k"
-                                 : /* no outputs */
-                                 : "r" (task[0]->tss.crp[1]));
-       else
-               asm __volatile__ (".chip 68030\n\t"
-                                 "pmove %0,%%crp\n\t"
-                                 ".chip 68k"
-                                 : /* no outputs */
-                                 : "m" (task[0]->tss.crp[0]));
-#ifdef DEBUG
-       printk ("set crp\n");
-#endif
-
        /*
         * Set up SFC/DFC registers (user data space)
         */
@@ -418,7 +386,7 @@ __initfunc(void mem_init(unsigned long start_mem, unsigned long end_mem))
                atari_stram_reserve_pages( start_mem );
 #endif
 
-       for (tmp = 0 ; tmp < end_mem ; tmp += PAGE_SIZE) {
+       for (tmp = PAGE_OFFSET ; tmp < end_mem ; tmp += PAGE_SIZE) {
                if (virt_to_phys ((void *)tmp) >= mach_max_dma_address)
                        clear_bit(PG_DMA, &mem_map[MAP_NR(tmp)].flags);
                if (PageReserved(mem_map+MAP_NR(tmp))) {
@@ -435,7 +403,7 @@ __initfunc(void mem_init(unsigned long start_mem, unsigned long end_mem))
                                datapages++;
                        continue;
                }
-               atomic_set(&mem_map[MAP_NR(tmp)].count, 1);
+               set_page_count(mem_map+MAP_NR(tmp), 1);
 #ifdef CONFIG_BLK_DEV_INITRD
                if (!initrd_start ||
                    (tmp < (initrd_start & PAGE_MASK) || tmp >= initrd_end))
@@ -450,6 +418,10 @@ __initfunc(void mem_init(unsigned long start_mem, unsigned long end_mem))
                        init_pointer_table(pgd_page(kernel_pg_dir[i]));
        }
 
+       /* insert also pointer table that we used to unmap the zero page */
+       if (zero_pgtable)
+               init_pointer_table((unsigned long)zero_pgtable);
+
        printk("Memory: %luk/%luk available (%dk kernel code, %dk data, %dk init)\n",
               (unsigned long) nr_free_pages << (PAGE_SHIFT-10),
               max_mapnr << (PAGE_SHIFT-10),
@@ -465,7 +437,7 @@ void free_initmem(void)
        addr = (unsigned long)&__init_begin;
        for (; addr < (unsigned long)&__init_end; addr += PAGE_SIZE) {
                mem_map[MAP_NR(addr)].flags &= ~(1 << PG_reserved);
-               atomic_set(&mem_map[MAP_NR(addr)].count, 1);
+               set_page_count(mem_map+MAP_NR(addr), 1);
                free_page(addr);
        }
 }
@@ -483,9 +455,9 @@ void si_meminfo(struct sysinfo *val)
        if (PageReserved(mem_map+i))
            continue;
        val->totalram++;
-       if (!atomic_read(&mem_map[i].count))
+       if (!page_count(mem_map+i))
            continue;
-       val->sharedram += atomic_read(&mem_map[i].count) - 1;
+       val->sharedram += page_count(mem_map+i) - 1;
     }
     val->totalram <<= PAGE_SHIFT;
     val->sharedram <<= PAGE_SHIFT;
index a6d496571bd509d6997e4ed040ad766697c6f5f9..cc91808484b74b7c18af23b8ec2f01bf3e06e816 100644 (file)
@@ -227,31 +227,33 @@ static unsigned long transp_transl_matches( unsigned long regval,
     /* address match? */
     base = regval & 0xff000000;
     mask = ~(regval << 8) & 0xff000000;
-    return ((vaddr ^ base) & mask) == 0;
+    return (((unsigned long)vaddr ^ base) & mask) == 0;
 }
 
+#if DEBUG_INVALID_PTOV
+int mm_inv_cnt = 5;
+#endif
+
 #ifndef CONFIG_SINGLE_MEMORY_CHUNK
 /*
  * The following two routines map from a physical address to a kernel
  * virtual address and vice versa.
  */
-unsigned long mm_vtop (unsigned long vaddr)
+unsigned long mm_vtop(unsigned long vaddr)
 {
        int i=0;
-       unsigned long voff = vaddr;
-       unsigned long offset = 0;
+       unsigned long voff = (unsigned long)vaddr - PAGE_OFFSET;
 
-       do{
-               if (voff < offset + m68k_memory[i].size) {
+       do {
+               if (voff < m68k_memory[i].size) {
 #ifdef DEBUGPV
-                       printk ("VTOP(%lx)=%lx\n", vaddr,
-                               m68k_memory[i].addr + voff - offset);
+                       printk ("VTOP(%p)=%lx\n", vaddr,
+                               m68k_memory[i].addr + voff);
 #endif
-                       return m68k_memory[i].addr + voff - offset;
-               } else
-                       offset += m68k_memory[i].size;
-               i++;
-       }while (i < m68k_num_memory);
+                       return m68k_memory[i].addr + voff;
+               }
+               voff -= m68k_memory[i].size;
+       } while (++i < m68k_num_memory);
 
        return mm_vtop_fallback(vaddr);
 }
@@ -259,7 +261,7 @@ unsigned long mm_vtop (unsigned long vaddr)
 
 /* Separate function to make the common case faster (needs to save less
    registers) */
-unsigned long mm_vtop_fallback (unsigned long vaddr)
+unsigned long mm_vtop_fallback(unsigned long vaddr)
 {
        /* not in one of the memory chunks; test for applying transparent
         * translation */
@@ -272,13 +274,13 @@ unsigned long mm_vtop_fallback (unsigned long vaddr)
                          ".chip 68k"
                          : : "a" (&ttreg) );
            if (transp_transl_matches( ttreg, vaddr ))
-               return vaddr;
+               return (unsigned long)vaddr;
            asm volatile( ".chip 68030\n\t"
                          "pmove %/tt1,%0@\n\t"
                          ".chip 68k"
                          : : "a" (&ttreg) );
            if (transp_transl_matches( ttreg, vaddr ))
-               return vaddr;
+               return (unsigned long)vaddr;
        }
        else if (CPU_IS_040_OR_060) {
            unsigned long ttreg;
@@ -288,13 +290,13 @@ unsigned long mm_vtop_fallback (unsigned long vaddr)
                          ".chip 68k"
                          : "=d" (ttreg) );
            if (transp_transl_matches( ttreg, vaddr ))
-               return vaddr;
+               return (unsigned long)vaddr;
            asm volatile( ".chip 68040\n\t"
                          "movec %%dtt1,%0\n\t"
                          ".chip 68k"
                          : "=d" (ttreg) );
            if (transp_transl_matches( ttreg, vaddr ))
-               return vaddr;
+               return (unsigned long)vaddr;
        }
 
        /* no match, too, so get the actual physical address from the MMU. */
@@ -306,11 +308,21 @@ unsigned long mm_vtop_fallback (unsigned long vaddr)
          set_fs (MAKE_MM_SEG(SUPER_DATA));
 
          /* The PLPAR instruction causes an access error if the translation
-          * is not possible. We don't catch that here, so a bad kernel trap
-          * will be reported in this case. */
-         asm volatile (".chip 68060\n\t"
-                       "plpar (%0)\n\t"
-                       ".chip 68k"
+          * is not possible. To catch this we use the same exception mechanism
+          * as for user space accesses in <asm/uaccess.h>. */
+         asm volatile (".chip 68060\n"
+                       "1: plpar (%0)\n"
+                       ".chip 68k\n"
+                       "2:\n"
+                       ".section .fixup,\"ax\"\n"
+                       "   .even\n"
+                       "3: lea -1,%0\n"
+                       "   jra 2b\n"
+                       ".previous\n"
+                       ".section __ex_table,\"a\"\n"
+                       "   .align 4\n"
+                       "   .long 1b,3b\n"
+                       ".previous"
                        : "=a" (paddr)
                        : "0" (vaddr));
          set_fs (fs);
@@ -332,12 +344,13 @@ unsigned long mm_vtop_fallback (unsigned long vaddr)
          set_fs (fs);
 
          if (mmusr & MMU_T_040) {
-           return (vaddr);     /* Transparent translation */
+           return (unsigned long)vaddr;        /* Transparent translation */
          }
          if (mmusr & MMU_R_040)
-           return (mmusr & PAGE_MASK) | (vaddr & (PAGE_SIZE-1));
+           return (mmusr & PAGE_MASK) | ((unsigned long)vaddr & (PAGE_SIZE-1));
 
-         panic ("VTOP040: bad virtual address %08lx (%lx)", vaddr, mmusr);
+         printk("VTOP040: bad virtual address %lx (%lx)", vaddr, mmusr);
+         return -1;
        } else {
          volatile unsigned short temp;
          unsigned short mmusr;
@@ -350,46 +363,51 @@ unsigned long mm_vtop_fallback (unsigned long vaddr)
          mmusr = temp;
 
          if (mmusr & (MMU_I|MMU_B|MMU_L))
-           panic ("VTOP030: bad virtual address %08lx (%x)", vaddr, mmusr);
+           printk("VTOP030: bad virtual address %lx (%x)\n", vaddr, mmusr);
 
          descaddr = phys_to_virt((unsigned long)descaddr);
 
          switch (mmusr & MMU_NUM) {
          case 1:
-           return (*descaddr & 0xfe000000) | (vaddr & 0x01ffffff);
+           return (*descaddr & 0xfe000000) | ((unsigned long)vaddr & 0x01ffffff);
          case 2:
-           return (*descaddr & 0xfffc0000) | (vaddr & 0x0003ffff);
+           return (*descaddr & 0xfffc0000) | ((unsigned long)vaddr & 0x0003ffff);
          case 3:
-           return (*descaddr & PAGE_MASK) | (vaddr & (PAGE_SIZE-1));
+           return (*descaddr & PAGE_MASK) | ((unsigned long)vaddr & (PAGE_SIZE-1));
          default:
-           panic ("VTOP: bad levels (%u) for virtual address %08lx", 
+           printk("VTOP: bad levels (%u) for virtual address %lx\n", 
                   mmusr & MMU_NUM, vaddr);
          }
        }
 
-       panic ("VTOP: bad virtual address %08lx", vaddr);
+       printk("VTOP: bad virtual address %lx\n", vaddr);
+       return -1;
 }
 
 #ifndef CONFIG_SINGLE_MEMORY_CHUNK
-unsigned long mm_ptov (unsigned long paddr)
+void *mm_ptov (unsigned long paddr)
 {
        int i = 0;
-       unsigned long offset = 0;
+       unsigned long poff, voff = PAGE_OFFSET;
 
-       do{
-               if (paddr >= m68k_memory[i].addr &&
-                   paddr < (m68k_memory[i].addr
-                            + m68k_memory[i].size)) {
+       do {
+               poff = paddr - m68k_memory[i].addr;
+               if (poff < m68k_memory[i].size) {
 #ifdef DEBUGPV
-                       printk ("PTOV(%lx)=%lx\n", paddr,
-                               (paddr - m68k_memory[i].addr) + offset);
+                       printk ("PTOV(%lx)=%lx\n", paddr, poff + voff);
+#endif
+                       return (void *)(poff + voff);
+               }
+               voff += m68k_memory[i].size;
+       } while (++i < m68k_num_memory);
+
+#if DEBUG_INVALID_PTOV
+       if (mm_inv_cnt > 0) {
+               mm_inv_cnt--;
+               printk("Invalid use of phys_to_virt(0x%lx) at 0x%p!\n",
+                       paddr, __builtin_return_address(0));
+       }
 #endif
-                       return (paddr - m68k_memory[i].addr) + offset;
-               } else
-                       offset += m68k_memory[i].size;
-               i++;
-       }while (i < m68k_num_memory);
-
        /*
         * assume that the kernel virtual address is the same as the
         * physical address.
@@ -411,9 +429,9 @@ unsigned long mm_ptov (unsigned long paddr)
         * to the ZTWO_VADDR range
         */
        if (MACH_IS_AMIGA && paddr < 16*1024*1024)
-               return ZTWO_VADDR(paddr);
+               return (void *)ZTWO_VADDR(paddr);
 #endif
-       return paddr;
+       return (void *)-1;
 }
 #endif
 
index 2fe61766a3ecbfa7ca091f876c0e51d1462af750..288e4c6724000bee2d06cd1d9f270e1285b251a5 100644 (file)
@@ -13,7 +13,6 @@
  * for more details.
  */
 
-#include <stdarg.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
index db7eb3137e083cf3eac6a9246d64551b0687f775..06eb148c72e4a988e5922450c9c2bb24ce764729 100644 (file)
@@ -15,7 +15,6 @@
  */
 
 #include <linux/config.h>
-#include <stdarg.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
index 0c6871f88bd0ab3f86103b8b86bec566513a94a0..889936243955a0e18f5686a0cc7fcbe34c536f95 100644 (file)
@@ -12,7 +12,6 @@
  * for more details.
  */
 
-#include <stdarg.h>
 #include <linux/config.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
index b79c9dd87e6dc2c28dbdaf66d5373c2708562d7d..74b32fdfb17b7ef32b30498175f11bdc112fa9e7 100644 (file)
@@ -31,22 +31,32 @@ SECTIONS
        CONSTRUCTORS
        }
 
-  .bss : { *(.bss) }           /* BSS */
-
   _edata = .;                  /* End of data section */
 
-  . = ALIGN(16);
-  .data.cacheline_aligned : { *(.data.cacheline_aligned) }
+  . = ALIGN(8192);
+  init_task : { *(init_task) }
 
   . = ALIGN(4096);             /* Init code and data */
   __init_begin = .;
   .text.init : { *(.text.init) }
   .data.init : { *(.data.init) }
+  . = ALIGN(16);
+  __setup_start = .;
+  .setup.init : { *(.setup.init) }
+  __setup_end = .;
+  __initcall_start = .;
+  .initcall.init : { *(.initcall.init) }
+  __initcall_end = .;
   . = ALIGN(8192);
   __init_end = .;
 
-  init_task : { *(init_task) } /* The initial task and kernel stack */
+  . = ALIGN(16);
+  .data.cacheline_aligned : { *(.data.cacheline_aligned) }
 
+  __bss_start = .;             /* BSS */
+  .bss : {
+       *(.bss)
+       }
   _end = . ;
 
   /* Stabs debugging sections.  */
index 0ee33bb49656902501aea09c3b13e92b3f936c94..ba16ed42691f842f990741d2fa0c4a1da8efedea 100644 (file)
@@ -325,11 +325,11 @@ void kernel_set_cachemode( unsigned long address, unsigned long size,
 
        switch (cmode)
        {
-       case KERNELMAP_FULL_CACHING:
+       case IOMAP_FULL_CACHING:
                mask = ~(_PAGE_NO_CACHE | _PAGE_GUARDED);
                flags = 0;
                break;
-       case KERNELMAP_NOCACHE_SER:
+       case IOMAP_NOCACHE_SER:
                mask = ~0;
                flags = (_PAGE_NO_CACHE | _PAGE_GUARDED);
                break;
index 1d13403314a67e8c5d536947667ecee31826081f..f2008adfdd6ce77e3c420f4d05e6016caa439777 100644 (file)
@@ -219,3 +219,7 @@ EXPORT_SYMBOL_NOVERS(memcmp);
 
 EXPORT_SYMBOL(abs);
 EXPORT_SYMBOL(device_is_compatible);
+
+#ifdef CONFIG_VT
+EXPORT_SYMBOL(screen_info);
+#endif
index ceb49dab92410cfeb54e05068a025ab12db61b4f..f95bfb1ea264ae88aa9225dad598fbbce1a962d1 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: srmmu.c,v 1.189 1999/07/30 09:35:08 davem Exp $
+/* $Id: srmmu.c,v 1.190 1999/08/07 17:47:01 anton Exp $
  * srmmu.c:  SRMMU specific routines for memory management.
  *
  * Copyright (C) 1995 David S. Miller  (davem@caip.rutgers.edu)
@@ -114,6 +114,7 @@ static unsigned long srmmu_p2v_hash[SRMMU_HASHSZ];
 #define srmmu_ahashfn(addr)    ((addr) >> 24)
 
 int viking_mxcc_present = 0;
+static spinlock_t srmmu_context_spinlock = SPIN_LOCK_UNLOCKED;
 
 /* Physical memory can be _very_ non-contiguous on the sun4m, especially
  * the SS10/20 class machines and with the latest openprom revisions.
@@ -819,7 +820,9 @@ static inline void free_context(int context)
 static void srmmu_switch_to_context(struct task_struct *tsk)
 {
        if(tsk->mm->context == NO_CONTEXT) {
+               spin_lock(&srmmu_context_spinlock);
                alloc_context(tsk->mm);
+               spin_unlock(&srmmu_context_spinlock);
                ctxd_set(&srmmu_context_table[tsk->mm->context], tsk->mm->pgd);
        }
        srmmu_set_context(tsk->mm->context);
@@ -827,7 +830,9 @@ static void srmmu_switch_to_context(struct task_struct *tsk)
 
 static void srmmu_init_new_context(struct mm_struct *mm)
 {
+       spin_lock(&srmmu_context_spinlock);
        alloc_context(mm);
+       spin_unlock(&srmmu_context_spinlock);
 
        flush_cache_mm(mm);
        ctxd_set(&srmmu_context_table[mm->context], mm->pgd);
@@ -1398,7 +1403,9 @@ static void hypersparc_switch_to_context(struct task_struct *tsk)
        if(tsk->mm->context == NO_CONTEXT) {
                ctxd_t *ctxp;
 
+               spin_lock(&srmmu_context_spinlock);
                alloc_context(tsk->mm);
+               spin_unlock(&srmmu_context_spinlock);
                ctxp = &srmmu_context_table[tsk->mm->context];
                srmmu_set_entry((pte_t *)ctxp, __pte((SRMMU_ET_PTD | (srmmu_v2p((unsigned long) tsk->mm->pgd) >> 4))));
                hypersparc_flush_page_to_ram((unsigned long)ctxp);
@@ -1411,7 +1418,9 @@ static void hypersparc_init_new_context(struct mm_struct *mm)
 {
        ctxd_t *ctxp;
 
+       spin_lock(&srmmu_context_spinlock);
        alloc_context(mm);
+       spin_unlock(&srmmu_context_spinlock);
 
        ctxp = &srmmu_context_table[mm->context];
        srmmu_set_entry((pte_t *)ctxp, __pte((SRMMU_ET_PTD | (srmmu_v2p((unsigned long) mm->pgd) >> 4))));
index 800fa1915e46efea87f2e7e199a1134432a0cbcb..1fbdad83594ec250f16d08cca4793f3cf9c6d342 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: ioctl32.c,v 1.65 1999/07/30 09:35:19 davem Exp $
+/* $Id: ioctl32.c,v 1.66 1999/08/08 01:37:06 davem Exp $
  * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
  *
  * Copyright (C) 1997  Jakub Jelinek  (jj@sunsite.mff.cuni.cz)
diff --git a/drivers/block/README.buddha b/drivers/block/README.buddha
new file mode 100644 (file)
index 0000000..d3b7bc7
--- /dev/null
@@ -0,0 +1,210 @@
+
+The Amiga Buddha and Catweasel IDE Driver (part of ide.c) was written by
+Geert Uytterhoeven based on the following specifications:
+
+------------------------------------------------------------------------
+
+Register map of the Buddha IDE controller and the
+Buddha-part of the Catweasel Zorro-II version
+
+The Autoconfiguration has been implemented just as Commodore
+described  in  their  manuals, no tricks have been used (for
+example leaving some address lines out of the equations...).
+If you want to configure the board yourself (for example let
+a  Linux  kernel  configure the card), look at the Commodore
+Docs.  Reading the nibbles should give this information:
+
+Vendor number: 4626 ($1212)
+product number: 0 (42 for Catweasel Z-II)
+Serial number: 0
+Rom-vector: $1000
+
+The  card  should be a Z-II board, size 64K, not for freemem
+list, Rom-Vektor is valid, no second Autoconfig-board on the
+same card, no space preferrence, supports "Shutup_forever".
+
+Setting  the  base address should be done in two steps, just
+as  the Amiga Kickstart does:  The lower nibble of the 8-Bit
+address is written to $4a, then the whole Byte is written to
+$48, while it doesn't matter how often you're writing to $4a
+as  long as $48 is not touched.  After $48 has been written,
+the  whole card disappears from $e8 and is mapped to the new
+addrress just written.  Make shure $4a is written befor $48,
+otherwise your chance is only 1:16 to find the board :-).
+
+The local memory-map is even active when mapped to $e8:
+
+$0-$7e         Autokonfig-space, see Z-II docs.
+
+$80-$7fd       reserved
+
+$7fe           Speed-select Register: Read & Write
+               (description see further down)
+
+$800-$8ff      IDE-Select 0 (Port 0, Register set 0)
+
+$900-$9ff      IDE-Select 1 (Port 0, Register set 1)
+
+$a00-$aff      IDE-Select 2 (Port 1, Register set 0)
+
+$b00-$bff      IDE-Select 3 (Port 1, Register set 1)
+
+$c00-$cff      IDE-Select 4 (Port 2, Register set 0,
+                          Catweasel only!)
+
+$d00-$dff      IDE-Select 5 (Port 3, Register set 1,
+                             Catweasel only!)
+
+$e00-$eff      local expansion port, on Catweasel Z-II the 
+               Catweasel registers are also mapped here.
+               Never touch, use multidisk.device!
+               
+$f00           read only, Byte-access: Bit 7 shows the 
+               level of the IRQ-line of IDE port 0. 
+
+$f01-$f3f      mirror of $f00
+
+$f40           read only, Byte-access: Bit 7 shows the 
+               level of the IRQ-line of IDE port 1. 
+
+$f41-$f7f      mirror of $f40
+
+$f80           read only, Byte-access: Bit 7 shows the 
+               level of the IRQ-line of IDE port 2. 
+               (Catweasel only!)
+
+$f81-$fbf      mirror of $f80
+
+$fc0           write-only: Writing any value to this
+               register enables IRQs to be passed from the 
+               IDE ports to the Zorro bus. This mechanism 
+               has been implemented to be compatible with 
+               harddisks that are either defective or have
+               a buggy firmware and pull the IRQ line up 
+               while starting up. If interrupts would 
+               always be passed to the bus, the computer 
+               might not start up. Once enabled, this flag 
+               can not be disabled again. The level of the 
+               flag can not be determined by software 
+               (what for? Write to me if it's necessary!).
+
+$fc1-$fff      mirror of $fc0
+
+$1000-$ffff    Buddha-Rom with offset $1000 in the rom
+               chip. The addresses $0 to $fff of the rom 
+               chip cannot be read. Rom is Byte-wide and
+               mapped to even addresses.
+
+The  IDE ports issue an INT2.  You can read the level of the
+IRQ-lines  of  the  IDE-ports by reading from the three (two
+for  Buddha-only)  registers  $f00, $f40 and $f80.  This way
+more  than one I/O request can be handled and you can easily
+determine  what  driver  has  to serve the INT2.  Buddha and
+Catweasel  expansion  boards  can issue an INT6.  A seperate
+memory  map  is available for the I/O module and the sysop's
+I/O module.
+
+The IDE ports are fed by the address lines A2 to A4, just as
+the  Amiga  1200  and  Amiga  4000  IDE ports are.  This way
+existing  drivers  can be easily ported to Buddha.  A move.l
+polls  two  words  out of the same address of IDE port since
+every  word  is  mirrored  once.  movem is not possible, but
+it's  not  necessary  either,  because  you can only speedup
+68000  systems  with  this  technique.   A 68020 system with
+fastmem is faster with move.l.
+
+If you're using the mirrored registers of the IDE-ports with
+A6=1,  the Buddha doesn't care about the speed that you have
+selected  in  the  speed  register (see further down).  With
+A6=1  (for example $840 for port 0, register set 0), a 780ns
+access  is being made.  These registers should be used for a
+command   access   to  the  harddisk/CD-Rom,  since  command
+accesses  are Byte-wide and have to be made slower according
+to the ATA-X3T9 manual.
+
+Now  for the speed-register:  The register is byte-wide, and
+only  the  upper  three  bits are used (Bits 7 to 5).  Bit 4
+must  always  be set to 1 to be compatible with later Buddha
+versions  (if  I'll  ever  update this one).  I presume that
+I'll  never use the lower four bits, but they have to be set
+to 1 by definition.
+  The  values in this table have to be shifted 5 bits to the
+left and or'd with $1f (this sets the lower 5 bits).
+
+All  the timings have in common:  Select and IOR/IOW rise at
+the  same  time.   IOR  and  IOW have a propagation delay of
+about  30ns  to  the clocks on the Zorro bus, that's why the
+values  are no multiple of 71.  One clock-cycle is 71ns long
+(exactly 70,5 at 14,18 Mhz on PAL systems).
+
+value 0 (Default after reset)
+
+497ns Select (7 clock cycles) , IOR/IOW after 172ns (2 clock cycles)
+(same timing as the Amiga 1200 does on it's IDE port without
+accelerator card)
+
+value 1
+
+639ns Select (9 clock cycles), IOR/IOW after 243ns (3 clock cycles)
+
+value 2
+
+781ns Select (11 clock cycles), IOR/IOW after 314ns (4 clock cycles)
+
+value 3
+
+355ns Select (5 clock cycles), IOR/IOW after 101ns (1 clock cycle)
+
+value 4
+
+355ns Select (5 clock cycles), IOR/IOW after 172ns (2 clock cycles)
+
+value 5
+
+355ns Select (5 clock cycles), IOR/IOW after 243ns (3 clock cycles)
+
+value 6
+
+1065ns Select (15 clock cycles), IOR/IOW after 314ns (4 clock cycles)
+
+value 7
+
+355ns Select, (5 clock cycles), IOR/IOW after 101ns (1 clock cycle)
+
+When accessing IDE registers with A6=1 (for example $84x),
+the timing will always be mode 0 8-bit compatible, no matter
+what you have selected in the speed register:
+
+781ns select, IOR/IOW after 4 clock cycles (=314ns) aktive. 
+
+All  the  timings with a very short select-signal (the 355ns
+fast  accesses)  depend  on the accelerator card used in the
+system:  Sometimes two more clock cycles are inserted by the
+bus  interface,  making  the  whole access 497ns long.  This
+doesn't  affect  the  reliability  of the controller nor the
+performance  of  the  card,  since  this doesn't happen very
+often.
+
+All  the  timings  are  calculated  and  only  confirmed  by
+measurements  that allowed me to count the clock cycles.  If
+the  system  is clocked by an oscillator other than 28,37516
+Mhz  (for  example  the  NTSC-frequency  28,63636 Mhz), each
+clock  cycle is shortened to a bit less than 70ns (not worth
+mentioning).   You  could think of a small performance boost
+by  overclocking  the  system,  but  you would either need a
+multisync  monitor,  or  a  graphics card, and your internal
+diskdrive would go crazy, that's why you shouldn't tune your
+Amiga this way.
+
+Giving  you  the  possibility  to  write  software  that  is
+compatible  with both the Buddha and the Catweasel Z-II, The
+Buddha  acts  just  like  a  Catweasel  Z-II  with no device
+connected  to  the  third  IDE-port.   The IRQ-register $f80
+always  shows a "no IRQ here" on the Buddha, and accesses to
+the  third  IDE  port  are  going into data's Nirwana on the
+Buddha.
+
+                           Jens Schönfeld february 19th, 1997
+                                       updated may 27th, 1997
+                            eMail: sysop@nostlgic.tng.oche.de
+
index ea0e989f82eb395f91e83dcaaa2785c794839679..80aa524723ef52a07062ebcf913b3bb3bbc5e7f0 100644 (file)
@@ -253,17 +253,8 @@ static int                         CurrentNSect;
 static char                            *CurrentBuffer;
 
 
-#define SET_TIMER()                                                    \
-       do {                                                            \
-               del_timer( &acsi_timer );                               \
-               acsi_timer.expires = jiffies + ACSI_TIMEOUT;            \
-               add_timer( &acsi_timer );                               \
-       } while(0)
-
-#define CLEAR_TIMER()                                                  \
-       do {                                                            \
-               del_timer( &acsi_timer );                               \
-       } while(0)
+#define SET_TIMER()    mod_timer(&acsi_timer, jiffies + ACSI_TIMEOUT)
+#define CLEAR_TIMER()  del_timer(&acsi_timer)
 
 static unsigned long   STramMask;
 #define STRAM_ADDR(a)  (((a) & STramMask) == 0)
@@ -425,8 +416,8 @@ int acsi_wait_for_IRQ( unsigned timeout )
 
 {
        if (INT_LEVEL < 6) {
-               unsigned long maxjif;
-               for( maxjif = jiffies + timeout; time_before(jiffies, maxjif); )
+               unsigned long maxjif = jiffies + timeout;
+               while (time_before(jiffies, maxjif))
                        if (!(mfp.par_dt_reg & 0x20)) return( 1 );
        }
        else {
@@ -442,8 +433,8 @@ int acsi_wait_for_noIRQ( unsigned timeout )
 
 {
        if (INT_LEVEL < 6) {
-               unsigned long maxjif;
-               for( maxjif = jiffies + timeout; time_before(jiffies, maxjif); )
+               unsigned long maxjif = jiffies + timeout;
+               while (time_before(jiffies, maxjif))
                        if (mfp.par_dt_reg & 0x20) return( 1 );
        }
        else {
@@ -502,7 +493,7 @@ static int acsicmd_dma( const char *cmd, char *buffer, int blocks, int rwflag, i
 #endif
        
        rwflag = rwflag ? 0x100 : 0;
-       paddr = VTOP( buffer );
+       paddr = virt_to_phys( buffer );
 
        acsi_delay_end(COMMAND_DELAY);
        DISABLE_IRQ();
@@ -610,7 +601,7 @@ static int acsi_reqsense( char *buffer, int targ, int lun)
        if (!acsicmd_nodma( reqsense_cmd, 0 )) return( 0 );
        if (!acsi_wait_for_IRQ( 10 )) return( 0 );
        acsi_getstatus();
-       dma_cache_maintenance( VTOP(buffer), 16, 0 );
+       dma_cache_maintenance( virt_to_phys(buffer), 16, 0 );
        
        return( 1 );
 }      
@@ -809,7 +800,7 @@ static void read_intr( void )
                return;
        }
 
-       dma_cache_maintenance( VTOP(CurrentBuffer), CurrentNSect*512, 0 );
+       dma_cache_maintenance( virt_to_phys(CurrentBuffer), CurrentNSect*512, 0 );
        if (CurrentBuffer == acsi_buffer)
                copy_from_acsibuffer();
 
@@ -1030,7 +1021,7 @@ static void redo_acsi_request( void )
         * consecutive buffers and thus can be done with a single command.
         */
        buffer      = CURRENT->buffer;
-       pbuffer     = VTOP(buffer);
+       pbuffer     = virt_to_phys(buffer);
        nsect       = CURRENT->current_nr_sectors;
        CurrentNReq = 1;
 
@@ -1052,7 +1043,7 @@ static void redo_acsi_request( void )
                        unsigned long pendadr, pnewadr;
                        pendadr = pbuffer + nsect*512;
                        while( (bh = bh->b_reqnext) ) {
-                               pnewadr = VTOP(bh->b_data);
+                               pnewadr = virt_to_phys(bh->b_data);
                                if (!STRAM_ADDR(pnewadr) || pendadr != pnewadr) break;
                                nsect += bh->b_size >> 9;
                                pendadr = pnewadr + bh->b_size;
@@ -1814,7 +1805,7 @@ int acsi_init( void )
                unregister_blkdev( MAJOR_NR, "ad" );
                return -ENOMEM;
        }
-       phys_acsi_buffer = VTOP( acsi_buffer );
+       phys_acsi_buffer = virt_to_phys( acsi_buffer );
        STramMask = ATARIHW_PRESENT(EXTD_DMA) ? 0x00000000 : 0xff000000;
        
        blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
index b341c39c4692315ddf41a02e04def02586920c61..d718075e26216147bd2afed3812db36e937b3fcc 100644 (file)
@@ -413,8 +413,8 @@ static void start_print( int device )
 
        CMDSET_TARG_LUN( slmprint_cmd, sip->target, sip->lun );
        cmd = slmprint_cmd;
-       paddr = VTOP( SLMBuffer );
-       dma_cache_maintenance( paddr, VTOP(BufferP)-paddr, 1 );
+       paddr = virt_to_phys( SLMBuffer );
+       dma_cache_maintenance( paddr, virt_to_phys(BufferP)-paddr, 1 );
        DISABLE_IRQ();
 
        /* Low on A1 */
@@ -466,7 +466,7 @@ static void slm_interrupt(int irc, void *data, struct pt_regs *fp)
        addr = get_dma_addr();
        stat = acsi_getstatus();
        SLMError = (stat < 0)             ? SLMSTAT_ACSITO :
-                      (addr < VTOP(BufferP)) ? SLMSTAT_NOTALL :
+                      (addr < virt_to_phys(BufferP)) ? SLMSTAT_NOTALL :
                                                                            stat;
 
        dma_wd.dma_mode_status = 0x80;
index cf408b8c79765caa67af4305e13ddf6c8769bda7..b8df872053afa41e494191cd5d0267c293fb4d92 100644 (file)
@@ -215,11 +215,10 @@ static struct atari_disk_type user_params[FD_MAX_UNITS];
  * restored upon disk change by floppy_revalidate() if valid (as seen by
  * default_params[].blocks > 0 - a bit in unit[].flags might be used for this?)
  */
-static struct atari_disk_type default_params[FD_MAX_UNITS] = {
-       { NULL,  0, 0, 0, 0},  };
+static struct atari_disk_type default_params[FD_MAX_UNITS];
 
 static int floppy_sizes[256];
-static int floppy_blocksizes[256] = { 0, };
+static int floppy_blocksizes[256];
 
 /* current info on each unit */
 static struct atari_floppy_struct {
@@ -331,26 +330,6 @@ static unsigned int changed_floppies = 0xff, fake_change = 0;
                                         * will give up. */
 
 
-#define        START_MOTOR_OFF_TIMER(delay)                            \
-    do {                                                       \
-        motor_off_timer.expires = jiffies + (delay);           \
-        add_timer( &motor_off_timer );                         \
-        MotorOffTrys = 0;                                      \
-       } while(0)
-
-#define        START_CHECK_CHANGE_TIMER(delay)                         \
-    do {                                                       \
-        timer_table[FLOPPY_TIMER].expires = jiffies + (delay); \
-        timer_active |= (1 << FLOPPY_TIMER);                   \
-       } while(0)
-
-#define        START_TIMEOUT()                                         \
-    mod_timer(&timeout_timer, jiffies + FLOPPY_TIMEOUT)
-
-#define        STOP_TIMEOUT()                                          \
-    del_timer(&timeout_timer)
-
-
 /*
  * The driver is trying to determine the correct media format
  * while Probing is set. fd_rwsec_done() clears it after a
@@ -420,6 +399,31 @@ static struct timer_list timeout_timer =
        { NULL, NULL, 0, 0, fd_times_out };
 
 
+static inline void
+start_motor_off_timer(void)
+{
+       mod_timer(&motor_off_timer, jiffies + FD_MOTOR_OFF_DELAY);
+       MotorOffTrys = 0;
+}
+
+static inline void
+start_check_change_timer(void)
+{
+       timer_table[FLOPPY_TIMER].expires = jiffies + CHECK_CHANGE_DELAY;
+       timer_active |= (1 << FLOPPY_TIMER);
+}
+
+static inline void
+start_timeout(void)
+{
+       mod_timer(&timeout_timer, jiffies + FLOPPY_TIMEOUT);
+}
+
+static inline void
+stop_timeout(void)
+{
+       del_timer(&timeout_timer);
+}
 
 /* Select the side to use. */
 
@@ -497,19 +501,12 @@ static void fd_deselect( void )
 
 static void fd_motor_off_timer( unsigned long dummy )
 {
-/*     unsigned long flags; */
        unsigned char status;
-       int                   delay;
 
-       del_timer( &motor_off_timer );
-       
        if (SelectedDrive < 0)
                /* no drive selected, needn't deselect anyone */
                return;
 
-/*     save_flags(flags);
-       cli(); */
-       
        if (stdma_islocked())
                goto retry;
 
@@ -519,21 +516,18 @@ static void fd_motor_off_timer( unsigned long dummy )
                /* motor already turned off by FDC -> deselect drives */
                MotorOn = 0;
                fd_deselect();
-/*             restore_flags(flags); */
                return;
        }
        /* not yet off, try again */
 
   retry:
-/*     restore_flags(flags); */
        /* Test again later; if tested too often, it seems there is no disk
         * in the drive and the FDC will leave the motor on forever (or,
         * at least until a disk is inserted). So we'll test only twice
         * per second from then on...
         */
-       delay = (MotorOffTrys < FD_MOTOR_OFF_MAXTRY) ?
-                       (++MotorOffTrys, HZ/20) : HZ/2;
-       START_MOTOR_OFF_TIMER( delay );
+       mod_timer(&motor_off_timer,
+                 jiffies + (MotorOffTrys++ < FD_MOTOR_OFF_MAXTRY ? HZ/20 : HZ/2));
 }
 
 
@@ -571,7 +565,7 @@ static void check_change( void )
        }
        restore_flags(flags);
 
-       START_CHECK_CHANGE_TIMER( CHECK_CHANGE_DELAY );
+       start_check_change_timer();
 }
 
  
@@ -603,8 +597,7 @@ static void floppy_irq (int irq, void *dummy, struct pt_regs *fp)
        unsigned char status;
        void (*handler)( int );
 
-       handler = FloppyIRQHandler;
-       FloppyIRQHandler = NULL;
+       handler = xchg(&FloppyIRQHandler, NULL);
 
        if (handler) {
                nop();
@@ -805,7 +798,7 @@ static void fd_calibrate( void )
 
        NeedSeek = 1;
        MotorOn = 1;
-       START_TIMEOUT();
+       start_timeout();
        /* wait for IRQ */
 }
 
@@ -813,7 +806,7 @@ static void fd_calibrate( void )
 static void fd_calibrate_done( int status )
 {
        DPRINT(("fd_calibrate_done()\n"));
-       STOP_TIMEOUT();
+       stop_timeout();
     
        /* set the correct speed now */
        if (ATARIHW_PRESENT(FDCSPEED))
@@ -853,7 +846,7 @@ static void fd_seek( void )
 
        MotorOn = 1;
        set_head_settle_flag();
-       START_TIMEOUT();
+       start_timeout();
        /* wait for IRQ */
 }
 
@@ -861,7 +854,7 @@ static void fd_seek( void )
 static void fd_seek_done( int status )
 {
        DPRINT(("fd_seek_done()\n"));
-       STOP_TIMEOUT();
+       stop_timeout();
        
        /* set the correct speed */
        if (ATARIHW_PRESENT(FDCSPEED))
@@ -900,7 +893,7 @@ static void fd_rwsec( void )
        DPRINT(("fd_rwsec(), Sec=%d, Access=%c\n",ReqSector, ReqCmd == WRITE ? 'w' : 'r' ));
        if (ReqCmd == WRITE) {
                if (ATARIHW_PRESENT(EXTD_DMA)) {
-                       paddr = (unsigned long)VTOP(ReqData);
+                       paddr = virt_to_phys(ReqData);
                }
                else {
                        copy_buffer( ReqData, DMABuffer );
@@ -913,7 +906,8 @@ static void fd_rwsec( void )
                if (read_track)
                        paddr = PhysTrackBuffer;
                else
-                       paddr = ATARIHW_PRESENT(EXTD_DMA) ? VTOP(ReqData) : PhysDMABuffer;
+                       paddr = ATARIHW_PRESENT(EXTD_DMA) ? 
+                               virt_to_phys(ReqData) : PhysDMABuffer;
                rwflag = 0;
        }
 
@@ -978,14 +972,12 @@ static void fd_rwsec( void )
                 * search for the first non-existent sector and need 1 sec to
                 * recognise that it isn't present :-(
                 */
-               del_timer (&readtrack_timer);
-               readtrack_timer.expires =
-                 jiffies + HZ/5 + (old_motoron ? 0 : HZ);
-                      /* 1 rot. + 5 rot.s if motor was off  */
                MultReadInProgress = 1;
-               add_timer( &readtrack_timer );
+               mod_timer(&readtrack_timer,
+                         /* 1 rot. + 5 rot.s if motor was off  */
+                         jiffies + HZ/5 + (old_motoron ? 0 : HZ));
        }
-       START_TIMEOUT();
+       start_timeout();
 }
 
     
@@ -996,8 +988,6 @@ static void fd_readtrack_check( unsigned long dummy )
        save_flags(flags);  
        cli();
 
-       del_timer( &readtrack_timer );
-
        if (!MultReadInProgress) {
                /* This prevents a race condition that could arise if the
                 * interrupt is triggered while the calling of this timer
@@ -1045,8 +1035,7 @@ static void fd_readtrack_check( unsigned long dummy )
                /* not yet finished, wait another tenth rotation */
                restore_flags(flags);
                DPRINT(("fd_readtrack_check(): not yet finished\n"));
-               readtrack_timer.expires = jiffies + HZ/5/10;
-               add_timer( &readtrack_timer );
+               mod_timer(&readtrack_timer, jiffies + HZ/5/10);
        }
 }
 
@@ -1068,7 +1057,7 @@ static void fd_rwsec_done1(int status)
 {
        unsigned int track;
 
-       STOP_TIMEOUT();
+       stop_timeout();
        
        /* Correct the track if stretch != 0 */
        if (SUDT->stretch) {
@@ -1150,7 +1139,7 @@ static void fd_rwsec_done1(int status)
                if (!read_track) {
                        void *addr;
                        addr = ATARIHW_PRESENT( EXTD_DMA ) ? ReqData : DMABuffer;
-                       dma_cache_maintenance( VTOP(addr), 512, 0 );
+                       dma_cache_maintenance( virt_to_phys(addr), 512, 0 );
                        if (!ATARIHW_PRESENT( EXTD_DMA ))
                                copy_buffer (addr, ReqData);
                } else {
@@ -1237,7 +1226,7 @@ static void fd_writetrack( void )
        dma_wd.fdc_acces_seccount = FDCCMD_WRTRA | get_head_settle_flag(); 
 
        MotorOn = 1;
-       START_TIMEOUT();
+       start_timeout();
        /* wait for interrupt */
 }
 
@@ -1246,7 +1235,7 @@ static void fd_writetrack_done( int status )
 {
        DPRINT(("fd_writetrack_done()\n"));
 
-       STOP_TIMEOUT();
+       stop_timeout();
 
        if (status & FDCSTAT_WPROT) {
                printk(KERN_NOTICE "fd%d: is write protected\n", SelectedDrive );
@@ -1304,7 +1293,7 @@ static void finish_fdc( void )
                SET_IRQ_HANDLER( finish_fdc_done );
                FDC_WRITE (FDCREG_CMD, FDCCMD_SEEK);
                MotorOn = 1;
-               START_TIMEOUT();
+               start_timeout();
                /* we must wait for the IRQ here, because the ST-DMA
                   is released immediately afterwards and the interrupt
                   may be delivered to the wrong driver. */
@@ -1317,19 +1306,18 @@ static void finish_fdc_done( int dummy )
        unsigned long flags;
 
        DPRINT(("finish_fdc_done entered\n"));
-       STOP_TIMEOUT();
+       stop_timeout();
        NeedSeek = 0;
 
        if ((timer_active & (1 << FLOPPY_TIMER)) &&
-           timer_table[FLOPPY_TIMER].expires < jiffies + 5)
+           time_before(timer_table[FLOPPY_TIMER].expires, jiffies + 5))
                /* If the check for a disk change is done too early after this
                 * last seek command, the WP bit still reads wrong :-((
                 */
                timer_table[FLOPPY_TIMER].expires = jiffies + 5;
        else
-               START_CHECK_CHANGE_TIMER( CHECK_CHANGE_DELAY );
-       del_timer( &motor_off_timer );
-       START_MOTOR_OFF_TIMER( FD_MOTOR_OFF_DELAY );
+               start_check_change_timer();
+       start_motor_off_timer();
 
        save_flags(flags);
        cli();
@@ -1828,10 +1816,10 @@ static int __init fd_test_drive_present( int drive )
        FDC_WRITE (FDCREG_TRACK, 0xff00);
        FDC_WRITE( FDCREG_CMD, FDCCMD_RESTORE | FDCCMDADD_H | FDCSTEP_6 );
 
-       for( ok = 0, timeout = jiffies + 2*HZ+HZ/2; time_before(jiffies, timeout); ) {
+       timeout = jiffies + 2*HZ+HZ/2;
+       while (time_before(jiffies, timeout))
                if (!(mfp.par_dt_reg & 0x20))
                        break;
-       }
 
        status = FDC_READ( FDCREG_STATUS );
        ok = (status & FDCSTAT_TR00) != 0;
@@ -1892,9 +1880,9 @@ static void __init config_types( void )
        }
        
        if (cnt > 0) {
-               START_MOTOR_OFF_TIMER( FD_MOTOR_OFF_DELAY );
+               start_motor_off_timer();
                if (cnt == 1) fd_select_drive( 0 );
-               START_CHECK_CHANGE_TIMER( CHECK_CHANGE_DELAY );
+               start_check_change_timer();
        }
 }
 
@@ -2045,8 +2033,8 @@ int __init atari_floppy_init (void)
                return -ENOMEM;
        }
        TrackBuffer = DMABuffer + 512;
-       PhysDMABuffer = (unsigned long) VTOP(DMABuffer);
-       PhysTrackBuffer = (unsigned long) VTOP(TrackBuffer);
+       PhysDMABuffer = virt_to_phys(DMABuffer);
+       PhysTrackBuffer = virt_to_phys(TrackBuffer);
        BufferDrive = BufferSide = BufferTrack = -1;
 
        for (i = 0; i < FD_MAX_UNITS; i++) {
index c40a5b2f6721355a70f58a1831891620ffb9ef63..020f94a445f7a3c6c3a80c62de9d5a45c2b44057 100644 (file)
@@ -2080,6 +2080,9 @@ static int ide_cdrom_packet(struct cdrom_device_info *cdi,
        struct packet_command pc;
        ide_drive_t *drive = (ide_drive_t*) cdi->handle;
 
+       /* here we queue the commands from the uniform CD-ROM
+          layer. the packet must be complete, as we do not
+          touch it at all. */
        memset(&pc, 0, sizeof(pc));
        memcpy(pc.c, cgc->cmd, CDROM_PACKET_SIZE);
        pc.buffer = cgc->buffer;
index 1dc68faeef7510d9d3203a9ccfbbea1416759b90..cfca595920f7d4acdc91dc29ceb20448f7d68ece 100644 (file)
@@ -252,7 +252,7 @@ static byte hpt363_shared_irq = 0;
  * settings of split-mirror pci-config space, place chipset into init-mode,
  * and/or preserve an interrupt if the card is not native ide support.
  */
-__initfunc(static unsigned int ide_special_settings (struct pci_dev *dev, const char *name))
+static unsigned int __init ide_special_settings (struct pci_dev *dev, const char *name)
 {
        switch(dev->device) {
                case PCI_DEVICE_ID_TTI_HPT343:
@@ -300,7 +300,7 @@ __initfunc(static unsigned int ide_special_settings (struct pci_dev *dev, const
  * Match a PCI IDE port against an entry in ide_hwifs[],
  * based on io_base port if possible.
  */
-__initfunc(static ide_hwif_t *ide_match_hwif (unsigned long io_base, byte bootable, const char *name))
+static ide_hwif_t __init *ide_match_hwif (unsigned long io_base, byte bootable, const char *name)
 {
        int h;
        ide_hwif_t *hwif;
@@ -362,7 +362,7 @@ __initfunc(static ide_hwif_t *ide_match_hwif (unsigned long io_base, byte bootab
        return NULL;
 }
 
-__initfunc(static int ide_setup_pci_baseregs (struct pci_dev *dev, const char *name))
+static int __init ide_setup_pci_baseregs (struct pci_dev *dev, const char *name)
 {
        byte reg, progif = 0;
 
@@ -406,7 +406,7 @@ __initfunc(static int ide_setup_pci_baseregs (struct pci_dev *dev, const char *n
  * we "know" about, this information is in the ide_pci_device_t struct;
  * for all other chipsets, we just assume both interfaces are enabled.
  */
-__initfunc(static void ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d))
+static void __init ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d)
 {
        unsigned int port, at_least_one_hwif_enabled = 0, autodma = 0, pciirq = 0;
        unsigned short pcicmd = 0, tried_config = 0;
@@ -621,7 +621,7 @@ __initfunc(static void hpt366_device_order_fixup (struct pci_dev *dev, ide_pci_d
  * ide_scan_pcibus() gets invoked at boot time from ide.c.
  * It finds all PCI IDE controllers and calls ide_setup_pci_device for them.
  */
-__initfunc(void ide_scan_pcibus (void))
+void __init ide_scan_pcibus (void)
 {
        struct pci_dev          *dev;
        ide_pci_devid_t         devid;
index c370c2dafcd12d1035665cf0dff04f0cacdfeb7d..a6e1f76264d950c94673d8dcf573415c85981105 100644 (file)
@@ -230,8 +230,8 @@ __initfunc(void pmac_ide_probe(void))
 
 #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
 
-__initfunc(static void
-pmac_ide_setup_dma(struct device_node *np, ide_hwif_t *hwif))
+static void __init 
+pmac_ide_setup_dma(struct device_node *np, ide_hwif_t *hwif)
 {
        hwif->dma_base = (unsigned long) ioremap(np->addrs[1].address, 0x200);
 
index 650594771b4676810222f7d3839528f7ea11a213..7b0df6e31de46fe33920cb03ffef6f584c554ee7 100644 (file)
@@ -2553,7 +2553,7 @@ char *ide_xfer_verbose (byte xfer_rate) {
  * stridx() returns the offset of c within s,
  * or -1 if c is '\0' or not found within s.
  */
-__initfunc(static int stridx (const char *s, char c))
+static int __init stridx (const char *s, char c)
 {
        char *i = strchr(s, c);
        return (i && c) ? i - s : -1;
@@ -2571,7 +2571,7 @@ __initfunc(static int stridx (const char *s, char c))
  *     and base16 is allowed when prefixed with "0x".
  * 4. otherwise, zero is returned.
  */
-__initfunc(static int match_parm (char *s, const char *keywords[], int vals[], int max_vals))
+static int __init match_parm (char *s, const char *keywords[], int vals[], int max_vals)
 {
        static const char *decimal = "0123456789";
        static const char *hex = "0123456789abcdef";
@@ -2701,8 +2701,9 @@ __initfunc(static int match_parm (char *s, const char *keywords[], int vals[], i
  * "ide0=ali14xx"      : probe/support ali14xx chipsets (ALI M1439, M1443, M1445)
  * "ide0=umc8672"      : probe/support umc8672 chipsets
  * "idex=dc4030"       : probe/support Promise DC4030VL interface
+ * "ide=doubler"       : probe/support IDE doublers on Amiga
  */
-__initfunc(void ide_setup (char *s))
+void __init ide_setup (char *s)
 {
        int i, vals[3];
        ide_hwif_t *hwif;
@@ -3128,7 +3129,7 @@ int ide_xlate_1024 (kdev_t i_rdev, int xparm, const char *msg)
 /*
  * probe_for_hwifs() finds/initializes "known" IDE interfaces
  */
-__initfunc(static void probe_for_hwifs (void))
+static void __init probe_for_hwifs (void)
 {
 #ifdef CONFIG_PCI
        if (pci_present())
@@ -3202,7 +3203,7 @@ __initfunc(static void probe_for_hwifs (void))
 #endif /* CONFIG_BLK_DEV_BUDDHA */
 }
 
-__initfunc(void ide_init_builtin_drivers (void))
+void __init ide_init_builtin_drivers (void)
 {
        /*
         * Probe for special PCI and other "known" interface chipsets
@@ -3523,7 +3524,7 @@ EXPORT_SYMBOL(ide_setup_ports);
 /*
  * This is gets invoked once during initialization, to set *everything* up
  */
-__initfunc(int ide_init (void))
+int __init ide_init (void)
 {
        static char banner_printed = 0;
 
@@ -3545,7 +3546,7 @@ __initfunc(int ide_init (void))
 char *options = NULL;
 MODULE_PARM(options,"s");
 
-__initfunc(static void parse_options (char *line))
+static void __init parse_options (char *line)
 {
        char *next = line;
 
index b6f72fd6a038fbf46fe733cc12526917865bc8a9..3993417d077f1f7a4134b63aa63a0fb1c6d39d62 100644 (file)
@@ -184,7 +184,7 @@ static struct md_personality linear_personality=
 
 #ifndef MODULE
 
-__initfunc(void linear_init (void))
+void __init linear_init (void)
 {
   register_md_personality (LINEAR, &linear_personality);
 }
index be51cd8da00118734250fdfac5bd29bd398c11ee..3f39f847fe927438201dd338036516d3613436a7 100644 (file)
@@ -286,7 +286,7 @@ static inline void drive_stat_acct(int cmd, unsigned long nr_sectors,
  * with the request-lists in peace. Thus it should be called with no spinlocks
  * held.
  *
- * By this point, req->cmd is always either READ/WRITE, never READA/WRITEA,
+ * By this point, req->cmd is always either READ/WRITE, never READA,
  * which is important for drive_stat_acct() above.
  */
 
@@ -417,7 +417,7 @@ void make_request(int major,int rw, struct buffer_head * bh)
                }
        }
 
-       rw_ahead = 0;   /* normal case; gets changed below for READA/WRITEA */
+       rw_ahead = 0;   /* normal case; gets changed below for READA */
        switch (rw) {
                case READA:
                        rw_ahead = 1;
@@ -431,9 +431,6 @@ void make_request(int major,int rw, struct buffer_head * bh)
                case WRITERAW:
                        rw = WRITE;
                        goto do_write;  /* Skip the buffer refile */
-               case WRITEA:
-                       rw_ahead = 1;
-                       rw = WRITE;     /* drop into WRITE */
                case WRITE:
                        if (!test_and_clear_bit(BH_Dirty, &bh->b_state))
                                goto end_io;    /* Hmmph! Nothing to write */
@@ -598,13 +595,6 @@ void ll_rw_block(int rw, int nr, struct buffer_head * bh[])
        struct blk_dev_struct * dev;
        int i;
 
-       /* Make sure that the first block contains something reasonable */
-       while (!*bh) {
-               bh++;
-               if (--nr <= 0)
-                       return;
-       }
-
        dev = NULL;
        if ((major = MAJOR(bh[0]->b_dev)) < MAX_BLKDEV)
                dev = blk_dev + major;
@@ -654,26 +644,22 @@ void ll_rw_block(int rw, int nr, struct buffer_head * bh[])
        }
 
        for (i = 0; i < nr; i++) {
-               if (bh[i]) {
-                       set_bit(BH_Req, &bh[i]->b_state);
+               set_bit(BH_Req, &bh[i]->b_state);
 #ifdef CONFIG_BLK_DEV_MD
-                       if (MAJOR(bh[i]->b_dev) == MD_MAJOR) {
-                               md_make_request(MINOR (bh[i]->b_dev), rw, bh[i]);
-                               continue;
-                       }
-#endif
-                       make_request(MAJOR(bh[i]->b_rdev), rw, bh[i]);
+               if (MAJOR(bh[i]->b_dev) == MD_MAJOR) {
+                       md_make_request(MINOR (bh[i]->b_dev), rw, bh[i]);
+                       continue;
                }
+#endif
+               make_request(MAJOR(bh[i]->b_rdev), rw, bh[i]);
        }
        return;
 
       sorry:
        for (i = 0; i < nr; i++) {
-               if (bh[i]) {
-                       clear_bit(BH_Dirty, &bh[i]->b_state);
-                       clear_bit(BH_Uptodate, &bh[i]->b_state);
-                       bh[i]->b_end_io(bh[i], 0);
-               }
+               clear_bit(BH_Dirty, &bh[i]->b_state);
+               clear_bit(BH_Uptodate, &bh[i]->b_state);
+               bh[i]->b_end_io(bh[i], 0);
        }
        return;
 }
index bd610dc7b2a3d9c17386c3e47a002c23624a3d2a..66023e933b393d47fe90942b95104c9e518c1a76 100644 (file)
@@ -1174,7 +1174,7 @@ struct {
 };
 
 /* called from init/main.c */
-__initfunc(void md_setup(char *str,int *ints))
+void __init md_setup(char *str,int *ints)
 {
        int i;
        for(i=0;i<=ints[0];i++) {
@@ -1186,7 +1186,7 @@ __initfunc(void md_setup(char *str,int *ints))
        return;
 }
 
-__initfunc(void do_md_setup(char *str,int *ints))
+void __init do_md_setup(char *str,int *ints)
 {
        int minor, pers, factor, fault;
        kdev_t dev;
@@ -1265,7 +1265,7 @@ void raid0_init (void);
 void raid1_init (void);
 void raid5_init (void);
 
-__initfunc(int md_init (void))
+int __init md_init (void)
 {
   printk ("md driver %d.%d.%d MAX_MD_DEV=%d, MAX_REAL=%d\n",
     MD_MAJOR_VERSION, MD_MINOR_VERSION, MD_PATCHLEVEL_VERSION,
@@ -1306,7 +1306,7 @@ __initfunc(int md_init (void))
 }
 
 #ifdef CONFIG_MD_BOOT
-__initfunc(void md_setup_drive(void))
+void __init md_setup_drive(void)
 {
        if(md_setup_args.set)
                do_md_setup(md_setup_args.str, md_setup_args.ints);
index 9f4c1aa921157e8ed24443e80deb010bc7fc3087..3ab183d3164e52736df615c70ab89e08821e52b0 100644 (file)
@@ -102,7 +102,7 @@ static int ns87415_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
        }
 }
 
-__initfunc(void ide_init_ns87415 (ide_hwif_t *hwif))
+void __init ide_init_ns87415 (ide_hwif_t *hwif)
 {
        struct pci_dev *dev = hwif->pci_dev;
        unsigned int ctrl, using_inta;
index e1ff03e8ffb71af6198b03e74b3869ec5bbf0ac7..253b5ce1e3c36ae26b1024c222abf2211a1b132c 100644 (file)
@@ -178,7 +178,7 @@ static struct gendisk ps2esdi_gendisk =
 };
 
 /* initialization routine called by ll_rw_blk.c   */
-__initfunc(int ps2esdi_init(void))
+int __init ps2esdi_init(void)
 {
 
        /* register the device - pass the name, major number and operations
@@ -244,7 +244,7 @@ cleanup_module(void)
 #endif /* MODULE */
 
 /* handles boot time command line parameters */
-__initfunc(void tp720_setup(char *str, int *ints))
+void __init tp720_setup(char *str, int *ints)
 {
        /* no params, just sets the tp720esdi flag if it exists */
 
@@ -252,7 +252,7 @@ __initfunc(void tp720_setup(char *str, int *ints))
        tp720esdi = 1;
 }
 
-__initfunc(void ed_setup(char *str, int *ints))
+void __init ed_setup(char *str, int *ints)
 {
        int hdind = 0;
 
@@ -299,7 +299,7 @@ static int ps2esdi_getinfo(char *buf, int slot, void *d)
 }
 
 /* ps2 esdi specific initialization - called thru the gendisk chain */
-__initfunc(static void ps2esdi_geninit(struct gendisk *ignored))
+static void __init ps2esdi_geninit(struct gendisk *ignored)
 {
        /*
           The first part contains the initialization code
@@ -437,7 +437,7 @@ __initfunc(static void ps2esdi_geninit(struct gendisk *ignored))
 }                              /* ps2esdi_geninit */
 
 
-__initfunc(static void ps2esdi_get_device_cfg(void))
+static void __init ps2esdi_get_device_cfg(void)
 {
        u_short cmd_blk[TYPE_0_CMD_BLK_LENGTH];
 
diff --git a/drivers/block/q40ide.c b/drivers/block/q40ide.c
new file mode 100644 (file)
index 0000000..93d302a
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ *  linux/drivers/block/q40ide.c -- Q40 I/O port IDE Driver
+ *
+ *     original file created 12 Jul 1997 by Geert Uytterhoeven
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive for
+ *  more details.
+ *
+ * RZ:
+ *  almost identical with pcide.c, maybe we can merge it later. 
+ *  Differences:
+ *       max 2 HWIFS for now
+ *       translate portaddresses to q40 native addresses (not yet...) instead rely on in/out[bw]
+ *         address translation
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+
+#include "ide.h"
+
+    /*
+     *  Bases of the IDE interfaces
+     */
+
+#define PCIDE_NUM_HWIFS        2
+
+#define PCIDE_BASE1    0x1f0
+#define PCIDE_BASE2    0x170
+#define PCIDE_BASE3    0x1e8
+#define PCIDE_BASE4    0x168
+#define PCIDE_BASE5    0x1e0
+#define PCIDE_BASE6    0x160
+
+static const q40ide_ioreg_t pcide_bases[PCIDE_NUM_HWIFS] = {
+    PCIDE_BASE1, PCIDE_BASE2, /* PCIDE_BASE3, PCIDE_BASE4  , PCIDE_BASE5,
+    PCIDE_BASE6 */
+};
+
+
+    /*
+     *  Offsets from one of the above bases
+     */
+
+#undef HD_DATA
+#define HD_DATA  0x1f0
+
+#define PCIDE_REG(x)   ((q40ide_ioreg_t)(HD_##x-PCIDE_BASE1))
+
+static const int pcide_offsets[IDE_NR_PORTS] = {
+    PCIDE_REG(DATA), PCIDE_REG(ERROR), PCIDE_REG(NSECTOR), PCIDE_REG(SECTOR),
+    PCIDE_REG(LCYL), PCIDE_REG(HCYL), PCIDE_REG(CURRENT), PCIDE_REG(STATUS),
+    PCIDE_REG(CMD)
+};
+
+int q40ide_default_irq(q40ide_ioreg_t base)
+{
+           switch (base) { 
+                   case 0x1f0: return 14;
+                   case 0x170: return 15;
+                   case 0x1e8: return 11;
+                   default:
+                       return 0;
+          }
+}
+
+void q40_ide_init_hwif_ports (q40ide_ioreg_t *p, q40ide_ioreg_t base, int *irq)
+{
+       q40ide_ioreg_t port = base;
+       int i = 8;
+
+       while (i--)
+               *p++ = port++;
+       *p++ = base + 0x206;
+       if (irq != NULL)
+               *irq = 0;
+}
+
+
+    /*
+     *  Probe for PC IDE interfaces
+     */
+
+int q40ide_probe_hwif(int index, ide_hwif_t *hwif)
+{
+    static int pcide_index[PCIDE_NUM_HWIFS] = { 0, };
+    int i;
+
+    if (!MACH_IS_Q40)
+      return 0;
+
+    for (i = 0; i < PCIDE_NUM_HWIFS; i++) {
+       if (!pcide_index[i]) {
+         /*printk("ide%d: Q40 IDE interface\n", index);*/
+           pcide_index[i] = index+1;
+       }
+       if (pcide_index[i] == index+1) {
+           ide_setup_ports(hwif,(ide_ioreg_t) pcide_bases[i], pcide_offsets, 0, /*q40_ack_intr???*/ NULL);
+           hwif->irq = ide_default_irq((ide_ioreg_t)pcide_bases[i]); /*q40_ide_irq[i];  */ /* 14 */
+           return 1;
+       }
+    }
+    return 0;
+}
index 116994416bb444a7ef7d1fa138cfc26704e07be3..bdf681ccc81046c0332b6de8ecb6a6badce43981 100644 (file)
@@ -343,7 +343,7 @@ static struct file_operations fd_fops = {
 };
 
 /* This is the registration and initialization section of the RAM disk driver */
-__initfunc(int rd_init(void))
+int __init rd_init(void)
 {
        int             i;
 
@@ -416,8 +416,8 @@ void cleanup_module(void)
  *     romfs
  *     gzip
  */
-__initfunc(int
-identify_ramdisk_image(kdev_t device, struct file *fp, int start_block))
+int __init 
+identify_ramdisk_image(kdev_t device, struct file *fp, int start_block)
 {
        const int size = 512;
        struct minix_super_block *minixsb;
@@ -509,7 +509,7 @@ done:
 /*
  * This routine loads in the RAM disk image.
  */
-__initfunc(static void rd_load_image(kdev_t device, int offset, int unit))
+static void __init rd_load_image(kdev_t device, int offset, int unit)
 {
        struct inode inode, out_inode;
        struct file infile, outfile;
@@ -631,7 +631,7 @@ done:
 }
 
 
-__initfunc(static void rd_load_disk(int n))
+static void __init rd_load_disk(int n)
 {
 #ifdef CONFIG_BLK_DEV_INITRD
        extern kdev_t real_root_dev;
@@ -660,18 +660,18 @@ __initfunc(static void rd_load_disk(int n))
 
 }
 
-__initfunc(void rd_load(void))
+void __init rd_load(void)
 {
        rd_load_disk(0);
 }
 
-__initfunc(void rd_load_secondary(void))
+void __init rd_load_secondary(void)
 {
        rd_load_disk(1);
 }
 
 #ifdef CONFIG_BLK_DEV_INITRD
-__initfunc(void initrd_load(void))
+void __init initrd_load(void)
 {
        rd_load_image(MKDEV(MAJOR_NR, INITRD_MINOR),rd_image_start,0);
 }
@@ -730,21 +730,21 @@ static void gzip_release(void **);
 
 #include "../../lib/inflate.c"
 
-__initfunc(static void *malloc(int size))
+static void __init *malloc(int size)
 {
        return kmalloc(size, GFP_KERNEL);
 }
 
-__initfunc(static void free(void *where))
+static void __init free(void *where)
 {
        kfree(where);
 }
 
-__initfunc(static void gzip_mark(void **ptr))
+static void __init gzip_mark(void **ptr)
 {
 }
 
-__initfunc(static void gzip_release(void **ptr))
+static void __init gzip_release(void **ptr)
 {
 }
 
@@ -753,7 +753,7 @@ __initfunc(static void gzip_release(void **ptr))
  * Fill the input buffer. This is called only when the buffer is empty
  * and at least one byte is really needed.
  */
-__initfunc(static int fill_inbuf(void))
+static int __init fill_inbuf(void)
 {
        if (exit_code) return -1;
        
@@ -770,7 +770,7 @@ __initfunc(static int fill_inbuf(void))
  * Write the output window window[0..outcnt-1] and update crc and bytes_out.
  * (Used for the decompressed data only.)
  */
-__initfunc(static void flush_window(void))
+static void __init flush_window(void)
 {
     ulg c = crc;         /* temporary variable */
     unsigned n;
@@ -787,14 +787,14 @@ __initfunc(static void flush_window(void))
     outcnt = 0;
 }
 
-__initfunc(static void error(char *x))
+static void __init error(char *x)
 {
        printk(KERN_ERR "%s", x);
        exit_code = 1;
 }
 
-__initfunc(static int
-crd_load(struct file * fp, struct file *outfp))
+static int __init 
+crd_load(struct file * fp, struct file *outfp)
 {
        int result;
 
index ae8749813248d3f8ac3478c5515741926bb136a8..30edea88779a216c294548ffb86b38ed0ab8db44 100644 (file)
@@ -33,7 +33,7 @@
 
 #ifdef CONFIG_BLK_DEV_IDEPCI
 
-__initfunc(void ide_init_rz1000 (ide_hwif_t *hwif))    /* called from ide-pci.c */
+void __init ide_init_rz1000 (ide_hwif_t *hwif) /* called from ide-pci.c */
 {
        unsigned short reg;
        struct pci_dev *dev = hwif->pci_dev;
@@ -53,7 +53,7 @@ __initfunc(void ide_init_rz1000 (ide_hwif_t *hwif))   /* called from ide-pci.c */
 
 #else
 
-__initfunc(static void init_rz1000 (struct pci_dev *dev, const char *name))
+static void __init init_rz1000 (struct pci_dev *dev, const char *name)
 {
        unsigned short reg, h;
 
@@ -83,7 +83,7 @@ __initfunc(static void init_rz1000 (struct pci_dev *dev, const char *name))
        }
 }
 
-__initfunc(void ide_probe_for_rz100x (void))   /* called from ide.c */
+void __init ide_probe_for_rz100x (void)        /* called from ide.c */
 {
        struct pci_dev *dev = NULL;
 
index 8476a8088d9aa7d348a69eead5fb67dcaa867b8b..1964b2cf603ca46d95a024bdb9386774a4999caa 100644 (file)
@@ -212,7 +212,7 @@ static int trm290_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
 /*
  * Invoked from ide-dma.c at boot time.
  */
-__initfunc(void ide_init_trm290 (ide_hwif_t *hwif))
+void __init ide_init_trm290 (ide_hwif_t *hwif)
 {
        unsigned int cfgbase = 0;
        unsigned long flags;
index 04c88fb08a1e442279fc9378db1298d1ba5c2668..523207d5d046869895a9dcc903246d57463bc1c5 100644 (file)
@@ -179,7 +179,7 @@ static volatile u_char xd_error;
 static int nodma = XD_DONT_USE_DMA;
 
 /* xd_init: register the block device number and set up pointer tables */
-__initfunc(int xd_init (void))
+int __init xd_init (void)
 {
        if (register_blkdev(MAJOR_NR,"xd",&xd_fops)) {
                printk("xd: Unable to get major number %d\n",MAJOR_NR);
@@ -194,7 +194,7 @@ __initfunc(int xd_init (void))
 }
 
 /* xd_detect: scan the possible BIOS ROM locations for the signature strings */
-__initfunc(static u_char xd_detect (u_char *controller, unsigned int *address))
+static __init u_char xd_detect (u_char *controller, unsigned int *address)
 {
        u_char i,j,found = 0;
 
@@ -218,7 +218,7 @@ __initfunc(static u_char xd_detect (u_char *controller, unsigned int *address))
 
 /* xd_geninit: grab the IRQ and DMA channel, initialise the drives */
 /* and set up the "raw" device entries in the table */
-__initfunc(static void xd_geninit (struct gendisk *ignored))
+static void __init xd_geninit (struct gendisk *ignored)
 {
        u_char i,controller;
        unsigned int address;
@@ -686,7 +686,7 @@ static u_int xd_command (u_char *command,u_char mode,u_char *indata,u_char *outd
        return (csb & CSB_ERROR);
 }
 
-__initfunc(static u_char xd_initdrives (void (*init_drive)(u_char drive)))
+static u_char __init xd_initdrives (void (*init_drive)(u_char drive))
 {
        u_char cmdblk[6],i,count = 0;
 
@@ -708,14 +708,14 @@ __initfunc(static u_char xd_initdrives (void (*init_drive)(u_char drive)))
        return (count);
 }
 
-__initfunc(static void xd_manual_geo_set (u_char drive))
+static void __init xd_manual_geo_set (u_char drive)
 {
        xd_info[drive].heads = (u_char)(xd_geo[3 * drive + 1]);
        xd_info[drive].cylinders = (u_short)(xd_geo[3 * drive]);
        xd_info[drive].sectors = (u_char)(xd_geo[3 * drive + 2]);
 }
 
-__initfunc(static void xd_dtc_init_controller (unsigned int address))
+static void __init xd_dtc_init_controller (unsigned int address)
 {
        switch (address) {
                case 0x00000:
@@ -732,7 +732,7 @@ __initfunc(static void xd_dtc_init_controller (unsigned int address))
 }
 
 
-__initfunc(static void xd_dtc5150cx_init_drive (u_char drive))
+static void __init xd_dtc5150cx_init_drive (u_char drive)
 {
        /* values from controller's BIOS - BIOS chip may be removed */
        static u_short geometry_table[][4] = {
@@ -779,7 +779,7 @@ __initfunc(static void xd_dtc5150cx_init_drive (u_char drive))
        xd_recalibrate(drive);
 }
 
-__initfunc(static void xd_dtc_init_drive (u_char drive))
+static void __init xd_dtc_init_drive (u_char drive)
 {
        u_char cmdblk[6],buf[64];
 
@@ -806,7 +806,7 @@ __initfunc(static void xd_dtc_init_drive (u_char drive))
                printk("xd_dtc_init_drive: error reading geometry for xd%c\n", 'a'+drive);
 }
 
-__initfunc(static void xd_wd_init_controller (unsigned int address))
+static void __init xd_wd_init_controller (unsigned int address)
 {
        switch (address) {
                case 0x00000:
@@ -828,7 +828,7 @@ __initfunc(static void xd_wd_init_controller (unsigned int address))
        sleep_on(&xdc_wait);
 }
 
-__initfunc(static void xd_wd_init_drive (u_char drive))
+static void __init xd_wd_init_drive (u_char drive)
 {
        /* values from controller's BIOS - BIOS may be disabled */
        static u_short geometry_table[][4] = {
@@ -912,7 +912,7 @@ __initfunc(static void xd_wd_init_drive (u_char drive))
 
 }
 
-__initfunc(static void xd_seagate_init_controller (unsigned int address))
+static void __init xd_seagate_init_controller (unsigned int address)
 {
        switch (address) {
                case 0x00000:
@@ -928,7 +928,7 @@ __initfunc(static void xd_seagate_init_controller (unsigned int address))
        outb(0,XD_RESET);               /* reset the controller */
 }
 
-__initfunc(static void xd_seagate_init_drive (u_char drive))
+static void __init xd_seagate_init_drive (u_char drive)
 {
        u_char cmdblk[6],buf[0x200];
 
@@ -944,7 +944,7 @@ __initfunc(static void xd_seagate_init_drive (u_char drive))
 }
 
 /* Omti support courtesy Dirk Melchers */
-__initfunc(static void xd_omti_init_controller (unsigned int address))
+static void __init xd_omti_init_controller (unsigned int address)
 {
        switch (address) {
                case 0x00000:
@@ -961,7 +961,7 @@ __initfunc(static void xd_omti_init_controller (unsigned int address))
        outb(0,XD_RESET);               /* reset the controller */
 }
 
-__initfunc(static void xd_omti_init_drive (u_char drive))
+static void __init xd_omti_init_drive (u_char drive)
 {
        /* gets infos from drive */
        xd_override_init_drive(drive);
@@ -971,7 +971,7 @@ __initfunc(static void xd_omti_init_drive (u_char drive))
 }
 
 /* Xebec support (AK) */
-__initfunc(static void xd_xebec_init_controller (unsigned int address))
+static void __init xd_xebec_init_controller (unsigned int address)
 {
 /* iobase may be set manually in range 0x300 - 0x33C
       irq may be set manually to 2(9),3,4,5,6,7
@@ -1004,7 +1004,7 @@ If you need non-standard settings use the xd=... command */
        sleep_on(&xdc_wait);
 }
 
-__initfunc(static void xd_xebec_init_drive (u_char drive))
+static void __init xd_xebec_init_drive (u_char drive)
 {
        /* values from controller's BIOS - BIOS chip may be removed */
        static u_short geometry_table[][5] = {
@@ -1047,7 +1047,7 @@ __initfunc(static void xd_xebec_init_drive (u_char drive))
 
 /* xd_override_init_drive: this finds disk geometry in a "binary search" style, narrowing in on the "correct" number of heads
    etc. by trying values until it gets the highest successful value. Idea courtesy Salvador Abreu (spa@fct.unl.pt). */
-__initfunc(static void xd_override_init_drive (u_char drive))
+static void __init xd_override_init_drive (u_char drive)
 {
        u_short min[] = { 0,0,0 },max[] = { 16,1024,64 },test[] = { 0,0,0 };
        u_char cmdblk[6],i;
@@ -1074,7 +1074,7 @@ __initfunc(static void xd_override_init_drive (u_char drive))
 }
 
 /* xd_setup: initialise controler from command line parameters */
-__initfunc(void xd_setup (char *command,int *integers))
+void __init xd_setup (char *command,int *integers)
 {
        switch (integers[0]) {
                case 4: if (integers[4] < 0)
@@ -1097,7 +1097,7 @@ __initfunc(void xd_setup (char *command,int *integers))
 #ifndef MODULE
 /* xd_manual_geo_init: initialise drive geometry from command line parameters
    (used only for WD drives) */
-__initfunc(void xd_manual_geo_init (char *command,int *integers))
+void __init xd_manual_geo_init (char *command,int *integers)
 {
        int i;
        if (integers[0]%3 != 0) {
@@ -1110,7 +1110,7 @@ __initfunc(void xd_manual_geo_init (char *command,int *integers))
 #endif /* MODULE */
 
 /* xd_setparam: set the drive characteristics */
-__initfunc(static void xd_setparam (u_char command,u_char drive,u_char heads,u_short cylinders,u_short rwrite,u_short wprecomp,u_char ecc))
+static void __init xd_setparam (u_char command,u_char drive,u_char heads,u_short cylinders,u_short rwrite,u_short wprecomp,u_char ecc)
 {
        u_char cmdblk[14];
 
index f863a8326fcdccaaff209b6d74b7664fe6625dd2..cf142b094150647d2143046b67bfad2838340947 100644 (file)
 #include <linux/malloc.h>
 #include <linux/blk.h>
 #include <linux/init.h>
-
-#if defined(MODULE)
 #include <linux/module.h>
-#endif
 
 #include <asm/setup.h>
 #include <asm/bitops.h>
 #include <asm/amigahw.h>
-#ifdef CONFIG_APUS
 #include <asm/pgtable.h>
 #include <asm/io.h>
-#endif
 #include <linux/zorro.h>
 
 
-extern int num_memory;
-extern struct mem_info memory[NUM_MEMINFO];
+extern int m68k_realnum_memory;
+extern struct mem_info m68k_memory[NUM_MEMINFO];
 
 #define TRUE                  (1)
 #define FALSE                 (0)
@@ -191,14 +186,14 @@ z2_open( struct inode *inode, struct file *filp )
                int index = device - Z2MINOR_MEMLIST1 + 1;
                unsigned long size, paddr, vaddr;
 
-               if (index >= num_memory) {
+               if (index >= m68k_realnum_memory) {
                        printk( KERN_ERR DEVICE_NAME
                                ": no such entry in z2ram_map\n" );
                        return -ENOMEM;
                }
 
-               paddr = memory[index].addr;
-               size = memory[index].size & ~(Z2RAM_CHUNKSIZE-1);
+               paddr = m68k_memory[index].addr;
+               size = m68k_memory[index].size & ~(Z2RAM_CHUNKSIZE-1);
 
 #ifdef __powerpc__
                /* FIXME: ioremap doesn't build correct memory tables. */
@@ -212,8 +207,7 @@ z2_open( struct inode *inode, struct file *filp )
                                                   _PAGE_WRITETHRU);
 
 #else
-               vaddr = kernel_map (paddr, size, KERNELMAP_FULL_CACHING,
-                                   NULL);
+               vaddr = (unsigned long)ioremap(paddr, size);
 #endif
                z2ram_map = 
                        kmalloc((size/Z2RAM_CHUNKSIZE)*sizeof(z2ram_map[0]),
@@ -316,9 +310,7 @@ z2_open( struct inode *inode, struct file *filp )
        blk_size[ MAJOR_NR ] = z2_sizes;
     }
 
-#if defined(MODULE)
     MOD_INC_USE_COUNT;
-#endif
 
     return 0;
 }
@@ -331,9 +323,11 @@ z2_release( struct inode *inode, struct file *filp )
 
     sync_dev( inode->i_rdev );
 
-#if defined(MODULE)
+    /*
+     * FIXME: unmap memory
+     */
+
     MOD_DEC_USE_COUNT;
-#endif
 
     return 0;
 }
@@ -356,8 +350,8 @@ static struct file_operations z2_fops =
        NULL,                   /* revalidate */
 };
 
-__initfunc(int
-z2_init( void ))
+int __init 
+z2_init( void )
 {
 
     if ( !MACH_IS_AMIGA )
index bbc4530202ae7744093d6a6b2f94dc0d36c8a2be..21c4cf6ab21550a5ba30a411d72430eb728a1f1f 100644 (file)
   correctly.
   -- Fix up ioctl handling so the device specific ones actually get
   called :).
+  
+  3.02 Aug 8, 1999 - Jens Axboe <axboe@image.dk>
+  -- Fixed volume control on SCSI drives (or others with longer audio
+  page).
+  -- Fixed a couple of DVD minors. Thanks to Andrew T. Veliath
+  <andrewtv@usa.net> for telling me and for having defined the various
+  DVD structures and ioctls in the first place! He designed the original
+  DVD patches for ide-cd and while I rearranged and unified them, the
+  interface is still the same.
 
 -------------------------------------------------------------------------*/
 
-#define REVISION "Revision: 3.01"
-#define VERSION "Id: cdrom.c 3.01 1999/08/06"
+#define REVISION "Revision: 3.02"
+#define VERSION "Id: cdrom.c 3.02 1999/08/08"
 
 /* I use an error-log mask to give fine grain control over the type of
    messages dumped to the system logs.  The available masks include: */
@@ -452,6 +461,9 @@ int open_for_data(struct cdrom_device_info * cdi)
         * for example, need bit CDO_CHECK_TYPE cleared! */
        if (tracks.data==0) {
                if (cdi->options & CDO_CHECK_TYPE) {
+                   /* give people a warning shot, now that CDO_CHECK_TYPE
+                      is the default case! */
+                   printk("cdrom: pid %d is buggy!\n", (unsigned int)current->pid);
                    cdinfo(CD_OPEN, "bummer. wrong media type.\n"); 
                    ret=-EMEDIUMTYPE;
                    goto clean_up_and_return;
@@ -804,7 +816,7 @@ static int dvd_do_auth (struct cdrom_device_info *cdi, dvd_authinfo *ai)
 
        case DVD_LU_SEND_ASF:
                cdinfo(CD_DO_IOCTL, "entering DVD_LU_SEND_ASF\n"); 
-               setup_report_key (&cgc, ai->lsasf.agid, 5);
+               setup_report_key (&cgc, ai->lsasf.asf, 5);
                cgc.buflen = cgc.cmd[9] = 8;
 
                rv = cdo->generic_packet(cdi, &cgc);
@@ -847,7 +859,7 @@ static int dvd_do_auth (struct cdrom_device_info *cdi, dvd_authinfo *ai)
        /* Misc */
        case DVD_INVALIDATE_AGID:
                cdinfo(CD_DO_IOCTL, "entering DVD_INVALIDATE_AGID\n"); 
-               setup_report_key (&cgc, ai->lsasf.agid, 0x3f);
+               setup_report_key (&cgc, ai->lsa.agid, 0x3f);
 
                rv = cdo->generic_packet(cdi, &cgc);
                if (rv)
@@ -1051,7 +1063,7 @@ static int cdrom_mode_sense(struct cdrom_device_info *cdi,
                            int page_code, int page_control)
 {
        struct cdrom_device_ops *cdo = cdi->ops;
-       
+
        memset(cgc->cmd, 0, sizeof(cgc->cmd));
 
        cgc->cmd[0] = 0x5a;             /* MODE_SENSE_10 */
@@ -1070,7 +1082,6 @@ static int cdrom_mode_select(struct cdrom_device_info *cdi,
        
        cgc->cmd[0] = 0x55;             /* MODE_SELECT_10 */
        cgc->cmd[1] = 0x10;             /* PF */
-       cgc->cmd[2] = 0x0e;             /* PF */
 
        /* generic_packet() wants the length as seen from the drive, i.e.
           it will transfer data _to_ us. The CD-ROM wants the absolute
@@ -1469,41 +1480,53 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
        case CDROMVOLREAD: {
                struct cdrom_volctrl volctrl;
                char buffer[32], mask[32];
+               unsigned short offset;
                cdinfo(CD_DO_IOCTL, "entering CDROMVOLUME\n");
 
                IOCTL_IN(arg, struct cdrom_volctrl, volctrl);
 
                cgc.buffer = buffer;
                cgc.buflen = 24;
-               rv = cdrom_mode_sense(cdi, &cgc, 0x0e, 0);
+               rv = cdrom_mode_sense(cdi, &cgc, 0xe, 0);
                if (rv) return rv;
                
+               /* some drives have longer pages, adjust and reread. */
+               if (buffer[1] > cgc.buflen) {
+                       cgc.buflen = buffer[1] + 2;
+                       rv = cdrom_mode_sense(cdi, &cgc, 0xe, 0);
+                       if (rv) return rv;
+               }
+               
+               /* get the offset from the length of the page. length
+                  is measure from byte 2 an on, thus the 14. */
+               offset = buffer[1] - 14;
+
                /* now we have the current volume settings. if it was only
                   a CDROMVOLREAD, return these values */
                if (cmd == CDROMVOLREAD) {
-                       volctrl.channel0 = buffer[17];
-                       volctrl.channel1 = buffer[19];
-                       volctrl.channel2 = buffer[21];
-                       volctrl.channel3 = buffer[23];
+                       volctrl.channel0 = buffer[offset+9];
+                       volctrl.channel1 = buffer[offset+11];
+                       volctrl.channel2 = buffer[offset+13];
+                       volctrl.channel3 = buffer[offset+15];
                        IOCTL_OUT(arg, struct cdrom_volctrl, volctrl);
                        return 0;
                }
                
                /* get the volume mask */
                cgc.buffer = mask;
-               rv = cdrom_mode_sense(cdi, &cgc, 0x0e, 1);
+               rv = cdrom_mode_sense(cdi, &cgc, 0xe, 1);
                if (rv) return rv;
 
-               buffer[17] = volctrl.channel0 & mask[17];
-               buffer[19] = volctrl.channel1 & mask[19];
-               buffer[21] = volctrl.channel2 & mask[21];
-               buffer[23] = volctrl.channel3 & mask[23];
+               buffer[offset+9] = volctrl.channel0 & mask[offset+9];
+               buffer[offset+11] = volctrl.channel1 & mask[offset+11];
+               buffer[offset+13] = volctrl.channel2 & mask[offset+13];
+               buffer[offset+15] = volctrl.channel3 & mask[offset+15];
 
                /* clear the first three */
                memset(buffer, 0, 3);
 
                /* set volume */
-               cgc.buflen = -24;
+               cgc.buflen = -cgc.buflen;
                cgc.buffer = buffer;
                return cdrom_mode_select(cdi, &cgc);
                }
@@ -1551,6 +1574,8 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
                }
 
        case CDROM_SEND_PACKET: {
+               if (!CDROM_CAN(CDC_GENERIC_PACKET))
+                       return -ENOSYS;
                cdinfo(CD_DO_IOCTL, "entering send_packet\n"); 
                IOCTL_IN(arg, struct cdrom_generic_command, cgc);
                cgc.buffer = kmalloc(cgc.buflen, GFP_KERNEL);
index d9ebd1084a3ceae95727edc215d6a2b706b9b97f..42e1ea7c85806f2752120f04366dd4f4159327f2 100644 (file)
@@ -257,7 +257,7 @@ static void keyboard_interrupt(int irq, void *dummy, struct pt_regs *fp)
            amikeyb_rep_timer.prev = amikeyb_rep_timer.next = NULL;
            add_timer(&amikeyb_rep_timer);
        }
-       handle_scancode(scancode, !break_flag);
+       handle_scancode(keycode, !break_flag);
     } else
        switch (keycode) {
            case 0x78:
@@ -341,8 +341,3 @@ int amiga_kbdrate( struct kbd_repeat *k )
     
     return( 0 );
 }
-
-/* for "kbd-reset" cmdline param */
-void __init amiga_kbd_reset_setup(char *str, int *ints)
-{
-}
index f0af759a11bc8bd95284f965712dc989e775ebd8..652d9f6b3f69faee6fdebc5969bd9ea48e31e626 100644 (file)
@@ -4874,9 +4874,9 @@ cy_detect_pci(void))
 
                 /* read PCI configuration area */
                cy_pci_irq = pdev->irq;
-               cy_pci_addr0 = pdev->base_address[0];
-               cy_pci_addr1 = pdev->base_address[1]
-               cy_pci_addr2 = pdev->base_address[2]
+               cy_pci_addr0 = pdev->resource[0].start;
+               cy_pci_addr1 = pdev->resource[1].start
+               cy_pci_addr2 = pdev->resource[2].start
                 pci_read_config_byte(pdev, PCI_REVISION_ID, &cyy_rev_id);
 
                device_id &= ~PCI_DEVICE_ID_MASK;
@@ -4891,10 +4891,8 @@ cy_detect_pci(void))
             printk("Cyclom-Y/PCI:found  winaddr=0x%lx ctladdr=0x%lx\n",
                (ulong)cy_pci_addr2, (ulong)cy_pci_addr0);
 #endif
-               cy_pci_addr0  &= PCI_BASE_ADDRESS_MEM_MASK;
-               cy_pci_addr2  &= PCI_BASE_ADDRESS_MEM_MASK;
 
-               if (cy_pci_addr2 & ~PCI_BASE_ADDRESS_IO_MASK) {
+               if (pdev->resource[2].flags & ~PCI_BASE_ADDRESS_IO_MASK) {
                    printk("  Warning: PCI I/O bit incorrectly set. "
                           "Ignoring it...\n");
                    cy_pci_addr2 &= PCI_BASE_ADDRESS_IO_MASK;
index eceb50f6ce78935db75a32f4f618468f738ffc01..97b237ca3628fcb37f7fca38d36658d0a04ba829 100644 (file)
@@ -55,7 +55,8 @@ static void debug_keyb_timer_handler(unsigned long ignored);
 static u_char debug_buf1[4096],debug_buf2[4096],*debug_buf=&debug_buf1[0];
 static u_char *shadow_buf=&debug_buf2[0];
 static short debug_buf_count=0;
-static int debug_buf_overrun=0,debug_timer_running=0,debug_buffer_updated=0;
+static int debug_buf_overrun=0,debug_timer_running=0;
+static unsigned long debug_buffer_updated=0;
 static struct timer_list debug_keyb_timer = { NULL, NULL, 0, 0,
                                                                                          debug_keyb_timer_handler };
 #endif
@@ -280,7 +281,7 @@ static void debug_keyb_timer_handler(unsigned long ignored) {
        u_char *swap;
        short length,i;
 
-       if((jiffies-debug_buffer_updated) > 100) {
+       if (time_after(jiffies, debug_buffer_updated + 100)) {
                save_flags(flags);
                cli();
                length=debug_buf_count;         
@@ -422,7 +423,7 @@ static void dn_keyb_process_key_event(unsigned char scancode) {
                        !(prev_scancode==DNKEY_CTRL || prev_scancode==DNKEY_LSHIFT ||
                        prev_scancode==DNKEY_RSHIFT || prev_scancode==DNKEY_REPT ||
                        prev_scancode==DNKEY_LALT || prev_scancode==DNKEY_RALT)) {
-                       if(jiffies-lastkeypress > DNKEY_REPEAT_DELAY) {
+                       if (time_after(jiffies, lastkeypress + DNKEY_REPEAT_DELAY)) {
                        /*      printk("handle_scancode: %02x\n",prev_scancode); */
                                handle_scancode(prev_scancode, 1);
                                }
@@ -491,8 +492,8 @@ static void dn_keyb_int(int irq, void *dummy, struct pt_regs *fp) {
                                debug_buf[debug_buf_count++]=data;
                                debug_buffer_updated=jiffies;   
                                if(!debug_timer_running) {
-                                       add_timer(&debug_keyb_timer);
                                        debug_keyb_timer.expires=jiffies+10;
+                                       add_timer(&debug_keyb_timer);
                                        debug_timer_running=1;
                                }
                        }
index 4df4a1e2b5b99c09cde0d595921c63869755bbc2..30a76a04ea6c2674dcf21ce88590f66ed194b2b1 100644 (file)
@@ -534,6 +534,8 @@ int __init dsp56k_init(void)
        dsp56k.in_use = 0;
 
        printk("DSP56k driver installed\n");
+
+       return 0;
 }
 
 #ifdef MODULE
index 16cba83417a8c2d5e993721a97cceecdf0b495d6..8119a5721c69c332e794d32748723daede09cd85 100644 (file)
@@ -2002,7 +2002,7 @@ int init_module(void)
                                        break;
                                        
                                /* found a PCI ISI card! */
-                               ioaddr = dev->base_address[3]; /* i.e at offset 0x1c in the
+                               ioaddr = dev->resource[3].start; /* i.e at offset 0x1c in the
                                                                * PCI configuration register
                                                                * space.
                                                                */
index b689bb7a58bc0b07d24ad42402af6468c8034c2d..024c839a6e245b200b4007b13dcce480877c1b63 100644 (file)
@@ -4387,7 +4387,7 @@ stli_donestartup:
  *     Probe and initialize the specified board.
  */
 
-__initfunc(static int stli_brdinit(stlibrd_t *brdp))
+static int __init stli_brdinit(stlibrd_t *brdp)
 {
 #if DEBUG
        printk("stli_brdinit(brdp=%x)\n", (int) brdp);
@@ -5305,7 +5305,7 @@ static int stli_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, un
 
 /*****************************************************************************/
 
-__initfunc(int stli_init(void))
+int __init stli_init(void)
 {
        printk(KERN_INFO "%s: version %s\n", stli_drvtitle, stli_drvversion);
 
index bc69e26058b0a08a6c633f2422b73fc257a21de3..4092d6b5589470ddd331963e90c1f4dc263b6449 100644 (file)
@@ -711,7 +711,7 @@ static int reset = 0;
 
 static int parport_ptr = 0;
 
-__initfunc(void lp_setup(char *str, int *ints))
+void __init lp_setup(char *str, int *ints)
 {
        if (!str) {
                if (ints[0] == 0 || ints[1] == 0) {
index e4fc30403f0df5e19c279e0aaafd41cc5f1fc499..b65d51118925bea565d20136c8085548924182bf 100644 (file)
@@ -219,7 +219,7 @@ static struct lp_struct tab = {
        NULL,
 };
 
-__initfunc(int lp_internal_init(void))
+int __init lp_internal_init(void)
 {
 #ifdef CONFIG_AMIGA
   if (MACH_IS_AMIGA && AMIGAHW_PRESENT(AMI_PARALLEL))
index 7eecf29659bec8317b6515d0c1e0d49927e1f9ff..b16de36c51c39808a7a3150d57e3d8d70226092e 100644 (file)
@@ -474,7 +474,7 @@ EXPORT_SYMBOL(lp_interrupt);
 EXPORT_SYMBOL(register_parallel);
 EXPORT_SYMBOL(unregister_parallel);
 
-__initfunc(int lp_m68k_init(void))
+int __init lp_m68k_init(void)
 {
        extern char m68k_debug_device[];
 
@@ -507,7 +507,7 @@ __initfunc(int lp_m68k_init(void))
 /*
  * Currently we do not accept any lp-parameters, but that may change.
  */
-__initfunc(void lp_setup(char *str, int *ints))
+void __init lp_setup(char *str, int *ints)
 {      
 }
 
diff --git a/drivers/char/macmouse.c b/drivers/char/macmouse.c
deleted file mode 100644 (file)
index 53a579f..0000000
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * Macintosh ADB Mouse driver for Linux
- *
- * 27 Oct 1997 Michael Schmitz
- *
- * Apple mouse protocol according to:
- *
- * Device code shamelessly stolen from:
- */
-/*
- * Atari Mouse Driver for Linux
- * by Robert de Vries (robert@and.nl) 19Jul93
- *
- * 16 Nov 1994 Andreas Schwab
- * Compatibility with busmouse
- * Support for three button mouse (shamelessly stolen from MiNT)
- * third button wired to one of the joystick directions on joystick 1
- *
- * 1996/02/11 Andreas Schwab
- * Module support
- * Allow multiple open's
- *
- * Converted to use new generic busmouse code.  5 Apr 1998
- *   Russell King <rmk@arm.uk.linux.org>
- */
-
-#include <linux/module.h>
-
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/miscdevice.h>
-#include <linux/mm.h>
-#include <linux/random.h>
-#include <linux/poll.h>
-#include <linux/init.h>
-
-#include <asm/setup.h>
-#include <asm/mac_mouse.h>
-#include <asm/segment.h>
-#include <asm/uaccess.h>
-
-#include "busmouse.h"
-
-static int msedev;
-static int mac_mouse_x_threshold = 2, mac_mouse_y_threshold = 2;
-static int mac_mouse_buttons = 0;
-
-extern void (*mac_mouse_interrupt_hook) (char *, int);
-extern int mac_emulate_button2;
-extern int mac_emulate_button3;
-
-extern int console_loglevel;
-
-/*
- *     XXX: need to figure out what ADB mouse packets mean ... 
- *     This is the stuff stolen from the Atari driver ...
- */
-static void mac_mouse_interrupt(char *buf, int nb)
-{
-    static int buttons = 7;    /* all mouse buttons _up_ !! */
-
-  /*
-    Handler 1 -- 100cpi original Apple mouse protocol.
-    Handler 2 -- 200cpi original Apple mouse protocol.
-
-    For Apple's standard one-button mouse protocol the data array will
-    contain the following values:
-
-                BITS    COMMENTS
-    data[0] = 0000 0000 ADB packet identifer.
-    data[1] = ???? ???? (?)
-    data[2] = ???? ??00 Bits 0-1 should be zero for a mouse device.
-    data[3] = bxxx xxxx First button and x-axis motion.
-    data[4] = byyy yyyy Second button and y-axis motion.
-
-    NOTE: data[0] is confirmed by the parent function and need not be
-    checked here.
-  */
-
-  /*
-    Handler 4 -- Apple Extended mouse protocol.
-
-    For Apple's 3-button mouse protocol the data array will contain the
-    following values:
-
-               BITS    COMMENTS
-    data[0] = 0000 0000 ADB packet identifer.
-    data[1] = 0100 0000 Extended protocol register.
-             Bits 6-7 are the device id, which should be 1.
-             Bits 4-5 are resolution which is in "units/inch".
-             The Logitech MouseMan returns these bits clear but it has
-             200/300cpi resolution.
-             Bits 0-3 are unique vendor id.
-    data[2] = 0011 1100 Bits 0-1 should be zero for a mouse device.
-             Bits 2-3 should be 8 + 4.
-                     Bits 4-7 should be 3 for a mouse device.
-    data[3] = bxxx xxxx Left button and x-axis motion.
-    data[4] = byyy yyyy Second button and y-axis motion.
-    data[5] = byyy bxxx Third button and fourth button.  
-             Y is additiona. high bits of y-axis motion.  
-             X is additional high bits of x-axis motion.
-
-    NOTE: data[0] and data[2] are confirmed by the parent function and
-    need not be checked here.
-  */
-
-    /*
-     * 'buttons' here means 'button down' states!
-     * Button 1 (left)  : bit 2, busmouse button 3
-     * Button 2 (right) : bit 0, busmouse button 1
-     * Button 3 (middle): bit 1, busmouse button 2
-     */
-
-    /* x/y and buttons swapped */
-    
-    if (buf[0] ==  0)  {                               /* real packet : use buttons? */
-#ifdef DEBUG_ADBMOUSE
-       if (console_loglevel >= 8)
-           printk("mac_mouse: real data; "); 
-#endif
-       /* button 1 (left, bit 2) : always significant ! */
-       buttons = (buttons&3) | (buf[3] & 0x80 ? 4 : 0); /* 1+2 unchanged */
-       /* button 2 (right, bit 0) present ? */
-       if ( !mac_emulate_button2 ) 
-           buttons = (buttons&6) | (buf[4] & 0x80 ? 1 : 0); /* 2+3 unchanged */
-       /* button 2 (middle) present? */
-       /* data valid only if extended mouse format ! (buf[3] = 0 else)*/
-       if ( !mac_emulate_button3 && buf[1]&0x40 )
-           buttons = (buttons&5) | (buf[5] & 0x80 ? 2 : 0); /* 1+3 unchanged */
-    } else {                                   /* fake packet : use 2+3 */
-#ifdef DEBUG_ADBMOUSE
-       if (console_loglevel >= 8)
-           printk("mac_mouse: fake data; "); 
-#endif
-       /* we only see state changes here, but the fake driver takes care
-        * to preserve state... button 1 state must stay unchanged! */
-       buttons = (buttons&4) | ((buf[4] & 0x80 ? 1 : 0) | (buf[5] & 0x80 ? 2 : 0));
-    }
-
-    busmouse_add_movementbuttons(msedev,
-                                ((buf[4]&0x7f) < 64 ? (buf[4]&0x7f) : (buf[4]&0x7f)-128 ),
-                                -((buf[3]&0x7f) < 64 ? (buf[3]&0x7f) : (buf[3]&0x7f)-128 ),
-                                buttons & 7);
-}
-
-static int release_mouse(struct inode *inode, struct file *file)
-{
-    mac_mouse_interrupt_hook = NULL;
-    MOD_DEC_USE_COUNT;
-    return 0;
-}
-
-static int open_mouse(struct inode *inode, struct file *file)
-{
-    MOD_INC_USE_COUNT;
-    mac_mouse_interrupt_hook = mac_mouse_interrupt;
-    return 0;
-}
-
-#define ADB_MOUSE_MINOR        10
-
-static struct busmouse macmouse = {
-       ADB_MOUSE_MINOR, "adbmouse", open_mouse, release_mouse, 0
-};
-
-__initfunc(int mac_mouse_init(void))
-{
-    if (!MACH_IS_MAC)
-       return -ENODEV;
-
-    msedev = register_busmouse(&macmouse);
-    if (msedev < 0)
-       printk(KERN_WARNING "Unable to register ADB mouse driver.\n");
-    else
-       printk(KERN_INFO "Macintosh ADB mouse installed.\n");
-    return msedev < 0 ? msedev : 0;
-}
-
-
-#define        MIN_THRESHOLD 1
-#define        MAX_THRESHOLD 20        /* more seems not reasonable... */
-
-__initfunc(void mac_mouse_setup(char *str, int *ints))
-{
-    if (ints[0] < 1) {
-       printk( "mac_mouse_setup: no arguments!\n" );
-       return;
-    }
-    else if (ints[0] > 2) {
-       printk( "mac_mouse_setup: too many arguments\n" );
-    }
-
-    if (ints[1] < MIN_THRESHOLD || ints[1] > MAX_THRESHOLD)
-       printk( "mac_mouse_setup: bad threshold value (ignored)\n" );
-    else {
-       mac_mouse_x_threshold = ints[1];
-       mac_mouse_y_threshold = ints[1];
-       if (ints[0] > 1) {
-           if (ints[2] < MIN_THRESHOLD || ints[2] > MAX_THRESHOLD)
-               printk("mac_mouse_setup: bad threshold value (ignored)\n" );
-           else
-               mac_mouse_y_threshold = ints[2];
-       }
-    }
-       
-}
-
-#ifdef MODULE
-#include <asm/setup.h>
-
-int init_module(void)
-{
-    return mac_mouse_init();
-}
-
-void cleanup_module(void)
-{
-    unregister_busmouse(msedev);
-}
-#endif
index fd123de44e72a05be2bbdd414c6a27f28fcdfef2..b47f0b6473771e141a193ab5c5c6ed057f626901 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/joystick.h>
 #include <linux/i2c.h>
 #include <linux/raw.h>
+#include <linux/capability.h>
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
@@ -459,11 +460,23 @@ static loff_t memory_lseek(struct file * file, loff_t offset, int orig)
        }
 }
 
+static int open_port(struct inode * inode, struct file * filp)
+{
+       return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
+}
+
+static int open_mem(struct inode * inode, struct file * filp)
+{
+       return (capable(CAP_SYS_RAWIO)
+               || !(filp->f_mode & FMODE_WRITE)) ? 0 : -EPERM;
+}
+
 #define mmap_kmem      mmap_mem
 #define zero_lseek     null_lseek
 #define full_lseek      null_lseek
 #define write_zero     write_null
 #define read_full       read_zero
+#define open_kmem      open_mem
 
 static struct file_operations mem_fops = {
        memory_lseek,
@@ -473,7 +486,7 @@ static struct file_operations mem_fops = {
        NULL,           /* mem_poll */
        NULL,           /* mem_ioctl */
        mmap_mem,
-       NULL,           /* no special open code */
+       open_mem,
        NULL,           /* flush */
        NULL,           /* no special release code */
        NULL            /* fsync */
@@ -487,7 +500,7 @@ static struct file_operations kmem_fops = {
        NULL,           /* kmem_poll */
        NULL,           /* kmem_ioctl */
        mmap_kmem,
-       NULL,           /* no special open code */
+       open_kmem,
        NULL,           /* flush */
        NULL,           /* no special release code */
        NULL            /* fsync */
@@ -515,7 +528,7 @@ static struct file_operations port_fops = {
        NULL,           /* port_poll */
        NULL,           /* port_ioctl */
        NULL,           /* port_mmap */
-       NULL,           /* no special open code */
+       open_port,
        NULL,           /* flush */
        NULL,           /* no special release code */
        NULL            /* fsync */
index ff17cd842474f8496aae696f504b462c8d878dc5..1348e4e23ebf80606b3375ea3ded88b949ba5397 100644 (file)
@@ -78,7 +78,6 @@ extern int rtc_MK48T08_init(void);
 extern int dsp56k_init(void);
 extern int nvram_init(void);
 extern int radio_init(void);
-extern void hfmodem_init(void);
 extern int pc110pad_init(void);
 extern int pmu_device_init(void);
 extern int qpmouse_init(void);
@@ -236,18 +235,12 @@ int __init misc_init(void)
 #ifdef CONFIG_ATARI_DSP56K
        dsp56k_init();
 #endif
-#ifdef CONFIG_HFMODEM
-       hfmodem_init();
-#endif
 #ifdef CONFIG_NVRAM
        nvram_init();
 #endif
 #ifdef CONFIG_MISC_RADIO
        radio_init();
 #endif
-#ifdef CONFIG_HFMODEM
-       hfmodem_init();
-#endif
 #ifdef CONFIG_PMAC_PBOOK
        pmu_device_init();
 #endif
diff --git a/drivers/char/q40_keyb.c b/drivers/char/q40_keyb.c
new file mode 100644 (file)
index 0000000..ea9d743
--- /dev/null
@@ -0,0 +1,471 @@
+/*
+ * linux/drivers/char/q40_keyb.c
+ *
+ */
+
+#include <linux/config.h>
+
+#include <asm/spinlock.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/mm.h>
+#include <linux/signal.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/kbd_ll.h>
+#include <linux/delay.h>
+#include <linux/sysrq.h>
+#include <linux/random.h>
+#include <linux/poll.h>
+#include <linux/miscdevice.h>
+#include <linux/malloc.h>
+
+#include <asm/keyboard.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/q40_master.h>
+#include <asm/irq.h>
+#include <asm/q40ints.h>
+
+/* Some configuration switches are present in the include file... */
+
+#define KBD_REPORT_ERR
+
+/* Simple translation table for the SysRq keys */
+
+#define SYSRQ_KEY 0x54
+
+#ifdef CONFIG_MAGIC_SYSRQ
+unsigned char q40kbd_sysrq_xlate[128] =
+       "\000\0331234567890-=\177\t"                    /* 0x00 - 0x0f */
+       "qwertyuiop[]\r\000as"                          /* 0x10 - 0x1f */
+       "dfghjkl;'`\000\\zxcv"                          /* 0x20 - 0x2f */
+       "bnm,./\000*\000 \000\201\202\203\204\205"      /* 0x30 - 0x3f */
+       "\206\207\210\211\212\000\000789-456+1"         /* 0x40 - 0x4f */
+       "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
+       "\r\000/";                                      /* 0x60 - 0x6f */
+#endif
+
+/* Q40 uses AT scancodes - no way to change it. so we have to translate ..*/
+/* 0x00 means not a valid entry or no conversion known                    */
+
+unsigned static char q40cl[256] =
+{/* 0,   1,   2,   3,   4,   5,   6,   7,   8,   9,   a,   b,   c,   d,   e,   f, */
+ 0x00,0x43,0x00,0x3f,0x3d,0x3b,0x3c,0x58,0x00,0x44,0x42,0x40,0x3e,0x0f,0x29,0x00,     /* 0x00 - 0x0f */
+ 0x00,0x38,0x2a,0x00,0x1d,0x10,0x02,0x00,0x00,0x00,0x2c,0x1f,0x1e,0x11,0x03,0x00,     /* 0x10 - 0x1f */
+ 0x00,0x2e,0x2d,0x20,0x12,0x05,0x04,0x00,0x21,0x39,0x2f,0x21,0x14,0x13,0x06,0x00,     /* 0x20 - 0x2f  'f' is at 0x2b, what is 0x28 ???*/
+ 0x00,0x31,0x30,0x23,0x22,0x15,0x07,0x00,0x24,0x00,0x32,0x24,0x16,0x08,0x09,0x00,     /* 0x30 - 0x3f */
+ 0x00,0x33,0x25,0x17,0x18,0x0b,0x0a,0x00,0x00,0x34,0x35,0x26,0x27,0x19,0x0c,0x00,     /* 0x40 - 0x4f */
+ 0x00,0x00,0x28,0x00,0x1a,0x0d,0x00,0x00,0x3a,0x36,0x1c,0x1b,0x00,0x2b,0x00,0x00,     /* 0x50 - 0x5f*/
+ 0x00,0x56,0x00,0x00,0x00,0x00,0x0e,0x00,0x00,0x4f,0x00,0x4b,0x47,0x00,0x00,0x00,     /* 0x60 - 0x6f */
+ 0x52,0x53,0x50,0x4c,0x4d,0x48,0x01,0x45,0x57,0x4e,0x51,0x4a,0x37,0x49,0x46,0x00,     /* 0x70 - 0x7f */
+ 0x00,0x00,0x00,0x41,0x37,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,     /* 0x80 - 0x8f  0x84/0x37 is SySrq*/
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,     /* 0x90 - 0x9f */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,     /* 0xa0 - 0xaf */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,     /* 0xb0 - 0xbf */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,     /* 0xc0 - 0xcf */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,     /* 0xd0 - 0xdf */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,     /* 0xe0 - 0xef */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,     /* 0xf0 - 0xff */
+};
+
+/* another table, AT 0xe0 codes to PC 0xe0 codes, 
+   0xff special entry for SysRq - DROPPED right now  */
+static unsigned char q40ecl[]=
+{/* 0,   1,   2,   3,   4,   5,   6,   7,   8,   9,   a,   b,   c,   d,   e,   f, */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,     /* 0x00 - 0x0f*/
+ 0x00,0x38,0x2a,0x00,0x1d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,     /* 0x10 - 0x1f */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,     /* 0x20 - 0x2f*/
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,     /* 0x30 - 0x3f*/
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x35,0x00,0x00,0x00,0x00,0x00,     /* 0x40 - 0x4f*/
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x36,0x1c,0x00,0x00,0x00,0x00,0x00,     /* 0x50 - 0x5f*/
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4f,0x00,0x4b,0x47,0x00,0x00,0x00,     /* 0x60 - 0x6f*/
+ 0x52,0x53,0x50,0x00,0x4d,0x48,0x00,0x00,0x00,0x00,0x51,0x00,0x00,0x49,0x00,0x00,     /* 0x70 - 0x7f*/
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,     /* 0x80 - 0x8f*/
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,     /* 0x90 - 0x9f*/
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,     /* 0xa0 - 0xaf*/
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,     /* 0xb0 - 0xbf*/
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,     /* 0xc0 - 0xcf*/
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,     /* 0xd0 - 0xdf*/
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,     /* 0xe0 - 0xef*/
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00      /* 0xf0 - 0xff*/
+};
+
+
+spinlock_t kbd_controller_lock = SPIN_LOCK_UNLOCKED;
+
+
+/*
+ * Translation of escaped scancodes to keycodes.
+ * This is now user-settable.
+ * The keycodes 1-88,96-111,119 are fairly standard, and
+ * should probably not be changed - changing might confuse X.
+ * X also interprets scancode 0x5d (KEY_Begin).
+ *
+ * For 1-88 keycode equals scancode.
+ */
+
+#define E0_KPENTER 96
+#define E0_RCTRL   97
+#define E0_KPSLASH 98
+#define E0_PRSCR   99
+#define E0_RALT    100
+#define E0_BREAK   101  /* (control-pause) */
+#define E0_HOME    102
+#define E0_UP      103
+#define E0_PGUP    104
+#define E0_LEFT    105
+#define E0_RIGHT   106
+#define E0_END     107
+#define E0_DOWN    108
+#define E0_PGDN    109
+#define E0_INS     110
+#define E0_DEL     111
+
+#define E1_PAUSE   119
+
+/*
+ * The keycodes below are randomly located in 89-95,112-118,120-127.
+ * They could be thrown away (and all occurrences below replaced by 0),
+ * but that would force many users to use the `setkeycodes' utility, where
+ * they needed not before. It does not matter that there are duplicates, as
+ * long as no duplication occurs for any single keyboard.
+ */
+#define SC_LIM 89
+
+#define FOCUS_PF1 85           /* actual code! */
+#define FOCUS_PF2 89
+#define FOCUS_PF3 90
+#define FOCUS_PF4 91
+#define FOCUS_PF5 92
+#define FOCUS_PF6 93
+#define FOCUS_PF7 94
+#define FOCUS_PF8 95
+#define FOCUS_PF9 120
+#define FOCUS_PF10 121
+#define FOCUS_PF11 122
+#define FOCUS_PF12 123
+
+#define JAP_86     124
+/* tfj@olivia.ping.dk:
+ * The four keys are located over the numeric keypad, and are
+ * labelled A1-A4. It's an rc930 keyboard, from
+ * Regnecentralen/RC International, Now ICL.
+ * Scancodes: 59, 5a, 5b, 5c.
+ */
+#define RGN1 124
+#define RGN2 125
+#define RGN3 126
+#define RGN4 127
+
+static unsigned char high_keys[128 - SC_LIM] = {
+  RGN1, RGN2, RGN3, RGN4, 0, 0, 0,                   /* 0x59-0x5f */
+  0, 0, 0, 0, 0, 0, 0, 0,                            /* 0x60-0x67 */
+  0, 0, 0, 0, 0, FOCUS_PF11, 0, FOCUS_PF12,          /* 0x68-0x6f */
+  0, 0, 0, FOCUS_PF2, FOCUS_PF9, 0, 0, FOCUS_PF3,    /* 0x70-0x77 */
+  FOCUS_PF4, FOCUS_PF5, FOCUS_PF6, FOCUS_PF7,        /* 0x78-0x7b */
+  FOCUS_PF8, JAP_86, FOCUS_PF10, 0                   /* 0x7c-0x7f */
+};
+
+/* BTC */
+#define E0_MACRO   112
+/* LK450 */
+#define E0_F13     113
+#define E0_F14     114
+#define E0_HELP    115
+#define E0_DO      116
+#define E0_F17     117
+#define E0_KPMINPLUS 118
+/*
+ * My OmniKey generates e0 4c for  the "OMNI" key and the
+ * right alt key does nada. [kkoller@nyx10.cs.du.edu]
+ */
+#define E0_OK  124
+/*
+ * New microsoft keyboard is rumoured to have
+ * e0 5b (left window button), e0 5c (right window button),
+ * e0 5d (menu button). [or: LBANNER, RBANNER, RMENU]
+ * [or: Windows_L, Windows_R, TaskMan]
+ */
+#define E0_MSLW        125
+#define E0_MSRW        126
+#define E0_MSTM        127
+
+/* this can be changed using setkeys : */
+static unsigned char e0_keys[128] = {
+  0, 0, 0, 0, 0, 0, 0, 0,                            /* 0x00-0x07 */
+  0, 0, 0, 0, 0, 0, 0, 0,                            /* 0x08-0x0f */
+  0, 0, 0, 0, 0, 0, 0, 0,                            /* 0x10-0x17 */
+  0, 0, 0, 0, E0_KPENTER, E0_RCTRL, 0, 0,            /* 0x18-0x1f */
+  0, 0, 0, 0, 0, 0, 0, 0,                            /* 0x20-0x27 */
+  0, 0, 0, 0, 0, 0, 0, 0,                            /* 0x28-0x2f */
+  0, 0, 0, 0, 0, E0_KPSLASH, 0, E0_PRSCR,            /* 0x30-0x37 */
+  E0_RALT, 0, 0, 0, 0, E0_F13, E0_F14, E0_HELP,              /* 0x38-0x3f */
+  E0_DO, E0_F17, 0, 0, 0, 0, E0_BREAK, E0_HOME,              /* 0x40-0x47 */
+  E0_UP, E0_PGUP, 0, E0_LEFT, E0_OK, E0_RIGHT, E0_KPMINPLUS, E0_END,/* 0x48-0x4f */
+  E0_DOWN, E0_PGDN, E0_INS, E0_DEL, 0, 0, 0, 0,              /* 0x50-0x57 */
+  0, 0, 0, E0_MSLW, E0_MSRW, E0_MSTM, 0, 0,          /* 0x58-0x5f */
+  0, 0, 0, 0, 0, 0, 0, 0,                            /* 0x60-0x67 */
+  0, 0, 0, 0, 0, 0, 0, E0_MACRO,                     /* 0x68-0x6f */
+  0, 0, 0, 0, 0, 0, 0, 0,                            /* 0x70-0x77 */
+  0, 0, 0, 0, 0, 0, 0, 0                             /* 0x78-0x7f */
+};
+
+static unsigned int prev_scancode = 0;   /* remember E0, E1 */
+
+int q40kbd_setkeycode(unsigned int scancode, unsigned int keycode)
+{
+       if (scancode < SC_LIM || scancode > 255 || keycode > 127)
+         return -EINVAL;
+       if (scancode < 128)
+         high_keys[scancode - SC_LIM] = keycode;
+       else
+         e0_keys[scancode - 128] = keycode;
+       return 0;
+}
+
+int q40kbd_getkeycode(unsigned int scancode)
+{
+       return
+         (scancode < SC_LIM || scancode > 255) ? -EINVAL :
+         (scancode < 128) ? high_keys[scancode - SC_LIM] :
+           e0_keys[scancode - 128];
+}
+
+
+#define disable_keyboard()     
+#define enable_keyboard()      
+
+
+
+int q40kbd_pretranslate(unsigned char scancode, char raw_mode)
+{
+       if (scancode == 0xff) {
+               /* in scancode mode 1, my ESC key generates 0xff */
+               /* the calculator keys on a FOCUS 9000 generate 0xff */
+#ifndef KBD_IS_FOCUS_9000
+#ifdef KBD_REPORT_ERR
+               if (!raw_mode)
+                 printk(KERN_DEBUG "Keyboard error\n");
+#endif
+#endif
+               prev_scancode = 0;
+               return 0;
+       }
+
+       if (scancode == 0xe0 || scancode == 0xe1) {
+               prev_scancode = scancode;
+               return 0;
+       }
+       return 1;
+}
+
+int q40kbd_translate(unsigned char scancode, unsigned char *keycode,
+                   char raw_mode)
+{
+  /*printk("translate ...\n");*/
+       if (prev_scancode) {
+         /*
+          * usually it will be 0xe0, but a Pause key generates
+          * e1 1d 45 e1 9d c5 when pressed, and nothing when released
+          */
+         if (prev_scancode != 0xe0) {
+             if (prev_scancode == 0xe1 && scancode == 0x1d) {
+                 prev_scancode = 0x100;
+                 return 0;
+             } else if (prev_scancode == 0x100 && scancode == 0x45) {
+                 *keycode = E1_PAUSE;
+                 prev_scancode = 0;
+             } else {
+#ifdef KBD_REPORT_UNKN
+                 if (!raw_mode)
+                   printk(KERN_INFO "keyboard: unknown e1 escape sequence\n");
+#endif
+                 prev_scancode = 0;
+                 return 0;
+             }
+         } else {
+             prev_scancode = 0;
+             /*
+              *  The keyboard maintains its own internal caps lock and
+              *  num lock statuses. In caps lock mode E0 AA precedes make
+              *  code and E0 2A follows break code. In num lock mode,
+              *  E0 2A precedes make code and E0 AA follows break code.
+              *  We do our own book-keeping, so we will just ignore these.
+              */
+             /*
+              *  For my keyboard there is no caps lock mode, but there are
+              *  both Shift-L and Shift-R modes. The former mode generates
+              *  E0 2A / E0 AA pairs, the latter E0 B6 / E0 36 pairs.
+              *  So, we should also ignore the latter. - aeb@cwi.nl
+              */
+             if (scancode == 0x2a || scancode == 0x36)
+               return 0;
+
+             if (e0_keys[scancode])
+               *keycode = e0_keys[scancode];
+             else {
+#ifdef KBD_REPORT_UNKN
+                 if (!raw_mode)
+                   printk(KERN_INFO "keyboard: unknown scancode e0 %02x\n",
+                          scancode);
+#endif
+                 return 0;
+             }
+         }
+       } else if (scancode >= SC_LIM) {
+           /* This happens with the FOCUS 9000 keyboard
+              Its keys PF1..PF12 are reported to generate
+              55 73 77 78 79 7a 7b 7c 74 7e 6d 6f
+              Moreover, unless repeated, they do not generate
+              key-down events, so we have to zero up_flag below */
+           /* Also, Japanese 86/106 keyboards are reported to
+              generate 0x73 and 0x7d for \ - and \ | respectively. */
+           /* Also, some Brazilian keyboard is reported to produce
+              0x73 and 0x7e for \ ? and KP-dot, respectively. */
+
+         *keycode = high_keys[scancode - SC_LIM];
+
+         if (!*keycode) {
+             if (!raw_mode) {
+#ifdef KBD_REPORT_UNKN
+                 printk(KERN_INFO "keyboard: unrecognized scancode (%02x)"
+                        " - ignored\n", scancode);
+#endif
+             }
+             return 0;
+         }
+       } else
+         *keycode = scancode;
+       return 1;
+}
+
+char q40kbd_unexpected_up(unsigned char keycode)
+{
+       /* unexpected, but this can happen: maybe this was a key release for a
+          FOCUS 9000 PF key; if we want to see it, we have to clear up_flag */
+       if (keycode >= SC_LIM || keycode == 85)
+           return 0;
+       else
+           return 0200;
+}
+
+static int keyup=0;
+static int qprev=0;
+
+static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+       unsigned long flags;
+       unsigned char status;
+
+       disable_keyboard();
+       spin_lock_irqsave(&kbd_controller_lock, flags);
+       kbd_pt_regs = regs;
+
+       status = IRQ_KEYB_MASK & master_inb(INTERRUPT_REG);
+       if (status ) 
+         {
+           unsigned char scancode,qcode;
+           
+           qcode = master_inb(KEYCODE_REG);
+           
+           if (qcode != 0xf0)
+             {
+               if (qcode == 0xe0)
+                 {
+                   qprev=0xe0;
+                   handle_scancode(qprev);
+                   goto exit;
+                 }
+               
+               scancode=qprev ? q40ecl[qcode] : q40cl[qcode];
+#if 0
+/* next line is last resort to hanlde some oddities */
+               if (qprev && !scancode) scancode=q40cl[qcode];
+#endif
+               qprev=0;
+               if (!scancode)
+                 {
+                   printk("unknown scancode %x\n",qcode);
+                   goto exit;
+                 }
+               if (scancode==0xff)  /* SySrq */
+                 scancode=SYSRQ_KEY;
+
+               handle_scancode(scancode | (keyup ? 0200 : 0));
+               keyup=0;
+               mark_bh(KEYBOARD_BH);
+
+             }
+           else
+             keyup=1;
+         }
+exit:
+       spin_unlock_irqrestore(&kbd_controller_lock, flags);
+       master_outb(-1,KEYBOARD_UNLOCK_REG); /* keyb ints reenabled herewith */
+       enable_keyboard();
+}
+
+
+
+
+#ifdef CONFIG_MAGIC_SYSRQ
+int kbd_is_sysrq(unsigned char keycode)
+{
+       return( keycode == SYSRQ_KEY );
+}
+#endif /* CONFIG_MAGIC_SYSRQ */
+
+
+
+
+#define KBD_NO_DATA    (-1)    /* No data */
+#define KBD_BAD_DATA   (-2)    /* Parity or other error */
+
+static int __init kbd_read_input(void)
+{
+       int retval = KBD_NO_DATA;
+       unsigned char status;
+
+       status = IRQ_KEYB_MASK & master_inb(INTERRUPT_REG);
+       if (status) {
+               unsigned char data = master_inb(KEYCODE_REG);
+
+               retval = data;
+               master_outb(-1,KEYBOARD_UNLOCK_REG);
+       }
+       return retval;
+}
+
+extern void q40kbd_leds(unsigned char leds)
+{ /* nothing can be done */ }
+
+static void __init kbd_clear_input(void)
+{
+       int maxread = 100;      /* Random number */
+
+       do {
+               if (kbd_read_input() == KBD_NO_DATA)
+                       break;
+       } while (--maxread);
+}
+
+
+void __init q40kbd_init_hw(void)
+{
+#if 0
+       /* Get the keyboard controller registers (incomplete decode) */
+       request_region(0x60, 16, "keyboard");
+#endif
+       /* Flush any pending input. */
+       kbd_clear_input();
+
+       /* Ok, finally allocate the IRQ, and off we go.. */
+       request_irq(Q40_IRQ_KEYBOARD, keyboard_interrupt, 0, "keyboard", NULL);
+       master_outb(-1,KEYBOARD_UNLOCK_REG);
+       master_outb(1,KEY_IRQ_ENABLE_REG);
+
+}
+
index a3d0d0278649e3260e835f82313d71011c6c5e84..c8936ceb65d1acebdc19aa986796632f42ccf5ac 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/major.h>
 #include <linux/blkdev.h>
 #include <linux/raw.h>
+#include <linux/capability.h>
 #include <asm/uaccess.h>
 
 #define dprintk(x...) 
@@ -233,6 +234,15 @@ int raw_ctl_ioctl(struct inode *inode,
                }
 
                if (command == RAW_SETBIND) {
+                       /*
+                        * This is like making block devices, so demand the
+                        * same capability
+                        */
+                       if (!capable(CAP_SYS_ADMIN)) {
+                               err = -EPERM;
+                               break;
+                       }
+
                        /* 
                         * For now, we don't need to check that the underlying
                         * block device is present or not: we can do that when
index aa649431f378fd4f94559891beb7abbfbbbd6523..1b4a5d667ad8cc46fd6ef94adf3a7b1eaa3ca095 100644 (file)
@@ -673,7 +673,7 @@ static void leds_done(struct adb_request *req)
 
 }
 
-__initfunc(void mackbd_init_hw(void))
+void __init mackbd_init_hw(void)
 {
        if ( (_machine != _MACH_chrp) && (_machine != _MACH_Pmac) )
            return;
index 2125fe67f7db47b86900c582f27c4905997f87db..f3c0a66f2eb71124a091d97fd974dbb9e724f8ec 100644 (file)
@@ -2121,7 +2121,7 @@ static kdev_t serial_console_device(struct console *c)
  *     - initialize the serial port
  *     Return non-zero if we didn't find a serial port.
  */
-__initfunc(static int serial_console_setup(struct console *co, char *options))
+static int __init serial_console_setup(struct console *co, char *options)
 {
        struct mac_serial *info = zs_soft + co->index;
        int     baud = 38400;
@@ -2306,7 +2306,7 @@ static struct console sercons = {
 /*
  *     Register console.
  */
-__initfunc (long serial_console_init(long kmem_start, long kmem_end))
+long __init serial_console_init(long kmem_start, long kmem_end)
 {
        register_console(&sercons);
        return kmem_start;
@@ -2376,7 +2376,7 @@ static inline void kgdb_chaninit(struct mac_zschannel *ms, int intson, int bps)
  * boot command line flags.
  * XXX at the moment probably only channel A will work
  */
-__initfunc(void zs_kgdb_hook(int tty_num))
+void __init zs_kgdb_hook(int tty_num)
 {
        /* Find out how many Z8530 SCCs we have */
        if (zs_chain == 0)
index 695946c3a5a930acffe189f2c64c0430126d0946..b200eb703818c4efc2f89786a2454609db8678f4 100644 (file)
@@ -108,7 +108,7 @@ static struct miscdevice nvram_dev = {
        &nvram_fops
 };
 
-__initfunc(int nvram_init(void))
+int nvram_init(void)
 {
        printk(KERN_INFO "Macintosh non-volatile memory driver v%s\n",
                NVRAM_VERSION);
index c5b300f8282a949bb24398d0add250bcf39400e6..78c124d8dc06bf4a667de824283361fda734f7f7 100644 (file)
@@ -904,6 +904,17 @@ else
   M_OBJS += hplance.o
   endif
 endif
+
+ifeq ($(CONFIG_MVME147_NET),y)
+L_OBJS += mvme147.o
+CONFIG_7990_BUILTIN = y
+else
+  ifeq ($(CONFIG_MVME147_NET),m)
+  CONFIG_7990_MODULE = y
+  M_OBJS += mvme147.o
+  endif
+endif
+
 # If we need generic LANCE support, either in the kernel or as a module,
 # build it in the appropriate way.
 ifdef CONFIG_7990_BUILTIN
@@ -1076,6 +1087,10 @@ else
   endif
 endif
 
+ifeq ($(CONFIG_MACSONIC),y)
+L_OBJS += macsonic.o
+endif
+
 ifeq ($(CONFIG_BMAC),y)
 L_OBJS += bmac.o
 else
index 7400b2eb3ea077ff6fb6b945647b0b6dfc36151e..debbf38979188915a339b666f44e1e27505db50d 100644 (file)
@@ -114,10 +114,12 @@ extern int rtl8139_probe(struct device *dev);
 extern int hplance_probe(struct device *dev);
 extern int bagetlance_probe(struct device *);
 extern int dec_lance_probe(struct device *);
+extern int mvme147lance_probe(struct device *dev);
 extern int via_rhine_probe(struct device *dev);
 extern int tc515_probe(struct device *dev);
 extern int lance_probe(struct device *dev);
 extern int rcpci_probe(struct device *);
+extern int mac_onboard_sonic_probe(struct device *dev);
 
 /* Gigabit Ethernet adapters */
 extern int yellowfin_probe(struct device *dev);
@@ -424,6 +426,12 @@ struct devprobe m68k_probes[] __initdata = {
 #endif
 #ifdef CONFIG_HPLANCE          /* HP300 internal Ethernet */
        {hplance_probe, 0},
+#endif
+#ifdef CONFIG_MVME147_NET      /* MVME147 internal Ethernet */
+       {mvme147lance_probe, 0},
+#endif
+#ifdef CONFIG_MACSONIC         /* Mac 68k Quadra builtin Ethernet */ 
+       {mac_onboard_sonic_probe, 0},
 #endif
        {NULL, 0},
 };
index fc02ecbb50cfde777b5eb99a269f936a582c9bb1..83ed4359b8667a6f6c03bd4d80f447db8ebd05ac 100644 (file)
@@ -177,6 +177,7 @@ static int __init ariadne2_init(struct device *dev, unsigned int key,
     name = "NE2000";
 
     dev->base_addr = ioaddr;
+    dev->irq = IRQ_AMIGA_PORTS;
 
     /* Install the Interrupt handler */
     if (request_irq(IRQ_AMIGA_PORTS, ei_interrupt, 0, "AriadNE2 Ethernet",
@@ -191,7 +192,9 @@ static int __init ariadne2_init(struct device *dev, unsigned int key,
     ((struct ei_device *)dev->priv)->priv = key;
 
     for(i = 0; i < ETHER_ADDR_LEN; i++) {
+#ifdef DEBUG
        printk(" %2.2x", SA_prom[i]);
+#endif
        dev->dev_addr[i] = SA_prom[i];
     }
 
index 8fb48eeb45248a80a10d968cf5c4c0b198e735a9..19de8e5ecf0050b6feb23db570ce8f81d9b19459 100644 (file)
@@ -446,7 +446,7 @@ bionet_send_packet(struct sk_buff *skb, struct device *dev) {
        }
        else {
                int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
-               unsigned long buf = VTOP(skb->data);
+               unsigned long buf = virt_to_phys(skb->data);
                int stat;
 
                stdma_lock(bionet_intr, NULL);
index 83cd0f665bc5f12d1a78d0abcaf01db2972fa3f6..08d763e8b03e27447c35d8f34ae04d4bb6c309b0 100644 (file)
@@ -439,7 +439,7 @@ inquiry (target, buffer)
        unsigned char *buffer;
 {
        int ret = -1;
-       unsigned char *vbuffer = (unsigned char *)PTOV(buffer);
+       unsigned char *vbuffer = phys_to_virt((unsigned long)buffer);
        unsigned char cmd_buffer[5];
 
        if (send_first(target, INQUIRY))
@@ -487,7 +487,7 @@ static HADDR
            !acsi_wait_for_IRQ(TIMEOUTDMA) ||
            get_status())
                goto bad;
-       ret = (HADDR *)PTOV(&(((DMAHWADDR *)buffer)->hwaddr));
+       ret = phys_to_virt(&(((DMAHWADDR *)buffer)->hwaddr));
        dma_cache_maintenance((unsigned long)buffer, 512, 0);
 bad:
        return (ret);
@@ -707,7 +707,7 @@ pamsnet_send_packet(struct sk_buff *skb, struct device *dev) {
        }
        else {
                int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
-               unsigned long buf = VTOP(skb->data);
+               unsigned long buf = virt_to_phys(skb->data);
                int stat;
 
                stdma_lock(pamsnet_intr, NULL);
index 25abf5d27c897752c96bad3bade2f2f6bd7fc73b..36001d1b754a184d849cfcbff626e3e7cee3a99b 100644 (file)
@@ -794,8 +794,8 @@ speedo_found1(int pci_bus, int pci_devfn, struct device *dev,
                void *mem = kmalloc(sizeof(*sp), GFP_KERNEL);
                dev->priv = sp = mem;           /* Cache align here if kmalloc does not. */
                sp->priv_addr = mem;
-       } else
-               memset(sp, 0, sizeof(*sp));
+       }
+       memset(sp, 0, sizeof(*sp));
        sp->next_module = root_speedo_dev;
        root_speedo_dev = dev;
 
diff --git a/drivers/net/macsonic.c b/drivers/net/macsonic.c
new file mode 100644 (file)
index 0000000..f295e7f
--- /dev/null
@@ -0,0 +1,485 @@
+/*
+ * macsonic.c
+ *
+ * (C) 1998 Alan Cox
+ *
+ * Debugging Andreas Ehliar, Michael Schmitz
+ *
+ * Based on code
+ * (C) 1996 by Thomas Bogendoerfer (tsbogend@bigbug.franken.de)
+ * 
+ * This driver is based on work from Andreas Busse, but most of
+ * the code is rewritten.
+ * 
+ * (C) 1995 by Andreas Busse (andy@waldorf-gmbh.de)
+ *
+ * A driver for the Mac onboard Sonic ethernet chip.
+ *
+ * 98/12/21 MSch: judged from tests on Q800, it's basically working, 
+ *               but eating up both receive and transmit resources
+ *               and duplicating packets. Needs more testing.
+ *
+ * 99/01/03 MSch: upgraded to version 0.92 of the core driver, fixed.
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/ctype.h>
+#include <linux/fcntl.h>
+#include <linux/interrupt.h>
+#include <linux/ptrace.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/in.h>
+#include <linux/malloc.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/nubus.h>
+#include <asm/bootinfo.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <asm/pgtable.h>
+#include <asm/segment.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/macintosh.h>
+
+#include <linux/errno.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+
+#include <config/macsonic.h>
+
+#define SREGS_PAD(n)    u16 n;
+
+#include "sonic.h"
+
+extern int mac_onboard_sonic_probe(void);
+
+static int setup_debug = -1;
+static int setup_offset = -1;
+static int setup_shift = -1;
+
+/*
+ * This seems to be the right default for the Q800
+ */
+
+static int reg_offset = 0;
+static int reg_shift = 0;
+
+/*
+ * Macros to access SONIC registers
+ */
+#define MAC_SONIC_REGISTERS    0x50F0A000
+#define MAC_SONIC_PROM_BASE    0x50f08000
+#define MAC_SONIC_IRQ          9       /* Nubus 9 */
+
+/*
+ *    FIXME: We may need to invert the byte ordering. These should
+ *      be ok for other aspects as they are uncached spaces.
+ *      The original macros from jazzsonic.c works for me
+ *      on my LC 630, YMMV /Andreas Ehliar
+ */
+
+#if 0
+#define SONIC_READ(reg) \
+       *((volatile unsigned int *)base_addr+((reg)<<2)+2)
+
+#define SONIC_WRITE(reg,val) \
+       *((volatile unsigned int *)base_addr+((reg)<<2)+2) = val
+#else
+#define SONIC_READ(reg) \
+       *((volatile unsigned int *)base_addr+reg)
+
+#define SONIC_WRITE(reg,val) \
+       *((volatile unsigned int *)base_addr+reg) = val
+#endif
+
+#define SONIC_READ_PROM(addr) \
+       *((volatile unsigned char *)prom_addr+addr)
+/*
+ * Function : mac_sonic_setup(char *str, int *ints)
+ *
+ * Purpose : booter command line initialization of the overrides array,
+ *
+ * Inputs : str - unused, ints - array of integer parameters with ints[0]
+ *     equal to the number of ints.
+ *
+ * Currently unused in the new driver; need to add settable parameters to the 
+ * detect function.
+ *
+ */
+
+void mac_sonic_setup(char *str, int *ints) {
+       /* Format of macsonic parameter is:
+        *   macsonic=<debug>,<offset>,<shift>
+        * Negative values mean don't change.
+        */
+       
+       /* Grmbl... the standard parameter parsing can't handle negative numbers
+        * :-( So let's do it ourselves!
+        */
+
+       int i = ints[0]+1, fact;
+
+       while( str && (isdigit(*str) || *str == '-') && i <= 10) {
+               if (*str == '-')
+                       fact = -1, ++str;
+               else
+                       fact = 1;
+               ints[i++] = simple_strtoul( str, NULL, 0 ) * fact;
+               if ((str = strchr( str, ',' )) != NULL)
+                       ++str;
+       }
+       ints[0] = i-1;
+       
+       if (ints[0] < 1) {
+               printk( "mac_sonic_setup: no arguments!\n" );
+               return;
+       }
+
+       if (ints[0] >= 1) {
+               /* 0 <= n <= 2 */
+               if (ints[1] >= 0 && ints[1] <= 8)
+                       setup_debug = ints[1];
+               else if (ints[1] > 16)
+                       printk( "mac_sonic_setup: invalid debug level %d !\n", ints[1] );
+       }
+       if (ints[0] >= 2) {
+               /* 0 <= n <= 2 */
+               if (ints[2] >= 0 && ints[2] <= 16)
+                       setup_offset = ints[2];
+               else if (ints[2] > 16)
+                       printk( "mac_sonic_setup: invalid offset %d !\n", ints[2] );
+       }
+       if (ints[0] >= 3) {
+               /* 0 <= n <= 2 */
+               if (ints[3] >= 0 && ints[3] <= 16)
+                       setup_shift = ints[3];
+               else if (ints[3] > 16)
+                       printk( "mac_sonic_setup: invalid shift %d !\n", ints[3] );
+       }
+}
+
+static int sonic_debug = 0;
+
+/*
+ * For reversing the PROM address
+ */
+
+static unsigned char nibbletab[] = {0, 8, 4, 12, 2, 10, 6, 14,
+                                   1, 9, 5, 13, 3, 11, 7, 15};
+
+__initfunc(int mac_onboard_sonic_probe(void))
+{
+       struct device *dev;
+       unsigned int silicon_revision;
+       unsigned int val;
+       struct sonic_local *lp;
+       int i;
+       int base_addr = MAC_SONIC_REGISTERS;
+       int prom_addr = MAC_SONIC_PROM_BASE;
+       static int one=0;
+       
+       if (!MACH_IS_MAC)
+               return -ENODEV;
+
+       if(++one!=1)    /* Only one is allowed */
+               return -ENODEV;
+
+       printk(KERN_INFO "Checking for internal Macintosh ethernet (SONIC).. ");
+
+       if (macintosh_config->ether_type != MAC_ETHER_SONIC)
+       {
+               printk("none.\n");
+               return -ENODEV;
+       }
+       
+       printk("yes\n");
+       
+       if (setup_debug >= 0)
+         sonic_debug = setup_debug;
+
+       /*
+        * This may depend on the actual Mac model ... works for me.
+        */
+       reg_offset = 
+         (setup_offset >= 0) ? setup_offset : 0;
+       reg_shift = 
+         (setup_shift >= 0) ? setup_shift : 0;
+
+       /*
+        * get the Silicon Revision ID. If this is one of the known
+        * one assume that we found a SONIC ethernet controller at
+        * the expected location.
+        * (This is not implemented in the Macintosh driver yet; need
+        * to collect values from various sources. Mine is 0x4 ...)
+        */
+
+       silicon_revision = SONIC_READ(SONIC_SR);
+       if (sonic_debug > 1)
+               printk("SONIC Silicon Revision = 0x%04x\n", silicon_revision);
+
+       /*
+        * We need to allocate sonic_local later on, making sure it's
+        * aligned on a 64k boundary. So, no space for dev->priv allocated
+        * here ...
+        */
+       dev = init_etherdev(0,0);
+       
+       if(dev==NULL)
+               return -ENOMEM;
+
+       printk("%s: %s found at 0x%08x, ",
+              dev->name, "SONIC ethernet", base_addr);
+
+       if (sonic_debug > 1)
+               printk("using offset %d shift %d,", reg_offset, reg_shift);
+
+       /* Fill in the 'dev' fields. */
+       dev->base_addr = base_addr;
+       dev->irq = MAC_SONIC_IRQ;
+
+       /*
+        * Put the sonic into software reset, then
+        * retrieve and print the ethernet address.
+        */
+
+       SONIC_WRITE(SONIC_CMD, SONIC_CR_RST);
+
+       /*
+        *        We can't trust MacOS to initialise things it seems.
+        */
+
+       if (sonic_debug > 1)
+               printk("SONIC_DCR was %X\n",SONIC_READ(SONIC_DCR));
+       
+       SONIC_WRITE(SONIC_DCR,
+                   SONIC_DCR_RFT1 | SONIC_DCR_TFT0 | SONIC_DCR_EXBUS | SONIC_DCR_DW);
+
+       /*
+        *  We don't want floating spare IRQ's around, not on
+        *  level triggered systems!
+        *  Strange though - writing to the ISR only clears currently
+        *  pending IRQs, but doesn't disable them... Does this make 
+        *  a difference?? Seems it does ...
+        */
+#if 1
+       SONIC_WRITE(SONIC_ISR,0x7fff);
+       SONIC_WRITE(SONIC_IMR,0);
+#else
+       SONIC_WRITE(SONIC_ISR, SONIC_IMR_DEFAULT);
+#endif
+       
+       /* This is how it is done in jazzsonic.c
+        * It doesn't seem to work here though.
+        */
+       if (sonic_debug > 2) {
+               printk("Retreiving CAM entry 0. This should be the HW address.\n");
+               
+               SONIC_WRITE(SONIC_CEP, 0);
+               for (i = 0; i < 3; i++)
+               {
+                       val = SONIC_READ(SONIC_CAP0 - i);
+                       dev->dev_addr[i * 2] = val;
+                       dev->dev_addr[i * 2 + 1] = val >> 8;
+               }
+
+               printk("HW Address from CAM 0: ");
+               for (i = 0; i < 6; i++)
+               {
+                       printk("%2.2x", dev->dev_addr[i]);
+                       if (i < 5)
+                               printk(":");
+               }
+               printk("\n");
+
+               printk("Retreiving CAM entry 15. Another candidate...\n");
+
+               /*
+                * MacOS seems to use CAM entry 15 ...
+                */
+               SONIC_WRITE(SONIC_CEP, 15);
+               for (i = 0; i < 3; i++)
+               {
+                       val = SONIC_READ(SONIC_CAP0 - i);
+                       dev->dev_addr[i * 2] = val;
+                       dev->dev_addr[i * 2 + 1] = val >> 8;
+               }
+
+               printk("HW Address from CAM 15: ");
+               for (i = 0; i < 6; i++)
+               {
+                       printk("%2.2x", dev->dev_addr[i]);
+                       if (i < 5)
+                               printk(":");
+               }
+               printk("\n");
+       }
+
+       /*
+        * if we can read the PROM, we're safe :-)
+        */
+       if (sonic_debug > 1)
+               printk("Retreiving HW address from the PROM: ");
+
+       for(i=0;i<6;i++){
+                dev->dev_addr[i]=SONIC_READ_PROM(i);
+        }                             
+       if (sonic_debug > 1) {
+               for (i = 0; i < 6; i++)
+               {
+                       printk("%2.2x", dev->dev_addr[i]);
+                       if (i < 5)
+                               printk(":");
+               }
+               printk("\n");
+       }
+       /*
+        *                If its not one of these we have
+        *          screwed up on this Mac model
+        */
+
+       if (memcmp(dev->dev_addr, "\x08\x00\x07", 3) &&
+           memcmp(dev->dev_addr, "\x00\xA0\x40", 3) &&
+           memcmp(dev->dev_addr, "\x00\x05\x02", 3))
+       {
+               /*
+                * Try bit reversed
+                */
+               for(i=0;i<6;i++){
+                       val = SONIC_READ_PROM(i);
+                       dev->dev_addr[i]=(nibbletab[val & 0xf] << 4) | 
+                                         nibbletab[(val >> 4) &0xf];
+               }
+               if (sonic_debug > 1) {
+                       printk("Trying bit reversed:  ");
+                       for (i = 0; i < 6; i++)
+                       {
+                               printk("%2.2x", dev->dev_addr[i]);
+                               if (i < 5)
+                                       printk(":");
+                       }
+                       printk("\n");
+               }
+               if (memcmp(dev->dev_addr, "\x08\x00\x07", 3) &&
+                   memcmp(dev->dev_addr, "\x00\xA0\x40", 3) &&
+                   memcmp(dev->dev_addr, "\x00\x05\x02", 3))
+               {
+                       /*
+                        * Still nonsense ... messed up someplace!
+                        */
+                       printk("ERROR (INVALID MAC)\n");
+                       return -EIO;
+               }
+       }
+
+       printk(" MAC ");
+       for (i = 0; i < 6; i++)
+       {
+               printk("%2.2x", dev->dev_addr[i]);
+               if (i < 5)
+                       printk(":");
+       }
+
+       printk(" IRQ %d\n", MAC_SONIC_IRQ);
+
+       /* Initialize the device structure. */
+       if (dev->priv == NULL)
+       {
+               if (sonic_debug > 2) {
+                       printk("Allocating memory for dev->priv aka lp\n");
+                       printk("Memory to allocate: %d\n",sizeof(*lp));
+               }
+               /*
+                * the memory be located in the same 64kb segment
+                */
+               lp = NULL;
+               i = 0;
+               do
+               {
+                       lp = (struct sonic_local *) kmalloc(sizeof(*lp), GFP_KERNEL);
+                       if ((unsigned long) lp >> 16 != ((unsigned long) lp + sizeof(*lp)) >> 16)
+                       {
+                               /* FIXME, free the memory later */
+                               kfree(lp);
+                               lp = NULL;
+                       }
+               }
+               while (lp == NULL && i++ < 20);
+
+               if (lp == NULL)
+               {
+                       printk("%s: couldn't allocate memory for descriptors\n",
+                              dev->name);
+                       return -ENOMEM;
+               }
+
+               if (sonic_debug > 2) {
+                       printk("Memory allocated after %d tries\n",i);
+               }
+
+               /* XXX sonic_local has the TDA, RRA, RDA, don't cache */
+               kernel_set_cachemode((u32)lp, 8192, IOMAP_NOCACHE_SER);
+               memset(lp, 0, sizeof(struct sonic_local));
+
+               lp->cda_laddr = (u32)lp;
+               if (sonic_debug > 2) {
+                       printk("memory allocated for sonic at 0x%x\n",lp);
+               }
+               lp->tda_laddr = lp->cda_laddr + sizeof(lp->cda);
+               lp->rra_laddr = lp->tda_laddr + sizeof(lp->tda);
+               lp->rda_laddr = lp->rra_laddr + sizeof(lp->rra);
+
+               /* allocate receive buffer area */
+               /* FIXME, maybe we should use skbs */
+               if ((lp->rba = (char *) kmalloc(SONIC_NUM_RRS * SONIC_RBSIZE, GFP_KERNEL)) == NULL)
+               {
+                       printk("%s: couldn't allocate receive buffers\n", dev->name);
+                       return -ENOMEM;
+               }
+               /* XXX RBA written by Sonic, not cached either */
+               kernel_set_cachemode((u32)lp->rba, 6*8192, IOMAP_NOCACHE_SER);
+               lp->rba_laddr = (u32)lp->rba;
+               flush_cache_all();
+               dev->priv = (struct sonic_local *) lp;
+       }
+       lp = (struct sonic_local *) dev->priv;
+       dev->open = sonic_open;
+       dev->stop = sonic_close;
+       dev->hard_start_xmit = sonic_send_packet;
+       dev->get_stats = sonic_get_stats;
+       dev->set_multicast_list = &sonic_multicast_list;
+
+       /* Fill in the fields of the device structure with ethernet values. */
+       ether_setup(dev);
+       return 0;
+}
+
+/*
+ *    SONIC uses a nubus IRQ
+ */
+
+#define sonic_request_irq(irq, vec, flags, name, dev) \
+               nubus_request_irq(irq, dev, vec)
+#define sonic_free_irq(irq,id) nubus_free_irq(irq)
+
+/*
+ *    No funnies on memory mapping.
+ */
+
+#define sonic_chiptomem(x)     (x)
+
+/*
+ *    No VDMA on a Macintosh. So we need request no such facility.
+ */
+
+#define vdma_alloc(x,y)                ((u32)(x))
+#define vdma_free(x)
+#define PHYSADDR(x)            (x)
+
+#include "sonic.c"
diff --git a/drivers/net/mvme147.c b/drivers/net/mvme147.c
new file mode 100644 (file)
index 0000000..f142cb7
--- /dev/null
@@ -0,0 +1,209 @@
+/* mvme147.c  : the  Linux/mvme147/lance ethernet driver
+ *
+ * Copyright (C) 05/1998 Peter Maydell <pmaydell@chiark.greenend.org.uk>
+ * Based on the Sun Lance driver and the NetBSD HP Lance driver
+ * Uses the generic 7990.c LANCE code.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/malloc.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+
+/* Used for the temporal inet entries and routing */
+#include <linux/socket.h>
+#include <linux/route.h>
+
+#include <linux/dio.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+
+#include <asm/mvme147hw.h>
+
+/* We have 16834 bytes of RAM for the init block and buffers. This places
+ * an upper limit on the number of buffers we can use. NetBSD uses 8 Rx
+ * buffers and 2 Tx buffers.
+ */
+#define LANCE_LOG_TX_BUFFERS 1
+#define LANCE_LOG_RX_BUFFERS 3
+
+#include "7990.h"                                 /* use generic LANCE code */
+
+/* Our private data structure */
+struct m147lance_private {
+       struct lance_private lance;
+       void *base;
+       void *ram;
+};
+
+/* function prototypes... This is easy because all the grot is in the
+ * generic LANCE support. All we have to support is probing for boards,
+ * plus board-specific init, open and close actions.
+ * Oh, and we need to tell the generic code how to read and write LANCE registers...
+ */
+int mvme147lance_probe(struct device *dev);
+static int m147lance_open(struct device *dev);
+static int m147lance_close(struct device *dev);
+static void m147lance_writerap(struct m147lance_private *lp, unsigned short value);
+static void m147lance_writerdp(struct m147lance_private *lp, unsigned short value);
+static unsigned short m147lance_readrdp(struct m147lance_private *lp);
+
+typedef void (*writerap_t)(void *, unsigned short);
+typedef void (*writerdp_t)(void *, unsigned short);
+typedef void (*readrdp_t)(void *);
+
+#ifdef MODULE
+static struct m147lance_private *root_m147lance_dev = NULL;
+#endif
+
+/* Initialise the one and only on-board 7990 */
+__initfunc(int mvme147lance_probe(struct device *dev))
+{
+       static int called = 0;
+       static const char name[] = "MVME147 LANCE";
+       struct m147lance_private *lp;
+       u_long *addr;
+       u_long address;
+
+       if (!MACH_IS_MVME147 || called)
+               return(ENODEV);
+       called++;
+
+       dev->priv = kmalloc(sizeof(struct m147lance_private), GFP_KERNEL);
+       if (dev->priv == NULL)
+               return -ENOMEM;
+       memset(dev->priv, 0, sizeof(struct m147lance_private));
+
+       /* Fill the dev fields */
+       dev->base_addr = (unsigned long)MVME147_LANCE_BASE;
+       dev->open = &m147lance_open;
+       dev->stop = &m147lance_close;
+       dev->hard_start_xmit = &lance_start_xmit;
+       dev->get_stats = &lance_get_stats;
+       dev->set_multicast_list = &lance_set_multicast;
+       dev->dma = 0;
+
+       addr=(u_long *)ETHERNET_ADDRESS;
+       address = *addr;
+       dev->dev_addr[0]=0x08;
+       dev->dev_addr[1]=0x00;
+       dev->dev_addr[2]=0x3e;
+       address=address>>8;
+       dev->dev_addr[5]=address&0xff;
+       address=address>>8;
+       dev->dev_addr[4]=address&0xff;
+       address=address>>8;
+       dev->dev_addr[3]=address&0xff;
+
+       printk("%s: MVME147 at 0x%08lx, irq %d, Hardware Address %02x:%02x:%02x:%02x:%02x:%02x\n",
+               dev->name, dev->base_addr, MVME147_LANCE_IRQ,
+               dev->dev_addr[0],
+               dev->dev_addr[1], dev->dev_addr[2],
+               dev->dev_addr[3], dev->dev_addr[4],
+               dev->dev_addr[5]);
+
+       lp = (struct m147lance_private *)dev->priv;
+       lp->ram = (void *)__get_dma_pages(GFP_ATOMIC, 3);       /* 16K */
+       if (!lp->ram)
+       {
+               printk("%s: No memory for LANCE buffers\n", dev->name);
+               return -ENODEV;
+       }
+
+       lp->lance.name = (char*)name;                   /* discards const, shut up gcc */
+       lp->lance.ll = (struct lance_regs *)(dev->base_addr);
+       lp->lance.init_block = (struct lance_init_block *)(lp->ram); /* CPU addr */
+       lp->lance.lance_init_block = (struct lance_init_block *)(lp->ram);                 /* LANCE addr of same RAM */
+       lp->lance.busmaster_regval = LE_C3_BSWP;        /* we're bigendian */
+       lp->lance.irq = MVME147_LANCE_IRQ;
+       lp->lance.writerap = (writerap_t)m147lance_writerap;
+       lp->lance.writerdp = (writerdp_t)m147lance_writerdp;
+       lp->lance.readrdp = (readrdp_t)m147lance_readrdp;
+       lp->lance.lance_log_rx_bufs = LANCE_LOG_RX_BUFFERS;
+       lp->lance.lance_log_tx_bufs = LANCE_LOG_TX_BUFFERS;
+       lp->lance.rx_ring_mod_mask = RX_RING_MOD_MASK;
+       lp->lance.tx_ring_mod_mask = TX_RING_MOD_MASK;
+       ether_setup(dev);
+
+#ifdef MODULE
+       dev->ifindex = dev_new_index();
+       lp->next_module = root_m147lance_dev;
+       root_m147lance_dev = lp;
+#endif /* MODULE */
+
+       return 0;
+}
+
+static void m147lance_writerap(struct m147lance_private *lp, unsigned short value)
+{
+       lp->lance.ll->rap = value;
+}
+
+static void m147lance_writerdp(struct m147lance_private *lp, unsigned short value)
+{
+       lp->lance.ll->rdp = value;
+}
+
+static unsigned short m147lance_readrdp(struct m147lance_private *lp)
+{
+       return lp->lance.ll->rdp;
+}
+
+static int m147lance_open(struct device *dev)
+{
+       int status;
+
+       status = lance_open(dev);                 /* call generic lance open code */
+       if (status)
+               return status;
+       /* enable interrupts at board level. */
+       m147_pcc->lan_cntrl=0;       /* clear the interrupts (if any) */
+       m147_pcc->lan_cntrl=0x08 | 0x04;     /* Enable irq 4 */
+
+       MOD_INC_USE_COUNT;
+       return 0;
+}
+
+static int m147lance_close(struct device *dev)
+{
+       /* disable interrupts at boardlevel */
+       m147_pcc->lan_cntrl=0x0; /* disable interrupts */
+       lance_close(dev);
+       MOD_DEC_USE_COUNT;
+       return 0;
+}
+
+#ifdef MODULE
+int init_module(void)
+{
+       root_lance_dev = NULL;
+       return mvme147lance_probe(NULL);
+}
+
+void cleanup_module(void)
+{
+       /* Walk the chain of devices, unregistering them */
+       struct m147lance_private *lp;
+       while (root_m147lance_dev) {
+               lp = root_m147lance_dev->next_module;
+               unregister_netdev(root_lance_dev->dev);
+               free_pages(lp->ram, 3);
+               kfree(root_lance_dev->dev);
+               root_lance_dev = lp;
+       }
+}
+
+#endif /* MODULE */
index ed768da54da4358901f7f723e8b954e02fd00941..1905874392a5da2446205f3151bc22a06d8c1c93 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: ptifddi.c,v 1.7 1999/06/09 08:19:01 davem Exp $
+/* $Id: ptifddi.c,v 1.8 1999/08/08 01:35:56 davem Exp $
  * ptifddi.c: Network driver for Performance Technologies single-attach
  *            and dual-attach FDDI sbus cards.
  *
index eaf8b66e36d4fa52925c31e6a89bfd193e4cfff3..b8bd189f8d40d6cb768c06782365c0a838779523 100644 (file)
@@ -152,14 +152,14 @@ int __init rr_hippi_probe (struct device *dev)
 
                printk(KERN_INFO "%s: Essential RoadRunner serial HIPPI "
                       "at 0x%08lx, irq %i, PCI latency %i\n", dev->name,
-                      pdev->base_address[0], dev->irq, pci_latency);
+                      pdev->resource[0].start, dev->irq, pci_latency);
 
                /*
                 * Remap the regs into kernel space.
                 */
 
                rrpriv->regs = (struct rr_regs *)
-                       ioremap(pdev->base_address[0], 0x1000);
+                       ioremap(pdev->resource[0].start, 0x1000);
 
                if (!rrpriv->regs){
                        printk(KERN_ERR "%s:  Unable to map I/O register, "
index 3de5624354dd2f28bece2d6cc209ff551fe0ebe8..f996f62d59f3dfe7f7bf00e4e241b9707f06429a 100644 (file)
@@ -246,7 +246,7 @@ static int __init sktr_pci_chk_card(struct device *dev)
 
                pdev            = pci_find_slot(pci_bus, pci_device_fn);
                pci_irq_line    = pdev->irq;
-               pci_ioaddr      = pdev->base_address[0];
+               pci_ioaddr      = pdev->resource[0].start;
 
                pcibios_read_config_word(pci_bus, pci_device_fn,
                                                PCI_COMMAND, &pci_command);
index c4cf074b2329132a200b59c44f62ae97a1d1aa80..526a7b1bb4a62f4d4a22cfb95504171ca58b89bf 100644 (file)
@@ -9,6 +9,9 @@
  * and pad structure members must be exchanged. Also, the structures
  * need to be changed accordingly to the bus size. 
  *
+ * 981229 MSch:        did just that for the 68k Mac port (32 bit, big endian),
+ *             see CONFIG_MACSONIC branch below.
+ *
  */
 
 #ifndef SONIC_H
 #define        SONIC_END_OF_LINKS      0x0001
 
 
+#ifdef CONFIG_MACSONIC
+/* Big endian like structures on Mac
+ * (680x0)
+ */
+
+typedef struct {
+  u32 rx_bufadr_l;     /* receive buffer ptr */
+  u32 rx_bufadr_h;
+
+  u32 rx_bufsize_l;    /* no. of words in the receive buffer */
+  u32 rx_bufsize_h;
+} sonic_rr_t;
+
+/*
+ * Sonic receive descriptor. Receive descriptors are
+ * kept in a linked list of these structures.
+ */
+
+typedef struct {
+  SREGS_PAD(pad0);
+  u16 rx_status;       /* status after reception of a packet */
+  SREGS_PAD(pad1);
+  u16 rx_pktlen;       /* length of the packet incl. CRC */
+  
+  /*
+   * Pointers to the location in the receive buffer area (RBA)
+   * where the packet resides. A packet is always received into
+   * a contiguous piece of memory.
+   */
+  SREGS_PAD(pad2);
+  u16 rx_pktptr_l;
+  SREGS_PAD(pad3);
+  u16 rx_pktptr_h;
+
+  SREGS_PAD(pad4);
+  u16 rx_seqno;        /* sequence no. */
+
+  SREGS_PAD(pad5);
+  u16 link;            /* link to next RDD (end if EOL bit set) */
+
+  /*
+   * Owner of this descriptor, 0= driver, 1=sonic
+   */
+  
+  SREGS_PAD(pad6);
+  u16 in_use;  
+
+  caddr_t rda_next;            /* pointer to next RD */
+} sonic_rd_t;
+
+
+/*
+ * Describes a Transmit Descriptor
+ */
+typedef struct {
+  SREGS_PAD(pad0);             
+  u16 tx_status;       /* status after transmission of a packet */
+  SREGS_PAD(pad1);             
+  u16 tx_config;       /* transmit configuration for this packet */
+  SREGS_PAD(pad2);             
+  u16 tx_pktsize;      /* size of the packet to be transmitted */
+  SREGS_PAD(pad3);             
+  u16 tx_frag_count;   /* no. of fragments */
+
+  SREGS_PAD(pad4);             
+  u16 tx_frag_ptr_l;
+  SREGS_PAD(pad5);             
+  u16 tx_frag_ptr_h;
+  SREGS_PAD(pad6);             
+  u16 tx_frag_size;
+  
+  SREGS_PAD(pad7);             
+  u16 link;            /* ptr to next descriptor */
+} sonic_td_t;
+
+
+/*
+ * Describes an entry in the CAM Descriptor Area.
+ */
+
+typedef struct {
+  SREGS_PAD(pad0);
+  u16 cam_entry_pointer;
+  SREGS_PAD(pad1);
+  u16 cam_cap0;
+  SREGS_PAD(pad2);
+  u16 cam_cap1;
+  SREGS_PAD(pad3);
+  u16 cam_cap2;
+} sonic_cd_t;
+
+#define CAM_DESCRIPTORS 16
+
+
+typedef struct {
+  sonic_cd_t cam_desc[CAM_DESCRIPTORS];
+  SREGS_PAD(pad);
+  u16 cam_enable;
+} sonic_cda_t;
+
+#else /* original declarations, little endian 32 bit */
+
 /*
  * structure definitions
  */
@@ -311,14 +416,23 @@ typedef struct {
   u16 cam_enable;
   SREGS_PAD(pad);
 } sonic_cda_t;
+#endif /* endianness */ 
 
 /*
  * Some tunables for the buffer areas. Power of 2 is required
  * the current driver uses one receive buffer for each descriptor.
+ *
+ * MSch: use more buffer space for the slow m68k Macs!
  */
+#ifdef CONFIG_MACSONIC
+#define SONIC_NUM_RRS    32             /* number of receive resources */
+#define SONIC_NUM_RDS    SONIC_NUM_RRS  /* number of receive descriptors */
+#define SONIC_NUM_TDS    32      /* number of transmit descriptors */
+#else
 #define SONIC_NUM_RRS    16             /* number of receive resources */
 #define SONIC_NUM_RDS    SONIC_NUM_RRS  /* number of receive descriptors */
 #define SONIC_NUM_TDS    16      /* number of transmit descriptors */
+#endif
 #define SONIC_RBSIZE   1520      /* size of one resource buffer */
 
 #define SONIC_RDS_MASK   (SONIC_NUM_RDS-1)
index 827a716b59ae07c8a5bf6cd2e094878b9e2a09aa..47cf165c5465c3589a13d96d67226a1a73918a93 100644 (file)
@@ -3325,11 +3325,10 @@ static int __init happy_meal_pci_init(struct device *dev, struct pci_dev *pdev)
        }               
 
        hpreg_base = pdev->resource[0].start;
-       if((pdev->resource[0].flags & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_MEMORY) {
+       if ((pdev->resource[0].flags & IORESOURCE_IOPORT) != 0) {
                printk("happymeal(PCI): Cannot find proper PCI device base address.\n");
                return ENODEV;
        }
-       hpreg_base &= PCI_BASE_ADDRESS_MEM_MASK;
 
        if (qfe_slot != -1 && prom_getproplen(node, "local-mac-address") == 6)
                prom_getproperty(node, "local-mac-address", dev->dev_addr, 6);
index 4d710fd517aa0f1d4df7e71dcc42d864809dd35f..6b03b1ad41e4b8cff46e513f00d92dff82b4d19e 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: sunlance.c,v 1.86 1999/07/23 01:52:58 davem Exp $
+/* $Id: sunlance.c,v 1.87 1999/08/08 01:36:14 davem Exp $
  * lance.c: Linux/Sparc/Lance driver
  *
  *     Written 1995, 1996 by Miguel de Icaza
index 4d716e7fb91dcb18bae297821a65f8008f976bda..5f8b91d13cc57884a1d7d2996a56be2a6f667e62 100644 (file)
@@ -25,7 +25,7 @@
 #ifdef DEBUG
 #define DPRINTK printk
 #else
-static inline int DPRINTK() {return 0;}
+#define DPRINTK(format, args...)
 #endif
 
 static struct parport *this_port = NULL;
@@ -64,7 +64,7 @@ static unsigned char control_amiga_to_pc(unsigned char control)
 {
        return PARPORT_CONTROL_SELECT |
              PARPORT_CONTROL_AUTOFD | PARPORT_CONTROL_STROBE;
-       /* fake value: select in, no reset,
+       /* fake value: interrupt enable, select in, no reset,
        no autolf, no strobe - seems to be closest the wiring diagram */
 }
 
@@ -138,7 +138,6 @@ 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 pardevice *dev, struct parport_state *s)
 {
        s->u.amiga.data = 0;
@@ -206,18 +205,18 @@ static struct parport_operations pp_amiga_ops = {
        amiga_inc_use_count,
        amiga_dec_use_count,
 
-       parport_ieee1284_epp_write_data,
-       parport_ieee1284_epp_read_data, /* impossible? */
-       parport_ieee1284_epp_write_addr,
-       parport_ieee1284_epp_read_addr, /* impossible? */
+       NULL, /* epp_write_data */
+       NULL, /* epp_read_data */
+       NULL, /* epp_write_addr */
+       NULL, /* epp_read_addr */
 
-       parport_ieee1284_ecp_write_data,
-       parport_ieee1284_ecp_read_data, /* impossible? */
-       parport_ieee1284_ecp_write_addr,
+       NULL, /* ecp_write_data */
+       NULL, /* ecp_read_data */
+       NULL, /* ecp_write_addr */
 
-       parport_ieee1284_write_compat, /* FIXME - need to write amiga one */
-       parport_ieee1284_read_nibble,
-       parport_ieee1284_read_byte, /* impossible? */
+       NULL, /* compat_write_data */
+       NULL, /* nibble_read_data */
+       NULL, /* byte_read_data */
 };
 
 /* ----------- Initialisation code --------------------------------- */
@@ -233,17 +232,17 @@ __initfunc(int parport_amiga_init(void))
                                        IRQ_AMIGA_CIAA_FLG, PARPORT_DMA_NONE,
                                        &pp_amiga_ops)))
                        return 0;
+               if (!request_irq(IRQ_AMIGA_CIAA_FLG, amiga_interrupt, 0, p->name, p)) {
+                       parport_unregister_port (p);
+                       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;
-               }
 
-               parport_announce_port (p);
+               parport_announce_port(p);
 
                return 1;
 
@@ -264,8 +263,8 @@ int init_module(void)
 
 void cleanup_module(void)
 {
-       if (p->irq != PARPORT_IRQ_NONE)
-               free_irq(IRQ_AMIGA_CIAA_FLG, p);
+       if (this_port->irq != PARPORT_IRQ_NONE)
+               free_irq(IRQ_MFP_BUSY, this_port);
        parport_proc_unregister(this_port);
        parport_unregister_port(this_port);
 }
index ddfd740681acf72a212b3ddc73fe8bdad363421b..8df0e5a33b8ca3447dd30322d73ba4fedad7f88b 100644 (file)
@@ -92,7 +92,7 @@ parport_atari_read_status(struct parport *p)
 }
 
 static void
-parport_atari_init_state(struct parport_state *s)
+parport_atari_init_state(struct pardevice *d, struct parport_state *s)
 {
 }
 
@@ -147,18 +147,18 @@ static struct parport_operations parport_atari_ops = {
        parport_atari_inc_use_count,
        parport_atari_dec_use_count,
 
-       parport_ieee1284_epp_write_data,
-       parport_ieee1284_epp_read_data,
-       parport_ieee1284_epp_write_addr,
-       parport_ieee1284_epp_read_addr,
+       NULL, /* epp_write_data */
+       NULL, /* epp_read_data */
+       NULL, /* epp_write_addr */
+       NULL, /* epp_read_addr */
 
-       parport_ieee1284_ecp_write_data,
-       parport_ieee1284_ecp_read_data,
-       parport_ieee1284_ecp_write_addr,
+       NULL, /* ecp_write_data */
+       NULL, /* ecp_read_data */
+       NULL, /* ecp_write_addr */
 
-       parport_ieee1284_write_compat,
-       parport_ieee1284_read_nibble,
-       parport_ieee1284_read_byte,
+       NULL, /* compat_write_data */
+       NULL, /* nibble_read_data */
+       NULL, /* byte_read_data */
 };
 
 
@@ -219,8 +219,8 @@ init_module(void)
 void
 cleanup_module(void)
 {
-       if (p->irq != PARPORT_IRQ_NONE)
-               free_irq(IRQ_MFP_BUSY, p);
+       if (this_port->irq != PARPORT_IRQ_NONE)
+               free_irq(IRQ_MFP_BUSY, this_port);
        parport_proc_unregister(this_port);
        parport_unregister_port(this_port);
 }
index 30c8a78677812578927ffcba009b4d63117a1a4f..938706d6db20b701d36d5e81d9ba5f23801ad0f6 100644 (file)
@@ -10,7 +10,6 @@
  *
  * 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
@@ -34,6 +33,9 @@
  * 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.
+ *
+ * Note that the ECP registers may not start at offset 0x400 for PCI cards,
+ * but rather will start at port->base_hi.
  */
 
 #include <linux/config.h>
@@ -74,7 +76,7 @@ static void frob_econtrol (struct parport *pb, unsigned char m,
        outb ((inb (ECONTROL (pb)) & ~m) ^ v, ECONTROL (pb));
 }
 
-#ifdef CONFIG_PARPORT_1284
+#if defined(CONFIG_PARPORT_1284) || defined(CONFIG_PARPORT_PC_FIFO)
 /* Safely change the mode bits in the ECR */
 static int change_mode(struct parport *p, int m)
 {
@@ -179,7 +181,7 @@ static int get_fifo_residue (struct parport *p)
        return residue;
 }
 
-#endif /* IEEE 1284 support */
+#endif /* IEEE 1284 support or FIFO support */
 
 /*
  * Clear TIMEOUT BIT in EPP MODE
@@ -1594,21 +1596,22 @@ struct parport *__maybe_init parport_pc_probe_port (unsigned long int base,
        }
        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) {
-               p->ops->compat_write_data =
-                       parport_pc_compat_write_block_pio;
+               p->ops->compat_write_data = parport_pc_compat_write_block_pio;
 #ifdef CONFIG_PARPORT_1284
-               p->ops->ecp_write_data =
-                       parport_pc_ecp_write_block_pio;
+               p->ops->ecp_write_data = parport_pc_ecp_write_block_pio;
 #endif /* IEEE 1284 support */
-               if (p->dma != PARPORT_DMA_NONE)
+               if (p->dma != PARPORT_DMA_NONE) {
+                       printk(", dma %d", p->dma);
                        p->modes |= PARPORT_MODE_DMA;
-               printk(", using FIFO");
+               }
+               else printk(", using FIFO");
        }
+       else
+               /* We can't use the DMA channel after all. */
+               p->dma = PARPORT_DMA_NONE;
 #endif /* Allowed to use FIFO/DMA */
 
        printk(" [");
index 63104929b270f8dc3ceb459b9ec9d141735f9f38..861b309d9c9f493600c741422544355ee2371e8b 100644 (file)
@@ -513,7 +513,7 @@ static int sprint_dev_config(struct pci_dev *dev, char *buf, int size)
                base = res->start;
                end = res->end;
                flags = res->flags;
-               if (!flags)
+               if (!end)
                        continue;
 
                if (flags & PCI_BASE_ADDRESS_SPACE_IO) {
index f9259bb761ab7c85de98075ea70be84cf6aef8c4..963c86f0c9edfecb6d3e9976b95fe6050cfd4d97 100644 (file)
@@ -1198,10 +1198,10 @@ NCR53c7x0_init (struct Scsi_Host *host) {
  *
  */
 
-__initfunc(static in
+static int  __ini
 normal_init (Scsi_Host_Template *tpnt, int board, int chip, 
     u32 base, int io_port, int irq, int dma, int pci_valid, 
-    unsigned char pci_bus, unsigned char pci_device_fn, long long options){
+    unsigned char pci_bus, unsigned char pci_device_fn, long long options){
     struct Scsi_Host *instance;
     struct NCR53c7x0_hostdata *hostdata;
     char chip_str[80];
@@ -1411,9 +1411,9 @@ normal_init (Scsi_Host_Template *tpnt, int board, int chip,
  *
  */
 
-__initfunc(static in
+static int  __ini
 ncr_pci_init (Scsi_Host_Template *tpnt, int board, int chip, 
-    unsigned char bus, unsigned char device_fn, long long options){
+    unsigned char bus, unsigned char device_fn, long long options){
     unsigned short command;
 #ifdef LINUX_1_2
     unsigned long
@@ -1445,8 +1445,8 @@ ncr_pci_init (Scsi_Host_Template *tpnt, int board, int chip,
                "        perhaps you specified an incorrect PCI bus, device, or function.\n", error);
        return -1;
     }
-    io_port = pdev->base_address[0];
-    base = pdev->base_address[1];
+    io_port = pdev->resource[0].start;
+    base = pdev->resource[1].start;
     irq = pdev->irq;
 
     /* If any one ever clones the NCR chips, this will have to change */
@@ -1560,8 +1560,8 @@ ncr_pci_init (Scsi_Host_Template *tpnt, int board, int chip,
  *
  */
 
-__initfunc(in
-NCR53c7xx_detect(Scsi_Host_Template *tpnt){
+int __ini
+NCR53c7xx_detect(Scsi_Host_Template *tpnt){
     int i;
     int current_override;
     int count;                 /* Number of boards detected */
index 475fb9ad539db768b1a2dd3c432bd6ee68ad69d0..f35145d21825f84db81eff218355ed825718a753 100644 (file)
  */
 #undef inb
 #undef outb
+#undef inw
+#undef outw
+#undef inl
+#undef outl
 #define inb(x)          1
 #define inw(x)          1
 #define inl(x)          1
@@ -1207,7 +1211,7 @@ ncr53c7xx_init (Scsi_Host_Template *tpnt, int board, int chip,
     memset((void *)instance->hostdata[0], 0, 8192);
     cache_push(virt_to_phys((void *)(instance->hostdata[0])), 8192);
     cache_clear(virt_to_phys((void *)(instance->hostdata[0])), 8192);
-    kernel_set_cachemode(instance->hostdata[0], 8192, KERNELMAP_NOCACHE_SER);
+    kernel_set_cachemode(instance->hostdata[0], 8192, IOMAP_NOCACHE_SER);
 
     /* FIXME : if we ever support an ISA NCR53c7xx based board, we
        need to check if the chip is running in a 16 bit mode, and if so 
@@ -1897,7 +1901,7 @@ abnormal_finished (struct NCR53c7x0_cmd *cmd, int result) {
     if (left < 0) 
        printk("scsi%d: loop detected in ncr reconncect list\n",
            host->host_no);
-    else if (ncr_search) 
+    else if (ncr_search) {
        if (found)
            printk("scsi%d: scsi %ld in ncr issue array and reconnect lists\n",
                host->host_no, c->pid);
@@ -1908,6 +1912,7 @@ abnormal_finished (struct NCR53c7x0_cmd *cmd, int result) {
 /* If we're at the tail end of the issue queue, update that pointer too. */
            found = 1;
        }
+    }
 
     /*
      * Traverse the host running list until we find this command or discover
@@ -2958,14 +2963,14 @@ NCR53c7x0_soft_reset (struct Scsi_Host *host) {
        NCR53c7x0_write8(DCNTL_REG, hostdata->saved_dcntl | DCNTL_SSM);
     else
        NCR53c7x0_write8(DCNTL_REG, hostdata->saved_dcntl);
-#if 0
-    /* Following disables snooping - run with caches disabled at first */
+    /* Following disables snooping - snooping is not required, as non-
+     * cached pages are used for shared data, and appropriate use is
+     * made of cache_push/cache_clear.  Indeed, for 68060
+     * enabling snooping causes disk corruption of ext2fs free block
+     * bitmaps and the like.  If you have a 68060 with snooping hardwared
+     * on, then you need to enable CONFIG_060_WRITETHROUGH.
+     */
     NCR53c7x0_write8(CTEST7_REG, CTEST7_10_TT1|CTEST7_STD);
-#else
-    /* Setup CTEST7 for SC1=0, SC0=1 - sink/source data without invalidating
-     * cache lines. */
-    NCR53c7x0_write8(CTEST7_REG, CTEST7_10_TT1|CTEST7_STD|CTEST7_10_SC0);
-#endif
     /* Actually burst of eight, according to my 53c710 databook */
     NCR53c7x0_write8(hostdata->dmode, DMODE_10_BL_8 | DMODE_10_FC2);
     NCR53c7x0_write8(SCID_REG, 1 << host->this_id);
@@ -3028,10 +3033,10 @@ NCR53c7x0_soft_reset (struct Scsi_Host *host) {
 static void
 my_free_page (void *addr, int dummy)
 {
-    /* XXX This assumes default cache mode to be KERNELMAP_FULL_CACHING, which
+    /* XXX This assumes default cache mode to be IOMAP_FULL_CACHING, which
      * XXX may be invalid (CONFIG_060_WRITETHROUGH)
      */
-    kernel_set_cachemode((u32)addr, 4096, KERNELMAP_FULL_CACHING);
+    kernel_set_cachemode((u32)addr, 4096, IOMAP_FULL_CACHING);
     free_page ((u32)addr);
 }
 
@@ -3087,7 +3092,7 @@ allocate_cmd (Scsi_Cmnd *cmd) {
         memset((void *)real, 0, 4096);
         cache_push(virt_to_phys((void *)real), 4096);
         cache_clear(virt_to_phys((void *)real), 4096);
-        kernel_set_cachemode(real, 4096, KERNELMAP_NOCACHE_SER);
+        kernel_set_cachemode(real, 4096, IOMAP_NOCACHE_SER);
        tmp = ROUNDUP(real, void *);
 #ifdef FORCE_DSA_ALIGNMENT
        {
@@ -3190,7 +3195,6 @@ create_cmd (Scsi_Cmnd *cmd) {
     case MODE_SELECT: 
     case WRITE_6:
     case WRITE_10:
-    case START_STOP: /* also SCAN, which may do DATA OUT */
 #if 0
        printk("scsi%d : command is ", host->host_no);
        print_command(cmd->cmnd);
@@ -3211,6 +3215,7 @@ create_cmd (Scsi_Cmnd *cmd) {
      */
     case TEST_UNIT_READY:
     case ALLOW_MEDIUM_REMOVAL:
+    case START_STOP:
        datain = dataout = 0;
        break;
     /*
@@ -5945,11 +5950,12 @@ ncr_halt (struct Scsi_Host *host) {
                }
            }
        }
-       if (!(istat & (ISTAT_SIP|ISTAT_DIP))) 
+       if (!(istat & (ISTAT_SIP|ISTAT_DIP))) {
            if (stage == 0)
                ++stage;
            else if (stage == 3)
                break;
+       }
     }
     hostdata->state = STATE_HALTED;
     restore_flags(flags);
@@ -6090,10 +6096,10 @@ NCR53c7x0_release(struct Scsi_Host *host) {
     if (hostdata->events) 
        vfree ((void *)hostdata->events);
 
-    /* XXX This assumes default cache mode to be KERNELMAP_FULL_CACHING, which
+    /* XXX This assumes default cache mode to be IOMAP_FULL_CACHING, which
      * XXX may be invalid (CONFIG_060_WRITETHROUGH)
      */
-    kernel_set_cachemode((u32)hostdata, 8192, KERNELMAP_FULL_CACHING);
+    kernel_set_cachemode((u32)hostdata, 8192, IOMAP_FULL_CACHING);
     free_pages ((u32)hostdata, 1);
     return 1;
 }
index 2508302508da24c36fbd126ef8812fa0c41dda8c..ae6bd13627d3b338daeecb82fb46168c9e625146 100644 (file)
@@ -1,4 +1,5 @@
 #include <linux/config.h>
+#include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
@@ -659,7 +660,7 @@ static __inline__ int AM53C974_pci_detect(Scsi_Host_Template * tpnt)
 * 
 * Returns : number of host adapters detected
 **************************************************************************/
-__initfunc(int AM53C974_detect(Scsi_Host_Template * tpnt))
+int __init AM53C974_detect(Scsi_Host_Template * tpnt)
 {
        int count = 0;          /* number of boards detected */
 
@@ -686,7 +687,7 @@ __initfunc(int AM53C974_detect(Scsi_Host_Template * tpnt))
 *       set up by the BIOS (as reflected by contents of register CNTLREG1).
 *       This is the only BIOS assistance we need.
 **************************************************************************/
-__initfunc(static int AM53C974_init(Scsi_Host_Template * tpnt, struct pci_dev *pdev))
+static int __init  AM53C974_init(Scsi_Host_Template * tpnt, struct pci_dev *pdev)
 {
        AM53C974_local_declare();
        int i, j;
@@ -701,7 +702,7 @@ __initfunc(static int AM53C974_init(Scsi_Host_Template * tpnt, struct pci_dev *p
        instance = scsi_register(tpnt, sizeof(struct AM53C974_hostdata));
        hostdata = (struct AM53C974_hostdata *) instance->hostdata;
        instance->base = NULL;
-       instance->io_port = pdev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK;
+       instance->io_port = pdev->resource[0].start;
        instance->irq = pdev->irq;
        instance->dma_channel = -1;
        AM53C974_setio(instance);
@@ -2467,5 +2468,9 @@ int AM53C974_release(struct Scsi_Host *shp)
 #ifdef MODULE
 static Scsi_Host_Template driver_template = AM53C974;
 
+/* You can specify overrides=a,b,c,d in the same format at AM53C974=a,b,c,d
+   on boot up */
+   
+MODULE_PARM(overrides, "1-32i");
 #include "scsi_module.c"
 #endif
index 56ae04b72f610124fbe227bbdd00b160971ca4a0..4b08067bab807608d1a0948c2e9d10e4321f9398 100644 (file)
@@ -736,12 +736,12 @@ static inline void NCR5380_all_init(void)
 
 static int probe_irq __initdata = 0;
 
-__initfunc(static void probe_intr(int irq, void *dev_id, struct pt_regs *regs))
+static void __init probe_intr(int irq, void *dev_id, struct pt_regs *regs)
 {
        probe_irq = irq;
 }
 
-__initfunc(static int NCR5380_probe_irq(struct Scsi_Host *instance, int possible))
+static int __init NCR5380_probe_irq(struct Scsi_Host *instance, int possible)
 {
        NCR5380_local_declare();
        struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *)
@@ -797,7 +797,7 @@ __initfunc(static int NCR5380_probe_irq(struct Scsi_Host *instance, int possible
  * Inputs : instance, pointer to this instance.  Unused.
  */
 
-__initfunc(static void NCR5380_print_options(struct Scsi_Host *instance))
+static void __init NCR5380_print_options(struct Scsi_Host *instance)
 {
        printk(" generic options"
 #ifdef AUTOPROBE_IRQ
@@ -1018,7 +1018,7 @@ char *lprint_opcode(int opcode, char *pos, char *buffer, int length)
  * 
  */
 
-__initfunc(static void NCR5380_init(struct Scsi_Host *instance, int flags))
+static void __init NCR5380_init(struct Scsi_Host *instance, int flags)
 {
        NCR5380_local_declare();
        int i, pass;
index e13d8a6325b43296b7dcf4f6f60d7153a416b41d..2f85cd32d05ada1c5f036d37f43da49591a9ed73 100644 (file)
@@ -461,8 +461,8 @@ static __inline__ int NCR53c406a_pio_write(unsigned char *request,
 }
 #endif USE_PIO
 
-__initfunc(in
-NCR53c406a_detect(Scsi_Host_Template * tpnt)){
+int  __ini
+NCR53c406a_detect(Scsi_Host_Template * tpnt){
     struct Scsi_Host *shpnt;
 #ifndef PORT_BASE
     int i;
@@ -593,7 +593,7 @@ NCR53c406a_detect(Scsi_Host_Template * tpnt)){
 }
 
 /* called from init/main.c */
-__initfunc(void NCR53c406a_setup(char *str, int *ints))
+void __init NCR53c406a_setup(char *str, int *ints)
 {
     static size_t setup_idx = 0;
     size_t i;
@@ -1022,7 +1022,7 @@ static void chip_init()
     outb(SYNC_MODE, SYNCOFF);   /* synchronous mode */  
 }
 
-__initfunc(void calc_port_addr(void))
+void __init calc_port_addr(void)
 {
     /* Control Register Set 0 */
     TC_LSB             = (port_base+0x00);
index 8537cf9bbf0e0fb22b638adeea1d1600ab46bda4..b1b6362f30a2f7bf96e75a7fd3e86150749eb656 100644 (file)
@@ -2,7 +2,7 @@ This file contains brief information about the SCSI tape driver.
 The driver is currently maintained by Kai M{kisara (email
 Kai.Makisara@metla.fi)
 
-Last modified: Sun Apr 18 13:24:43 1999 by makisara@home
+Last modified: Sat Aug  7 13:52:16 1999 by makisara@kai.makisara.local
 
 
 BASICS
@@ -130,22 +130,26 @@ closed. Buffer allocation uses chunks of memory having sizes
 2^n * (page size). Because of this the actual buffer size may be
 larger than the buffer size specified with ST_BUFFER_BLOCKS.
 
-Allocation of the buffers is done at run-time when they are
-needed. Allocation of the specified number of buffers can be done at
-initialization if ST_RUNTIME_BUFFERS is defined non-zero. The
-advantage of run-time allocation is that memory is not wasted for
-buffers not being used. The disadvantage is that there may not be
-memory available at the time when a buffer is needed for the first
-time (once a buffer is allocated, it is not released).
-
-The maximum number of buffers allocated at initialization is defined by
-ST_MAX_BUFFERS. One buffer is allocated for each drive detected when
-the driver is initialized up to the maximum. The minimum number of
-allocated buffers is ST_EXTRA_DEVS (in hosts.h). This ensures some
-functionality also for the drives found after tape driver
-initialization (a SCSI adapter driver is loaded as a module). The
-default for ST_EXTRA_DEVS is two. The driver tries to allocate new
-buffers at run-time if necessary.
+A small number of buffers are allocated at driver initialisation. The
+maximum number of these buffers is defined by ST_MAX_BUFFERS. The
+maximum can be changed with kernel or module startup options. One
+buffer is allocated for each drive detected when the driver is
+initialized up to the maximum. The minimum number of allocated buffers
+is ST_EXTRA_DEVS (in hosts.h) (unless this number exceeds the defined
+maximum). This ensures some functionality also for the drives found
+after tape driver initialization (a SCSI adapter driver is loaded as a
+module). The default for ST_EXTRA_DEVS is two.
+
+The driver tries to allocate new buffers at run-time if
+necessary. These buffers are freed after use. If the maximum number of
+initial buffers is set to zero, all buffer allocation is done at
+run-time. The advantage of run-time allocation is that memory is not
+wasted for buffers not being used. The disadvantage is that there may
+not be memory available at the time when a buffer is needed for the
+first time (once a buffer is allocated, it is not released). This risk
+should not be big if the tape drive is connected to a PCI adapter that
+supports scatter/gather (the allocation is not limited to "DMA memory"
+and the buffer can be composed of several fragments).
 
 The threshold for triggering asynchronous write in fixed block mode
 is defined by ST_WRITE_THRESHOLD. This may be optimized for each
@@ -178,31 +182,43 @@ is smaller than the number of segments used in phases 1 and 2,
 extending the buffer will always fail.
 
 
-BOOT TIME CONFIGURATION
+MODULE PARAMETERS
 
 The buffer size, write threshold, and the maximum number of allocated buffers
-are configurable at boot time using, e.g., the LILO command line. The option
-syntax is the following:
+are configurable when the driver is loaded as a module. The keywords are:
+
+buffer_kbs=xxx             the buffer size in kilobytes is set to xxx
+write_threshold_kbs=xxx    the write threshold in kilobytes set to xxx
+max_buffers=xxx            the maximum number of tape buffer set to xxx
+max_sg_segs=xxx                   the maximum number of scatter/gather
+                          segments
+
+Note that if the buffer size is changed but the write threshold is not
+set, the write threshold is set to the new buffer size - 2 kB.
+
+
+BOOT TIME CONFIGURATION
+
+If the driver is compiled into the kernel, the same parameters can be
+also set using, e.g., the LILO command line. The preferred syntax is
+to use the same keywords as when loading the driver as module. If
+several parameters are set, the keyword-value pairs are separated with
+a comma (no spaces allowed). A colon can be used instead of the equal
+mark. The definition is prepended by the string st=. Here is an
+example:
 
-           st=aa[,bb[,cc]]
+       st=buffer_kbs:64,max_buffers:2
+
+The following syntax used by the old kernel versions is also supported:
+
+           st=aa[,bb[,cc[,dd]]]
 
 where
   aa is the buffer size in 1024 byte units
   bb is the write threshold in 1024 byte units
   cc is the maximum number of tape buffers to allocate (the number of
         buffers is bounded also by the number of drives detected)
-
-
-MODULE PARAMETERS
-
-The same parameters can be also set when the driver is loaded as a
-module. The keywords are:
-
-buffer_kbs=xxx             the buffer size in kilobytes is set to xxx
-write_threshold_kbs=xxx    the write threshold in kilobytes set to xxx
-max_buffers=xxx            the maximum number of tape buffer set to xxx
-max_sg_segs=xxx                   the maximum number of scatter/gather
-                          segments
+  dd is the maximum number of scatter/gather segments
 
 
 IOCTLS
index 0fcf5cabb5879df9ffcab91c7bf97e216f86a9fa..fd4959d42e00e309007380f3c4bcbd2d27544f2d 100644 (file)
@@ -828,8 +828,8 @@ static inline int read_pio(unsigned long iobase, ushort *start, ushort *end) {
    return FALSE;
 }
 
-__initfunc (static inline int
-            get_pci_irq(unsigned long port_base, unsigned char *apic_irq)) {
+static inline int __init 
+get_pci_irq(unsigned long port_base, unsigned char *apic_irq){
 
 #if defined(CONFIG_PCI)
 
@@ -866,8 +866,8 @@ __initfunc (static inline int
    return FALSE;
 }
 
-__initfunc (static inline int port_detect \
-      (unsigned long port_base, unsigned int j, Scsi_Host_Template *tpnt){
+static inline int __init port_detect \
+      (unsigned long port_base, unsigned int j, Scsi_Host_Template *tpnt){
    unsigned char irq, dma_channel, subversion, i;
    unsigned char protocol_rev, apic_irq;
    struct eata_info info;
@@ -1151,7 +1151,7 @@ __initfunc (static inline int port_detect \
    return TRUE;
 }
 
-__initfunc (void eata2x_setup(char *str, int *ints)) {
+void  __init eata2x_setup(char *str, int *ints){
    int i, argc = ints[0];
    char *cur = str, *pc;
 
@@ -1187,7 +1187,7 @@ __initfunc (void eata2x_setup(char *str, int *ints)) {
    return;
 }
 
-__initfunc (static void add_pci_ports(void)) {
+static void __init add_pci_ports(void){
 
 #if defined(CONFIG_PCI)
 
@@ -1253,7 +1253,7 @@ __initfunc (static void add_pci_ports(void)) {
    return;
 }
 
-__initfunc (int eata2x_detect(Scsi_Host_Template *tpnt)) {
+int __init eata2x_detect(Scsi_Host_Template *tpnt){
    unsigned int j = 0, k;
    IRQ_FLAGS
 
index 760b3fbc5617389c2df5ef16b2ba88ceb9da3de5..4fea48e7e9cf4daf0043dc7b893005542785f8e4 100644 (file)
@@ -840,14 +840,14 @@ static int fdomain_pci_bios_detect( int *irq, int *iobase )
    /* We now have the appropriate device function for the FD board so we
       just read the PCI config info from the registers.  */
 
-   pci_base = pdev->base_address[0];
+   pci_base = pdev->resource[0].start;
    pci_irq = pdev->irq;
 
    /* Now we have the I/O base address and interrupt from the PCI
       configuration registers. */
 
    *irq    = pci_irq;
-   *iobase = (pci_base & PCI_BASE_ADDRESS_IO_MASK);
+   *iobase = pci_base;
 
 #if DEBUG_DETECT
    printk( "scsi: <fdomain> TMC-3260 detect:"
index ec1f6edc8569eed2e41713cbbdca9815e175fd6e..875da3846e8bfa3b9a0e5e17d1c7e7b919b382f0 100644 (file)
@@ -158,7 +158,7 @@ static struct override {
  *
  */
 
-__initfunc(static void internal_setup(int board, char *str, int *ints)) {
+static void __init internal_setup(int board, char *str, int *ints){
     static int commandline_current = 0;
     switch (board) {
     case BOARD_NCR5380:
@@ -204,7 +204,7 @@ __initfunc(static void internal_setup(int board, char *str, int *ints)) {
  *     equal to the number of ints.
  */
 
-__initfunc(void generic_NCR5380_setup (char *str, int *ints)) {
+void __init generic_NCR5380_setup (char *str, int *ints){
     internal_setup (BOARD_NCR5380, str, ints);
 }
 
@@ -217,7 +217,7 @@ __initfunc(void generic_NCR5380_setup (char *str, int *ints)) {
  *     equal to the number of ints.
  */
 
-__initfunc(void generic_NCR53C400_setup (char *str, int *ints)) {
+void __init generic_NCR53C400_setup (char *str, int *ints){
     internal_setup (BOARD_NCR53C400, str, ints);
 }
 
@@ -259,7 +259,7 @@ void generic_DTC3181E_setup (char *str, int *ints) {
  *
  */
 
-__initfunc(int generic_NCR5380_detect(Scsi_Host_Template * tpnt)) {
+int __init generic_NCR5380_detect(Scsi_Host_Template * tpnt){
     static int current_override = 0;
     int count, i;
     u_int *ports;
index 63468443a9630e89656284e8b369f3e0a8683af0..cd6fda3caa2875b63ad8140e7293c82a07a2c736 100644 (file)
@@ -598,7 +598,7 @@ static void gdth_eval_mapping(ulong32 size, int *cyls, int *heads, int *secs)
 
 /* controller search and initialization functions */
 
-__initfunc (static int gdth_search_eisa(ushort eisa_adr))
+static int __init gdth_search_eisa(ushort eisa_adr)
 {
     ulong32 id;
     
@@ -616,7 +616,7 @@ __initfunc (static int gdth_search_eisa(ushort eisa_adr))
 }
 
 
-__initfunc (static int gdth_search_isa(ulong32 bios_adr))
+static int __init gdth_search_isa(ulong32 bios_adr)
 {
     void *addr;
     ulong32 id;
@@ -632,7 +632,7 @@ __initfunc (static int gdth_search_isa(ulong32 bios_adr))
 }
 
 
-__initfunc (static int gdth_search_pci(gdth_pci_str *pcistr))
+static int __init gdth_search_pci(gdth_pci_str *pcistr)
 {
     ulong32 base0, base1, base2;
     ushort device_id, cnt;
@@ -651,7 +651,6 @@ __initfunc (static int gdth_search_pci(gdth_pci_str *pcistr))
         if (device_id > PCI_DEVICE_ID_VORTEX_GDT6555 &&
             device_id < PCI_DEVICE_ID_VORTEX_GDT6x17RP)
             continue;
-#if LINUX_VERSION_CODE >= 0x2015C
         pdev = NULL;
         while ((pdev = pci_find_device(PCI_VENDOR_ID_VORTEX,device_id,pdev)) 
                != NULL) {
@@ -663,15 +662,15 @@ __initfunc (static int gdth_search_pci(gdth_pci_str *pcistr))
             pcistr[cnt].bus = pdev->bus->number;
             pcistr[cnt].device_fn = pdev->devfn;
             pcistr[cnt].irq = pdev->irq;
-            base0 = pdev->base_address[0];
-            base1 = pdev->base_address[1];
-            base2 = pdev->base_address[2];
+            base0 = pdev->resource[0].flags;
+            base1 = pdev->resource[1].flags;
+            base2 = pdev->resource[2].flags;
             if (device_id <= PCI_DEVICE_ID_VORTEX_GDT6000B ||   /* GDT6000/B */
                 device_id >= PCI_DEVICE_ID_VORTEX_GDT6x17RP) {  /* MPR */
                 if ((base0 & PCI_BASE_ADDRESS_SPACE) != 
                     PCI_BASE_ADDRESS_SPACE_MEMORY)
                     continue;
-                pcistr[cnt].dpmem = base0 & PCI_BASE_ADDRESS_MEM_MASK;
+                pcistr[cnt].dpmem = pdev->resource[0].start;
             } else {                                    /* GDT6110, GDT6120, .. */
                 if ((base0 & PCI_BASE_ADDRESS_SPACE) !=
                     PCI_BASE_ADDRESS_SPACE_MEMORY ||
@@ -680,77 +679,21 @@ __initfunc (static int gdth_search_pci(gdth_pci_str *pcistr))
                     (base1 & PCI_BASE_ADDRESS_SPACE) !=
                     PCI_BASE_ADDRESS_SPACE_IO)
                     continue;
-                pcistr[cnt].dpmem = base2 & PCI_BASE_ADDRESS_MEM_MASK;
-                pcistr[cnt].io_mm = base0 & PCI_BASE_ADDRESS_MEM_MASK;
-                pcistr[cnt].io    = base1 & PCI_BASE_ADDRESS_IO_MASK;
+                pcistr[cnt].dpmem = pdev->resource[2].start;
+                pcistr[cnt].io_mm = pdev->resource[0].start;
+                pcistr[cnt].io    = pdev->resource[1].start;
             }
             TRACE2(("Controller found at %d/%d, irq %d, dpmem 0x%x\n",
                     pcistr[cnt].bus, PCI_SLOT(pcistr[cnt].device_fn), 
                     pcistr[cnt].irq, pcistr[cnt].dpmem));
             cnt++;
         }       
-#else   
-        idx = 0;
-        while (!pcibios_find_device(PCI_VENDOR_ID_VORTEX,device_id,idx++,
-                                    &pcistr[cnt].bus,&pcistr[cnt].device_fn)) {
-            if (cnt >= MAXHA)
-                return cnt;
-            /* GDT PCI ctr. found, now read resources from config space */
-#if LINUX_VERSION_CODE >= 0x010300
-#define GDTH_BASEP      (int *)
-#else
-#define GDTH_BASEP
-#endif
-            if ((error = pcibios_read_config_dword(pcistr[cnt].bus,
-                                                   pcistr[cnt].device_fn,
-                                                   PCI_BASE_ADDRESS_0,
-                                                   GDTH_BASEP&base0)) ||
-                (error = pcibios_read_config_dword(pcistr[cnt].bus,
-                                                   pcistr[cnt].device_fn,
-                                                   PCI_BASE_ADDRESS_1,
-                                                   GDTH_BASEP&base1)) ||
-                (error = pcibios_read_config_dword(pcistr[cnt].bus,
-                                                   pcistr[cnt].device_fn,
-                                                   PCI_BASE_ADDRESS_2,
-                                                   GDTH_BASEP&base2)) ||
-                (error = pcibios_read_config_byte(pcistr[cnt].bus,
-                                                  pcistr[cnt].device_fn,
-                                                  PCI_INTERRUPT_LINE,
-                                                  &pcistr[cnt].irq))) {
-                printk("GDT-PCI: error %d reading configuration space", error);
-                continue;
-            }
-            pcistr[cnt].device_id = device_id;
-            if (device_id <= PCI_DEVICE_ID_VORTEX_GDT6000B ||   /* GDT6000/B */
-                device_id >= PCI_DEVICE_ID_VORTEX_GDT6x17RP) {  /* MPR */
-                if ((base0 & PCI_BASE_ADDRESS_SPACE) !=
-                    PCI_BASE_ADDRESS_SPACE_MEMORY)
-                    continue;
-                pcistr[cnt].dpmem = base0 & PCI_BASE_ADDRESS_MEM_MASK;
-            } else {                                    /* GDT6110, GDT6120, .. */
-                if ((base0 & PCI_BASE_ADDRESS_SPACE) !=
-                    PCI_BASE_ADDRESS_SPACE_MEMORY ||
-                    (base2 & PCI_BASE_ADDRESS_SPACE) !=
-                    PCI_BASE_ADDRESS_SPACE_MEMORY ||
-                    (base1 & PCI_BASE_ADDRESS_SPACE) !=
-                    PCI_BASE_ADDRESS_SPACE_IO)
-                    continue;
-                pcistr[cnt].dpmem = base2 & PCI_BASE_ADDRESS_MEM_MASK;
-                pcistr[cnt].io_mm = base0 & PCI_BASE_ADDRESS_MEM_MASK;
-                pcistr[cnt].io    = base1 & PCI_BASE_ADDRESS_IO_MASK;
-            }
-            TRACE2(("Controller found at %d/%d, irq %d, dpmem 0x%x\n",
-                    pcistr[cnt].bus, PCI_SLOT(pcistr[cnt].device_fn), 
-                    pcistr[cnt].irq, pcistr[cnt].dpmem));
-            cnt++;
-        }
-#endif
     }   
     return cnt;
 }
 
 
-__initfunc (static void gdth_sort_pci(gdth_pci_str *pcistr, int cnt))
+static void __init gdth_sort_pci(gdth_pci_str *pcistr, int cnt)
 {    
     gdth_pci_str temp;
     int i, changed;
@@ -788,7 +731,7 @@ __initfunc (static void gdth_sort_pci(gdth_pci_str *pcistr, int cnt))
 }
 
 
-__initfunc (static int gdth_init_eisa(ushort eisa_adr,gdth_ha_str *ha))
+static int __init gdth_init_eisa(ushort eisa_adr,gdth_ha_str *ha)
 {
     ulong32 retries,id;
     unchar prot_ver,eisacf,i,irq_found;
@@ -877,7 +820,7 @@ __initfunc (static int gdth_init_eisa(ushort eisa_adr,gdth_ha_str *ha))
 }
 
        
-__initfunc (static int gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha))
+static int __init gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha)
 {
     register gdt2_dpram_str *dp2_ptr;
     int i;
@@ -974,7 +917,7 @@ __initfunc (static int gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha))
 }
 
 
-__initfunc (static int gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha))
+static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
 {
     register gdt6_dpram_str *dp6_ptr;
     register gdt6c_dpram_str *dp6c_ptr;
@@ -1241,7 +1184,7 @@ __initfunc (static int gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha))
 
 /* controller protocol functions */
 
-__initfunc (static void gdth_enable_int(int hanum))
+static void __init gdth_enable_int(int hanum)
 {
     gdth_ha_str *ha;
     ulong flags;
@@ -1574,7 +1517,7 @@ static int gdth_internal_cmd(int hanum,unchar service,ushort opcode,ulong32 p1,
 
 /* search for devices */
 
-__initfunc (static int gdth_search_drives(int hanum))
+static int __init gdth_search_drives(int hanum)
 {
     register gdth_ha_str *ha;
     ushort cdev_cnt, i;
@@ -3287,7 +3230,7 @@ void gdth_timeout(ulong data)
 #endif
 
 
-__initfunc (int gdth_detect(Scsi_Host_Template *shtp))
+int __init gdth_detect(Scsi_Host_Template *shtp)
 {
     struct Scsi_Host *shp;
     gdth_ha_str *ha;
@@ -3959,7 +3902,7 @@ void gdth_halt(void)
 
 
 /* called from init/main.c */
-__initfunc (void gdth_setup(char *str,int *ints))
+void __init gdth_setup(char *str,int *ints)
 {
     int i, argc;
     char *cur_str, *argv;
index 0999b88d8e3ba318d64189a0cfa571ebd8c0ad8b..bb93250eb64f3b0016a2130e7f519fb40f3b17b6 100644 (file)
@@ -752,7 +752,7 @@ static void launch_error_handler_thread(struct Scsi_Host * shpnt)
             shpnt->eh_notify = NULL;
 }
 
-__initfunc(unsigned int scsi_init(void))
+unsigned int __init scsi_init(void)
 {
     static int called = 0;
     int i, pcount;
index c6ce1c7378eaf9bbab1b51f0cfb2f7c0faf7faf2..af6b7d9aab40b56a7f10fd6f575efb5ed0f11477 100644 (file)
@@ -348,7 +348,7 @@ int tul_NewReturnNumberOfAdapters(void)
                                dRegValue = 0;
                        wBIOS = (wBIOS << 8) + ((UWORD) ((dRegValue & 0xFF00) >> 8));
                        if (Addi91u_into_Adapter_table(wBIOS,
-                                                       (pDev->base_address[0] & 0xFFFE),
+                                                       (pDev->resource[0].start),
                                                        pDev->irq,
                                                        pDev->bus->number,
                                                        (pDev->devfn >> 3)
index 870b24e6c97cd6c0114aaa056b087c384ccf8aa2..0e40264eddb369168204ec30ed81c67096d289e1 100644 (file)
@@ -330,7 +330,7 @@ int orc_ReturnNumberOfAdapters(void)
 #if LINUX_VERSION_CODE > CVT_LINUX_VERSION(2,1,92)
                                        bPCIBusNum = pdev->bus->number;
                                        bPCIDeviceNum = pdev->devfn;
-                                       dRegValue = pdev->base_address[0];
+                                       dRegValue = pdev->resource[0].start;
                                        if (dRegValue == -1) {  /* Check return code            */
                                                printk("\n\rinia100: orchid read configuration error.\n");
                                                return (0);     /* Read configuration space error  */
index e90e4132f3e5d6dc6693a808b6326880a5944e07..9ef1016abd40a3b73611946c6626e50b21bf8a87 100644 (file)
@@ -1267,17 +1267,8 @@ int findCard (Scsi_Host_Template * pHostTmpl,
            PCI_FUNC (pciDevFun));
 
     /* Read the base port and IRQ from PCI */
-#if LINUX_VERSION_CODE < 0x20100
-    pcibios_read_config_dword (pciBus, pciDevFun,
-                              PCI_BASE_ADDRESS_0,
-                              (u_int *) & megaBase);
-    pcibios_read_config_byte (pciBus, pciDevFun,
-                             PCI_INTERRUPT_LINE,
-                             &megaIrq);
-#else
-    megaBase = pdev->base_address[0];
+    megaBase = pdev->resource[0].start;
     megaIrq  = pdev->irq;
-#endif
     pciIdx++;
 
     if (flag & BOARD_QUARTZ) {
index a65ab21c9734defaa2c9afad3773897ecae19ecb..e73fb0f995e87b98164852269e9e66e8e529d764 100644 (file)
@@ -213,8 +213,8 @@ unsigned short  pas16_offset[ 8 ] =
  *
  */
 
-__initfunc(static void
-       enable_board( int  board_num,  unsigned short port ))
+static void __init
+       enable_board( int  board_num,  unsigned short port )
 {
     outb( 0xbc + board_num, MASTER_ADDRESS_PTR );
     outb( port >> 2, MASTER_ADDRESS_PTR );
@@ -233,8 +233,8 @@ __initfunc(static void
  *
  */
 
-__initfunc (static void
-       init_board( unsigned short io_port, int irq, int force_irq ))
+static void __init 
+       init_board( unsigned short io_port, int irq, int force_irq )
 {
        unsigned int    tmp;
        unsigned int    pas_irq_code;
@@ -282,8 +282,8 @@ __initfunc (static void
  * Returns : 0 if board not found, 1 if found.
  */
 
-__initfunc(static int
-     pas16_hw_detect( unsigned short  board_num ))
+static int __init 
+     pas16_hw_detect( unsigned short  board_num )
 {
     unsigned char      board_rev, tmp;
     unsigned short     io_port = bases[ board_num ].io_port;
@@ -342,7 +342,8 @@ __initfunc(static int
  *
  */
 
-__initfunc(void pas16_setup(char *str, int *ints)) {
+void __init pas16_setup(char *str, int *ints)
+{
     static int commandline_current = 0;
     int i;
     if (ints[0] != 2) 
@@ -373,7 +374,8 @@ __initfunc(void pas16_setup(char *str, int *ints)) {
  *
  */
 
-__initfunc(int pas16_detect(Scsi_Host_Template * tpnt)) {
+int __init pas16_detect(Scsi_Host_Template * tpnt)
+{
     static int current_override = 0;
     static unsigned short current_base = 0;
     struct Scsi_Host *instance;
index 72a9dfc7c89b1feb3a87c69ff6e332237bd9d05c..33518cd397377e6f84c79cc01bf6f236538556ae 100644 (file)
@@ -1054,6 +1054,7 @@ static int sr_packet(struct cdrom_device_info *cdi, struct cdrom_generic_command
        /* do the locking and issue the command */
        SCpnt->request.rq_dev = cdi->dev;
        SCpnt->request.rq_status = RQ_SCSI_BUSY;
+       /* scsi_do_cmd sets the command length */
        SCpnt->cmd_len = 0;
        SCpnt->request.sem = &sem;
        spin_lock_irqsave(&io_request_lock, flags);
index d43121e680915dd83fed5f1c5aa1028802d16117..939c911c61fcc8ef953a2f82ffc6ac037ca42be1 100644 (file)
@@ -11,7 +11,7 @@
   Copyright 1992 - 1999 Kai Makisara
                 email Kai.Makisara@metla.fi
 
-  Last modified: Tue May 18 08:32:34 1999 by makisara@home
+  Last modified: Sat Aug  7 13:54:31 1999 by makisara@kai.makisara.local
   Some small formal changes - aeb, 950809
 */
 
 
 #include "constants.h"
 
+static int buffer_kbs = 0;
+static int write_threshold_kbs = 0;
+static int max_buffers = (-1);
+static int max_sg_segs = 0;
 #ifdef MODULE
+MODULE_AUTHOR("Kai Makisara");
+MODULE_DESCRIPTION("SCSI Tape Driver");
 MODULE_PARM(buffer_kbs, "i");
 MODULE_PARM(write_threshold_kbs, "i");
 MODULE_PARM(max_buffers, "i");
 MODULE_PARM(max_sg_segs, "i");
-static int buffer_kbs = 0;
-static int write_threshold_kbs = 0;
-static int max_buffers = 0;
-static int max_sg_segs = 0;
+#else
+static struct st_dev_parm {
+    char *name;
+    int *val;
+} parms[] __initdata = {
+    {"buffer_kbs", &buffer_kbs},
+    {"write_threshold_kbs", &write_threshold_kbs},
+    {"max_buffers", &max_buffers},
+    {"max_sg_segs", &max_sg_segs}};
 #endif
 
+
 /* The default definitions have been moved to st_options.h */
 
 #define ST_BUFFER_SIZE (ST_BUFFER_BLOCKS * ST_KILOBYTE)
@@ -183,7 +195,7 @@ st_chk_result(Scsi_Cmnd * SCpnt)
     else
       printk(KERN_WARNING
             "st%d: Error %x (sugg. bt 0x%x, driver bt 0x%x, host bt 0x%x).\n",
-            dev, result, suggestion(result), driver_byte(result),
+            dev, result, suggestion(result), driver_byte(result) & DRIVER_MASK,
             host_byte(result));
   }
 
@@ -3318,23 +3330,66 @@ from_buffer(ST_buffer *st_bp, char *ubp, int do_count)
 }
 
 
+/* Validate the options from command line or module parameters */
+static void validate_options(void)
+{
+    if (buffer_kbs > 0)
+       st_buffer_size = buffer_kbs * ST_KILOBYTE;
+    if (write_threshold_kbs > 0)
+       st_write_threshold = write_threshold_kbs * ST_KILOBYTE;
+    else if (buffer_kbs > 0)
+       st_write_threshold = st_buffer_size - 2048;
+    if (st_write_threshold > st_buffer_size) {
+       st_write_threshold = st_buffer_size;
+       printk(KERN_WARNING "st: write_threshold limited to %d bytes.\n",
+              st_write_threshold);
+    }
+    if (max_buffers >= 0)
+       st_max_buffers = max_buffers;
+    if (max_sg_segs >= ST_FIRST_SG)
+       st_max_sg_segs = max_sg_segs;
+}
+
 #ifndef MODULE
-/* Set the boot options. Syntax: st=xxx,yyy
-   where xxx is buffer size in 1024 byte blocks and yyy is write threshold
-   in 1024 byte blocks. */
-       __initfunc( void
-st_setup(char *str, int *ints))
+/* Set the boot options. Syntax is defined in README.st.
+*/
+static int __init st_setup(char *str)
 {
-  if (ints[0] > 0 && ints[1] > 0)
-    st_buffer_size = ints[1] * ST_KILOBYTE;
-  if (ints[0] > 1 && ints[2] > 0) {
-    st_write_threshold = ints[2] * ST_KILOBYTE;
-    if (st_write_threshold > st_buffer_size)
-      st_write_threshold = st_buffer_size;
-  }
-  if (ints[0] > 2 && ints[3] > 0)
-    st_max_buffers = ints[3];
+    int i, len, ints[5];
+    char *stp;
+
+    stp = get_options(str, ARRAY_SIZE(ints), ints);
+
+    if (ints[0] > 0) {
+       for (i=0; i < ints[0] && i < ARRAY_SIZE(parms) ; i++)
+           *parms[i].val = ints[i + 1];
+    }
+    else {
+       while (stp != NULL) {
+           for (i=0; i < ARRAY_SIZE(parms); i++) {
+               len = strlen(parms[i].name);
+               if (!strncmp(stp, parms[i].name, len) &&
+                   (*(stp + len) == ':' || *(stp + len) == '=')) {
+                   *parms[i].val = simple_strtoul(stp + len + 1, NULL, 0);
+                   break;
+               }
+           }
+           if (i >= sizeof(parms) / sizeof(struct st_dev_parm))
+               printk(KERN_WARNING "st: illegal parameter in '%s'\n",
+                      stp);
+           stp = strchr(stp, ',');
+           if (stp)
+               stp++;
+       }
+    }
+
+    validate_options();
+
+    return 1;
 }
+
+__setup("st=", st_setup);
+
 #endif
 
 
@@ -3449,12 +3504,13 @@ static int st_init()
 {
   int i;
   Scsi_Tape * STp;
-#if !ST_RUNTIME_BUFFERS
   int target_nbr;
-#endif
 
   if (st_template.dev_noticed == 0) return 0;
 
+  printk(KERN_INFO "st: bufsize %d, wrt %d, max init. buffers %d, s/g segs %d.\n",
+        st_buffer_size, st_write_threshold, st_max_buffers, st_max_sg_segs);
+
   if(!st_registered) {
     if (register_chrdev(SCSI_TAPE_MAJOR,"st",&st_fops)) {
       printk(KERN_ERR "Unable to get major %d for SCSI tapes\n",MAJOR_NR);
@@ -3505,9 +3561,6 @@ static int st_init()
     return 1;
   }
 
-#if ST_RUNTIME_BUFFERS
-  st_nbr_buffers = 0;
-#else
   target_nbr = st_template.dev_noticed;
   if (target_nbr < ST_EXTRA_DEVS)
     target_nbr = ST_EXTRA_DEVS;
@@ -3517,24 +3570,14 @@ static int st_init()
   for (i=st_nbr_buffers=0; i < target_nbr; i++) {
     if (!new_tape_buffer(TRUE, TRUE)) {
       if (i == 0) {
-#if 0
-       printk(KERN_ERR "Can't continue without at least one tape buffer.\n");
-       unregister_chrdev(SCSI_TAPE_MAJOR, "st");
-       scsi_init_free((char *) st_buffers,
-                      st_template.dev_max * sizeof(ST_buffer *));
-       scsi_init_free((char *) scsi_tapes,
-                      st_template.dev_max * sizeof(Scsi_Tape));
-       return 1;
-#else
        printk(KERN_INFO "No tape buffers allocated at initialization.\n");
        break;
-#endif
       }
       printk(KERN_INFO "Number of tape buffers adjusted.\n");
       break;
     }
   }
-#endif
+
   return 0;
 }
 
@@ -3557,21 +3600,10 @@ static void st_detach(Scsi_Device * SDp)
 
 #ifdef MODULE
 
-int init_module(void) {
+int __init init_module(void) {
   int result;
 
-  if (buffer_kbs > 0)
-      st_buffer_size = buffer_kbs * ST_KILOBYTE;
-  if (write_threshold_kbs > 0)
-      st_write_threshold = write_threshold_kbs * ST_KILOBYTE;
-  if (st_write_threshold > st_buffer_size)
-      st_write_threshold = st_buffer_size;
-  if (max_buffers > 0)
-      st_max_buffers = max_buffers;
-  if (max_sg_segs >= ST_FIRST_SG)
-      st_max_sg_segs = max_sg_segs;
-  printk(KERN_INFO "st: bufsize %d, wrt %d, max buffers %d, s/g segs %d.\n",
-        st_buffer_size, st_write_threshold, st_max_buffers, st_max_sg_segs);
+  validate_options();
 
   st_template.module = &__this_module;
   result = scsi_register_module(MODULE_SCSI_DEV, &st_template);
index 4df4f91ca0d2e2f9b8979bb2495e606d83f5b900..cca95103647633f1bdbe297cfc9ddd53c67d9359 100644 (file)
@@ -1,20 +1,14 @@
 /*
    The compile-time configurable defaults for the Linux SCSI tape driver.
 
-   Copyright 1995 Kai Makisara.
+   Copyright 1995-1999 Kai Makisara.
 
-   Last modified: Wed Sep  2 21:24:07 1998 by root@home
+   Last modified: Sat Aug  7 13:42:21 1999 by makisara@kai.makisara.local
 */
 
 #ifndef _ST_OPTIONS_H
 #define _ST_OPTIONS_H
 
-/* The driver allocates the tape buffers when needed if ST_RUNTIME_BUFFERS
-   is nonzero. Otherwise a number of buffers are allocated at initialization.
-   The drawback of runtime allocation is that allocation may fail. In any
-   case the driver tries to allocate a new tape buffer when none is free. */
-#define ST_RUNTIME_BUFFERS 0
-
 /* The minimum limit for the number of SCSI tape devices is determined by
    ST_MAX_TAPES. If the number of tape devices and the "slack" defined by
    ST_EXTRA_DEVS exceeds ST_MAX_TAPES, the large number is used. */
    below. */
 #define ST_WRITE_THRESHOLD_BLOCKS 30
 
-/* The maximum number of tape buffers the driver allocates. The number
-   is also constrained by the number of drives detected. Determines the
-   maximum number of concurrently active tape drives. */
+/* The maximum number of tape buffers the driver tries to allocate at 
+   driver initialisation. The number is also constrained by the number
+   of drives detected. If more buffers are needed, they are allocated
+   at run time and freed after use. */
 #define ST_MAX_BUFFERS (2 + ST_EXTRA_DEVS)
 
 /* Maximum number of scatter/gather segments */
index e9c82a413d07c79d2d264971ca18df176f43b20a..2fdf0c3cd781c84fff2f92542708ba84f7eeed17 100644 (file)
@@ -168,7 +168,7 @@ static const struct signature {
  *
  */
 
-__initfunc(void t128_setup(char *str, int *ints)) {
+void __init t128_setup(char *str, int *ints){
     static int commandline_current = 0;
     int i;
     if (ints[0] != 2) 
@@ -199,7 +199,7 @@ __initfunc(void t128_setup(char *str, int *ints)) {
  *
  */
 
-__initfunc(int t128_detect(Scsi_Host_Template * tpnt)) {
+int __init t128_detect(Scsi_Host_Template * tpnt){
     static int current_override = 0, current_base = 0;
     struct Scsi_Host *instance;
     unsigned char *base;
index af47e706c70e76864b04d9a4fcebaf2be03de211..4f1bbf265573e9208b25d368b313f4e2c663c863 100644 (file)
 # define PCI_PRESENT pci_present ()
 # define PCI_SET_MASTER pci_set_master (pdev)
 # define PCI_FIND_DEVICE(vend, id) (pdev = pci_find_device (vend, id, pdev))
-# define PCI_GET_IO_AND_IRQ io_port = pdev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK; irq = pdev->irq
+# define PCI_GET_IO_AND_IRQ io_port = pdev->resource[0].start; irq = pdev->irq
 #else
 # include <linux/bios32.h>
 # define PDEV pbus, pdevfn
index 977137092028d4928ae3cba5fd8cd444857ab0fd..ad4c56aefc33fef9f2c7f1042ce1a43144a73541 100644 (file)
@@ -700,8 +700,8 @@ static int board_inquiry(unsigned int j) {
    return FALSE;
 }
 
-__initfunc (static inline int port_detect \
-      (unsigned long port_base, unsigned int j, Scsi_Host_Template *tpnt)) {
+static inline int __init port_detect \
+      (unsigned long port_base, unsigned int j, Scsi_Host_Template *tpnt) {
    unsigned char irq, dma_channel, subversion, i;
    unsigned char in_byte;
    char *bus_type, dma_name[16];
@@ -914,7 +914,8 @@ __initfunc (static inline int port_detect \
    return TRUE;
 }
 
-__initfunc (void u14_34f_setup(char *str, int *ints)) {
+void __init u14_34f_setup(char *str, int *ints)
+{
    int i, argc = ints[0];
    char *cur = str, *pc;
 
@@ -948,7 +949,8 @@ __initfunc (void u14_34f_setup(char *str, int *ints)) {
    return;
 }
 
-__initfunc (int u14_34f_detect(Scsi_Host_Template *tpnt)) {
+int __init u14_34f_detect(Scsi_Host_Template *tpnt)
+{
    unsigned int j = 0, k;
    IRQ_FLAGS
 
index 12b105d4f9a444ec466aa1dd4ae033b7db787c6f..e0a21ca169dd3e20a2661163c515c2ce8eae102d 100644 (file)
@@ -75,6 +75,7 @@
 #include <linux/string.h>
 #include <linux/delay.h>
 #include <linux/version.h>
+#include <linux/init.h>
 #include <asm/irq.h>
 
 #if LINUX_VERSION_CODE >= 0x010300
@@ -176,6 +177,7 @@ MODULE_PARM(setup_strings, "s");
 static inline uchar read_wd33c93(wd33c93_regs *regp,uchar reg_num)
 {
    regp->SASR = reg_num;
+   mb();
    return(regp->SCMD);
 }
 
@@ -186,14 +188,18 @@ static inline uchar read_wd33c93(wd33c93_regs *regp,uchar reg_num)
 static inline void write_wd33c93(wd33c93_regs *regp,uchar reg_num, uchar value)
 {
    regp->SASR = reg_num;
+   mb();
    regp->SCMD = value;
+   mb();
 }
 
 
 static inline void write_wd33c93_cmd(wd33c93_regs *regp, uchar cmd)
 {
    regp->SASR = WD_COMMAND;
+   mb();
    regp->SCMD = cmd;
+   mb();
 }
 
 
@@ -216,9 +222,11 @@ uchar x = 0;
 static void write_wd33c93_count(wd33c93_regs *regp,unsigned long value)
 {
    regp->SASR = WD_TRANSFER_COUNT_MSB;
+   mb();
    regp->SCMD = value >> 16;
    regp->SCMD = value >> 8;
    regp->SCMD = value;
+   mb();
 }
 
 
@@ -227,9 +235,11 @@ static unsigned long read_wd33c93_count(wd33c93_regs *regp)
 unsigned long value;
 
    regp->SASR = WD_TRANSFER_COUNT_MSB;
+   mb();
    value = regp->SCMD << 16;
    value |= regp->SCMD << 8;
    value |= regp->SCMD;
+   mb();
    return value;
 }
 
@@ -1587,10 +1597,10 @@ static char setup_buffer[SETUP_BUFFER_SIZE];
 static char setup_used[MAX_SETUP_ARGS];
 static int done_setup = 0;
 
-void wd33c93_setup (char *str, int *ints)
+int wd33c93_setup (char *str)
 {
-int i,x;
-char *p1,*p2;
+   int i;
+   char *p1,*p2;
 
    /* The kernel does some processing of the command-line before calling
     * this function: If it begins with any decimal or hex number arguments,
@@ -1603,12 +1613,17 @@ char *p1,*p2;
 
    p1 = setup_buffer;
    *p1 = '\0';
+#if 0
+/*
+ * Old style command line arguments are now dead
+ */
    if (ints[0]) {
       for (i=0; i<ints[0]; i++) {
          x = vsprintf(p1,"nosync:0x%02x,",&(ints[i+1]));
          p1 += x;
          }
       }
+#endif
    if (str)
       strncpy(p1, str, SETUP_BUFFER_SIZE - strlen(setup_buffer));
    setup_buffer[SETUP_BUFFER_SIZE - 1] = '\0';
@@ -1631,8 +1646,12 @@ char *p1,*p2;
    for (i=0; i<MAX_SETUP_ARGS; i++)
       setup_used[i] = 0;
    done_setup = 1;
+
+   return 0;
 }
 
+__setup("wd33c93", wd33c93_setup);
+
 
 /* check_setup_args() returns index if key found, 0 if not
  */
@@ -1676,7 +1695,7 @@ int val;
 char buf[32];
 
    if (!done_setup && setup_strings)
-      wd33c93_setup(setup_strings,0);
+      wd33c93_setup(setup_strings);
 
    hostdata = (struct WD33C93_hostdata *)instance->hostdata;
 
index 03e9aef7d0796a57a99cfb11a59c10d36d8af0bc..c67d5a129cf7a405f8bfcb5a45dcfb57ee086b0c 100644 (file)
@@ -223,13 +223,13 @@ struct WD33C93_hostdata {
     uchar            clock_freq;
     uchar            chip;             /* what kind of wd33c93? */
     uchar            microcode;        /* microcode rev */
+    uchar            dma_buffer_pool;  /* FEF: buffer from chip_ram? */
     int              dma_dir;          /* data transfer dir. */
     dma_setup_t      dma_setup;
     dma_stop_t       dma_stop;
     unsigned int     dma_xfer_mask;
     uchar            *dma_bounce_buffer;
     unsigned int     dma_bounce_len;
-    uchar            dma_buffer_pool;  /* FEF: buffer from chip_ram? */
     volatile uchar   busy[8];          /* index = target, bit = lun */
     volatile Scsi_Cmnd *input_Q;       /* commands waiting to be started */
     volatile Scsi_Cmnd *selecting;     /* trying to select this command */
index 9a0dd76ca4a6ad9b2d5a29dc19f1892d846fd6da..f7b170acbd3f9e4d9e064476384d15f508f3633d 100644 (file)
@@ -12,6 +12,7 @@
 dep_tristate 'C-Media PCI (CMI8338/8378)' CONFIG_SOUND_CMPCI $CONFIG_SOUND
 dep_tristate 'Ensoniq AudioPCI (ES1370)' CONFIG_SOUND_ES1370 $CONFIG_SOUND
 dep_tristate 'Creative Ensoniq AudioPCI 97 (ES1371)' CONFIG_SOUND_ES1371 $CONFIG_SOUND
+dep_tristate 'ESS Technology Solo1' CONFIG_SOUND_ESSSOLO1 $CONFIG_SOUND
 dep_tristate 'S3 SonicVibes' CONFIG_SOUND_SONICVIBES $CONFIG_SOUND
 
 dep_tristate 'Support for Turtle Beach MultiSound Classic, Tahiti, Monterey' CONFIG_SOUND_MSNDCLAS $CONFIG_SOUND
index af3c37d3188c3e752d481ebc0bbe20bba527d368..f7a3aad8b39e57af69cc5129bf20b8be224ba19c 100644 (file)
@@ -75,11 +75,11 @@ obj-$(CONFIG_SOUND_VIDC)    += vidc_mod.o
 obj-$(CONFIG_SOUND_WAVEARTIST) += waveartist.o
 obj-$(CONFIG_SOUND_WAVEFRONT)   += wavefront.o
 
-#jnx
+obj-$(CONFIG_SOUND_SONICVIBES) += sonicvibes.o
 obj-$(CONFIG_SOUND_CMPCI)      += cmpci.o
 obj-$(CONFIG_SOUND_ES1370)     += es1370.o
 obj-$(CONFIG_SOUND_ES1371)     += es1371.o
-obj-$(CONFIG_SOUND_SONICVIBES) += sonicvibes.o
+obj-$(CONFIG_SOUND_ESSSOLO1)   += esssolo1.o
 
 # Declare multi-part drivers.
 
diff --git a/drivers/sound/esssolo1.c b/drivers/sound/esssolo1.c
new file mode 100644 (file)
index 0000000..065efa7
--- /dev/null
@@ -0,0 +1,2239 @@
+/*****************************************************************************/
+
+/*
+ *      esssolo1.c  --  ESS Technology Solo1 (ES1946) audio driver.
+ *
+ *      Copyright (C) 1998-1999  Thomas Sailer (sailer@ife.ee.ethz.ch)
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License
+ *      along with this program; if not, write to the Free Software
+ *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Module command line parameters:
+ *   none so far
+ *
+ *  Supported devices:
+ *  /dev/dsp    standard /dev/dsp device, (mostly) OSS compatible
+ *  /dev/mixer  standard /dev/mixer device, (mostly) OSS compatible
+ *  /dev/midi   simple MIDI UART interface, no ioctl
+ *
+ *  Revision history
+ *    10.11.98   0.1   Initial release (without any hardware)
+ *    22.03.99   0.2   cinfo.blocks should be reset after GETxPTR ioctl.
+ *                     reported by Johan Maes <joma@telindus.be>
+ *                     return EAGAIN instead of EBUSY when O_NONBLOCK
+ *                     read/write cannot be executed
+ *    07.04.99   0.3   implemented the following ioctl's: SOUND_PCM_READ_RATE, 
+ *                     SOUND_PCM_READ_CHANNELS, SOUND_PCM_READ_BITS; 
+ *                     Alpha fixes reported by Peter Jones <pjones@redhat.com>
+ *    15.06.99   0.4   Fix bad allocation bug.
+ *                     Thanks to Deti Fliegl <fliegl@in.tum.de>
+ *    28.06.99   0.5   Add pci_set_master
+ *
+ *
+ */
+
+/*****************************************************************************/
+      
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/sound.h>
+#include <linux/malloc.h>
+#include <linux/soundcard.h>
+#include <linux/pci.h>
+#include <linux/bitops.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <linux/init.h>
+#include <linux/poll.h>
+#include <asm/spinlock.h>
+#include <asm/uaccess.h>
+#include <asm/hardirq.h>
+
+#include "dm.h"
+
+/* --------------------------------------------------------------------- */
+
+#ifndef PCI_VENDOR_ID_ESS
+#define PCI_VENDOR_ID_ESS         0x125d
+#endif
+#ifndef PCI_DEVICE_ID_ESS_SOLO1
+#define PCI_DEVICE_ID_ESS_SOLO1   0x1969
+#endif
+
+#define SOLO1_MAGIC  ((PCI_VENDOR_ID_ESS<<16)|PCI_DEVICE_ID_ESS_SOLO1)
+
+#define IOBASE_EXTENT             16
+#define SBBASE_EXTENT             16
+#define VCBASE_EXTENT             16
+#define MPUBASE_EXTENT            4
+#define GPBASE_EXTENT             4
+
+
+/* MIDI buffer sizes */
+
+#define MIDIINBUF  256
+#define MIDIOUTBUF 256
+
+#define FMODE_MIDI_SHIFT 3
+#define FMODE_MIDI_READ  (FMODE_READ << FMODE_MIDI_SHIFT)
+#define FMODE_MIDI_WRITE (FMODE_WRITE << FMODE_MIDI_SHIFT)
+
+#define FMODE_DMFM 0x10
+
+/* --------------------------------------------------------------------- */
+
+#define DEBUGREC
+
+/* --------------------------------------------------------------------- */
+
+struct solo1_state {
+       /* magic */
+       unsigned int magic;
+
+       /* we keep sb cards in a linked list */
+       struct solo1_state *next;
+
+       /* soundcore stuff */
+       int dev_audio;
+       int dev_mixer;
+       int dev_midi;
+       int dev_dmfm;
+
+       /* hardware resources */
+       unsigned long iobase, sbbase, vcbase, mpubase, gpbase; /* long for SPARC */
+       unsigned int irq;
+
+       /* mixer registers; there is no HW readback */
+       struct {
+               unsigned short vol[10];
+               unsigned int recsrc;
+               unsigned int modcnt;
+               unsigned short micpreamp;
+       } mix;
+
+       /* wave stuff */
+       unsigned fmt;
+       unsigned channels;
+       unsigned rate;
+       unsigned char clkdiv;
+       unsigned ena;
+
+       spinlock_t lock;
+       struct semaphore open_sem;
+       mode_t open_mode;
+       wait_queue_head_t open_wait;
+
+       struct dmabuf {
+               void *rawbuf;
+               unsigned buforder;
+               unsigned numfrag;
+               unsigned fragshift;
+               unsigned hwptr, swptr;
+               unsigned total_bytes;
+               int count;
+               unsigned error; /* over/underrun */
+               wait_queue_head_t wait;
+               /* redundant, but makes calculations easier */
+               unsigned fragsize;
+               unsigned dmasize;
+               unsigned fragsamples;
+               /* OSS stuff */
+               unsigned mapped:1;
+               unsigned ready:1;
+               unsigned endcleared:1;
+               unsigned ossfragshift;
+               int ossmaxfrags;
+               unsigned subdivision;
+       } dma_dac, dma_adc;
+
+       /* midi stuff */
+       struct {
+               unsigned ird, iwr, icnt;
+               unsigned ord, owr, ocnt;
+               wait_queue_head_t iwait;
+               wait_queue_head_t owait;
+               struct timer_list timer;
+               unsigned char ibuf[MIDIINBUF];
+               unsigned char obuf[MIDIOUTBUF];
+       } midi;
+};
+
+/* --------------------------------------------------------------------- */
+
+struct solo1_state *devs = NULL;
+
+/* --------------------------------------------------------------------- */
+
+extern inline void write_seq(struct solo1_state *s, unsigned char data)
+{
+        int i;
+       unsigned long flags;
+        
+       /* the __cli stunt is to send the data within the command window */
+        for (i = 0; i < 0xffff; i++) {
+               __save_flags(flags);
+               __cli();
+                if (!(inb(s->sbbase+0xc) & 0x80)) {
+                        outb(data, s->sbbase+0xc);
+                       __restore_flags(flags);
+                        return;
+                }
+               __restore_flags(flags);
+       }
+}
+
+extern inline int read_seq(struct solo1_state *s, unsigned char *data)
+{
+        int i;
+
+        if (!data)
+                return 0;
+        for (i = 0; i < 0xffff; i++)
+                if (inb(s->sbbase+0xe) & 0x80) {
+                        *data = inb(s->sbbase+0xa);
+                        return 1;
+                }
+        return 0;
+}
+
+static int inline reset_ctrl(struct solo1_state *s)
+{
+        int i;
+
+        outb(3, s->sbbase+6); /* clear sequencer and FIFO */
+        udelay(10);
+        outb(0, s->sbbase+6);
+        for (i = 0; i < 0xffff; i++)
+                if (inb(s->sbbase+0xe) & 0x80)
+                        if (inb(s->sbbase+0xa) == 0xaa) {
+                               write_seq(s, 0xc6); /* enter enhanced mode */
+                                return 1;
+                       }
+        return 0;
+}
+
+static void write_ctrl(struct solo1_state *s, unsigned char reg, unsigned char data)
+{
+       write_seq(s, reg);
+       write_seq(s, data);
+}
+
+static unsigned char read_ctrl(struct solo1_state *s, unsigned char reg)
+{
+        unsigned char r;
+
+       write_seq(s, 0xc0);
+       write_seq(s, reg);
+       read_seq(s, &r);
+       return r;
+}
+
+static void write_mixer(struct solo1_state *s, unsigned char reg, unsigned char data)
+{
+       outb(reg, s->sbbase+4);
+       outb(data, s->sbbase+5);
+}
+
+static unsigned char read_mixer(struct solo1_state *s, unsigned char reg)
+{
+       outb(reg, s->sbbase+4);
+       return inb(s->sbbase+5);
+}
+
+/* --------------------------------------------------------------------- */
+
+extern inline unsigned ld2(unsigned int x)
+{
+       unsigned r = 0;
+       
+       if (x >= 0x10000) {
+               x >>= 16;
+               r += 16;
+       }
+       if (x >= 0x100) {
+               x >>= 8;
+               r += 8;
+       }
+       if (x >= 0x10) {
+               x >>= 4;
+               r += 4;
+       }
+       if (x >= 4) {
+               x >>= 2;
+               r += 2;
+       }
+       if (x >= 2)
+               r++;
+       return r;
+}
+
+/* --------------------------------------------------------------------- */
+
+extern inline void stop_dac(struct solo1_state *s)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&s->lock, flags);
+       s->ena &= ~FMODE_WRITE;
+       write_mixer(s, 0x78, 0x10);
+       spin_unlock_irqrestore(&s->lock, flags);
+}
+
+static void start_dac(struct solo1_state *s)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&s->lock, flags);
+       if (!(s->ena & FMODE_WRITE) && (s->dma_dac.mapped || s->dma_dac.count > 0) && s->dma_dac.ready) {
+               s->ena |= FMODE_WRITE;
+               write_mixer(s, 0x78, 0x13);
+       }
+       spin_unlock_irqrestore(&s->lock, flags);
+}      
+
+extern inline void stop_adc(struct solo1_state *s)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&s->lock, flags);
+       s->ena &= ~FMODE_READ;
+       write_ctrl(s, 0xb8, 0xe);
+       spin_unlock_irqrestore(&s->lock, flags);
+}
+
+static void start_adc(struct solo1_state *s)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&s->lock, flags);
+       if (!(s->ena & FMODE_READ) && (s->dma_adc.mapped || s->dma_adc.count < (signed)(s->dma_adc.dmasize - 2*s->dma_adc.fragsize))
+           && s->dma_adc.ready) {
+               s->ena |= FMODE_READ;
+               write_ctrl(s, 0xb8, 0xf);
+#ifdef DEBUGREC
+               printk(KERN_DEBUG "solo1: DMAbuffer: 0x%08lx\n", (long)s->dma_adc.rawbuf);
+               printk(KERN_DEBUG "solo1: DMA: mask: 0x%02x cnt: 0x%04x addr: 0x%08x  stat: 0x%02x\n", 
+                      inb(s->vcbase+0xf), inw(s->vcbase+4), inl(s->vcbase), inb(s->vcbase+8));
+#endif
+                outb(0, s->vcbase+0xd); /* master reset */
+#ifdef DEBUGREC
+               printk(KERN_DEBUG "solo1: DMA: mask: 0x%02x cnt: 0x%04x addr: 0x%08x  stat: 0x%02x (a. clr)\n", 
+                      inb(s->vcbase+0xf), inw(s->vcbase+4), inl(s->vcbase), inb(s->vcbase+8));
+#endif
+               outb(1, s->vcbase+0xf);  /* mask */
+#ifdef DEBUGREC
+               printk(KERN_DEBUG "solo1: DMA: mask: 0x%02x cnt: 0x%04x addr: 0x%08x  stat: 0x%02x (a. mask)\n", 
+                      inb(s->vcbase+0xf), inw(s->vcbase+4), inl(s->vcbase), inb(s->vcbase+8));
+#endif
+               outb(0x54/*0x14*/, s->vcbase+0xb);  /* DMA_MODE_READ | DMA_MODE_AUTOINIT */
+#ifdef DEBUGREC
+               printk(KERN_DEBUG "solo1: DMA: mask: 0x%02x cnt: 0x%04x addr: 0x%08x  stat: 0x%02x (a. wrmode)\n", 
+                      inb(s->vcbase+0xf), inw(s->vcbase+4), inl(s->vcbase), inb(s->vcbase+8));
+#endif
+               outl(virt_to_bus(s->dma_adc.rawbuf), s->vcbase);
+#ifdef DEBUGREC
+               printk(KERN_DEBUG "solo1: DMA: mask: 0x%02x cnt: 0x%04x addr: 0x%08x  stat: 0x%02x (a. wrbase)\n", 
+                      inb(s->vcbase+0xf), inw(s->vcbase+4), inl(s->vcbase), inb(s->vcbase+8));
+#endif
+               outw(s->dma_adc.dmasize-1, s->vcbase+4);
+#ifdef DEBUGREC
+               printk(KERN_DEBUG "solo1: DMA: mask: 0x%02x cnt: 0x%04x addr: 0x%08x  stat: 0x%02x (a. wrcnt)\n", 
+                      inb(s->vcbase+0xf), inw(s->vcbase+4), inl(s->vcbase), inb(s->vcbase+8));
+#endif
+               outb(0, s->vcbase+0xf);
+#ifdef DEBUGREC
+               printk(KERN_DEBUG "solo1: DMA: mask: 0x%02x cnt: 0x%04x addr: 0x%08x  stat: 0x%02x (a. clrmask)\n", 
+                      inb(s->vcbase+0xf), inw(s->vcbase+4), inl(s->vcbase), inb(s->vcbase+8));
+#endif
+       }
+       spin_unlock_irqrestore(&s->lock, flags);
+#ifdef DEBUGREC
+       printk(KERN_DEBUG "solo1: start DMA: reg B8: 0x%02x  DMAstat: 0x%02x  DMAcnt: 0x%04x  DMAmask: 0x%02x  SBstat: 0x%02x\n", 
+              read_ctrl(s, 0xb8), inb(s->vcbase+8), inw(s->vcbase+4), inb(s->vcbase+0xf), inb(s->sbbase+0xc));
+
+       printk(KERN_DEBUG "solo1: A1: 0x%02x  A2: 0x%02x  A4: 0x%02x  A5: 0x%02x  A8: 0x%02x\n"  
+              KERN_DEBUG "solo1: B1: 0x%02x  B2: 0x%02x  B4: 0x%02x  B7: 0x%02x  B8: 0x%02x  B9: 0x%02x\n",
+              read_ctrl(s, 0xa1), read_ctrl(s, 0xa2), read_ctrl(s, 0xa4), read_ctrl(s, 0xa5), read_ctrl(s, 0xa8), 
+              read_ctrl(s, 0xb1), read_ctrl(s, 0xb2), read_ctrl(s, 0xb4), read_ctrl(s, 0xb7), read_ctrl(s, 0xb8), 
+              read_ctrl(s, 0xb9));
+#endif
+}
+
+/* --------------------------------------------------------------------- */
+
+#define DMABUF_DEFAULTORDER (15-PAGE_SHIFT)
+#define DMABUF_MINORDER 1
+
+extern inline void dealloc_dmabuf(struct dmabuf *db)
+{
+       unsigned long map, mapend;
+
+       if (db->rawbuf) {
+               /* undo marking the pages as reserved */
+               mapend = MAP_NR(db->rawbuf + (PAGE_SIZE << db->buforder) - 1);
+               for (map = MAP_NR(db->rawbuf); map <= mapend; map++)
+                       clear_bit(PG_reserved, &mem_map[map].flags);    
+               free_pages((unsigned long)db->rawbuf, db->buforder);
+       }
+       db->rawbuf = NULL;
+       db->mapped = db->ready = 0;
+}
+
+static int prog_dmabuf(struct solo1_state *s, struct dmabuf *db, int gfp_mask)
+{
+       int order;
+       unsigned bytespersec;
+       unsigned bufs, sample_shift = 0;
+       unsigned long map, mapend;
+
+       db->hwptr = db->swptr = db->total_bytes = db->count = db->error = db->endcleared = 0;
+       if (!db->rawbuf) {
+               db->ready = db->mapped = 0;
+                for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; order--)
+                        if ((db->rawbuf = (void *)__get_free_pages(gfp_mask, order)))
+                               break;
+               if (!db->rawbuf)
+                       return -ENOMEM;
+               db->buforder = order;
+               /* now mark the pages as reserved; otherwise remap_page_range doesn't do what we want */
+               mapend = MAP_NR(db->rawbuf + (PAGE_SIZE << db->buforder) - 1);
+               for (map = MAP_NR(db->rawbuf); map <= mapend; map++)
+                       set_bit(PG_reserved, &mem_map[map].flags);
+       }
+       if (s->fmt & (AFMT_S16_LE | AFMT_U16_LE))
+               sample_shift++;
+       if (s->channels > 1)
+               sample_shift++;
+       bytespersec = s->rate << sample_shift;
+       bufs = PAGE_SIZE << db->buforder;
+       if (db->ossfragshift) {
+               if ((1000 << db->ossfragshift) < bytespersec)
+                       db->fragshift = ld2(bytespersec/1000);
+               else
+                       db->fragshift = db->ossfragshift;
+       } else {
+               db->fragshift = ld2(bytespersec/100/(db->subdivision ? db->subdivision : 1));
+               if (db->fragshift < 3)
+                       db->fragshift = 3;
+       }
+       db->numfrag = bufs >> db->fragshift;
+       while (db->numfrag < 4 && db->fragshift > 3) {
+               db->fragshift--;
+               db->numfrag = bufs >> db->fragshift;
+       }
+       db->fragsize = 1 << db->fragshift;
+       if (db->ossmaxfrags >= 4 && db->ossmaxfrags < db->numfrag)
+               db->numfrag = db->ossmaxfrags;
+       db->fragsamples = db->fragsize >> sample_shift;
+       db->dmasize = db->numfrag << db->fragshift;
+       return 0;
+}
+
+extern inline int prog_dmabuf_adc(struct solo1_state *s)
+{
+       unsigned long va;
+       int c;
+
+       stop_adc(s);
+       if ((c = prog_dmabuf(s, &s->dma_adc, GFP_KERNEL | GFP_DMA)))
+               return c;
+       va = virt_to_bus(s->dma_adc.rawbuf);
+       if ((va & ~((1<<24)-1)))
+               panic("solo1: buffer above 16M boundary");
+       outb(0, s->vcbase+0xd);  /* clear */
+       outb(1, s->vcbase+0xf); /* mask */
+       //outb(0, s->vcbase+8);  /* enable (enable is active low!) */
+       outb(0x54, s->vcbase+0xb);  /* DMA_MODE_READ | DMA_MODE_AUTOINIT */
+       outl(va, s->vcbase);
+       outw(s->dma_adc.dmasize-1, s->vcbase+4);
+       c = - s->dma_adc.fragsamples;
+       write_ctrl(s, 0xa4, c);
+       write_ctrl(s, 0xa5, c >> 8);
+       outb(0, s->vcbase+0xf);
+       s->dma_adc.ready = 1;
+       return 0;
+}
+
+extern inline int prog_dmabuf_dac(struct solo1_state *s)
+{
+       unsigned long va;
+       int c;
+
+       stop_dac(s);
+       if ((c = prog_dmabuf(s, &s->dma_dac, GFP_KERNEL)))
+               return c;
+       memset(s->dma_dac.rawbuf, (s->fmt & (AFMT_U8 | AFMT_U16_LE)) ? 0 : 0x80, s->dma_dac.dmasize); /* almost correct for U16 */
+       va = virt_to_bus(s->dma_dac.rawbuf);
+       if ((va ^ (va + s->dma_dac.dmasize - 1)) & ~((1<<20)-1))
+               panic("solo1: buffer crosses 1M boundary");
+       outl(va, s->iobase);
+       /* warning: s->dma_dac.dmasize & 0xffff must not be zero! i.e. this limits us to a 32k buffer */
+       outw(s->dma_dac.dmasize, s->iobase+4);
+       c = - s->dma_dac.fragsamples;
+       write_mixer(s, 0x74, c);
+       write_mixer(s, 0x76, c >> 8);
+       outb(0xa, s->iobase+6);
+       s->dma_dac.ready = 1;
+       return 0;
+}
+
+extern inline void clear_advance(void *buf, unsigned bsize, unsigned bptr, unsigned len, unsigned char c)
+{
+       if (bptr + len > bsize) {
+               unsigned x = bsize - bptr;
+               memset(((char *)buf) + bptr, c, x);
+               bptr = 0;
+               len -= x;
+       }
+       memset(((char *)buf) + bptr, c, len);
+}
+
+/* call with spinlock held! */
+
+static void solo1_update_ptr(struct solo1_state *s)
+{
+       int diff;
+       unsigned hwptr;
+
+       /* update ADC pointer */
+       if (s->ena & FMODE_READ) {
+               hwptr = (s->dma_adc.dmasize - 1 - inw(s->vcbase+4)) % s->dma_adc.dmasize;
+                diff = (s->dma_adc.dmasize + hwptr - s->dma_adc.hwptr) % s->dma_adc.dmasize;
+                s->dma_adc.hwptr = hwptr;
+               s->dma_adc.total_bytes += diff;
+               s->dma_adc.count += diff;
+#ifdef DEBUGREC
+               printk(KERN_DEBUG "solo1: rd: hwptr %u swptr %u dmasize %u count %u\n",
+                      s->dma_adc.hwptr, s->dma_adc.swptr, s->dma_adc.dmasize, s->dma_adc.count);
+#endif
+               if (s->dma_adc.mapped) {
+                       if (s->dma_adc.count >= (signed)s->dma_adc.fragsize)
+                               wake_up(&s->dma_adc.wait);
+               } else {
+                       if (s->dma_adc.count > (signed)(s->dma_adc.dmasize - ((3 * s->dma_adc.fragsize) >> 1))) {
+                               s->ena &= ~FMODE_READ;
+                               write_ctrl(s, 0xb8, 0xe);
+                               s->dma_adc.error++;
+                       }
+                       if (s->dma_adc.count > 0)
+                               wake_up(&s->dma_adc.wait);
+               }
+       }
+       /* update DAC pointer */
+       if (s->ena & FMODE_WRITE) {
+                hwptr = (s->dma_dac.dmasize - inw(s->iobase+4)) % s->dma_dac.dmasize;
+                diff = (s->dma_dac.dmasize + hwptr - s->dma_dac.hwptr) % s->dma_dac.dmasize;
+                s->dma_dac.hwptr = hwptr;
+               s->dma_dac.total_bytes += diff;
+#if 0
+               printk(KERN_DEBUG "solo1: wr: hwptr %u swptr %u dmasize %u count %u\n",
+                      s->dma_dac.hwptr, s->dma_dac.swptr, s->dma_dac.dmasize, s->dma_dac.count);
+#endif
+               if (s->dma_dac.mapped) {
+                       s->dma_dac.count += diff;
+                       if (s->dma_dac.count >= (signed)s->dma_dac.fragsize)
+                               wake_up(&s->dma_dac.wait);
+               } else {
+                       s->dma_dac.count -= diff;
+                       if (s->dma_dac.count <= 0) {
+                               s->ena &= ~FMODE_WRITE;
+                               write_mixer(s, 0x78, 0x12);
+                               s->dma_dac.error++;
+                       } else if (s->dma_dac.count <= (signed)s->dma_dac.fragsize && !s->dma_dac.endcleared) {
+                               clear_advance(s->dma_dac.rawbuf, s->dma_dac.dmasize, s->dma_dac.swptr,
+                                             s->dma_dac.fragsize, (s->fmt & (AFMT_U8 | AFMT_U16_LE)) ? 0 : 0x80);
+                               s->dma_dac.endcleared = 1;
+                       }
+                       if (s->dma_dac.count < (signed)s->dma_dac.dmasize)
+                               wake_up(&s->dma_dac.wait);
+               }
+       }
+}
+
+/* --------------------------------------------------------------------- */
+
+static void prog_codec(struct solo1_state *s)
+{
+       unsigned long flags;
+       int fdiv, filter;
+       unsigned char c;
+
+       reset_ctrl(s);
+       write_seq(s, 0xd3);
+       /* program sampling rates */
+       filter = s->rate * 9 / 20; /* Set filter roll-off to 90% of rate/2 */
+       fdiv = 256 - 7160000 / (filter * 82);
+       spin_lock_irqsave(&s->lock, flags);
+       write_ctrl(s, 0xa1, s->clkdiv);
+       write_ctrl(s, 0xa2, fdiv);
+       write_mixer(s, 0x70, s->clkdiv);
+       write_mixer(s, 0x72, fdiv);
+       /* program ADC parameters */
+       write_ctrl(s, 0xb8, 0xe);
+       write_ctrl(s, 0xb9, /*0x1*/0);
+       write_ctrl(s, 0xa8, (s->channels > 1) ? 0x11 : 0x12);
+       c = 0xd0;
+       if (s->fmt & (AFMT_S16_LE | AFMT_U16_LE))
+               c |= 0x04;
+       if (s->fmt & (AFMT_S16_LE | AFMT_S8))
+               c |= 0x20;
+       if (s->channels > 1)
+               c ^= 0x48;
+       write_ctrl(s, 0xb7, (c & 0x70) | 1);
+       write_ctrl(s, 0xb7, c);
+       write_ctrl(s, 0xb1, 0x50);
+       write_ctrl(s, 0xb2, 0x50);
+       /* program DAC parameters */
+       c = 0x40;
+       if (s->fmt & (AFMT_S16_LE | AFMT_U16_LE))
+               c |= 1;
+       if (s->fmt & (AFMT_S16_LE | AFMT_S8))
+               c |= 4;
+       if (s->channels > 1)
+               c |= 2;
+       write_mixer(s, 0x7a, c);
+       write_mixer(s, 0x78, 0x10);
+       s->ena = 0;
+       spin_unlock_irqrestore(&s->lock, flags);
+}
+
+/* --------------------------------------------------------------------- */
+
+static const char invalid_magic[] = KERN_CRIT "solo1: invalid magic value\n";
+
+#define VALIDATE_STATE(s)                         \
+({                                                \
+       if (!(s) || (s)->magic != SOLO1_MAGIC) { \
+               printk(invalid_magic);            \
+               return -ENXIO;                    \
+       }                                         \
+})
+
+/* --------------------------------------------------------------------- */
+
+static int mixer_ioctl(struct solo1_state *s, unsigned int cmd, unsigned long arg)
+{
+       static const unsigned int mixer_src[8] = {
+               SOUND_MASK_MIC, SOUND_MASK_MIC, SOUND_MASK_CD, SOUND_MASK_VOLUME,
+               SOUND_MASK_MIC, 0, SOUND_MASK_LINE, 0
+       };
+       static const unsigned char mixtable[SOUND_MIXER_NRDEVICES] = {
+               [SOUND_MIXER_PCM]    = 0x7c,   /* voice */
+               [SOUND_MIXER_SYNTH]  = 0x36,   /* FM */
+               [SOUND_MIXER_CD]     = 0x38,   /* CD */
+               [SOUND_MIXER_LINE]   = 0x3e,   /* Line */
+               [SOUND_MIXER_LINE1]  = 0x3a,   /* AUX */
+               [SOUND_MIXER_MIC]    = 0x1a,   /* Mic */
+               [SOUND_MIXER_LINE2]  = 0x6d    /* Mono in */
+       };
+       unsigned char l, r, rl, rr;
+       int i, val;
+
+       VALIDATE_STATE(s);
+
+       if (cmd == SOUND_MIXER_PRIVATE1) {
+               /* enable/disable/query mixer preamp */
+               get_user_ret(val, (int *)arg, -EFAULT);
+               if (val != -1) {
+                       val = val ? 0xff : 0xf7;
+                       write_mixer(s, 0x7d, (read_mixer(s, 0x7d) | 0x08) & val);
+               }
+               val = (read_mixer(s, 0x7d) & 0x08) ? 1 : 0;
+               return put_user(val, (int *)arg);
+       }
+       if (cmd == SOUND_MIXER_PRIVATE1) {
+               /* enable/disable/query mixer preamp */
+               get_user_ret(val, (int *)arg, -EFAULT);
+               if (val != -1) {
+                       val = val ? 0xff : 0xf7;
+                       write_mixer(s, 0x7d, (read_mixer(s, 0x7d) | 0x08) & val);
+               }
+               val = (read_mixer(s, 0x7d) & 0x08) ? 1 : 0;
+               return put_user(val, (int *)arg);
+       }
+       if (cmd == SOUND_MIXER_PRIVATE2) {
+               /* enable/disable/query spatializer */
+               get_user_ret(val, (int *)arg, -EFAULT);
+               if (val != -1) {
+                       val &= 0x3f;
+                       write_mixer(s, 0x52, val);
+                       write_mixer(s, 0x50, val ? 0x08 : 0);
+               }
+               return put_user(read_mixer(s, 0x52), (int *)arg);
+       }
+        if (cmd == SOUND_MIXER_INFO) {
+               mixer_info info;
+               strncpy(info.id, "Solo1", sizeof(info.id));
+               strncpy(info.name, "ESS Solo1", sizeof(info.name));
+               info.modify_counter = s->mix.modcnt;
+               if (copy_to_user((void *)arg, &info, sizeof(info)))
+                       return -EFAULT;
+               return 0;
+       }
+       if (cmd == SOUND_OLD_MIXER_INFO) {
+               _old_mixer_info info;
+               strncpy(info.id, "Solo1", sizeof(info.id));
+               strncpy(info.name, "ESS Solo1", sizeof(info.name));
+               if (copy_to_user((void *)arg, &info, sizeof(info)))
+                       return -EFAULT;
+               return 0;
+       }
+       if (cmd == OSS_GETVERSION)
+               return put_user(SOUND_VERSION, (int *)arg);
+       if (_IOC_TYPE(cmd) != 'M' || _IOC_SIZE(cmd) != sizeof(int))
+                return -EINVAL;
+        if (_IOC_DIR(cmd) == _IOC_READ) {
+                switch (_IOC_NR(cmd)) {
+                case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */
+                       return put_user(mixer_src[read_mixer(s, 0x1c) & 7], (int *)arg);
+
+                case SOUND_MIXER_DEVMASK: /* Arg contains a bit for each supported device */
+                       return put_user(SOUND_MASK_PCM | SOUND_MASK_SYNTH | SOUND_MASK_CD |
+                                       SOUND_MASK_LINE | SOUND_MASK_LINE1 | SOUND_MASK_MIC |
+                                       SOUND_MASK_VOLUME | SOUND_MASK_LINE2 | SOUND_MASK_RECLEV |
+                                       SOUND_MASK_SPEAKER, (int *)arg);
+
+                case SOUND_MIXER_RECMASK: /* Arg contains a bit for each supported recording source */
+                       return put_user(SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD | SOUND_MASK_VOLUME, (int *)arg);
+
+                case SOUND_MIXER_STEREODEVS: /* Mixer channels supporting stereo */
+                       return put_user(SOUND_MASK_PCM | SOUND_MASK_SYNTH | SOUND_MASK_CD |
+                                       SOUND_MASK_LINE | SOUND_MASK_LINE1 | SOUND_MASK_MIC |
+                                       SOUND_MASK_VOLUME | SOUND_MASK_LINE2 | SOUND_MASK_RECLEV, (int *)arg);
+                       
+                case SOUND_MIXER_CAPS:
+                       return put_user(SOUND_CAP_EXCL_INPUT, (int *)arg);
+
+               case SOUND_MIXER_VOLUME:
+                       rl = read_mixer(s, 0x60);
+                       rr = read_mixer(s, 0x62);
+                       l = (rl * 3 + 11) / 2;
+                       if (rl & 0x40)
+                               l = 0;
+                       r = (rr * 3 + 11) / 2;
+                       if (rr & 0x40)
+                               r = 0;
+                       return put_user((((unsigned int)r) << 8) | l, (int *)arg);
+
+               case SOUND_MIXER_SPEAKER:
+                       rl = read_mixer(s, 0x3c);
+                       l = (rl & 7) * 14 + 2;
+                       return put_user(l * 0x101, (int *)arg);
+
+               case SOUND_MIXER_RECLEV:
+                       rl = read_ctrl(s, 0xb4);
+                       r = ((rl & 0xf) * 13 + 5) / 2;
+                       l = (((rl >> 4) & 0xf) * 13 + 5) / 2;
+                       return put_user((((unsigned int)r) << 8) | l, (int *)arg);
+
+               default:
+                       i = _IOC_NR(cmd);
+                        if (i >= SOUND_MIXER_NRDEVICES || !mixtable[i])
+                                return -EINVAL;
+                       rl = read_mixer(s, mixtable[i]);
+                       r = ((rl & 0xf) * 13 + 5) / 2;
+                       l = (((rl >> 4) & 0xf) * 13 + 5) / 2;
+                       return put_user((((unsigned int)r) << 8) | l, (int *)arg);
+               }
+       }
+        if (_IOC_DIR(cmd) != (_IOC_READ|_IOC_WRITE)) 
+               return -EINVAL;
+       s->mix.modcnt++;
+       switch (_IOC_NR(cmd)) {
+       case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */
+
+       {
+               static const unsigned char regs[] = {
+                       0x1c, 0x1a, 0x36, 0x38, 0x3a, 0x3c, 0x3e, 0x60, 0x62, 0x6d, 0x7c
+               };
+               int i;
+
+               for (i = 0; i < sizeof(regs); i++)
+                       printk(KERN_DEBUG "solo1: mixer reg 0x%02x: 0x%02x\n",
+                              regs[i], read_mixer(s, regs[i]));
+               printk(KERN_DEBUG "solo1: ctrl reg 0x%02x: 0x%02x\n",
+                      0xb4, read_ctrl(s, 0xb4));
+       } 
+
+               get_user_ret(val, (int *)arg, -EFAULT);
+                i = hweight32(val);
+                if (i == 0)
+                        return 0;
+                else if (i > 1) 
+                        val &= ~mixer_src[read_mixer(s, 0x1c) & 7];
+               for (i = 0; i < 8; i++) {
+                       if (mixer_src[i] & val)
+                               break;
+               }
+               if (i > 7)
+                       return 0;
+               write_mixer(s, 0x1c, i);
+               return 0;
+
+       case SOUND_MIXER_VOLUME:
+               get_user_ret(val, (int *)arg, -EFAULT);
+               l = val & 0xff;
+               if (l > 100)
+                       l = 100;
+               r = (val >> 8) & 0xff;
+               if (r > 100)
+                       r = 100;
+               if (l < 6) {
+                       rl = 0x40;
+                       l = 0;
+               } else {
+                       rl = (l * 2 - 11) / 3;
+                       l = (rl * 3 + 11) / 2;
+               }
+               if (r < 6) {
+                       rr = 0x40;
+                       r = 0;
+               } else {
+                       rr = (r * 2 - 11) / 3;
+                       r = (rr * 3 + 11) / 2;
+               }
+               write_mixer(s, 0x60, rl);
+               write_mixer(s, 0x62, rr);
+               return put_user((((unsigned int)r) << 8) | l, (int *)arg);
+
+       case SOUND_MIXER_SPEAKER:
+               get_user_ret(val, (int *)arg, -EFAULT);
+               l = val & 0xff;
+               if (l > 100)
+                       l = 100;
+               else if (l < 2)
+                       l = 2;
+               rl = (l - 2) / 14;
+               l = rl * 14 + 2;
+               write_mixer(s, 0x3c, rl);
+               return put_user(l * 0x101, (int *)arg);
+
+       case SOUND_MIXER_RECLEV:
+               get_user_ret(val, (int *)arg, -EFAULT);
+               l = (val << 1) & 0x1fe;
+               if (l > 200)
+                       l = 200;
+               else if (l < 5)
+                       l = 5;
+               r = (val >> 7) & 0x1fe;
+               if (r > 200)
+                       r = 200;
+               else if (r < 5)
+                       r = 5;
+               rl = (l - 5) / 13;
+               rr = (r - 5) / 13;
+               r = (rl * 13 + 5) / 2;
+               l = (rr * 13 + 5) / 2;
+               write_ctrl(s, 0xb4, (rl << 4) | rr);
+               return put_user((((unsigned int)r) << 8) | l, (int *)arg);
+
+       default:
+               i = _IOC_NR(cmd);
+               if (i >= SOUND_MIXER_NRDEVICES || !mixtable[i])
+                       return -EINVAL;
+               get_user_ret(val, (int *)arg, -EFAULT);
+               l = (val << 1) & 0x1fe;
+               if (l > 200)
+                       l = 200;
+               else if (l < 5)
+                       l = 5;
+               r = (val >> 7) & 0x1fe;
+               if (r > 200)
+                       r = 200;
+               else if (r < 5)
+                       r = 5;
+               rl = (l - 5) / 13;
+               rr = (r - 5) / 13;
+               r = (rl * 13 + 5) / 2;
+               l = (rr * 13 + 5) / 2;
+               write_mixer(s, mixtable[i], (rl << 4) | rr);
+               return put_user((((unsigned int)r) << 8) | l, (int *)arg);
+       }
+}
+
+/* --------------------------------------------------------------------- */
+
+static loff_t solo1_llseek(struct file *file, loff_t offset, int origin)
+{
+        return -ESPIPE;
+}
+
+/* --------------------------------------------------------------------- */
+
+static int solo1_open_mixdev(struct inode *inode, struct file *file)
+{
+       int minor = MINOR(inode->i_rdev);
+       struct solo1_state *s = devs;
+
+       while (s && s->dev_mixer != minor)
+               s = s->next;
+       if (!s)
+               return -ENODEV;
+               VALIDATE_STATE(s);
+       file->private_data = s;
+       MOD_INC_USE_COUNT;
+       return 0;
+}
+
+static int solo1_release_mixdev(struct inode *inode, struct file *file)
+{
+       struct solo1_state *s = (struct solo1_state *)file->private_data;
+       
+       VALIDATE_STATE(s);
+       MOD_DEC_USE_COUNT;
+       return 0;
+}
+
+static int solo1_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+{
+       return mixer_ioctl((struct solo1_state *)file->private_data, cmd, arg);
+}
+
+static /*const*/ struct file_operations solo1_mixer_fops = {
+       &solo1_llseek,
+       NULL,  /* read */
+       NULL,  /* write */
+       NULL,  /* readdir */
+       NULL,  /* poll */
+       &solo1_ioctl_mixdev,
+       NULL,  /* mmap */
+       &solo1_open_mixdev,
+       NULL,  /* flush */
+       &solo1_release_mixdev,
+       NULL,  /* fsync */
+       NULL,  /* fasync */
+       NULL,  /* check_media_change */
+#if 0
+       NULL,  /* revalidate */
+       NULL,  /* lock */
+#endif
+};
+
+/* --------------------------------------------------------------------- */
+
+static int drain_dac(struct solo1_state *s, int nonblock)
+{
+       DECLARE_WAITQUEUE(wait, current);
+       unsigned long flags;
+       int count, tmo;
+       
+       if (s->dma_dac.mapped)
+               return 0;
+        current->state = TASK_INTERRUPTIBLE;
+        add_wait_queue(&s->dma_dac.wait, &wait);
+        for (;;) {
+                spin_lock_irqsave(&s->lock, flags);
+               count = s->dma_dac.count;
+                spin_unlock_irqrestore(&s->lock, flags);
+               if (count <= 0)
+                       break;
+               if (signal_pending(current))
+                        break;
+                if (nonblock) {
+                        remove_wait_queue(&s->dma_dac.wait, &wait);
+                        current->state = TASK_RUNNING;
+                        return -EBUSY;
+                }
+               tmo = (count * HZ) / s->rate;
+               if (s->fmt & (AFMT_S16_LE | AFMT_U16_LE))
+                       tmo >>= 1;
+               if (s->channels > 1)
+                       tmo >>= 1;
+                if (!schedule_timeout(tmo ? : 1) && tmo)
+                        printk(KERN_DEBUG "solo1: dma timed out??\n");
+        }
+        remove_wait_queue(&s->dma_dac.wait, &wait);
+        current->state = TASK_RUNNING;
+        if (signal_pending(current))
+                return -ERESTARTSYS;
+        return 0;
+}
+
+/* --------------------------------------------------------------------- */
+
+static ssize_t solo1_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
+{
+       struct solo1_state *s = (struct solo1_state *)file->private_data;
+       ssize_t ret;
+       unsigned long flags;
+       unsigned swptr;
+       int cnt;
+
+       VALIDATE_STATE(s);
+       if (ppos != &file->f_pos)
+               return -ESPIPE;
+       if (s->dma_adc.mapped)
+               return -ENXIO;
+       if (!s->dma_adc.ready && (ret = prog_dmabuf_adc(s)))
+               return ret;
+       if (!access_ok(VERIFY_WRITE, buffer, count))
+               return -EFAULT;
+       ret = 0;
+       while (count > 0) {
+               spin_lock_irqsave(&s->lock, flags);
+               swptr = s->dma_adc.swptr;
+               cnt = s->dma_adc.dmasize-swptr;
+               if (s->dma_adc.count < cnt)
+                       cnt = s->dma_adc.count;
+               spin_unlock_irqrestore(&s->lock, flags);
+               if (cnt > count)
+                       cnt = count;
+#ifdef DEBUGREC
+               printk(KERN_DEBUG "solo1_read: reg B8: 0x%02x  DMAstat: 0x%02x  DMAcnt: 0x%04x  SBstat: 0x%02x  cnt: %u\n", 
+                      read_ctrl(s, 0xb8), inb(s->vcbase+8), inw(s->vcbase+4), inb(s->sbbase+0xc), cnt);
+#endif
+               if (cnt <= 0) {
+                       start_adc(s);
+#ifdef DEBUGREC
+                       printk(KERN_DEBUG "solo1_read: regs: A1: 0x%02x  A2: 0x%02x  A4: 0x%02x  A5: 0x%02x  A8: 0x%02x\n"
+                              KERN_DEBUG "solo1_read: regs: B1: 0x%02x  B2: 0x%02x  B7: 0x%02x  B8: 0x%02x  B9: 0x%02x\n"
+                              KERN_DEBUG "solo1_read: DMA: addr: 0x%08x cnt: 0x%04x stat: 0x%02x mask: 0x%02x\n"  
+                              KERN_DEBUG "solo1_read: SBstat: 0x%02x  cnt: %u\n",
+                              read_ctrl(s, 0xa1), read_ctrl(s, 0xa2), read_ctrl(s, 0xa4), read_ctrl(s, 0xa5), read_ctrl(s, 0xa8), 
+                              read_ctrl(s, 0xb1), read_ctrl(s, 0xb2), read_ctrl(s, 0xb7), read_ctrl(s, 0xb8), read_ctrl(s, 0xb9), 
+                              inl(s->vcbase), inw(s->vcbase+4), inb(s->vcbase+8), inb(s->vcbase+15), inb(s->sbbase+0xc), cnt);
+#endif
+                       if (inb(s->vcbase+15) & 1) {
+                               printk(KERN_ERR "solo1: cannot start recording, DDMA mask bit stuck at 1\n");
+                               return -EIO;
+                       }
+                       if (file->f_flags & O_NONBLOCK)
+                               return ret ? ret : -EAGAIN;
+                       interruptible_sleep_on(&s->dma_adc.wait);
+#ifdef DEBUGREC
+                       printk(KERN_DEBUG "solo1_read: regs: A1: 0x%02x  A2: 0x%02x  A4: 0x%02x  A5: 0x%02x  A8: 0x%02x\n"
+                              KERN_DEBUG "solo1_read: regs: B1: 0x%02x  B2: 0x%02x  B7: 0x%02x  B8: 0x%02x  B9: 0x%02x\n"
+                              KERN_DEBUG "solo1_read: DMA: addr: 0x%08x cnt: 0x%04x stat: 0x%02x mask: 0x%02x\n"  
+                              KERN_DEBUG "solo1_read: SBstat: 0x%02x  cnt: %u\n",
+                              read_ctrl(s, 0xa1), read_ctrl(s, 0xa2), read_ctrl(s, 0xa4), read_ctrl(s, 0xa5), read_ctrl(s, 0xa8), 
+                              read_ctrl(s, 0xb1), read_ctrl(s, 0xb2), read_ctrl(s, 0xb7), read_ctrl(s, 0xb8), read_ctrl(s, 0xb9), 
+                              inl(s->vcbase), inw(s->vcbase+4), inb(s->vcbase+8), inb(s->vcbase+15), inb(s->sbbase+0xc), cnt);
+#endif
+                       if (signal_pending(current))
+                               return ret ? ret : -ERESTARTSYS;
+                       continue;
+               }
+               if (copy_to_user(buffer, s->dma_adc.rawbuf + swptr, cnt))
+                       return ret ? ret : -EFAULT;
+               swptr = (swptr + cnt) % s->dma_adc.dmasize;
+               spin_lock_irqsave(&s->lock, flags);
+               s->dma_adc.swptr = swptr;
+               s->dma_adc.count -= cnt;
+               spin_unlock_irqrestore(&s->lock, flags);
+               count -= cnt;
+               buffer += cnt;
+               ret += cnt;
+               start_adc(s);
+#ifdef DEBUGREC
+               printk(KERN_DEBUG "solo1_read: reg B8: 0x%02x  DMAstat: 0x%02x  DMAcnt: 0x%04x  SBstat: 0x%02x\n", 
+                      read_ctrl(s, 0xb8), inb(s->vcbase+8), inw(s->vcbase+4), inb(s->sbbase+0xc));
+#endif
+       }
+       return ret;
+}
+
+static ssize_t solo1_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
+{
+       struct solo1_state *s = (struct solo1_state *)file->private_data;
+       ssize_t ret;
+       unsigned long flags;
+       unsigned swptr;
+       int cnt;
+
+       VALIDATE_STATE(s);
+       if (ppos != &file->f_pos)
+               return -ESPIPE;
+       if (s->dma_dac.mapped)
+               return -ENXIO;
+       if (!s->dma_dac.ready && (ret = prog_dmabuf_dac(s)))
+               return ret;
+       if (!access_ok(VERIFY_READ, buffer, count))
+               return -EFAULT;
+#if 0
+       printk(KERN_DEBUG "solo1_write: reg 70: 0x%02x  71: 0x%02x  72: 0x%02x  74: 0x%02x  76: 0x%02x  78: 0x%02x  7A: 0x%02x\n"
+              KERN_DEBUG "solo1_write: DMA: addr: 0x%08x  cnt: 0x%04x  stat: 0x%02x  SBstat: 0x%02x\n", 
+              read_mixer(s, 0x70), read_mixer(s, 0x71), read_mixer(s, 0x72), read_mixer(s, 0x74), read_mixer(s, 0x76),
+              read_mixer(s, 0x78), read_mixer(s, 0x7a), inl(s->iobase), inw(s->iobase+4), inb(s->iobase+6), inb(s->sbbase+0xc));
+       printk(KERN_DEBUG "solo1_write: reg 78: 0x%02x  reg 7A: 0x%02x  DMAcnt: 0x%04x  DMAstat: 0x%02x  SBstat: 0x%02x\n", 
+              read_mixer(s, 0x78), read_mixer(s, 0x7a), inw(s->iobase+4), inb(s->iobase+6), inb(s->sbbase+0xc));
+#endif
+       ret = 0;
+       while (count > 0) {
+               spin_lock_irqsave(&s->lock, flags);
+               if (s->dma_dac.count < 0) {
+                       s->dma_dac.count = 0;
+                       s->dma_dac.swptr = s->dma_dac.hwptr;
+               }
+               swptr = s->dma_dac.swptr;
+               cnt = s->dma_dac.dmasize-swptr;
+               if (s->dma_dac.count + cnt > s->dma_dac.dmasize)
+                       cnt = s->dma_dac.dmasize - s->dma_dac.count;
+               spin_unlock_irqrestore(&s->lock, flags);
+               if (cnt > count)
+                       cnt = count;
+               if (cnt <= 0) {
+                       start_dac(s);
+                       if (file->f_flags & O_NONBLOCK)
+                               return ret ? ret : -EAGAIN;
+                       interruptible_sleep_on(&s->dma_dac.wait);
+                       if (signal_pending(current))
+                               return ret ? ret : -ERESTARTSYS;
+                       continue;
+               }
+               if (copy_from_user(s->dma_dac.rawbuf + swptr, buffer, cnt))
+                       return ret ? ret : -EFAULT;
+               swptr = (swptr + cnt) % s->dma_dac.dmasize;
+               spin_lock_irqsave(&s->lock, flags);
+               s->dma_dac.swptr = swptr;
+               s->dma_dac.count += cnt;
+               s->dma_dac.endcleared = 0;
+               spin_unlock_irqrestore(&s->lock, flags);
+               count -= cnt;
+               buffer += cnt;
+               ret += cnt;
+               start_dac(s);
+       }
+       return ret;
+}
+
+static unsigned int solo1_poll(struct file *file, struct poll_table_struct *wait)
+{
+       struct solo1_state *s = (struct solo1_state *)file->private_data;
+       unsigned long flags;
+       unsigned int mask = 0;
+
+       VALIDATE_STATE(s);
+       if (file->f_mode & FMODE_WRITE)
+               poll_wait(file, &s->dma_dac.wait, wait);
+       if (file->f_mode & FMODE_READ)
+               poll_wait(file, &s->dma_adc.wait, wait);
+       spin_lock_irqsave(&s->lock, flags);
+       solo1_update_ptr(s);
+       if (file->f_mode & FMODE_READ) {
+               if (s->dma_adc.mapped) {
+                       if (s->dma_adc.count >= (signed)s->dma_adc.fragsize)
+                               mask |= POLLIN | POLLRDNORM;
+               } else {
+                       if (s->dma_adc.count > 0)
+                               mask |= POLLIN | POLLRDNORM;
+               }
+       }
+       if (file->f_mode & FMODE_WRITE) {
+               if (s->dma_dac.mapped) {
+                       if (s->dma_dac.count >= (signed)s->dma_dac.fragsize) 
+                               mask |= POLLOUT | POLLWRNORM;
+               } else {
+                       if ((signed)s->dma_dac.dmasize > s->dma_dac.count)
+                               mask |= POLLOUT | POLLWRNORM;
+               }
+       }
+       spin_unlock_irqrestore(&s->lock, flags);
+       return mask;
+}
+
+
+static int solo1_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       struct solo1_state *s = (struct solo1_state *)file->private_data;
+       struct dmabuf *db;
+       int ret;
+       unsigned long size;
+
+       VALIDATE_STATE(s);
+       if (vma->vm_flags & VM_WRITE) {
+               if ((ret = prog_dmabuf_dac(s)) != 0)
+                       return ret;
+               db = &s->dma_dac;
+       } else if (vma->vm_flags & VM_READ) {
+               if ((ret = prog_dmabuf_adc(s)) != 0)
+                       return ret;
+               db = &s->dma_adc;
+       } else 
+               return -EINVAL;
+       if (vma->vm_offset != 0)
+               return -EINVAL;
+       size = vma->vm_end - vma->vm_start;
+       if (size > (PAGE_SIZE << db->buforder))
+               return -EINVAL;
+       if (remap_page_range(vma->vm_start, virt_to_phys(db->rawbuf), size, vma->vm_page_prot))
+               return -EAGAIN;
+       db->mapped = 1;
+       return 0;
+}
+
+static int solo1_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+{
+       struct solo1_state *s = (struct solo1_state *)file->private_data;
+       unsigned long flags;
+        audio_buf_info abinfo;
+        count_info cinfo;
+       int val, mapped, ret;
+        int div1, div2;
+        unsigned rate1, rate2;
+
+       VALIDATE_STATE(s);
+        mapped = ((file->f_mode & FMODE_WRITE) && s->dma_dac.mapped) ||
+               ((file->f_mode & FMODE_READ) && s->dma_adc.mapped);
+       switch (cmd) {
+       case OSS_GETVERSION:
+               return put_user(SOUND_VERSION, (int *)arg);
+
+       case SNDCTL_DSP_SYNC:
+               if (file->f_mode & FMODE_WRITE)
+                       return drain_dac(s, 0/*file->f_flags & O_NONBLOCK*/);
+               return 0;
+               
+       case SNDCTL_DSP_SETDUPLEX:
+               return 0;
+
+       case SNDCTL_DSP_GETCAPS:
+               return put_user(DSP_CAP_DUPLEX | DSP_CAP_REALTIME | DSP_CAP_TRIGGER | DSP_CAP_MMAP, (int *)arg);
+               
+        case SNDCTL_DSP_RESET:
+               if (file->f_mode & FMODE_WRITE) {
+                       stop_dac(s);
+                       synchronize_irq();
+                       s->dma_dac.swptr = s->dma_dac.hwptr = s->dma_dac.count = s->dma_dac.total_bytes = 0;
+               }
+               if (file->f_mode & FMODE_READ) {
+                       stop_adc(s);
+                       synchronize_irq();
+                       s->dma_adc.swptr = s->dma_adc.hwptr = s->dma_adc.count = s->dma_adc.total_bytes = 0;
+               }
+               prog_codec(s);
+               return 0;
+
+        case SNDCTL_DSP_SPEED:
+                get_user_ret(val, (int *)arg, -EFAULT);
+               if (val >= 0) {
+                       stop_adc(s);
+                       stop_dac(s);
+                       s->dma_adc.ready = s->dma_dac.ready = 0;
+                       /* program sampling rates */
+                       if (val > 48000)
+                               val = 48000;
+                       if (val < 6300)
+                               val = 6300;
+                       div1 = (768000 + val / 2) / val;
+                       rate1 = (768000 + div1 / 2) / div1;
+                       div1 = -div1;
+                       div2 = (793800 + val / 2) / val;
+                       rate2 = (793800 + div2 / 2) / div2;
+                       div2 = (-div2) & 0x7f;
+                       if (abs(val - rate2) < abs(val - rate1)) {
+                               rate1 = rate2;
+                               div1 = div2;
+                       }
+                       s->rate = rate1;
+                       s->clkdiv = div1;
+                       prog_codec(s);
+               }
+               return put_user(s->rate, (int *)arg);
+               
+        case SNDCTL_DSP_STEREO:
+                get_user_ret(val, (int *)arg, -EFAULT);
+               stop_adc(s);
+               stop_dac(s);
+               s->dma_adc.ready = s->dma_dac.ready = 0;
+               /* program channels */
+               s->channels = val ? 2 : 1;
+               prog_codec(s);
+               return 0;
+
+        case SNDCTL_DSP_CHANNELS:
+                get_user_ret(val, (int *)arg, -EFAULT);
+               if (val != 0) {
+                       stop_adc(s);
+                       stop_dac(s);
+                       s->dma_adc.ready = s->dma_dac.ready = 0;
+                       /* program channels */
+                       s->channels = val ? 2 : 1;
+                       prog_codec(s);
+               }
+               return put_user(s->channels, (int *)arg);
+
+       case SNDCTL_DSP_GETFMTS: /* Returns a mask */
+                return put_user(AFMT_S16_LE|AFMT_U16_LE|AFMT_S8|AFMT_U8, (int *)arg);
+
+       case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/
+               get_user_ret(val, (int *)arg, -EFAULT);
+               if (val != AFMT_QUERY) {
+                       stop_adc(s);
+                       stop_dac(s);
+                       s->dma_adc.ready = s->dma_dac.ready = 0;
+                       /* program format */
+                       if (val != AFMT_S16_LE && val != AFMT_U16_LE && 
+                           val != AFMT_S8 && val != AFMT_U8)
+                               val = AFMT_U8;
+                       s->fmt = val;
+                       prog_codec(s);
+               }
+               return put_user(s->fmt, (int *)arg);
+
+       case SNDCTL_DSP_POST:
+                return 0;
+
+        case SNDCTL_DSP_GETTRIGGER:
+               val = 0;
+               if (file->f_mode & s->ena & FMODE_READ)
+                       val |= PCM_ENABLE_INPUT;
+               if (file->f_mode & s->ena & FMODE_WRITE)
+                       val |= PCM_ENABLE_OUTPUT;
+               return put_user(val, (int *)arg);
+
+       case SNDCTL_DSP_SETTRIGGER:
+               get_user_ret(val, (int *)arg, -EFAULT);
+               if (file->f_mode & FMODE_READ) {
+                       if (val & PCM_ENABLE_INPUT) {
+                               if (!s->dma_adc.ready && (ret = prog_dmabuf_adc(s)))
+                                       return ret;
+                               start_adc(s);
+                               if (inb(s->vcbase+15) & 1)
+                                       printk(KERN_ERR "solo1: cannot start recording, DDMA mask bit stuck at 1\n");
+                       } else
+                               stop_adc(s);
+               }
+               if (file->f_mode & FMODE_WRITE) {
+                       if (val & PCM_ENABLE_OUTPUT) {
+                               if (!s->dma_dac.ready && (ret = prog_dmabuf_dac(s)))
+                                       return ret;
+                               start_dac(s);
+                       } else
+                               stop_dac(s);
+               }
+               return 0;
+
+       case SNDCTL_DSP_GETOSPACE:
+               if (!(file->f_mode & FMODE_WRITE))
+                       return -EINVAL;
+               if (!(s->ena & FMODE_WRITE) && (val = prog_dmabuf_dac(s)) != 0)
+                       return val;
+               spin_lock_irqsave(&s->lock, flags);
+               solo1_update_ptr(s);
+               abinfo.fragsize = s->dma_dac.fragsize;
+                abinfo.bytes = s->dma_dac.dmasize - s->dma_dac.count;
+                abinfo.fragstotal = s->dma_dac.numfrag;
+                abinfo.fragments = abinfo.bytes >> s->dma_dac.fragshift;      
+               spin_unlock_irqrestore(&s->lock, flags);
+               return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
+
+       case SNDCTL_DSP_GETISPACE:
+               if (!(file->f_mode & FMODE_READ))
+                       return -EINVAL;
+               if (!(s->ena & FMODE_READ) && (val = prog_dmabuf_adc(s)) != 0)
+                       return val;
+               spin_lock_irqsave(&s->lock, flags);
+               solo1_update_ptr(s);
+               abinfo.fragsize = s->dma_adc.fragsize;
+                abinfo.bytes = s->dma_adc.count;
+                abinfo.fragstotal = s->dma_adc.numfrag;
+                abinfo.fragments = abinfo.bytes >> s->dma_adc.fragshift;      
+               spin_unlock_irqrestore(&s->lock, flags);
+               return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
+
+        case SNDCTL_DSP_NONBLOCK:
+                file->f_flags |= O_NONBLOCK;
+                return 0;
+
+        case SNDCTL_DSP_GETODELAY:
+               if (!(file->f_mode & FMODE_WRITE))
+                       return -EINVAL;
+               spin_lock_irqsave(&s->lock, flags);
+               solo1_update_ptr(s);
+                val = s->dma_dac.count;
+               spin_unlock_irqrestore(&s->lock, flags);
+               return put_user(val, (int *)arg);
+
+        case SNDCTL_DSP_GETIPTR:
+               if (!(file->f_mode & FMODE_READ))
+                       return -EINVAL;
+               spin_lock_irqsave(&s->lock, flags);
+               solo1_update_ptr(s);
+                cinfo.bytes = s->dma_adc.total_bytes;
+                cinfo.blocks = s->dma_adc.count >> s->dma_adc.fragshift;
+                cinfo.ptr = s->dma_adc.hwptr;
+               if (s->dma_adc.mapped)
+                       s->dma_adc.count &= s->dma_adc.fragsize-1;
+               spin_unlock_irqrestore(&s->lock, flags);
+                return copy_to_user((void *)arg, &cinfo, sizeof(cinfo));
+
+        case SNDCTL_DSP_GETOPTR:
+               if (!(file->f_mode & FMODE_WRITE))
+                       return -EINVAL;
+               spin_lock_irqsave(&s->lock, flags);
+               solo1_update_ptr(s);
+                cinfo.bytes = s->dma_dac.total_bytes;
+                cinfo.blocks = s->dma_dac.count >> s->dma_dac.fragshift;
+                cinfo.ptr = s->dma_dac.hwptr;
+               if (s->dma_dac.mapped)
+                       s->dma_dac.count &= s->dma_dac.fragsize-1;
+               spin_unlock_irqrestore(&s->lock, flags);
+                return copy_to_user((void *)arg, &cinfo, sizeof(cinfo));
+
+        case SNDCTL_DSP_GETBLKSIZE:
+               if (file->f_mode & FMODE_WRITE) {
+                       if ((val = prog_dmabuf_dac(s)))
+                               return val;
+                       return put_user(s->dma_dac.fragsize, (int *)arg);
+               }
+               if ((val = prog_dmabuf_adc(s)))
+                       return val;
+               return put_user(s->dma_adc.fragsize, (int *)arg);
+
+        case SNDCTL_DSP_SETFRAGMENT:
+                get_user_ret(val, (int *)arg, -EFAULT);
+               if (file->f_mode & FMODE_READ) {
+                       s->dma_adc.ossfragshift = val & 0xffff;
+                       s->dma_adc.ossmaxfrags = (val >> 16) & 0xffff;
+                       if (s->dma_adc.ossfragshift < 4)
+                               s->dma_adc.ossfragshift = 4;
+                       if (s->dma_adc.ossfragshift > 15)
+                               s->dma_adc.ossfragshift = 15;
+                       if (s->dma_adc.ossmaxfrags < 4)
+                               s->dma_adc.ossmaxfrags = 4;
+               }
+               if (file->f_mode & FMODE_WRITE) {
+                       s->dma_dac.ossfragshift = val & 0xffff;
+                       s->dma_dac.ossmaxfrags = (val >> 16) & 0xffff;
+                       if (s->dma_dac.ossfragshift < 4)
+                               s->dma_dac.ossfragshift = 4;
+                       if (s->dma_dac.ossfragshift > 15)
+                               s->dma_dac.ossfragshift = 15;
+                       if (s->dma_dac.ossmaxfrags < 4)
+                               s->dma_dac.ossmaxfrags = 4;
+               }
+               return 0;
+
+        case SNDCTL_DSP_SUBDIVIDE:
+               if ((file->f_mode & FMODE_READ && s->dma_adc.subdivision) ||
+                   (file->f_mode & FMODE_WRITE && s->dma_dac.subdivision))
+                       return -EINVAL;
+                get_user_ret(val, (int *)arg, -EFAULT);
+               if (val != 1 && val != 2 && val != 4)
+                       return -EINVAL;
+               if (file->f_mode & FMODE_READ)
+                       s->dma_adc.subdivision = val;
+               if (file->f_mode & FMODE_WRITE)
+                       s->dma_dac.subdivision = val;
+               return 0;
+
+        case SOUND_PCM_READ_RATE:
+               return put_user(s->rate, (int *)arg);
+
+        case SOUND_PCM_READ_CHANNELS:
+               return put_user(s->channels, (int *)arg);
+
+        case SOUND_PCM_READ_BITS:
+               return put_user((s->fmt & (AFMT_S8|AFMT_U8)) ? 8 : 16, (int *)arg);
+
+        case SOUND_PCM_WRITE_FILTER:
+        case SNDCTL_DSP_SETSYNCRO:
+        case SOUND_PCM_READ_FILTER:
+                return -EINVAL;
+               
+       }
+       return mixer_ioctl(s, cmd, arg);
+}
+
+static int solo1_release(struct inode *inode, struct file *file)
+{
+       struct solo1_state *s = (struct solo1_state *)file->private_data;
+
+       VALIDATE_STATE(s);
+       if (file->f_mode & FMODE_WRITE)
+               drain_dac(s, file->f_flags & O_NONBLOCK);
+       down(&s->open_sem);
+       if (file->f_mode & FMODE_WRITE) {
+               stop_dac(s);
+               outb(0, s->iobase+6);  /* disable DMA */
+               dealloc_dmabuf(&s->dma_dac);
+       }
+       if (file->f_mode & FMODE_READ) {
+               stop_adc(s);
+               outb(1, s->vcbase+0xf); /* mask DMA channel */
+               //outb(0, s->vcbase+0xd); /* DMA master clear */
+               dealloc_dmabuf(&s->dma_adc);
+       }
+       s->open_mode &= ~(FMODE_READ | FMODE_WRITE);
+       up(&s->open_sem);
+       wake_up(&s->open_wait);
+       MOD_DEC_USE_COUNT;
+       return 0;
+}
+
+static int solo1_open(struct inode *inode, struct file *file)
+{
+       int minor = MINOR(inode->i_rdev);
+       struct solo1_state *s = devs;
+
+       while (s && ((s->dev_audio ^ minor) & ~0xf))
+               s = s->next;
+       if (!s)
+               return -ENODEV;
+               VALIDATE_STATE(s);
+       file->private_data = s;
+       /* wait for device to become free */
+       down(&s->open_sem);
+       while (s->open_mode & (FMODE_READ | FMODE_WRITE)) {
+               if (file->f_flags & O_NONBLOCK) {
+                       up(&s->open_sem);
+                       return -EBUSY;
+               }
+               up(&s->open_sem);
+               interruptible_sleep_on(&s->open_wait);
+               if (signal_pending(current))
+                       return -ERESTARTSYS;
+               down(&s->open_sem);
+       }
+       s->fmt = AFMT_U8;
+       s->channels = 1;
+       s->rate = 8000;
+       s->clkdiv = 96 | 0x80;
+       s->ena = 0;
+       s->dma_adc.ossfragshift = s->dma_adc.ossmaxfrags = s->dma_adc.subdivision = 0;
+       s->dma_dac.ossfragshift = s->dma_dac.ossmaxfrags = s->dma_dac.subdivision = 0;
+       s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE);
+       up(&s->open_sem);
+       MOD_INC_USE_COUNT;
+       if (prog_dmabuf_dac(s) || prog_dmabuf_adc(s)) {
+               solo1_release(inode, file);
+               return -ENOMEM;
+       }
+       prog_codec(s);
+       return 0;
+}
+
+static /*const*/ struct file_operations solo1_audio_fops = {
+       &solo1_llseek,
+       &solo1_read,
+       &solo1_write,
+       NULL,  /* readdir */
+       &solo1_poll,
+       &solo1_ioctl,
+       &solo1_mmap,
+       &solo1_open,
+       NULL,  /* flush */
+       &solo1_release,
+       NULL,  /* fsync */
+       NULL,  /* fasync */
+       NULL,  /* check_media_change */
+#if 0
+       NULL,  /* revalidate */
+       NULL,  /* lock */
+#endif
+};
+
+/* --------------------------------------------------------------------- */
+
+/* hold spinlock for the following! */
+static void solo1_handle_midi(struct solo1_state *s)
+{
+       unsigned char ch;
+       int wake;
+
+       if (!(s->mpubase))
+               return;
+       wake = 0;
+       while (inb(s->mpubase+1) & 0x80) {
+               ch = inb(s->mpubase);
+               if (s->midi.icnt < MIDIINBUF) {
+                       s->midi.ibuf[s->midi.iwr] = ch;
+                       s->midi.iwr = (s->midi.iwr + 1) % MIDIINBUF;
+                       s->midi.icnt++;
+               }
+               wake = 1;
+       }
+       if (wake)
+               wake_up(&s->midi.iwait);
+       wake = 0;
+       while ((inb(s->mpubase+1) & 0x40) && s->midi.ocnt > 0) {
+               outb(s->midi.obuf[s->midi.ord], s->mpubase);
+               s->midi.ord = (s->midi.ord + 1) % MIDIOUTBUF;
+               s->midi.ocnt--;
+               if (s->midi.ocnt < MIDIOUTBUF-16)
+                       wake = 1;
+       }
+       if (wake)
+               wake_up(&s->midi.owait);
+}
+
+static void solo1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+        struct solo1_state *s = (struct solo1_state *)dev_id;
+       unsigned int intsrc;
+
+       static unsigned lim = 0;
+       
+       /* fastpath out, to ease interrupt sharing */
+       intsrc = inb(s->iobase+7); /* get interrupt source(s) */
+       if (!intsrc)
+               return;
+       (void)inb(s->sbbase+0xe);  /* clear interrupt */
+#ifdef DEBUGREC
+       if (intsrc & 0x10 && lim < 20) {
+               lim++;
+               printk(KERN_DEBUG "solo1: audio1int reg B8: 0x%02x  DMAstat: 0x%02x  DMAcnt: 0x%04x  SBstat: 0x%02x\n", 
+                      read_ctrl(s, 0xb8), inb(s->vcbase+8), inw(s->vcbase+4), inb(s->sbbase+0xc));
+       }
+       //printk(KERN_DEBUG "solo1: interrupt 0x%02x\n", intsrc);
+#endif
+       spin_lock(&s->lock);
+       /* clear audio interrupts first */
+       if (intsrc & 0x20)
+               write_mixer(s, 0x7a, read_mixer(s, 0x7a) & 0x7f);
+       solo1_update_ptr(s);
+       solo1_handle_midi(s);
+       spin_unlock(&s->lock);
+}
+
+static void solo1_midi_timer(unsigned long data)
+{
+       struct solo1_state *s = (struct solo1_state *)data;
+       unsigned long flags;
+       
+       spin_lock_irqsave(&s->lock, flags);
+       solo1_handle_midi(s);
+       spin_unlock_irqrestore(&s->lock, flags);
+       s->midi.timer.expires = jiffies+1;
+       add_timer(&s->midi.timer);
+}
+
+/* --------------------------------------------------------------------- */
+
+static ssize_t solo1_midi_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
+{
+       struct solo1_state *s = (struct solo1_state *)file->private_data;
+       ssize_t ret;
+       unsigned long flags;
+       unsigned ptr;
+       int cnt;
+
+       VALIDATE_STATE(s);
+       if (ppos != &file->f_pos)
+               return -ESPIPE;
+       if (!access_ok(VERIFY_WRITE, buffer, count))
+               return -EFAULT;
+       ret = 0;
+       while (count > 0) {
+               spin_lock_irqsave(&s->lock, flags);
+               ptr = s->midi.ird;
+               cnt = MIDIINBUF - ptr;
+               if (s->midi.icnt < cnt)
+                       cnt = s->midi.icnt;
+               spin_unlock_irqrestore(&s->lock, flags);
+               if (cnt > count)
+                       cnt = count;
+               if (cnt <= 0) {
+                       if (file->f_flags & O_NONBLOCK)
+                               return ret ? ret : -EAGAIN;
+                       interruptible_sleep_on(&s->midi.iwait);
+                       if (signal_pending(current))
+                               return ret ? ret : -ERESTARTSYS;
+                       continue;
+               }
+               if (copy_to_user(buffer, s->midi.ibuf + ptr, cnt))
+                       return ret ? ret : -EFAULT;
+               ptr = (ptr + cnt) % MIDIINBUF;
+               spin_lock_irqsave(&s->lock, flags);
+               s->midi.ird = ptr;
+               s->midi.icnt -= cnt;
+               spin_unlock_irqrestore(&s->lock, flags);
+               count -= cnt;
+               buffer += cnt;
+               ret += cnt;
+       }
+       return ret;
+}
+
+static ssize_t solo1_midi_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
+{
+       struct solo1_state *s = (struct solo1_state *)file->private_data;
+       ssize_t ret;
+       unsigned long flags;
+       unsigned ptr;
+       int cnt;
+
+       VALIDATE_STATE(s);
+       if (ppos != &file->f_pos)
+               return -ESPIPE;
+       if (!access_ok(VERIFY_READ, buffer, count))
+               return -EFAULT;
+       ret = 0;
+       while (count > 0) {
+               spin_lock_irqsave(&s->lock, flags);
+               ptr = s->midi.owr;
+               cnt = MIDIOUTBUF - ptr;
+               if (s->midi.ocnt + cnt > MIDIOUTBUF)
+                       cnt = MIDIOUTBUF - s->midi.ocnt;
+               if (cnt <= 0)
+                       solo1_handle_midi(s);
+               spin_unlock_irqrestore(&s->lock, flags);
+               if (cnt > count)
+                       cnt = count;
+               if (cnt <= 0) {
+                       if (file->f_flags & O_NONBLOCK)
+                               return ret ? ret : -EAGAIN;
+                       interruptible_sleep_on(&s->midi.owait);
+                       if (signal_pending(current))
+                               return ret ? ret : -ERESTARTSYS;
+                       continue;
+               }
+               if (copy_from_user(s->midi.obuf + ptr, buffer, cnt))
+                       return ret ? ret : -EFAULT;
+               ptr = (ptr + cnt) % MIDIOUTBUF;
+               spin_lock_irqsave(&s->lock, flags);
+               s->midi.owr = ptr;
+               s->midi.ocnt += cnt;
+               spin_unlock_irqrestore(&s->lock, flags);
+               count -= cnt;
+               buffer += cnt;
+               ret += cnt;
+               spin_lock_irqsave(&s->lock, flags);
+               solo1_handle_midi(s);
+               spin_unlock_irqrestore(&s->lock, flags);
+       }
+       return ret;
+}
+
+static unsigned int solo1_midi_poll(struct file *file, struct poll_table_struct *wait)
+{
+       struct solo1_state *s = (struct solo1_state *)file->private_data;
+       unsigned long flags;
+       unsigned int mask = 0;
+
+       VALIDATE_STATE(s);
+       if (file->f_flags & FMODE_WRITE)
+               poll_wait(file, &s->midi.owait, wait);
+       if (file->f_flags & FMODE_READ)
+               poll_wait(file, &s->midi.iwait, wait);
+       spin_lock_irqsave(&s->lock, flags);
+       if (file->f_flags & FMODE_READ) {
+               if (s->midi.icnt > 0)
+                       mask |= POLLIN | POLLRDNORM;
+       }
+       if (file->f_flags & FMODE_WRITE) {
+               if (s->midi.ocnt < MIDIOUTBUF)
+                       mask |= POLLOUT | POLLWRNORM;
+       }
+       spin_unlock_irqrestore(&s->lock, flags);
+       return mask;
+}
+
+static int solo1_midi_open(struct inode *inode, struct file *file)
+{
+       int minor = MINOR(inode->i_rdev);
+       struct solo1_state *s = devs;
+       unsigned long flags;
+
+       while (s && s->dev_midi != minor)
+               s = s->next;
+       if (!s)
+               return -ENODEV;
+               VALIDATE_STATE(s);
+       file->private_data = s;
+       /* wait for device to become free */
+       down(&s->open_sem);
+       while (s->open_mode & (file->f_mode << FMODE_MIDI_SHIFT)) {
+               if (file->f_flags & O_NONBLOCK) {
+                       up(&s->open_sem);
+                       return -EBUSY;
+               }
+               up(&s->open_sem);
+               interruptible_sleep_on(&s->open_wait);
+               if (signal_pending(current))
+                       return -ERESTARTSYS;
+               down(&s->open_sem);
+       }
+       spin_lock_irqsave(&s->lock, flags);
+       if (!(s->open_mode & (FMODE_MIDI_READ | FMODE_MIDI_WRITE))) {
+               s->midi.ird = s->midi.iwr = s->midi.icnt = 0;
+               s->midi.ord = s->midi.owr = s->midi.ocnt = 0;
+               outb(0xff, s->mpubase+1); /* reset command */
+               outb(0x3f, s->mpubase+1); /* uart command */
+               if (!(inb(s->mpubase+1) & 0x80))
+                       inb(s->mpubase);
+               s->midi.ird = s->midi.iwr = s->midi.icnt = 0;
+               outb(0xb0, s->iobase + 7); /* enable A1, A2, MPU irq's */
+               init_timer(&s->midi.timer);
+               s->midi.timer.expires = jiffies+1;
+               s->midi.timer.data = (unsigned long)s;
+               s->midi.timer.function = solo1_midi_timer;
+               add_timer(&s->midi.timer);
+       }
+       if (file->f_mode & FMODE_READ) {
+               s->midi.ird = s->midi.iwr = s->midi.icnt = 0;
+       }
+       if (file->f_mode & FMODE_WRITE) {
+               s->midi.ord = s->midi.owr = s->midi.ocnt = 0;
+       }
+       spin_unlock_irqrestore(&s->lock, flags);
+       s->open_mode |= (file->f_mode << FMODE_MIDI_SHIFT) & (FMODE_MIDI_READ | FMODE_MIDI_WRITE);
+       up(&s->open_sem);
+       MOD_INC_USE_COUNT;
+       return 0;
+}
+
+static int solo1_midi_release(struct inode *inode, struct file *file)
+{
+       struct solo1_state *s = (struct solo1_state *)file->private_data;
+       DECLARE_WAITQUEUE(wait, current);
+       unsigned long flags;
+       unsigned count, tmo;
+
+       VALIDATE_STATE(s);
+
+       if (file->f_mode & FMODE_WRITE) {
+               current->state = TASK_INTERRUPTIBLE;
+               add_wait_queue(&s->midi.owait, &wait);
+               for (;;) {
+                       spin_lock_irqsave(&s->lock, flags);
+                       count = s->midi.ocnt;
+                       spin_unlock_irqrestore(&s->lock, flags);
+                       if (count <= 0)
+                               break;
+                       if (signal_pending(current))
+                               break;
+                       if (file->f_flags & O_NONBLOCK) {
+                               remove_wait_queue(&s->midi.owait, &wait);
+                               current->state = TASK_RUNNING;
+                               return -EBUSY;
+                       }
+                       tmo = (count * HZ) / 3100;
+                       if (!schedule_timeout(tmo ? : 1) && tmo)
+                               printk(KERN_DEBUG "solo1: midi timed out??\n");
+               }
+               remove_wait_queue(&s->midi.owait, &wait);
+               current->state = TASK_RUNNING;
+       }
+       down(&s->open_sem);
+       s->open_mode &= (~(file->f_mode << FMODE_MIDI_SHIFT)) & (FMODE_MIDI_READ|FMODE_MIDI_WRITE);
+       spin_lock_irqsave(&s->lock, flags);
+       if (!(s->open_mode & (FMODE_MIDI_READ | FMODE_MIDI_WRITE))) {
+               outb(0x30, s->iobase + 7); /* enable A1, A2 irq's */
+               del_timer(&s->midi.timer);              
+       }
+       spin_unlock_irqrestore(&s->lock, flags);
+       up(&s->open_sem);
+       wake_up(&s->open_wait);
+       MOD_DEC_USE_COUNT;
+       return 0;
+}
+
+static /*const*/ struct file_operations solo1_midi_fops = {
+       &solo1_llseek,
+       &solo1_midi_read,
+       &solo1_midi_write,
+       NULL,  /* readdir */
+       &solo1_midi_poll,
+       NULL,  /* ioctl */
+       NULL,  /* mmap */
+       &solo1_midi_open,
+       NULL,  /* flush */
+       &solo1_midi_release,
+       NULL,  /* fsync */
+       NULL,  /* fasync */
+       NULL,  /* check_media_change */
+#if 0
+       NULL,  /* revalidate */
+       NULL,  /* lock */
+#endif
+};
+
+/* --------------------------------------------------------------------- */
+
+static int solo1_dmfm_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+{
+       static const unsigned char op_offset[18] = {
+               0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+               0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D,
+               0x10, 0x11, 0x12, 0x13, 0x14, 0x15
+       };
+       struct solo1_state *s = (struct solo1_state *)file->private_data;
+       struct dm_fm_voice v;
+       struct dm_fm_note n;
+       struct dm_fm_params p;
+       unsigned int io;
+       unsigned int regb;
+
+       switch (cmd) {          
+       case FM_IOCTL_RESET:
+               for (regb = 0xb0; regb < 0xb9; regb++) {
+                       outb(regb, s->sbbase);
+                       outb(0, s->sbbase+1);
+                       outb(regb, s->sbbase+2);
+                       outb(0, s->sbbase+3);
+               }
+               return 0;
+
+       case FM_IOCTL_PLAY_NOTE:
+               if (copy_from_user(&n, (void *)arg, sizeof(n)))
+                       return -EFAULT;
+               if (n.voice >= 18)
+                       return -EINVAL;
+               if (n.voice >= 9) {
+                       regb = n.voice - 9;
+                       io = s->sbbase+2;
+               } else {
+                       regb = n.voice;
+                       io = s->sbbase;
+               }
+               outb(0xa0 + regb, io);
+               outb(n.fnum & 0xff, io+1);
+               outb(0xb0 + regb, io);
+               outb(((n.fnum >> 8) & 3) | ((n.octave & 7) << 2) | ((n.key_on & 1) << 5), io+1);
+               return 0;
+
+       case FM_IOCTL_SET_VOICE:
+               if (copy_from_user(&v, (void *)arg, sizeof(v)))
+                       return -EFAULT;
+               if (v.voice >= 18)
+                       return -EINVAL;
+               regb = op_offset[v.voice];
+               io = s->sbbase + ((v.op & 1) << 1);
+               outb(0x20 + regb, io);
+               outb(((v.am & 1) << 7) | ((v.vibrato & 1) << 6) | ((v.do_sustain & 1) << 5) | 
+                    ((v.kbd_scale & 1) << 4) | (v.harmonic & 0xf), io+1);
+               outb(0x40 + regb, io);
+               outb(((v.scale_level & 0x3) << 6) | (v.volume & 0x3f), io+1);
+               outb(0x60 + regb, io);
+               outb(((v.attack & 0xf) << 4) | (v.decay & 0xf), io+1);
+               outb(0x80 + regb, io);
+               outb(((v.sustain & 0xf) << 4) | (v.release & 0xf), io+1);
+               outb(0xe0 + regb, io);
+               outb(v.waveform & 0x7, io+1);
+               if (n.voice >= 9) {
+                       regb = n.voice - 9;
+                       io = s->sbbase+2;
+               } else {
+                       regb = n.voice;
+                       io = s->sbbase;
+               }
+               outb(0xc0 + regb, io);
+               outb(((v.right & 1) << 5) | ((v.left & 1) << 4) | ((v.feedback & 7) << 1) |
+                    (v.connection & 1), io+1);
+               return 0;
+               
+       case FM_IOCTL_SET_PARAMS:
+               if (copy_from_user(&p, (void *)arg, sizeof(p)))
+                       return -EFAULT;
+               outb(0x08, s->sbbase);
+               outb((p.kbd_split & 1) << 6, s->sbbase+1);
+               outb(0xbd, s->sbbase);
+               outb(((p.am_depth & 1) << 7) | ((p.vib_depth & 1) << 6) | ((p.rhythm & 1) << 5) | ((p.bass & 1) << 4) |
+                    ((p.snare & 1) << 3) | ((p.tomtom & 1) << 2) | ((p.cymbal & 1) << 1) | (p.hihat & 1), s->sbbase+1);
+               return 0;
+
+       case FM_IOCTL_SET_OPL:
+               outb(4, s->sbbase+2);
+               outb(arg, s->sbbase+3);
+               return 0;
+
+       case FM_IOCTL_SET_MODE:
+               outb(5, s->sbbase+2);
+               outb(arg & 1, s->sbbase+3);
+               return 0;
+
+       default:
+               return -EINVAL;
+       }
+}
+
+static int solo1_dmfm_open(struct inode *inode, struct file *file)
+{
+       int minor = MINOR(inode->i_rdev);
+       struct solo1_state *s = devs;
+
+       while (s && s->dev_dmfm != minor)
+               s = s->next;
+       if (!s)
+               return -ENODEV;
+               VALIDATE_STATE(s);
+       file->private_data = s;
+       /* wait for device to become free */
+       down(&s->open_sem);
+       while (s->open_mode & FMODE_DMFM) {
+               if (file->f_flags & O_NONBLOCK) {
+                       up(&s->open_sem);
+                       return -EBUSY;
+               }
+               up(&s->open_sem);
+               interruptible_sleep_on(&s->open_wait);
+               if (signal_pending(current))
+                       return -ERESTARTSYS;
+               down(&s->open_sem);
+       }
+       /* init the stuff */
+       outb(1, s->sbbase);
+       outb(0x20, s->sbbase+1); /* enable waveforms */
+       outb(4, s->sbbase+2);
+       outb(0, s->sbbase+3);  /* no 4op enabled */
+       outb(5, s->sbbase+2);
+       outb(1, s->sbbase+3);  /* enable OPL3 */
+       s->open_mode |= FMODE_DMFM;
+       up(&s->open_sem);
+       MOD_INC_USE_COUNT;
+       return 0;
+}
+
+static int solo1_dmfm_release(struct inode *inode, struct file *file)
+{
+       struct solo1_state *s = (struct solo1_state *)file->private_data;
+       unsigned int regb;
+
+       VALIDATE_STATE(s);
+       down(&s->open_sem);
+       s->open_mode &= ~FMODE_DMFM;
+       for (regb = 0xb0; regb < 0xb9; regb++) {
+               outb(regb, s->sbbase);
+               outb(0, s->sbbase+1);
+               outb(regb, s->sbbase+2);
+               outb(0, s->sbbase+3);
+       }
+       up(&s->open_sem);
+       wake_up(&s->open_wait);
+       MOD_DEC_USE_COUNT;
+       return 0;
+}
+
+static /*const*/ struct file_operations solo1_dmfm_fops = {
+       &solo1_llseek,
+       NULL,  /* read */
+       NULL,  /* write */
+       NULL,  /* readdir */
+       NULL,  /* poll */
+       &solo1_dmfm_ioctl,
+       NULL,  /* mmap */
+       &solo1_dmfm_open,
+       NULL,  /* flush */
+       &solo1_dmfm_release,
+       NULL,  /* fsync */
+       NULL,  /* fasync */
+       NULL,  /* check_media_change */
+#if 0
+       NULL,  /* revalidate */
+       NULL,  /* lock */
+#endif
+};
+
+/* --------------------------------------------------------------------- */
+
+/* maximum number of devices */
+#define NR_DEVICE 5
+
+/* --------------------------------------------------------------------- */
+
+static struct initvol {
+       int mixch;
+       int vol;
+} initvol[] __initdata = {
+       { SOUND_MIXER_WRITE_VOLUME, 0x4040 },
+       { SOUND_MIXER_WRITE_PCM, 0x4040 },
+       { SOUND_MIXER_WRITE_SYNTH, 0x4040 },
+       { SOUND_MIXER_WRITE_CD, 0x4040 },
+       { SOUND_MIXER_WRITE_LINE, 0x4040 },
+       { SOUND_MIXER_WRITE_LINE1, 0x4040 },
+       { SOUND_MIXER_WRITE_LINE2, 0x4040 },
+       { SOUND_MIXER_WRITE_RECLEV, 0x4040 },
+       { SOUND_MIXER_WRITE_SPEAKER, 0x4040 },
+       { SOUND_MIXER_WRITE_MIC, 0x4040 }
+};
+
+static int __init init_solo1(void)
+{
+       struct solo1_state *s;
+       struct pci_dev *pcidev = NULL;
+       mm_segment_t fs;
+       int i, val, index = 0;
+       u16 ddmabase;
+
+       if (!pci_present())   /* No PCI bus in this machine! */
+               return -ENODEV;
+       printk(KERN_INFO "solo1: version v0.5 time " __TIME__ " " __DATE__ "\n");
+       while (index < NR_DEVICE && 
+              (pcidev = pci_find_device(PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_SOLO1, pcidev))) {
+               if (pcidev->resource[0].start == 0 ||
+                   (pcidev->resource[0].flags & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_IO ||
+                   pcidev->resource[1].start == 0 ||
+                   (pcidev->resource[1].flags & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_IO ||
+                   pcidev->resource[2].start == 0 ||
+                   (pcidev->resource[2].flags & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_IO ||
+                   pcidev->resource[3].start == 0 ||
+                   (pcidev->resource[3].flags & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_IO)
+                       continue;
+               if (pcidev->irq == 0)
+                       continue;
+               if (!(s = kmalloc(sizeof(struct solo1_state), GFP_KERNEL))) {
+                       printk(KERN_WARNING "solo1: out of memory\n");
+                       continue;
+               }
+               memset(s, 0, sizeof(struct solo1_state));
+               init_waitqueue_head(&s->dma_adc.wait);
+               init_waitqueue_head(&s->dma_dac.wait);
+               init_waitqueue_head(&s->open_wait);
+               init_waitqueue_head(&s->midi.iwait);
+               init_waitqueue_head(&s->midi.owait);
+               init_MUTEX(&s->open_sem);
+               s->magic = SOLO1_MAGIC;
+               s->iobase = pcidev->resource[0].start;
+               s->sbbase = pcidev->resource[1].start;
+               s->vcbase = pcidev->resource[2].start;
+               s->mpubase = pcidev->resource[3].start;
+               s->gpbase = pcidev->resource[4].start;
+               s->irq = pcidev->irq;
+               if (check_region(s->iobase, IOBASE_EXTENT) ||
+                   check_region(s->sbbase, SBBASE_EXTENT) ||
+                   check_region(s->vcbase, VCBASE_EXTENT) ||
+                   check_region(s->mpubase, MPUBASE_EXTENT)) {
+                       printk(KERN_ERR "solo1: io ports in use\n");
+                       goto err_region;
+               }
+               request_region(s->iobase, IOBASE_EXTENT, "ESS Solo1");
+               request_region(s->sbbase, SBBASE_EXTENT, "ESS Solo1");
+               request_region(s->vcbase, VCBASE_EXTENT, "ESS Solo1");
+               request_region(s->mpubase, MPUBASE_EXTENT, "ESS Solo1");
+               if (request_irq(s->irq, solo1_interrupt, SA_SHIRQ, "ESS Solo1", s)) {
+                       printk(KERN_ERR "solo1: irq %u in use\n", s->irq);
+                       goto err_irq;
+               }
+               /* initialize DDMA base address */
+               /* use PCI config reg, and not vcbase, we need the bus view */
+               pci_read_config_word(pcidev, 0x18, &ddmabase);
+               pci_write_config_word(pcidev, 0x60, (ddmabase & (~0xf)) | 1);
+#ifdef DEBUGREC
+               printk(KERN_DEBUG "solo1: DMA: mask: 0x%02x cnt: 0x%04x addr: 0x%08x  stat: 0x%02x\n", 
+                      inb(s->vcbase+0xf), inw(s->vcbase+4), inl(s->vcbase), inb(s->vcbase+8));
+#endif
+               /* set DMA policy to DDMA, IRQ emulation off (CLKRUN disabled for now) */
+               pci_write_config_dword(pcidev, 0x50, 0);
+               /* disable legacy audio address decode */
+               pci_write_config_word(pcidev, 0x40, 0x907f);
+
+               printk(KERN_INFO "solo1: joystick port at %#lx\n", s->gpbase+1);
+
+               /* register devices */
+               if ((s->dev_audio = register_sound_dsp(&solo1_audio_fops, -1)) < 0)
+                       goto err_dev1;
+               if ((s->dev_mixer = register_sound_mixer(&solo1_mixer_fops, -1)) < 0)
+                       goto err_dev2;
+               if ((s->dev_midi = register_sound_midi(&solo1_midi_fops, -1)) < 0)
+                       goto err_dev3;
+               if ((s->dev_dmfm = register_sound_special(&solo1_dmfm_fops, 15 /* ?? */)) < 0)
+                       goto err_dev4;
+               /* initialize the chips */
+               outb(0xb0, s->iobase+7); /* enable A1, A2, MPU irq's */
+
+               /* initialize mixer regs */
+               write_mixer(s, 0x7f, 0); /* disable music digital recording */
+               write_mixer(s, 0x7d, 0x0c); /* enable mic preamp, MONO_OUT is 2nd DAC right channel */
+               write_mixer(s, 0x64, 0x45); /* volume control */
+               write_mixer(s, 0x48, 0x10); /* enable music DAC/ES6xx interface */
+               write_mixer(s, 0x50, 0);  /* disable spatializer */
+               write_mixer(s, 0x52, 0);
+               write_mixer(s, 0x14, 0);  /* DAC1 minimum volume */
+               write_mixer(s, 0x71, 0x20); /* enable new 0xA1 reg format */
+#ifdef DEBUGREC
+               printk(KERN_DEBUG "solo1: DMA: mask: 0x%02x cnt: 0x%04x addr: 0x%08x  stat: 0x%02x\n", 
+                      inb(s->vcbase+0xf), inw(s->vcbase+4), inl(s->vcbase), inb(s->vcbase+8));
+#endif
+               outb(0, s->vcbase+0xd); /* DMA master clear */
+#ifdef DEBUGREC
+               printk(KERN_DEBUG "solo1: DMA: mask: 0x%02x cnt: 0x%04x addr: 0x%08x  stat: 0x%02x\n", 
+                      inb(s->vcbase+0xf), inw(s->vcbase+4), inl(s->vcbase), inb(s->vcbase+8));
+#endif
+               outb(1, s->vcbase+0xf); /* mask channel */
+#ifdef DEBUGREC
+               printk(KERN_DEBUG "solo1: DMA: mask: 0x%02x cnt: 0x%04x addr: 0x%08x  stat: 0x%02x\n", 
+                      inb(s->vcbase+0xf), inw(s->vcbase+4), inl(s->vcbase), inb(s->vcbase+8));
+#endif
+               //outb(0, s->vcbase+0x8); /* enable controller (enable is low active!!) */
+
+               pci_set_master(pcidev);  /* enable bus mastering */
+               
+               fs = get_fs();
+               set_fs(KERNEL_DS);
+               val = SOUND_MASK_LINE;
+               mixer_ioctl(s, SOUND_MIXER_WRITE_RECSRC, (unsigned long)&val);
+               for (i = 0; i < sizeof(initvol)/sizeof(initvol[0]); i++) {
+                       val = initvol[i].vol;
+                       mixer_ioctl(s, initvol[i].mixch, (unsigned long)&val);
+               }
+               set_fs(fs);
+               /* queue it for later freeing */
+               s->next = devs;
+               devs = s;
+               index++;
+               continue;
+
+       err_dev4:
+               unregister_sound_dsp(s->dev_midi);
+       err_dev3:
+               unregister_sound_mixer(s->dev_mixer);
+       err_dev2:
+               unregister_sound_dsp(s->dev_audio);
+       err_dev1:
+               printk(KERN_ERR "solo1: cannot register misc device\n");
+               free_irq(s->irq, s);
+       err_irq:
+               release_region(s->iobase, IOBASE_EXTENT);
+               release_region(s->sbbase, SBBASE_EXTENT);
+               release_region(s->vcbase, VCBASE_EXTENT);
+               release_region(s->mpubase, MPUBASE_EXTENT);
+       err_region:
+               kfree_s(s, sizeof(struct solo1_state));
+       }
+       if (!devs)
+               return -ENODEV;
+       return 0;
+}
+
+/* --------------------------------------------------------------------- */
+
+MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu");
+MODULE_DESCRIPTION("ESS Solo1 Driver");
+
+static void __exit cleanup_solo1(void)
+{
+       struct solo1_state *s;
+
+       while ((s = devs)) {
+               devs = devs->next;
+               /* stop DMA controller */
+               outb(0, s->iobase+6);
+               outb(0, s->vcbase+0xd); /* DMA master clear */
+               outb(3, s->sbbase+6); /* reset sequencer and FIFO */
+               synchronize_irq();
+               free_irq(s->irq, s);
+               release_region(s->iobase, IOBASE_EXTENT);
+               release_region(s->sbbase, SBBASE_EXTENT);
+               release_region(s->vcbase, VCBASE_EXTENT);
+               release_region(s->mpubase, MPUBASE_EXTENT);
+               unregister_sound_dsp(s->dev_audio);
+               unregister_sound_mixer(s->dev_mixer);
+               unregister_sound_midi(s->dev_midi);
+               unregister_sound_special(s->dev_dmfm);
+               kfree_s(s, sizeof(struct solo1_state));
+       }
+       printk(KERN_INFO "solo1: unloading\n");
+}
+
+/* --------------------------------------------------------------------- */
+
+module_init(init_solo1);
+module_exit(cleanup_solo1);
+
index a89e5db1575158b9c573c2e5ffbcf82071837b3d..636eda6fbc820af3b4823b910dea5053498ff729 100644 (file)
@@ -30,11 +30,13 @@ if [ ! "$CONFIG_USB" = "n" ]; then
   dep_tristate 'USB audio parsing support' CONFIG_USB_AUDIO $CONFIG_USB
   dep_tristate 'USB Communications Device Class (ACM) support' CONFIG_USB_ACM $CONFIG_USB
   dep_tristate 'USB Printer support' CONFIG_USB_PRINTER $CONFIG_USB
+  dep_tristate 'USB CPiA Camera support' CONFIG_USB_CPIA $CONFIG_USB
   dep_tristate 'USB SCSI Support' CONFIG_USB_SCSI $CONFIG_USB
   if [ "$CONFIG_USB_SCSI" != "n" ]; then
          dep_tristate '  USB SCSI verbose debug' CONFIG_USB_SCSI_DEBUG $CONFIG_USB_SCSI
   fi
   dep_tristate 'EZUSB Firmware downloader' CONFIG_USB_EZUSB $CONFIG_USB
+  dep_tristate 'USS720 parport driver' CONFIG_USB_USS720 $CONFIG_USB $CONFIG_PARPORT
   if [ "$CONFIG_PROC_FS" != "n" ]; then
        bool 'Preliminary /proc/bus/usb support' CONFIG_USB_PROC
   fi
index 601e867a513e385d03701113d1de9c4e141927c9..fc2f642e7db728620eb3f718c0d81328782ab18a 100644 (file)
@@ -85,6 +85,15 @@ ifeq ($(CONFIG_USB_PRINTER),m)
   MIX_OBJS += printer.o  
 endif
 
+ifeq ($(CONFIG_USB_CPIA),y)
+  L_OBJS += cpia.o
+endif
+
+ifeq ($(CONFIG_USB_CPIA),m)
+  M_OBJS += cpia.o
+  MIX_OBJS += cpia.o  
+endif
+
 ifeq ($(CONFIG_USB_KBD),y)
   L_OBJS += keyboard.o keymap.o
 endif
@@ -119,6 +128,14 @@ ifeq ($(CONFIG_USB_SCSI),y)
   endif
 endif
 
+ifeq ($(CONFIG_USB_SCSI),m)
+  M_OBJS += usb-scsi.o
+  MIX_OBJS += usb_scsi.o
+  ifeq ($(CONFIG_USB_SCSI_DEBUG),y)
+    MIX_OBJS += usb_scsi_debug.o
+  endif
+endif
+
 ifeq ($(CONFIG_USB_EZUSB),y)
   L_OBJS += ezusb.o
 endif
@@ -128,6 +145,15 @@ ifeq ($(CONFIG_USB_EZUSB),m)
   MIX_OBJS += ezusb.o
 endif
 
+ifeq ($(CONFIG_USB_USS720),y)
+  L_OBJS += uss720.o
+endif
+
+ifeq ($(CONFIG_USB_USS720),m)
+  M_OBJS += uss720.o
+  MIX_OBJS += uss720.o
+endif
+
 include $(TOPDIR)/Rules.make
 
 keymap.o: keymap.c
@@ -147,6 +173,14 @@ usb-keyboard.o: keymap-mac.o keyboard.o
        $(LD) $(LD_RFLAG) -r -o $@  keymap-mac.o keyboard.o 
 endif
 
+ifeq ($(CONFIG_USB_SCSI_DEBUG),y)
+usb-scsi.o: usb_scsi.o usb_scsi_debug.o
+       $(LD) $(LD_RFLAG) -r -o $@  usb_scsi.o usb_scsi_debug.o 
+else
+usb-scsi.o: usb_scsi.o
+       $(LD) $(LD_RFLAG) -r -o $@  usb_scsi.o
+endif
+
 usb-uhci.o: uhci.o uhci-debug.o 
        $(LD) $(LD_RFLAG) -r -o $@  uhci.o uhci-debug.o 
 
index fc503f3cb7ecf5c257b82352833fe94e0f3538f8..6039a8b2102e33d0f856a115ec767321c0773c13 100644 (file)
@@ -11,24 +11,25 @@ static int usb_audio_probe(struct usb_device *dev);
 static void usb_audio_disconnect(struct usb_device *dev);
 static LIST_HEAD(usb_audio_list);
 
-struct usb_audio
-{
+struct usb_audio {
        struct usb_device *dev;
        struct list_head list;
 };
 
-static struct usb_driver usb_audio_driver =
-{
+static struct usb_driver usb_audio_driver = {
        "audio",
        usb_audio_probe,
        usb_audio_disconnect,
-       {NULL, NULL}
+       { NULL, NULL }
 };
 
 
 static int usb_audio_irq(int state, void *buffer, int len, void *dev_id)
 {
-       struct usb_audio *aud = (struct usb_audio*) dev_id;
+       struct usb_audio *aud = (struct usb_audio *)dev_id;
+
+       printk("irq on %p\n", aud);
+
        return 1;
 }
 
@@ -37,16 +38,12 @@ static int usb_audio_probe(struct usb_device *dev)
        struct usb_interface_descriptor *interface;
        struct usb_endpoint_descriptor *endpoint;
        struct usb_audio *aud;
-
        int i;
        int na=0;
        
        interface = &dev->config[0].altsetting[0].interface[0];
 
-       for(i=0;i<dev->config[0].bNumInterfaces;i++)
-       {
-               int x;
-               
+       for (i=0; i<dev->config[0].bNumInterfaces; i++) {
                endpoint = &interface->endpoint[i];
 
                if(interface->bInterfaceClass != 1) 
@@ -54,8 +51,7 @@ static int usb_audio_probe(struct usb_device *dev)
 
                printk(KERN_INFO "USB audio device detected.\n");
        
-               switch(interface->bInterfaceSubClass)
-               {
+               switch(interface->bInterfaceSubClass) {
                        case 0x01:
                                printk(KERN_INFO "audio: Control device.\n");
                                break;
@@ -69,12 +65,11 @@ static int usb_audio_probe(struct usb_device *dev)
                na++;
        }
        
-       if(na==0)
+       if (!na)
                return -1;
 
        aud = kmalloc(sizeof(struct usb_audio), GFP_KERNEL);
-       if(aud)
-       {
+       if (aud) {
                memset(aud, 0, sizeof(*aud));
                aud->dev = dev;
                dev->private = aud;
@@ -107,8 +102,8 @@ static int usb_audio_probe(struct usb_device *dev)
 static void usb_audio_disconnect(struct usb_device *dev)
 {
        struct usb_audio *aud = (struct usb_audio*) dev->private;
-       if(aud)
-       {
+
+       if (aud) {
                dev->private = NULL;
                list_del(&aud->list);
                kfree(aud);
@@ -146,3 +141,4 @@ void cleanup_module(void)
 }
 
 #endif
+
index 8b5e26fb6cc9c6610a675ee77ceacb7f8e2c57d7..64116d483d22715afc6c8731a62d78733ab2bc58 100644 (file)
 #include <linux/module.h>
 
 #include <asm/spinlock.h>
+#include <asm/uaccess.h>
 
 #include "usb.h"
 #include "hub.h"
 
 /* Wakes up khubd */
-static DECLARE_WAIT_QUEUE_HEAD(usb_hub_wait);
 static spinlock_t hub_event_lock = SPIN_LOCK_UNLOCKED;
 static spinlock_t hub_list_lock = SPIN_LOCK_UNLOCKED;
 
-/* List of hubs needing servicing */
-static struct list_head hub_event_list;
+static LIST_HEAD(hub_event_list);      /* List of hubs needing servicing */
+static LIST_HEAD(hub_list);            /* List containing all of the hubs (for cleanup) */
 
-/* List containing all of the hubs (for cleanup) */
-static struct list_head all_hubs_list;
+static DECLARE_WAIT_QUEUE_HEAD(khubd_wait);
+static int khubd_pid = 0;                      /* PID of khubd */
+static int khubd_running = 0;
 
-/* PID of khubd */
-static int khubd_pid = 0;
+static int usb_get_hub_descriptor(struct usb_device *dev, void *data, int size)
+{
+       devrequest dr;
+
+       dr.requesttype = USB_DIR_IN | USB_RT_HUB;
+       dr.request = USB_REQ_GET_DESCRIPTOR;
+       dr.value = (USB_DT_HUB << 8);
+       dr.index = 0;
+       dr.length = size;
+
+       return dev->bus->op->control_msg(dev, usb_rcvctrlpipe(dev,0), &dr,
+               data, size);
+}
+
+static int usb_clear_port_feature(struct usb_device *dev, int port, int feature)
+{
+       devrequest dr;
+
+       dr.requesttype = USB_RT_PORT;
+       dr.request = USB_REQ_CLEAR_FEATURE;
+       dr.value = feature;
+       dr.index = port;
+       dr.length = 0;
+
+       return dev->bus->op->control_msg(dev, usb_sndctrlpipe(dev,0), &dr,
+               NULL, 0);
+}
+
+static int usb_set_port_feature(struct usb_device *dev, int port, int feature)
+{
+       devrequest dr;
+
+       dr.requesttype = USB_RT_PORT;
+       dr.request = USB_REQ_SET_FEATURE;
+       dr.value = feature;
+       dr.index = port;
+       dr.length = 0;
+
+       return dev->bus->op->control_msg(dev, usb_sndctrlpipe(dev,0), &dr,
+               NULL, 0);
+}
+
+static int usb_get_hub_status(struct usb_device *dev, void *data)
+{
+       devrequest dr;
+
+       dr.requesttype = USB_DIR_IN | USB_RT_HUB;
+       dr.request = USB_REQ_GET_STATUS;
+       dr.value = 0;
+       dr.index = 0;
+       dr.length = 4;
+
+       return dev->bus->op->control_msg(dev, usb_rcvctrlpipe(dev,0), &dr,
+               data, 4);
+}
+
+static int usb_get_port_status(struct usb_device *dev, int port, void *data)
+{
+       devrequest dr;
+
+       dr.requesttype = USB_DIR_IN | USB_RT_PORT;
+       dr.request = USB_REQ_GET_STATUS;
+       dr.value = 0;
+       dr.index = port;
+       dr.length = 4;
+
+       return dev->bus->op->control_msg(dev, usb_rcvctrlpipe(dev,0), &dr,
+               data, 4);
+}
 
 /*
  * A irq handler returns non-zero to indicate to
@@ -42,13 +110,13 @@ static int hub_irq(int status, void *__buffer, int len, void *dev_id)
        struct usb_hub *hub = dev_id;
        unsigned long flags;
 
-       if (waitqueue_active(&usb_hub_wait)) {
+       if (waitqueue_active(&khubd_wait)) {
                /* Add the hub to the event queue */
                spin_lock_irqsave(&hub_event_lock, flags);
                if (hub->event_list.next == &hub->event_list) {
                        list_add(&hub->event_list, &hub_event_list);
                        /* Wake up khubd */
-                       wake_up(&usb_hub_wait);
+                       wake_up(&khubd_wait);
                }
                spin_unlock_irqrestore(&hub_event_lock, flags);
        }
@@ -68,83 +136,63 @@ static void usb_hub_configure(struct usb_hub *hub)
                return;
 
        hub->nports = dev->maxchild = hubdescriptor[2];
-       printk("hub: %d-port%s detected\n", hub->nports,
+       printk(KERN_INFO "hub: %d-port%s detected\n", hub->nports,
                (hub->nports == 1) ? "" : "s");
 
        charac = (hubdescriptor[4] << 8) + hubdescriptor[3];
        switch (charac & HUB_CHAR_LPSM) {
                case 0x00:
-                       printk("hub: ganged power switching\n");
+                       printk(KERN_INFO "hub: ganged power switching\n");
                        break;
                case 0x01:
-                       printk("hub: individual port power switching\n");
+                       printk(KERN_INFO "hub: individual port power switching\n");
                        break;
                case 0x02:
                case 0x03:
-                       printk("hub: unknown reserved power switching mode\n");
+                       printk(KERN_INFO "hub: unknown reserved power switching mode\n");
                        break;
        }
 
        if (charac & HUB_CHAR_COMPOUND)
-               printk("hub: part of a compound device\n");
+               printk(KERN_INFO "hub: part of a compound device\n");
        else
-               printk("hub: standalone hub\n");
+               printk(KERN_INFO "hub: standalone hub\n");
 
        switch (charac & HUB_CHAR_OCPM) {
                case 0x00:
-                       printk("hub: global over current protection\n");
+                       printk(KERN_INFO "hub: global over current protection\n");
                        break;
                case 0x08:
-                       printk("hub: individual port over current protection\n");
+                       printk(KERN_INFO "hub: individual port over current protection\n");
                        break;
                case 0x10:
                case 0x18:
-                       printk("hub: no over current protection\n");
+                       printk(KERN_INFO "hub: no over current protection\n");
                         break;
        }
 
-       printk("hub: power on to power good time: %dms\n",
+       printk(KERN_INFO "hub: power on to power good time: %dms\n",
                hubdescriptor[5] * 2);
 
-       printk("hub: hub controller current requirement: %dmA\n",
+       printk(KERN_INFO "hub: hub controller current requirement: %dmA\n",
                hubdescriptor[6]);
 
        for (i = 0; i < dev->maxchild; i++)
-               printk("hub:  port %d is%s removable\n", i + 1,
+               printk(KERN_INFO "hub:  port %d is%s removable\n", i + 1,
                        hubdescriptor[7 + ((i + 1)/8)] & (1 << ((i + 1) % 8))
                        ? " not" : "");
 
        if (usb_get_hub_status(dev, buf))
                return;
 
-       printk("hub: local power source is %s\n",
+       printk(KERN_INFO "hub: local power source is %s\n",
                (buf[0] & 1) ? "lost (inactive)" : "good");
 
-       printk("hub: %sover current condition exists\n",
+       printk(KERN_INFO "hub: %sover current condition exists\n",
                (buf[0] & 2) ? "" : "no ");
 
-#if 0
-       for (i = 0; i < hub->nports; i++) {
-               int portstat, portchange;
-               unsigned char portstatus[4];
-
-               if (usb_get_port_status(dev, i + 1, portstatus))
-                       return;
-               portstat = (portstatus[1] << 8) + portstatus[0];
-               portchange = (portstatus[3] << 8) + portstatus[2];
-
-               printk("hub: port %d status\n", i + 1);
-               printk("hub:  %sdevice present\n", (portstat & 1) ? "" : "no ");
-               printk("hub:  %s\n", (portstat & 2) ? "enabled" : "disabled");
-               printk("hub:  %ssuspended\n", (portstat & 4) ? "" : "not ");
-               printk("hub:  %sover current\n", (portstat & 8) ? "" : "not ");
-               printk("hub:  has %spower\n", (portstat & 0x100) ? "" : "no ");
-               printk("hub:  %s speed\n", (portstat & 0x200) ? "low" : "full");
-       }
-#endif
-
        /* Enable power to the ports */
-       printk("enabling power on all ports\n");
+       printk(KERN_INFO "hub: enabling power on all ports\n");
        for (i = 0; i < hub->nports; i++)
                usb_set_port_feature(dev, i + 1, USB_PORT_FEAT_POWER);
 }
@@ -180,7 +228,7 @@ static int hub_probe(struct usb_device *dev)
        endpoint = &interface->endpoint[0];
 
        /* Output endpoint? Curiousier and curiousier.. */
-       if (!(endpoint->bEndpointAddress & 0x80))
+       if (!(endpoint->bEndpointAddress & USB_DIR_IN))
                return -1;
 
        /* If it's not an interrupt endpoint, we'd better punt! */
@@ -188,10 +236,10 @@ static int hub_probe(struct usb_device *dev)
                return -1;
 
        /* We found a hub */
-       printk("USB hub found\n");
+       printk(KERN_INFO "USB hub found\n");
 
        if ((hub = kmalloc(sizeof(*hub), GFP_KERNEL)) == NULL) {
-               printk("couldn't kmalloc hub struct\n");
+               printk(KERN_ERR "couldn't kmalloc hub struct\n");
                return -1;
        }
 
@@ -205,15 +253,16 @@ static int hub_probe(struct usb_device *dev)
        /* Record the new hub's existence */
        spin_lock_irqsave(&hub_list_lock, flags);
        INIT_LIST_HEAD(&hub->hub_list);
-       list_add(&hub->hub_list, &all_hubs_list);
+       list_add(&hub->hub_list, &hub_list);
        spin_unlock_irqrestore(&hub_list_lock, flags);
 
        usb_hub_configure(hub);
 
-       hub->irq_handle = usb_request_irq(dev, usb_rcvctrlpipe(dev, endpoint->bEndpointAddress), hub_irq, endpoint->bInterval, hub);
+       hub->irq_handle = usb_request_irq(dev, usb_rcvctrlpipe(dev,
+               endpoint->bEndpointAddress), hub_irq, endpoint->bInterval, hub);
 
        /* Wake up khubd */
-       wake_up(&usb_hub_wait);
+       wake_up(&khubd_wait);
 
        return 0;
 }
@@ -246,40 +295,51 @@ static void usb_hub_port_connect_change(struct usb_device *hub, int port)
        unsigned char buf[4];
        unsigned short portstatus, portchange;
 
+       /* Disconnect anything that may have been there */
        usb_disconnect(&hub->children[port]);
 
+       /* Reset the port */
        usb_set_port_feature(hub, port + 1, USB_PORT_FEAT_RESET);
 
        wait_ms(50);    /* FIXME: This is from the *BSD stack, thanks! :) */
 
+       /* Check status */
        if (usb_get_port_status(hub, port + 1, buf)) {
-               printk("get_port_status failed\n");
+               printk(KERN_ERR "get_port_status failed\n");
                return;
        }
 
        portstatus = le16_to_cpup((unsigned short *)buf + 0);
        portchange = le16_to_cpup((unsigned short *)buf + 1);
 
+       /* If it's not in CONNECT and ENABLE state, we're done */
        if ((!(portstatus & USB_PORT_STAT_CONNECTION)) &&
-               (!(portstatus & USB_PORT_STAT_ENABLE))) {
+           (!(portstatus & USB_PORT_STAT_ENABLE)))
                /* We're done now, we already disconnected the device */
-               /* printk("not connected/enabled\n"); */
                return;
-       }
 
+       /* Allocate a new device struct for it */
        usb = hub->bus->op->allocate(hub);
        if (!usb) {
-               printk("couldn't allocate usb_device\n");
+               printk(KERN_ERR "couldn't allocate usb_device\n");
                return;
        }
 
-       usb_connect(usb);
-
        usb->slow = (portstatus & USB_PORT_STAT_LOW_SPEED) ? 1 : 0;
 
        hub->children[port] = usb;
 
-       usb_new_device(usb);
+       /* Find a new device ID for it */
+       usb_connect(usb);
+
+       /* Run it through the hoops (find a driver, etc) */
+       if (usb_new_device(usb)) {
+               /* Woops, disable the port */
+               printk(KERN_DEBUG "hub: disabling malfunctioning port %d\n",
+                       port + 1);
+               usb_clear_port_feature(hub, port + 1, USB_PORT_FEAT_ENABLE);
+               usb_clear_port_feature(hub, port + 1, USB_PORT_FEAT_POWER);
+       }
 }
 
 static void usb_hub_events(void)
@@ -306,7 +366,7 @@ static void usb_hub_events(void)
 
                for (i = 0; i < hub->nports; i++) {
                        if (usb_get_port_status(dev, i + 1, buf)) {
-                               printk("get_port_status failed\n");
+                               printk(KERN_ERR "get_port_status failed\n");
                                continue;
                        }
 
@@ -314,7 +374,8 @@ static void usb_hub_events(void)
                        portchange = le16_to_cpup((unsigned short *)buf + 1);
 
                        if (portchange & USB_PORT_STAT_C_CONNECTION) {
-                               printk("hub: port %d connection change\n", i + 1);
+                               printk(KERN_INFO "hub: port %d connection change\n",
+                                       i + 1);
 
                                usb_clear_port_feature(dev, i + 1,
                                        USB_PORT_FEAT_C_CONNECTION);
@@ -323,46 +384,29 @@ static void usb_hub_events(void)
                        }
 
                        if (portchange & USB_PORT_STAT_C_ENABLE) {
-                               printk("hub: port %d enable change\n", i + 1);
+                               printk(KERN_INFO "hub: port %d enable change\n",
+                                       i + 1);
                                usb_clear_port_feature(dev, i + 1,
                                        USB_PORT_FEAT_C_ENABLE);
                        }
 
                        if (portchange & USB_PORT_STAT_C_SUSPEND)
-                               printk("hub: port %d suspend change\n", i + 1);
+                               printk(KERN_INFO "hub: port %d suspend change\n",
+                                       i + 1);
 
                        if (portchange & USB_PORT_STAT_C_OVERCURRENT)
-                               printk("hub: port %d over-current change\n", i + 1);
+                               printk(KERN_INFO "hub: port %d over-current change\n",
+                                       i + 1);
 
                        if (portchange & USB_PORT_STAT_C_RESET) {
-                               printk("hub: port %d reset change\n", i + 1);
+                               printk(KERN_INFO "hub: port %d reset change\n",
+                                       i + 1);
                                usb_clear_port_feature(dev, i + 1,
                                        USB_PORT_FEAT_C_RESET);
                        }
 
-#if 0
-                       if (!portchange)
-                               continue;
-
-                       if (usb_get_port_status(dev, i + 1, buf))
-                               return;
-
-                       portstatus = (buf[1] << 8) + buf[0];
-                       portchange = (buf[3] << 8) + buf[2];
-
-                       printk("hub: port %d status\n", i + 1);
-                       printk("hub:  %sdevice present\n", (portstatus & 1) ? "" : "no ");
-                       printk("hub:  %s\n", (portstatus & 2) ? "enabled" : "disabled");
-                       printk("hub:  %ssuspended\n", (portstatus & 4) ? "" : "not ");
-                       printk("hub:  %sover current\n", (portstatus & 8) ? "" : "not ");
-                       printk("hub:  has %spower\n", (portstatus & 0x100) ? "" : "no ");
-                       printk("hub:  %s speed\n", (portstatus & 0x200) ? "low" : "full");
-#endif
                }
                tmp = next;
-#if 0
-               wait_ms(1000);
-#endif
         }
 
        spin_unlock_irqrestore(&hub_event_lock, flags);
@@ -370,9 +414,11 @@ static void usb_hub_events(void)
 
 static int usb_hub_thread(void *__hub)
 {
+/*
        MOD_INC_USE_COUNT;
+*/
        
-       printk(KERN_INFO "USB hub driver registered\n");
+       khubd_running = 1;
 
        lock_kernel();
 
@@ -389,13 +435,16 @@ static int usb_hub_thread(void *__hub)
 
        /* Send me a signal to get me die (for debugging) */
        do {
-               interruptible_sleep_on(&usb_hub_wait);
                usb_hub_events();
+               interruptible_sleep_on(&khubd_wait);
        } while (!signal_pending(current));
 
+/*
        MOD_DEC_USE_COUNT;
+*/
 
        printk("usb_hub_thread exiting\n");
+       khubd_running = 0;
 
        return 0;
 }
@@ -414,24 +463,44 @@ int usb_hub_init(void)
 {
        int pid;
 
-       INIT_LIST_HEAD(&hub_event_list);
-       INIT_LIST_HEAD(&all_hubs_list);
-
        usb_register(&hub_driver);
-       pid = kernel_thread(usb_hub_thread, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
+       printk(KERN_INFO "USB hub driver registered\n");
+
+       pid = kernel_thread(usb_hub_thread, NULL,
+               CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
        if (pid >= 0) {
                khubd_pid = pid;
+
                return 0;
        }
 
        /* Fall through if kernel_thread failed */
        usb_deregister(&hub_driver);
 
-       return 0;
+       return 1;
 }
 
 void usb_hub_cleanup(void)
 {
+       struct list_head *next, *tmp, *head = &hub_list;
+       struct usb_hub *hub;
+       unsigned long flags, flags2;
+       int ret;
+
+       /* Kill the thread */
+       ret = kill_proc(khubd_pid, SIGTERM, 1);
+       if (!ret) {
+               int count = 10;
+
+               while (khubd_running && --count) {
+                       current->state = TASK_INTERRUPTIBLE;
+                       schedule_timeout(1);
+               }
+
+               if (!count)
+                       printk(KERN_ERR "hub: giving up on killing khubd\n");
+       }
+
        /*
         * Hub resources are freed for us by usb_deregister.  It
         * usb_driver_purge on every device which in turn calls that
@@ -443,11 +512,14 @@ void usb_hub_cleanup(void)
 } /* usb_hub_cleanup() */
 
 #ifdef MODULE
-int init_module(void){
+int init_module(void)
+{
        return usb_hub_init();
 }
 
-void cleanup_module(void){
+void cleanup_module(void)
+{
        usb_hub_cleanup();
 }
 #endif
+
index 8a1d3032c533526cd9c44850e910a39d4bc4803e..b081842be3e9eb914aea0f2006b7f11aa94026ac 100644 (file)
@@ -115,12 +115,12 @@ void show_status(struct uhci *uhci)
 
 #define uhci_link_to_qh(x) ((struct uhci_qh *) uhci_link_to_td(x))
 
-struct uhci_td * uhci_link_to_td(unsigned int link)
+struct uhci_td *uhci_link_to_td(unsigned int link)
 {
-       if (link & 1)
+       if (link & UHCI_PTR_TERM)
                return NULL;
 
-       return bus_to_virt(link & ~15);
+       return bus_to_virt(link & ~UHCI_PTR_BITS);
 }
 
 void show_queue(struct uhci_qh *qh)
@@ -128,18 +128,24 @@ void show_queue(struct uhci_qh *qh)
        struct uhci_td *td;
        int i = 0;
 
-#if 0
-       printk("    link = %p, element = %p\n", qh->link, qh->element);
-#endif
-       if(!(qh->element & ~0xF)) {
-               printk("    td 0 = NULL\n");
+       if (qh->element & UHCI_PTR_QH)
+               printk("      Element points to QH?\n");
+
+       if (qh->element & UHCI_PTR_DEPTH)
+               printk("      Depth traverse\n");
+
+       if (qh->element & UHCI_PTR_TERM)
+               printk("      Terminate\n");
+
+       if (!(qh->element & ~UHCI_PTR_BITS)) {
+               printk("      td 0 = NULL\n");
                return;
        }
 
        for(td = uhci_link_to_td(qh->element); td; 
            td = uhci_link_to_td(td->link)) {
-               printk("    td %d = %p\n", i++, td);
-               printk("    ");
+               printk("      td %d = %p\n", i++, td);
+               printk("      ");
                show_td(td);
        }
 }
@@ -147,39 +153,39 @@ void show_queue(struct uhci_qh *qh)
 int is_skeleton_qh(struct uhci *uhci, struct uhci_qh *qh)
 {
        int j;
-       struct uhci_device * root_hub=usb_to_uhci(uhci->bus->root_hub);
-       for (j = 0; j < UHCI_MAXQH; j++)
-               if (qh == root_hub->qh + j)
+
+       for (j = 0; j < UHCI_NUM_SKELQH; j++)
+               if (qh == uhci->skelqh + j)
                        return 1;
 
        return 0;
 }
 
-static const char *qh_names[] = {"isochronous", "interrupt2", "interrupt4",
-                                "interrupt8", "interrupt16", "interrupt32",
-                                "interrupt64", "interrupt128", "interrupt256",
-                                "control", "bulk0", "bulk1", "bulk2", "bulk3",
-                                "unused", "unused"};
+static const char *qh_names[] = {"interrupt2", "interrupt4", "interrupt8",
+                                "interrupt16", "interrupt32", "interrupt64",
+                                "interrupt128", "interrupt256", "control",
+                                "bulk"};
 
 void show_queues(struct uhci *uhci)
 {
        int i;
        struct uhci_qh *qh;
-       struct uhci_device * root_hub=usb_to_uhci(uhci->bus->root_hub);
 
-       for (i = 0; i < UHCI_MAXQH; ++i) {
-               printk("  %s:\n", qh_names[i]);
-#if 0
-               printk("  qh #%d, %p\n", i, virt_to_bus(root_hub->qh + i));
-               show_queue(uhci->root_hub->qh + i);
-#endif
+       for (i = 0; i < UHCI_NUM_SKELQH; ++i) {
+               printk("  %s: [%p] (%08X) (%08X)\n", qh_names[i],
+                       &uhci->skelqh[i],
+                       uhci->skelqh[i].link, uhci->skelqh[i].element);
 
-               qh = uhci_link_to_qh(root_hub->qh[i].link);
+               qh = uhci_link_to_qh(uhci->skelqh[i].link);
                for (; qh; qh = uhci_link_to_qh(qh->link)) {
                        if (is_skeleton_qh(uhci, qh))
                                break;
 
+                       printk("    [%p] (%08X) (%08x)\n",
+                               qh, qh->link, qh->element);
+
                        show_queue(qh);
                }
        }
 }
+
index e4f493b4784f6f7fd93af5e86dfc9a6d1cf2dca1..d42a6b3471a275008c716b2feccbf32290d28ee9 100644 (file)
@@ -2,6 +2,7 @@
  * Universal Host Controller Interface driver for USB.
  *
  * (C) Copyright 1999 Linus Torvalds
+ * (C) Copyright 1999 Johannes Erdfelt
  *
  * Intel documents this fairly well, and as far as I know there
  * are no royalties or anything like that, but even so there are
@@ -54,32 +55,40 @@ static int uhci_debug = 1;
 
 static DECLARE_WAIT_QUEUE_HEAD(uhci_configure);
 
+static kmem_cache_t *uhci_td_cachep;
+static kmem_cache_t *uhci_qh_cachep;
+
+static LIST_HEAD(uhci_list);
+
+#define UHCI_DEBUG
+
 /*
  * Map status to standard result codes
  */
 static int uhci_map_status(int status, int dir_out)
 {
-    if (!status)
-           return USB_ST_NOERROR;
-    if (status & 0x02)                         /* Bitstuff error*/
-           return USB_ST_BITSTUFF;
-    if (status & 0x04) {                       /* CRC/Timeout */
-       if (dir_out)
-           return USB_ST_NORESPONSE;
-       else
-           return USB_ST_CRC;
-    }
-    if (status & 0x08)                         /* NAK */
-           return USB_ST_TIMEOUT;
-    if (status & 0x10)                         /* Babble */
-           return USB_ST_STALL;
-    if (status & 0x20)                         /* Buffer error */
-           return USB_ST_BUFFERUNDERRUN;
-    if (status & 0x40)                         /* Stalled */
-           return USB_ST_STALL;
-    if (status & 0x80)                         /* Active */
-           return USB_ST_NOERROR;
-    return USB_ST_INTERNALERROR;
+       if (!status)
+               return USB_ST_NOERROR;
+       if (status & 0x02)                              /* Bitstuff error*/
+               return USB_ST_BITSTUFF;
+       if (status & 0x04)      {                       /* CRC/Timeout */
+               if (dir_out)
+                       return USB_ST_NORESPONSE;
+               else
+                       return USB_ST_CRC;
+       }
+       if (status & 0x08)                              /* NAK */
+               return USB_ST_TIMEOUT;
+       if (status & 0x10)                              /* Babble */
+               return USB_ST_STALL;
+       if (status & 0x20)                              /* Buffer error */
+               return USB_ST_BUFFERUNDERRUN;
+       if (status & 0x40)                              /* Stalled */
+               return USB_ST_STALL;
+       if (status & 0x80)                              /* Active */
+               return USB_ST_NOERROR;
+
+       return USB_ST_INTERNALERROR;
 }
 /*
  * Return the result of a TD..
@@ -87,11 +96,16 @@ static int uhci_map_status(int status, int dir_out)
 static int uhci_td_result(struct uhci_device *dev, struct uhci_td *td, unsigned long *rval)
 {
        unsigned int status;
-       struct uhci_td *tmp= td->first;
+       struct uhci_td *tmp;
+
+       if (!td->qh)
+               tmp = td;
+       else
+               tmp = uhci_ptr_to_virt(td->qh->element);
 
-       if(rval)
+       if (rval)
                *rval = 0;
-               
+
        /* locate the first failing td, if any */
 
        do {
@@ -99,51 +113,54 @@ static int uhci_td_result(struct uhci_device *dev, struct uhci_td *td, unsigned
                if (status) {
                        /* must reset the toggle on first error */
                        if (uhci_debug) {
-                           printk("Set toggle from %x rval %ld\n", (unsigned int)tmp, rval ? *rval : 0);
+                               printk(KERN_DEBUG "Set toggle from %x rval %ld\n",
+                                       (unsigned int)tmp, rval ? *rval : 0);
                        }
-                       usb_settoggle(dev->usb, usb_pipeendpoint(tmp->info), usb_pipeout(tmp->info), (tmp->info >> 19) & 1);
+                       usb_settoggle(dev->usb, usb_pipeendpoint(tmp->info),
+                               usb_pipeout(tmp->info), (tmp->info >> 19) & 1);
                        break;
                } else {
-                   if(rval)
+                   if (rval)
                        *rval += (tmp->status & 0x3ff) + 1;
                }
-               if ((tmp->link & 1) || (tmp->link & 2))
+               if ((tmp->link & UHCI_PTR_TERM) ||
+                   (tmp->link & UHCI_PTR_QH))
                        break;
-               tmp = bus_to_virt(tmp->link & ~0xF);
+               tmp = uhci_ptr_to_virt(tmp->link);
        } while (1);
 
        if (!status)
                return USB_ST_NOERROR;
 
        /* Some debugging code */
-       if (uhci_debug /* && (!usb_pipeendpoint(tmp->info) || !(status & 0x08))*/ ) {
-               int i = 10;
-
-               tmp = td->first;
-               printk("uhci_td_result() failed with status %x\n", status);
-               //show_status(dev->uhci);
+       if (uhci_debug) {
+               int count = 10;
+
+               if (!td->qh)
+                       tmp = td;
+               else
+                       tmp = uhci_ptr_to_virt(td->qh->element);
+               printk(KERN_DEBUG "uhci_td_result() failed with status %x\n",
+                       status);
                do {
                        show_td(tmp);
-                       if ((tmp->link & 1) || (tmp->link & 2))
+                       if ((tmp->link & UHCI_PTR_TERM) ||
+                           (tmp->link & UHCI_PTR_QH))
                                break;
-                       tmp = bus_to_virt(tmp->link & ~0xF);
-                       if (!--i)
-                               break;
-               } while (1);
+                       tmp = uhci_ptr_to_virt(tmp->link);
+               } while (--count);
        }
 
        if (status & 0x40) {
-           /* endpoint has stalled - mark it halted */
-
-           usb_endpoint_halt(dev->usb, usb_pipeendpoint(tmp->info));
-           return USB_ST_STALL;
-
+               /* endpoint has stalled - mark it halted */
+               usb_endpoint_halt(dev->usb, usb_pipeendpoint(tmp->info));
+               return USB_ST_STALL;
        }
 
        if (status == 0x80) {
-           /* still active */
-           if (!rval)
-               return USB_ST_DATAUNDERRUN;
+               /* still active */
+               if (!rval)
+                       return USB_ST_DATAUNDERRUN;
        }
        return uhci_map_status(status, usb_pipeout(tmp->info));         
 }
@@ -162,7 +179,7 @@ static int uhci_td_result(struct uhci_device *dev, struct uhci_td *td, unsigned
 static void uhci_insert_tds_in_qh(struct uhci_qh *qh, struct uhci_td *first, struct uhci_td *last)
 {
        unsigned int link = qh->element;
-       unsigned int new = 4 | virt_to_bus(first);
+       unsigned int new = virt_to_bus(first) | UHCI_PTR_DEPTH;
 
        for (;;) {
                unsigned char success;
@@ -174,9 +191,9 @@ static void uhci_insert_tds_in_qh(struct uhci_qh *qh, struct uhci_td *first, str
                        :"m" (qh->element), "1" (link), "r" (new)
                        :"memory");
                if (success) {
-                       /* Was there a successor entry? Fix it's backpointer.. */
-                       if ((link & 1) == 0) {
-                               struct uhci_td *next = bus_to_virt(link & ~15);
+                       /* Was there a successor entry? Fix it's backpointer */
+                       if ((link & UHCI_PTR_TERM) == 0) {
+                               struct uhci_td *next = uhci_ptr_to_virt(link);
                                next->backptr = &last->link;
                        }
                        break;
@@ -192,23 +209,22 @@ static inline void uhci_insert_td_in_qh(struct uhci_qh *qh, struct uhci_td *td)
 static void uhci_insert_qh(struct uhci_qh *qh, struct uhci_qh *newqh)
 {
        newqh->link = qh->link;
-       qh->link = virt_to_bus(newqh) | 2;
+       qh->link = virt_to_bus(newqh) | UHCI_PTR_QH;
 }
 
 static void uhci_remove_qh(struct uhci_qh *qh, struct uhci_qh *remqh)
 {
-       unsigned int remphys = virt_to_bus(remqh);
        struct uhci_qh *lqh = qh;
 
-       while ((lqh->link & ~0xF) != remphys) {
-               if (lqh->link & 1)
+       while (uhci_ptr_to_virt(lqh->link) != remqh) {
+               if (lqh->link & UHCI_PTR_TERM)
                        break;
 
-               lqh = bus_to_virt(lqh->link & ~0xF);
+               lqh = uhci_ptr_to_virt(lqh->link);
        }
 
-       if (lqh->link & 1) {
-               printk("couldn't find qh in chain!\n");
+       if (lqh->link & UHCI_PTR_TERM) {
+               printk(KERN_DEBUG "couldn't find qh in chain!\n");
                return;
        }
 
@@ -243,8 +259,8 @@ static void uhci_remove_td(struct uhci_td *td)
         * so we can always just look at that and fix up the backpointer
         * of any next element..
         */
-       if (!(link & 1)) {
-               struct uhci_td *next = bus_to_virt(link & ~15);
+       if (!(link & UHCI_PTR_TERM)) {
+               struct uhci_td *next = uhci_ptr_to_virt(link);
                next->backptr = backptr;
        }
 
@@ -261,60 +277,67 @@ static void uhci_remove_td(struct uhci_td *td)
                :"memory");
 }
 
-static struct uhci_qh *uhci_qh_allocate(struct uhci_device *dev)
+static struct uhci_td *uhci_td_alloc(struct uhci_device *dev)
 {
-       struct uhci_qh *qh;
-       int inuse;
+       struct uhci_td *td;
 
-       qh = dev->qh;
-       for (; (inuse = test_and_set_bit(0, &qh->inuse)) != 0 && qh < &dev->qh[UHCI_MAXQH]; qh++)
-               ;
+       td = kmem_cache_alloc(uhci_td_cachep, SLAB_KERNEL);
+       if (!td)
+               return NULL;
 
-       if (!inuse)
-               return(qh);
+#ifdef UHCI_DEBUG
+       if ((__u32)td & UHCI_PTR_BITS)
+               printk("qh not 16 byte aligned!\n");
+#endif
 
-       printk("ran out of qh's for dev %p\n", dev);
-       return(NULL);
-}
+       td->link = UHCI_PTR_TERM;
+       td->buffer = 0;
 
-static void uhci_qh_deallocate(struct uhci_qh *qh)
-{
-//     if (qh->element != 1)
-//             printk("qh %p leaving dangling entries? (%X)\n", qh, qh->element);
+       td->backptr = NULL;
+       td->qh = NULL;
+       td->dev_id = NULL;
+       td->dev = dev;
+       td->flags = 0;
+       INIT_LIST_HEAD(&td->irq_list);
+       atomic_set(&td->refcnt, 1);
 
-       qh->element = 1;
-       qh->link = 1;
+       return td;
+}
 
-       clear_bit(0, &qh->inuse);
+static void uhci_td_free(struct uhci_td *td)
+{
+       if (atomic_dec_and_test(&td->refcnt))
+               kmem_cache_free(uhci_td_cachep, td);
 }
 
-static struct uhci_td *uhci_td_allocate(struct uhci_device *dev)
+static struct uhci_qh *uhci_qh_alloc(struct uhci_device *dev)
 {
-       struct uhci_td *td;
-       int inuse;
+       struct uhci_qh *qh;
 
-       td = dev->td;
-       for (; (inuse = test_and_set_bit(0, &td->inuse)) != 0 && td < &dev->td[UHCI_MAXTD]; td++)
-               ;
+       qh = kmem_cache_alloc(uhci_qh_cachep, SLAB_KERNEL);
+       if (!qh)
+               return NULL;
 
-       if (!inuse) {
-               td->inuse = 1;
-                               td->dev=uhci_to_usb(dev);
-               return(td);
-       }
+#ifdef UHCI_DEBUG
+       if ((__u32)qh & UHCI_PTR_BITS)
+               printk("qh not 16 byte aligned!\n");
+#endif
+
+       qh->element = UHCI_PTR_TERM;
+       qh->link = UHCI_PTR_TERM;
 
-       printk("ran out of td's for dev %p\n", dev);
-       return(NULL);
+       qh->dev = dev;
+       qh->skel = NULL;
+       init_waitqueue_head(&qh->wakeup);
+       atomic_set(&qh->refcnt, 1);
+
+       return qh;
 }
 
-/*
- * This MUST only be called when it has been removed from a QH already (or
- * the QH has been removed from the skeleton
- */
-static void uhci_td_deallocate(struct uhci_td *td)
+static void uhci_qh_free(struct uhci_qh *qh)
 {
-       td->link = 1;
-       clear_bit(0, &td->inuse);
+       if (atomic_dec_and_test(&qh->refcnt))
+               kmem_cache_free(uhci_qh_cachep, qh);
 }
 
 /*
@@ -343,35 +366,41 @@ static void uhci_remove_irq_list(struct uhci_td *td)
        spin_unlock_irqrestore(&irqlist_lock, flags);
 }
 
-
 /*
  * This function removes and disallcoates all structures set up for an transfer.
  * It takes the qh out of the skeleton, removes the tq and the td's.
  * It only removes the associated interrupt handler if removeirq ist set.
  * The *td argument is any td in the list of td's.
  */
-static void uhci_remove_transfer(struct uhci_td *td, char removeirq) {
-       int maxcount = 100;
-       struct uhci_td *curtd = td->first;
+static void uhci_remove_transfer(struct uhci_td *td, char removeirq)
+{
+       int maxcount = 1000;
+       struct uhci_td *curtd;
        unsigned int nextlink;
 
-/* Remove it from the skeleton */
+       if (!td->qh)
+               curtd = td;
+       else
+               curtd = uhci_ptr_to_virt(td->qh->element);
+
+       /* Remove it from the skeleton */
        uhci_remove_qh(td->qh->skel, td->qh);
-       uhci_qh_deallocate(td->qh);  
+       uhci_qh_free(td->qh);
        do {
                nextlink = curtd->link;
-               /*IOC? => remove handler*/
-               if (removeirq && (td->status & (1 << 24))) {
+
+               /* IOC? => remove handler */
+               if (removeirq && (td->status & TD_CTRL_IOC))
                        uhci_remove_irq_list(td);
-               }
+
                uhci_remove_td(curtd);
-               uhci_td_deallocate(curtd);
-               if (nextlink & 1)       /* Tail? */
-               break;
+               uhci_td_free(curtd);
+               if (nextlink & UHCI_PTR_TERM)   /* Tail? */
+                       break;
 
-               curtd = bus_to_virt(nextlink & ~0xF);
+               curtd = bus_to_virt(nextlink & ~UHCI_PTR_BITS);
                if (!--maxcount) {
-                       printk("runaway td's!?\n");
+                       printk(KERN_ERR "runaway td's!?\n");
                        break;
                }
        } while (1);
@@ -383,99 +412,48 @@ static void uhci_remove_transfer(struct uhci_td *td, char removeirq) {
  * Returns: a "handle pointer" that release_irq can use to stop this
  * interrupt.  (It's really a pointer to the TD).
  */
-static voiduhci_request_irq(struct usb_device *usb_dev, unsigned int pipe, usb_device_irq handler, int period, void *dev_id)
+static void *uhci_request_irq(struct usb_device *usb_dev, unsigned int pipe, usb_device_irq handler, int period, void *dev_id)
 {
        struct uhci_device *dev = usb_to_uhci(usb_dev);
-       struct uhci_device *root_hub=usb_to_uhci(dev->uhci->bus->root_hub);
-       struct uhci_td *td = uhci_td_allocate(dev);
-       struct uhci_qh *interrupt_qh = uhci_qh_allocate(dev);
-
+       struct uhci_td *td = uhci_td_alloc(dev);
+       struct uhci_qh *qh = uhci_qh_alloc(dev);
        unsigned int destination, status;
 
-       /* Destination: pipe destination with INPUT */
-       destination = (pipe & PIPE_DEVEP_MASK) | usb_packetid (pipe);
+       if (!td || !qh)
+               return NULL;
 
-       /* Status:    slow/fast,      Interrupt,   Active,    Short Packet Detect     Infinite Errors */
-       status = (pipe & (1 << 26)) | (1 << 24) | (1 << 23)   |   (1 << 29)       |    (0 << 27);
+       /* Destination: pipe destination with INPUT */
+       destination = (pipe & PIPE_DEVEP_MASK) | usb_packetid(pipe);
 
-       if(interrupt_qh->element != 1)
-               printk("interrupt_qh->element = 0x%x\n", 
-                      interrupt_qh->element);
+       /* Infinite errors is 0, so no bits */
+       status = (pipe & TD_CTRL_LS) | TD_CTRL_IOC | TD_CTRL_ACTIVE |
+                       TD_CTRL_SPD;
 
-       td->link = 1;
-       td->status = status;
+       td->link = UHCI_PTR_TERM;               /* Terminate */
+       td->status = status;                    /* In */
        td->info = destination | ((usb_maxpacket(usb_dev, pipe) - 1) << 21) |
-               (usb_gettoggle(usb_dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)) << 19);
+               (usb_gettoggle(usb_dev, usb_pipeendpoint(pipe),
+               usb_pipeout(pipe)) << 19);
        td->buffer = virt_to_bus(dev->data);
-       td->first = td;
-       td->qh = interrupt_qh;
-       td->dev = usb_dev;
+       td->qh = qh;
+       td->dev = dev;
 
        /* if period 0, insert into fast q */
-
        if (period == 0) {
-               td->inuse |= 2;
-               interrupt_qh->skel = &root_hub->skel_int2_qh;
+               td->flags |= UHCI_TD_REMOVE;
+               qh->skel = &dev->uhci->skel_int2_qh;
        } else
-               interrupt_qh->skel = &root_hub->skel_int8_qh;
+               qh->skel = &dev->uhci->skel_int8_qh;
 
        uhci_add_irq_list(dev->uhci, td, handler, dev_id);
 
-       uhci_insert_td_in_qh(interrupt_qh, td);
+       uhci_insert_td_in_qh(qh, td);
 
        /* Add it into the skeleton */
-       uhci_insert_qh(interrupt_qh->skel, interrupt_qh);
-
-       return (void*)td;
-}
-
-/*
- * Remove running irq td from queues
- *
- * This function is not used anymore.
- */
-#if 0
-static int uhci_remove_irq(struct usb_device *usb_dev, unsigned int pipe, usb_device_irq handler, int period, void *dev_id)
-{
-    struct uhci_device *dev = usb_to_uhci(usb_dev);
-    struct uhci_device *root_hub=usb_to_uhci(dev->uhci->bus->root_hub);
-    struct uhci_td *td;
-    struct uhci_qh *interrupt_qh;
-    unsigned long flags;
-    struct list_head *head = &dev->uhci->interrupt_list;
-    struct list_head *tmp;
-
-    spin_lock_irqsave(&irqlist_lock, flags);
-
-    /* find the TD in the interrupt list */
-
-    tmp = head->next;
-    while (tmp != head) {
-       td = list_entry(tmp, struct uhci_td, irq_list);
-       if (td->dev_id == dev_id && td->completed == handler) {
-
-           /* found the right one - let's remove it */
+       uhci_insert_qh(qh->skel, qh);
 
-           /* notify removal */
-
-           td->completed(USB_ST_REMOVED, NULL, 0, td->dev_id);
-
-           /* this is DANGEROUS - not sure whether this is right */
-
-           list_del(&td->irq_list);
-           uhci_remove_td(td);
-           interrupt_qh = td->qh;
-           uhci_remove_qh(interrupt_qh->skel, interrupt_qh);
-           uhci_td_deallocate(td);
-           uhci_qh_deallocate(interrupt_qh);
-           spin_unlock_irqrestore(&irqlist_lock, flags);
-           return USB_ST_NOERROR;
-       }
-    }
-    spin_unlock_irqrestore(&irqlist_lock, flags);
-    return USB_ST_INTERNALERROR;
+       return (void *)td;
 }
-#endif
 
 /*
  * Release an interrupt handler previously allocated using
@@ -485,48 +463,40 @@ static int uhci_remove_irq(struct usb_device *usb_dev, unsigned int pipe, usb_de
  *
  * This function can NOT be called from an interrupt.
  */
-int uhci_release_irq(voidhandle)
+int uhci_release_irq(void *handle)
 {
        struct uhci_td *td;
-       struct uhci_qh *interrupt_qh;
-       unsigned long flags;
+       struct uhci_qh *qh;
 
 #ifdef UHCI_DEBUG
-       printk("usb-uhci: Releasing irq handle %p\n", handle);
+       printk(KERN_DEBUG "usb-uhci: releasing irq handle %p\n", handle);
 #endif
 
-       td = (struct uhci_td*)handle;
-       if (td == NULL)
+       td = (struct uhci_td *)handle;
+       if (!td)
                return USB_ST_INTERNALERROR;
 
        /* Remove it from the internal irq_list */
        uhci_remove_irq_list(td);
-#if 0
-       spin_lock_irqsave(&irqlist_lock, flags);
-       list_del(&td->irq_list);
-       spin_unlock_irqrestore(&irqlist_lock, flags);
-#endif
 
        /* Remove the interrupt TD and QH */
        uhci_remove_td(td);
-       interrupt_qh = td->qh;
-       uhci_remove_qh(interrupt_qh->skel, interrupt_qh);
+       qh = td->qh;
+       uhci_remove_qh(qh->skel, qh);
 
        if (td->completed != NULL)
                td->completed(USB_ST_REMOVED, NULL, 0, td->dev_id);
 
        /* Free the TD and QH */
-       uhci_td_deallocate(td);
-       uhci_qh_deallocate(interrupt_qh);
+       uhci_td_free(td);
+       uhci_qh_free(qh);
 
        return USB_ST_NOERROR;
 } /* uhci_release_irq() */
 
-
 /*
- * Isochronous thread operations
+ * Isochronous operations
  */
-
 static int uhci_compress_isochronous(struct usb_device *usb_dev, void *_isodesc)
 {
        struct uhci_iso_td *isodesc = (struct uhci_iso_td *)_isodesc;
@@ -534,16 +504,19 @@ static int uhci_compress_isochronous(struct usb_device *usb_dev, void *_isodesc)
        int i, totlen = 0;
 
        for (i = 0; i < isodesc->num; i++) {
-               char *cdata = bus_to_virt(isodesc->td[i].buffer & ~0xF);
-               int n = (isodesc->td[i].status + 1) & 0x7FF;
+               struct uhci_td *td = &isodesc->td[i];
+               char *cdata = uhci_ptr_to_virt(td->buffer);
+               int n = (td->status + 1) & 0x7FF;
 
                if ((cdata != data) && (n))
                        memmove(data, cdata, n);
 
+#ifdef UHCI_DEBUG
                /* Debugging */
-               if ((isodesc->td[i].status >> 16) & 0xFF)
-                       printk("error: %d %X\n", i,
-                               (isodesc->td[i].status >> 16));
+               if ((td->status >> 16) & 0xFF)
+                       printk(KERN_DEBUG "error: %d %X\n", i,
+                               (td->status >> 16));
+#endif
 
                data += n;
                totlen += n;
@@ -559,14 +532,22 @@ static int uhci_unschedule_isochronous(struct usb_device *usb_dev, void *_isodes
        struct uhci_iso_td *isodesc = (struct uhci_iso_td *)_isodesc;
        int i;
 
-       if ((isodesc->frame < 0) || (isodesc->frame > 1023))
+       if ((isodesc->frame < 0) || (isodesc->frame > 1023)) {
+               printk(KERN_ERR "illegal frame number %d\n", isodesc->frame);
                return 1;
+       }
+
+       /* FIXME: Use uhci_remove_td */
 
        /* Remove from previous frames */
        for (i = 0; i < isodesc->num; i++) {
+               struct uhci_td *td = &isodesc->td[i];
+
                /* Turn off Active and IOC bits */
-               isodesc->td[i].status &= ~(3 << 23);
-               uhci->fl->frame[(isodesc->frame + i) % 1024] = isodesc->td[i].link;
+               td->status &= ~(3 << 23);
+               td->status &= ~(TD_CTRL_ACTIVE | TD_CTRL_IOC);
+               
+               uhci->fl->frame[(isodesc->frame + i) % 1024] = td->link;
        }
 
        isodesc->frame = -1;
@@ -584,7 +565,7 @@ static int uhci_schedule_isochronous(struct usb_device *usb_dev, void *_isodesc,
        int frame, i;
 
        if (isodesc->frame != -1) {
-               printk("isoc queue not removed\n");
+               printk(KERN_ERR "isoc queue not removed\n");
                uhci_unschedule_isochronous(usb_dev, isodesc);
        }
 
@@ -592,21 +573,24 @@ static int uhci_schedule_isochronous(struct usb_device *usb_dev, void *_isodesc,
        if (!pisodesc) {
                /* It's not guaranteed to be 1-1024 */
                frame = inw(uhci->io_addr + USBFRNUM) % 1024;
+
                /* HACK: Start 2 frames from now */
                frame = (frame + 2) % 1024;
        } else
                frame = (pisodesc->endframe + 1) % 1024;
 
        for (i = 0; i < isodesc->num; i++) {
+               struct uhci_td *td = &isodesc->td[i];
+
                /* Active */
-               isodesc->td[i].status |= (1 << 23);
-               isodesc->td[i].backptr = &uhci->fl->frame[(frame + i) % 1024];
-               isodesc->td[i].link = uhci->fl->frame[(frame + i) % 1024];
-               uhci->fl->frame[(frame + i) % 1024] = virt_to_bus(&isodesc->td[i]);
+               td->status |= TD_CTRL_ACTIVE;
+               td->backptr = &uhci->fl->frame[(frame + i) % 1024];
+               td->link = uhci->fl->frame[(frame + i) % 1024];
+               uhci->fl->frame[(frame + i) % 1024] = virt_to_bus(td);
        }
 
        /* IOC on the last TD */
-       isodesc->td[i - 1].status |= (1 << 24);
+       isodesc->td[i - 1].status |= TD_CTRL_IOC;
 
        isodesc->frame = frame;
        isodesc->endframe = (frame + isodesc->num - 1) % 1024;
@@ -627,9 +611,10 @@ static void *uhci_allocate_isochronous(struct usb_device *usb_dev, unsigned int
 
        isodesc = kmalloc(sizeof(*isodesc), GFP_KERNEL);
        if (!isodesc) {
-               printk("Couldn't allocate isodesc!\n");
+               printk(KERN_ERR "Couldn't allocate isodesc!\n");
                return NULL;
        }
+
        memset(isodesc, 0, sizeof(*isodesc));
 
        /* Carefully work around the non contiguous pages */
@@ -640,7 +625,7 @@ static void *uhci_allocate_isochronous(struct usb_device *usb_dev, unsigned int
        isodesc->maxsze = maxsze;
        
        if (!isodesc->td) {
-               printk("Couldn't allocate td's\n");
+               printk(KERN_ERR "couldn't allocate td's\n");
                kfree(isodesc);
                return NULL;
        }
@@ -657,10 +642,9 @@ static void *uhci_allocate_isochronous(struct usb_device *usb_dev, unsigned int
 
                /* The "pipe" thing contains the destination in bits 8--18 */
                destination = (pipe & PIPE_DEVEP_MASK)
-                       | usb_packetid (pipe);  /* add IN or OUT */
+                       | usb_packetid (pipe);  /* add IN or OUT */
 
-               /* Status:    slow/fast,       Active,       Isochronous */
-               status = (pipe & (1 << 26)) | (1 << 23)   |   (1 << 25);
+               status = (pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | TD_CTRL_IOS;
 
                /*
                 * Build the TD for the control request
@@ -668,7 +652,6 @@ static void *uhci_allocate_isochronous(struct usb_device *usb_dev, unsigned int
                td->status = status;
                td->info = destination | ((maxsze - 1) << 21);
                td->buffer = virt_to_bus(data);
-               td->first = td;
                td->backptr = NULL;
 
                i++;
@@ -677,11 +660,6 @@ static void *uhci_allocate_isochronous(struct usb_device *usb_dev, unsigned int
                len -= maxsze;
        } while (i < isodesc->num);
 
-#if 0
-       /* IOC on the last TD */
-       td->status |= (1 << 24);
-#endif
-
        uhci_add_irq_list(dev->uhci, td, completed, dev_id);
 
        return isodesc;
@@ -710,11 +688,16 @@ static void uhci_delete_isochronous(struct usb_device *usb_dev, void *_isodesc)
  * We need to remove the TD from the lists (both interrupt
  * list and TD lists) by hand if something bad happens!
  */
-static DECLARE_WAIT_QUEUE_HEAD(control_wakeup);
 
-static int uhci_control_completed(int status, void *buffer, int len, void *dev_id)
+static int uhci_generic_completed(int status, void *buffer, int len, void *dev_id)
 {
-       wake_up(&control_wakeup);
+       wait_queue_head_t *wakeup = (wait_queue_head_t *)dev_id;
+
+       if (waitqueue_active(wakeup))
+               wake_up(wakeup);
+       else
+               printk("waitqueue empty!\n");
+
        return 0;                       /* Don't re-instate */
 }
 
@@ -722,62 +705,52 @@ static int uhci_control_completed(int status, void *buffer, int len, void *dev_i
 static int uhci_run_control(struct uhci_device *dev, struct uhci_td *first, struct uhci_td *last)
 {
        DECLARE_WAITQUEUE(wait, current);
-       struct uhci_qh *ctrl_qh = uhci_qh_allocate(dev);
-       struct uhci_td *curtd;
-       struct uhci_device *root_hub=usb_to_uhci(dev->uhci->bus->root_hub);
+       struct uhci_qh *qh = uhci_qh_alloc(dev);
+
+       if (!qh)
+               return -1;
+
        current->state = TASK_UNINTERRUPTIBLE;
-       add_wait_queue(&control_wakeup, &wait);
+       add_wait_queue(&qh->wakeup, &wait);
 
-       uhci_add_irq_list(dev->uhci, last, uhci_control_completed, NULL);
+       uhci_add_irq_list(dev->uhci, last, uhci_generic_completed, &qh->wakeup);
        
+#if 0
        /* FIXME: This is kinda kludged */
        /* Walk the TD list and update the QH pointer */
        {
-       int maxcount = 100;
+       struct uhci_td *curtd;
+       int count = 100;
 
        curtd = first;
        do {
                curtd->qh = ctrl_qh;
-               if (curtd->link & 1)
+               if (curtd->link & TD_CTRL_TERM)
                        break;
 
-               curtd = bus_to_virt(curtd->link & ~0xF);
-               if (!--maxcount) {
-                       printk("runaway tds!\n");
-                       break;
-               }
-       } while (1);
+               curtd = uhci_ptr_to_virt(curtd->link);
+       } while (--count);
+       if (!count)
+               printk(KERN_DEBUG "runaway tds!\n");
        }
+#endif
 
-       uhci_insert_tds_in_qh(ctrl_qh, first, last);
+       uhci_insert_tds_in_qh(qh, first, last);
 
        /* Add it into the skeleton */
-       uhci_insert_qh(&root_hub->skel_control_qh, ctrl_qh);
-
-//     control should be full here...  
-//     printk("control\n");
-//     show_status(dev->uhci);
-//     show_queues(dev->uhci);
-
-       schedule_timeout(HZ*5);
+       uhci_insert_qh(&dev->uhci->skel_control_qh, qh);
 
-//     control should be empty here... 
-//     show_status(dev->uhci);
-//     show_queues(dev->uhci);
+       schedule_timeout(HZ * 5);       /* 5 seconds */
 
-       remove_wait_queue(&control_wakeup, &wait);
+       remove_wait_queue(&qh->wakeup, &wait);
 
        /* Clean up in case it failed.. */
        uhci_remove_irq_list(last);
 
-#if 0
-       printk("Looking for tds [%p, %p]\n", dev->control_td, td);
-#endif
-
        /* Remove it from the skeleton */
-       uhci_remove_qh(&root_hub->skel_control_qh, ctrl_qh);
+       uhci_remove_qh(&dev->uhci->skel_control_qh, qh);
 
-       uhci_qh_deallocate(ctrl_qh);
+       uhci_qh_free(qh);
 
        return uhci_td_result(dev, last, NULL);
 }
@@ -808,20 +781,19 @@ static int uhci_control_msg(struct usb_device *usb_dev, unsigned int pipe, devre
        struct uhci_device *dev = usb_to_uhci(usb_dev);
        struct uhci_td *first, *td, *prevtd;
        unsigned long destination, status;
-       int ret;
+       int ret, count;
        int maxsze = usb_maxpacket(usb_dev, pipe);
+       __u32 nextlink;
 
-
-       if (len > maxsze * 29)
-               printk("Warning, too much data for a control packet, crashing\n");
-
-       first = td = uhci_td_allocate(dev);
+       first = td = uhci_td_alloc(dev);
+       if (!td)
+               return -ENOMEM;
 
        /* The "pipe" thing contains the destination in bits 8--18, 0x2D is SETUP */
        destination = (pipe & PIPE_DEVEP_MASK) | 0x2D;
 
-       /* Status:    slow/fast,       Active,    Short Packet Detect     Three Errors */
-       status = (pipe & (1 << 26)) | (1 << 23)   |   (1 << 29)       |    (3 << 27);
+       /* 3 errors */
+       status = (pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | TD_CTRL_SPD | (3 << 27);
 
        /*
         * Build the TD for the control request
@@ -829,7 +801,6 @@ static int uhci_control_msg(struct usb_device *usb_dev, unsigned int pipe, devre
        td->status = status;                            /* Try forever */
        td->info = destination | (7 << 21);             /* 8 bytes of data */
        td->buffer = virt_to_bus(cmd);
-       td->first = td;
 
        /*
         * If direction is "send", change the frame from SETUP (0x2D)
@@ -840,8 +811,11 @@ static int uhci_control_msg(struct usb_device *usb_dev, unsigned int pipe, devre
                destination ^= (0xE1 ^ 0x69);           /* IN -> OUT */
 
        prevtd = td;
-       td = uhci_td_allocate(dev);
-       prevtd->link = 4 | virt_to_bus(td);
+       td = uhci_td_alloc(dev);
+       if (!td)
+               return -ENOMEM;
+
+       prevtd->link = virt_to_bus(td) | UHCI_PTR_DEPTH;
 
        /*
         * Build the DATA TD's
@@ -857,18 +831,18 @@ static int uhci_control_msg(struct usb_device *usb_dev, unsigned int pipe, devre
                destination ^= 1 << 19;
        
                td->status = status;                                    /* Status */
-               td->info = destination | ((pktsze-1) << 21);            /* pktsze bytes of data */
+               td->info = destination | ((pktsze - 1) << 21);          /* pktsze bytes of data */
                td->buffer = virt_to_bus(data);
-               td->first = first;
                td->backptr = &prevtd->link;
 
                data += pktsze;
                len -= pktsze;
 
                prevtd = td;
-               td = uhci_td_allocate(dev);
-               prevtd->link = 4 | virt_to_bus(td);                     /* Update previous TD */
-
+               td = uhci_td_alloc(dev);
+               if (!td)
+                       return -ENOMEM;
+               prevtd->link = virt_to_bus(td) | UHCI_PTR_DEPTH;        /* Update previous TD */
        }
 
        /*
@@ -877,46 +851,40 @@ static int uhci_control_msg(struct usb_device *usb_dev, unsigned int pipe, devre
        destination ^= (0xE1 ^ 0x69);                   /* OUT -> IN */
        destination |= 1 << 19;                         /* End in Data1 */
 
-       td->backptr = &prevtd->link;
-       td->status = (status /* & ~(3 << 27) */) | (1 << 24);   /* no limit on final packet */
+       td->status = status | TD_CTRL_IOC;                      /* no limit on errors on final packet */
        td->info = destination | (UHCI_NULL_DATA_SIZE << 21);   /* 0 bytes of data */
        td->buffer = 0;
-       td->first = first;
-       td->link = 1;                                   /* Terminate */
+       td->backptr = &prevtd->link;
+       td->link = UHCI_PTR_TERM;                       /* Terminate */
 
        /* Start it up.. */
        ret = uhci_run_control(dev, first, td);
 
-       {
-               int maxcount = 100;
-               struct uhci_td *curtd = first;
-               unsigned int nextlink;
+       count = 100;
+       td = first;
+       do {
+               nextlink = td->link;
+               uhci_remove_td(td);
+               uhci_td_free(td);
 
-               do {
-                       nextlink = curtd->link;
-                       uhci_remove_td(curtd);
-                       uhci_td_deallocate(curtd);
-                       if (nextlink & 1)       /* Tail? */
-                               break;
+               if (nextlink & UHCI_PTR_TERM)   /* Tail? */
+                       break;
 
-                       curtd = bus_to_virt(nextlink & ~0xF);
-                       if (!--maxcount) {
-                               printk("runaway td's!?\n");
-                               break;
-                       }
-               } while (1);
-       }
+               td = uhci_ptr_to_virt(nextlink);
+       } while (--count);
+
+       if (!count)
+               printk(KERN_ERR "runaway td's!?\n");
 
        if (uhci_debug && ret) {
                __u8 *p = (__u8 *)cmd;
 
-               printk("Failed cmd - %02X %02X %02X %02X %02X %02X %02X %02X\n",
+               printk(KERN_DEBUG "Failed cmd - %02X %02X %02X %02X %02X %02X %02X %02X\n",
                       p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
        }
        return ret;
 }
 
-
 /*
  * Bulk thread operations: we just mark the last TD
  * in a bulk thread as an interrupt TD, and wake up
@@ -925,74 +893,56 @@ static int uhci_control_msg(struct usb_device *usb_dev, unsigned int pipe, devre
  * We need to remove the TD from the lists (both interrupt
  * list and TD lists) by hand if something bad happens!
  */
-static DECLARE_WAIT_QUEUE_HEAD(bulk_wakeup);
-
-static int uhci_bulk_completed(int status, void *buffer, int len, void *dev_id)
-{
-       wake_up(&bulk_wakeup);
-       return 0;                       /* Don't re-instate */
-}
 
 /* td points to the last td in the list, which interrupts on completion */
 static int uhci_run_bulk(struct uhci_device *dev, struct uhci_td *first, struct uhci_td *last, unsigned long *rval)
 {
        DECLARE_WAITQUEUE(wait, current);
-       struct uhci_qh *bulk_qh = uhci_qh_allocate(dev);
-       struct uhci_td *curtd;
-       struct uhci_device *root_hub = usb_to_uhci(dev->uhci->bus->root_hub);
+       struct uhci_qh *qh = uhci_qh_alloc(dev);
+
+       if (!qh)
+               return -ENOMEM;
 
        current->state = TASK_UNINTERRUPTIBLE;
-       add_wait_queue(&bulk_wakeup, &wait);
+       add_wait_queue(&qh->wakeup, &wait);
 
-       uhci_add_irq_list(dev->uhci, last, uhci_bulk_completed, NULL);
+       uhci_add_irq_list(dev->uhci, last, uhci_generic_completed, &qh->wakeup);
        
+#if 0
        /* FIXME: This is kinda kludged */
        /* Walk the TD list and update the QH pointer */
        {
-       int maxcount = 100;
+       struct uhci_td *curtd;
+       int count = 100;
 
        curtd = first;
        do {
                curtd->qh = bulk_qh;
-               if (curtd->link & 1)
+               if (curtd->link & UHCI_PTR_TERM)
                        break;
 
-               curtd = bus_to_virt(curtd->link & ~0xF);
-               if (!--maxcount) {
-                       printk("runaway tds!\n");
-                       break;
-               }
-       } while (1);
+               curtd = uhci_ptr_to_virt(curtd->link);
+       } while (--count);
+       if (!count)
+               printk(KERN_ERR "runaway tds!\n");
        }
+#endif
 
-       uhci_insert_tds_in_qh(bulk_qh, first, last);
+       uhci_insert_tds_in_qh(qh, first, last);
 
        /* Add it into the skeleton */
-       uhci_insert_qh(&root_hub->skel_bulk0_qh, bulk_qh);
-
-//     now we're in the queue... but don't ask WHAT is in there ;-(
-//     printk("bulk\n");
-//     show_status(dev->uhci);
-//     show_queues(dev->uhci);
+       uhci_insert_qh(&dev->uhci->skel_bulk_qh, qh);
 
-       schedule_timeout(HZ*5);
-//     show_status(dev->uhci);
-//     show_queues(dev->uhci);
+       schedule_timeout(HZ*5);         /* 5 seconds */
 
-       //show_queue(first->qh);
-       remove_wait_queue(&bulk_wakeup, &wait);
+       remove_wait_queue(&qh->wakeup, &wait);
 
        /* Clean up in case it failed.. */
        uhci_remove_irq_list(last);
 
-#if 0
-       printk("Looking for tds [%p, %p]\n", dev->control_td, td);
-#endif
-
-       /* Remove it from the skeleton */
-       uhci_remove_qh(&root_hub->skel_bulk0_qh, bulk_qh);
+       uhci_remove_qh(&dev->uhci->skel_bulk_qh, qh);
 
-       uhci_qh_deallocate(bulk_qh);
+       uhci_qh_free(qh);
 
        return uhci_td_result(dev, last, rval);
 }
@@ -1005,13 +955,6 @@ static int uhci_run_bulk(struct uhci_device *dev, struct uhci_td *first, struct
  *
  * A bulk message is only built up from
  * the data phase
- *
- * The data phase can be an arbitrary number of TD's
- * although we currently had better not have more than
- * 31 TD's here.
- *
- * 31 TD's is a minimum of 248 bytes worth of bulk
- * information.
  */
 static int uhci_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, void *data, int len, unsigned long *rval)
 {
@@ -1025,19 +968,19 @@ static int uhci_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, void *da
            usb_clear_halt(usb_dev, usb_pipeendpoint(pipe) | (pipe & 0x80)))
                return USB_ST_STALL;
 
-       if (len > maxsze * 31)
-               printk("Warning, too much data for a bulk packet, crashing (%d/%d)\n", len, maxsze);
-
        /* The "pipe" thing contains the destination in bits 8--18 */
        destination = (pipe & PIPE_DEVEP_MASK) | usb_packetid (pipe);
 
-       /* Status:    slow/fast,       Active,    Short Packet Detect     Three Errors */
-       status = (pipe & (1 << 26)) | (1 << 23)   |   (1 << 29)       |    (3 << 27);
+       /* 3 errors */
+       status = (pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | TD_CTRL_SPD | (3 << 27);
 
        /*
         * Build the TDs for the bulk request
         */
-        first = td = uhci_td_allocate(dev);
+        first = td = uhci_td_alloc(dev);
+       if (!td)
+               return -ENOMEM;
+
         prevtd = first; //This is fake, but at least it's not NULL
        while (len > 0) {
                /* Build the TD for control status */
@@ -1051,22 +994,25 @@ static int uhci_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, void *da
                         (usb_gettoggle(usb_dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)) << 19); /* pktsze bytes of data */
                td->buffer = virt_to_bus(data);
                td->backptr = &prevtd->link;
-               td->first = first;
 
                data += maxsze;
                len -= maxsze;
 
                if (len > 0) {
                        prevtd = td;
-                       td = uhci_td_allocate(dev);
-                       prevtd->link = 4 | virt_to_bus(td);                     /* Update previous TD */
+                       td = uhci_td_alloc(dev);
+                       if (!td)
+                               return -ENOMEM;
+
+                       prevtd->link = virt_to_bus(td) | UHCI_PTR_DEPTH;/* Update previous TD */
                }
 
                /* Alternate Data0/1 (start with Data0) */
-               usb_dotoggle(usb_dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)); 
+               usb_dotoggle(usb_dev, usb_pipeendpoint(pipe), usb_pipeout(pipe));
        }
+
        td->link = 1;                           /* Terminate */
-       td->status |= (1 << 24);                /* IOC */
+       td->status |= TD_CTRL_IOC;
 
        /* CHANGE DIRECTION HERE! SAVE IT SOMEWHERE IN THE ENDPOINT!!! */
 
@@ -1074,51 +1020,46 @@ static int uhci_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, void *da
        ret = uhci_run_bulk(dev, first, td, rval);
 
        {
-               int maxcount = 100;
+               int count = 100;
                struct uhci_td *curtd = first;
                unsigned int nextlink;
 
                do {
                        nextlink = curtd->link;
                        uhci_remove_td(curtd);
-                       uhci_td_deallocate(curtd);
-                       if (nextlink & 1)       /* Tail? */
-                               break;
+                       uhci_td_free(curtd);
 
-                       curtd = bus_to_virt(nextlink & ~0xF);
-                       if (!--maxcount) {
-                               printk("runaway td's!?\n");
+                       if (nextlink & UHCI_PTR_TERM)   /* Tail? */
                                break;
-                       }
-               } while (1);
+
+                       curtd = uhci_ptr_to_virt(nextlink);
+               } while (--count);
+
+               if (!count)
+                       printk(KERN_DEBUG "runaway td's!?\n");
        }
+
        return ret;
 }
 
 static void * uhci_request_bulk(struct usb_device *usb_dev, unsigned int pipe, usb_device_irq handler, void *data, int len, void *dev_id)
 {
        struct uhci_device *dev = usb_to_uhci(usb_dev);
-       struct uhci_device *root_hub=usb_to_uhci(dev->uhci->bus->root_hub);
+       struct uhci *uhci = dev->uhci;
        struct uhci_td *first, *td, *prevtd;
-       struct uhci_qh *bulk_qh = uhci_qh_allocate(dev);
+       struct uhci_qh *bulk_qh = uhci_qh_alloc(dev);
        unsigned long destination, status;
        int maxsze = usb_maxpacket(usb_dev, pipe);
-       
-       if (len > maxsze * 31)
-               printk("Warning, too much data for a bulk packet, crashing\n");
 
        /* The "pipe" thing contains the destination in bits 8--18, 0x69 is IN */
        destination = (pipe & 0x0007ff00) | usb_packetid(pipe);
 
-       /* Status:    slow/fast,       Active,    Short Packet Detect     Infinite Errors */
-       status = (pipe & (1 << 26)) | (1 << 23)   |   (1 << 29)       |    (0 << 27);
-
+       /* Infinite errors is 0 */
+       status = (pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | TD_CTRL_SPD;
 
-       /*
-        * Build the TDs for the bulk request
-        */
-       first = td = uhci_td_allocate(dev);
-       prevtd=td;
+       /* Build the TDs for the bulk request */
+       first = td = uhci_td_alloc(dev);
+       prevtd = td;
        while (len > 0) {
                /* Build the TD for control status */
                int pktsze = len;
@@ -1126,41 +1067,38 @@ static void * uhci_request_bulk(struct usb_device *usb_dev, unsigned int pipe, u
                if (pktsze > maxsze)
                        pktsze = maxsze;
 
-               td->status = status;                                    /* Status */
+               td->status = status;                                    /* Status */
                td->info = destination | ((pktsze-1) << 21) |
-                        (usb_gettoggle(usb_dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)) << 19); /* pktsze bytes of data */
+                       (usb_gettoggle(usb_dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)) << 19); /* pktsze bytes of data */
                td->buffer = virt_to_bus(data);
                td->backptr = &prevtd->link;
-               td->first = first;
                td->qh = bulk_qh;
-               td->dev=usb_dev;
-
+               td->dev = dev;
                data += pktsze;
                len -= pktsze;
 
                if (len > 0) {
                        prevtd = td;
-                       td = uhci_td_allocate(dev);
-                       prevtd->link = 4 | virt_to_bus(td);                     /* Update previous TD */
+                       td = uhci_td_alloc(dev);
+                       prevtd->link = virt_to_bus(td) | UHCI_PTR_DEPTH;
                }
 
                /* Alternate Data0/1 */
                usb_dotoggle(usb_dev, usb_pipeendpoint(pipe), usb_pipeout(pipe));
        }
-       
-       first->backptr=NULL;
-       td->link = 1;                           /* Terminate */
-       td->status = status | (1 << 24);        /* IOC */
-       td->first = first;
-               
+
+       first->backptr = NULL;
+       td->link = 1;                           /* Terminate */
+       td->status = status | TD_CTRL_IOC;      /* IOC */
+
        uhci_add_irq_list(dev->uhci, td, handler, dev_id);
 
        uhci_insert_tds_in_qh(bulk_qh, first, td);
 
-       bulk_qh->skel=&root_hub->skel_bulk0_qh;
-       uhci_insert_qh(&root_hub->skel_bulk0_qh, bulk_qh);
-       
-       //Return last td for removal
+       bulk_qh->skel = &uhci->skel_bulk_qh;
+       uhci_insert_qh(&uhci->skel_bulk_qh, bulk_qh);
+
+       /* Return last td for removal */
        return td;
 }
 
@@ -1170,21 +1108,21 @@ static void * uhci_request_bulk(struct usb_device *usb_dev, unsigned int pipe, u
  * There is only one queue using this pipe. (the one we remove)
  * Any data that is in the queue is useless for us, we throw it away.
  */
-static int uhci_terminate_bulk(struct usb_device *dev, void * first) 
+static int uhci_terminate_bulk(struct usb_device *dev, void * first)
 {
-       //none found? there is nothing to remove!
-       if (!first) return 0;
+       /* none found? there is nothing to remove! */
+       if (!first)
+               return 0;
 
        uhci_remove_transfer(first,1);
-       return 1;
 
+       return 1;
 }
 
-static struct usb_device *uhci_usb_allocate(struct usb_device *parent)
+static struct usb_device *uhci_usb_alloc(struct usb_device *parent)
 {
        struct usb_device *usb_dev;
        struct uhci_device *dev;
-       int i;
 
        /* Allocate the USB device */
        usb_dev = kmalloc(sizeof(*usb_dev), GFP_KERNEL);
@@ -1205,6 +1143,7 @@ static struct usb_device *uhci_usb_allocate(struct usb_device *parent)
 
        usb_dev->hcpriv = dev;
        dev->usb = usb_dev;
+
        usb_dev->parent = parent;
 
        if (parent) {
@@ -1212,49 +1151,12 @@ static struct usb_device *uhci_usb_allocate(struct usb_device *parent)
                dev->uhci = usb_to_uhci(parent)->uhci;
        }
 
-       /* Reset the QH's and TD's */
-       for (i = 0; i < UHCI_MAXQH; i++) {
-               dev->qh[i].link = 1;
-               dev->qh[i].element = 1;
-               dev->qh[i].inuse = 0;
-       }
-
-       for (i = 0; i < UHCI_MAXTD; i++) {
-               dev->td[i].link = 1;
-               dev->td[i].inuse = 0;
-       }
-
        return usb_dev;
 }
 
-static int uhci_usb_deallocate(struct usb_device *usb_dev)
+static int uhci_usb_free(struct usb_device *usb_dev)
 {
        struct uhci_device *dev = usb_to_uhci(usb_dev);
-       int i;
-
-       /* There are UHCI_MAXTD preallocated tds */
-       for (i = 0; i < UHCI_MAXTD; ++i) {
-               struct uhci_td *td = dev->td + i;
-
-               if (td->inuse & 1) {
-                       uhci_remove_td(td);
-
-                       /* And remove it from the irq list, if it's active */
-                       if (td->status & (1 << 23))
-                               td->status &= ~(1 << 23);
-#if 0
-                               uhci_remove_irq_list(td);
-#endif
-               }
-       }
-
-       /* Remove the td from any queues */
-       for (i = 0; i < UHCI_MAXQH; ++i) {
-               struct uhci_qh *qh = dev->qh + i;
-
-               if (qh->inuse & 1)
-                       uhci_remove_qh(qh->skel, qh);
-       }
 
        kfree(dev);
        usb_destroy_configuration(usb_dev);
@@ -1264,8 +1166,8 @@ static int uhci_usb_deallocate(struct usb_device *usb_dev)
 }
 
 struct usb_operations uhci_device_operations = {
-       uhci_usb_allocate,
-       uhci_usb_deallocate,
+       uhci_usb_alloc,
+       uhci_usb_free,
        uhci_control_msg,
        uhci_bulk_msg,
        uhci_request_irq,
@@ -1308,7 +1210,6 @@ static void uhci_reset_port(unsigned int port)
 
 }
 
-
 /*
  * This gets called if the connect status on the root
  * hub (and the root hub only) changes.
@@ -1318,8 +1219,11 @@ static void uhci_connect_change(struct uhci *uhci, unsigned int port, unsigned i
        struct usb_device *usb_dev;
        struct uhci_device *dev;
        unsigned short status;
-       struct uhci_device *root_hub=usb_to_uhci(uhci->bus->root_hub);
-       printk("uhci_connect_change: called for %d\n", nr);
+       struct uhci_device *root_hub = usb_to_uhci(uhci->bus->root_hub);
+
+#ifdef UHCI_DEBUG
+       printk(KERN_INFO "uhci_connect_change: called for %d\n", nr);
+#endif
 
        /*
         * Even if the status says we're connected,
@@ -1343,12 +1247,12 @@ static void uhci_connect_change(struct uhci *uhci, unsigned int port, unsigned i
         * Ok, we got a new connection. Allocate a device to it,
         * and find out what it wants to do..
         */
-       usb_dev = uhci_usb_allocate(root_hub->usb);
+       usb_dev = uhci_usb_alloc(root_hub->usb);
        if (!usb_dev)
                return;
        
        dev = usb_dev->hcpriv;
-       dev->uhci = uhci;
+
        usb_connect(usb_dev);
 
        root_hub->usb->children[nr] = usb_dev;
@@ -1364,7 +1268,13 @@ static void uhci_connect_change(struct uhci *uhci, unsigned int port, unsigned i
         * The rest is generic for any new USB attach, regardless of
         * hub type.
         */
-       usb_new_device(usb_dev);
+       if (usb_new_device(usb_dev)) {
+               unsigned short status = inw(port);
+
+               printk(KERN_INFO "uhci: disabling malfunctioning port %d\n",
+                       nr + 1);
+               outw(status | USBPORTSC_PE, port);
+       }
 }
 
 /*
@@ -1374,7 +1284,7 @@ static void uhci_connect_change(struct uhci *uhci, unsigned int port, unsigned i
  */
 static void uhci_check_configuration(struct uhci *uhci)
 {
-       struct uhci_device * root_hub=usb_to_uhci(uhci->bus->root_hub);
+       struct uhci_device *root_hub = usb_to_uhci(uhci->bus->root_hub);
        unsigned int io_addr = uhci->io_addr + USBPORTSC1;
        int maxchild = root_hub->usb->maxchild;
        int nr = 0;
@@ -1391,60 +1301,70 @@ static void uhci_check_configuration(struct uhci *uhci)
 
 static void uhci_interrupt_notify(struct uhci *uhci)
 {
-       struct list_head *head = &uhci->interrupt_list;
-       struct list_head *tmp;
+       struct list_head *tmp, *head = &uhci->interrupt_list;
        int status;
 
        spin_lock(&irqlist_lock);
        tmp = head->next;
        while (tmp != head) {
-               struct uhci_td *td = list_entry(tmp, struct uhci_td, irq_list);
-               struct list_head *next;
-               
-               next = tmp->next;
+               struct uhci_td *first, *td = list_entry(tmp,
+                                       struct uhci_td, irq_list);
 
-               if (!((status = td->status) & (1 << 23)) ||  /* No longer active? */
-                   ((td->qh->element & ~15) && 
-                     !((status = uhci_link_to_td(td->qh->element)->status) & (1 <<23)) &&
-                     (status & 0x760000) /* is in error state (Stall, db, babble, timeout, bitstuff) */)) {    
-                               unsigned long rval;
-                               int status;
+               tmp = tmp->next;
 
-                               status=uhci_td_result(usb_to_uhci(td->dev),td,&rval);
-                               /* remove from IRQ list */
-                               __list_del(tmp->prev, next);
-                               INIT_LIST_HEAD(tmp);
+               /* We check the TD which had the IOC bit as well as the */
+               /*  first TD */
+               /* XXX: Shouldn't we check all of the TD's in the chain? */
+               if ((td->qh) && (td->qh->element & ~UHCI_PTR_BITS))
+                       first = uhci_link_to_td(td->qh->element);
+               else
+                       first = NULL;
 
-                               if (td->completed(status, bus_to_virt(td->buffer), rval, td->dev_id)) {
-                                       list_add(&td->irq_list, &uhci->interrupt_list);
-       
-                                       if (!(td->status & (1 << 25))) {
-                                               struct uhci_qh *interrupt_qh = td->qh;
+               /* If any of the error bits are set OR the active is NOT set */
+               /*  then we're interested in this TD */
+               status = td->status & 0xF60000;
 
-                                               usb_dotoggle(td->dev, usb_pipeendpoint(td->info), usb_pipeout(td->info));
-                                               td->info &= ~(1 << 19); /* clear data toggle */
-                                               td->info |= usb_gettoggle(td->dev, usb_pipeendpoint(td->info), usb_pipeout(td->info)) << 19; /* toggle between data0 and data1 */
-                                               td->status = (td->status & 0x2f000000) | (1 << 23) | (1 << 24); /* active */
-       
-                                               /* Remove then readd? Is that necessary */
-                                               uhci_remove_td(td);
-                                               uhci_insert_td_in_qh(interrupt_qh, td);
-                                       }
-                               } else if (td->inuse & 2) {
-                                       struct uhci_qh *interrupt_qh = td->qh;
-                                       /* marked for removal */
-                                       td->inuse &= ~2;
-                                       usb_dotoggle(td->dev, usb_pipeendpoint(td->info), usb_pipeout(td->info));
-                                       uhci_remove_qh(interrupt_qh->skel, interrupt_qh);
-                                       uhci_qh_deallocate(interrupt_qh);
-                                       uhci_td_deallocate(td);
-                               }
-                               /* If completed wants to not reactivate, then it's */
-                               /* responsible for free'ing the TD's and QH's */
-                               /* or another function (such as run_control) */
+               if ((!(status ^ TD_CTRL_ACTIVE)) && (first) &&
+                   (!(first->status & TD_CTRL_ACTIVE)))
+                       status = first->status & 0xF60000;
 
-               } 
-               tmp = next;
+               if (!(status ^ TD_CTRL_ACTIVE))
+                       continue;
+
+
+               /* remove from IRQ list */
+               list_del(&td->irq_list);
+               INIT_LIST_HEAD(&td->irq_list);
+
+               if (td->completed(uhci_map_status(status, 0),
+                   bus_to_virt(td->buffer), -1, td->dev_id)) {
+                       list_add(&td->irq_list, &uhci->interrupt_list);
+
+                       /* Isochronous TD's don't need this */
+                       if (!(td->status & TD_CTRL_IOS)) {
+                               struct usb_device *usb_dev = td->dev->usb;
+
+                               usb_dotoggle(usb_dev, usb_pipeendpoint(td->info), usb_pipeout(td->info));
+                               td->info &= ~(1 << 19); /* clear data toggle */
+                               td->info |= usb_gettoggle(usb_dev, usb_pipeendpoint(td->info), usb_pipeout(td->info)) << 19; /* toggle between data0 and data1 */
+                               td->status = (td->status & 0x2F000000) | TD_CTRL_ACTIVE | TD_CTRL_IOC;
+                               /* The HC removes it, so readd it */
+                               uhci_insert_td_in_qh(td->qh, td);
+                       }
+               } else if (td->flags & UHCI_TD_REMOVE) {
+                       struct usb_device *usb_dev = td->dev->usb;
+
+                       /* marked for removal */
+                       td->flags &= ~UHCI_TD_REMOVE;
+                       usb_dotoggle(usb_dev, usb_pipeendpoint(td->info), usb_pipeout(td->info));
+                       uhci_remove_qh(td->qh->skel, td->qh);
+                       uhci_qh_free(td->qh);
+                       uhci_td_free(td);
+               }
+
+               /* If completed does not wants to reactivate, then */
+               /* it's responsible for free'ing the TD's and QH's */
+               /* or another function (such as run_control) */
        }
        spin_unlock(&irqlist_lock);
 }
@@ -1460,8 +1380,9 @@ static void uhci_interrupt_notify(struct uhci *uhci)
 static void uhci_root_hub_events(struct uhci *uhci, unsigned int io_addr)
 {
        if (waitqueue_active(&uhci_configure)) {
-               struct uhci_device * root_hub=usb_to_uhci(uhci->bus->root_hub);
+               struct uhci_device *root_hub = usb_to_uhci(uhci->bus->root_hub);
                int ports = root_hub->usb->maxchild;
+
                io_addr += USBPORTSC1;
                do {
                        if (inw(io_addr) & USBPORTSC_CSC) {
@@ -1485,9 +1406,6 @@ static void uhci_interrupt(int irq, void *__uhci, struct pt_regs *regs)
        status = inw(io_addr + USBSTS);
        outw(status, io_addr + USBSTS);
 
-//     if ((status & ~0x21) != 0)
-//             printk("interrupt: %X\n", status);
-
        /* Walk the list of pending TD's to see which ones completed.. */
        uhci_interrupt_notify(uhci);
 
@@ -1505,16 +1423,23 @@ static void uhci_interrupt(int irq, void *__uhci, struct pt_regs *regs)
 static void uhci_init_ticktd(struct uhci *uhci)
 {
        struct uhci_device *dev = usb_to_uhci(uhci->bus->root_hub);
-       struct uhci_td *td = uhci_td_allocate(dev);
+       struct uhci_td *td = uhci_td_alloc(dev);
+
+       if (!td) {
+               printk(KERN_ERR "unable to allocate ticktd\n");
+               return;
+       }
 
-       td->link = 1;
-       td->status = (1 << 24);                                 /* interrupt on completion */
+       /* Don't clobber the frame */
+       td->link = uhci->fl->frame[0];
+       td->status = TD_CTRL_IOC;
        td->info = (15 << 21) | 0x7f69;                         /* (ignored) input packet, 16 bytes, device 127 */
        td->buffer = 0;
-       td->first = td;
        td->qh = NULL;
 
        uhci->fl->frame[0] = virt_to_bus(td);
+
+       uhci->ticktd = td;
 }
 
 static void reset_hc(struct uhci *uhci)
@@ -1522,9 +1447,9 @@ static void reset_hc(struct uhci *uhci)
        unsigned int io_addr = uhci->io_addr;
 
        /* Global reset for 50ms */
-       outw(USBCMD_GRESET, io_addr+USBCMD);
+       outw(USBCMD_GRESET, io_addr + USBCMD);
        wait_ms(50);
-       outw(0, io_addr+USBCMD);
+       outw(0, io_addr + USBCMD);
        wait_ms(10);
 }
 
@@ -1544,13 +1469,15 @@ static void start_hc(struct uhci *uhci)
        outw(USBCMD_HCRESET, io_addr + USBCMD);
        while (inw(io_addr + USBCMD) & USBCMD_HCRESET) {
                if (!--timeout) {
-                       printk("USBCMD_HCRESET timed out!\n");
+                       printk(KERN_ERR "USBCMD_HCRESET timed out!\n");
                        break;
                }
        }
 
-
+       /* Turn on all interrupts */
        outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP, io_addr + USBINTR);
+
+       /* Start at frame 0 */
        outw(0, io_addr + USBFRNUM);
        outl(virt_to_bus(uhci->fl), io_addr + USBFLBASEADD);
 
@@ -1575,6 +1502,9 @@ static void start_hc(struct uhci *uhci)
  * We could certainly have multiple queues of the same
  * type, and maybe we should. We could have per-device
  * queues, for example. We begin small.
+ *
+ * Queues are dynamically allocated for devices now,
+ * this code only sets up the skeleton queue
  */
 static struct uhci *alloc_uhci(unsigned int io_addr)
 {
@@ -1599,33 +1529,27 @@ static struct uhci *alloc_uhci(unsigned int io_addr)
        if (!uhci->fl)
                goto au_free_uhci;
 
-       bus = kmalloc(sizeof(*bus), GFP_KERNEL);
+       bus = usb_alloc_bus(&uhci_device_operations);
        if (!bus)
                goto au_free_fl;
 
-       memset(bus, 0, sizeof(*bus));
-
        uhci->bus = bus;
        bus->hcpriv = uhci;
-       bus->op = &uhci_device_operations;
 
        /*
-        * We allocate a 8kB area for the UHCI hub. The area
-        * is described by the uhci_device structure, and basically
-        * contains everything needed for normal operation.
-        *
-        * The first page is the actual device descriptor for the
-        * hub.
-        *
-        * The second page is used for the frame list.
+        * Allocate the root_hub
         */
-       usb = uhci_usb_allocate(NULL);
+       usb = uhci_usb_alloc(NULL);
        if (!usb)
                goto au_free_bus;
 
        usb->bus = bus;
+
        dev = usb_to_uhci(usb);
-       uhci->bus->root_hub=uhci_to_usb(dev);
+       dev->uhci = uhci;
+
+       uhci->bus->root_hub = uhci_to_usb(dev);
+
        /* Initialize the root hub */
        /* UHCI specs says devices must have 2 ports, but goes on to say */
        /* they may have more but give no way to determine how many they */
@@ -1633,29 +1557,20 @@ static struct uhci *alloc_uhci(unsigned int io_addr)
        usb->maxchild = 2;
        usb_init_root_hub(usb);
 
-       /*
-        * Initialize the queues. They all start out empty,
-        * linked to each other in the proper order.
-        */
-       for (i = 1 ; i < 9; i++) {
-               dev->qh[i].link = 2 | virt_to_bus(&dev->skel_control_qh);
-               dev->qh[i].element = 1;
-       }
-       
-       dev->skel_control_qh.link = 2 | virt_to_bus(&dev->skel_bulk0_qh);
-       dev->skel_control_qh.element = 1;
-
-       dev->skel_bulk0_qh.link = 2 | virt_to_bus(&dev->skel_bulk1_qh);
-       dev->skel_bulk0_qh.element = 1;
+       /* 8 Interrupt queues */
+       for (i = 0; i < 8; i++) {
+               struct uhci_qh *qh = &uhci->skelqh[i];
 
-       dev->skel_bulk1_qh.link = 2 | virt_to_bus(&dev->skel_bulk2_qh);
-       dev->skel_bulk1_qh.element = 1;
+               qh->link = virt_to_bus(&uhci->skel_control_qh) | UHCI_PTR_QH;
+               qh->element = UHCI_PTR_TERM;
+       }
 
-       dev->skel_bulk2_qh.link = 2 | virt_to_bus(&dev->skel_bulk3_qh);
-       dev->skel_bulk2_qh.element = 1;
+       uhci->skel_control_qh.link = virt_to_bus(&uhci->skel_bulk_qh) |
+               UHCI_PTR_QH;
+       uhci->skel_control_qh.element = UHCI_PTR_TERM;
 
-       dev->skel_bulk3_qh.link = 1;
-       dev->skel_bulk3_qh.element = 1;
+       uhci->skel_bulk_qh.link = UHCI_PTR_TERM;
+       uhci->skel_bulk_qh.element = UHCI_PTR_TERM;
 
        /*
         * Fill the frame list: make all entries point to
@@ -1666,7 +1581,7 @@ static struct uhci *alloc_uhci(unsigned int io_addr)
         * us a reasonable dynamic range for irq latencies.
         */
        for (i = 0; i < 1024; i++) {
-               struct uhci_qh * irq = &dev->skel_int2_qh;
+               struct uhci_qh *irq = &uhci->skel_int2_qh;
                if (i & 1) {
                        irq++;
                        if (i & 2) {
@@ -1688,7 +1603,7 @@ static struct uhci *alloc_uhci(unsigned int io_addr)
                                }
                        }
                }
-               uhci->fl->frame[i] =  2 | virt_to_bus(irq);
+               uhci->fl->frame[i] =  virt_to_bus(irq) | UHCI_PTR_QH;
        }
 
        return uhci;
@@ -1698,15 +1613,14 @@ static struct uhci *alloc_uhci(unsigned int io_addr)
  */
 
 au_free_bus:
-       kfree (bus);
+       usb_free_bus(bus);
 au_free_fl:
-       free_page ((unsigned long)uhci->fl);
+       free_page((unsigned long)uhci->fl);
 au_free_uhci:
-       kfree (uhci);
+       kfree(uhci);
        return NULL;
 }
 
-
 /*
  * De-allocate all resources..
  */
@@ -1717,51 +1631,44 @@ static void release_uhci(struct uhci *uhci)
                uhci->irq = -1;
        }
 
-#if 0
-       if (uhci->bus->root_hub) {
-               uhci_usb_deallocate(uhci_to_usb(uhci->bus->root_hub));
-               uhci->bus->root_hub = NULL;
+       if (uhci->ticktd) {
+               uhci_td_free(uhci->ticktd);
+               uhci->ticktd = NULL;
        }
-#endif
 
        if (uhci->fl) {
                free_page((unsigned long)uhci->fl);
                uhci->fl = NULL;
        }
 
-       kfree(uhci->bus);
+       usb_free_bus(uhci->bus);
        kfree(uhci);
 }
 
 static int uhci_control_thread(void * __uhci)
 {
        struct uhci *uhci = (struct uhci *)__uhci;
-       struct uhci_device * root_hub =usb_to_uhci(uhci->bus->root_hub);
+
+       uhci->control_running = 1;
 
        lock_kernel();
-       request_region(uhci->io_addr, 32, "usb-uhci");
 
        /*
         * This thread doesn't need any user-level access,
         * so get rid of all our resources..
         */
-       printk("uhci_control_thread at %p\n", &uhci_control_thread);
        exit_mm(current);
        exit_files(current);
-       //exit_fs(current);
 
        strcpy(current->comm, "uhci-control");
 
        /*
         * Ok, all systems are go..
         */
-       start_hc(uhci);
-       usb_register_bus(uhci->bus);
-       for(;;) {
+       do {
                siginfo_t info;
                int unsigned long signr;
 
-               interruptible_sleep_on(&uhci_configure);
 #ifdef CONFIG_APM
                if (apm_resume) {
                        apm_resume = 0;
@@ -1771,40 +1678,31 @@ static int uhci_control_thread(void * __uhci)
 #endif
                uhci_check_configuration(uhci);
 
-               if(signal_pending(current)) {
+               interruptible_sleep_on(&uhci_configure);
+
+               if (signal_pending(current)) {
                        /* sending SIGUSR1 makes us print out some info */
                        spin_lock_irq(&current->sigmask_lock);
                        signr = dequeue_signal(&current->blocked, &info);
                        spin_unlock_irq(&current->sigmask_lock);
 
-                       if(signr == SIGUSR1) {
-                               printk("UHCI queue dump:\n");
+                       if (signr == SIGUSR1) {
+                               printk(KERN_DEBUG "UHCI queue dump:\n");
                                show_queues(uhci);
                        } else if (signr == SIGUSR2) {
                                uhci_debug = !uhci_debug;
-                               printk("UHCI debug toggle = %x\n", uhci_debug);
-                       } else {
+                               printk(KERN_DEBUG "UHCI debug toggle = %x\n",
+                                       uhci_debug);
+                       } else
                                break;
-                       }
                }
-       }
-
-       {
-       int i;
-       if(root_hub)
-               for(i = 0; i < root_hub->usb->maxchild; i++)
-                       usb_disconnect(root_hub->usb->children + i);
-       }
-
-       usb_deregister_bus(uhci->bus);
+       } while (uhci->control_continue);
 
-       reset_hc(uhci);
-       release_region(uhci->io_addr, 32);
-
-       release_uhci(uhci);
+/*
        MOD_DEC_USE_COUNT;
+*/
 
-       printk("uhci_control_thread exiting\n");
+       uhci->control_running = 0;
 
        return 0;
 }      
@@ -1822,21 +1720,37 @@ static int found_uhci(int irq, unsigned int io_addr)
        if (!uhci)
                return -ENOMEM;
 
+       INIT_LIST_HEAD(&uhci->uhci_list);
+       list_add(&uhci->uhci_list, &uhci_list);
+
+       request_region(uhci->io_addr, 32, "usb-uhci");
+
        reset_hc(uhci);
 
+       usb_register_bus(uhci->bus);
+       start_hc(uhci);
+
+       uhci->control_continue = 1;
+
        retval = -EBUSY;
-       if (request_irq(irq, uhci_interrupt, SA_SHIRQ, "usb", uhci) == 0) {
+       if (request_irq(irq, uhci_interrupt, SA_SHIRQ, "uhci", uhci) == 0) {
                int pid;
-               MOD_INC_USE_COUNT;
+
                uhci->irq = irq;
                pid = kernel_thread(uhci_control_thread, uhci,
                        CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
-               if (pid >= 0)
-                       return 0;
+               if (pid >= 0) {
+                       uhci->control_pid = pid;
+
+                       return(pid);
+               }
 
-               MOD_DEC_USE_COUNT;
                retval = pid;
        }
+
+       reset_hc(uhci);
+       release_region(uhci->io_addr, 32);
+
        release_uhci(uhci);
        return retval;
 }
@@ -1852,6 +1766,13 @@ static int start_uhci(struct pci_dev *dev)
                /* IO address? */
                if (!(dev->resource[i].flags & 1))
                        continue;
+
+#if 0
+               /* Is it already in use? */
+               if (check_region(io_addr, 32))
+                       break;
+#endif
+
                return found_uhci(dev->irq, io_addr);
        }
        return -1;
@@ -1888,16 +1809,44 @@ static int handle_apm_event(apm_event_t event)
 }
 #endif
 
-
 int uhci_init(void)
 {
        int retval;
        struct pci_dev *dev = NULL;
        u8 type;
+       char *name;
+
+       /* FIXME: This is lame, but I guess it's better to leak memory than */
+       /* crash */
+       name = kmalloc(10, GFP_KERNEL);
+       if (!name)
+               return -ENOMEM;
+
+       strcpy(name, "uhci_td");
+
+       uhci_td_cachep = kmem_cache_create(name,
+               sizeof(struct uhci_td), 0,
+               SLAB_HWCACHE_ALIGN, NULL, NULL);
+
+       if (!uhci_td_cachep)
+               return -ENOMEM;
+
+       name = kmalloc(10, GFP_KERNEL);
+       if (!name)
+               return -ENOMEM;
+
+       strcpy(name, "uhci_qh");
+
+       uhci_qh_cachep = kmem_cache_create(name,
+               sizeof(struct uhci_qh), 0,
+               SLAB_HWCACHE_ALIGN, NULL, NULL);
+
+       if (!uhci_qh_cachep)
+               return -ENOMEM;
 
        retval = -ENODEV;
        for (;;) {
-               dev = pci_find_class(PCI_CLASS_SERIAL_USB<<8, dev);
+               dev = pci_find_class(PCI_CLASS_SERIAL_USB << 8, dev);
                if (!dev)
                        break;
                /* Is it UHCI */
@@ -1917,6 +1866,59 @@ int uhci_init(void)
        return retval;
 }
 
+void uhci_cleanup(void)
+{
+       struct list_head *next, *tmp, *head = &uhci_list;
+       int ret, i;
+
+       tmp = head->next;
+       while (tmp != head) {
+               struct uhci *uhci = list_entry(tmp, struct uhci, uhci_list);
+               struct uhci_device *root_hub = usb_to_uhci(uhci->bus->root_hub);
+
+               next = tmp->next;
+
+               list_del(&uhci->uhci_list);
+               INIT_LIST_HEAD(&uhci->uhci_list);
+
+               /* Check if the process is still running */
+               ret = kill_proc(uhci->control_pid, 0, 1);
+               if (!ret) {
+                       int count = 10;
+
+                       uhci->control_continue = 0;
+                       wake_up(&uhci_configure);
+
+                       while (uhci->control_running && --count) {
+                               current->state = TASK_INTERRUPTIBLE;
+                               schedule_timeout(1);
+                       }
+
+                       if (!count)
+                               printk(KERN_ERR "uhci: giving up on killing uhci-control\n");
+               }
+
+               if (root_hub)
+                       for (i = 0; i < root_hub->usb->maxchild; i++)
+                               usb_disconnect(root_hub->usb->children + i);
+
+               usb_deregister_bus(uhci->bus);
+
+               reset_hc(uhci);
+               release_region(uhci->io_addr, 32);
+
+               release_uhci(uhci);
+
+               tmp = next;
+       }
+
+       if (kmem_cache_destroy(uhci_qh_cachep))
+               printk(KERN_INFO "uhci: not all QH's were freed\n");
+
+       if (kmem_cache_destroy(uhci_td_cachep))
+               printk(KERN_INFO "uhci: not all TD's were freed\n");
+}
+
 #ifdef MODULE
 int init_module(void)
 {
@@ -1928,5 +1930,7 @@ void cleanup_module(void)
 #ifdef CONFIG_APM
        apm_unregister_callback(&handle_apm_event);
 #endif
+       uhci_cleanup();
 }
 #endif //MODULE
+
index ea76df0cc1fa9fa82f61fec30393cc50cafc44f4..4f71f30cc7a982b7dc42823dc3f2306abb9a0f94 100644 (file)
 
 #define UHCI_NULL_DATA_SIZE    0x7ff   /* for UHCI controller TD */
 
+#define UHCI_PTR_BITS          0x000F
+#define UHCI_PTR_TERM          0x0001
+#define UHCI_PTR_QH            0x0002
+#define UHCI_PTR_DEPTH         0x0004
+
 struct uhci_qh {
-       unsigned int link;      /* Next queue */
-       unsigned int element;   /* Queue element pointer */
-       int inuse;              /* Inuse? */
-       struct uhci_qh *skel;   /* Skeleton head */
+       /* Hardware fields */
+       __u32 link;                             /* Next queue */
+       __u32 element;                          /* Queue element pointer */
+
+       /* Software fields */
+       atomic_t refcnt;                        /* Reference counting */
+       struct uhci_device *dev;                /* The owning device */
+       struct uhci_qh *skel;                   /* Skeleton head */
+
+       wait_queue_head_t wakeup;
 } __attribute__((aligned(16)));
 
 struct uhci_framelist {
-       unsigned int frame[1024];
+       __u32 frame[1024];
 } __attribute__((aligned(4096)));
 
+#define TD_CTRL_SPD            (1 << 29)       /* Short Packet Detect */
+#define TD_CTRL_LS             (1 << 26)       /* Low Speed Device */
+#define TD_CTRL_IOS            (1 << 25)       /* Isochronous Select */
+#define TD_CTRL_IOC            (1 << 24)       /* Interrupt on Complete */
+#define TD_CTRL_ACTIVE         (1 << 23)       /* TD Active */
+#define TD_CTRL_STALLED                (1 << 22)       /* TD Stalled */
+#define TD_CTRL_DBUFERR                (1 << 21)       /* Data Buffer Error */
+#define TD_CTRL_BABBLE         (1 << 20)       /* Babble Detected */
+#define TD_CTRL_NAK            (1 << 19)       /* NAK Received */
+#define TD_CTRL_CRCTIME                (1 << 18)       /* CTC/Time Out Error */
+#define TD_CTRL_BITSTUFF       (1 << 17)       /* Bit Stuff Error */
+
+#define uhci_ptr_to_virt(x)    bus_to_virt(x & ~UHCI_PTR_BITS)
+
+#define UHCI_TD_REMOVE         0x0001          /* Remove when done */
+
 /*
  * The documentation says "4 words for hardware, 4 words for software".
  *
@@ -77,7 +104,7 @@ struct uhci_framelist {
  * On 64-bit machines we probably want to take advantage of the fact that
  * hw doesn't really care about the size of the sw-only area.
  *
- * Alas, not anymore, we have more than 4 words of software, woops
+ * Alas, not anymore, we have more than 4 words for software, woops
  */
 struct uhci_td {
        /* Hardware fields */
@@ -87,25 +114,27 @@ struct uhci_td {
        __u32 buffer;
 
        /* Software fields */
+       unsigned int *backptr;          /* Where to remove this from.. */
        struct list_head irq_list;      /* Active interrupt list.. */
+
        usb_device_irq completed;       /* Completion handler routine */
-       unsigned int *backptr;          /* Where to remove this from.. */
        void *dev_id;
-       int inuse;                      /* Inuse? (b0) Remove (b1)*/
-       struct uhci_qh *qh;
-       struct uhci_td *first;
-       struct usb_device *dev;         /* the owning device */
-} __attribute__((aligned(32)));
+
+       atomic_t refcnt;                /* Reference counting */
+       struct uhci_device *dev;        /* The owning device */
+       struct uhci_qh *qh;             /* QH this TD is a part of (ignored for Isochronous) */
+       int flags;                      /* Remove, etc */
+} __attribute__((aligned(16)));
 
 struct uhci_iso_td {
-       int num;
-       char *data;
-       int maxsze;
+       int num;                        /* Total number of TD's */
+       char *data;                     /* Beginning of buffer */
+       int maxsze;                     /* Maximum size of each data block */
 
-       struct uhci_td *td;
+       struct uhci_td *td;             /* Pointer to first TD */
 
-       int frame;
-       int endframe;
+       int frame;                      /* Beginning frame */
+       int endframe;                   /* End frame */
 };
 
 /*
@@ -117,17 +146,21 @@ struct uhci_iso_td {
  */
 struct uhci;
 
+#if 0
 #define UHCI_MAXTD     64
 
 #define UHCI_MAXQH     16
+#endif
 
 /* The usb device part must be first! */
 struct uhci_device {
        struct usb_device       *usb;
 
        struct uhci             *uhci;
+#if 0
        struct uhci_qh          qh[UHCI_MAXQH];         /* These are the "common" qh's for each device */
        struct uhci_td          td[UHCI_MAXTD];
+#endif
 
        unsigned long           data[16];
 };
@@ -135,16 +168,6 @@ struct uhci_device {
 #define uhci_to_usb(uhci)      ((uhci)->usb)
 #define usb_to_uhci(usb)       ((struct uhci_device *)(usb)->hcpriv)
 
-/*
- * The root hub pre-allocated QH's and TD's have
- * some special global uses..
- */
-#if 0
-#define control_td     td              /* Td's 0-30 */
-/* This is only for the root hub's TD list */
-#define tick_td                td[31]
-#endif
-
 /*
  * There are various standard queues. We set up several different
  * queues for each of the three basic queue types: interrupt,
@@ -180,37 +203,25 @@ struct uhci_device {
  * transfers in QH's and all of their pictures don't have that either) but
  * other than that, that is what we're doing now
  *
- * To keep with Linus' nomenclature, this is called the qh skeleton. These
- * labels (below) are only signficant to the root hub's qh's
+ * And now we don't put Iso transfers in QH's, so we don't waste one on it
+ *
+ * To keep with Linus' nomenclature, this is called the QH skeleton. These
+ * labels (below) are only signficant to the root hub's QH's
  */
-#define skel_iso_qh            qh[0]
+#define UHCI_NUM_SKELQH                10
 
-#define skel_int2_qh           qh[1]
-#define skel_int4_qh           qh[2]
-#define skel_int8_qh           qh[3]
-#define skel_int16_qh          qh[4]
-#define skel_int32_qh          qh[5]
-#define skel_int64_qh          qh[6]
-#define skel_int128_qh         qh[7]
-#define skel_int256_qh         qh[8]
+#define skel_int2_qh           skelqh[0]
+#define skel_int4_qh           skelqh[1]
+#define skel_int8_qh           skelqh[2]
+#define skel_int16_qh          skelqh[3]
+#define skel_int32_qh          skelqh[4]
+#define skel_int64_qh          skelqh[5]
+#define skel_int128_qh         skelqh[6]
+#define skel_int256_qh         skelqh[7]
 
-#define skel_control_qh                qh[9]
+#define skel_control_qh                skelqh[8]
 
-#define skel_bulk0_qh          qh[10]
-#define skel_bulk1_qh          qh[11]
-#define skel_bulk2_qh          qh[12]
-#define skel_bulk3_qh          qh[13]
-
-/*
- * These are significant to the devices allocation of QH's
- */
-#if 0
-#define iso_qh                 qh[0]
-#define int_qh                 qh[1]   /* We have 2 "common" interrupt QH's */
-#define control_qh             qh[3]
-#define bulk_qh                        qh[4]   /* We have 4 "common" bulk QH's */
-#define extra_qh               qh[8]   /* The rest, anything goes */
-#endif
+#define skel_bulk_qh           skelqh[9]
 
 /*
  * This describes the full uhci information.
@@ -222,14 +233,20 @@ struct uhci {
        int irq;
        unsigned int io_addr;
 
+       int control_pid;
+       int control_running;
+       int control_continue;
+
+       struct list_head uhci_list;
+
        struct usb_bus *bus;
 
-#if 0
-       /* These are "standard" QH's for the entire bus */
-       struct uhci_qh qh[UHCI_MAXQH];
-#endif
+       struct uhci_qh skelqh[UHCI_NUM_SKELQH]; /* Skeleton QH's */
+
        struct uhci_framelist *fl;              /* Frame list */
        struct list_head interrupt_list;        /* List of interrupt-active TD's for this uhci */
+
+       struct uhci_td *ticktd;
 };
 
 /* needed for the debugging code */
index 3b5122e32c4e6bbb87b93adf143c40c3a901171e..fbe9ba12d3490124ee5306cb24d3774f747668de 100644 (file)
@@ -51,40 +51,49 @@ static LIST_HEAD(usb_bus_list);
 
 int usb_register(struct usb_driver *new_driver)
 {
-       struct list_head *tmp = usb_bus_list.next;
+       struct list_head *tmp;
+
+       printk("usbcore: Registering new driver %s\n", new_driver->name);
+
        /* Add it to the list of known drivers */
        list_add(&new_driver->driver_list, &usb_driver_list);
 
        /*
-         * We go through all existing devices, and see if any of them would
-         * be acceptable to the new driver.. This is done using a depth-first
-         * search for devices without a registered driver already, then 
+        * We go through all existing devices, and see if any of them would
+        * be acceptable to the new driver.. This is done using a depth-first
+        * search for devices without a registered driver already, then 
         * running 'probe' with each of the drivers registered on every one 
         * of these.
         */
-        while (tmp!= &usb_bus_list) {
-               struct usb_bus * bus = list_entry(tmp,struct
-                       usb_bus,bus_list);
-               tmp=tmp->next;  
+       tmp = usb_bus_list.next;
+       while (tmp != &usb_bus_list) {
+               struct usb_bus *bus = list_entry(tmp,struct usb_bus,bus_list);
+
+               tmp = tmp->next;
                usb_check_support(bus->root_hub);
-        }
+       }
        return 0;
 }
 
 void usb_deregister(struct usb_driver *driver)
 {
-      struct list_head *tmp = usb_bus_list.next;
-      /*first we remove the driver, to be sure it doesn't get used by
-       *another thread while we are stepping through removing entries
-       */
+       struct list_head *tmp;
+
+       printk("usbcore: Deregistering driver %s\n", driver->name);
+
+       /*
+        * first we remove the driver, to be sure it doesn't get used by
+        * another thread while we are stepping through removing entries
+        */
        list_del(&driver->driver_list);
-      printk("usbcore: deregistering driver\n");
-      while (tmp!= &usb_bus_list) {
-              struct usb_bus * bus = list_entry(tmp,struct 
-                       usb_bus,bus_list);
-              tmp=tmp->next;
-              usb_driver_purge(driver,bus->root_hub);
-      }
+
+       tmp = usb_bus_list.next;
+       while (tmp != &usb_bus_list) {
+               struct usb_bus *bus = list_entry(tmp,struct usb_bus,bus_list);
+
+               tmp = tmp->next;
+               usb_driver_purge(driver, bus->root_hub);
+       }
 }
 
 /* This function is part of a depth-first search down the device tree,
@@ -93,45 +102,82 @@ void usb_deregister(struct usb_driver *driver)
 void usb_driver_purge(struct usb_driver *driver,struct usb_device *dev)
 {
        int i;
-       if (dev==NULL){
-               printk("null device being passed in!!!\n");
-               return;
-       }
-       for (i=0;i<USB_MAXCHILDREN;i++)
-               if (dev->children[i]!=NULL)
-                       usb_driver_purge(driver,dev->children[i]);
-       /*now we check this device*/
-       if(dev->driver==driver) {
-               /*
-                * Note: this is not the correct way to do this, this
-                * uninitializes and reinitializes EVERY driver
-                */
-               printk("disconnecting driverless device\n");
-               dev->driver->disconnect(dev);
-               dev->driver=NULL;
-               /* This will go back through the list looking for a driver
-                * that can handle the device
-               */
-               usb_device_descriptor(dev);
-      }
+
+       if (!dev) {
+               printk(KERN_ERR "usbcore: null device being purged!!!\n");
+               return;
+       }
+
+       for (i=0; i<USB_MAXCHILDREN; i++)
+               if (dev->children[i])
+                       usb_driver_purge(driver, dev->children[i]);
+
+       /* now we check this device */
+       if (dev->driver == driver) {
+               /*
+                * Note: this is not the correct way to do this, this
+                * uninitializes and reinitializes EVERY driver
+                */
+               printk(KERN_INFO "disconnect driverless device %d\n",
+                       dev->devnum);
+               dev->driver->disconnect(dev);
+               dev->driver = NULL;
+
+               /*
+                * This will go back through the list looking for a driver
+                * that can handle the device
+                */
+               usb_find_driver(dev);
+       }
 }
 
 /*
  * New functions for (de)registering a controller
  */
+struct usb_bus *usb_alloc_bus(struct usb_operations *op)
+{
+       struct usb_bus *bus;
+
+       bus = kmalloc(sizeof(*bus), GFP_KERNEL);
+       if (!bus)
+               return NULL;
+
+       memset(&bus->devmap, 0, sizeof(struct usb_devmap));
+
+       bus->op = op;
+       bus->root_hub = NULL;
+       bus->hcpriv = NULL;
+
+       INIT_LIST_HEAD(&bus->bus_list);
+
+       return bus;
+}
+
+void usb_free_bus(struct usb_bus *bus)
+{
+       if (!bus)
+               return;
+
+       if (bus->bus_list.next != &bus->bus_list)
+               printk(KERN_ERR "usbcore: freeing non-empty bus\n");
+
+       kfree(bus);
+}
+
 void usb_register_bus(struct usb_bus *new_bus)
 {
-      /* Add it to the list of buses */
-      list_add(&new_bus->bus_list, &usb_bus_list);
-      printk("New bus registered\n");
+       /* Add it to the list of buses */
+       list_add(&new_bus->bus_list, &usb_bus_list);
+       printk("New USB bus registered\n");
 }
 
 void usb_deregister_bus(struct usb_bus *bus)
 {
-        /* NOTE: make sure that all the devices are removed by the
-         * controller code, as well as having it call this when cleaning
+       /*
+        * NOTE: make sure that all the devices are removed by the
+        * controller code, as well as having it call this when cleaning
         * itself up
-         */
+        */
        list_del(&bus->bus_list);
 }
 
@@ -141,18 +187,20 @@ void usb_deregister_bus(struct usb_bus *bus)
  */
 void usb_check_support(struct usb_device *dev)
 {
-      int i;
-      if (dev==NULL)
-      {
-              printk("null device being passed in!!!\n");
-              return;
-      }
-      for (i=0;i<USB_MAXCHILDREN;i++)
-              if (dev->children[i]!=NULL)
-                      usb_check_support(dev->children[i]);
-      /*now we check this device*/
-      if (dev->driver==NULL)
-             usb_device_descriptor(dev);
+       int i;
+
+       if (!dev) {
+               printk(KERN_ERR "usbcore: null device being checked!!!\n");
+               return;
+       }
+
+       for (i=0; i<USB_MAXCHILDREN; i++)
+               if (dev->children[i])
+                       usb_check_support(dev->children[i]);
+
+       /* now we check this device */
+       if (!dev->driver && dev->devnum > 0)
+               usb_find_driver(dev);
 }
 /*
  * This entrypoint gets called for each new device.
@@ -161,7 +209,7 @@ void usb_check_support(struct usb_device *dev)
  * looking for one that will accept this device as
  * his..
  */
-int usb_device_descriptor(struct usb_device *dev)
+int usb_find_driver(struct usb_device *dev)
 {
        struct list_head *tmp = usb_driver_list.next;
 
@@ -174,6 +222,7 @@ int usb_device_descriptor(struct usb_device *dev)
                dev->driver = driver;
                return 1;
        }
+
        /*
         * Ok, no driver accepted the device, so show the info
         * for debugging..
@@ -243,8 +292,7 @@ static int usb_check_descriptor(unsigned char *ptr, int len, unsigned char desct
        if (len <= 0)
                return -1;
 
-       if (n_len < 2 || n_len > len)
-       {
+       if (n_len < 2 || n_len > len) {
                int i;
                printk("Short descriptor. (%d, %d):\n", len, n_len);
                for (i = 0; i < len; ++i)
@@ -272,8 +320,7 @@ static int usb_parse_endpoint(struct usb_device *dev, struct usb_endpoint_descri
        parsed += ptr[parsed];
        len -= parsed;
 
-       while((i = usb_check_descriptor(ptr+parsed, len, 0x25))>=0)
-       {
+       while((i = usb_check_descriptor(ptr+parsed, len, 0x25)) >= 0) {
                usb_audio_endpoint(endpoint, ptr+parsed+i);
                len -= ptr[parsed+i];
                parsed += ptr[parsed+i];
@@ -295,23 +342,20 @@ static int usb_parse_interface(struct usb_device *dev, struct usb_interface_desc
        len -= ptr[parsed];
        parsed += ptr[parsed];
 
-       while((i=usb_check_descriptor(ptr+parsed, len, 0x24))>=0)
-       {
+       while((i=usb_check_descriptor(ptr+parsed, len, 0x24)) >= 0) {
                usb_audio_interface(interface, ptr+parsed+i);
                len -= ptr[parsed+i];
                parsed += ptr[parsed+i];
        }
        
-       if (interface->bNumEndpoints > USB_MAXENDPOINTS)
-       {
+       if (interface->bNumEndpoints > USB_MAXENDPOINTS) {
                printk(KERN_WARNING "usb: too many endpoints.\n");
                return -1;
        }
 
        interface->endpoint = (struct usb_endpoint_descriptor *)
                kmalloc(interface->bNumEndpoints * sizeof(struct usb_endpoint_descriptor), GFP_KERNEL);
-       if(interface->endpoint==NULL)
-       {
+       if (!interface->endpoint) {
                printk(KERN_WARNING "usb: out of memory.\n");
                return -1;      
        }
@@ -323,7 +367,8 @@ static int usb_parse_interface(struct usb_device *dev, struct usb_interface_desc
 //                     len -= 9;
 //             }
                retval = usb_parse_endpoint(dev, interface->endpoint + i, ptr + parsed, len);
-               if (retval < 0) return retval;
+               if (retval < 0)
+                       return retval;
                parsed += retval;
                len -= retval;
        }
@@ -345,8 +390,7 @@ static int usb_parse_config(struct usb_device *dev, struct usb_config_descriptor
        parsed += *ptr;
        le16_to_cpus(&config->wTotalLength);
 
-       if (config->bNumInterfaces > USB_MAXINTERFACES)
-       {
+       if (config->bNumInterfaces > USB_MAXINTERFACES) {
                printk(KERN_WARNING "usb: too many interfaces.\n");
                return -1;
 
@@ -354,7 +398,7 @@ static int usb_parse_config(struct usb_device *dev, struct usb_config_descriptor
 
        config->altsetting = (struct usb_alternate_setting *)
                kmalloc(USB_MAXALTSETTING * sizeof(struct usb_alternate_setting), GFP_KERNEL);
-       if (config->altsetting == NULL) {
+       if (!config->altsetting) {
                printk(KERN_WARNING "usb: out of memory.\n");
                return -1;
        }
@@ -363,8 +407,7 @@ static int usb_parse_config(struct usb_device *dev, struct usb_config_descriptor
 
        config->altsetting->interface = (struct usb_interface_descriptor *)
                kmalloc(config->bNumInterfaces * sizeof(struct usb_interface_descriptor), GFP_KERNEL);
-       if(config->altsetting->interface==NULL)
-       {
+       if (!config->altsetting->interface) {
                printk(KERN_WARNING "usb: out of memory.\n");
                return -1;      
        }
@@ -384,26 +427,26 @@ static int usb_parse_config(struct usb_device *dev, struct usb_config_descriptor
 
        // now parse for additional alternate settings
        for (j = 1; j < USB_MAXALTSETTING; j++) {
-         retval = usb_expect_descriptor(ptr + parsed, len, USB_DT_INTERFACE, 9);
-         if (retval) 
-           break;
-         config->num_altsetting++;
-         as = config->altsetting + j;
-         as->interface = (struct usb_interface_descriptor *)
-           kmalloc(config->bNumInterfaces * sizeof(struct usb_interface_descriptor), GFP_KERNEL);
-         if (as->interface == NULL) {
-           printk(KERN_WARNING "usb: out of memory.\n");
-           return -1;
-         }
-         memset(as->interface, 0, config->bNumInterfaces * sizeof(struct usb_interface_descriptor));
-         for (i = 0; i < config->bNumInterfaces; i++) {
-           retval = usb_parse_interface(dev, as->interface + i, 
+               retval = usb_expect_descriptor(ptr + parsed, len, USB_DT_INTERFACE, 9);
+               if (retval) 
+                       break;
+               config->num_altsetting++;
+               as = config->altsetting + j;
+               as->interface = (struct usb_interface_descriptor *)
+                       kmalloc(config->bNumInterfaces * sizeof(struct usb_interface_descriptor), GFP_KERNEL);
+               if (!as->interface) {
+                       printk(KERN_WARNING "usb: out of memory.\n");
+                       return -1;
+               }
+               memset(as->interface, 0, config->bNumInterfaces * sizeof(struct usb_interface_descriptor));
+               for (i = 0; i < config->bNumInterfaces; i++) {
+                       retval = usb_parse_interface(dev, as->interface + i, 
                                         ptr + parsed, len);
-           if (retval < 0)
-             return parsed;
-           parsed += retval;
-           len -= retval;
-         }
+                       if (retval < 0)
+                               return parsed;
+                       parsed += retval;
+                       len -= retval;
+               }
        }
        return parsed;
 }
@@ -413,16 +456,14 @@ int usb_parse_configuration(struct usb_device *dev, void *__buf, int bytes)
        int i;
        unsigned char *ptr = __buf;
 
-       if (dev->descriptor.bNumConfigurations > USB_MAXCONFIG)
-       {
+       if (dev->descriptor.bNumConfigurations > USB_MAXCONFIG) {
                printk(KERN_WARNING "usb: too many configurations.\n");
                return -1;
        }
 
        dev->config = (struct usb_config_descriptor *)
                kmalloc(dev->descriptor.bNumConfigurations * sizeof(struct usb_config_descriptor), GFP_KERNEL);
-       if(dev->config==NULL)
-       {
+       if (!dev->config) {
                printk(KERN_WARNING "usb: out of memory.\n");
                return -1;      
        }
@@ -446,21 +487,18 @@ void usb_destroy_configuration(struct usb_device *dev)
        struct usb_alternate_setting *as;
        struct usb_interface_descriptor *ifp;
        
-       if(dev->config==NULL)
+       if (!dev->config)
                return;
 
-       for(c = 0; c < dev->descriptor.bNumConfigurations; c++)
-       {
+       for (c = 0; c < dev->descriptor.bNumConfigurations; c++) {
                cf = &dev->config[c];
-               if (cf->altsetting == NULL)
+               if (!cf->altsetting)
                        break;
-               for (a = 0; a < cf->num_altsetting; a++)
-               {
+               for (a = 0; a < cf->num_altsetting; a++) {
                        as = &cf->altsetting[a];
                        if (as->interface == NULL)
                                break;
-                       for(i=0;i<cf->bNumInterfaces;i++)
-                       {
+                       for(i=0;i<cf->bNumInterfaces;i++) {
                                ifp = &as->interface[i];
                                if(ifp->endpoint==NULL)
                                       break;
@@ -604,45 +642,6 @@ int usb_get_device_descriptor(struct usb_device *dev)
        return ret;
 }
 
-int usb_get_hub_descriptor(struct usb_device *dev, void *data, int size)
-{
-       devrequest dr;
-
-       dr.requesttype = USB_RT_HUB | 0x80;
-       dr.request = USB_REQ_GET_DESCRIPTOR;
-       dr.value = (USB_DT_HUB << 8);
-       dr.index = 0;
-       dr.length = size;
-
-       return dev->bus->op->control_msg(dev, usb_rcvctrlpipe(dev,0), &dr, data, size);
-}
-
-int usb_clear_port_feature(struct usb_device *dev, int port, int feature)
-{
-       devrequest dr;
-
-       dr.requesttype = USB_RT_PORT;
-       dr.request = USB_REQ_CLEAR_FEATURE;
-       dr.value = feature;
-       dr.index = port;
-       dr.length = 0;
-
-       return dev->bus->op->control_msg(dev, usb_sndctrlpipe(dev,0), &dr, NULL, 0);
-}
-
-int usb_set_port_feature(struct usb_device *dev, int port, int feature)
-{
-       devrequest dr;
-
-       dr.requesttype = USB_RT_PORT;
-       dr.request = USB_REQ_SET_FEATURE;
-       dr.value = feature;
-       dr.index = port;
-       dr.length = 0;
-
-       return dev->bus->op->control_msg(dev, usb_sndctrlpipe(dev,0), &dr, NULL, 0);
-}
-
 int usb_get_status (struct usb_device *dev, int type, int target, void *data)
 {
        devrequest dr;
@@ -656,32 +655,6 @@ int usb_get_status (struct usb_device *dev, int type, int target, void *data)
        return dev->bus->op->control_msg (dev, usb_rcvctrlpipe (dev,0), &dr, data, 2);
 }
 
-int usb_get_hub_status(struct usb_device *dev, void *data)
-{
-       devrequest dr;
-
-       dr.requesttype = USB_RT_HUB | 0x80;
-       dr.request = USB_REQ_GET_STATUS;
-       dr.value = 0;
-       dr.index = 0;
-       dr.length = 4;
-
-       return dev->bus->op->control_msg(dev, usb_rcvctrlpipe(dev,0), &dr, data, 4);
-}
-
-int usb_get_port_status(struct usb_device *dev, int port, void *data)
-{
-       devrequest dr;
-
-       dr.requesttype = USB_RT_PORT | 0x80;
-       dr.request = USB_REQ_GET_STATUS;
-       dr.value = 0;
-       dr.index = port;
-       dr.length = 4;
-
-       return dev->bus->op->control_msg(dev, usb_rcvctrlpipe(dev,0), &dr, data, 4);
-}
-
 int usb_get_protocol(struct usb_device *dev)
 {
        unsigned char buf[8];
@@ -743,6 +716,7 @@ static void usb_set_maxpacket(struct usb_device *dev)
                struct usb_interface_descriptor *ip = &as->interface[i];
                struct usb_endpoint_descriptor *ep = ip->endpoint;
                int e;
+
                for (e=0; e<ip->bNumEndpoints; e++) {
                        dev->epmaxpacket[ep[e].bEndpointAddress & 0x0f] =
                                ep[e].wMaxPacketSize;
@@ -768,9 +742,8 @@ int usb_clear_halt(struct usb_device *dev, int endp)
        result = dev->bus->op->control_msg(dev, usb_sndctrlpipe(dev,0), &dr, NULL, 0);
 
        /* dont clear if failed */
-       if (result) {
+       if (result)
            return result;
-       }
 
 #if 1  /* lets be really tough */
        dr.requesttype = 0x80 | USB_RT_ENDPOINT;
@@ -780,12 +753,10 @@ int usb_clear_halt(struct usb_device *dev, int endp)
 
        result = dev->bus->op->control_msg(dev, usb_rcvctrlpipe(dev,0), &dr, &status, 2);
 
-       if (result) {
+       if (result)
            return result;
-       }
-       if (status & 1) {
+       if (status & 1)
            return 1;           /* still halted */
-       }
 #endif
        usb_endpoint_running(dev, endp & 0x0f);
 
@@ -1006,38 +977,27 @@ char *usb_string(struct usb_device *dev, int index)
  * and is in the default state. We need to identify the thing and
  * get the ball rolling..
  */
-void usb_new_device(struct usb_device *dev)
+int usb_new_device(struct usb_device *dev)
 {
-       int addr, i;
+       int addr;
 
-       printk("USB new device connect, assigned device number %d\n",
+       printk(KERN_INFO "USB new device connect, assigned device number %d\n",
                dev->devnum);
 
        dev->maxpacketsize = 0;         /* Default to 8 byte max packet size */
         dev->epmaxpacket[0] = 8;
 
+       /* We still haven't set the Address yet */
        addr = dev->devnum;
        dev->devnum = 0;
 
-#if 1
        /* Slow devices */
-       for (i = 0; i < 5; i++) {
-               if (!usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, 8))
-                       break;
-
-               printk("get_descriptor failed, waiting\n");
-               wait_ms(200);
-       }
-       if (i == 5) {
-               printk("giving up\n");
-               return;
+       if (usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, 8)) {
+               printk(KERN_ERR "USB device not responding, giving up\n");
+               dev->devnum = -1;
+               return 1;
        }
-#endif
-
 
-#if 0
-       printk("maxpacketsize: %d\n", dev->descriptor.bMaxPacketSize0);
-#endif
        dev->epmaxpacket[0] = dev->descriptor.bMaxPacketSize0;
        switch (dev->descriptor.bMaxPacketSize0) {
                case 8: dev->maxpacketsize = 0; break;
@@ -1045,36 +1005,29 @@ void usb_new_device(struct usb_device *dev)
                case 32: dev->maxpacketsize = 2; break;
                case 64: dev->maxpacketsize = 3; break;
        }
-#if 0
-       printk("dev->mps: %d\n", dev->maxpacketsize);
-#endif
 
        dev->devnum = addr;
 
-#if 1
        if (usb_set_address(dev)) {
-               printk("Unable to set address\n");
-               /* FIXME: We should disable the port */
-               return;
+               printk(KERN_ERR "USB device not accepting new address\n");
+               dev->devnum = -1;
+               return 1;
        }
-#else
-       usb_set_address(dev);
-#endif
 
        wait_ms(10);    /* Let the SET_ADDRESS settle */
 
        if (usb_get_device_descriptor(dev)) {
-               printk("Unable to get device descriptor\n");
-               return;
+               printk(KERN_ERR "Unable to get device descriptor\n");
+               dev->devnum = -1;
+               return 1;
        }
 
        if (usb_get_configuration(dev)) {
-               printk("Unable to get configuration\n");
-               return;
+               printk(KERN_ERR "Unable to get configuration\n");
+               dev->devnum = -1;
+               return 1;
        }
 
-       /* usb_get_stringtable(dev); */
-
        dev->actconfig = dev->config;
        dev->ifnum = 0;
        usb_set_maxpacket(dev);
@@ -1083,20 +1036,16 @@ void usb_new_device(struct usb_device *dev)
        usb_show_string(dev, "Product", dev->descriptor.iProduct);
        usb_show_string(dev, "SerialNumber", dev->descriptor.iSerialNumber);
 
-#if 0
-       printk("Vendor: %X\n", dev->descriptor.idVendor);
-       printk("Product: %X\n", dev->descriptor.idProduct);
-#endif
-
-       if (usb_device_descriptor(dev)==0)
-       {
+       if (!usb_find_driver(dev)) {
                /*
                 * Ok, no driver accepted the device, so show the info for
                 * debugging
                 */
-               printk ("Unknown new USB device:\n");
+               printk(KERN_DEBUG "Unknown new USB device:\n");
                usb_show_device(dev);
        }
+
+       return 0;
 }
 
 void* usb_request_irq(struct usb_device *dev, unsigned int pipe, usb_device_irq handler, int period, void *dev_id)
@@ -1104,17 +1053,16 @@ void* usb_request_irq(struct usb_device *dev, unsigned int pipe, usb_device_irq
        return dev->bus->op->request_irq(dev, pipe, handler, period, dev_id);
 }
 
-void* usb_request_bulk(struct usb_device *dev, unsigned int pipe, usb_device_irq handler, void * data, int len, void *dev_id)
+void *usb_request_bulk(struct usb_device *dev, unsigned int pipe, usb_device_irq handler, void *data, int len, void *dev_id)
 {
        return dev->bus->op->request_bulk(dev, pipe, handler, data, len, dev_id);
 }
 
-int usb_terminate_bulk(struct usb_device *dev, voidfirst)
+int usb_terminate_bulk(struct usb_device *dev, void *first)
 {
        return dev->bus->op->terminate_bulk(dev, first);
 }
 
-
 void *usb_allocate_isochronous (struct usb_device *usb_dev, unsigned int pipe, void *data, int len, int maxsze, usb_device_irq completed, void *dev_id)
 {
        return usb_dev->bus->op->alloc_isoc (usb_dev, pipe, data, len, maxsze, completed, dev_id);
index 3d1b58c03b8ac8095d034a05aac694886575be11..bccde88c89c616fe36037d5af1b43f7bd9c11d63 100644 (file)
@@ -290,8 +290,9 @@ struct usb_operations {
        int (*bulk_msg)(struct usb_device *, unsigned int, void *, int,unsigned long *);
        void* (*request_irq)(struct usb_device *, unsigned int, usb_device_irq, int, void *);
        int (*release_irq)(void* handle);
-       void* (*request_bulk)(struct usb_device *, unsigned int, usb_device_irq, void *, int, void *);
-       int (*terminate_bulk)(struct usb_device *, void*);
+       void *(*request_bulk)(struct usb_device *, unsigned int, usb_device_irq,
+ void *, int, void *);
+       int (*terminate_bulk)(struct usb_device *, void *);
        void *(*alloc_isoc)(struct usb_device *usb_dev, unsigned int pipe, void *data, int len, int maxsze, usb_device_irq completed, void *dev_id);
        void (*delete_isoc)(struct usb_device *dev, void *_isodesc);
        int (*sched_isoc)(struct usb_device *usb_dev, void *_isodesc, void *_pisodesc);
@@ -348,20 +349,22 @@ struct usb_device {
 extern int usb_register(struct usb_driver *);
 extern void usb_deregister(struct usb_driver *);
 
+extern struct usb_bus *usb_alloc_bus(struct usb_operations *);
+extern void usb_free_bus(struct usb_bus *);
 extern void usb_register_bus(struct usb_bus *);
 extern void usb_deregister_bus(struct usb_bus *);
 
 extern void* usb_request_irq(struct usb_device *, unsigned int, usb_device_irq, int, void *);
 extern int usb_release_irq(struct usb_device *dev, void *handle);
 
-extern voidusb_request_bulk(struct usb_device *, unsigned int, usb_device_irq, void *, int, void *);
-extern int usb_terminate_bulk(struct usb_device *, void*);
+extern void *usb_request_bulk(struct usb_device *, unsigned int, usb_device_irq, void *, int, void *);
+extern int usb_terminate_bulk(struct usb_device *, void *);
 
 extern void usb_init_root_hub(struct usb_device *dev);
 extern void usb_connect(struct usb_device *dev);
 extern void usb_disconnect(struct usb_device **);
 
-extern int usb_device_descriptor(struct usb_device *dev);
+extern int usb_find_driver(struct usb_device *dev);
 void usb_check_support(struct usb_device *);
 void usb_driver_purge(struct usb_driver *,struct usb_device *);
 extern int  usb_parse_configuration(struct usb_device *dev, void *buf, int len);
@@ -458,17 +461,12 @@ static inline unsigned int __default_pipe(struct usb_device *dev)
 /*
  * Send and receive control messages..
  */
-void usb_new_device(struct usb_device *dev);
+int usb_new_device(struct usb_device *dev);
 int usb_set_address(struct usb_device *dev);
 int usb_get_descriptor(struct usb_device *dev, unsigned char desctype, unsigned
 char descindex, void *buf, int size);
 int usb_get_device_descriptor(struct usb_device *dev);
-int usb_get_hub_descriptor(struct usb_device *dev, void *data, int size);
-int usb_clear_port_feature(struct usb_device *dev, int port, int feature);
-int usb_set_port_feature(struct usb_device *dev, int port, int feature);
 int usb_get_status (struct usb_device *dev, int type, int target, void *data);
-int usb_get_hub_status(struct usb_device *dev, void *data);
-int usb_get_port_status(struct usb_device *dev, int port, void *data);
 int usb_get_protocol(struct usb_device *dev);
 int usb_set_protocol(struct usb_device *dev, int protocol);
 int usb_set_interface(struct usb_device *dev, int interface, int alternate);
diff --git a/drivers/usb/uss720.c b/drivers/usb/uss720.c
new file mode 100644 (file)
index 0000000..d88d204
--- /dev/null
@@ -0,0 +1,678 @@
+/*****************************************************************************/
+
+/*
+ *     uss720.c  --  USS720 USB Parport Cable.
+ *
+ *     Copyright (C) 1999
+ *          Thomas Sailer (sailer@ife.ee.ethz.ch)
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ *     You should have received a copy of the GNU General Public License
+ *     along with this program; if not, write to the Free Software
+ *     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *  Based on parport_pc.c
+ *
+ *  History:
+ *   0.1  04.08.99  Created
+ *   0.2  07.08.99  Some fixes mainly suggested by Tim Waugh
+ *                  Interrupt handling currently disabled because
+ *                  usb_request_irq crashes somewhere within ohci.c
+ *                  for no apparent reason (that is for me, anyway)
+ *                  ECP currently untested
+ *
+ */
+
+/*****************************************************************************/
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/socket.h>
+#include <linux/parport.h>
+#include <linux/init.h>
+
+#include "usb.h"
+
+/* --------------------------------------------------------------------- */
+
+struct parport_uss720_private {
+       struct usb_device *usbdev;
+       void *irqhandle;
+        unsigned char reg[7];  /* USB registers */
+};
+
+/* --------------------------------------------------------------------- */
+
+static int get_1284_register(struct parport *pp, unsigned char reg, unsigned char *val)
+{
+       struct parport_uss720_private *priv = pp->private_data;
+       struct usb_device *usbdev = priv->usbdev;
+       static const unsigned char regindex[9] = {
+               4, 0, 1, 5, 5, 0, 2, 3, 6
+       };
+        devrequest dr;
+        int ret;
+
+       if (!usbdev)
+               return -1;
+        dr.requesttype = 0xc0;
+        dr.request = 3;
+        dr.value = ((unsigned int)reg) << 8;
+        dr.index = 0;
+        dr.length = 7;
+        ret = usbdev->bus->op->control_msg(usbdev, usb_rcvctrlpipe(usbdev,0), &dr, priv->reg, 7);
+        if (ret) {
+                printk(KERN_DEBUG "uss720: get_1284_register(%d) failed, status 0x%x\n",
+                      (unsigned int)reg, ret);
+        } else {
+#if 0
+                printk(KERN_DEBUG "uss720: get_1284_register(%d) return %02x %02x %02x %02x %02x %02x %02x\n",
+                      (unsigned int)reg, (unsigned int)priv->reg[0], (unsigned int)priv->reg[1],
+                      (unsigned int)priv->reg[2], (unsigned int)priv->reg[3], (unsigned int)priv->reg[4],
+                      (unsigned int)priv->reg[5], (unsigned int)priv->reg[6]);
+#endif
+               /* if nAck interrupts are enabled and we have an interrupt, call the interrupt procedure */
+               if (priv->reg[2] & priv->reg[1] & 0x10)
+                       parport_generic_irq(0, pp, NULL);
+       }
+       if (val)
+               *val = priv->reg[(reg >= 9) ? 0 : regindex[reg]];
+       return ret;
+}
+
+static int set_1284_register(struct parport *pp, unsigned char reg, unsigned char val)
+{
+       struct parport_uss720_private *priv = pp->private_data;
+       struct usb_device *usbdev = priv->usbdev;
+        devrequest dr;
+        int ret;
+
+       if (!usbdev)
+               return -1;
+        dr.requesttype = 0x40;
+        dr.request = 4;
+        dr.value = (((unsigned int)reg) << 8) | val;
+        dr.index = 0;
+        dr.length = 0;
+        ret = usbdev->bus->op->control_msg(usbdev, usb_sndctrlpipe(usbdev,0), &dr, NULL, 0);
+        if (ret) {
+                printk(KERN_DEBUG "uss720: set_1284_register(%u,0x%02x) failed, status 0x%x\n", 
+                      (unsigned int)reg, (unsigned int)val, ret);
+        } else {
+#if 0
+                printk(KERN_DEBUG "uss720: set_1284_register(%u,0x%02x)\n", 
+                      (unsigned int)reg, (unsigned int)val);
+#endif
+        }
+       return ret;
+}
+
+/* --------------------------------------------------------------------- */
+
+/* ECR modes */
+#define ECR_SPP 00
+#define ECR_PS2 01
+#define ECR_PPF 02
+#define ECR_ECP 03
+#define ECR_EPP 04
+
+/* Safely change the mode bits in the ECR */
+static int change_mode(struct parport *pp, int m)
+{
+       struct parport_uss720_private *priv = pp->private_data;
+       int mode;
+
+       if (get_1284_register(pp, 6, NULL))
+               return -EIO;
+       /* Bits <7:5> contain the mode. */
+       mode = (priv->reg[2] >> 5) & 0x7;
+       if (mode == m)
+               return 0;
+       /* We have to go through mode 000 or 001 */
+       if (mode > ECR_PS2 && m > ECR_PS2)
+               if (change_mode(pp, ECR_PS2))
+                       return -EIO;
+
+       if (m <= ECR_PS2 && !(priv->reg[1] & 0x20)) {
+               /* This mode resets the FIFO, so we may
+                * have to wait for it to drain first. */
+               long expire = jiffies + pp->physport->cad->timeout;
+               switch (mode) {
+               case ECR_PPF: /* Parallel Port FIFO mode */
+               case ECR_ECP: /* ECP Parallel Port mode */
+                       /* Poll slowly. */
+                       for (;;) {
+                               if (get_1284_register(pp, 6, NULL))
+                                       return -EIO;
+                               if (priv->reg[2] & 0x01)
+                                       break;
+                               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. */
+       if (set_1284_register(pp, 6, m << 5))
+               return -EIO;
+       return 0;
+}
+
+/*
+ * Clear TIMEOUT BIT in EPP MODE
+ */
+static int clear_epp_timeout(struct parport *pp)
+{
+       unsigned char stat;
+
+       if (get_1284_register(pp, 1, &stat))
+               return 1;
+       return stat & 1;
+}
+
+/*
+ * Access functions.
+ */
+
+static void parport_uss720_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+}
+
+static int uss720_irq(int usbstatus, void *buffer, int len, void *dev_id)
+{
+       struct parport *pp = (struct parport *)dev_id;
+       struct parport_uss720_private *priv = pp->private_data; 
+
+       if (usbstatus != USB_ST_NOERROR || len < 4 || !buffer)
+               return 1;
+       memcpy(priv->reg, buffer, 4);
+       /* if nAck interrupts are enabled and we have an interrupt, call the interrupt procedure */
+       if (priv->reg[2] & priv->reg[1] & 0x10)
+               parport_generic_irq(0, pp, NULL);
+       return 1;
+}
+
+static void parport_uss720_write_data(struct parport *pp, unsigned char d)
+{
+       set_1284_register(pp, 0, d);
+}
+
+static unsigned char parport_uss720_read_data(struct parport *pp)
+{
+       unsigned char ret;
+
+       if (get_1284_register(pp, 0, &ret))
+               return 0;
+       return ret;
+}
+
+static void parport_uss720_write_control(struct parport *pp, unsigned char d)
+{
+       struct parport_uss720_private *priv = pp->private_data; 
+
+       d = (d & 0xf) | (priv->reg[1] & 0xf0);
+       if (set_1284_register(pp, 2, d))
+               return;
+       priv->reg[1] = d;
+}
+
+static unsigned char parport_uss720_read_control(struct parport *pp)
+{
+       struct parport_uss720_private *priv = pp->private_data; 
+       return priv->reg[1] & 0xf; /* Use soft copy */
+}
+
+static unsigned char parport_uss720_frob_control(struct parport *pp, unsigned char mask, unsigned char val)
+{
+       struct parport_uss720_private *priv = pp->private_data; 
+       unsigned char d;
+
+       mask &= 0x0f;
+       val &= 0x0f;
+       d = (priv->reg[1] & (~mask)) ^ val;
+       if (set_1284_register(pp, 2, d))
+               return 0;
+       priv->reg[1] = d;
+       return d & 0xf;
+}
+
+static unsigned char parport_uss720_read_status(struct parport *pp)
+{
+       unsigned char ret;
+
+       if (get_1284_register(pp, 1, &ret))
+               return 0;
+       return ret & 0xf8;
+}
+
+static void parport_uss720_disable_irq(struct parport *pp)
+{
+       struct parport_uss720_private *priv = pp->private_data; 
+       unsigned char d;
+
+       d = priv->reg[1] & ~0x10;
+       if (set_1284_register(pp, 2, d))
+               return;
+       priv->reg[1] = d;
+}
+
+static void parport_uss720_enable_irq(struct parport *pp)
+{
+       struct parport_uss720_private *priv = pp->private_data; 
+       unsigned char d;
+
+       d = priv->reg[1] | 0x10;
+       if (set_1284_register(pp, 2, d))
+               return;
+       priv->reg[1] = d;
+}
+
+static void parport_uss720_data_forward (struct parport *pp)
+{
+       struct parport_uss720_private *priv = pp->private_data; 
+       unsigned char d;
+
+       d = priv->reg[1] & ~0x20;
+       if (set_1284_register(pp, 2, d))
+               return;
+       priv->reg[1] = d;
+}
+
+static void parport_uss720_data_reverse (struct parport *pp)
+{
+       struct parport_uss720_private *priv = pp->private_data; 
+       unsigned char d;
+
+       d = priv->reg[1] | 0x20;
+       if (set_1284_register(pp, 2, d))
+               return;
+       priv->reg[1] = d;
+}
+
+static void parport_uss720_init_state(struct pardevice *dev, struct parport_state *s)
+{
+       s->u.pc.ctr = 0xc | (dev->irq_func ? 0x10 : 0x0);
+       s->u.pc.ecr = 0x24;
+}
+
+static void parport_uss720_save_state(struct parport *pp, struct parport_state *s)
+{
+       struct parport_uss720_private *priv = pp->private_data; 
+
+       if (get_1284_register(pp, 2, NULL))
+               return;
+       s->u.pc.ctr = priv->reg[1];
+       s->u.pc.ecr = priv->reg[2];
+}
+
+static void parport_uss720_restore_state(struct parport *pp, struct parport_state *s)
+{
+       set_1284_register(pp, 2, s->u.pc.ctr);
+       set_1284_register(pp, 6, s->u.pc.ecr);
+       get_1284_register(pp, 2, NULL);
+}
+
+static size_t parport_uss720_epp_read_data(struct parport *pp, void *buf, size_t length, int flags)
+{
+       struct parport_uss720_private *priv = pp->private_data; 
+       size_t got = 0;
+
+       if (change_mode(pp, ECR_EPP))
+               return 0;
+       for (; got < length; got++) {
+               if (get_1284_register(pp, 4, (char *)buf))
+                       break;
+               ((char*)buf)++;
+               if (priv->reg[0] & 0x01) {
+                       clear_epp_timeout(pp);
+                       break;
+               }
+       }
+       change_mode(pp, ECR_PS2);
+       return got;
+}
+
+static size_t parport_uss720_epp_write_data(struct parport *pp, const void *buf, size_t length, int flags)
+{
+#if 0
+       struct parport_uss720_private *priv = pp->private_data; 
+       size_t written = 0;
+
+       if (change_mode(pp, ECR_EPP))
+               return 0;
+       for (; written < length; written++) {
+               if (set_1284_register(pp, 4, (char *)buf))
+                       break;
+               ((char*)buf)++;
+               if (get_1284_register(pp, 1, NULL))
+                       break;
+               if (priv->reg[0] & 0x01) {
+                       clear_epp_timeout(pp);
+                       break;
+               }
+       }
+       change_mode(pp, ECR_PS2);
+       return written;
+#else
+       struct parport_uss720_private *priv = pp->private_data;
+       struct usb_device *usbdev = priv->usbdev;
+       unsigned long rlen;
+       int i;
+
+       if (!usbdev)
+               return 0;
+       if (change_mode(pp, ECR_EPP))
+               return 0;
+       i = usbdev->bus->op->bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 1), buf, length, &rlen);
+       if (i)
+               printk(KERN_ERR "uss720: sendbulk ep 1 buf %p len %u rlen %lu\n", buf, length, rlen);
+       change_mode(pp, ECR_PS2);
+       return rlen;
+#endif
+}
+
+static size_t parport_uss720_epp_read_addr(struct parport *pp, void *buf, size_t length, int flags)
+{
+       struct parport_uss720_private *priv = pp->private_data; 
+       size_t got = 0;
+
+       if (change_mode(pp, ECR_EPP))
+               return 0;
+       for (; got < length; got++) {
+               if (get_1284_register(pp, 3, (char *)buf))
+                       break;
+               ((char*)buf)++;
+               if (priv->reg[0] & 0x01) {
+                       clear_epp_timeout(pp);
+                       break;
+               }
+       }
+       change_mode(pp, ECR_PS2);
+       return got;
+}
+
+static size_t parport_uss720_epp_write_addr(struct parport *pp, const void *buf, size_t length, int flags)
+{
+       struct parport_uss720_private *priv = pp->private_data; 
+       size_t written = 0;
+
+       if (change_mode(pp, ECR_EPP))
+               return 0;
+       for (; written < length; written++) {
+               if (set_1284_register(pp, 3, *(char *)buf))
+                       break;
+               ((char*)buf)++;
+               if (get_1284_register(pp, 1, NULL))
+                       break;
+               if (priv->reg[0] & 0x01) {
+                       clear_epp_timeout(pp);
+                       break;
+               }
+       }
+       change_mode(pp, ECR_PS2);
+       return written;
+}
+
+static size_t parport_uss720_ecp_write_data(struct parport *pp, const void *buffer, size_t len, int flags)
+{
+       struct parport_uss720_private *priv = pp->private_data;
+       struct usb_device *usbdev = priv->usbdev;
+       unsigned long rlen;
+       int i;
+
+       if (!usbdev)
+               return 0;
+       if (change_mode(pp, ECR_ECP))
+               return 0;
+       i = usbdev->bus->op->bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 1), buffer, len, &rlen);
+       if (i)
+               printk(KERN_ERR "uss720: sendbulk ep 1 buf %p len %u rlen %lu\n", buffer, len, rlen);
+       change_mode(pp, ECR_PS2);
+       return rlen;
+}
+
+static size_t parport_uss720_ecp_read_data(struct parport *pp, void *buffer, size_t len, int flags)
+{
+       struct parport_uss720_private *priv = pp->private_data;
+       struct usb_device *usbdev = priv->usbdev;
+       unsigned long rlen;
+       int i;
+
+       if (!usbdev)
+               return 0;
+       if (change_mode(pp, ECR_ECP))
+               return 0;
+       i = usbdev->bus->op->bulk_msg(usbdev, usb_rcvbulkpipe(usbdev, 2), buffer, len, &rlen);
+       if (i)
+               printk(KERN_ERR "uss720: recvbulk ep 2 buf %p len %u rlen %lu\n", buffer, len, rlen);
+       change_mode(pp, ECR_PS2);
+       return rlen;
+}
+
+static size_t parport_uss720_ecp_write_addr(struct parport *pp, const void *buffer, size_t len, int flags)
+{
+       size_t written = 0;
+
+       if (change_mode(pp, ECR_ECP))
+               return 0;
+       for (; written < len; written++) {
+               if (set_1284_register(pp, 5, *(char *)buffer))
+                       break;
+               ((char*)buffer)++;
+       }
+       change_mode(pp, ECR_PS2);
+       return written;
+}
+
+static size_t parport_uss720_write_compat(struct parport *pp, const void *buffer, size_t len, int flags)
+{
+       struct parport_uss720_private *priv = pp->private_data;
+       struct usb_device *usbdev = priv->usbdev;
+       unsigned long rlen;
+       int i;
+
+       if (!usbdev)
+               return 0;
+       if (change_mode(pp, ECR_PPF))
+               return 0;
+       i = usbdev->bus->op->bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 1), buffer, len, &rlen);
+       if (i)
+               printk(KERN_ERR "uss720: sendbulk ep 1 buf %p len %u rlen %lu\n", buffer, len, rlen);
+       change_mode(pp, ECR_PS2);
+       return rlen;
+}
+
+void parport_uss720_inc_use_count(void)
+{
+#ifdef MODULE
+       MOD_INC_USE_COUNT;
+#endif
+}
+
+void parport_uss720_dec_use_count(void)
+{
+#ifdef MODULE
+       MOD_DEC_USE_COUNT;
+#endif
+}
+
+/* --------------------------------------------------------------------- */
+
+static struct parport_operations parport_uss720_ops = 
+{
+       parport_uss720_write_data,
+       parport_uss720_read_data,
+
+       parport_uss720_write_control,
+       parport_uss720_read_control,
+       parport_uss720_frob_control,
+
+       parport_uss720_read_status,
+
+       parport_uss720_enable_irq,
+       parport_uss720_disable_irq,
+
+       parport_uss720_data_forward,
+       parport_uss720_data_reverse,
+
+       parport_uss720_init_state,
+       parport_uss720_save_state,
+       parport_uss720_restore_state,
+
+       parport_uss720_inc_use_count,
+       parport_uss720_dec_use_count,
+
+       parport_uss720_epp_write_data,
+       parport_uss720_epp_read_data,
+       parport_uss720_epp_write_addr,
+       parport_uss720_epp_read_addr,
+
+       parport_uss720_ecp_write_data,
+       parport_uss720_ecp_read_data,
+       parport_uss720_ecp_write_addr,
+
+       parport_uss720_write_compat,
+       parport_ieee1284_read_nibble,
+       parport_ieee1284_read_byte,
+};
+
+/* --------------------------------------------------------------------- */
+
+static int uss720_probe(struct usb_device *usbdev)
+{
+        struct usb_interface_descriptor *interface;
+        struct usb_endpoint_descriptor *endpoint;
+       struct parport_uss720_private *priv;
+       struct parport *pp;
+        int i;
+
+        printk(KERN_DEBUG "uss720: probe: vendor id 0x%x, device id 0x%x\n",
+               usbdev->descriptor.idVendor, usbdev->descriptor.idProduct);
+
+        if ((usbdev->descriptor.idVendor != 0x047e || usbdev->descriptor.idProduct != 0x1001) &&
+            (usbdev->descriptor.idVendor != 0x0557 || usbdev->descriptor.idProduct != 0x2001))
+                return -1;
+
+        /* We don't handle multiple configurations */
+        if (usbdev->descriptor.bNumConfigurations != 1)
+                return -1;
+
+        /* We don't handle multiple interfaces */
+        if (usbdev->config[0].bNumInterfaces != 1)
+                return -1;
+
+        /* We don't handle multiple interfaces */
+        if (usbdev->config[0].num_altsetting != 3)
+                return -1;
+
+        printk(KERN_DEBUG "uss720: set configuration\n");
+        usb_set_configuration(usbdev, usbdev->config[0].bConfigurationValue);
+
+        i = usb_set_interface(usbdev, 0, 2);
+        printk(KERN_DEBUG "uss720: set inteface result %d\n", i);
+
+        interface = &usbdev->config[0].altsetting[2].interface[0];
+
+        //printk(KERN_DEBUG "uss720: get interface\n");
+        //i = usb_get_interface(usbdev, 0);
+        //printk(KERN_DEBUG "uss720: is in alternate setting %d\n", i);
+
+       /*
+        * Allocate parport interface 
+        */
+       printk(KERN_INFO "uss720: (C) 1999 by Thomas Sailer, <sailer@ife.ee.ethz.ch>\n");
+
+       if (!(priv = kmalloc(sizeof(struct parport_uss720_private), GFP_KERNEL)))
+               return -1;
+       if (!(pp = parport_register_port(0, PARPORT_IRQ_NONE, PARPORT_DMA_NONE, &parport_uss720_ops))) {
+               kfree(priv);
+               return -1;
+       }
+       pp->private_data = priv;
+        usbdev->private = pp;
+       priv->usbdev = usbdev;
+       pp->modes = PARPORT_MODE_PCSPP | PARPORT_MODE_TRISTATE | PARPORT_MODE_EPP | PARPORT_MODE_ECP | PARPORT_MODE_COMPAT;
+
+        /* set the USS720 control register to manual mode, no ECP compression, enable all ints */
+        set_1284_register(pp, 7, 0x00);
+       set_1284_register(pp, 6, 0x30);  /* PS/2 mode */
+       set_1284_register(pp, 2, 0x0c);
+        /* debugging */
+        get_1284_register(pp, 0, NULL);
+        printk("uss720: reg: %02x %02x %02x %02x %02x %02x %02x\n",
+               priv->reg[0], priv->reg[1], priv->reg[2], priv->reg[3], priv->reg[4], priv->reg[5], priv->reg[6]);
+
+        endpoint = &interface->endpoint[2];
+       printk(KERN_DEBUG "uss720: epaddr %d interval %d\n", endpoint->bEndpointAddress, endpoint->bInterval);
+#if 0
+        priv->irqhandle = usb_request_irq(usbdev, usb_rcvctrlpipe(usbdev, endpoint->bEndpointAddress),
+                                         uss720_irq, endpoint->bInterval, pp);
+#endif
+        parport_proc_register(pp);
+        parport_announce_port(pp);
+
+       MOD_INC_USE_COUNT;
+        return 0;
+}
+
+static void uss720_disconnect(struct usb_device *usbdev)
+{
+       struct parport *pp = (struct parport *)usbdev->private;
+       struct parport_uss720_private *priv = pp->private_data;
+
+#if 0
+       usb_release_irq(usbdev, priv->irqhandle);
+#endif
+        usbdev->private = NULL;
+        priv->usbdev = NULL;
+       parport_proc_unregister(pp);
+       parport_unregister_port(pp);
+       kfree(priv);
+       MOD_DEC_USE_COUNT;
+}
+
+static struct usb_driver uss720_driver = {
+        "uss720",
+        uss720_probe,
+        uss720_disconnect,
+        { NULL, NULL }
+};
+
+/* --------------------------------------------------------------------- */
+
+#define __exit
+#define module_exit(x) void cleanup_module(void) { x(); }
+#define module_init(x) int init_module(void) { return x(); }
+
+/* --------------------------------------------------------------------- */
+
+static int __init uss720_init(void)
+{
+       usb_register(&uss720_driver);
+        printk(KERN_INFO "uss720: USB<->IEEE1284 cable driver v0.2 registered.\n"
+              KERN_INFO "uss720: (C) 1999 by Thomas Sailer, <sailer@ife.ee.ethz.ch>\n");
+       return 0;
+}
+
+static void __exit uss720_cleanup(void)
+{
+       usb_deregister(&uss720_driver);
+}
+
+module_init(uss720_init);
+module_exit(uss720_cleanup);
+
+/* --------------------------------------------------------------------- */
index 06dacf03f4ff01435099a772ea930e94e16d469d..d38a157a25781ae0aead7951b83866231f7f14d9 100644 (file)
@@ -49,7 +49,7 @@ if [ "$CONFIG_FB" = "y" ]; then
   fi
   if [ "$CONFIG_ATARI" = "y" ]; then
     bool 'Atari native chipset support' CONFIG_FB_ATARI
-    bool 'ATI Mach64 display support' CONFIG_FB_ATY
+    tristate 'ATI Mach64 display support' CONFIG_FB_ATY
   fi
   if [ "$CONFIG_PPC" = "y" ]; then
     bool 'Open Firmware frame buffer device support' CONFIG_FB_OF
@@ -57,11 +57,12 @@ if [ "$CONFIG_FB" = "y" ]; then
       bool 'Apple "control" display support' CONFIG_FB_CONTROL
       bool 'Apple "platinum" display support' CONFIG_FB_PLATINUM
       bool 'Apple "valkyrie" display support' CONFIG_FB_VALKYRIE
-      bool 'ATI Mach64 display support' CONFIG_FB_ATY
+      tristate 'ATI Mach64 display support' CONFIG_FB_ATY
       bool 'IMS Twin Turbo display support' CONFIG_FB_IMSTT
       bool 'Chips 65550 display support' CONFIG_FB_CT65550
       bool 'S3 Trio display support' CONFIG_FB_S3TRIO
     fi
+    tristate 'VGA 16-color graphics console' CONFIG_FB_VGA16
   fi
   if [ "$CONFIG_MAC" = "y" ]; then
     define_bool CONFIG_FB_MAC y
@@ -74,7 +75,7 @@ if [ "$CONFIG_FB" = "y" ]; then
   fi
   if [ "$ARCH" = "i386" ]; then
     bool 'VESA VGA graphics console' CONFIG_FB_VESA
-    bool 'VGA 16-color graphics console' CONFIG_FB_VGA16
+    tristate 'VGA 16-color graphics console' CONFIG_FB_VGA16
     define_bool CONFIG_VIDEO_SELECT y
   fi
   if [ "$CONFIG_VISWS" = "y" ]; then
@@ -86,10 +87,10 @@ if [ "$CONFIG_FB" = "y" ]; then
       if  [ "$CONFIG_FB_MATROX" != "n" ]; then
         bool '  Millennium I/II support' CONFIG_FB_MATROX_MILLENIUM
         bool '  Mystique support' CONFIG_FB_MATROX_MYSTIQUE
-        bool '  G100/G200 support' CONFIG_FB_MATROX_G100
+        bool '  G100/G200/G400 support' CONFIG_FB_MATROX_G100
         bool '  Multihead support' CONFIG_FB_MATROX_MULTIHEAD
       fi
-      bool 'ATI Mach64 display support' CONFIG_FB_ATY
+      tristate 'ATI Mach64 display support' CONFIG_FB_ATY
     fi
   fi
   if [ "$ARCH" = "sparc" -o "$ARCH" = "sparc64" ]; then
@@ -120,7 +121,7 @@ if [ "$CONFIG_FB" = "y" ]; then
     if [ "$CONFIG_PCI" != "n" ]; then
       bool 'PCI framebuffers' CONFIG_FB_PCI
       if [ "$CONFIG_FB_PCI" != "n" ]; then
-        bool '  ATI Mach64 display support' CONFIG_FB_ATY
+        tristate '  ATI Mach64 display support' CONFIG_FB_ATY
       fi
     fi
   fi
@@ -142,7 +143,7 @@ if [ "$CONFIG_FB" = "y" ]; then
     tristate 'Atari interleaved bitplanes (8 planes) support' CONFIG_FBCON_IPLAN2P8
 #   tristate 'Atari interleaved bitplanes (16 planes) support' CONFIG_FBCON_IPLAN2P16
     tristate 'Mac variable bpp packed pixels support' CONFIG_FBCON_MAC
-    bool 'VGA 16-color planar support' CONFIG_FBCON_VGA_PLANES
+    tristate 'VGA 16-color planar support' CONFIG_FBCON_VGA_PLANES
     tristate 'VGA characters/attributes support' CONFIG_FBCON_VGA
   else
     # Guess what we need
@@ -287,6 +288,10 @@ if [ "$CONFIG_FB" = "y" ]; then
     fi
     if [ "$CONFIG_FB_VGA16" = "y" ]; then
       define_bool CONFIG_FBCON_VGA_PLANES y
+    else
+      if [ "$CONFIG_FB_VGA16" = "m" ]; then
+       define_bool CONFIG_FBCON_VGA_PLANES m
+      fi
     fi
     if [ "$CONFIG_FB_MDA" = "y" -o "$CONFIG_FB_VGA" = "y" ]; then
       define_bool CONFIG_FBCON_VGA y
index 534d0fed0bf34292e5c679e77d0c7fb2ee6c2386..d6d2b7ff1a66d0825e6d044590fa6aac9d96e6d4 100644 (file)
@@ -102,6 +102,10 @@ endif
 
 ifeq ($(CONFIG_FB_ATY),y)
 L_OBJS += atyfb.o
+else
+  ifeq ($(CONFIG_FB_ATY),m)
+  M_OBJS += atyfb.o
+  endif
 endif
 
 ifeq ($(CONFIG_FB_IGA),y)
@@ -206,6 +210,10 @@ endif
 
 ifeq ($(CONFIG_FB_VGA16),y)
 L_OBJS += vga16fb.o
+else
+  ifeq ($(CONFIG_FB_VGA16),m)
+  M_OBJS += vga16fb.o
+  endif
 endif
 
 ifeq ($(CONFIG_FB_VIRGE),y)
index c83c83c967527398e34109c8caf830feaca10497..6e73954b74a8256ccb3aba67cff8df63bad831bf 100644 (file)
@@ -288,7 +288,7 @@ static int s3trio_ioctl(struct inode *inode, struct file *file, u_int cmd,
     return -EINVAL;
 }
 
-__initfunc(void s3triofb_init(void))
+void __init s3triofb_init(void)
 {
 #ifdef __powerpc__
     /* We don't want to be called like this. */
@@ -298,7 +298,7 @@ __initfunc(void s3triofb_init(void))
 #endif /* !__powerpc__ */
 }
 
-__initfunc(void s3trio_resetaccel(void)) {
+void __init s3trio_resetaccel(void){
 
 
 #define EC01_ENH_ENB    0x0005
@@ -341,7 +341,7 @@ __initfunc(void s3trio_resetaccel(void)) {
        outw( MF_PIX_CONTROL | MFA_SRC_FOREGR_MIX,  0xbee8);
 }
 
-__initfunc(int s3trio_init(struct device_node *dp)) {
+int __init s3trio_init(struct device_node *dp){
 
     u_char bus, dev;
     unsigned int t32;
@@ -402,7 +402,7 @@ __initfunc(int s3trio_init(struct device_node *dp)) {
      *  We heavily rely on OF for the moment. This needs fixing.
      */
 
-__initfunc(void s3triofb_init_of(struct device_node *dp))
+void __init s3triofb_init_of(struct device_node *dp)
 {
     int i, *pp, len;
     unsigned long address;
index 42485a999dae81c56ce3b96c9a260be2577e3bc9..b20445d0f060b4779a33f350ef7efe84a5f9fa66 100644 (file)
@@ -1429,8 +1429,8 @@ static const struct modex_params modex_params[] __initdata = {
        }
 };
 
-__initfunc(static int
-acornfb_lookup_timing(struct fb_var_screeninfo *var))
+static int __init 
+acornfb_lookup_timing(struct fb_var_screeninfo *var)
 {
        const struct modex_params *x;
        const struct modey_params *y;
@@ -1518,8 +1518,8 @@ found:
        return 0;
 }
 
-__initfunc(static void
-acornfb_init_fbinfo(void))
+static void __init 
+acornfb_init_fbinfo(void)
 {
        static int first = 1;
 
@@ -1612,14 +1612,14 @@ acornfb_init_fbinfo(void))
  *     size can optionally be followed by 'M' or 'K' for
  *     MB or KB respectively.
  */
-__initfunc(static void
-acornfb_parse_font(char *opt))
+static void __init 
+acornfb_parse_font(char *opt)
 {
        strcpy(fb_info.fontname, opt);
 }
 
-__initfunc(static void
-acornfb_parse_mon(char *opt))
+static void __init 
+acornfb_parse_mon(char *opt)
 {
        fb_info.monspecs.hfmin = simple_strtoul(opt, &opt, 0);
        if (*opt == '-')
@@ -1652,8 +1652,8 @@ acornfb_parse_mon(char *opt))
        init_var.height = simple_strtoul(opt + 1, NULL, 0);
 }
 
-__initfunc(static void
-acornfb_parse_montype(char *opt))
+static void __init 
+acornfb_parse_montype(char *opt)
 {
        current_par.montype = -2;
 
@@ -1694,8 +1694,8 @@ acornfb_parse_montype(char *opt))
        }
 }
 
-__initfunc(static void
-acornfb_parse_dram(char *opt))
+static void __init 
+acornfb_parse_dram(char *opt)
 {
        unsigned int size;
 
@@ -1728,8 +1728,8 @@ static struct options {
        { NULL, NULL }
 };
 
-__initfunc(void
-acornfb_setup(char *options, int *ints))
+void __init 
+acornfb_setup(char *options, int *ints)
 {
        struct options *optp;
        char *opt;
@@ -1765,8 +1765,8 @@ acornfb_setup(char *options, int *ints))
  * Detect type of monitor connected
  *  For now, we just assume SVGA
  */
-__initfunc(static int
-acornfb_detect_monitortype(void))
+static int __init 
+acornfb_detect_monitortype(void)
 {
        return 4;
 }
@@ -1802,8 +1802,8 @@ free_unused_pages(unsigned int virtual_start, unsigned int virtual_end)
        printk("acornfb: freed %dK memory\n", mb_freed);
 }
 
-__initfunc(void
-acornfb_init(void))
+void __init 
+acornfb_init(void)
 {
        unsigned long size;
        u_int h_sync, v_sync;
index 2aa4a29e3a658ac57f641473d8a1cec6871ddbdc..51f45aa71ae6d134745bfb6d72e98c3d29948216 100644 (file)
@@ -1259,8 +1259,7 @@ static struct fb_ops amifb_ops = {
        amifb_pan_display, amifb_ioctl
 };
 
-
-__initfunc(void amifb_setup(char *options, int *ints))
+void __init amifb_setup(char *options, int *ints)
 {
        char *this_opt;
        char mcap_spec[80];
@@ -1715,7 +1714,7 @@ static int amifb_set_cursorstate(struct fb_cursorstate *state, int con)
         * Initialisation
         */
 
-__initfunc(void amifb_init(void))
+void __init amifb_init(void)
 {
        int tag, i;
        u_long chipptr;
@@ -2053,7 +2052,7 @@ static void amifb_interrupt(int irq, void *dev_id, struct pt_regs *fp)
         * Get a Video Mode
         */
 
-__initfunc(static void get_video_mode(const char *name))
+static void __init get_video_mode(const char *name)
 {
        int i;
 
@@ -2070,7 +2069,7 @@ __initfunc(static void get_video_mode(const char *name))
         *  Probe the Video Modes
         */
 
-__initfunc(static void check_default_mode(void))
+static void __init check_default_mode(void)
 {
        struct amifb_par par;
        int mode;
@@ -2090,7 +2089,7 @@ __initfunc(static void check_default_mode(void))
         * Allocate, Clear and Align a Block of Chip Memory
         */
 
-__initfunc(static u_long chipalloc(u_long size))
+static u_long __init chipalloc(u_long size)
 {
        u_long ptr;
 
@@ -2107,7 +2106,7 @@ __initfunc(static u_long chipalloc(u_long size))
         * A strtok which returns empty strings, too
         */
 
-__initfunc(static char *strtoke(char *s,const char *ct))
+static char __init *strtoke(char *s,const char *ct)
 {
        char *sbegin, *send;
        static char *ssave = NULL;
@@ -3314,7 +3313,7 @@ static void ami_set_sprite(void)
         * Initialise the Copper Initialisation List
         */
 
-__initfunc(static void ami_init_copper(void))
+static void __init ami_init_copper(void)
 {
        copins *cop = copdisplay.init;
        u_long p;
index e35a79e0ba95695194b9a4ab80091f9c411312e1..dc080d62ce94040afad3542e27276c1ec76995c7 100644 (file)
@@ -2745,7 +2745,7 @@ atafb_blank(int blank, struct fb_info *info)
                do_install_cmap(currcon, info);
 }
 
-__initfunc(void atafb_init(void))
+void __init atafb_init(void)
 {
        int pad;
        int detected_mode;
@@ -2828,9 +2828,12 @@ __initfunc(void atafb_init(void))
                /* Map the video memory (physical address given) to somewhere
                 * in the kernel address space.
                 */
-               external_addr = ioremap_writethrough(external_addr, external_len);
+               external_addr =
+                 ioremap_writethrough((unsigned long)external_addr,
+                                      external_len);
                if (external_vgaiobase)
-                       external_vgaiobase = ioremap(external_vgaiobase, 0x10000 );
+                       external_vgaiobase =
+                         (unsigned long)ioremap(external_vgaiobase, 0x10000);
                screen_base      =
                real_screen_base = external_addr;
                screen_len       = external_len & PAGE_MASK;
@@ -2892,7 +2895,7 @@ static char * strtoke(char * s,const char * ct)
   return sbegin;
 }
 
-__initfunc(void atafb_setup( char *options, int *ints ))
+void __init atafb_setup( char *options, int *ints )
 {
     char *this_opt;
     int temp;
@@ -3069,7 +3072,7 @@ __initfunc(void atafb_setup( char *options, int *ints ))
        external_yres  = yres;
        external_depth = depth;
        external_pmode = planes;
-       external_addr  = addr;
+       external_addr  = (void *)addr;
        external_len   = len;
                
        if (external_card_type == IS_MV300)
index 667e7c3ecfdfc130976813c410c521f34cf17e73..e7b6620adae79f9e87508963cce42d4ae41a67f9 100644 (file)
@@ -88,6 +88,8 @@
 #define MEM_VGA_WP_SEL         0x00B4  /* Dword offset 0_2D */
 #define MEM_VGA_RP_SEL         0x00B8  /* Dword offset 0_2E */
 
+#define I2C_CNTL_1             0x00BC  /* Dword offset 0_2F */
+
 #define DAC_REGS               0x00C0  /* Dword offset 0_30 */
 #define DAC_W_INDEX            0x00C0  /* Dword offset 0_30 */
 #define DAC_DATA               0x00C1  /* Dword offset 0_30 */
index f0f2e7a1ed1789b7c7909f5cb121afbc65e414e5..06e3061d3b1f4ade15df07914c5a21b127e60f68 100644 (file)
@@ -1,4 +1,4 @@
-/*  $Id: atyfb.c,v 1.107 1999/06/08 19:59:03 geert Exp $
+/*  $Id: atyfb.c,v 1.109 1999/08/08 01:38:05 davem Exp $
  *  linux/drivers/video/atyfb.c -- Frame buffer device for ATI Mach64
  *
  *     Copyright (C) 1997-1998  Geert Uytterhoeven
@@ -191,6 +191,7 @@ struct aty_cursor {
 
 struct fb_info_aty {
     struct fb_info fb_info;
+    struct fb_info_aty *next;
     unsigned long ati_regbase_phys;
     unsigned long ati_regbase;
     unsigned long frame_buffer_phys;
@@ -946,8 +947,10 @@ atyfb_cursor(struct display *p, int mode, int x, int y)
        }
 }
 
-__initfunc(static struct aty_cursor *
-aty_init_cursor(struct fb_info_aty *fb))
+static struct fb_info_aty *fb_list = NULL;
+
+static struct aty_cursor * __init 
+aty_init_cursor(struct fb_info_aty *fb)
 {
        struct aty_cursor *cursor;
        unsigned long addr;
@@ -2488,7 +2491,7 @@ static void atyfb_palette(int enter)
      *  Initialisation
      */
 
-__initfunc(static int aty_init(struct fb_info_aty *info, const char *name))
+static int __init aty_init(struct fb_info_aty *info, const char *name)
 {
     u32 chip_id;
     u32 i;
@@ -2810,12 +2813,15 @@ __initfunc(static int aty_init(struct fb_info_aty *info, const char *name))
     if (register_framebuffer(&info->fb_info) < 0)
        return 0;
 
+    info->next = fb_list;
+    fb_list = info;
+
     printk("fb%d: %s frame buffer device on %s\n",
           GET_FB_IDX(info->fb_info.node), atyfb_name, name);
     return 1;
 }
 
-__initfunc(void atyfb_init(void))
+void __init atyfb_init(void)
 {
 #if defined(CONFIG_FB_OF)
     /* We don't want to be called like this. */
@@ -2843,6 +2849,7 @@ __initfunc(void atyfb_init(void))
     for (pdev = pci_devices; pdev; pdev = pdev->next) {
        if (((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) &&
            (pdev->vendor == PCI_VENDOR_ID_ATI)) {
+           struct resource *rp;
 
            info = kmalloc(sizeof(struct fb_info_aty), GFP_ATOMIC);
            if (!info) {
@@ -2851,12 +2858,12 @@ __initfunc(void atyfb_init(void))
            }
            memset(info, 0, sizeof(struct fb_info_aty));
 
-           addr = pdev->base_address[0];
-           if ((addr & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO)
-               addr = pdev->base_address[1];
+           rp = &pdev->resource[0];
+           if (rp->flags & IORESOURCE_IOPORT)
+                   rp = &pdev->resource[1];
+           addr = rp->start;
            if (!addr)
                continue;
-           addr &= PCI_BASE_ADDRESS_MEM_MASK;
 
 #ifdef __sparc__
            /*
@@ -2875,7 +2882,7 @@ __initfunc(void atyfb_init(void))
             * Figure mmap addresses from PCI config space.
             * Split Framebuffer in big- and little-endian halfs.
             */
-           for (i = 0; i < 6 && pdev->base_address[i]; i++)
+           for (i = 0; i < 6 && pdev->resource[i].start; i++)
                /* nothing */;
            j = i + 4;
 
@@ -2887,14 +2894,15 @@ __initfunc(void atyfb_init(void))
            }
            memset(info->mmap_map, 0, j * sizeof(*info->mmap_map));
 
-           for (i = 0, j = 2; i < 6 && pdev->base_address[i]; i++) {
+           for (i = 0, j = 2; i < 6 && pdev->resource[i].start; i++) {
+               struct resource *rp = &pdev->resource[i];
                int io, breg = PCI_BASE_ADDRESS_0 + (i << 2);
                unsigned long base;
                u32 size, pbase;
 
-               base = pdev->base_address[i];
+               base = rp->start;
 
-               io = (base & PCI_BASE_ADDRESS_SPACE)==PCI_BASE_ADDRESS_SPACE_IO;
+               io = (rp->flags & IORESOURCE_IOPORT);
 
                pci_read_config_dword(pdev, breg, &pbase);
                pci_write_config_dword(pdev, breg, 0xffffffff);
@@ -3160,7 +3168,7 @@ __initfunc(void atyfb_init(void))
 }
 
 #ifdef CONFIG_FB_OF
-__initfunc(void atyfb_of_init(struct device_node *dp))
+void __init atyfb_of_init(struct device_node *dp)
 {
     unsigned long addr;
     u8 bus, devfn;
@@ -3199,7 +3207,7 @@ __initfunc(void atyfb_of_init(struct device_node *dp))
                                                   0x1000);
 
     if(! info->ati_regbase) {
-           printk("atyfb_init: ioremap() returned NULL\n");
+           printk("atyfb_of_init: ioremap() returned NULL\n");
            kfree(info);
            return;
     }
@@ -3226,7 +3234,7 @@ __initfunc(void atyfb_of_init(struct device_node *dp))
     info->frame_buffer = (unsigned long)ioremap(addr, 0x800000);
 
     if(! info->frame_buffer) {
-           printk("atyfb_init: ioremap() returned NULL\n");
+           printk("atyfb_of_init: ioremap() returned NULL\n");
            kfree(info);
            return;
     }
@@ -3244,7 +3252,7 @@ __initfunc(void atyfb_of_init(struct device_node *dp))
 #endif /* CONFIG_FB_OF */
 
 
-__initfunc(void atyfb_setup(char *options, int *ints))
+void __init atyfb_setup(char *options, int *ints)
 {
     char *this_opt;
 
@@ -3315,7 +3323,7 @@ __initfunc(void atyfb_setup(char *options, int *ints))
 }
 
 #ifdef CONFIG_ATARI
-__initfunc(static int store_video_par(char *video_str, unsigned char m64_num))
+static int __init store_video_par(char *video_str, unsigned char m64_num)
 {
     char *p;
     unsigned long vmembase, size, guiregbase;
@@ -3344,7 +3352,7 @@ mach64_invalid:
     return -1;
 }
 
-__initfunc(static char *strtoke(char *s, const char *ct))
+static char __init *strtoke(char *s, const char *ct)
 {
     static char *ssave = NULL;
     char *sbegin, *send;
@@ -3934,3 +3942,44 @@ static struct display_switch fbcon_aty32 = {
     FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
 };
 #endif
+
+#ifdef MODULE
+int __init init_module(void)
+{
+    atyfb_init();
+    return fb_list ? 0 : -ENXIO;
+}
+
+void cleanup_module(void)
+{
+    while (fb_list) {
+       struct fb_info_aty *info = fb_list;
+       fb_list = info->next;
+
+       unregister_framebuffer(&info->fb_info);
+
+#ifndef __sparc__
+       if (info->ati_regbase)
+           iounmap((void *)info->ati_regbase);
+       if (info->frame_buffer)
+           iounmap((void *)info->frame_buffer);
+#ifdef __BIG_ENDIAN
+       if (info->cursor && info->cursor->ram)
+           iounmap(info->cursor->ram);
+#endif
+#endif
+
+       if (info->cursor) {
+           if (info->cursor->timer)
+               kfree(info->cursor->timer);
+           kfree(info->cursor);
+       }
+#ifdef __sparc__
+       if (info->mmap_map)
+           kfree(info->mmap_map);
+#endif
+       kfree(info);
+    }
+}
+
+#endif
index c5dfaad6ee000b51f6c6102825cad8d643b211e2..57210b6a7ab8d568821d184f65d67153370452ef 100644 (file)
@@ -288,19 +288,19 @@ static int cg14_ioctl (struct fb_info_sbusfb *fb, unsigned int cmd, unsigned lon
        return 0;
 }
 
-__initfunc(static unsigned long get_phys(unsigned long addr))
+static unsigned long __init get_phys(unsigned long addr)
 {
        return __get_phys(addr);
 }
 
-__initfunc(static int get_iospace(unsigned long addr))
+static int __init get_iospace(unsigned long addr)
 {
        return __get_iospace(addr);
 }
 
 static char idstring[60] __initdata = { 0 };
 
-__initfunc(char *cgfourteenfb_init(struct fb_info_sbusfb *fb))
+char __init *cgfourteenfb_init(struct fb_info_sbusfb *fb)
 {
        struct fb_fix_screeninfo *fix = &fb->fix;
        struct display *disp = &fb->disp;
index 1973ba92bcb90b0b75304a36f85b23cc57238d50..c2032a6d286c45c658417ec66cdd5177e2934f65 100644 (file)
@@ -590,7 +590,7 @@ static void cg6_margins (struct fb_info_sbusfb *fb, struct display *p, int x_mar
 
 static char idstring[70] __initdata = { 0 };
 
-__initfunc(char *cgsixfb_init(struct fb_info_sbusfb *fb))
+char __init *cgsixfb_init(struct fb_info_sbusfb *fb)
 {
        struct fb_fix_screeninfo *fix = &fb->fix;
        struct fb_var_screeninfo *var = &fb->var;
index 91611c6746444047a617286d56f75f9b42c87cac..223317719755b74c190e95e30747e3dcf9b7ddfd 100644 (file)
@@ -145,7 +145,7 @@ static u_char cg3_dacvals[] __initdata = {
 
 static char idstring[60] __initdata = { 0 };
 
-__initfunc(char *cgthreefb_init(struct fb_info_sbusfb *fb))
+char __init *cgthreefb_init(struct fb_info_sbusfb *fb)
 {
        struct fb_fix_screeninfo *fix = &fb->fix;
        struct display *disp = &fb->disp;
index eb5d8931c166d4c7eb92eb23b88125e39beda0d4..a46e039358f55b0fcd26e3e9e3ca883e412ba295 100644 (file)
@@ -525,7 +525,7 @@ static struct chips_init_reg chips_init_xr[] = {
        { 0xa8, 0x00 }
 };
 
-__initfunc(static void chips_hw_init(struct fb_info_chips *p))
+static void __init chips_hw_init(struct fb_info_chips *p)
 {
        int i;
 
@@ -544,7 +544,7 @@ __initfunc(static void chips_hw_init(struct fb_info_chips *p))
                write_fr(chips_init_fr[i].addr, chips_init_fr[i].data);
 }
 
-__initfunc(static void init_chips(struct fb_info_chips *p))
+static void __init init_chips(struct fb_info_chips *p)
 {
        int i;
 
@@ -645,7 +645,7 @@ __initfunc(static void init_chips(struct fb_info_chips *p))
        all_chips = p;
 }
 
-__initfunc(void chips_init(void))
+void __init chips_init(void)
 {
 #ifndef CONFIG_FB_OF
        struct device_node *dp;
@@ -656,7 +656,7 @@ __initfunc(void chips_init(void))
 #endif /* CONFIG_FB_OF */
 }
 
-__initfunc(void chips_of_init(struct device_node *dp))
+void __init chips_of_init(struct device_node *dp)
 {
        struct fb_info_chips *p;
        unsigned long addr;
index 3f95ae58cebcea9cf8f02e873075f7a18b844a0e..8ce2ddf69bd941f87529265a5dceb9375bfc5125 100644 (file)
@@ -1467,7 +1467,7 @@ static void fbcon_clgen8_clear(struct vc_data *conp, struct display *p,
 /********************************************************************/
 /* clgenfb_init() - master initialization function                  */
 /********************************************************************/
-__initfunc(void clgenfb_init(void))
+void __init clgenfb_init(void)
 {
     const struct ConfigDev *cd  = NULL;
     const struct ConfigDev *cd2 = NULL;
@@ -1655,7 +1655,7 @@ static char *strtoke(char *s,const char *ct)
 /* arguments to the video= bootstrap parameter. Right now, there */
 /* is nothing I do here.                                         */
 /*****************************************************************/
-__initfunc(void clgenfb_setup(char *options, int *ints))
+void __init clgenfb_setup(char *options, int *ints)
 {
 //    char *this_opt;
 
index 2a783fc9b32f2543d0ebeea62a5bc5d8c1e827a4..5ab50fcc89d327988f9c8504bc5803025257c22a 100644 (file)
@@ -523,7 +523,7 @@ static void set_control_clock(unsigned char *params)
 }
 
 
-__initfunc(static void init_control(struct fb_info_control *p))
+static void __init init_control(struct fb_info_control *p)
 {
        struct fb_par_control parstruct;
        struct fb_par_control *par = &parstruct;
@@ -660,7 +660,7 @@ static void control_set_hardware(struct fb_info_control *p, struct fb_par_contro
 #endif /* CONFIG_FB_COMPAT_XPMAC */
 }
 
-__initfunc(void control_init(void))
+void __init control_init(void)
 {
 #ifndef CONFIG_FB_OF
        struct device_node *dp;
@@ -671,7 +671,7 @@ __initfunc(void control_init(void))
 #endif /* CONFIG_FB_OF */
 }
 
-__initfunc(void control_of_init(struct device_node *dp))
+void __init control_of_init(struct device_node *dp)
 {
        struct fb_info_control  *p;
        unsigned long           addr, size;
@@ -1152,7 +1152,7 @@ static void control_init_info(struct fb_info *info, struct fb_info_control *p)
 }
 
 /* Parse user speficied options (`video=controlfb:') */
-__initfunc(void control_setup(char *options, int *ints))
+void __init control_setup(char *options, int *ints)
 {
        char *this_opt;
 
index 81421a7ff54665495500dbe0c29029906867c5c7..812e0f669b410dfc49c124549757ff46c66c4951 100644 (file)
@@ -637,7 +637,7 @@ static void ffb_switch_from_graph (struct fb_info_sbusfb *fb)
 
 static char idstring[60] __initdata = { 0 };
 
-__initfunc(char *creatorfb_init(struct fb_info_sbusfb *fb))
+char __init *creatorfb_init(struct fb_info_sbusfb *fb)
 {
        struct fb_fix_screeninfo *fix = &fb->fix;
        struct fb_var_screeninfo *var = &fb->var;
index d342304a31945d05a33a11f680b471c1283d333d..ddbab8b17813667e586179e2d35a64e37565fd91 100644 (file)
@@ -1018,7 +1018,7 @@ static void cyber2000fb_blank(int blank, struct fb_info *fb_info)
        }
 }
 
-__initfunc(void cyber2000fb_setup(char *options, int *ints))
+void __init cyber2000fb_setup(char *options, int *ints)
 {
 }
 
@@ -1035,8 +1035,8 @@ static struct fb_ops cyber2000fb_ops =
        cyber2000fb_ioctl
 };
 
-__initfunc(static void
-cyber2000fb_init_fbinfo(void))
+static void __init 
+cyber2000fb_init_fbinfo(void)
 {
        static int first = 1;
 
@@ -1138,7 +1138,7 @@ cyber2000fb_init_fbinfo(void))
 /*
  *    Initialization
  */
-__initfunc(void cyber2000fb_init(void))
+void __init cyber2000fb_init(void)
 {
        struct pci_dev *dev;
        u_int h_sync, v_sync;
index 6882ebfb0c82386fcef7283a2c4ea2dfe78a9559..80cfbed8b035e8608111e61678e5220fe847f017 100644 (file)
@@ -109,7 +109,10 @@ static void cv64_dump(void);
 
 #define arraysize(x)    (sizeof(x)/sizeof(*(x)))
 
-#define wb_64(reg,dat) (*((unsigned char volatile *)CyberRegs + reg) = dat)
+#define wb_64(regs,reg,dat) (*(((volatile unsigned char *)regs) + reg) = dat)
+#define rb_64(regs, reg) (*(((volatile unsigned char *)regs) + reg))
+
+#define ww_64(regs,reg,dat) (*((volatile unsigned short *)(regs + reg) = dat)
 
 struct cyberfb_par {
        struct fb_var_screeninfo var;
@@ -129,60 +132,32 @@ static struct fb_info fb_info;
 
 
 /*
-*    Switch for Chipset Independency
-*/
-
-static struct fb_hwswitch {
-
-/* Initialisation */
-
-int (*init)(void);
-
-/* Display Control */
-
-int (*encode_fix)(struct fb_fix_screeninfo *fix, struct cyberfb_par *par);
-int (*decode_var)(struct fb_var_screeninfo *var, struct cyberfb_par *par);
-int (*encode_var)(struct fb_var_screeninfo *var, struct cyberfb_par *par);
-int (*getcolreg)(u_int regno, u_int *red, u_int *green, u_int *blue,
-                u_int *transp, struct fb_info *info);
-int (*setcolreg)(u_int regno, u_int red, u_int green, u_int blue,
-                u_int transp, struct fb_info *info);
-void (*blank)(int blank);
-} *fbhw;
-
-
-/*
-*    Frame Buffer Name
-*/
+ *    Frame Buffer Name
+ */
 
 static char cyberfb_name[16] = "Cybervision";
 
 
 /*
-*    Cybervision Graphics Board
-*/
+ *    CyberVision Graphics Board
+ */
 
 static unsigned char Cyber_colour_table [256][3];
-static unsigned long CyberMem;
 static unsigned long CyberSize;
-static volatile char *CyberRegs;
+static volatile unsigned char *CyberBase;
+static volatile unsigned char *CyberMem;
+static volatile unsigned char *CyberRegs;
 static unsigned long CyberMem_phys;
 static unsigned long CyberRegs_phys;
-/* From cvision.c  for cvision_core.c */
-static unsigned long cv64_mem;
-static unsigned long cv64_fbmem;
-static volatile char *cv64_regs;
-static unsigned long cv64_size;
-#if 0
-static int cvision_custom_mode = 0;
-static int hbs, hbe, hss, hse, ht, vbs, vbe, vss, vse, vt;
-#endif
 
 /*
-*    Predefined Video Modes
-*/
+ *    Predefined Video Modes
+ */
 
-static struct fb_videomode cyberfb_predefined[] __initdata = {
+static struct {
+    const char *name;
+    struct fb_var_screeninfo var;
+} cyberfb_predefined[] __initdata = {
        { "640x480-8", {                /* Default 8 BPP mode (cyber8) */
                640, 480, 640, 480, 0, 0, 8, 0,
                {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
@@ -251,17 +226,18 @@ static struct fb_videomode cyberfb_predefined[] __initdata = {
 static int Cyberfb_inverse = 0;
 
 /*
-*    Some default modes
-*/
+ *    Some default modes
+ */
 
 #define CYBER8_DEFMODE     (0)
 #define CYBER16_DEFMODE    (1)
 
 static struct fb_var_screeninfo cyberfb_default;
+static int cyberfb_usermode __initdata = 0;
 
 /*
-*    Interface used by the world
-*/
+ *    Interface used by the world
+ */
 
 void cyberfb_setup(char *options, int *ints);
 
@@ -283,8 +259,8 @@ static int cyberfb_ioctl(struct inode *inode, struct file *file, u_int cmd,
                         u_long arg, int con, struct fb_info *info);
 
 /*
-*    Interface to the low level console driver
-*/
+ *    Interface to the low level console driver
+ */
 
 void cyberfb_init(void);
 static int Cyberfb_switch(int con, struct fb_info *info);
@@ -292,16 +268,16 @@ static int Cyberfb_updatevar(int con, struct fb_info *info);
 static void Cyberfb_blank(int blank, struct fb_info *info);
 
 /*
-*    Text console acceleration
-*/
+ *    Text console acceleration
+ */
 
 #ifdef FBCON_HAS_CFB8
 static struct display_switch fbcon_cyber8;
 #endif
 
 /*
-*    Accelerated Functions used by the low level console driver
-*/
+ *    Accelerated Functions used by the low level console driver
+ */
 
 static void Cyber_WaitQueue(u_short fifo);
 static void Cyber_WaitBlit(void);
@@ -310,11 +286,13 @@ static void Cyber_BitBLT(u_short curx, u_short cury, u_short destx,
                         u_short mode);
 static void Cyber_RectFill(u_short x, u_short y, u_short width, u_short height,
                           u_short mode, u_short color);
+#if 0
 static void Cyber_MoveCursor(u_short x, u_short y);
+#endif
 
 /*
-*   Hardware Specific Routines
-*/
+ *   Hardware Specific Routines
+ */
 
 static int Cyber_init(void);
 static int Cyber_encode_fix(struct fb_fix_screeninfo *fix,
@@ -327,11 +305,10 @@ static int Cyber_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
                           u_int *transp, struct fb_info *info);
 static int Cyber_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
                           u_int transp, struct fb_info *info);
-static void Cyber_blank(int blank);
 
 /*
-*    Internal routines
-*/
+ *    Internal routines
+ */
 
 static void cyberfb_get_par(struct cyberfb_par *par);
 static void cyberfb_set_par(struct cyberfb_par *par);
@@ -342,7 +319,7 @@ static int get_video_mode(const char *name);
 
 /* For cvision_core.c */
 static unsigned short cv64_compute_clock(unsigned long);
-static int cv_has_4mb (volatile caddr_t);
+static int cv_has_4mb (volatile unsigned char *);
 static void cv64_board_init (void);
 static void cv64_load_video_mode (struct fb_var_screeninfo *);
 
@@ -351,16 +328,17 @@ static void cv64_load_video_mode (struct fb_var_screeninfo *);
 
 
 /*
-*    Initialization
-*
-*    Set the default video mode for this chipset. If a video mode was
-*    specified on the command line, it will override the default mode.
-*/
+ *    Initialization
+ *
+ *    Set the default video mode for this chipset. If a video mode was
+ *    specified on the command line, it will override the default mode.
+ */
 
 static int Cyber_init(void)
 {
+       volatile unsigned char *regs = CyberRegs;
+       volatile unsigned long *CursorBase;
        int i;
-       volatile u_long *CursorBase;
        DPRINTK("ENTER\n");
 
 /* Init local cmap as greyscale levels */
@@ -371,27 +349,25 @@ static int Cyber_init(void)
        }
 
 /* Initialize the board and determine fbmem size */
-       cv64_board_init (); 
+       cv64_board_init(); 
 #ifdef CYBERFBDEBUG
        DPRINTK("Register state after initing board\n");
        cv64_dump();
 #endif
 /* Clear framebuffer memory */
        DPRINTK("Clear framebuffer memory\n");
-       memset ((char *) cv64_fbmem, 0, cv64_size);
+       memset ((char *)CyberMem, 0, CyberSize);
 
 /* Disable hardware cursor */
        DPRINTK("Disable HW cursor\n");
-       wb_64(S3_CRTC_ADR, S3_REG_LOCK2);
-       wb_64(S3_CRTC_DATA, 0xa0);
-       wb_64(S3_CRTC_ADR, S3_HGC_MODE);
-       wb_64(S3_CRTC_DATA, 0x00);
-       wb_64(S3_CRTC_ADR, S3_HWGC_DX);
-       wb_64(S3_CRTC_DATA, 0x00);
-       wb_64(S3_CRTC_ADR, S3_HWGC_DY);
-       wb_64(S3_CRTC_DATA, 0x00);
-
-       CyberSize = cv64_size;
+       wb_64(regs, S3_CRTC_ADR, S3_REG_LOCK2);
+       wb_64(regs, S3_CRTC_DATA, 0xa0);
+       wb_64(regs, S3_CRTC_ADR, S3_HGC_MODE);
+       wb_64(regs, S3_CRTC_DATA, 0x00);
+       wb_64(regs, S3_CRTC_ADR, S3_HWGC_DX);
+       wb_64(regs, S3_CRTC_DATA, 0x00);
+       wb_64(regs, S3_CRTC_ADR, S3_HWGC_DY);
+       wb_64(regs, S3_CRTC_DATA, 0x00);
 
 /* Initialize hardware cursor */
        DPRINTK("Init HW cursor\n");
@@ -420,9 +396,9 @@ static int Cyber_init(void)
 
 
 /*
-*    This function should fill in the `fix' structure based on the
-*    values in the `par' structure.
-*/
+ *    This function should fill in the `fix' structure based on the
+ *    values in the `par' structure.
+ */
 
 static int Cyber_encode_fix(struct fb_fix_screeninfo *fix,
                            struct cyberfb_par *par)
@@ -546,19 +522,21 @@ static int Cyber_encode_var(struct fb_var_screeninfo *var,
 
 
 /*
-*    Set a single color register. Return != 0 for invalid regno.
-*/
+ *    Set a single color register. Return != 0 for invalid regno.
+ */
 
 static int Cyber_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
                           u_int transp, struct fb_info *info)
 {
+       volatile unsigned char *regs = CyberRegs;
+
        /*DPRINTK("ENTER\n");*/
        if (regno > 255) {
                DPRINTK("EXIT - Register # > 255\n");
                return (1);
        }
 
-       wb_64(0x3c8, (unsigned char) regno);
+       wb_64(regs, 0x3c8, (unsigned char) regno);
 
        red >>= 10;
        green >>= 10;
@@ -568,9 +546,9 @@ static int Cyber_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
        Cyber_colour_table [regno][1] = green;
        Cyber_colour_table [regno][2] = blue;
 
-       wb_64(0x3c9, red);
-       wb_64(0x3c9, green);
-       wb_64(0x3c9, blue);
+       wb_64(regs, 0x3c9, red);
+       wb_64(regs, 0x3c9, green);
+       wb_64(regs, 0x3c9, blue);
 
        /*DPRINTK("EXIT\n");*/
        return (0);
@@ -611,29 +589,30 @@ static int Cyber_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
 *           0 = restore fb cmap from local cmap
 */
 
-void Cyber_blank(int blank)
+void Cyberfb_blank(int blank, struct fb_info *info)
 {
+       volatile unsigned char *regs = CyberRegs;
        int i;
 
        DPRINTK("ENTER\n");
 #if 0
 /* Blank by turning gfx off */
-       gfx_on_off (1, cv64_regs);
+       gfx_on_off (1, regs);
 #else
        if (blank) {
                for (i = 0; i < 256; i++) {
-                       wb_64(0x3c8, (unsigned char) i);
+                       wb_64(regs, 0x3c8, (unsigned char) i);
                        /* ARB Pale red to detect this blanking method */
-                       wb_64(0x3c9, 48); 
-                       wb_64(0x3c9, 0);
-                       wb_64(0x3c9, 0);
+                       wb_64(regs, 0x3c9, 48); 
+                       wb_64(regs, 0x3c9, 0);
+                       wb_64(regs, 0x3c9, 0);
                }
        } else {
                for (i = 0; i < 256; i++) {
-                       wb_64(0x3c8, (unsigned char) i);
-                       wb_64(0x3c9, Cyber_colour_table[i][0]);
-                       wb_64(0x3c9, Cyber_colour_table[i][1]);
-                       wb_64(0x3c9, Cyber_colour_table[i][2]);
+                       wb_64(regs, 0x3c8, (unsigned char) i);
+                       wb_64(regs, 0x3c9, Cyber_colour_table[i][0]);
+                       wb_64(regs, 0x3c9, Cyber_colour_table[i][1]);
+                       wb_64(regs, 0x3c9, Cyber_colour_table[i][2]);
                }
        }
 #endif
@@ -646,13 +625,12 @@ void Cyber_blank(int blank)
  */
 static void Cyber_WaitQueue (u_short fifo)
 {
-       u_short status;
+       unsigned short status;
 
        DPRINTK("ENTER\n");
        do {
                status = *((u_short volatile *)(CyberRegs + S3_GP_STAT));
-       }
-       while (status & fifo);
+       } while (status & fifo);
        DPRINTK("EXIT\n");
 }
 
@@ -661,13 +639,12 @@ static void Cyber_WaitQueue (u_short fifo)
  */
 static void Cyber_WaitBlit (void)
 {
-       u_short status;
+       unsigned short status;
 
        DPRINTK("ENTER\n");
        do {
                status = *((u_short volatile *)(CyberRegs + S3_GP_STAT));
-       }
-       while (status & S3_HDW_BUSY);
+       } while (status & S3_HDW_BUSY);
        DPRINTK("EXIT\n");
 }
 
@@ -678,6 +655,7 @@ static void Cyber_BitBLT (u_short curx, u_short cury, u_short destx,
                          u_short desty, u_short width, u_short height,
                          u_short mode)
 {
+       volatile unsigned char *regs = CyberRegs;
        u_short blitcmd = S3_BITBLT;
 
        DPRINTK("ENTER\n");
@@ -699,19 +677,19 @@ static void Cyber_BitBLT (u_short curx, u_short cury, u_short destx,
 
        Cyber_WaitQueue (0x8000);
 
-       *((u_short volatile *)(CyberRegs + S3_PIXEL_CNTL)) = 0xa000;
-       *((u_short volatile *)(CyberRegs + S3_FRGD_MIX)) = (0x0060 | mode);
+       *((u_short volatile *)(regs + S3_PIXEL_CNTL)) = 0xa000;
+       *((u_short volatile *)(regs + S3_FRGD_MIX)) = (0x0060 | mode);
 
-       *((u_short volatile *)(CyberRegs + S3_CUR_X)) = curx;
-       *((u_short volatile *)(CyberRegs + S3_CUR_Y)) = cury;
+       *((u_short volatile *)(regs + S3_CUR_X)) = curx;
+       *((u_short volatile *)(regs + S3_CUR_Y)) = cury;
 
-       *((u_short volatile *)(CyberRegs + S3_DESTX_DIASTP)) = destx;
-       *((u_short volatile *)(CyberRegs + S3_DESTY_AXSTP)) = desty;
+       *((u_short volatile *)(regs + S3_DESTX_DIASTP)) = destx;
+       *((u_short volatile *)(regs + S3_DESTY_AXSTP)) = desty;
 
-       *((u_short volatile *)(CyberRegs + S3_MIN_AXIS_PCNT)) = height - 1;
-       *((u_short volatile *)(CyberRegs + S3_MAJ_AXIS_PCNT)) = width  - 1;
+       *((u_short volatile *)(regs + S3_MIN_AXIS_PCNT)) = height - 1;
+       *((u_short volatile *)(regs + S3_MAJ_AXIS_PCNT)) = width  - 1;
 
-       *((u_short volatile *)(CyberRegs + S3_CMD)) = blitcmd;
+       *((u_short volatile *)(regs + S3_CMD)) = blitcmd;
        DPRINTK("EXIT\n");
 }
 
@@ -721,56 +699,52 @@ static void Cyber_BitBLT (u_short curx, u_short cury, u_short destx,
 static void Cyber_RectFill (u_short x, u_short y, u_short width,
                            u_short height, u_short mode, u_short color)
 {
+       volatile unsigned char *regs = CyberRegs;
        u_short blitcmd = S3_FILLEDRECT;
 
        DPRINTK("ENTER\n");
        Cyber_WaitQueue (0x8000);
 
-       *((u_short volatile *)(CyberRegs + S3_PIXEL_CNTL)) = 0xa000;
-       *((u_short volatile *)(CyberRegs + S3_FRGD_MIX)) = (0x0020 | mode);
+       *((u_short volatile *)(regs + S3_PIXEL_CNTL)) = 0xa000;
+       *((u_short volatile *)(regs + S3_FRGD_MIX)) = (0x0020 | mode);
 
-       *((u_short volatile *)(CyberRegs + S3_MULT_MISC)) = 0xe000;
-       *((u_short volatile *)(CyberRegs + S3_FRGD_COLOR)) = color;
+       *((u_short volatile *)(regs + S3_MULT_MISC)) = 0xe000;
+       *((u_short volatile *)(regs + S3_FRGD_COLOR)) = color;
 
-       *((u_short volatile *)(CyberRegs + S3_CUR_X)) = x;
-       *((u_short volatile *)(CyberRegs + S3_CUR_Y)) = y;
+       *((u_short volatile *)(regs + S3_CUR_X)) = x;
+       *((u_short volatile *)(regs + S3_CUR_Y)) = y;
 
-       *((u_short volatile *)(CyberRegs + S3_MIN_AXIS_PCNT)) = height - 1;
-       *((u_short volatile *)(CyberRegs + S3_MAJ_AXIS_PCNT)) = width  - 1;
+       *((u_short volatile *)(regs + S3_MIN_AXIS_PCNT)) = height - 1;
+       *((u_short volatile *)(regs + S3_MAJ_AXIS_PCNT)) = width  - 1;
 
-       *((u_short volatile *)(CyberRegs + S3_CMD)) = blitcmd;
+       *((u_short volatile *)(regs + S3_CMD)) = blitcmd;
        DPRINTK("EXIT\n");
 }
 
+
+#if 0
 /**************************************************************
  * Move cursor to x, y
  */
 static void Cyber_MoveCursor (u_short x, u_short y)
 {
+       volatile unsigned char *regs = CyberRegs;
        DPRINTK("ENTER\n");
-       *(CyberRegs + S3_CRTC_ADR)  = 0x39;
-       *(CyberRegs + S3_CRTC_DATA) = 0xa0;
-
-       *(CyberRegs + S3_CRTC_ADR)  = S3_HWGC_ORGX_H;
-       *(CyberRegs + S3_CRTC_DATA) = (char)((x & 0x0700) >> 8);
-       *(CyberRegs + S3_CRTC_ADR)  = S3_HWGC_ORGX_L;
-       *(CyberRegs + S3_CRTC_DATA) = (char)(x & 0x00ff);
-
-       *(CyberRegs + S3_CRTC_ADR)  = S3_HWGC_ORGY_H;
-       *(CyberRegs + S3_CRTC_DATA) = (char)((y & 0x0700) >> 8);
-       *(CyberRegs + S3_CRTC_ADR)  = S3_HWGC_ORGY_L;
-       *(CyberRegs + S3_CRTC_DATA) = (char)(y & 0x00ff);
+       *(regs + S3_CRTC_ADR)  = 0x39;
+       *(regs + S3_CRTC_DATA) = 0xa0;
+
+       *(regs + S3_CRTC_ADR)  = S3_HWGC_ORGX_H;
+       *(regs + S3_CRTC_DATA) = (char)((x & 0x0700) >> 8);
+       *(regs + S3_CRTC_ADR)  = S3_HWGC_ORGX_L;
+       *(regs + S3_CRTC_DATA) = (char)(x & 0x00ff);
+
+       *(regs + S3_CRTC_ADR)  = S3_HWGC_ORGY_H;
+       *(regs + S3_CRTC_DATA) = (char)((y & 0x0700) >> 8);
+       *(regs + S3_CRTC_ADR)  = S3_HWGC_ORGY_L;
+       *(regs + S3_CRTC_DATA) = (char)(y & 0x00ff);
        DPRINTK("EXIT\n");
 }
-
-
-/* -------------------- Interfaces to hardware functions -------------------- */
-
-
-static struct fb_hwswitch Cyber_switch = {
-       Cyber_init, Cyber_encode_fix, Cyber_decode_var, Cyber_encode_var,
-       Cyber_getcolreg, Cyber_setcolreg, Cyber_blank
-};
+#endif
 
 
 /* -------------------- Generic routines ---------------------------------- */
@@ -786,7 +760,7 @@ static void cyberfb_get_par(struct cyberfb_par *par)
        if (current_par_valid) {
                *par = current_par;
        } else {
-               fbhw->decode_var(&cyberfb_default, par);
+               Cyber_decode_var(&cyberfb_default, par);
        }
        DPRINTK("EXIT\n");
 }
@@ -819,14 +793,14 @@ static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
        struct cyberfb_par par;
 
        DPRINTK("ENTER\n");
-       if ((err = fbhw->decode_var(var, &par))) {
+       if ((err = Cyber_decode_var(var, &par))) {
                DPRINTK("EXIT - decode_var failed\n");
                return(err);
        }
        activate = var->activate;
        if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW && isactive)
                cyberfb_set_par(&par);
-       fbhw->encode_var(var, &par);
+       Cyber_encode_var(var, &par);
        var->activate = activate;
 
        cyber_set_video(var);
@@ -844,11 +818,11 @@ static void do_install_cmap(int con, struct fb_info *info)
        }
        if (fb_display[con].cmap.len) {
                DPRINTK("Use console cmap\n");
-               fb_set_cmap(&fb_display[con].cmap, 1, fbhw->setcolreg, info);
+               fb_set_cmap(&fb_display[con].cmap, 1, Cyber_setcolreg, info);
        } else {
                DPRINTK("Use default cmap\n");
                fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
-                           1, fbhw->setcolreg, info);
+                           1, Cyber_setcolreg, info);
        }
        DPRINTK("EXIT\n");
 }
@@ -889,10 +863,10 @@ static int cyberfb_get_fix(struct fb_fix_screeninfo *fix, int con,
        if (con == -1) {
                cyberfb_get_par(&par);
        } else {
-               error = fbhw->decode_var(&fb_display[con].var, &par);
+               error = Cyber_decode_var(&fb_display[con].var, &par);
        }
        DPRINTK("EXIT\n");
-       return(error ? error : fbhw->encode_fix(fix, &par));
+       return(error ? error : Cyber_encode_fix(fix, &par));
 }
 
 
@@ -909,7 +883,7 @@ static int cyberfb_get_var(struct fb_var_screeninfo *var, int con,
        DPRINTK("ENTER\n");
        if (con == -1) {
                cyberfb_get_par(&par);
-               error = fbhw->encode_var(var, &par);
+               error = Cyber_encode_var(var, &par);
                disp.var = *var;   /* ++Andre: don't know if this is the right place */
        } else {
                *var = fb_display[con].var;
@@ -934,7 +908,7 @@ static void cyberfb_set_disp(int con, struct fb_info *info)
        cyberfb_get_fix(&fix, con, info);
        if (con == -1)
                con = 0;
-       display->screen_base = phys_to_virt ((unsigned long) fix.smem_start);
+       display->screen_base = (unsigned char *)CyberMem;
        display->visual = fix.visual;
        display->type = fix.type;
        display->type_aux = fix.type_aux;
@@ -1014,7 +988,7 @@ static int cyberfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
        DPRINTK("ENTER\n");
        if (con == currcon) { /* current console? */
                DPRINTK("EXIT - console is current console\n");
-               return(fb_get_cmap(cmap, kspc, fbhw->getcolreg, info));
+               return(fb_get_cmap(cmap, kspc, Cyber_getcolreg, info));
        } else if (fb_display[con].cmap.len) { /* non default colormap? */
                DPRINTK("Use console cmap\n");
                fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
@@ -1048,7 +1022,7 @@ static int cyberfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
        }
        if (con == currcon) {            /* current console? */
                DPRINTK("EXIT - Current console\n");
-               return(fb_set_cmap(cmap, kspc, fbhw->setcolreg, info));
+               return(fb_set_cmap(cmap, kspc, Cyber_setcolreg, info));
        } else {
                fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
        }
@@ -1066,7 +1040,7 @@ static int cyberfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
 static int cyberfb_pan_display(struct fb_var_screeninfo *var, int con,
                               struct fb_info *info)
 {
-       return(-EINVAL);
+       return -EINVAL;
 }
 
 
@@ -1077,7 +1051,7 @@ static int cyberfb_pan_display(struct fb_var_screeninfo *var, int con,
 static int cyberfb_ioctl(struct inode *inode, struct file *file,
                         u_int cmd, u_long arg, int con, struct fb_info *info)
 {
-       return(-EINVAL);
+       return -EINVAL;
 }
 
 
@@ -1088,7 +1062,7 @@ static struct fb_ops cyberfb_ops = {
 };
 
 
-__initfunc(void cyberfb_setup(char *options, int *ints))
+void __init cyberfb_setup(char *options, int *ints)
 {
        char *this_opt;
        DPRINTK("ENTER\n");
@@ -1109,8 +1083,10 @@ __initfunc(void cyberfb_setup(char *options, int *ints))
                        strcpy(fb_info.fontname, this_opt+5);
                } else if (!strcmp (this_opt, "cyber8")) {
                        cyberfb_default = cyberfb_predefined[CYBER8_DEFMODE].var;
+                       cyberfb_usermode = 1;
                } else if (!strcmp (this_opt, "cyber16")) {
                        cyberfb_default = cyberfb_predefined[CYBER16_DEFMODE].var;
+                       cyberfb_usermode = 1;
                } else get_video_mode(this_opt);
        }
 
@@ -1125,7 +1101,7 @@ __initfunc(void cyberfb_setup(char *options, int *ints))
  *    Initialization
  */
 
-__initfunc(void cyberfb_init(void))
+void __init cyberfb_init(void)
 {
        struct cyberfb_par par;
        unsigned long board_addr;
@@ -1146,14 +1122,12 @@ __initfunc(void cyberfb_init(void))
        DPRINTK("board_addr=%08lx\n", board_addr);
        DPRINTK("board_size=%08lx\n", board_size);
 
-       cv64_mem = ioremap(board_addr, board_size);
-       cv64_regs = (volatile char *)(cv64_mem + 0x02000000);
-       cv64_fbmem = cv64_mem + 0x01400000;
-       DPRINTK("cv64_mem=%08lx cv64_regs=%08lx cv64_fbmem=%08lx\n",
-               cv64_mem, (long unsigned int)cv64_regs, cv64_fbmem);
+       CyberBase = ioremap(board_addr, board_size);
+       CyberRegs = CyberBase + 0x02000000;
+       CyberMem = CyberBase + 0x01400000;
+       DPRINTK("CyberBase=%08lx CyberRegs=%08lx CyberMem=%08lx\n",
+               CyberBase, (long unsigned int)CyberRegs, CyberMem);
 
-       CyberMem = cv64_fbmem;
-       CyberRegs = cv64_regs;
        CyberMem_phys = board_addr + 0x01400000;
        CyberRegs_phys = CyberMem_phys + 0x00c00000;
        DPRINTK("CyberMem=%08lx CyberRegs=%08lx\n", CyberMem,
@@ -1164,8 +1138,6 @@ __initfunc(void cyberfb_init(void))
        cv64_dump();
 #endif
 
-       fbhw = &Cyber_switch;
-
        strcpy(fb_info.modename, cyberfb_name);
        fb_info.changevar = NULL;
        fb_info.node = -1;
@@ -1175,9 +1147,14 @@ __initfunc(void cyberfb_init(void))
        fb_info.updatevar = &Cyberfb_updatevar;
        fb_info.blank = &Cyberfb_blank;
 
-       fbhw->init();
-       fbhw->decode_var(&cyberfb_default, &par);
-       fbhw->encode_var(&cyberfb_default, &par);
+       Cyber_init();
+       /* ++Andre: set cyberfb default mode */
+       if (!cyberfb_usermode) {
+               cyberfb_default = cyberfb_predefined[CYBER8_DEFMODE].var;
+               DPRINTK("Use default cyber8 mode\n");
+       }
+       Cyber_decode_var(&cyberfb_default, &par);
+       Cyber_encode_var(&cyberfb_default, &par);
 
        do_fb_set_var(&cyberfb_default, 1);
        cyberfb_get_var(&fb_display[0].var, -1, &fb_info);
@@ -1203,7 +1180,7 @@ static int Cyberfb_switch(int con, struct fb_info *info)
         DPRINTK("ENTER\n");
        /* Do we have to save the colormap? */
        if (fb_display[currcon].cmap.len) {
-               fb_get_cmap(&fb_display[currcon].cmap, 1, fbhw->getcolreg,
+               fb_get_cmap(&fb_display[currcon].cmap, 1, Cyber_getcolreg,
                            info);
        }
 
@@ -1230,23 +1207,11 @@ static int Cyberfb_updatevar(int con, struct fb_info *info)
 }
 
 
-/*
- *    Blank the display.
- */
-
-static void Cyberfb_blank(int blank, struct fb_info *info)
-{
-       DPRINTK("Enter\n");
-       fbhw->blank(blank);
-       DPRINTK("Exit\n");
-}
-
-
 /*
  *    Get a Video Mode
  */
 
-__initfunc(static int get_video_mode(const char *name))
+static int __init get_video_mode(const char *name)
 {
        int i;
 
@@ -1254,13 +1219,11 @@ __initfunc(static int get_video_mode(const char *name))
        for (i = 0; i < NUM_TOTAL_MODES; i++) {
                if (!strcmp(name, cyberfb_predefined[i].name)) {
                        cyberfb_default = cyberfb_predefined[i].var;
+                       cyberfb_usermode = 1;
                        DPRINTK("EXIT - Matched predefined mode\n");
                        return(i);
                }
        }
-       /* ++Andre: set cyberfb default mode */
-       cyberfb_default = cyberfb_predefined[CYBER8_DEFMODE].var;
-       DPRINTK("EXIT - Use default cyber8 mode\n");
        return(0);
 }
 
@@ -1454,71 +1417,38 @@ unsigned char cvconscolors[16][3] = {   /* background, foreground, hilite */
 };
 
 /* -------------------- Hardware specific routines ------------------------- */
-#if 0
-/* ARB Generates 100 usec delay */
-inline void __cv_delay (unsigned long usecs)
-{
-       int k;
-       
-       for (k = 0; k < 1000; k++) {
-               asm volatile ("nop");
-       }
-}
-#endif
-
-/* Wait while Graphics Engine is busy */
-inline void GfxBusyWait (volatile caddr_t board)
-{
-       int test;
-       DPRINTK("ENTER\n");
-       
-       do {
-               test = vgar16 (board, ECR_GP_STAT);
-               asm volatile ("nop");
-       } while (test & (1 << 9));
-       DPRINTK("EXIT\n");
-}
-
-/* Wait for any of the 8 Trio32 FIFOs to be free */ 
-inline void GfxFifoWait (volatile caddr_t board)
-{
-       int test;
-       DPRINTK("ENTER\n");
-       
-       do {
-               test = vgar16 (board, ECR_GP_STAT);
-       } while (test & 0x0f);
-       DPRINTK("EXIT\n");
-}
 
 /* Read Attribute Controller Register=idx */
-inline unsigned char RAttr (volatile caddr_t board, short idx)
+inline unsigned char RAttr (volatile unsigned char *regs, short idx)
 {
-       vgaw (board, ACT_ADDRESS_W, idx);
+       wb_64 (regs, ACT_ADDRESS_W, idx);
+       mb();
        udelay(100);
-       /* __cv_delay (0); */
-       return (vgar (board, ACT_ADDRESS_R));
+       return (rb_64(regs, ACT_ADDRESS_R));
 }
 
 /* Read Sequencer Register=idx */
-inline unsigned char RSeq (volatile caddr_t board, short idx)
+inline unsigned char RSeq (volatile unsigned char *regs, short idx)
 {
-       vgaw (board, SEQ_ADDRESS, idx);
-       return (vgar (board, SEQ_ADDRESS_R));
+       wb_64 (regs, SEQ_ADDRESS, idx);
+       mb();
+       return (rb_64(regs, SEQ_ADDRESS_R));
 }
 
 /* Read CRT Controller Register=idx */
-inline unsigned char RCrt (volatile caddr_t board, short idx)
+inline unsigned char RCrt (volatile unsigned char *regs, short idx)
 {
-       vgaw (board, CRT_ADDRESS, idx);
-       return (vgar (board, CRT_ADDRESS_R));
+       wb_64 (regs, CRT_ADDRESS, idx);
+       mb();
+       return (rb_64(regs, CRT_ADDRESS_R));
 }
 
 /* Read Graphics Controller Register=idx */
-inline unsigned char RGfx (volatile caddr_t board, short idx)
+inline unsigned char RGfx (volatile unsigned char *regs, short idx)
 {
-       vgaw (board, GCT_ADDRESS, idx);
-       return (vgar (board, GCT_ADDRESS_R));
+       wb_64 (regs, GCT_ADDRESS, idx);
+       mb();
+       return (rb_64(regs, GCT_ADDRESS_R));
 }
 
 /*
@@ -1526,13 +1456,13 @@ inline unsigned char RGfx (volatile caddr_t board, short idx)
  */
 
 inline void cv64_write_port (unsigned short bits,
-                            volatile unsigned char *board)
+                            volatile unsigned char *base)
 {
        volatile unsigned char *addr;
        static unsigned char cvportbits = 0; /* Mirror port bits here */
        DPRINTK("ENTER\n");
 
-       addr = board + 0x40001;
+       addr = base + 0x40001;
        if (bits & 0x8000) {
                cvportbits |= bits & 0xff; /* Set bits */
                DPRINTK("Set bits: %04x\n", bits);
@@ -1542,7 +1472,7 @@ inline void cv64_write_port (unsigned short bits,
                cvportbits &= bits; /* Clear bits */
                DPRINTK("Clear bits: %04x\n", bits);
        }
-       
+
        *addr = cvportbits;
        DPRINTK("EXIT\n");
 }
@@ -1572,7 +1502,7 @@ inline void cvscreen (int toggle, volatile unsigned char *board)
 /* Control screen display */
 /* toggle: 0 = on, 1 = off */
 /* board = registerbase */
-inline void gfx_on_off (int toggle, volatile unsigned char *board)
+inline void gfx_on_off(int toggle, volatile unsigned char *regs)
 {
        int r;
        DPRINTK("ENTER\n");
@@ -1581,10 +1511,10 @@ inline void gfx_on_off (int toggle, volatile unsigned char *board)
        toggle = toggle << 5;
        DPRINTK("Turn display %s\n", (toggle ? "off" : "on"));
        
-       r = (int) RSeq ((volatile caddr_t) board, SEQ_ID_CLOCKING_MODE);
+       r = (int) RSeq(regs, SEQ_ID_CLOCKING_MODE);
        r &= 0xdf;      /* Set bit 5 to 0 */
        
-       WSeq (board, SEQ_ID_CLOCKING_MODE, r | toggle);
+       WSeq (regs, SEQ_ID_CLOCKING_MODE, r | toggle);
        DPRINTK("EXIT\n");
 }
 
@@ -1640,11 +1570,11 @@ static unsigned short cv64_compute_clock(unsigned long freq)
        return (erg);
 }
 
-static int cv_has_4mb (volatile caddr_t fb)
+static int cv_has_4mb (volatile unsigned char *fb)
 {
        volatile unsigned long *tr, *tw;
        DPRINTK("ENTER\n");
-       
+
        /* write patterns in memory and test if they can be read */
        tw = (volatile unsigned long *) fb;
        tr = (volatile unsigned long *) (fb + 0x02000000);
@@ -1655,41 +1585,42 @@ static int cv_has_4mb (volatile caddr_t fb)
                DPRINTK("EXIT - <4MB\n");
                return (0);
        }
-       
+
        /* upper memory region */
        tw = (volatile unsigned long *) (fb + 0x00200000);
        tr = (volatile unsigned long *) (fb + 0x02200000);
-       
+
        *tw = 0x87654321;
-       
+
        if (*tr != 0x87654321) {
                DPRINTK("EXIT - <4MB\n");
                return (0);
        }
-       
+
        *tw = 0xAAAAAAAA;
-       
+
        if (*tr != 0xAAAAAAAA) {
                DPRINTK("EXIT - <4MB\n");
                return (0);
        }
-       
+
        *tw = 0x55555555;
-       
+
        if (*tr != 0x55555555) {
                DPRINTK("EXIT - <4MB\n");
                return (0);
        }
-       
+
        DPRINTK("EXIT\n");
        return (1);
 }
 
 static void cv64_board_init (void)
 {
+       volatile unsigned char *regs = CyberRegs;
        int i;
-       unsigned char test;
        unsigned int clockpar;
+       unsigned char test;
        
        DPRINTK("ENTER\n");
 
@@ -1698,259 +1629,252 @@ static void cv64_board_init (void)
         */
        /* Reset board */
        for (i = 0; i < 6; i++) {
-               cv64_write_port (0xff, (volatile unsigned char *) cv64_mem);
+               cv64_write_port (0xff, CyberBase);
        }
        /* Return to operational mode */
-       cv64_write_port (0x8004, (volatile unsigned char *) cv64_mem);
+       cv64_write_port (0x8004, CyberBase);
        
-  /*
-   * Generic (?) S3 chip wakeup
-   */
-  /* Disable I/O & memory decoders, video in setup mode */
-  vgaw (cv64_regs, SREG_VIDEO_SUBS_ENABLE, 0x10);
-  /* Video responds to cmds, addrs & data */
-  vgaw (cv64_regs, SREG_OPTION_SELECT, 0x1);
-  /* Enable I/O & memory decoders, video in operational mode */
-  vgaw (cv64_regs, SREG_VIDEO_SUBS_ENABLE, 0x8);
-  /* VGA color emulation, enable cpu access to display mem */ 
-  vgaw (cv64_regs, GREG_MISC_OUTPUT_W, 0x03);
-  /* Unlock S3 VGA regs */
-  WCrt (cv64_regs, CRT_ID_REGISTER_LOCK_1, 0x48); 
-  /* Unlock system control & extension registers */
-  WCrt (cv64_regs, CRT_ID_REGISTER_LOCK_2, 0xA5);
+       /*
+        * Generic (?) S3 chip wakeup
+        */
+       /* Disable I/O & memory decoders, video in setup mode */
+       wb_64 (regs, SREG_VIDEO_SUBS_ENABLE, 0x10);
+       /* Video responds to cmds, addrs & data */
+       wb_64 (regs, SREG_OPTION_SELECT, 0x1);
+       /* Enable I/O & memory decoders, video in operational mode */
+       wb_64 (regs, SREG_VIDEO_SUBS_ENABLE, 0x8);
+       /* VGA color emulation, enable cpu access to display mem */ 
+       wb_64 (regs, GREG_MISC_OUTPUT_W, 0x03);
+       /* Unlock S3 VGA regs */
+       WCrt (regs, CRT_ID_REGISTER_LOCK_1, 0x48); 
+       /* Unlock system control & extension registers */
+       WCrt (regs, CRT_ID_REGISTER_LOCK_2, 0xA5);
 /* GRF - Enable interrupts */
-  /* Enable enhanced regs access, Ready cntl 0 wait states */
-  test = RCrt (cv64_regs, CRT_ID_SYSTEM_CONFIG);
-  test = test | 0x01;          /* enable enhaced register access */
-  test = test & 0xEF;          /* clear bit 4, 0 wait state */
-  WCrt (cv64_regs, CRT_ID_SYSTEM_CONFIG, test);
-  /*
-   * bit 0=1: Enable enhaced mode functions
-   * bit 2=0: Enhanced mode 8+ bits/pixel
-   * bit 4=1: Enable linear addressing
-   * bit 5=1: Enable MMIO
-   */
-  vgaw (cv64_regs, ECR_ADV_FUNC_CNTL, 0x31);
-  /*
-   * bit 0=1: Color emulation
-   * bit 1=1: Enable CPU access to display memory
-   * bit 5=1: Select high 64K memory page
-   */
+       /* Enable enhanced regs access, Ready cntl 0 wait states */
+       test = RCrt (regs, CRT_ID_SYSTEM_CONFIG);
+       test = test | 0x01;             /* enable enhanced register access */
+       test = test & 0xEF;             /* clear bit 4, 0 wait state */
+       WCrt (regs, CRT_ID_SYSTEM_CONFIG, test);
+       /*
+        * bit 0=1: Enable enhaced mode functions
+        * bit 2=0: Enhanced mode 8+ bits/pixel
+        * bit 4=1: Enable linear addressing
+        * bit 5=1: Enable MMIO
+        */
+       wb_64 (regs, ECR_ADV_FUNC_CNTL, 0x31);
+       /*
+        * bit 0=1: Color emulation
+        * bit 1=1: Enable CPU access to display memory
+        * bit 5=1: Select high 64K memory page
+        */
 /* GRF - 0xE3 */
-  vgaw (cv64_regs, GREG_MISC_OUTPUT_W, 0x23);
-       
-  /* Cpu base addr */
-  WCrt (cv64_regs, CRT_ID_EXT_SYS_CNTL_4, 0x0);
-       
-  /* Reset. This does nothing on Trio, but standard VGA practice */
-  /* WSeq (cv64_regs, SEQ_ID_RESET, 0x03); */
-  /* Character clocks 8 dots wide */
-  WSeq (cv64_regs, SEQ_ID_CLOCKING_MODE, 0x01);
-  /* Enable cpu write to all color planes */
-  WSeq (cv64_regs, SEQ_ID_MAP_MASK, 0x0F);
-  /* Font table in 1st 8k of plane 2, font A=B disables swtich */
-  WSeq (cv64_regs, SEQ_ID_CHAR_MAP_SELECT, 0x0);
-  /* Allow mem access to 256kb */
-  WSeq (cv64_regs, SEQ_ID_MEMORY_MODE, 0x2);
-  /* Unlock S3 extensions to VGA Sequencer regs */
-  WSeq (cv64_regs, SEQ_ID_UNLOCK_EXT, 0x6);
-       
-  /* Enable 4MB fast page mode */
-  test = RSeq (cv64_regs, SEQ_ID_BUS_REQ_CNTL);
-  test = test | 1 << 6;
-  WSeq (cv64_regs, SEQ_ID_BUS_REQ_CNTL, test);
-       
-  /* Faster LUT write: 1 DCLK LUT write cycle, RAMDAC clk doubled */
-  WSeq (cv64_regs, SEQ_ID_RAMDAC_CNTL, 0xC0);
-       
-  /* Clear immediate clock load bit */
-  test = RSeq (cv64_regs, SEQ_ID_CLKSYN_CNTL_2);
-  test = test & 0xDF;
-  /* If > 55MHz, enable 2 cycle memory write */
-  if (cv64_memclk >= 55000000) {
-    test |= 0x80;
-  }
-  WSeq (cv64_regs, SEQ_ID_CLKSYN_CNTL_2, test);
-
-  /* Set MCLK value */
-  clockpar = cv64_compute_clock (cv64_memclk);
-  test = (clockpar & 0xFF00) >> 8;
-  WSeq (cv64_regs, SEQ_ID_MCLK_HI, test);
-  test = clockpar & 0xFF;
-  WSeq (cv64_regs, SEQ_ID_MCLK_LO, test);
-
-  /* Chip rev specific: Not in my Trio manual!!! */
-  if (RCrt (cv64_regs, CRT_ID_REVISION) == 0x10)
-    WSeq (cv64_regs, SEQ_ID_MORE_MAGIC, test);
-       
-  /* We now load an 25 MHz, 31kHz, 640x480 standard VGA Mode. */
-
-  /* Set DCLK value */
-  WSeq (cv64_regs, SEQ_ID_DCLK_HI, 0x13);
-  WSeq (cv64_regs, SEQ_ID_DCLK_LO, 0x41);
-
-  /* Load DCLK (and MCLK?) immediately */
-  test = RSeq (cv64_regs, SEQ_ID_CLKSYN_CNTL_2);
-  test = test | 0x22;
-  WSeq (cv64_regs, SEQ_ID_CLKSYN_CNTL_2, test);
-
-  /* Enable loading of DCLK */
-  test = vgar (cv64_regs, GREG_MISC_OUTPUT_R);
-  test = test | 0x0C;
-  vgaw (cv64_regs, GREG_MISC_OUTPUT_W, test);
-
-  /* Turn off immediate xCLK load */
-  WSeq (cv64_regs, SEQ_ID_CLKSYN_CNTL_2, 0x2);
-
-  /* Horizontal character clock counts */
-  /* 8 LSB of 9 bits = total line - 5 */
-  WCrt (cv64_regs, CRT_ID_HOR_TOTAL, 0x5F);
-  /* Active display line */
-  WCrt (cv64_regs, CRT_ID_HOR_DISP_ENA_END, 0x4F);
-  /* Blank assertion start */
-  WCrt (cv64_regs, CRT_ID_START_HOR_BLANK, 0x50);
-  /* Blank assertion end */
-  WCrt (cv64_regs, CRT_ID_END_HOR_BLANK, 0x82);
-  /* HSYNC assertion start */
-  WCrt (cv64_regs, CRT_ID_START_HOR_RETR, 0x54);
-  /* HSYNC assertion end */
-  WCrt (cv64_regs, CRT_ID_END_HOR_RETR, 0x80);
-  WCrt (cv64_regs, CRT_ID_VER_TOTAL, 0xBF);
-  WCrt (cv64_regs, CRT_ID_OVERFLOW, 0x1F);
-  WCrt (cv64_regs, CRT_ID_PRESET_ROW_SCAN, 0x0);
-  WCrt (cv64_regs, CRT_ID_MAX_SCAN_LINE, 0x40);
-  WCrt (cv64_regs, CRT_ID_CURSOR_START, 0x00);
-  WCrt (cv64_regs, CRT_ID_CURSOR_END, 0x00);
-  WCrt (cv64_regs, CRT_ID_START_ADDR_HIGH, 0x00);
-  WCrt (cv64_regs, CRT_ID_START_ADDR_LOW, 0x00);
-  WCrt (cv64_regs, CRT_ID_CURSOR_LOC_HIGH, 0x00);
-  WCrt (cv64_regs, CRT_ID_CURSOR_LOC_LOW, 0x00);
-  WCrt (cv64_regs, CRT_ID_START_VER_RETR, 0x9C);
-  WCrt (cv64_regs, CRT_ID_END_VER_RETR, 0x0E);
-  WCrt (cv64_regs, CRT_ID_VER_DISP_ENA_END, 0x8F);
-  WCrt (cv64_regs, CRT_ID_SCREEN_OFFSET, 0x50);
-  WCrt (cv64_regs, CRT_ID_UNDERLINE_LOC, 0x00);
-  WCrt (cv64_regs, CRT_ID_START_VER_BLANK, 0x96);
-  WCrt (cv64_regs, CRT_ID_END_VER_BLANK, 0xB9);
-  WCrt (cv64_regs, CRT_ID_MODE_CONTROL, 0xE3);
-  WCrt (cv64_regs, CRT_ID_LINE_COMPARE, 0xFF);
-  WCrt (cv64_regs, CRT_ID_BACKWAD_COMP_3, 0x10);       /* FIFO enabled */
-  WCrt (cv64_regs, CRT_ID_MISC_1, 0x35);
-  WCrt (cv64_regs, CRT_ID_DISPLAY_FIFO, 0x5A);
-  WCrt (cv64_regs, CRT_ID_EXT_MEM_CNTL_2, 0x70);
-  WCrt (cv64_regs, CRT_ID_LAW_POS_LO, 0x40);
-  WCrt (cv64_regs, CRT_ID_EXT_MEM_CNTL_3, 0xFF);
-  
-  WGfx (cv64_regs, GCT_ID_SET_RESET, 0x0);
-  WGfx (cv64_regs, GCT_ID_ENABLE_SET_RESET, 0x0);
-  WGfx (cv64_regs, GCT_ID_COLOR_COMPARE, 0x0);
-  WGfx (cv64_regs, GCT_ID_DATA_ROTATE, 0x0);
-  WGfx (cv64_regs, GCT_ID_READ_MAP_SELECT, 0x0);
-  WGfx (cv64_regs, GCT_ID_GRAPHICS_MODE, 0x40);
-  WGfx (cv64_regs, GCT_ID_MISC, 0x01);
-  WGfx (cv64_regs, GCT_ID_COLOR_XCARE, 0x0F);
-  WGfx (cv64_regs, GCT_ID_BITMASK, 0xFF);
-       
-  /* Colors for text mode */
-  for (i = 0; i < 0xf; i++)
-    WAttr (cv64_regs, i, i);
-       
-  WAttr (cv64_regs, ACT_ID_ATTR_MODE_CNTL, 0x41);
-  WAttr (cv64_regs, ACT_ID_OVERSCAN_COLOR, 0x01);
-  WAttr (cv64_regs, ACT_ID_COLOR_PLANE_ENA, 0x0F);
-  WAttr (cv64_regs, ACT_ID_HOR_PEL_PANNING, 0x0);
-  WAttr (cv64_regs, ACT_ID_COLOR_SELECT, 0x0);
-       
-  vgaw (cv64_regs, VDAC_MASK, 0xFF);
-       
-  *((unsigned long *) (cv64_regs + ECR_FRGD_COLOR)) = 0xFF;
-  *((unsigned long *) (cv64_regs + ECR_BKGD_COLOR)) = 0;
-       
-  /* Colors initially set to grayscale */
-       
-  vgaw (cv64_regs, VDAC_ADDRESS_W, 0);
-  for (i = 255; i >= 0; i--) {
-    vgaw (cv64_regs, VDAC_DATA, i);
-    vgaw (cv64_regs, VDAC_DATA, i);
-    vgaw (cv64_regs, VDAC_DATA, i);
-  }
+       wb_64 (regs, GREG_MISC_OUTPUT_W, 0x23);
+       
+       /* Cpu base addr */
+       WCrt (regs, CRT_ID_EXT_SYS_CNTL_4, 0x0);
+       
+       /* Reset. This does nothing on Trio, but standard VGA practice */
+       /* WSeq (CyberRegs, SEQ_ID_RESET, 0x03); */
+       /* Character clocks 8 dots wide */
+       WSeq (regs, SEQ_ID_CLOCKING_MODE, 0x01);
+       /* Enable cpu write to all color planes */
+       WSeq (regs, SEQ_ID_MAP_MASK, 0x0F);
+       /* Font table in 1st 8k of plane 2, font A=B disables swtich */
+       WSeq (regs, SEQ_ID_CHAR_MAP_SELECT, 0x0);
+       /* Allow mem access to 256kb */
+       WSeq (regs, SEQ_ID_MEMORY_MODE, 0x2);
+       /* Unlock S3 extensions to VGA Sequencer regs */
+       WSeq (regs, SEQ_ID_UNLOCK_EXT, 0x6);
+       
+       /* Enable 4MB fast page mode */
+       test = RSeq (regs, SEQ_ID_BUS_REQ_CNTL);
+       test = test | 1 << 6;
+       WSeq (regs, SEQ_ID_BUS_REQ_CNTL, test);
+       
+       /* Faster LUT write: 1 DCLK LUT write cycle, RAMDAC clk doubled */
+       WSeq (regs, SEQ_ID_RAMDAC_CNTL, 0xC0);
+
+       /* Clear immediate clock load bit */
+       test = RSeq (regs, SEQ_ID_CLKSYN_CNTL_2);
+       test = test & 0xDF;
+       /* If > 55MHz, enable 2 cycle memory write */
+       if (cv64_memclk >= 55000000) {
+               test |= 0x80;
+       }
+       WSeq (regs, SEQ_ID_CLKSYN_CNTL_2, test);
+
+       /* Set MCLK value */
+       clockpar = cv64_compute_clock (cv64_memclk);
+       test = (clockpar & 0xFF00) >> 8;
+       WSeq (regs, SEQ_ID_MCLK_HI, test);
+       test = clockpar & 0xFF;
+       WSeq (regs, SEQ_ID_MCLK_LO, test);
+
+       /* Chip rev specific: Not in my Trio manual!!! */
+       if (RCrt (regs, CRT_ID_REVISION) == 0x10)
+               WSeq (regs, SEQ_ID_MORE_MAGIC, test);
+
+       /* We now load an 25 MHz, 31kHz, 640x480 standard VGA Mode. */
+
+       /* Set DCLK value */
+       WSeq (regs, SEQ_ID_DCLK_HI, 0x13);
+       WSeq (regs, SEQ_ID_DCLK_LO, 0x41);
+
+       /* Load DCLK (and MCLK?) immediately */
+       test = RSeq (regs, SEQ_ID_CLKSYN_CNTL_2);
+       test = test | 0x22;
+       WSeq (regs, SEQ_ID_CLKSYN_CNTL_2, test);
+
+       /* Enable loading of DCLK */
+       test = rb_64(regs, GREG_MISC_OUTPUT_R);
+       test = test | 0x0C;
+       wb_64 (regs, GREG_MISC_OUTPUT_W, test);
+
+       /* Turn off immediate xCLK load */
+       WSeq (regs, SEQ_ID_CLKSYN_CNTL_2, 0x2);
+
+       /* Horizontal character clock counts */
+       /* 8 LSB of 9 bits = total line - 5 */
+       WCrt (regs, CRT_ID_HOR_TOTAL, 0x5F);
+       /* Active display line */
+       WCrt (regs, CRT_ID_HOR_DISP_ENA_END, 0x4F);
+       /* Blank assertion start */
+       WCrt (regs, CRT_ID_START_HOR_BLANK, 0x50);
+       /* Blank assertion end */
+       WCrt (regs, CRT_ID_END_HOR_BLANK, 0x82);
+       /* HSYNC assertion start */
+       WCrt (regs, CRT_ID_START_HOR_RETR, 0x54);
+       /* HSYNC assertion end */
+       WCrt (regs, CRT_ID_END_HOR_RETR, 0x80);
+       WCrt (regs, CRT_ID_VER_TOTAL, 0xBF);
+       WCrt (regs, CRT_ID_OVERFLOW, 0x1F);
+       WCrt (regs, CRT_ID_PRESET_ROW_SCAN, 0x0);
+       WCrt (regs, CRT_ID_MAX_SCAN_LINE, 0x40);
+       WCrt (regs, CRT_ID_CURSOR_START, 0x00);
+       WCrt (regs, CRT_ID_CURSOR_END, 0x00);
+       WCrt (regs, CRT_ID_START_ADDR_HIGH, 0x00);
+       WCrt (regs, CRT_ID_START_ADDR_LOW, 0x00);
+       WCrt (regs, CRT_ID_CURSOR_LOC_HIGH, 0x00);
+       WCrt (regs, CRT_ID_CURSOR_LOC_LOW, 0x00);
+       WCrt (regs, CRT_ID_START_VER_RETR, 0x9C);
+       WCrt (regs, CRT_ID_END_VER_RETR, 0x0E);
+       WCrt (regs, CRT_ID_VER_DISP_ENA_END, 0x8F);
+       WCrt (regs, CRT_ID_SCREEN_OFFSET, 0x50);
+       WCrt (regs, CRT_ID_UNDERLINE_LOC, 0x00);
+       WCrt (regs, CRT_ID_START_VER_BLANK, 0x96);
+       WCrt (regs, CRT_ID_END_VER_BLANK, 0xB9);
+       WCrt (regs, CRT_ID_MODE_CONTROL, 0xE3);
+       WCrt (regs, CRT_ID_LINE_COMPARE, 0xFF);
+       WCrt (regs, CRT_ID_BACKWAD_COMP_3, 0x10);       /* FIFO enabled */
+       WCrt (regs, CRT_ID_MISC_1, 0x35);
+       WCrt (regs, CRT_ID_DISPLAY_FIFO, 0x5A);
+       WCrt (regs, CRT_ID_EXT_MEM_CNTL_2, 0x70);
+       WCrt (regs, CRT_ID_LAW_POS_LO, 0x40);
+       WCrt (regs, CRT_ID_EXT_MEM_CNTL_3, 0xFF);
+
+       WGfx (regs, GCT_ID_SET_RESET, 0x0);
+       WGfx (regs, GCT_ID_ENABLE_SET_RESET, 0x0);
+       WGfx (regs, GCT_ID_COLOR_COMPARE, 0x0);
+       WGfx (regs, GCT_ID_DATA_ROTATE, 0x0);
+       WGfx (regs, GCT_ID_READ_MAP_SELECT, 0x0);
+       WGfx (regs, GCT_ID_GRAPHICS_MODE, 0x40);
+       WGfx (regs, GCT_ID_MISC, 0x01);
+       WGfx (regs, GCT_ID_COLOR_XCARE, 0x0F);
+       WGfx (regs, GCT_ID_BITMASK, 0xFF);
+
+       /* Colors for text mode */
+       for (i = 0; i < 0xf; i++)
+               WAttr (regs, i, i);
+
+       WAttr (regs, ACT_ID_ATTR_MODE_CNTL, 0x41);
+       WAttr (regs, ACT_ID_OVERSCAN_COLOR, 0x01);
+       WAttr (regs, ACT_ID_COLOR_PLANE_ENA, 0x0F);
+       WAttr (regs, ACT_ID_HOR_PEL_PANNING, 0x0);
+       WAttr (regs, ACT_ID_COLOR_SELECT, 0x0);
+
+       wb_64 (regs, VDAC_MASK, 0xFF);
+
+       *((unsigned long *) (regs + ECR_FRGD_COLOR)) = 0xFF;
+       *((unsigned long *) (regs + ECR_BKGD_COLOR)) = 0;
+
+       /* Colors initially set to grayscale */
+
+       wb_64 (regs, VDAC_ADDRESS_W, 0);
+       for (i = 255; i >= 0; i--) {
+               wb_64(regs, VDAC_DATA, i);
+               wb_64(regs, VDAC_DATA, i);
+               wb_64(regs, VDAC_DATA, i);
+       }
 
-  /* GFx hardware cursor off */
-  WCrt (cv64_regs, CRT_ID_HWGC_MODE, 0x00);
+       /* GFx hardware cursor off */
+       WCrt (regs, CRT_ID_HWGC_MODE, 0x00);
 
-  /* Set first to 4MB, so test will work */
-  WCrt (cv64_regs, CRT_ID_LAW_CNTL, 0x13);
-  /* Find "correct" size of fbmem of Z3 board */
-  if (cv_has_4mb ((volatile caddr_t) cv64_fbmem)) {
-    cv64_size = 1024 * 1024 * 4;
-    WCrt (cv64_regs, CRT_ID_LAW_CNTL, 0x13);
-    DPRINTK("4MB board\n");
-  } else {
-    cv64_size = 1024 * 1024 * 2;
-    WCrt (cv64_regs, CRT_ID_LAW_CNTL, 0x12);
-    DPRINTK("2MB board\n");
-  }
-       
-  /* Initialize graphics engine */
-  Cyber_WaitBlit();
-  /* GfxBusyWait (cv64_regs); */
-  vgaw16 (cv64_regs, ECR_FRGD_MIX, 0x27);
-  vgaw16 (cv64_regs, ECR_BKGD_MIX, 0x07);
-  vgaw16 (cv64_regs, ECR_READ_REG_DATA, 0x1000);
-  udelay(200);
-  /* __cv_delay (200000); */
-  vgaw16 (cv64_regs, ECR_READ_REG_DATA, 0x2000);
-  Cyber_WaitBlit();
-  /* GfxBusyWait (cv64_regs); */
-  vgaw16 (cv64_regs, ECR_READ_REG_DATA, 0x3FFF);
-  Cyber_WaitBlit();
-  /* GfxBusyWait (cv64_regs); */
-  udelay(200);
-  /* __cv_delay (200000); */
-  vgaw16 (cv64_regs, ECR_READ_REG_DATA, 0x4FFF);
-  Cyber_WaitBlit();
-  /* GfxBusyWait (cv64_regs); */
-  vgaw16 (cv64_regs, ECR_BITPLANE_WRITE_MASK, ~0);
-  Cyber_WaitBlit();
-  /* GfxBusyWait (cv64_regs); */
-  vgaw16 (cv64_regs, ECR_READ_REG_DATA, 0xE000);
-  vgaw16 (cv64_regs, ECR_CURRENT_Y_POS2, 0x00);
-  vgaw16 (cv64_regs, ECR_CURRENT_X_POS2, 0x00);
-  vgaw16 (cv64_regs, ECR_READ_REG_DATA, 0xA000);
-  vgaw16 (cv64_regs, ECR_DEST_Y__AX_STEP, 0x00);
-  vgaw16 (cv64_regs, ECR_DEST_Y2__AX_STEP2, 0x00);
-  vgaw16 (cv64_regs, ECR_DEST_X__DIA_STEP, 0x00);
-  vgaw16 (cv64_regs, ECR_DEST_X2__DIA_STEP2, 0x00);
-  vgaw16 (cv64_regs, ECR_SHORT_STROKE, 0x00);
-  vgaw16 (cv64_regs, ECR_DRAW_CMD, 0x01);
-       
-  Cyber_WaitBlit();
-  /* GfxBusyWait (cv64_regs); */
-       
-  vgaw16 (cv64_regs, ECR_READ_REG_DATA, 0x4FFF);
-  vgaw16 (cv64_regs, ECR_BKGD_COLOR, 0x01);
-  vgaw16 (cv64_regs, ECR_FRGD_COLOR, 0x00);
-       
-       
-  /* Enable video display (set bit 5) */
+       /* Set first to 4MB, so test will work */
+       WCrt (regs, CRT_ID_LAW_CNTL, 0x13);
+       /* Find "correct" size of fbmem of Z3 board */
+       if (cv_has_4mb (CyberMem)) {
+               CyberSize = 1024 * 1024 * 4;
+               WCrt (regs, CRT_ID_LAW_CNTL, 0x13);
+               DPRINTK("4MB board\n");
+       } else {
+               CyberSize = 1024 * 1024 * 2;
+               WCrt (regs, CRT_ID_LAW_CNTL, 0x12);
+               DPRINTK("2MB board\n");
+       }
+
+       /* Initialize graphics engine */
+       Cyber_WaitBlit();
+       vgaw16 (regs, ECR_FRGD_MIX, 0x27);
+       vgaw16 (regs, ECR_BKGD_MIX, 0x07);
+       vgaw16 (regs, ECR_READ_REG_DATA, 0x1000);
+       udelay(200);
+       vgaw16 (regs, ECR_READ_REG_DATA, 0x2000);
+       Cyber_WaitBlit();
+       vgaw16 (regs, ECR_READ_REG_DATA, 0x3FFF);
+       Cyber_WaitBlit();
+       udelay(200);
+       vgaw16 (regs, ECR_READ_REG_DATA, 0x4FFF);
+       Cyber_WaitBlit();
+       vgaw16 (regs, ECR_BITPLANE_WRITE_MASK, ~0);
+       Cyber_WaitBlit();
+       vgaw16 (regs, ECR_READ_REG_DATA, 0xE000);
+       vgaw16 (regs, ECR_CURRENT_Y_POS2, 0x00);
+       vgaw16 (regs, ECR_CURRENT_X_POS2, 0x00);
+       vgaw16 (regs, ECR_READ_REG_DATA, 0xA000);
+       vgaw16 (regs, ECR_DEST_Y__AX_STEP, 0x00);
+       vgaw16 (regs, ECR_DEST_Y2__AX_STEP2, 0x00);
+       vgaw16 (regs, ECR_DEST_X__DIA_STEP, 0x00);
+       vgaw16 (regs, ECR_DEST_X2__DIA_STEP2, 0x00);
+       vgaw16 (regs, ECR_SHORT_STROKE, 0x00);
+       vgaw16 (regs, ECR_DRAW_CMD, 0x01);
+
+       Cyber_WaitBlit();
+
+       vgaw16 (regs, ECR_READ_REG_DATA, 0x4FFF);
+       vgaw16 (regs, ECR_BKGD_COLOR, 0x01);
+       vgaw16 (regs, ECR_FRGD_COLOR, 0x00);
+
+
+       /* Enable video display (set bit 5) */
 /* ARB - Would also seem to write to AR13.
  *       May want to use parts of WAttr to set JUST bit 5
  */
-  WAttr (cv64_regs, 0x33, 0);
+       WAttr (regs, 0x33, 0);
        
 /* GRF - function code ended here */
 
-  /* Turn gfx on again */
-  gfx_on_off (0, cv64_regs);
-       
-  /* Pass-through */
-  cvscreen (0, (volatile unsigned char *) cv64_mem);
+       /* Turn gfx on again */
+       gfx_on_off (0, regs);
 
-  DPRINTK("EXIT\n");
+       /* Pass-through */
+       cvscreen (0, CyberBase);
+
+       DPRINTK("EXIT\n");
 }
 
 static void cv64_load_video_mode (struct fb_var_screeninfo *video_mode)
 {
+  volatile unsigned char *regs = CyberRegs;
   int fx, fy;
   unsigned short mnr;
   unsigned short HT, HDE, HBS, HBE, HSS, HSE, VDE, VBS, VBE, VSS, VSE, VT;
@@ -1977,7 +1901,7 @@ static void cv64_load_video_mode (struct fb_var_screeninfo *video_mode)
 
 /* GRF - Disable interrupts */ 
        
-  gfx_on_off (1, cv64_regs);
+  gfx_on_off (1, regs);
        
   switch (video_mode->bits_per_pixel) {
   case 15:
@@ -2049,7 +1973,7 @@ static void cv64_load_video_mode (struct fb_var_screeninfo *video_mode)
     VT  = yres + vfront + vsync + vback - 2;
   }
 
-  vgaw (cv64_regs, ECR_ADV_FUNC_CNTL, (TEXT ? 0x00 : 0x31));
+  wb_64 (regs, ECR_ADV_FUNC_CNTL, (TEXT ? 0x00 : 0x31));
        
   if (TEXT)
     HDE = ((video_mode->xres + fx - 1) / fx) - 1;
@@ -2058,15 +1982,15 @@ static void cv64_load_video_mode (struct fb_var_screeninfo *video_mode)
        
   VDE = video_mode->yres - 1;
 
-  WCrt (cv64_regs, CRT_ID_HWGC_MODE, 0x00);
-  WCrt (cv64_regs, CRT_ID_EXT_DAC_CNTL, 0x00);
+  WCrt (regs, CRT_ID_HWGC_MODE, 0x00);
+  WCrt (regs, CRT_ID_EXT_DAC_CNTL, 0x00);
        
-  WSeq (cv64_regs, SEQ_ID_MEMORY_MODE,
+  WSeq (regs, SEQ_ID_MEMORY_MODE,
        (TEXT || (video_mode->bits_per_pixel == 1)) ? 0x06 : 0x0e);
-  WGfx (cv64_regs, GCT_ID_READ_MAP_SELECT, 0x00);
-  WSeq (cv64_regs, SEQ_ID_MAP_MASK,
+  WGfx (regs, GCT_ID_READ_MAP_SELECT, 0x00);
+  WSeq (regs, SEQ_ID_MAP_MASK,
        (video_mode->bits_per_pixel == 1) ? 0x01 : 0xFF);
-  WSeq (cv64_regs, SEQ_ID_CHAR_MAP_SELECT, 0x00);
+  WSeq (regs, SEQ_ID_CHAR_MAP_SELECT, 0x00);
        
   /* cv64_compute_clock accepts arguments in Hz */
   /* pixclock is in ps ... convert to Hz */
@@ -2081,11 +2005,11 @@ static void cv64_load_video_mode (struct fb_var_screeninfo *video_mode)
 #endif
 
   mnr = cv64_compute_clock (freq);
-  WSeq (cv64_regs, SEQ_ID_DCLK_HI, ((mnr & 0xFF00) >> 8));
-  WSeq (cv64_regs, SEQ_ID_DCLK_LO, (mnr & 0xFF));
+  WSeq (regs, SEQ_ID_DCLK_HI, ((mnr & 0xFF00) >> 8));
+  WSeq (regs, SEQ_ID_DCLK_LO, (mnr & 0xFF));
        
   /* Load display parameters into board */
-  WCrt (cv64_regs, CRT_ID_EXT_HOR_OVF,
+  WCrt (regs, CRT_ID_EXT_HOR_OVF,
        ((HT & 0x100) ? 0x01 : 0x00) |
        ((HDE & 0x100) ? 0x02 : 0x00) |
        ((HBS & 0x100) ? 0x04 : 0x00) |
@@ -2095,7 +2019,7 @@ static void cv64_load_video_mode (struct fb_var_screeninfo *video_mode)
        (((HT-5) & 0x100) ? 0x40 : 0x00)
        );
        
-  WCrt (cv64_regs, CRT_ID_EXT_VER_OVF,
+  WCrt (regs, CRT_ID_EXT_VER_OVF,
        0x40 |
        ((VT & 0x400) ? 0x01 : 0x00) |
        ((VDE & 0x400) ? 0x02 : 0x00) |
@@ -2103,18 +2027,18 @@ static void cv64_load_video_mode (struct fb_var_screeninfo *video_mode)
        ((VSS & 0x400) ? 0x10 : 0x00)
        );
        
-  WCrt (cv64_regs, CRT_ID_HOR_TOTAL, HT);
-  WCrt (cv64_regs, CRT_ID_DISPLAY_FIFO, HT - 5);
-  WCrt (cv64_regs, CRT_ID_HOR_DISP_ENA_END, ((HDE >= HBS) ? (HBS - 1) : HDE));
-  WCrt (cv64_regs, CRT_ID_START_HOR_BLANK, HBS);
-  WCrt (cv64_regs, CRT_ID_END_HOR_BLANK, ((HBE & 0x1F) | 0x80));
-  WCrt (cv64_regs, CRT_ID_START_HOR_RETR, HSS);
-  WCrt (cv64_regs, CRT_ID_END_HOR_RETR,
+  WCrt (regs, CRT_ID_HOR_TOTAL, HT);
+  WCrt (regs, CRT_ID_DISPLAY_FIFO, HT - 5);
+  WCrt (regs, CRT_ID_HOR_DISP_ENA_END, ((HDE >= HBS) ? (HBS - 1) : HDE));
+  WCrt (regs, CRT_ID_START_HOR_BLANK, HBS);
+  WCrt (regs, CRT_ID_END_HOR_BLANK, ((HBE & 0x1F) | 0x80));
+  WCrt (regs, CRT_ID_START_HOR_RETR, HSS);
+  WCrt (regs, CRT_ID_END_HOR_RETR,
        (HSE & 0x1F) |
        ((HBE & 0x20) ? 0x80 : 0x00)
        );
-  WCrt (cv64_regs, CRT_ID_VER_TOTAL, VT);
-  WCrt (cv64_regs, CRT_ID_OVERFLOW,
+  WCrt (regs, CRT_ID_VER_TOTAL, VT);
+  WCrt (regs, CRT_ID_OVERFLOW,
        0x10 |
        ((VT & 0x100) ? 0x01 : 0x00) |
        ((VDE & 0x100) ? 0x02 : 0x00) |
@@ -2124,65 +2048,65 @@ static void cv64_load_video_mode (struct fb_var_screeninfo *video_mode)
        ((VDE & 0x200) ? 0x40 : 0x00) |
        ((VSS & 0x200) ? 0x80 : 0x00)
        );
-  WCrt (cv64_regs, CRT_ID_MAX_SCAN_LINE,
+  WCrt (regs, CRT_ID_MAX_SCAN_LINE,
        0x40 |
        (DBLSCAN ? 0x80 : 0x00) |
        ((VBS & 0x200) ? 0x20 : 0x00) |
        (TEXT ? ((fy - 1) & 0x1F) : 0x00)
        );
        
-  WCrt (cv64_regs, CRT_ID_MODE_CONTROL, 0xE3);
+  WCrt (regs, CRT_ID_MODE_CONTROL, 0xE3);
 
   /* Text cursor */
        
   if (TEXT) {
 #if 1
-    WCrt (cv64_regs, CRT_ID_CURSOR_START, (fy & 0x1f) - 2);
-    WCrt (cv64_regs, CRT_ID_CURSOR_END, (fy & 0x1F) - 1);
+    WCrt (regs, CRT_ID_CURSOR_START, (fy & 0x1f) - 2);
+    WCrt (regs, CRT_ID_CURSOR_END, (fy & 0x1F) - 1);
 #else
-    WCrt (cv64_regs, CRT_ID_CURSOR_START, 0x00);
-    WCrt (cv64_regs, CRT_ID_CURSOR_END, fy & 0x1F);
+    WCrt (regs, CRT_ID_CURSOR_START, 0x00);
+    WCrt (regs, CRT_ID_CURSOR_END, fy & 0x1F);
 #endif
-    WCrt (cv64_regs, CRT_ID_UNDERLINE_LOC, (fy - 1) & 0x1F);
-    WCrt (cv64_regs, CRT_ID_CURSOR_LOC_HIGH, 0x00);
-    WCrt (cv64_regs, CRT_ID_CURSOR_LOC_LOW, 0x00);
+    WCrt (regs, CRT_ID_UNDERLINE_LOC, (fy - 1) & 0x1F);
+    WCrt (regs, CRT_ID_CURSOR_LOC_HIGH, 0x00);
+    WCrt (regs, CRT_ID_CURSOR_LOC_LOW, 0x00);
   }
        
-  WCrt (cv64_regs, CRT_ID_START_ADDR_HIGH, 0x00);
-  WCrt (cv64_regs, CRT_ID_START_ADDR_LOW, 0x00);
-  WCrt (cv64_regs, CRT_ID_START_VER_RETR, VSS);
-  WCrt (cv64_regs, CRT_ID_END_VER_RETR, (VSE & 0x0F));
-  WCrt (cv64_regs, CRT_ID_VER_DISP_ENA_END, VDE);
-  WCrt (cv64_regs, CRT_ID_START_VER_BLANK, VBS);
-  WCrt (cv64_regs, CRT_ID_END_VER_BLANK, VBE);
-  WCrt (cv64_regs, CRT_ID_LINE_COMPARE, 0xFF);
-  WCrt (cv64_regs, CRT_ID_LACE_RETR_START, HT / 2);
-  WCrt (cv64_regs, CRT_ID_LACE_CONTROL, (LACE ? 0x20 : 0x00));
-  WGfx (cv64_regs, GCT_ID_GRAPHICS_MODE,
+  WCrt (regs, CRT_ID_START_ADDR_HIGH, 0x00);
+  WCrt (regs, CRT_ID_START_ADDR_LOW, 0x00);
+  WCrt (regs, CRT_ID_START_VER_RETR, VSS);
+  WCrt (regs, CRT_ID_END_VER_RETR, (VSE & 0x0F));
+  WCrt (regs, CRT_ID_VER_DISP_ENA_END, VDE);
+  WCrt (regs, CRT_ID_START_VER_BLANK, VBS);
+  WCrt (regs, CRT_ID_END_VER_BLANK, VBE);
+  WCrt (regs, CRT_ID_LINE_COMPARE, 0xFF);
+  WCrt (regs, CRT_ID_LACE_RETR_START, HT / 2);
+  WCrt (regs, CRT_ID_LACE_CONTROL, (LACE ? 0x20 : 0x00));
+  WGfx (regs, GCT_ID_GRAPHICS_MODE,
        ((TEXT || (video_mode->bits_per_pixel == 1)) ? 0x00 : 0x40));
-  WGfx (cv64_regs, GCT_ID_MISC, (TEXT ? 0x04 : 0x01));
-  WSeq (cv64_regs, SEQ_ID_MEMORY_MODE,
+  WGfx (regs, GCT_ID_MISC, (TEXT ? 0x04 : 0x01));
+  WSeq (regs, SEQ_ID_MEMORY_MODE,
        ((TEXT || (video_mode->bits_per_pixel == 1)) ? 0x06 : 0x02));
        
-  vgaw (cv64_regs, VDAC_MASK, 0xFF);
+  wb_64 (regs, VDAC_MASK, 0xFF);
        
   /* Blank border */
-  test = RCrt (cv64_regs, CRT_ID_BACKWAD_COMP_2);
-  WCrt (cv64_regs, CRT_ID_BACKWAD_COMP_2, (test | 0x20));
+  test = RCrt (regs, CRT_ID_BACKWAD_COMP_2);
+  WCrt (regs, CRT_ID_BACKWAD_COMP_2, (test | 0x20));
        
-  sr15 = RSeq (cv64_regs, SEQ_ID_CLKSYN_CNTL_2);
+  sr15 = RSeq (regs, SEQ_ID_CLKSYN_CNTL_2);
   sr15 &= 0xEF;
-  sr18 = RSeq (cv64_regs, SEQ_ID_RAMDAC_CNTL);
+  sr18 = RSeq (regs, SEQ_ID_RAMDAC_CNTL);
   sr18 &= 0x7F;
   clock_mode = 0x00;
   cr50 = 0x00;
        
-  test = RCrt (cv64_regs, CRT_ID_EXT_MISC_CNTL_2);
+  test = RCrt (regs, CRT_ID_EXT_MISC_CNTL_2);
   test &= 0xD;
        
   /* Clear roxxler byte-swapping... */
-  cv64_write_port (0x0040, (volatile unsigned char *) cv64_mem);
-  cv64_write_port (0x0020, (volatile unsigned char *) cv64_mem);
+  cv64_write_port (0x0040, CyberBase);
+  cv64_write_port (0x0020, CyberBase);
        
   switch (video_mode->bits_per_pixel) {
   case 1:
@@ -2201,14 +2125,14 @@ static void cv64_load_video_mode (struct fb_var_screeninfo *video_mode)
     break;
                
   case 15:
-    cv64_write_port (0x8020, (volatile unsigned char *) cv64_mem);
+    cv64_write_port (0x8020, CyberBase);
     clock_mode = 0x30;
     HDE = video_mode->xres / 4;
     cr50 |= 0x10;
     break;
                
   case 16:
-    cv64_write_port (0x8020, (volatile unsigned char *) cv64_mem);
+    cv64_write_port (0x8020, CyberBase);
     clock_mode = 0x50;
     HDE = video_mode->xres / 4;
     cr50 |= 0x10;
@@ -2216,24 +2140,24 @@ static void cv64_load_video_mode (struct fb_var_screeninfo *video_mode)
                
   case 24:
   case 32:
-    cv64_write_port (0x8040, (volatile unsigned char *) cv64_mem);
+    cv64_write_port (0x8040, CyberBase);
     clock_mode = 0xD0;
     HDE = video_mode->xres / 2;
     cr50 |= 0x30;
     break;
   }
-       
-  WCrt (cv64_regs, CRT_ID_EXT_MISC_CNTL_2, clock_mode | test);
-  WSeq (cv64_regs, SEQ_ID_CLKSYN_CNTL_2, sr15);
-  WSeq (cv64_regs, SEQ_ID_RAMDAC_CNTL, sr18);
-  WCrt (cv64_regs, CRT_ID_SCREEN_OFFSET, HDE);
 
-  WCrt (cv64_regs, CRT_ID_MISC_1, (TEXT ? 0x05 : 0x35));
+  WCrt (regs, CRT_ID_EXT_MISC_CNTL_2, clock_mode | test);
+  WSeq (regs, SEQ_ID_CLKSYN_CNTL_2, sr15);
+  WSeq (regs, SEQ_ID_RAMDAC_CNTL, sr18);
+  WCrt (regs, CRT_ID_SCREEN_OFFSET, HDE);
+
+  WCrt (regs, CRT_ID_MISC_1, (TEXT ? 0x05 : 0x35));
        
-  test = RCrt (cv64_regs, CRT_ID_EXT_SYS_CNTL_2);
+  test = RCrt (regs, CRT_ID_EXT_SYS_CNTL_2);
   test &= ~0x30;
   test |= (HDE >> 4) & 0x30;
-  WCrt (cv64_regs, CRT_ID_EXT_SYS_CNTL_2, test);
+  WCrt (regs, CRT_ID_EXT_SYS_CNTL_2, test);
        
   /* Set up graphics engine */
   switch (video_mode->xres) {
@@ -2265,17 +2189,14 @@ static void cv64_load_video_mode (struct fb_var_screeninfo *video_mode)
     break;
   }
        
-  WCrt (cv64_regs, CRT_ID_EXT_SYS_CNTL_1, cr50);
+  WCrt (regs, CRT_ID_EXT_SYS_CNTL_1, cr50);
        
   udelay(100);
-  /* __cv_delay (100000); */
-  WAttr (cv64_regs, ACT_ID_ATTR_MODE_CNTL, (TEXT ? 0x08 : 0x41));
+  WAttr (regs, ACT_ID_ATTR_MODE_CNTL, (TEXT ? 0x08 : 0x41));
   udelay(100);
-  /* __cv_delay (100000); */
-  WAttr (cv64_regs, ACT_ID_COLOR_PLANE_ENA,
+  WAttr (regs, ACT_ID_COLOR_PLANE_ENA,
         (video_mode->bits_per_pixel == 1) ? 0x01 : 0x0F);
   udelay(100);
-  /* __cv_delay (100000); */
        
   tfillm = (96 * (cv64_memclk / 1000)) / 240000;
        
@@ -2304,10 +2225,9 @@ static void cv64_load_video_mode (struct fb_var_screeninfo *video_mode)
     m = 0x18;
   n = 0xFF;
        
-  WCrt (cv64_regs, CRT_ID_EXT_MEM_CNTL_2, m);
-  WCrt (cv64_regs, CRT_ID_EXT_MEM_CNTL_3, n);
+  WCrt (regs, CRT_ID_EXT_MEM_CNTL_2, m);
+  WCrt (regs, CRT_ID_EXT_MEM_CNTL_3, n);
   udelay(10);
-  /* __cv_delay (10000); */
        
   /* Text initialization */
        
@@ -2317,21 +2237,21 @@ static void cv64_load_video_mode (struct fb_var_screeninfo *video_mode)
        
   if (CONSOLE) {
     int i;
-    vgaw (cv64_regs, VDAC_ADDRESS_W, 0);
+    wb_64 (regs, VDAC_ADDRESS_W, 0);
     for (i = 0; i < 4; i++) {
-      vgaw (cv64_regs, VDAC_DATA, cvconscolors [i][0]);
-      vgaw (cv64_regs, VDAC_DATA, cvconscolors [i][1]);
-      vgaw (cv64_regs, VDAC_DATA, cvconscolors [i][2]);
+      wb_64 (regs, VDAC_DATA, cvconscolors [i][0]);
+      wb_64 (regs, VDAC_DATA, cvconscolors [i][1]);
+      wb_64 (regs, VDAC_DATA, cvconscolors [i][2]);
     }
   }
        
-  WAttr (cv64_regs, 0x33, 0);
+  WAttr (regs, 0x33, 0);
        
   /* Turn gfx on again */
-  gfx_on_off (0, (volatile unsigned char *) cv64_regs);
+  gfx_on_off (0, (volatile unsigned char *) regs);
        
   /* Pass-through */
-  cvscreen (0, (volatile unsigned char *) cv64_mem);
+  cvscreen (0, CyberBase);
 
 DPRINTK("EXIT\n");
 }
@@ -2339,6 +2259,7 @@ DPRINTK("EXIT\n");
 void cvision_bitblt (u_short sx, u_short sy, u_short dx, u_short dy,
                     u_short w, u_short h)
 {
+       volatile unsigned char *regs = CyberRegs;
        unsigned short drawdir = 0;
        
        DPRINTK("ENTER\n");
@@ -2357,37 +2278,36 @@ void cvision_bitblt (u_short sx, u_short sy, u_short dx, u_short dy,
        }
        
        Cyber_WaitBlit();
-       /* GfxBusyWait (cv64_regs); */
-       vgaw16 (cv64_regs, ECR_READ_REG_DATA, 0xA000);
-       vgaw16 (cv64_regs, ECR_BKGD_MIX, 0x7);
-       vgaw16 (cv64_regs, ECR_FRGD_MIX, 0x67);
-       vgaw16 (cv64_regs, ECR_BKGD_COLOR, 0x0);
-       vgaw16 (cv64_regs, ECR_FRGD_COLOR, 0x1);
-       vgaw16 (cv64_regs, ECR_BITPLANE_READ_MASK, 0x1);
-       vgaw16 (cv64_regs, ECR_BITPLANE_WRITE_MASK, 0xFFF);
-       vgaw16 (cv64_regs, ECR_CURRENT_Y_POS, sy);
-       vgaw16 (cv64_regs, ECR_CURRENT_X_POS, sx);
-       vgaw16 (cv64_regs, ECR_DEST_Y__AX_STEP, dy);
-       vgaw16 (cv64_regs, ECR_DEST_X__DIA_STEP, dx);
-       vgaw16 (cv64_regs, ECR_READ_REG_DATA, h - 1);
-       vgaw16 (cv64_regs, ECR_MAJ_AXIS_PIX_CNT, w - 1);
-       vgaw16 (cv64_regs, ECR_DRAW_CMD, 0xC051 | drawdir);
+       vgaw16 (regs, ECR_READ_REG_DATA, 0xA000);
+       vgaw16 (regs, ECR_BKGD_MIX, 0x7);
+       vgaw16 (regs, ECR_FRGD_MIX, 0x67);
+       vgaw16 (regs, ECR_BKGD_COLOR, 0x0);
+       vgaw16 (regs, ECR_FRGD_COLOR, 0x1);
+       vgaw16 (regs, ECR_BITPLANE_READ_MASK, 0x1);
+       vgaw16 (regs, ECR_BITPLANE_WRITE_MASK, 0xFFF);
+       vgaw16 (regs, ECR_CURRENT_Y_POS, sy);
+       vgaw16 (regs, ECR_CURRENT_X_POS, sx);
+       vgaw16 (regs, ECR_DEST_Y__AX_STEP, dy);
+       vgaw16 (regs, ECR_DEST_X__DIA_STEP, dx);
+       vgaw16 (regs, ECR_READ_REG_DATA, h - 1);
+       vgaw16 (regs, ECR_MAJ_AXIS_PIX_CNT, w - 1);
+       vgaw16 (regs, ECR_DRAW_CMD, 0xC051 | drawdir);
        DPRINTK("EXIT\n");
 }
 
 void cvision_clear (u_short dx, u_short dy, u_short w, u_short h, u_short bg)
 {
+       volatile unsigned char *regs = CyberRegs;
        DPRINTK("ENTER\n");
        Cyber_WaitBlit();
-       /* GfxBusyWait (cv64_regs); */
-       vgaw16 (cv64_regs, ECR_FRGD_MIX, 0x0027);
-       vgaw16 (cv64_regs, ECR_FRGD_COLOR, bg);
-       vgaw16 (cv64_regs, ECR_READ_REG_DATA, 0xA000);
-       vgaw16 (cv64_regs, ECR_CURRENT_Y_POS, dy);
-       vgaw16 (cv64_regs, ECR_CURRENT_X_POS, dx);
-       vgaw16 (cv64_regs, ECR_READ_REG_DATA, h - 1);
-       vgaw16 (cv64_regs, ECR_MAJ_AXIS_PIX_CNT, w - 1);
-       vgaw16 (cv64_regs, ECR_DRAW_CMD, 0x40B1);       
+       vgaw16 (regs, ECR_FRGD_MIX, 0x0027);
+       vgaw16 (regs, ECR_FRGD_COLOR, bg);
+       vgaw16 (regs, ECR_READ_REG_DATA, 0xA000);
+       vgaw16 (regs, ECR_CURRENT_Y_POS, dy);
+       vgaw16 (regs, ECR_CURRENT_X_POS, dx);
+       vgaw16 (regs, ECR_READ_REG_DATA, h - 1);
+       vgaw16 (regs, ECR_MAJ_AXIS_PIX_CNT, w - 1);
+       vgaw16 (regs, ECR_DRAW_CMD, 0x40B1);    
        DPRINTK("EXIT\n");
 }
 
@@ -2397,83 +2317,84 @@ void cvision_clear (u_short dx, u_short dy, u_short w, u_short h, u_short bg)
  */
 static void cv64_dump (void)
 {
+       volatile unsigned char *regs = CyberRegs;
        DPRINTK("ENTER\n");
         /* Dump the VGA setup values */
-       *(CyberRegs + S3_CRTC_ADR) = 0x00;
-       DPRINTK("CR00 = %x\n", *(CyberRegs + S3_CRTC_DATA));
-       *(CyberRegs + S3_CRTC_ADR) = 0x01;
-       DPRINTK("CR01 = %x\n", *(CyberRegs + S3_CRTC_DATA));
-       *(CyberRegs + S3_CRTC_ADR) = 0x02;
-       DPRINTK("CR02 = %x\n", *(CyberRegs + S3_CRTC_DATA));
-       *(CyberRegs + S3_CRTC_ADR) = 0x03;
-       DPRINTK("CR03 = %x\n", *(CyberRegs + S3_CRTC_DATA));
-       *(CyberRegs + S3_CRTC_ADR) = 0x04;
-       DPRINTK("CR04 = %x\n", *(CyberRegs + S3_CRTC_DATA));
-       *(CyberRegs + S3_CRTC_ADR) = 0x05;
-       DPRINTK("CR05 = %x\n", *(CyberRegs + S3_CRTC_DATA));
-       *(CyberRegs + S3_CRTC_ADR) = 0x06;
-       DPRINTK("CR06 = %x\n", *(CyberRegs + S3_CRTC_DATA));
-       *(CyberRegs + S3_CRTC_ADR) = 0x07;
-       DPRINTK("CR07 = %x\n", *(CyberRegs + S3_CRTC_DATA));
-       *(CyberRegs + S3_CRTC_ADR) = 0x08;
-       DPRINTK("CR08 = %x\n", *(CyberRegs + S3_CRTC_DATA));
-       *(CyberRegs + S3_CRTC_ADR) = 0x09;
-       DPRINTK("CR09 = %x\n", *(CyberRegs + S3_CRTC_DATA));
-       *(CyberRegs + S3_CRTC_ADR) = 0x10;
-       DPRINTK("CR10 = %x\n", *(CyberRegs + S3_CRTC_DATA));
-       *(CyberRegs + S3_CRTC_ADR) = 0x11;
-       DPRINTK("CR11 = %x\n", *(CyberRegs + S3_CRTC_DATA));
-       *(CyberRegs + S3_CRTC_ADR) = 0x12;
-       DPRINTK("CR12 = %x\n", *(CyberRegs + S3_CRTC_DATA));
-       *(CyberRegs + S3_CRTC_ADR) = 0x13;
-       DPRINTK("CR13 = %x\n", *(CyberRegs + S3_CRTC_DATA));
-       *(CyberRegs + S3_CRTC_ADR) = 0x15;
-       DPRINTK("CR15 = %x\n", *(CyberRegs + S3_CRTC_DATA));
-       *(CyberRegs + S3_CRTC_ADR) = 0x16;
-       DPRINTK("CR16 = %x\n", *(CyberRegs + S3_CRTC_DATA));
-       *(CyberRegs + S3_CRTC_ADR) = 0x36;
-       DPRINTK("CR36 = %x\n", *(CyberRegs + S3_CRTC_DATA));
-       *(CyberRegs + S3_CRTC_ADR) = 0x37;
-       DPRINTK("CR37 = %x\n", *(CyberRegs + S3_CRTC_DATA));
-       *(CyberRegs + S3_CRTC_ADR) = 0x42;
-       DPRINTK("CR42 = %x\n", *(CyberRegs + S3_CRTC_DATA));
-       *(CyberRegs + S3_CRTC_ADR) = 0x43;
-       DPRINTK("CR43 = %x\n", *(CyberRegs + S3_CRTC_DATA));
-       *(CyberRegs + S3_CRTC_ADR) = 0x50;
-       DPRINTK("CR50 = %x\n", *(CyberRegs + S3_CRTC_DATA));
-       *(CyberRegs + S3_CRTC_ADR) = 0x51;
-       DPRINTK("CR51 = %x\n", *(CyberRegs + S3_CRTC_DATA));
-       *(CyberRegs + S3_CRTC_ADR) = 0x53;
-       DPRINTK("CR53 = %x\n", *(CyberRegs + S3_CRTC_DATA));
-       *(CyberRegs + S3_CRTC_ADR) = 0x58;
-       DPRINTK("CR58 = %x\n", *(CyberRegs + S3_CRTC_DATA));
-       *(CyberRegs + S3_CRTC_ADR) = 0x59;
-       DPRINTK("CR59 = %x\n", *(CyberRegs + S3_CRTC_DATA));
-       *(CyberRegs + S3_CRTC_ADR) = 0x5A;
-       DPRINTK("CR5A = %x\n", *(CyberRegs + S3_CRTC_DATA));
-       *(CyberRegs + S3_CRTC_ADR) = 0x5D;
-       DPRINTK("CR5D = %x\n", *(CyberRegs + S3_CRTC_DATA));
-       *(CyberRegs + S3_CRTC_ADR) = 0x5E;
-       DPRINTK("CR5E = %x\n", *(CyberRegs + S3_CRTC_DATA));
-       DPRINTK("MISC = %x\n", *(CyberRegs + GREG_MISC_OUTPUT_R));
-       *(CyberRegs + SEQ_ADDRESS) = 0x01;
-       DPRINTK("SR01 = %x\n", *(CyberRegs + SEQ_ADDRESS_R));
-       *(CyberRegs + SEQ_ADDRESS) = 0x02;
-       DPRINTK("SR02 = %x\n", *(CyberRegs + SEQ_ADDRESS_R));
-       *(CyberRegs + SEQ_ADDRESS) = 0x03;
-       DPRINTK("SR03 = %x\n", *(CyberRegs + SEQ_ADDRESS_R));
-       *(CyberRegs + SEQ_ADDRESS) = 0x09;
-       DPRINTK("SR09 = %x\n", *(CyberRegs + SEQ_ADDRESS_R));
-       *(CyberRegs + SEQ_ADDRESS) = 0x10;
-       DPRINTK("SR10 = %x\n", *(CyberRegs + SEQ_ADDRESS_R));
-       *(CyberRegs + SEQ_ADDRESS) = 0x11;
-       DPRINTK("SR11 = %x\n", *(CyberRegs + SEQ_ADDRESS_R));
-       *(CyberRegs + SEQ_ADDRESS) = 0x12;
-       DPRINTK("SR12 = %x\n", *(CyberRegs + SEQ_ADDRESS_R));
-       *(CyberRegs + SEQ_ADDRESS) = 0x13;
-       DPRINTK("SR13 = %x\n", *(CyberRegs + SEQ_ADDRESS_R));
-       *(CyberRegs + SEQ_ADDRESS) = 0x15;
-       DPRINTK("SR15 = %x\n", *(CyberRegs + SEQ_ADDRESS_R));
+       *(regs + S3_CRTC_ADR) = 0x00;
+       DPRINTK("CR00 = %x\n", *(regs + S3_CRTC_DATA));
+       *(regs + S3_CRTC_ADR) = 0x01;
+       DPRINTK("CR01 = %x\n", *(regs + S3_CRTC_DATA));
+       *(regs + S3_CRTC_ADR) = 0x02;
+       DPRINTK("CR02 = %x\n", *(regs + S3_CRTC_DATA));
+       *(regs + S3_CRTC_ADR) = 0x03;
+       DPRINTK("CR03 = %x\n", *(regs + S3_CRTC_DATA));
+       *(regs + S3_CRTC_ADR) = 0x04;
+       DPRINTK("CR04 = %x\n", *(regs + S3_CRTC_DATA));
+       *(regs + S3_CRTC_ADR) = 0x05;
+       DPRINTK("CR05 = %x\n", *(regs + S3_CRTC_DATA));
+       *(regs + S3_CRTC_ADR) = 0x06;
+       DPRINTK("CR06 = %x\n", *(regs + S3_CRTC_DATA));
+       *(regs + S3_CRTC_ADR) = 0x07;
+       DPRINTK("CR07 = %x\n", *(regs + S3_CRTC_DATA));
+       *(regs + S3_CRTC_ADR) = 0x08;
+       DPRINTK("CR08 = %x\n", *(regs + S3_CRTC_DATA));
+       *(regs + S3_CRTC_ADR) = 0x09;
+       DPRINTK("CR09 = %x\n", *(regs + S3_CRTC_DATA));
+       *(regs + S3_CRTC_ADR) = 0x10;
+       DPRINTK("CR10 = %x\n", *(regs + S3_CRTC_DATA));
+       *(regs + S3_CRTC_ADR) = 0x11;
+       DPRINTK("CR11 = %x\n", *(regs + S3_CRTC_DATA));
+       *(regs + S3_CRTC_ADR) = 0x12;
+       DPRINTK("CR12 = %x\n", *(regs + S3_CRTC_DATA));
+       *(regs + S3_CRTC_ADR) = 0x13;
+       DPRINTK("CR13 = %x\n", *(regs + S3_CRTC_DATA));
+       *(regs + S3_CRTC_ADR) = 0x15;
+       DPRINTK("CR15 = %x\n", *(regs + S3_CRTC_DATA));
+       *(regs + S3_CRTC_ADR) = 0x16;
+       DPRINTK("CR16 = %x\n", *(regs + S3_CRTC_DATA));
+       *(regs + S3_CRTC_ADR) = 0x36;
+       DPRINTK("CR36 = %x\n", *(regs + S3_CRTC_DATA));
+       *(regs + S3_CRTC_ADR) = 0x37;
+       DPRINTK("CR37 = %x\n", *(regs + S3_CRTC_DATA));
+       *(regs + S3_CRTC_ADR) = 0x42;
+       DPRINTK("CR42 = %x\n", *(regs + S3_CRTC_DATA));
+       *(regs + S3_CRTC_ADR) = 0x43;
+       DPRINTK("CR43 = %x\n", *(regs + S3_CRTC_DATA));
+       *(regs + S3_CRTC_ADR) = 0x50;
+       DPRINTK("CR50 = %x\n", *(regs + S3_CRTC_DATA));
+       *(regs + S3_CRTC_ADR) = 0x51;
+       DPRINTK("CR51 = %x\n", *(regs + S3_CRTC_DATA));
+       *(regs + S3_CRTC_ADR) = 0x53;
+       DPRINTK("CR53 = %x\n", *(regs + S3_CRTC_DATA));
+       *(regs + S3_CRTC_ADR) = 0x58;
+       DPRINTK("CR58 = %x\n", *(regs + S3_CRTC_DATA));
+       *(regs + S3_CRTC_ADR) = 0x59;
+       DPRINTK("CR59 = %x\n", *(regs + S3_CRTC_DATA));
+       *(regs + S3_CRTC_ADR) = 0x5A;
+       DPRINTK("CR5A = %x\n", *(regs + S3_CRTC_DATA));
+       *(regs + S3_CRTC_ADR) = 0x5D;
+       DPRINTK("CR5D = %x\n", *(regs + S3_CRTC_DATA));
+       *(regs + S3_CRTC_ADR) = 0x5E;
+       DPRINTK("CR5E = %x\n", *(regs + S3_CRTC_DATA));
+       DPRINTK("MISC = %x\n", *(regs + GREG_MISC_OUTPUT_R));
+       *(regs + SEQ_ADDRESS) = 0x01;
+       DPRINTK("SR01 = %x\n", *(regs + SEQ_ADDRESS_R));
+       *(regs + SEQ_ADDRESS) = 0x02;
+       DPRINTK("SR02 = %x\n", *(regs + SEQ_ADDRESS_R));
+       *(regs + SEQ_ADDRESS) = 0x03;
+       DPRINTK("SR03 = %x\n", *(regs + SEQ_ADDRESS_R));
+       *(regs + SEQ_ADDRESS) = 0x09;
+       DPRINTK("SR09 = %x\n", *(regs + SEQ_ADDRESS_R));
+       *(regs + SEQ_ADDRESS) = 0x10;
+       DPRINTK("SR10 = %x\n", *(regs + SEQ_ADDRESS_R));
+       *(regs + SEQ_ADDRESS) = 0x11;
+       DPRINTK("SR11 = %x\n", *(regs + SEQ_ADDRESS_R));
+       *(regs + SEQ_ADDRESS) = 0x12;
+       DPRINTK("SR12 = %x\n", *(regs + SEQ_ADDRESS_R));
+       *(regs + SEQ_ADDRESS) = 0x13;
+       DPRINTK("SR13 = %x\n", *(regs + SEQ_ADDRESS_R));
+       *(regs + SEQ_ADDRESS) = 0x15;
+       DPRINTK("SR15 = %x\n", *(regs + SEQ_ADDRESS_R));
        
        return;
 }
index bce02a462d059cce5434ae57ad702a4722426084..2acff941a099835ca0191adf6ceecc3d628fcf35 100644 (file)
 #define GRFBBOPset             0xf     /* 1 */
 
 
-/* Read VGA register */
-#define vgar(ba, reg) (*(((volatile caddr_t)ba)+reg))
-
-/* Write VGA register */
-#define vgaw(ba, reg, val) \
-*(((volatile caddr_t)ba)+reg) = ((val) & 0xff)
-
-/* Read 16 Bit VGA register */
-#define vgar16(ba, reg) (  *((unsigned short *) (((volatile caddr_t)ba)+reg)) )
-
 /* Write 16 Bit VGA register */
 #define vgaw16(ba, reg, val) \
-*((unsigned short *)  (((volatile caddr_t)ba)+reg)) = val
-
-/* Read 32 Bit VGA register */
-#define vgar32(ba, reg) (  *((unsigned long *) (((volatile caddr_t)ba)+reg)) )
-
-/* Write 32 Bit VGA register */
-#define vgaw32(ba, reg, val) \
-     *((unsigned long *)  (((volatile caddr_t)ba)+reg)) = val
+*((unsigned short *)  (((volatile unsigned char *)ba)+reg)) = val
 
 /*
  * Defines for the used register addresses (mw)
 
 
 #define WGfx(ba, idx, val) \
-do { vgaw(ba, GCT_ADDRESS, idx); vgaw(ba, GCT_ADDRESS_W , val); } while (0)
+do { wb_64(ba, GCT_ADDRESS, idx); wb_64(ba, GCT_ADDRESS_W , val); } while (0)
 
 #define WSeq(ba, idx, val) \
-do { vgaw(ba, SEQ_ADDRESS, idx); vgaw(ba, SEQ_ADDRESS_W , val); } while (0)
+do { wb_64(ba, SEQ_ADDRESS, idx); wb_64(ba, SEQ_ADDRESS_W , val); } while (0)
 
 #define WCrt(ba, idx, val) \
-do { vgaw(ba, CRT_ADDRESS, idx); vgaw(ba, CRT_ADDRESS_W , val); } while (0)
+do { wb_64(ba, CRT_ADDRESS, idx); wb_64(ba, CRT_ADDRESS_W , val); } while (0)
 
 #define WAttr(ba, idx, val) \
 do { \
   unsigned char tmp;\
-  tmp = vgar(ba, ACT_ADDRESS_RESET);\
-  vgaw(ba, ACT_ADDRESS_W, idx);\
-  vgaw(ba, ACT_ADDRESS_W, val);\
+  tmp = rb_64(ba, ACT_ADDRESS_RESET);\
+  wb_64(ba, ACT_ADDRESS_W, idx);\
+  wb_64(ba, ACT_ADDRESS_W, val);\
 } while (0)
 
 #define SetTextPlane(ba, m) \
@@ -420,21 +403,17 @@ do { \
      /* prototypes                        */
      /* --------------------------------- */
 
-/* in cvision_core.c */
-inline void __cv_delay(unsigned long usecs);
-inline void GfxBusyWait(volatile caddr_t board);
-inline void GfxFifoWait(volatile caddr_t board);
-inline unsigned char RAttr(volatile caddr_t board, short idx);
-inline unsigned char RSeq(volatile caddr_t board, short idx);
-inline unsigned char RCrt(volatile caddr_t board, short idx);
-inline unsigned char RGfx(volatile caddr_t board, short idx);
+inline unsigned char RAttr(volatile unsigned char * board, short idx);
+inline unsigned char RSeq(volatile unsigned char * board, short idx);
+inline unsigned char RCrt(volatile unsigned char * board, short idx);
+inline unsigned char RGfx(volatile unsigned char * board, short idx);
 inline void cv64_write_port(unsigned short bits,
                            volatile unsigned char *board);
 inline void cvscreen(int toggle, volatile unsigned char *board);
 inline void gfx_on_off(int toggle, volatile unsigned char *board);
 #if 0
 unsigned short cv64_compute_clock(unsigned long freq);
-int cv_has_4mb(volatile caddr_t fb);
+int cv_has_4mb(volatile unsigned char * fb);
 void cv64_board_init(void);
 void cv64_load_video_mode(struct fb_var_screeninfo *video_mode);
 #endif
index ea8743495ac3c62321e45990438d1a50ee5b5e64..ecabee5e581c172c9d7dbce36528ab30a5fcf616 100644 (file)
@@ -25,7 +25,7 @@
 #define DUMMY_ROWS     25
 #endif
 
-__initfunc(static const char *dummycon_startup(void))
+static const char __init *dummycon_startup(void)
 {
     return "dummy device";
 }
index 0389cee23520d4cc37504edacca0a51bdf6f3f4c..1895dd39657fd41793e47a77386d2faadb66480b 100644 (file)
@@ -1364,7 +1364,6 @@ static int fbcon_switch(struct vc_data *conp)
        p->dispsw->clear_margins(conp, p, 0);
     if (logo_shown == -2) {
        logo_shown = fg_console;
-       fbcon_clear(conp, 0, 0, LOGO_H, p->var.xres-LOGO_W);
        fbcon_show_logo(); /* This is protected above by initmem_freed */
        update_region(fg_console,
                      conp->vc_origin + conp->vc_size_row * conp->vc_top,
@@ -1952,7 +1951,7 @@ static inline unsigned safe_shift(unsigned d,int n)
     return n<0 ? d>>-n : d<<n;
 }
 
-__initfunc(static int fbcon_show_logo( void ))
+static int __init fbcon_show_logo( void )
 {
     struct display *p = &fb_display[fg_console]; /* draw to vt in foreground */
     int depth = p->var.bits_per_pixel;
index 24e7ad742b10f255bef61c0389be126c7f24498e..4a64ad348e52fc9ca86236d169c6ac40aeeb1372 100644 (file)
@@ -619,8 +619,8 @@ unregister_framebuffer(const struct fb_info *fb_info)
 
 static struct proc_dir_entry *proc_fbmem;
 
-__initfunc(void
-fbmem_init(void))
+void __init 
+fbmem_init(void)
 {
        int i;
 
@@ -679,7 +679,7 @@ int fbmon_dpms(const struct fb_info *fb_info)
      *  Command line options
      */
 
-__initfunc(void video_setup(char *options, int *ints))
+void __init video_setup(char *options, int *ints)
 {
     int i, j;
 
index e5ab75e08e74eea961530543ef74c12f104b3826..a2f638ebe981336522f2c16e4b85f55c2405e8d9 100644 (file)
@@ -374,7 +374,7 @@ static int fm2fb_ioctl(struct inode *inode, struct file *file, u_int cmd,
      *  Initialisation
      */
 
-__initfunc(void fm2fb_init(void))
+void __init fm2fb_init(void)
 {
     int key, is_fm;
     const struct ConfigDev *cd  = NULL;
@@ -466,7 +466,7 @@ __initfunc(void fm2fb_init(void))
           fb_fix.id);
 }
 
-__initfunc(void fm2fb_setup(char *options, int *ints))
+void __init fm2fb_setup(char *options, int *ints)
 {
     char *this_opt;
 
index fe57a75581edcc7bbe77f981c9c347ba8ec6dfbc..02fdbefd372223cbdff849e54af12c10685b467d 100644 (file)
@@ -297,7 +297,7 @@ static int g364fb_ioctl(struct inode *inode, struct file *file, u_int cmd,
 /*
  *  Initialisation
  */
-__initfunc(void g364fb_init(void))
+void __init g364fb_init(void)
 {
     int i,j;
     volatile unsigned int *pal_ptr = (volatile unsigned int *) CLR_PAL_REG;
index 11689b1502319c8cdd40e461fd04d6879d8c610e..66593da9dff540c8195d8cc0c326e72859f88c60 100644 (file)
@@ -301,7 +301,7 @@ static struct fb_ops hpfb_ops = {
 #define TOPCAT_FBOMSB  0x5d
 #define TOPCAT_FBOLSB  0x5f
 
-__initfunc(int hpfb_init_one(unsigned long base))
+int __init hpfb_init_one(unsigned long base)
 {
        unsigned long fboff;
 
@@ -384,7 +384,7 @@ __initfunc(int hpfb_init_one(unsigned long base))
  * Initialise the framebuffer
  */
 
-__initfunc(unsigned long hpfb_init(unsigned long mem_start))
+unsigned long __init hpfb_init(unsigned long mem_start)
 {
        unsigned int sid;
 
@@ -424,6 +424,6 @@ __initfunc(unsigned long hpfb_init(unsigned long mem_start))
        return mem_start;
 }
 
-__initfunc(void hpfb_setup(char *options, int *ints))
+void __init hpfb_setup(char *options, int *ints)
 {
 }
index dbf56108cbcd5fbb7599e5cb08505ba0ff491c94..e011189963e97c2918ea57ffa91d6cae9236b4d9 100644 (file)
@@ -559,7 +559,7 @@ static void igafb_blank(int blank, struct fb_info *info)
 }
 
 
-__initfunc(static int iga_init(struct fb_info_iga *info))
+static int __init iga_init(struct fb_info_iga *info)
 {
         char vramsz = iga_inb(info, IGA_EXT_CNTRL, IGA_IDX_EXT_BUS_CNTL) 
                                                         & MEM_SIZE_ALIAS;
@@ -624,7 +624,7 @@ __initfunc(static int iga_init(struct fb_info_iga *info))
 }      
 
 
-__initfunc(void igafb_init(void))
+void __init igafb_init(void)
 {
         struct pci_dev *pdev;
         struct fb_info_iga *info;
@@ -777,7 +777,7 @@ __initfunc(void igafb_init(void))
 #endif /* __sparc__ */
 }
 
-__initfunc(void igafb_setup(char *options, int *ints))
+void __init igafb_setup(char *options, int *ints)
 {
     char *this_opt;
 
index 26ab31f48056dff40ab2b1b71c96aa4ab182c17d..c7ea11029e420a1fc95fc43a9ec12f1f796a47d2 100644 (file)
@@ -967,8 +967,8 @@ out:
        add_timer(&c->timer);
 }
 
-__initfunc(static void
-imstt_cursor_init (struct fb_info_imstt *p))
+static void __init 
+imstt_cursor_init (struct fb_info_imstt *p)
 {
        struct imstt_cursor *c = &p->cursor;
 
@@ -1728,8 +1728,8 @@ imsttfbcon_blank (int blank, struct fb_info *info)
        out_le32(&p->dc_regs[STGCTL], ctrl);
 }
 
-__initfunc(static void
-init_imstt(struct fb_info_imstt *p))
+static void __init 
+init_imstt(struct fb_info_imstt *p)
 {
        __u32 i, tmp;
        __u32 *ip, *end;
@@ -1868,8 +1868,8 @@ init_imstt(struct fb_info_imstt *p))
 }
 
 #if defined(CONFIG_FB_OF) && !defined(MODULE)
-__initfunc(void
-imsttfb_of_init(struct device_node *dp))
+void __init 
+imsttfb_of_init(struct device_node *dp)
 {
        struct fb_info_imstt *p;
        int i;
@@ -1912,8 +1912,8 @@ imsttfb_of_init(struct device_node *dp))
 }
 #endif
 
-__initfunc(void
-imsttfb_init(void))
+void __init 
+imsttfb_init(void)
 {
 #if defined(CONFIG_FB_OF) && !defined(MODULE)
        /* We don't want to be called like this. */
@@ -1969,8 +1969,8 @@ imsttfb_init(void))
 }
 
 #ifndef MODULE
-__initfunc(void
-imsttfb_setup(char *options, int *ints))
+void __init 
+imsttfb_setup(char *options, int *ints)
 {
        char *this_opt;
 
index 0f964f60a4d0943129a89d660e9c9af635ecae1c..0f1a54592719d07cb702fc4d65fc22d992f43d73 100644 (file)
@@ -512,7 +512,7 @@ static struct nubus_device_specifier nb_video={
        NULL
 };
 
-__initfunc(void macfb_init(void))
+void __init macfb_init(void)
 {
        /* nubus_remap the video .. */
 
index 755739c6231c40613de6c20ff710d71d106875a5..6706e429eea66483bf27900217c6031d3b619233 100644 (file)
@@ -1,10 +1,10 @@
 /*
  *
- * Hardware accelerated Matrox Millennium I, II, Mystique and G200
+ * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200 and G400
  *
  * (c) 1998,1999 Petr Vandrovec <vandrove@vc.cvut.cz>
  *
- * Version: 1.15 1999/04/19
+ * Version: 1.19 1999/08/05
  *
  * MTRR stuff: 1998 Tom Rini <tmrini@ntplx.net>
  *
@@ -14,8 +14,8 @@
  *               "Kurt Garloff" <garloff@kg1.ping.de>
  *                     Betatesting, fixes, ideas, videomodes, videomodes timmings
  *
- *               "Tom Rini" <tmrini@ntplx.net>
- *                     MTRR stuff, betatesting, fixes, ideas
+ *               "Tom Rini" <trini@disparity.net>
+ *                     MTRR stuff, PPC cleanups, betatesting, fixes, ideas
  *
  *               "Bibek Sahu" <scorpio@dodds.net>
  *                     Access device through readb|w|l and write b|w|l
@@ -60,6 +60,9 @@
  *               "Cort Dougan" <cort@cs.nmt.edu>
  *                     CHRP fixes and PReP cleanup
  *
+ *               "Mark Vojkovich" <mvojkovi@ucsd.edu>
+ *                     G400 support
+ *
  * (following author is not in any relation with this code, but his code
  *  is included in this driver)
  *
 /* Debug register calls, too? */
 #undef MATROXFB_DEBUG_REG
 
+/* Log reentrancy attempts - you must have printstate() patch applied */
+#undef MATROXFB_DEBUG_REENTER
+/* you must define DEBUG_REENTER to get debugged CONSOLEBH... */
+#undef MATROXFB_DEBUG_CONSOLEBH
+
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <video/macmodes.h>
 #endif
 
+/* always compile support for 32MB... It cost almost nothing */
+#define CONFIG_FB_MATROX_32MB
+
 #define FBCON_HAS_VGATEXT
 
 #ifdef MATROXFB_DEBUG
 
 #define DEBUG
-#define DBG(x)         printk("matroxfb: %s\n", (x));
+#define DBG(x)         printk(KERN_DEBUG "matroxfb: %s\n", (x));
 
 #ifdef MATROXFB_DEBUG_HEAVY
 #define DBG_HEAVY(x)   DBG(x)
 #ifndef PCI_DEVICE_ID_MATROX_G100_AGP
 #define PCI_DEVICE_ID_MATROX_G100_AGP  0x1001
 #endif
+#ifndef PCI_DEVICE_ID_MATROX_G400_AGP
+#define PCI_DEVICE_ID_MATROX_G400_AGP  0x0525
+#endif
 
 #ifndef PCI_SS_ID_MATROX_PRODUCTIVA_G100_AGP
 #define PCI_SS_ID_MATROX_GENERIC               0xFF00
@@ -422,7 +436,7 @@ struct matrox_hw_state {
        unsigned char   MiscOutReg;
        unsigned char   DACpal[768];
        unsigned char   CRTC[25];
-       unsigned char   CRTCEXT[6];
+       unsigned char   CRTCEXT[9];
        unsigned char   SEQ[5];
        /* unused for MGA mode, but who knows... */
        unsigned char   GCTL[9];
@@ -453,7 +467,8 @@ static inline struct matrox_fb_info* mxinfo(const struct display* p) {
 }
 
 #define PMXINFO(p) mxinfo(p),
-#define MINFO_FROM_DISP(x) struct matrox_fb_info* minfo = mxinfo(x)
+#define MINFO_FROM(x)     struct matrox_fb_info* minfo = x
+#define MINFO_FROM_DISP(x) MINFO_FROM(mxinfo(x))
 
 #else
 
@@ -476,6 +491,7 @@ static inline struct matrox_fb_info* mxinfo(const struct display* p) {
 #endif
 
 #define PMXINFO(p)
+#define MINFO_FROM(x)
 #define MINFO_FROM_DISP(x)
 
 #endif
@@ -563,6 +579,9 @@ struct matrox_fb_info {
                int             hwcursor;
                int             blink;
                int             sgram;
+#ifdef CONFIG_FB_MATROX_32MB
+               int             support32MB;
+#endif
 
                int             accelerator;
                int             text_type_aux;
@@ -609,6 +628,8 @@ struct matrox_fb_info {
 #if defined(CONFIG_FB_OF)
 unsigned char nvram_read_byte(int);
 int matrox_of_init(struct device_node *dp);
+static int default_vmode = VMODE_NVRAM;
+static int default_cmode = CMODE_NVRAM;
 #endif
 
 #define curr_ydstorg(x)        ACCESS_FBINFO2(x, curr.ydstorg.pixels)
@@ -678,6 +699,8 @@ int matrox_of_init(struct device_node *dp);
 
 #define M_RESET                0x1E40
 
+#define M_AGP2PLL      0x1E4C
+
 #define M_OPMODE       0x1E54
 #define     M_OPMODE_DMA_GEN_WRITE     0x00
 #define     M_OPMODE_DMA_BLIT          0x04
@@ -713,6 +736,9 @@ int matrox_of_init(struct device_node *dp);
 #define M_EXTVGA_INDEX 0x1FDE
 #define M_EXTVGA_DATA  0x1FDF
 
+/* G200 only */
+#define M_SRCORG       0x2CB4
+
 #define M_RAMDAC_BASE  0x3C00
 
 /* fortunately, same on TVP3026 and MGA1064 */
@@ -723,6 +749,9 @@ int matrox_of_init(struct device_node *dp);
 #define M_X_INDEX      0x00
 #define M_X_DATAREG    0x0A
 
+#define DAC_XGENIOCTRL         0x2A
+#define DAC_XGENIODATA         0x2B
+
 #ifdef CONFIG_FB_MATROX_MILLENIUM
 #define TVP3026_INDEX          0x00
 #define TVP3026_PALWRADD       0x00
@@ -1054,6 +1083,48 @@ int matrox_of_init(struct device_node *dp);
 #define isMilleniumII(x) (0)
 #endif
 
+#ifdef MATROXFB_DEBUG_REENTER
+static atomic_t guard_counter = ATOMIC_INIT(1);
+static atomic_t guard_printing = ATOMIC_INIT(1);
+static void guard_start(void) {
+       if (atomic_dec_and_test(&guard_counter)) {      /* first level */
+               if (!(bh_mask & (1 << CONSOLE_BH)))     /* and CONSOLE_BH disabled */
+                       return;                         /* is OK */
+               /* otherwise it is first level with CONSOLE_BH enabled -
+                  - if we are __sti or SMP, reentering from console_bh possible */
+               atomic_dec(&guard_printing);    /* disable reentrancy warning */
+               printk(KERN_DEBUG "matroxfb entered without CONSOLE_BH disabled\n");
+#ifdef printstate
+               printstate();
+#endif
+               atomic_inc(&guard_printing);
+               return;
+       }
+       /* real reentering... You should be already warned by code above */
+       if (atomic_dec_and_test(&guard_printing)) {
+#ifdef printstate
+               printstate();
+#endif
+       }
+       atomic_inc(&guard_printing);
+}
+
+static inline void guard_end(void) {
+       atomic_inc(&guard_counter);
+}
+
+#define CRITBEGIN guard_start();
+#define CRITEND   guard_end();
+
+#else
+
+#define CRITBEGIN
+#define CRITEND
+
+#endif
+
+#define mga_ydstlen(y,l) mga_outl(M_YDSTLEN | M_EXEC, ((y) << 16) | (l))
+
 static void matrox_cfbX_init(WPMINFO struct display* p) {
        u_int32_t maccess;
        u_int32_t mpitch;
@@ -1101,7 +1172,7 @@ static void matrox_cfbX_init(WPMINFO struct display* p) {
        mga_outl(M_OPMODE, mopmode);
        mga_outl(M_CXBNDRY, 0xFFFF0000);
        mga_outl(M_YTOP, 0);
-       mga_outl(M_YBOT, 0x007FFFFF);
+       mga_outl(M_YBOT, 0x01FFFFFF);
        mga_outl(M_MACCESS, maccess);
        ACCESS_FBINFO(accel.m_dwg_rect) = M_DWG_TRAP | M_DWG_SOLID | M_DWG_ARZERO | M_DWG_SGNZERO | M_DWG_SHIFTZERO;
        if (isMilleniumII(MINFO)) ACCESS_FBINFO(accel.m_dwg_rect) |= M_DWG_TRANSC;
@@ -1113,7 +1184,9 @@ static void matrox_cfbX_bmove(struct display* p, int sy, int sx, int dy, int dx,
        MINFO_FROM_DISP(p);
 
        DBG("matrox_cfbX_bmove")
-       
+
+       CRITBEGIN
+
        sx *= fontwidth(p);
        dx *= fontwidth(p);
        width *= fontwidth(p);
@@ -1142,8 +1215,10 @@ static void matrox_cfbX_bmove(struct display* p, int sy, int sx, int dy, int dx,
        mga_outl(M_AR0, end);
        mga_outl(M_AR3, start);
        mga_outl(M_FXBNDRY, ((dx+width)<<16) | dx);
-       mga_outl(M_YDSTLEN | M_EXEC, ((dy)<<16) | height);
+       mga_ydstlen(dy, height);
        WaitTillIdle();
+
+       CRITEND
 }
 
 #ifdef FBCON_HAS_CFB4
@@ -1154,7 +1229,9 @@ static void matrox_cfb4_bmove(struct display* p, int sy, int sx, int dy, int dx,
           also odd, that means that we cannot use acceleration */
        
        DBG("matrox_cfb4_bmove")
-       
+
+       CRITBEGIN
+
        if ((sx | dx | width) & fontwidth(p) & 1) {
                fbcon_cfb4_bmove(p, sy, sx, dy, dx, height, width);
                return;
@@ -1194,6 +1271,8 @@ static void matrox_cfb4_bmove(struct display* p, int sy, int sx, int dy, int dx,
        mga_outl(M_YDST, dy*pixx >> 5);
        mga_outl(M_LEN | M_EXEC, height);
        WaitTillIdle();
+
+       CRITEND
 }
 #endif
 
@@ -1201,13 +1280,17 @@ static void matroxfb_accel_clear(CPMINFO u_int32_t color, int sy, int sx, int he
                int width) {
        
        DBG("matroxfb_accel_clear")
-       
-       mga_fifo(4);
+
+       CRITBEGIN
+
+       mga_fifo(5);
        mga_outl(M_DWGCTL, ACCESS_FBINFO(accel.m_dwg_rect) | M_DWG_REPLACE);
        mga_outl(M_FCOL, color);
        mga_outl(M_FXBNDRY, ((sx + width) << 16) | sx);
-       mga_outl(M_YDSTLEN | M_EXEC, (sy << 16) | height);
+       mga_ydstlen(sy, height);
        WaitTillIdle();
+
+       CRITEND
 }
 
 static void matrox_cfbX_clear(u_int32_t color, struct display* p, int sy, int sx, int height, int width) {
@@ -1225,7 +1308,9 @@ static void matrox_cfb4_clear(struct vc_data* conp, struct display* p, int sy, i
        MINFO_FROM_DISP(p);
 
        DBG("matrox_cfb4_clear")
-       
+
+       CRITBEGIN
+
        whattodo = 0; 
        bgx = attr_bgcol_ec(p, conp);
        bgx |= bgx << 4;
@@ -1277,6 +1362,8 @@ static void matrox_cfb4_clear(struct vc_data* conp, struct display* p, int sy, i
                        }
                }
        }
+
+       CRITEND
 }
 #endif
 
@@ -1323,7 +1410,10 @@ static void matrox_cfbX_fastputc(u_int32_t fgx, u_int32_t bgx, struct display* p
        charcell = fontwidth(p) * fontheight(p);
        yy *= fontheight(p);
        xx *= fontwidth(p);
-       mga_fifo(7);
+
+       CRITBEGIN
+
+       mga_fifo(8);
        mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SGNZERO | M_DWG_SHIFTZERO | M_DWG_BMONOWF | M_DWG_LINEAR | M_DWG_REPLACE);
        
        mga_outl(M_FCOL, fgx);
@@ -1332,8 +1422,10 @@ static void matrox_cfbX_fastputc(u_int32_t fgx, u_int32_t bgx, struct display* p
        ar3 = ACCESS_FBINFO(fastfont.mgabase) + (c & p->charmask) * charcell;
        mga_outl(M_AR3, ar3);
        mga_outl(M_AR0, (ar3 + charcell - 1) & 0x0003FFFF);
-       mga_outl(M_YDSTLEN | M_EXEC, (yy << 16) | fontheight(p));
+       mga_ydstlen(yy, fontheight(p));
        WaitTillIdle();
+
+       CRITEND
 }
        
 static void matrox_cfbX_putc(u_int32_t fgx, u_int32_t bgx, struct display* p, int c, int yy, int xx) {
@@ -1345,6 +1437,9 @@ static void matrox_cfbX_putc(u_int32_t fgx, u_int32_t bgx, struct display* p, in
        
        yy *= fontheight(p);
        xx *= fontwidth(p);
+
+       CRITBEGIN
+
 #ifdef __BIG_ENDIAN
        WaitTillIdle();
        mga_outl(M_OPMODE, M_OPMODE_8BPP);
@@ -1367,7 +1462,7 @@ static void matrox_cfbX_putc(u_int32_t fgx, u_int32_t bgx, struct display* p, in
                mga_outl(M_BCOL, bgx);
                mga_outl(M_AR3, 0);
                mga_outl(M_AR0, fontheight(p)*fontwidth(p)-1);
-               mga_outl(M_YDSTLEN | M_EXEC, (yy<<16) | fontheight(p));
+               mga_ydstlen(yy, fontheight(p));
                mga_memcpy_toio(ACCESS_FBINFO(mmio.vbase), 0, p->fontdata+(c&p->charmask)*charcell, charcell);
        } else {
                u8* chardata = p->fontdata+(c&p->charmask)*fontheight(p)*step;
@@ -1379,7 +1474,7 @@ static void matrox_cfbX_putc(u_int32_t fgx, u_int32_t bgx, struct display* p, in
                mga_outl(M_AR5, 0);
                mga_outl(M_AR3, 0);
                mga_outl(M_AR0, ar0);
-               mga_outl(M_YDSTLEN | M_EXEC, (yy << 16) | fontheight(p));
+               mga_ydstlen(yy, fontheight(p));
 
                switch (step) {
                case 1: 
@@ -1410,6 +1505,7 @@ static void matrox_cfbX_putc(u_int32_t fgx, u_int32_t bgx, struct display* p, in
 #ifdef __BIG_ENDIAN
        mga_outl(M_OPMODE, ACCESS_FBINFO(accel.m_opmode));
 #endif
+       CRITEND
 }
 
 #ifdef FBCON_HAS_CFB8
@@ -1464,6 +1560,9 @@ static void matrox_cfbX_fastputcs(u_int32_t fgx, u_int32_t bgx, struct display*
        yy *= fontheight(p);
        xx *= fontwidth(p);
        charcell = fontwidth(p) * fontheight(p);
+
+       CRITBEGIN
+
        mga_fifo(3);
        mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SGNZERO | M_DWG_SHIFTZERO | M_DWG_BMONOWF | M_DWG_LINEAR | M_DWG_REPLACE);
        mga_outl(M_FCOL, fgx);
@@ -1475,10 +1574,12 @@ static void matrox_cfbX_fastputcs(u_int32_t fgx, u_int32_t bgx, struct display*
                mga_outl(M_FXBNDRY, ((xx + fontwidth(p) - 1) << 16) | xx);
                mga_outl(M_AR3, ar3);
                mga_outl(M_AR0, (ar3 + charcell - 1) & 0x0003FFFF);
-               mga_outl(M_YDSTLEN | M_EXEC, (yy << 16) | fontheight(p));
+               mga_ydstlen(yy, fontheight(p));
                xx += fontwidth(p);
        }
        WaitTillIdle();
+
+       CRITEND
 }
 
 static void matrox_cfbX_putcs(u_int32_t fgx, u_int32_t bgx, struct display* p, const unsigned short* s, int count, int yy, int xx) {
@@ -1504,7 +1605,7 @@ static void matrox_cfbX_putcs(u_int32_t fgx, u_int32_t bgx, struct display* p, c
                step = 4;
        charcell = fontheight(p)*step;
        xlen = (charcell + 3) & ~3;
-       ydstlen = (yy<<16) | fontheight(p);
+       ydstlen = (yy << 16) | fontheight(p);
        if (fontwidth(p) == step << 3) {
                ar0 = fontheight(p)*fontwidth(p) - 1;
                easy = 1;
@@ -1512,6 +1613,9 @@ static void matrox_cfbX_putcs(u_int32_t fgx, u_int32_t bgx, struct display* p, c
                ar0 = fontwidth(p) - 1;
                easy = 0;
        }
+
+       CRITBEGIN
+
 #ifdef __BIG_ENDIAN
        WaitTillIdle();
        mga_outl(M_OPMODE, M_OPMODE_8BPP);
@@ -1529,7 +1633,7 @@ static void matrox_cfbX_putcs(u_int32_t fgx, u_int32_t bgx, struct display* p, c
        while (count--) {
                u_int8_t* chardata = p->fontdata + (scr_readw(s++) & p->charmask)*charcell;
 
-               mga_fifo(5);
+               mga_fifo(6);
                mga_writel(mmio, M_FXBNDRY, fxbndry);
                mga_writel(mmio, M_AR0, ar0);
                mga_writel(mmio, M_AR3, 0);
@@ -1573,6 +1677,7 @@ static void matrox_cfbX_putcs(u_int32_t fgx, u_int32_t bgx, struct display* p, c
 #ifdef __BIG_ENDIAN
        mga_outl(M_OPMODE, ACCESS_FBINFO(accel.m_opmode));
 #endif
+       CRITEND
 }
 
 #ifdef FBCON_HAS_CFB8
@@ -1635,6 +1740,8 @@ static void matrox_cfb4_revc(struct display* p, int xx, int yy) {
        xx |= (xx + fontwidth(p)) << 16;
        xx >>= 1;
 
+       CRITBEGIN
+       
        mga_fifo(5);
        mga_outl(M_DWGCTL, ACCESS_FBINFO(accel.m_dwg_rect) | M_DWG_XOR);
        mga_outl(M_FCOL, 0xFFFFFFFF);
@@ -1642,6 +1749,8 @@ static void matrox_cfb4_revc(struct display* p, int xx, int yy) {
        mga_outl(M_YDST, yy * p->var.xres_virtual >> 6);
        mga_outl(M_LEN | M_EXEC, fontheight(p));
        WaitTillIdle();
+
+       CRITEND
 } 
 #endif
 
@@ -1654,12 +1763,16 @@ static void matrox_cfb8_revc(struct display* p, int xx, int yy) {
        yy *= fontheight(p);
        xx *= fontwidth(p);
 
+       CRITBEGIN
+       
        mga_fifo(4);
        mga_outl(M_DWGCTL, ACCESS_FBINFO(accel.m_dwg_rect) | M_DWG_XOR);
        mga_outl(M_FCOL, 0x0F0F0F0F);
        mga_outl(M_FXBNDRY, ((xx + fontwidth(p)) << 16) | xx);
-       mga_outl(M_YDSTLEN | M_EXEC, (yy << 16) | fontheight(p));
+       mga_ydstlen(yy, fontheight(p));
        WaitTillIdle();
+
+       CRITEND
 }
 #endif
 
@@ -1671,12 +1784,16 @@ static void matrox_cfbX_revc(struct display* p, int xx, int yy) {
        yy *= fontheight(p);
        xx *= fontwidth(p);
 
+       CRITBEGIN
+       
        mga_fifo(4);
        mga_outl(M_DWGCTL, ACCESS_FBINFO(accel.m_dwg_rect) | M_DWG_XOR);
        mga_outl(M_FCOL, 0xFFFFFFFF);
        mga_outl(M_FXBNDRY, ((xx + fontwidth(p)) << 16) | xx);
-       mga_outl(M_YDSTLEN | M_EXEC, (yy << 16) | fontheight(p));
+       mga_ydstlen(yy, fontheight(p));
        WaitTillIdle();
+
+       CRITEND
 }
 
 static void matrox_cfbX_clear_margins(struct vc_data* conp, struct display* p, int bottom_only) {
@@ -1840,6 +1957,9 @@ static void matroxfb_ti3026_cursor(struct display* p, int mode, int x, int y) {
 
        DBG("matroxfb_ti3026_cursor")
        
+       if (ACCESS_FBINFO(currcon_display) != p)
+               return;
+
        if (mode == CM_ERASE) {
                if (ACCESS_FBINFO(cursor.state) != CM_ERASE) {
                        spin_lock_irqsave(&ACCESS_FBINFO(lock.DAC), flags);
@@ -1914,6 +2034,9 @@ static void matroxfb_DAC1064_createcursor(WPMINFO struct display* p) {
        xline = (~0) << (32 - ACCESS_FBINFO(cursor.w));
        cursorbase = ACCESS_FBINFO(video.vbase);
        h = ACCESS_FBINFO(features.DAC1064.cursorimage);
+
+       CRITBEGIN
+
 #ifdef __BIG_ENDIAN
        WaitTillIdle();
        mga_outl(M_OPMODE, M_OPMODE_32BPP);
@@ -1944,12 +2067,17 @@ static void matroxfb_DAC1064_createcursor(WPMINFO struct display* p) {
 #ifdef __BIG_ENDIAN
        mga_outl(M_OPMODE, ACCESS_FBINFO(accel.m_opmode));
 #endif
+
+       CRITEND
 }
        
 static void matroxfb_DAC1064_cursor(struct display* p, int mode, int x, int y) {
        unsigned long flags;
        MINFO_FROM_DISP(p);
 
+       if (ACCESS_FBINFO(currcon_display) != p)
+               return;
+
        if (mode == CM_ERASE) {
                if (ACCESS_FBINFO(cursor.state) != CM_ERASE) {
                        spin_lock_irqsave(&ACCESS_FBINFO(lock.DAC), flags);
@@ -2010,6 +2138,9 @@ static int matroxfb_fastfont_tryset(WPMINFO struct display* p) {
        fsize = (p->userfont?FNTCHARCNT(p->fontdata):256) * fontheight(p);
        if (((fsize * width + 31) / 32) * 4 > ACCESS_FBINFO(fastfont.size))
                return 0;
+
+       CRITBEGIN
+
        mga_outl(M_OPMODE, M_OPMODE_8BPP);
        if (width <= 8) {
                if (width == 8)
@@ -2100,6 +2231,9 @@ static int matroxfb_fastfont_tryset(WPMINFO struct display* p) {
                }
        }
        mga_outl(M_OPMODE, ACCESS_FBINFO(accel.m_opmode));
+
+       CRITEND
+
        return 1;
 }
 
@@ -2117,6 +2251,8 @@ static void matrox_text_bmove(struct display* p, int sy, int sx, int dy, int dx,
        unsigned int step;
        MINFO_FROM_DISP(p);
 
+       CRITBEGIN
+
        step = ACCESS_FBINFO(devflags.textstep);
        srcoff = (sy * p->next_line) + (sx * step);
        dstoff = (dy * p->next_line) + (dx * step);
@@ -2144,6 +2280,7 @@ static void matrox_text_bmove(struct display* p, int sy, int sx, int dy, int dx,
                        height--;
                }
        }
+       CRITEND
 }
 
 static void matrox_text_clear(struct vc_data* conp, struct display* p, int sy, int sx,
@@ -2156,6 +2293,9 @@ static void matrox_text_clear(struct vc_data* conp, struct display* p, int sy, i
        step = ACCESS_FBINFO(devflags.textstep);
        offs = sy * p->next_line + sx * step;
        val = ntohs((attr_bgcol(p, conp->vc_video_erase_char) << 4) | attr_fgcol(p, conp->vc_video_erase_char) | (' ' << 8));
+
+       CRITBEGIN
+       
        while (height > 0) {
                int i;
                for (i = width; i > 0; offs += step, i--)
@@ -2163,6 +2303,7 @@ static void matrox_text_clear(struct vc_data* conp, struct display* p, int sy, i
                offs += p->next_line - width * step;
                height--;
        }
+       CRITEND
 }
 
 static void matrox_text_putc(struct vc_data* conp, struct display* p, int c, int yy, int xx) {
@@ -2175,7 +2316,12 @@ static void matrox_text_putc(struct vc_data* conp, struct display* p, int c, int
        offs = yy * p->next_line + xx * step;
        chr = attr_fgcol(p,c) | (attr_bgcol(p,c) << 4) | ((c & p->charmask) << 8);
        if (chr & 0x10000) chr |= 0x08;
+
+       CRITBEGIN
+       
        mga_writew(ACCESS_FBINFO(video.vbase), offs, ntohs(chr));
+
+       CRITEND
 }
 
 static void matrox_text_putcs(struct vc_data* conp, struct display* p, const unsigned short* s,
@@ -2188,12 +2334,17 @@ static void matrox_text_putcs(struct vc_data* conp, struct display* p, const uns
        step = ACCESS_FBINFO(devflags.textstep);
        offs = yy * p->next_line + xx * step;
        attr = attr_fgcol(p, scr_readw(s)) | (attr_bgcol(p, scr_readw(s)) << 4);
+
+       CRITBEGIN
+       
        while (count-- > 0) {
                unsigned int chr = ((scr_readw(s++)) & p->charmask) << 8;
                if (chr & 0x10000) chr ^= 0x10008;
                mga_writew(ACCESS_FBINFO(video.vbase), offs, ntohs(attr|chr));
                offs += step;
        }
+
+       CRITEND
 }
 
 static void matrox_text_revc(struct display* p, int xx, int yy) {
@@ -2203,7 +2354,12 @@ static void matrox_text_revc(struct display* p, int xx, int yy) {
 
        step = ACCESS_FBINFO(devflags.textstep);
        offs = yy * p->next_line + xx * step + 1;
+       
+       CRITBEGIN
+       
        mga_writeb(ACCESS_FBINFO(video.vbase), offs, mga_readb(ACCESS_FBINFO(video.vbase), offs) ^ 0x77);
+
+       CRITEND
 }
 
 static int matrox_text_loadfont(WPMINFO struct display* p) {
@@ -2221,6 +2377,9 @@ static int matrox_text_loadfont(WPMINFO struct display* p) {
        dst = ACCESS_FBINFO(video.vbase);
        i = 2;
        font = (u_int8_t*)p->fontdata;
+
+       CRITBEGIN
+
        mga_setr(M_SEQ_INDEX, 0x02, 0x04);
        while (fsize--) {
                int l;
@@ -2233,6 +2392,9 @@ static int matrox_text_loadfont(WPMINFO struct display* p) {
                i += (32 - fontheight(p)) * ACCESS_FBINFO(devflags.vgastep);
        }
        mga_setr(M_SEQ_INDEX, 0x02, 0x03);
+
+       CRITEND
+
        return 1;
 }
 
@@ -2242,17 +2404,31 @@ static void matrox_text_createcursor(WPMINFO struct display* p) {
                return;
 
        matroxfb_createcursorshape(PMINFO p, 0);
+
+       CRITBEGIN
+       
        mga_setr(M_CRTC_INDEX, 0x0A, ACCESS_FBINFO(cursor.u));
        mga_setr(M_CRTC_INDEX, 0x0B, ACCESS_FBINFO(cursor.d) - 1);
+
+       CRITEND
 }
 
 static void matrox_text_cursor(struct display* p, int mode, int x, int y) {
        unsigned int pos;
        MINFO_FROM_DISP(p);
 
+       if (ACCESS_FBINFO(currcon_display) != p)
+               return;
+
        if (mode == CM_ERASE) {
                if (ACCESS_FBINFO(cursor.state) != CM_ERASE) {
+
+                       CRITBEGIN
+                       
                        mga_setr(M_CRTC_INDEX, 0x0A, 0x20);
+
+                       CRITEND
+
                        ACCESS_FBINFO(cursor.state) = CM_ERASE;
                }
                return;
@@ -2264,10 +2440,16 @@ static void matrox_text_cursor(struct display* p, int mode, int x, int y) {
        ACCESS_FBINFO(cursor.x) = x;
        ACCESS_FBINFO(cursor.y) = y;
        pos = p->next_line / ACCESS_FBINFO(devflags.textstep) * y + x;
+
+       CRITBEGIN
+       
        mga_setr(M_CRTC_INDEX, 0x0F, pos);
        mga_setr(M_CRTC_INDEX, 0x0E, pos >> 8);
 
        mga_setr(M_CRTC_INDEX, 0x0A, ACCESS_FBINFO(cursor.u));
+
+       CRITEND
+
        ACCESS_FBINFO(cursor.state) = CM_DRAW;
 }
 
@@ -2523,6 +2705,9 @@ static struct fb_var_screeninfo vesafb_defined __initdata = {
 static void matrox_pan_var(WPMINFO struct fb_var_screeninfo *var) {
        unsigned int pos;
        unsigned short p0, p1, p2;
+#ifdef CONFIG_FB_MATROX_32MB
+       unsigned int p3;
+#endif
        struct display *disp;
 
        DBG("matrox_pan_var")
@@ -2536,10 +2721,22 @@ static void matrox_pan_var(WPMINFO struct fb_var_screeninfo *var) {
        }
        p0 = ACCESS_FBINFO(currenthw)->CRTC[0x0D] = pos & 0xFF;
        p1 = ACCESS_FBINFO(currenthw)->CRTC[0x0C] = (pos & 0xFF00) >> 8;
-       p2 = ACCESS_FBINFO(currenthw)->CRTCEXT[0] = (ACCESS_FBINFO(currenthw)->CRTCEXT[0] & 0xF0) | ((pos >> 16) & 0x0F);
+       p2 = ACCESS_FBINFO(currenthw)->CRTCEXT[0] = (ACCESS_FBINFO(currenthw)->CRTCEXT[0] & 0xB0) | ((pos >> 16) & 0x0F) | ((pos >> 14) & 0x40);
+#ifdef CONFIG_FB_MATROX_32MB
+       p3 = ACCESS_FBINFO(currenthw)->CRTCEXT[8] = pos >> 21;
+#endif 
+
+       CRITBEGIN
+
        mga_setr(M_CRTC_INDEX, 0x0D, p0);
        mga_setr(M_CRTC_INDEX, 0x0C, p1);
+#ifdef CONFIG_FB_MATROX_32MB
+       if (ACCESS_FBINFO(devflags.support32MB))
+               mga_setr(M_EXTVGA_INDEX, 0x08, p3);
+#endif
        mga_setr(M_EXTVGA_INDEX, 0x00, p2);
+
+       CRITEND
 }
 
        /*
@@ -2627,13 +2824,16 @@ static int matroxfb_test_and_set_rounding(CPMINFO int xres, int bpp) {
                case 0:         return xres;
                case 4:         rounding = 128;
                                break;
-               case 8:         rounding = 64;
+               case 8:         rounding = 64;  /* doc says 64; 32 is OK for G400 */
                                break;
                case 16:        rounding = 32;
                                break;
-               case 24:        rounding = 64;
+               case 24:        rounding = 64;  /* doc says 64; 32 is OK for G400 */
                                break;
                default:        rounding = 16;
+                               /* on G400, 16 really does not work */
+                               if (ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG400)
+                                       rounding = 32;
                                break;
        }
        if (isInterleave(MINFO)) {
@@ -3140,7 +3340,7 @@ static void DAC1064_setpclk(CPMINFO struct matrox_hw_state* hw, unsigned long fo
        hw->DACclk[2] = p;
 }
 
-__initfunc(static void DAC1064_setmclk(CPMINFO struct matrox_hw_state* hw, int oscinfo, unsigned long fmem)) {
+static void __init DAC1064_setmclk(CPMINFO struct matrox_hw_state* hw, int oscinfo, unsigned long fmem){
        u_int32_t mx;
 
        DBG("DAC1064_setmclk")
@@ -3288,6 +3488,8 @@ static int DAC1064_init_2(CPMINFO struct matrox_hw_state* hw, struct my_timming*
 static void DAC1064_restore_1(CPMINFO const struct matrox_hw_state* hw, const struct matrox_hw_state* oldhw) {
        
        DBG("DAC1064_restore_1")
+
+       CRITBEGIN
        
        outDAC1064(PMINFO DAC1064_XSYSPLLM, hw->DACclk[3]);
        outDAC1064(PMINFO DAC1064_XSYSPLLN, hw->DACclk[4]);
@@ -3298,6 +3500,8 @@ static void DAC1064_restore_1(CPMINFO const struct matrox_hw_state* hw, const st
                for (i = 0; i < sizeof(MGA1064_DAC_regs); i++)
                        outDAC1064(PMINFO MGA1064_DAC_regs[i], hw->DACreg[i]);
        }
+
+       CRITEND
 }
 
 static void DAC1064_restore_2(WPMINFO const struct matrox_hw_state* hw, const struct matrox_hw_state* oldhw, struct display* p) {
@@ -3305,6 +3509,8 @@ static void DAC1064_restore_2(WPMINFO const struct matrox_hw_state* hw, const st
        unsigned int tmout;
        
        DBG("DAC1064_restore_2")
+
+       CRITBEGIN
        
        for (i = 0; i < 3; i++)
                outDAC1064(PMINFO M1064_XPIXPLLCM + i, hw->DACclk[i]);
@@ -3313,6 +3519,9 @@ static void DAC1064_restore_2(WPMINFO const struct matrox_hw_state* hw, const st
                        break;
                udelay(10);
        };
+
+       CRITEND
+
        if (!tmout)
                printk(KERN_ERR "matroxfb: Pixel PLL not locked after 5 secs\n");
 
@@ -3585,7 +3794,9 @@ static int matroxfb_decode_var(CPMINFO struct display* p, struct fb_var_screenin
                        var->pixclock = 15000;  /* limit for "normal" gclk & mclk */
 #endif
        }
-
+       /* YDSTLEN contains only signed 16bit value */
+       if (var->yres_virtual > 32767)
+               var->yres_virtual = 32767;
        if (var->yres_virtual < var->yres)
                var->yres = var->yres_virtual;
        if (var->xres_virtual < var->xres)
@@ -3684,7 +3895,7 @@ static int matroxfb_decode_var(CPMINFO struct display* p, struct fb_var_screenin
 }
 
 #ifdef CONFIG_FB_MATROX_MILLENIUM
-__initfunc(static void ti3026_setMCLK(CPMINFO struct matrox_hw_state* hw, int fout)) {
+static void __init ti3026_setMCLK(CPMINFO struct matrox_hw_state* hw, int fout){
        unsigned int f_pll;
        unsigned int pclk_m, pclk_n, pclk_p;
        unsigned int mclk_m, mclk_n, mclk_p;
@@ -3783,7 +3994,7 @@ __initfunc(static void ti3026_setMCLK(CPMINFO struct matrox_hw_state* hw, int fo
                printk(KERN_ERR "matroxfb: Pixel PLL not locked after 5 secs\n");
 }
 
-__initfunc(static void ti3026_ramdac_init(WPMINFO struct matrox_hw_state* hw)) {
+static void __init ti3026_ramdac_init(WPMINFO struct matrox_hw_state* hw){
 
        DBG("ti3026_ramdac_init")
 
@@ -3800,7 +4011,7 @@ __initfunc(static void ti3026_ramdac_init(WPMINFO struct matrox_hw_state* hw)) {
 }
 #endif
 
-__initfunc(static void matroxfb_fastfont_init(struct matrox_fb_info* minfo)) {
+static void matroxfb_fastfont_init(struct matrox_fb_info* minfo){
        unsigned int size;
 
        size = ACCESS_FBINFO(fastfont.size);
@@ -3824,7 +4035,7 @@ __initfunc(static void matroxfb_fastfont_init(struct matrox_fb_info* minfo)) {
 }
 
 #ifdef CONFIG_FB_MATROX_MYSTIQUE
-__initfunc(static void MGA1064_ramdac_init(WPMINFO struct matrox_hw_state* hw)) {
+static void __init MGA1064_ramdac_init(WPMINFO struct matrox_hw_state* hw){
 
        DBG("MGA1064_ramdac_init");
 
@@ -3841,7 +4052,7 @@ __initfunc(static void MGA1064_ramdac_init(WPMINFO struct matrox_hw_state* hw))
        DAC1064_setmclk(PMINFO hw, DAC1064_OPT_MDIV2 | DAC1064_OPT_GDIV3 | DAC1064_OPT_SCLK_PLL, 133333);
 }
 
-__initfunc(static int MGA1064_preinit(WPMINFO struct matrox_hw_state* hw)) {
+static int __init MGA1064_preinit(WPMINFO struct matrox_hw_state* hw){
        static const int vxres_mystique[] = { 512,        640, 768,  800,  832,  960, 
                                             1024, 1152, 1280,      1600, 1664, 1920, 
                                             2048,    0};
@@ -3873,7 +4084,7 @@ __initfunc(static int MGA1064_preinit(WPMINFO struct matrox_hw_state* hw)) {
        return 0;
 }
 
-__initfunc(static void MGA1064_reset(WPMINFO struct matrox_hw_state* hw)) {
+static void __init MGA1064_reset(WPMINFO struct matrox_hw_state* hw){
 
        DBG("MGA1064_reset");
 
@@ -3893,7 +4104,7 @@ static int x7AF4 = 0x10;    /* flags, maybe 0x10 = SDRAM, 0x00 = SGRAM??? */
 static int def50 = 0;  /* reg50, & 0x0F, & 0x3000 (only 0x0000, 0x1000, 0x2000 (0x3000 disallowed and treated as 0) */
 #endif
 
-__initfunc(static void MGAG100_progPixClock(CPMINFO int flags, int m, int n, int p)) {
+static void __init MGAG100_progPixClock(CPMINFO int flags, int m, int n, int p){
        int reg;
        int selClk;
        int clk;
@@ -3937,7 +4148,7 @@ __initfunc(static void MGAG100_progPixClock(CPMINFO int flags, int m, int n, int
        outDAC1064(PMINFO M1064_XPIXCLKCTRL, inDAC1064(PMINFO M1064_XPIXCLKCTRL) & ~M1064_XPIXCLKCTRL_DIS);
 }
 
-__initfunc(static void MGAG100_setPixClock(CPMINFO int flags, int freq)) {
+static void __init MGAG100_setPixClock(CPMINFO int flags, int freq){
        unsigned int m, n, p;
 
        DBG("MGAG100_setPixClock")
@@ -3946,7 +4157,7 @@ __initfunc(static void MGAG100_setPixClock(CPMINFO int flags, int freq)) {
        MGAG100_progPixClock(PMINFO flags, m, n, p);
 }
 
-__initfunc(static int MGAG100_preinit(WPMINFO struct matrox_hw_state* hw)) {
+static int __init MGAG100_preinit(WPMINFO struct matrox_hw_state* hw){
        static const int vxres_g100[] = {  512,        640, 768,  800,  832,  960, 
                                           1024, 1152, 1280,      1600, 1664, 1920, 
                                           2048, 0};
@@ -4036,7 +4247,7 @@ __initfunc(static int MGAG100_preinit(WPMINFO struct matrox_hw_state* hw)) {
        return 0;
 }
        
-__initfunc(static void MGAG100_reset(WPMINFO struct matrox_hw_state* hw)) {
+static void __init MGAG100_reset(WPMINFO struct matrox_hw_state* hw){
        u_int8_t b;
 
        DBG("MGAG100_reset")
@@ -4104,6 +4315,8 @@ static void vgaHWrestore(CPMINFO struct matrox_hw_state* hw, struct matrox_hw_st
                dprintk("%02X:", hw->ATTR[i]);
        dprintk("\n");
 
+       CRITBEGIN
+
        mga_inb(M_ATTR_RESET);
        mga_outb(M_ATTR_INDEX, 0);
        mga_outb(M_MISC_REG, hw->MiscOutReg);
@@ -4125,6 +4338,8 @@ static void vgaHWrestore(CPMINFO struct matrox_hw_state* hw, struct matrox_hw_st
                mga_outb(M_DAC_VAL, hw->DACpal[i]);
        mga_inb(M_ATTR_RESET);
        mga_outb(M_ATTR_INDEX, 0x20);
+
+       CRITEND
 }
 
 static int matrox_setcolreg(unsigned regno, unsigned red, unsigned green,
@@ -4227,10 +4442,15 @@ static void MGA1064_restore(WPMINFO struct matrox_hw_state* hw, struct matrox_hw
        int i;
 
        DBG("MGA1064_restore")
+
+       CRITBEGIN
        
        pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg);
        mga_outb(M_IEN, 0x00);
        mga_outb(M_CACHEFLUSH, 0x00);
+
+       CRITEND
+
        DAC1064_restore_1(PMINFO hw, oldhw);
        vgaHWrestore(PMINFO hw, oldhw);
        for (i = 0; i < 6; i++)
@@ -4244,10 +4464,18 @@ static void MGAG100_restore(WPMINFO struct matrox_hw_state* hw, struct matrox_hw
        int i;
 
        DBG("MGAG100_restore")
-       
+
+       CRITBEGIN
+
        pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg);
+       CRITEND
+
        DAC1064_restore_1(PMINFO hw, oldhw);
        vgaHWrestore(PMINFO hw, oldhw);
+#ifdef CONFIG_FB_MATROX_32MB
+       if (ACCESS_FBINFO(devflags.support32MB))
+               mga_setr(M_EXTVGA_INDEX, 8, hw->CRTCEXT[8]);
+#endif
        for (i = 0; i < 6; i++)
                mga_setr(M_EXTVGA_INDEX, i, hw->CRTCEXT[i]);
        DAC1064_restore_2(PMINFO hw, oldhw, p);
@@ -4265,9 +4493,16 @@ static void Ti3026_restore(WPMINFO struct matrox_hw_state* hw, struct matrox_hw_
                dprintk("%02X:", hw->CRTCEXT[i]);
        dprintk("\n");
 
+       CRITBEGIN
+
        pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg);
 
+       CRITEND
+
        vgaHWrestore(PMINFO hw, oldhw);
+
+       CRITBEGIN
+
        for (i = 0; i < 6; i++)
                mga_setr(M_EXTVGA_INDEX, i, hw->CRTCEXT[i]);
 
@@ -4285,11 +4520,13 @@ static void Ti3026_restore(WPMINFO struct matrox_hw_state* hw, struct matrox_hw_
                oldhw->DACclk[2] = inTi3026(PMINFO TVP3026_XPIXPLLDATA);
                oldhw->DACclk[5] = inTi3026(PMINFO TVP3026_XLOOPPLLDATA);
        }
+       CRITEND
        if (!oldhw || memcmp(hw->DACclk, oldhw->DACclk, 6)) {
                /* agrhh... setting up PLL is very slow on Millenium... */
                /* Mystique PLL is locked in few ms, but Millenium PLL lock takes about 0.15 s... */
                /* Maybe even we should call schedule() ? */
 
+               CRITBEGIN
                outTi3026(PMINFO TVP3026_XCLKCTRL, hw->DACreg[POS3026_XCLKCTRL]);
                outTi3026(PMINFO TVP3026_XPLLADDR, 0x2A);
                outTi3026(PMINFO TVP3026_XLOOPPLLDATA, 0);
@@ -4307,24 +4544,31 @@ static void Ti3026_restore(WPMINFO struct matrox_hw_state* hw, struct matrox_hw_
                                        break;
                                udelay(10);
                        }
+
+                       CRITEND
+
                        if (!tmout)
                                printk(KERN_ERR "matroxfb: Pixel PLL not locked after 5 secs\n");
                        else
                                dprintk(KERN_INFO "PixelPLL: %d\n", 500000-tmout);
+                       CRITBEGIN
                }
                outTi3026(PMINFO TVP3026_XMEMPLLCTRL, hw->DACreg[POS3026_XMEMPLLCTRL]);
                outTi3026(PMINFO TVP3026_XPLLADDR, 0x00);
                for (i = 3; i < 6; i++)
                        outTi3026(PMINFO TVP3026_XLOOPPLLDATA, hw->DACclk[i]);
+               CRITEND
                if ((hw->MiscOutReg & 0x08) && ((hw->DACclk[5] & 0x80) == 0x80)) {
                        int tmout;
 
+                       CRITBEGIN
                        outTi3026(PMINFO TVP3026_XPLLADDR, 0x3F);
                        for (tmout = 500000; tmout; --tmout) {
                                if (inTi3026(PMINFO TVP3026_XLOOPPLLDATA) & 0x40) 
                                        break;
                                udelay(10);
                        }
+                       CRITEND
                        if (!tmout)
                                printk(KERN_ERR "matroxfb: Loop PLL not locked after 5 secs\n");
                        else
@@ -4379,7 +4623,7 @@ static int matroxfb_get_fix(struct fb_fix_screeninfo *fix, int con,
        strcpy(fix->id,"MATROX");
 
        fix->smem_start = (void*)ACCESS_FBINFO(video.base) + ACCESS_FBINFO(curr.ydstorg.bytes);
-       fix->smem_len = ACCESS_FBINFO(video.len) - ACCESS_FBINFO(curr.ydstorg.bytes);
+       fix->smem_len = ACCESS_FBINFO(video.len_usable) - ACCESS_FBINFO(curr.ydstorg.bytes);
        fix->type = p->type;
        fix->type_aux = p->type_aux;
        fix->visual = p->visual;
@@ -4531,7 +4775,8 @@ static int matroxfb_set_var(struct fb_var_screeninfo *var, int con,
 
                        hw->CRTC[0x0D] = pos & 0xFF;
                        hw->CRTC[0x0C] = (pos & 0xFF00) >> 8;
-                       hw->CRTCEXT[0] = (hw->CRTCEXT[0] & 0xF0) | ((pos >> 16) & 0x0F);
+                       hw->CRTCEXT[0] = (hw->CRTCEXT[0] & 0xF0) | ((pos >> 16) & 0x0F) | ((pos >> 14) & 0x40);
+                       hw->CRTCEXT[8] = pos >> 21;
                        ACCESS_FBINFO(hw_switch->restore(PMINFO hw, ohw, display));
                        ACCESS_FBINFO(cursor.redraw) = 1;
                        ACCESS_FBINFO(currenthw) = hw;
@@ -4717,10 +4962,16 @@ static void matroxfb_blank(int blank, struct fb_info *info)
                case 4:  seq = 0x20; crtc = 0x30; break;
                default: seq = 0x00; crtc = 0x00; break;
        }
+
+       CRITBEGIN
+       
        mga_outb(M_SEQ_INDEX, 1);
        mga_outb(M_SEQ_DATA, (mga_inb(M_SEQ_DATA) & ~0x20) | seq);
        mga_outb(M_EXTVGA_INDEX, 1);
        mga_outb(M_EXTVGA_DATA, (mga_inb(M_EXTVGA_DATA) & ~0x30) | crtc);
+
+       CRITEND
+
 #undef minfo
 }
 
@@ -4739,7 +4990,8 @@ static void matroxfb_blank(int blank, struct fb_info *info)
 #define RS1056x344     12      /* 132 x 43 text */
 #define RS1056x400     13      /* 132 x 50 text */
 #define RS1056x480     14      /* 132 x 60 text */
-/* 0F-FF */
+#define RSNoxNo                15
+/* 10-FF */
 static struct { int xres, yres, left, right, upper, lower, hslen, vslen, vfreq; } timmings[] __initdata = {
        {  640,  400,  48, 16, 39,  8,  96, 2, 70 },
        {  640,  480,  48, 16, 33, 10,  96, 2, 60 },
@@ -4754,7 +5006,8 @@ static struct { int xres, yres, left, right, upper, lower, hslen, vslen, vfreq;
        {  640,  350,  48, 16, 39,  8,  96, 2, 70 },
        { 1056,  344,  96, 24, 59, 44, 160, 2, 70 },
        { 1056,  400,  96, 24, 39,  8, 160, 2, 70 },
-       { 1056,  480,  96, 24, 36, 12, 160, 3, 60 }
+       { 1056,  480,  96, 24, 36, 12, 160, 3, 60 },
+       {    0,    0,  ~0, ~0, ~0, ~0,   0, 0,  0 }
 };
 
 #define RSDepth(X)     (((X) >> 8) & 0x0F)
@@ -4775,13 +5028,14 @@ static struct { struct fb_bitfield red, green, blue, transp; int bits_per_pixel;
        { {  0, 8, 0}, { 0, 8, 0}, { 0, 8, 0}, {  0, 0, 0},  4 },
        { { 16, 8, 0}, { 8, 8, 0}, { 0, 8, 0}, {  0, 0, 0}, 24 },
        { {  0, 6, 0}, { 0, 6, 0}, { 0, 6, 0}, {  0, 0, 0},  0 },       /* textmode with (default) VGA8x16 */
-       { {  0, 6, 0}, { 0, 6, 0}, { 0, 6, 0}, {  0, 0, 0},  0 }        /* textmode hardwired to VGA8x8 */
+       { {  0, 6, 0}, { 0, 6, 0}, { 0, 6, 0}, {  0, 0, 0},  0 },       /* textmode hardwired to VGA8x8 */
 };
 
 #define RSCreate(X,Y)  ((X) | ((Y) << 8))
 static struct { unsigned int vesa; unsigned int info; } *RSptr, vesamap[] __initdata = {
 /* default must be first */
 #ifdef FBCON_HAS_CFB8
+       {    ~0, RSCreate(RSNoxNo,     RS8bpp ) },
        { 0x101, RSCreate(RS640x480,   RS8bpp ) },
        { 0x100, RSCreate(RS640x400,   RS8bpp ) },
        { 0x180, RSCreate(RS768x576,   RS8bpp ) },
@@ -4793,14 +5047,8 @@ static struct { unsigned int vesa; unsigned int info; } *RSptr, vesamap[] __init
        { 0x198, RSCreate(RS1408x1056, RS8bpp ) },
        { 0x11C, RSCreate(RS1600x1200, RS8bpp ) },
 #endif
-#ifdef FBCON_HAS_CFB4
-       { 0x010, RSCreate(RS640x350,   RS4bpp ) },
-       { 0x012, RSCreate(RS640x480,   RS4bpp ) },
-       { 0x102, RSCreate(RS800x600,   RS4bpp ) },
-       { 0x104, RSCreate(RS1024x768,  RS4bpp ) },
-       { 0x106, RSCreate(RS1280x1024, RS4bpp ) },
-#endif
 #ifdef FBCON_HAS_CFB16
+       {    ~0, RSCreate(RSNoxNo,     RS15bpp) },
        { 0x110, RSCreate(RS640x480,   RS15bpp) },
        { 0x181, RSCreate(RS768x576,   RS15bpp) },
        { 0x113, RSCreate(RS800x600,   RS15bpp) },
@@ -4821,6 +5069,7 @@ static struct { unsigned int vesa; unsigned int info; } *RSptr, vesamap[] __init
        { 0x11E, RSCreate(RS1600x1200, RS16bpp) },
 #endif
 #ifdef FBCON_HAS_CFB24
+       {    ~0, RSCreate(RSNoxNo,     RS24bpp) },
        { 0x1B2, RSCreate(RS640x480,   RS24bpp) },
        { 0x184, RSCreate(RS768x576,   RS24bpp) },
        { 0x1B5, RSCreate(RS800x600,   RS24bpp) },
@@ -4832,6 +5081,7 @@ static struct { unsigned int vesa; unsigned int info; } *RSptr, vesamap[] __init
        { 0x1BF, RSCreate(RS1600x1200, RS24bpp) },
 #endif
 #ifdef FBCON_HAS_CFB32
+       {    ~0, RSCreate(RSNoxNo,     RS32bpp) },
        { 0x112, RSCreate(RS640x480,   RS32bpp) },
        { 0x183, RSCreate(RS768x576,   RS32bpp) },
        { 0x115, RSCreate(RS800x600,   RS32bpp) },
@@ -4843,6 +5093,7 @@ static struct { unsigned int vesa; unsigned int info; } *RSptr, vesamap[] __init
        { 0x11F, RSCreate(RS1600x1200, RS32bpp) },
 #endif
 #ifdef FBCON_HAS_VGATEXT
+       {    ~0, RSCreate(RSNoxNo,     RSText)  },
        { 0x002, RSCreate(RS640x400,   RSText)  },      /* 80x25 */
        { 0x003, RSCreate(RS640x400,   RSText)  },      /* 80x25 */
        { 0x007, RSCreate(RS640x400,   RSText)  },      /* 80x25 */
@@ -4852,6 +5103,14 @@ static struct { unsigned int vesa; unsigned int info; } *RSptr, vesamap[] __init
        { 0x10A, RSCreate(RS1056x344,  RSText8) },      /* 132x43 */
        { 0x10B, RSCreate(RS1056x400,  RSText8) },      /* 132x50 */
        { 0x10C, RSCreate(RS1056x480,  RSText8) },      /* 132x60 */
+#endif
+#ifdef FBCON_HAS_CFB4
+       {    ~0, RSCreate(RSNoxNo,     RS4bpp ) },
+       { 0x010, RSCreate(RS640x350,   RS4bpp ) },
+       { 0x012, RSCreate(RS640x480,   RS4bpp ) },
+       { 0x102, RSCreate(RS800x600,   RS4bpp ) },
+       { 0x104, RSCreate(RS1024x768,  RS4bpp ) },
+       { 0x106, RSCreate(RS1280x1024, RS4bpp ) },
 #endif
        {     0, 0                                 }};
 
@@ -4871,19 +5130,21 @@ static int inverse = 0;                 /* "matrox:inverse" */
 static int hwcursor = 1;               /* "matrox:nohwcursor" */
 static int blink = 1;                  /* "matrox:noblink" */
 static int sgram = 0;                  /* "matrox:sgram" */
+#ifdef CONFIG_MTRR
 static int mtrr = 1;                   /* "matrox:nomtrr" */
+#endif
 static int grayscale = 0;              /* "matrox:grayscale" */
 static unsigned int fastfont = 0;      /* "matrox:fastfont:xxxxx" */
 static int dev = -1;                   /* "matrox:dev:xxxxx" */
-static unsigned int vesa = 0x101;      /* "matrox:vesa:xxxxx" */
+static unsigned int vesa = ~0;         /* "matrox:vesa:xxxxx" */
 static int depth = -1;                 /* "matrox:depth:xxxxx" */
 static unsigned int xres = 0;          /* "matrox:xres:xxxxx" */
 static unsigned int yres = 0;          /* "matrox:yres:xxxxx" */
-static unsigned int upper = 0;         /* "matrox:upper:xxxxx" */
-static unsigned int lower = 0;         /* "matrox:lower:xxxxx" */
+static unsigned int upper = ~0;                /* "matrox:upper:xxxxx" */
+static unsigned int lower = ~0;                /* "matrox:lower:xxxxx" */
 static unsigned int vslen = 0;         /* "matrox:vslen:xxxxx" */
-static unsigned int left = 0;          /* "matrox:left:xxxxx" */
-static unsigned int right = 0;         /* "matrox:right:xxxxx" */
+static unsigned int left = ~0;         /* "matrox:left:xxxxx" */
+static unsigned int right = ~0;                /* "matrox:right:xxxxx" */
 static unsigned int hslen = 0;         /* "matrox:hslen:xxxxx" */
 static unsigned int pixclock = 0;      /* "matrox:pixclock:xxxxx" */
 static int sync = -1;                  /* "matrox:sync:xxxxx" */
@@ -4893,7 +5154,7 @@ static unsigned int maxclk = 0;           /* "matrox:maxclk:xxxxM" */
 static char fontname[64];              /* "matrox:font:xxxxx" */
 
 #ifndef MODULE
-__initfunc(void matroxfb_setup(char *options, int *ints)) {
+void __init matroxfb_setup(char *options, int *ints){
        char *this_opt;
        
        DBG("matroxfb_setup")
@@ -4901,7 +5162,7 @@ __initfunc(void matroxfb_setup(char *options, int *ints)) {
        fontname[0] = '\0';
        
        if (!options || !*options)
-               return;
+               return 0;
        
        for(this_opt=strtok(options,","); this_opt; this_opt=strtok(NULL,",")) {
                if (!*this_opt) continue;
@@ -4954,6 +5215,31 @@ __initfunc(void matroxfb_setup(char *options, int *ints)) {
                        fv = simple_strtoul(this_opt+3, NULL, 0);
                else if (!strncmp(this_opt, "mem:", 4)) 
                        mem = simple_strtoul(this_opt+4, NULL, 0);
+               else if (!strncmp(this_opt, "mode:", 5))
+                       strcpy(videomode, this_opt+5);
+#ifdef CONFIG_FB_OF
+               else if (!strncmp(this_opt, "vmode:", 6)) {
+                       unsigned int vmode = simple_strtoul(this_opt+6, NULL, 0);
+                       if (vmode > 0 && vmode <= VMODE_MAX)
+                               default_vmode = vmode;
+               } else if (!strncmp(this_opt, "cmode:", 6)) {
+                       unsigned int cmode = simple_strtoul(this_opt+6, NULL, 0);
+                       switch (cmode) {
+                               case 0:
+                               case 8:
+                                       default_cmode = CMODE_8;
+                                       break;
+                               case 15:
+                               case 16:
+                                       default_cmode = CMODE_16;
+                                       break;
+                               case 24:
+                               case 32:
+                                       default_cmode = CMODE_32;
+                                       break;
+                       }
+               }
+#endif
                else if (!strncmp(this_opt, "fastfont:", 9))
                        fastfont = simple_strtoul(this_opt+9, NULL, 0);
                else if (!strcmp(this_opt, "nofastfont"))       /* fastfont:N and nofastfont (nofastfont = fastfont:0) */
@@ -4987,8 +5273,10 @@ __initfunc(void matroxfb_setup(char *options, int *ints)) {
                                nobios = !value;
                        else if (!strcmp(this_opt, "init"))
                                noinit = !value;
+#ifdef CONFIG_MTRR
                        else if (!strcmp(this_opt, "mtrr"))
                                mtrr = value;
+#endif
                        else if (!strcmp(this_opt, "inv24"))
                                inv24 = value;
                        else if (!strcmp(this_opt, "cross4MB"))
@@ -5004,15 +5292,16 @@ __initfunc(void matroxfb_setup(char *options, int *ints)) {
                        }
                }
        }
+       return 0;
 }
 #endif
 
-__initfunc(static int matroxfb_getmemory(WPMINFO unsigned int maxSize, unsigned int* realOffset, unsigned int *realSize)) {
+static int matroxfb_getmemory(WPMINFO unsigned int maxSize, unsigned int* realOffset, unsigned int *realSize){
        vaddr_t vm;
        unsigned int offs;
        unsigned int offs2;
        unsigned char store;
-       unsigned char bytes[16];
+       unsigned char bytes[32];
        unsigned char* tmp;
        unsigned long cbase;
        unsigned long mbase;
@@ -5025,7 +5314,7 @@ __initfunc(static int matroxfb_getmemory(WPMINFO unsigned int maxSize, unsigned
        maxSize &= ~0x1FFFFF;   /* must be X*2MB (really it must be 2 or X*4MB) */
        /* at least 2MB */
        if (maxSize < 0x0200000) return 0;
-       if (maxSize > 0x1000000) maxSize = 0x1000000;
+       if (maxSize > 0x2000000) maxSize = 0x2000000;
 
        mga_outb(M_EXTVGA_INDEX, 0x03);
        mga_outb(M_EXTVGA_DATA, mga_inb(M_EXTVGA_DATA) | 0x80);
@@ -5080,7 +5369,7 @@ __initfunc(static int matroxfb_getmemory(WPMINFO unsigned int maxSize, unsigned
 }
 
 #ifdef CONFIG_FB_MATROX_MILLENIUM
-__initfunc(static int Ti3026_preinit(WPMINFO struct matrox_hw_state* hw)) {
+static int __init Ti3026_preinit(WPMINFO struct matrox_hw_state* hw){
        static const int vxres_mill2[] = { 512,        640, 768,  800,  832,  960, 
                                          1024, 1152, 1280,      1600, 1664, 1920, 
                                          2048, 0};
@@ -5133,7 +5422,7 @@ __initfunc(static int Ti3026_preinit(WPMINFO struct matrox_hw_state* hw)) {
        return 0;
 }
 
-__initfunc(static void Ti3026_reset(WPMINFO struct matrox_hw_state* hw)) {
+static void __init Ti3026_reset(WPMINFO struct matrox_hw_state* hw){
        
        DBG("Ti3026_reset")
        
@@ -5163,20 +5452,28 @@ static struct matrox_switch matrox_G100 = {
 
 struct video_board {
        int maxvram;
+       int maxdisplayable;
        int accelID;
        struct matrox_switch* lowlevel;
                 };
 #ifdef CONFIG_FB_MATROX_MILLENIUM
-static struct video_board vbMillenium __initdata       = {0x0800000,   FB_ACCEL_MATROX_MGA2064W,       &matrox_millenium};
-static struct video_board vbMillenium2 __initdata      = {0x1000000,   FB_ACCEL_MATROX_MGA2164W,       &matrox_millenium};
-static struct video_board vbMillenium2A __initdata     = {0x1000000,   FB_ACCEL_MATROX_MGA2164W_AGP,   &matrox_millenium};
+static struct video_board vbMillenium __initdata   = {0x0800000, 0x0800000, FB_ACCEL_MATROX_MGA2064W,    &matrox_millenium};
+static struct video_board vbMillenium2 __initdata  = {0x1000000, 0x0800000, FB_ACCEL_MATROX_MGA2164W,    &matrox_millenium};
+static struct video_board vbMillenium2A __initdata = {0x1000000, 0x0800000, FB_ACCEL_MATROX_MGA2164W_AGP, &matrox_millenium};
 #endif /* CONFIG_FB_MATROX_MILLENIUM */
 #ifdef CONFIG_FB_MATROX_MYSTIQUE
-static struct video_board vbMystique __initdata                = {0x0800000,   FB_ACCEL_MATROX_MGA1064SG,      &matrox_mystique};
+static struct video_board vbMystique __initdata    = {0x0800000, 0x0800000, FB_ACCEL_MATROX_MGA1064SG,   &matrox_mystique};
 #endif /* CONFIG_FB_MATROX_MYSTIQUE */
 #ifdef CONFIG_FB_MATROX_G100
-static struct video_board vbG100 __initdata            = {0x0800000,   FB_ACCEL_MATROX_MGAG100,        &matrox_G100};
-static struct video_board vbG200 __initdata            = {0x1000000,   FB_ACCEL_MATROX_MGAG200,        &matrox_G100};
+static struct video_board vbG100 __initdata       = {0x0800000, 0x0800000, FB_ACCEL_MATROX_MGAG100,      &matrox_G100};
+static struct video_board vbG200 __initdata       = {0x1000000, 0x1000000, FB_ACCEL_MATROX_MGAG200,      &matrox_G100};
+#ifdef CONFIG_FB_MATROX_32MB
+/* from doc it looks like that accelerator can draw only to low 16MB :-( Direct accesses & displaying are OK for
+   whole 32MB */
+static struct video_board vbG400 __initdata       = {0x2000000, 0x1000000, FB_ACCEL_MATROX_MGAG400,      &matrox_G100};
+#else
+static struct video_board vbG400 __initdata       = {0x2000000, 0x1000000, FB_ACCEL_MATROX_MGAG400,      &matrox_G100};
+#endif
 #endif
 
 #define DEVF_VIDEO64BIT        0x01
@@ -5185,6 +5482,15 @@ static struct video_board vbG200 __initdata              = {0x1000000,   FB_ACCEL_MATROX_MGAG2
 #define        DEVF_MILLENIUM2 0x08
 #define DEVF_CROSS4MB  0x10
 #define DEVF_TEXT4B    0x20
+#define DEVF_DDC_8_2   0x40
+#define DEVF_DMA       0x80
+#define DEVF_SUPPORT32MB       0x100
+#define DEVF_ANY_VXRES         0x200
+
+#define DEVF_G100      (DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB | DEVF_DDC_8_2) /* no doc, no vxres... */
+#define DEVF_G200      (DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB | DEVF_DDC_8_2 | DEVF_ANY_VXRES)
+#define DEVF_G400      (DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB | DEVF_DDC_8_2 | DEVF_ANY_VXRES | DEVF_SUPPORT32MB)
+
 static struct board {
        unsigned short vendor, device, rev, svid, sid;
        unsigned int flags;
@@ -5229,88 +5535,94 @@ static struct board {
 #ifdef CONFIG_FB_MATROX_G100
        {PCI_VENDOR_ID_MATROX,  PCI_DEVICE_ID_MATROX_G100,      0xFF,
                PCI_SS_VENDOR_ID_MATROX,        PCI_SS_ID_MATROX_MGA_G100_PCI,
-               DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
+               DEVF_G100,
                230000,
                &vbG100,
                "MGA-G100 (PCI)"},
        {PCI_VENDOR_ID_MATROX,  PCI_DEVICE_ID_MATROX_G100,      0xFF,
                0,                      0,
-               DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
+               DEVF_G100,
                230000,
                &vbG100,
                "unknown G100 (PCI)"},
        {PCI_VENDOR_ID_MATROX,  PCI_DEVICE_ID_MATROX_G100_AGP,  0xFF,
                PCI_SS_VENDOR_ID_MATROX,        PCI_SS_ID_MATROX_GENERIC,
-               DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
+               DEVF_G100,
                230000,
                &vbG100,
                "MGA-G100 (AGP)"},
        {PCI_VENDOR_ID_MATROX,  PCI_DEVICE_ID_MATROX_G100_AGP,  0xFF,
                PCI_SS_VENDOR_ID_MATROX,        PCI_SS_ID_MATROX_MGA_G100_AGP,
-               DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
+               DEVF_G100,
                230000,
                &vbG100,
                "MGA-G100 (AGP)"},
        {PCI_VENDOR_ID_MATROX,  PCI_DEVICE_ID_MATROX_G100_AGP,  0xFF,
                PCI_SS_VENDOR_ID_SIEMENS_NIXDORF,       PCI_SS_ID_SIEMENS_MGA_G100_AGP,
-               DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
+               DEVF_G100,
                230000,
                &vbG100,
                "MGA-G100 (AGP)"},
        {PCI_VENDOR_ID_MATROX,  PCI_DEVICE_ID_MATROX_G100_AGP,  0xFF,
                PCI_SS_VENDOR_ID_MATROX,        PCI_SS_ID_MATROX_PRODUCTIVA_G100_AGP,
-               DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
+               DEVF_G100,
                230000,
                &vbG100,
                "Productiva G100 (AGP)"},
        {PCI_VENDOR_ID_MATROX,  PCI_DEVICE_ID_MATROX_G100_AGP,  0xFF,
                0,                      0,
-               DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
+               DEVF_G100,
                230000,
                &vbG100,
                "unknown G100 (AGP)"},
        {PCI_VENDOR_ID_MATROX,  PCI_DEVICE_ID_MATROX_G200_PCI,  0xFF,
                0,                      0,
-               DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
+               DEVF_G200,
                250000,
                &vbG200,
                "unknown G200 (PCI)"},
        {PCI_VENDOR_ID_MATROX,  PCI_DEVICE_ID_MATROX_G200_AGP,  0xFF,
                PCI_SS_VENDOR_ID_MATROX,        PCI_SS_ID_MATROX_GENERIC,
-               DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
+               DEVF_G200,
                220000,
                &vbG200,
                "MGA-G200 (AGP)"},
        {PCI_VENDOR_ID_MATROX,  PCI_DEVICE_ID_MATROX_G200_AGP,  0xFF,
                PCI_SS_VENDOR_ID_MATROX,        PCI_SS_ID_MATROX_MYSTIQUE_G200_AGP,
-               DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
+               DEVF_G200,
                230000,
                &vbG200,
                "Mystique G200 (AGP)"},
        {PCI_VENDOR_ID_MATROX,  PCI_DEVICE_ID_MATROX_G200_AGP,  0xFF,
                PCI_SS_VENDOR_ID_MATROX,        PCI_SS_ID_MATROX_MILLENIUM_G200_AGP,
-               DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
+               DEVF_G200,
                250000,
                &vbG200,
                "Millennium G200 (AGP)"},
        {PCI_VENDOR_ID_MATROX,  PCI_DEVICE_ID_MATROX_G200_AGP,  0xFF,
                PCI_SS_VENDOR_ID_MATROX,        PCI_SS_ID_MATROX_MARVEL_G200_AGP,
-               DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
+               DEVF_G200,
                230000,
                &vbG200,
                "Marvel G200 (AGP)"},
        {PCI_VENDOR_ID_MATROX,  PCI_DEVICE_ID_MATROX_G200_AGP,  0xFF,
                PCI_SS_VENDOR_ID_SIEMENS_NIXDORF,       PCI_SS_ID_SIEMENS_MGA_G200_AGP,
-               DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
+               DEVF_G200,
                230000,
                &vbG200,
                "MGA-G200 (AGP)"},
        {PCI_VENDOR_ID_MATROX,  PCI_DEVICE_ID_MATROX_G200_AGP,  0xFF,
                0,                      0,
-               DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
+               DEVF_G200,
                230000,
                &vbG200,
                "unknown G200 (AGP)"},
+       {PCI_VENDOR_ID_MATROX,  PCI_DEVICE_ID_MATROX_G400_AGP,  0xFF,
+               0,                      0,
+               DEVF_G400,
+               360000,
+               &vbG400,
+               "unknown G400 (AGP)"},
 #endif
        {0,                     0,                              0xFF,
                0,                      0,
@@ -5319,7 +5631,7 @@ static struct board {
                NULL,
                NULL}};
        
-__initfunc(static int initMatrox2(WPMINFO struct display* d, struct board* b)) {
+static int __init initMatrox2(WPMINFO struct display* d, struct board* b){
        unsigned long ctrlptr_phys = 0;
        unsigned long video_base_phys = 0;
        unsigned int memsize;
@@ -5348,17 +5660,21 @@ __initfunc(static int initMatrox2(WPMINFO struct display* d, struct board* b)) {
                ACCESS_FBINFO(devflags.vgastepdisp) = 64;
                ACCESS_FBINFO(devflags.text_type_aux) = FB_AUX_TEXT_MGA_STEP8;
        }
+#ifdef CONFIG_FB_MATROX_32MB
+       ACCESS_FBINFO(devflags.support32MB) = b->flags & DEVF_SUPPORT32MB;
+#endif
+       ACCESS_FBINFO(devflags.precise_width) = !(b->flags & DEVF_ANY_VXRES);
        ACCESS_FBINFO(devflags.textstep) = ACCESS_FBINFO(devflags.vgastep) * ACCESS_FBINFO(devflags.textmode);
        ACCESS_FBINFO(devflags.textvram) = 65536 / ACCESS_FBINFO(devflags.textmode);
 
        if (ACCESS_FBINFO(capable.cross4MB) < 0)
                ACCESS_FBINFO(capable.cross4MB) = b->flags & DEVF_CROSS4MB;
        if (b->flags & DEVF_SWAPS) {
-               ctrlptr_phys = ACCESS_FBINFO(pcidev)->resource[1].start & ~0x3FFF;
-               video_base_phys = ACCESS_FBINFO(pcidev)->resource[0].start & ~0x7FFFFF; /* aligned at 8MB (or 16 for Mill 2) */
+               ctrlptr_phys = ACCESS_FBINFO(pcidev)->resource[1].start;
+               video_base_phys = ACCESS_FBINFO(pcidev)->resource[0].start;
        } else {
-               ctrlptr_phys = ACCESS_FBINFO(pcidev)->resource[0].start & ~0x3FFF;
-               video_base_phys = ACCESS_FBINFO(pcidev)->resource[1].start & ~0x7FFFFF; /* aligned at 8MB */
+               ctrlptr_phys = ACCESS_FBINFO(pcidev)->resource[0].start;
+               video_base_phys = ACCESS_FBINFO(pcidev)->resource[1].start;
        }
        if (!ctrlptr_phys) {
                printk(KERN_ERR "matroxfb: control registers are not available, matroxfb disabled\n");
@@ -5472,8 +5788,8 @@ __initfunc(static int initMatrox2(WPMINFO struct display* d, struct board* b)) {
                return -ENOMEM;
        }
        ACCESS_FBINFO(video.len_usable) = ACCESS_FBINFO(video.len);
-       if (ACCESS_FBINFO(video.len_usable) > 0x08000000)
-               ACCESS_FBINFO(video.len_usable) = 0x08000000;
+       if (ACCESS_FBINFO(video.len_usable) > b->base->maxdisplayable)
+               ACCESS_FBINFO(video.len_usable) = b->base->maxdisplayable;
 #ifdef CONFIG_MTRR
        if (mtrr) {
                ACCESS_FBINFO(mtrr.vram) = mtrr_add(video_base_phys, ACCESS_FBINFO(video.len), MTRR_TYPE_WRCOMB, 1);
@@ -5482,11 +5798,16 @@ __initfunc(static int initMatrox2(WPMINFO struct display* d, struct board* b)) {
        }
 #endif /* CONFIG_MTRR */
 
+       if (!ACCESS_FBINFO(devflags.novga))
+               request_region(0x3C0, 32, "matrox");
+       ACCESS_FBINFO(hw_switch->reset(PMINFO hw));
+
 /* validate params, autodetect k, M */
        if (fh < 1000) fh *= 1000;      /* 1kHz minimum */
        if (maxclk < 1000) maxclk *= 1000;      /* kHz -> Hz, MHz -> kHz */
        if (maxclk < 1000000) maxclk *= 1000;   /* kHz -> Hz, 1MHz minimum */
-       vesa &= 0x1DFF;         /* mask out clearscreen, acceleration and so on */
+       if (vesa != ~0)
+               vesa &= 0x1DFF;         /* mask out clearscreen, acceleration and so on */
 
        ACCESS_FBINFO(fbcon.monspecs.hfmin) = 0;
        ACCESS_FBINFO(fbcon.monspecs.hfmax) = fh;
@@ -5504,19 +5825,19 @@ __initfunc(static int initMatrox2(WPMINFO struct display* d, struct board* b)) {
        }
        {
                int res = RSResolution(RSptr->info)-1;
-               if (!left)
+               if (left == ~0)
                        left = timmings[res].left;
                if (!xres)
                        xres = timmings[res].xres;
-               if (!right)
+               if (right == ~0)
                        right = timmings[res].right;
                if (!hslen)
                        hslen = timmings[res].hslen;
-               if (!upper)
+               if (upper == ~0)
                        upper = timmings[res].upper;
                if (!yres)
                        yres = timmings[res].yres;
-               if (!lower)
+               if (lower == ~0)
                        lower = timmings[res].lower;
                if (!vslen)
                        vslen = timmings[res].vslen;
@@ -5525,6 +5846,7 @@ __initfunc(static int initMatrox2(WPMINFO struct display* d, struct board* b)) {
                if (depth == -1)
                        depth = RSDepth(RSptr->info);
        }
+#if 0  
        if (sync == -1) {
                sync = 0;
                if (yres < 400)
@@ -5532,31 +5854,7 @@ __initfunc(static int initMatrox2(WPMINFO struct display* d, struct board* b)) {
                else if (yres < 480)
                        sync |= FB_SYNC_VERT_HIGH_ACT;
        }
-       if (xres < 320)
-               xres = 320;
-       if (xres > 2048)
-               xres = 2048;
-       if (yres < 200)
-               yres = 200;
-       if (yres > 2048)
-               yres = 2048;
-       {
-               unsigned int tmp;
-
-               if (fv) {
-                       tmp = fv * (upper + yres + lower + vslen);
-                       if ((tmp < fh) || (fh == 0)) fh = tmp;
-               }
-               if (fh) {
-                       tmp = fh * (left + xres + right + hslen);
-                       if ((tmp < maxclk) || (maxclk == 0)) maxclk = tmp;
-               }
-               maxclk = (maxclk + 499) / 500;
-               if (maxclk) {
-                       tmp = (2000000000 + maxclk) / maxclk;
-                       if (tmp > pixclock) pixclock = tmp;
-               }
-       }
+#endif
        if ((depth == RSText8) && (!*ACCESS_FBINFO(fbcon.fontname))) {
                strcpy(ACCESS_FBINFO(fbcon.fontname), "VGA8x8");
        }
@@ -5564,27 +5862,8 @@ __initfunc(static int initMatrox2(WPMINFO struct display* d, struct board* b)) {
        vesafb_defined.green = colors[depth-1].green;
        vesafb_defined.blue = colors[depth-1].blue;
        vesafb_defined.bits_per_pixel = colors[depth-1].bits_per_pixel;
-       if (pixclock < 2000)            /* > 500MHz */
-               pixclock = 4000;        /* 250MHz */
-       if (pixclock > 1000000)
-               pixclock = 1000000;     /* 1MHz */
-       vesafb_defined.xres = xres;
-       vesafb_defined.yres = yres;
-       vesafb_defined.xoffset = 0;
-       vesafb_defined.yoffset = 0;
        vesafb_defined.grayscale = grayscale;
-       vesafb_defined.pixclock = pixclock;
-       vesafb_defined.left_margin = left;
-       vesafb_defined.right_margin = right;
-       vesafb_defined.hsync_len = hslen;
-       vesafb_defined.upper_margin = upper;
-       vesafb_defined.lower_margin = lower;
-       vesafb_defined.vsync_len = vslen;
-       vesafb_defined.sync = sync;
        vesafb_defined.vmode = 0;
-
-       if (!ACCESS_FBINFO(devflags.novga))
-               request_region(0x3C0, 32, "matrox");
        if (noaccel)
                vesafb_defined.accel_flags &= ~FB_ACCELF_TEXT;
 
@@ -5597,8 +5876,60 @@ __initfunc(static int initMatrox2(WPMINFO struct display* d, struct board* b)) {
        ACCESS_FBINFO(fbcon.updatevar) = &matroxfb_updatevar;
        ACCESS_FBINFO(fbcon.blank) = &matroxfb_blank;
        ACCESS_FBINFO(fbcon.flags) = FBINFO_FLAG_DEFAULT;
-       ACCESS_FBINFO(hw_switch->reset(PMINFO hw));
        ACCESS_FBINFO(video.len_usable) &= PAGE_MASK;
+
+#if 0
+       fb_find_mode(&vesafb_defined, &ACCESS_FBINFO(fbcon), videomode[0]?videomode:NULL,
+               NULL, 0, NULL, vesafb_defined.bits_per_pixel);
+#endif
+       /* mode modifiers */
+       if (sync != -1)
+               vesafb_defined.sync = sync;
+       if (hslen)
+               vesafb_defined.hsync_len = hslen;
+       if (vslen)
+               vesafb_defined.vsync_len = vslen;
+       if (left != ~0)
+               vesafb_defined.left_margin = left;
+       if (right != ~0)
+               vesafb_defined.right_margin = right;
+       if (upper != ~0)
+               vesafb_defined.upper_margin = upper;
+       if (lower != ~0)
+               vesafb_defined.lower_margin = lower;
+       if (xres)
+               vesafb_defined.xres = xres;
+       if (yres)
+               vesafb_defined.yres = yres;
+       /* fv, fh, maxclk limits was specified */
+       {
+               unsigned int tmp;
+
+               if (fv) {
+                       tmp = fv * (vesafb_defined.upper_margin + vesafb_defined.yres 
+                                 + vesafb_defined.lower_margin + vesafb_defined.vsync_len);
+                       if ((tmp < fh) || (fh == 0)) fh = tmp;
+               }
+               if (fh) {
+                       tmp = fh * (vesafb_defined.left_margin + vesafb_defined.xres 
+                                 + vesafb_defined.right_margin + vesafb_defined.hsync_len);
+                       if ((tmp < maxclk) || (maxclk == 0)) maxclk = tmp;
+               }
+               maxclk = (maxclk + 499) / 500;
+               if (maxclk) {
+                       tmp = (2000000000 + maxclk) / maxclk;
+                       if (tmp > pixclock) pixclock = tmp;
+               }
+       }
+       if (pixclock) {
+               if (pixclock < 2000)            /* > 500MHz */
+                       pixclock = 4000;        /* 250MHz */
+               if (pixclock > 1000000)
+                       pixclock = 1000000;     /* 1MHz */
+               vesafb_defined.pixclock = pixclock;
+       }
+               
+       /* FIXME: Where to move this?! */
 #if defined(CONFIG_FB_OF)
 #if defined(CONFIG_FB_COMPAT_XPMAC)
        strcpy(ACCESS_FBINFO(matrox_name), "MTRX,");    /* OpenFirmware naming convension */
@@ -5608,30 +5939,30 @@ __initfunc(static int initMatrox2(WPMINFO struct display* d, struct board* b)) {
 #endif
        if ((xres <= 640) && (yres <= 480)) {
                struct fb_var_screeninfo var;
-               int default_vmode = nvram_read_byte(NV_VMODE);
-               int default_cmode = nvram_read_byte(NV_CMODE);
-
-               if ((default_vmode <= 0) || (default_vmode > VMODE_MAX))
+               if (default_vmode == VMODE_NVRAM) {
+                       default_vmode = nvram_read_byte(NV_VMODE);
+                       if (default_vmode <= 0 || default_vmode > VMODE_MAX)
+                               default_vmode = VMODE_CHOOSE;
+               }
+               if (default_vmode <= 0 || default_vmode > VMODE_MAX)
                        default_vmode = VMODE_640_480_60;
-               if ((default_cmode < CMODE_8) || (default_cmode > CMODE_32))
+               if (default_cmode == CMODE_NVRAM)
+                       default_cmode = nvram_read_byte(NV_CMODE);
+               if (default_cmode < CMODE_8 || default_cmode > CMODE_32)
                        default_cmode = CMODE_8;
                if (!mac_vmode_to_var(default_vmode, default_cmode, &var)) {
                        var.accel_flags = vesafb_defined.accel_flags;
                        var.xoffset = var.yoffset = 0;
                        vesafb_defined = var; /* Note: mac_vmode_to_var() doesnot set all parameters */
-               }
+              }
        }
 #endif
-       {
-               int pixel_size = vesafb_defined.bits_per_pixel;
-
-               vesafb_defined.xres_virtual = matroxfb_pitch_adjust(PMINFO vesafb_defined.xres, pixel_size);
-               if (nopan) {
-                       vesafb_defined.yres_virtual = vesafb_defined.yres;
-               } else {
-                       vesafb_defined.yres_virtual = 65536; /* large enough to be INF, but small enough
-                                                               to yres_virtual * xres_virtual < 2^32 */
-               }
+       vesafb_defined.xres_virtual = vesafb_defined.xres;
+       if (nopan) {
+               vesafb_defined.yres_virtual = vesafb_defined.yres;
+       } else {
+               vesafb_defined.yres_virtual = 65536; /* large enough to be INF, but small enough
+                                                       to yres_virtual * xres_virtual < 2^32 */
        }
        if (matroxfb_set_var(&vesafb_defined, -2, &ACCESS_FBINFO(fbcon))) {
                printk(KERN_ERR "matroxfb: cannot set required parameters\n");
@@ -5647,8 +5978,9 @@ __initfunc(static int initMatrox2(WPMINFO struct display* d, struct board* b)) {
 /* We do not have to set currcon to 0... register_framebuffer do it for us on first console
  * and we do not want currcon == 0 for subsequent framebuffers */
 
-       if (register_framebuffer(&ACCESS_FBINFO(fbcon)) < 0)
+       if (register_framebuffer(&ACCESS_FBINFO(fbcon)) < 0) {
                return -EINVAL;
+       }
        printk("fb%d: %s frame buffer device\n",
               GET_FB_IDX(ACCESS_FBINFO(fbcon.node)), ACCESS_FBINFO(fbcon.modename));
        if (ACCESS_FBINFO(currcon) < 0) {
@@ -5663,7 +5995,7 @@ __initfunc(static int initMatrox2(WPMINFO struct display* d, struct board* b)) {
 
 static struct matrox_fb_info* fb_list = NULL;
 
-__initfunc(static int matrox_init(void)) {
+static int __init matrox_init(void){
        struct pci_dev* pdev = NULL;
 
        DBG("matrox_init")
@@ -5756,7 +6088,7 @@ leave:;
 #ifndef MODULE
 static int __init initialized = 0;
 
-__initfunc(void matroxfb_init(void))
+void __init matroxfb_init(void)
 {
        DBG("matroxfb_init")
        
@@ -5764,10 +6096,12 @@ __initfunc(void matroxfb_init(void))
                initialized = 1;
                matrox_init();
        }
+       if (!fb_list) return -ENXIO;
+       return 0;
 }
 
 #if defined(CONFIG_FB_OF)
-__initfunc(int matrox_of_init(struct device_node *dp)) {
+int __init matrox_of_init(struct device_node *dp){
        DBG("matrox_of_init");
        
        if (!initialized) {
@@ -5781,8 +6115,8 @@ __initfunc(int matrox_of_init(struct device_node *dp)) {
 
 #else
 
-MODULE_AUTHOR("(c) 1998 Petr Vandrovec <vandrove@vc.cvut.cz>");
-MODULE_DESCRIPTION("Accelerated FBDev driver for Matrox Millennium/Mystique/G100/G200");
+MODULE_AUTHOR("(c) 1998,1999 Petr Vandrovec <vandrove@vc.cvut.cz>");
+MODULE_DESCRIPTION("Accelerated FBDev driver for Matrox Millennium/Mystique/G100/G200/G400");
 MODULE_PARM(mem, "i");
 MODULE_PARM_DESC(mem, "Size of available memory in MB, KB or B (2,4,8,12,16MB, default=autodetect)");
 MODULE_PARM(disabled, "i");
@@ -5802,7 +6136,7 @@ MODULE_PARM_DESC(noinit, "Disables W/SG/SD-RAM and bus interface initialization
 MODULE_PARM(mtrr, "i");
 MODULE_PARM_DESC(mtrr, "This speeds up video memory accesses (0=disabled or 1) (default=1)");
 MODULE_PARM(sgram, "i");
-MODULE_PARM_DESC(sgram, "Indicates that G200 has SGRAM memory (0=SDRAM, 1=SGRAM) (default=0)");
+MODULE_PARM_DESC(sgram, "Indicates that G200/G400 has SGRAM memory (0=SDRAM, 1=SGRAM) (default=0)");
 MODULE_PARM(inv24, "i");
 MODULE_PARM_DESC(inv24, "Inverts clock polarity for 24bpp and loop frequency > 100MHz (default=do not invert polarity)");
 MODULE_PARM(inverse, "i");
@@ -5855,14 +6189,20 @@ MODULE_PARM(grayscale, "i");
 MODULE_PARM_DESC(grayscale, "Sets display into grayscale. Works perfectly with paletized videomode (4, 8bpp), some limitations apply to 16, 24 and 32bpp videomodes (default=nograyscale)");
 MODULE_PARM(cross4MB, "i");
 MODULE_PARM_DESC(cross4MB, "Specifies that 4MB boundary can be in middle of line. (default=autodetected)");
+#ifdef CONFIG_FB_OF
+MODULE_PARM(vmode, "i");
+MODULE_PARM_DESC(vmode, "Specify the vmode mode number that should be used (640x480 default)");
+MODULE_PARM(cmode, "i");
+MODULE_PARM_DESC(cmode, "Specify the video depth that should be used (8bit default)");
+#endif
 
-__initfunc(int init_module(void)) {
+int __init init_module(void){
 
        DBG("init_module")
 
 #ifdef DEBUG
        if( disabled )
-               return 0;
+               return -ENXIO;
 #endif /* DEBUG */
 
        if (depth == 0)
index ae32da083dca957487f6035f2668cb8b31ad8cca..0c45722febab29dc287862a13111649e76696136 100644 (file)
@@ -182,7 +182,7 @@ static inline void mda_set_cursor_size(int from, int to)
 
 
 #ifndef MODULE
-__initfunc(void mdacon_setup(char *str, int *ints))
+void __init mdacon_setup(char *str, int *ints)
 {
        /* command line format: mdacon=<first>,<last> */
 
@@ -201,7 +201,7 @@ __initfunc(void mdacon_setup(char *str, int *ints))
 #ifdef MODULE
 static int mda_detect(void)
 #else
-__initfunc(static int mda_detect(void))
+static int __init mda_detect(void)
 #endif
 {
        int count=0;
@@ -283,7 +283,7 @@ __initfunc(static int mda_detect(void))
 #ifdef MODULE
 static void mda_initialize(void)
 #else
-__initfunc(static void mda_initialize(void))
+static void __init mda_initialize(void)
 #endif
 {
        write_mda_b(97, 0x00);          /* horizontal total */
@@ -312,7 +312,7 @@ __initfunc(static void mda_initialize(void))
 #ifdef MODULE
 static const char *mdacon_startup(void)
 #else
-__initfunc(static const char *mdacon_startup(void))
+static const char __init *mdacon_startup(void)
 #endif
 {
        mda_num_columns = 80;
@@ -591,7 +591,7 @@ struct consw mda_con = {
 #ifdef MODULE
 void mda_console_init(void)
 #else
-__initfunc(void mda_console_init(void))
+void __init mda_console_init(void)
 #endif
 {
        if (mda_first_vc > mda_last_vc)
index a769e945436b4e891847cce62263f042548eb4c5..38c569970bbae739a4a49be8c35e3f8790d8483e 100644 (file)
@@ -320,7 +320,7 @@ extern void platinum_of_init(struct device_node *dp);
      *  Initialisation
      */
 
-__initfunc(void offb_init(void))
+void __init offb_init(void)
 {
     struct device_node *dp;
     unsigned int dpy;
@@ -391,7 +391,7 @@ __initfunc(void offb_init(void))
     }
 }
 
-__initfunc(static int offb_init_driver(struct device_node *dp))
+static int __init offb_init_driver(struct device_node *dp)
 {
 #ifdef CONFIG_FB_ATY
     if (!strncmp(dp->name, "ATY", 3)) {
@@ -444,7 +444,7 @@ __initfunc(static int offb_init_driver(struct device_node *dp))
     return 0;
 }
 
-__initfunc(static void offb_init_nodriver(struct device_node *dp))
+static void __init offb_init_nodriver(struct device_node *dp)
 {
     int *pp, i;
     unsigned int len;
@@ -488,9 +488,9 @@ __initfunc(static void offb_init_nodriver(struct device_node *dp))
     
 }
 
-__initfunc(static void offb_init_fb(const char *name, const char *full_name,
+static void offb_init_fb(const char *name, const char *full_name,
                                    int width, int height, int depth,
-                                   int pitch, unsigned long address))
+                                   int pitch, unsigned long address)
 {
     int i;
     struct fb_fix_screeninfo *fix;
index 89f6860f28583d2921dee4a90e617e496e1f76ad..2d915f799d81b92cc9b290002bf67c670b5e6ea8 100644 (file)
@@ -581,7 +581,7 @@ static void platinum_set_par(const struct fb_par_platinum *par, struct fb_info_p
 }
 
 
-__initfunc(static int init_platinum(struct fb_info_platinum *info))
+static int __init init_platinum(struct fb_info_platinum *info)
 {
        struct fb_var_screeninfo var;
        struct display *disp;
@@ -651,7 +651,7 @@ __initfunc(static int init_platinum(struct fb_info_platinum *info))
        return 1;
 }
 
-__initfunc(void platinum_init(void))
+void __init platinum_init(void)
 {
 #ifndef CONFIG_FB_OF
        struct device_node *dp;
@@ -670,7 +670,7 @@ __initfunc(void platinum_init(void))
 #define invalidate_cache(addr)
 #endif
 
-__initfunc(void platinum_of_init(struct device_node *dp))
+void __init platinum_of_init(struct device_node *dp)
 {
        struct fb_info_platinum *info;
        unsigned long           addr, size;
@@ -854,7 +854,7 @@ static int platinum_encode_fix(struct fb_fix_screeninfo *fix,
 /* 
  * Parse user speficied options (`video=platinumfb:')
  */
-__initfunc(void platinum_setup(char *options, int *ints))
+void __init platinum_setup(char *options, int *ints)
 {
        char *this_opt;
 
index dfb0f8ae819abe21468985259b73232084e9128c..002737e3c537685d222c55de5f51c6f51ae8c2da 100644 (file)
@@ -741,7 +741,7 @@ static void pm2fb_reset(struct pm2fb_info* p) {
                set_memclock(p, p->memclock);
 }
 
-__initfunc(static int pm2fb_conf(struct pm2fb_info* p)) {
+static int __init pm2fb_conf(struct pm2fb_info* p){
 
        for (p->board=0; board_table[p->board].detect &&
                        !(board_table[p->board].detect(p)); p->board++);
@@ -1526,14 +1526,14 @@ static int pm2fb_setcolreg(unsigned regno,
 }
 
 static void pm2fb_set_disp(const void* par, struct display* disp,
-                                               struct fb_info_gen* info) {
+                                                  struct fb_info_gen* info) {
        struct pm2fb_info* i=(struct pm2fb_info* )info;
-       u32 flags;
-       u32 depth;
+       unsigned long flags;
+       unsigned long depth;
 
        save_flags(flags);
        cli();
-       disp->screen_base=i->regions.v_fb;
+       disp->screen_base = i->regions.v_fb;
        switch (depth=((struct pm2fb_par* )par)->depth) {
 #ifdef FBCON_HAS_CFB8
                case 8:
@@ -1591,7 +1591,7 @@ void pm2fb_cleanup(struct fb_info* info) {
                board_table[i->board].cleanup(i);
 }
 
-__initfunc(void pm2fb_init(void)) {
+void __init pm2fb_init(void){
 
        memset(&fb_info, 0, sizeof(fb_info));
        if (!pm2fb_conf(&fb_info))
@@ -1624,7 +1624,7 @@ __initfunc(void pm2fb_init(void)) {
        MOD_INC_USE_COUNT;
 }
 
-__initfunc(void pm2fb_mode_setup(char* options)) {
+void __init pm2fb_mode_setup(char* options){
        int i;
 
        for (i=0; user_mode[i].name[0] &&
@@ -1634,13 +1634,13 @@ __initfunc(void pm2fb_mode_setup(char* options)) {
                                        sizeof(pm2fb_options.user_mode));
 }
 
-__initfunc(void pm2fb_font_setup(char* options)) {
+void __init pm2fb_font_setup(char* options){
 
        strncpy(pm2fb_options.font, options, sizeof(pm2fb_options.font));
        pm2fb_options.font[sizeof(pm2fb_options.font)-1]='\0';
 }
 
-__initfunc(void pm2fb_setup(char* options, int* ints)) {
+void __init pm2fb_setup(char* options, int* ints){
        char* next;
 
        while (options) {
index 984edab98e192cb4e25ceb372c07ed4892456fc3..4b7b9a23a99b71c3f21965b5bb677ecdf9d9ccbe 100644 (file)
@@ -104,7 +104,7 @@ promcon_end(struct vc_data *conp, char *b)
        return b - p;
 }
 
-__initfunc(const char *promcon_startup(void))
+const char __init *promcon_startup(void)
 {
        const char *display_desc = "PROM";
        int node;
@@ -128,8 +128,8 @@ __initfunc(const char *promcon_startup(void))
        return display_desc;
 }
 
-__initfunc(static void
-promcon_init_unimap(struct vc_data *conp))
+static void __init 
+promcon_init_unimap(struct vc_data *conp)
 {
        mm_segment_t old_fs = get_fs();
        struct unipair *p, *p1;
@@ -591,7 +591,7 @@ struct consw prom_con = {
        con_invert_region:      NULL,
 };
 
-__initfunc(void prom_con_init(void))
+void __init prom_con_init(void)
 {
 #ifdef CONFIG_DUMMY_CONSOLE
        if (conswitchp == &dummy_con)
index 8cacf5966fa708fc849cf7433c09594bfdddacc8..035019f868d29d47700571e53248113fa925bb06 100644 (file)
@@ -6,6 +6,8 @@
 #include <linux/malloc.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
+
+#include <asm/uaccess.h>
 #include <asm/setup.h>
 #include <asm/segment.h>
 #include <asm/system.h>
 #include <linux/module.h>
 #include <asm/pgtable.h>
 
+#include <video/fbcon.h>
 #include <video/fbcon-cfb16.h>
 
+#define FBIOSETSCROLLMODE   0x4611
 
 #define Q40_PHYS_SCREEN_ADDR 0xFE800000
 static unsigned long q40_screen_addr;
@@ -212,7 +216,7 @@ static int q40_setcolreg(unsigned regno, unsigned red, unsigned green,
   blue>>=10;
 
     if (regno < 16) {
-      fbcon_cmap_cfb16[regno] = ((red & 31) <<5) |
+      fbcon_cmap_cfb16[regno] = ((red & 31) <<6) |
                                 ((green & 31) << 11) |
                                 (blue & 63);
     }
@@ -275,6 +279,27 @@ static int q40fb_ioctl(struct inode *inode, struct file *file,
                      unsigned int cmd, unsigned long arg, int con,
                      struct fb_info *info)
 {
+#if 0
+        unsigned long i;
+       struct display *display;
+
+       if (con>=0)
+         display = &fb_display[con];
+       else
+         display = &disp[0];
+
+        if (cmd == FBIOSETSCROLLMODE)
+         {
+           i = verify_area(VERIFY_READ, (void *)arg, sizeof(unsigned long));
+           if (!i) 
+             {
+               copy_from_user(&i, (void *)arg, sizeof(unsigned long));
+               display->scrollmode = i;
+             }
+           q40_updatescrollmode(display);
+           return i;
+         }
+#endif
        return -EINVAL;
 }
 
@@ -302,6 +327,8 @@ static void q40fb_set_disp(int con, struct fb_info *info)
    display->inverse = 0;
    display->line_length = fix.line_length;
 
+   display->scrollmode = SCROLL_YREDRAW;
+
 #ifdef FBCON_HAS_CFB16
    display->dispsw = &fbcon_cfb16;
    disp->dispsw_data = fbcon_cmap_cfb16;
@@ -312,6 +339,9 @@ static void q40fb_set_disp(int con, struct fb_info *info)
   
 void q40fb_init(void)
 {
+
+        if ( !MACH_IS_Q40)
+         return;
 #if 0
         q40_screen_addr = kernel_map(Q40_PHYS_SCREEN_ADDR, 1024*1024,
                                           KERNELMAP_NO_COPYBACK, NULL);
index 1ee42692f349b4649750f9b3ce6d9e56b764da10..82ea3a84ffdbc0fe68f32a2db1bf0f626b62c1ea 100644 (file)
@@ -109,6 +109,7 @@ struct retz3_fb_info {
        unsigned long physregs;
        int currcon;
        int current_par_valid; /* set to 0 by memset */
+       int blitbusy;
        struct display disp;
        struct retz3fb_par current_par;
        unsigned char color_table [256][3];
@@ -178,11 +179,7 @@ static struct fb_videomode retz3fb_predefined[] __initdata = {
        "640x480", {            /* 640x480, 8 bpp */
            640, 480, 640, 480, 0, 0, 8, 0,
            {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-#if 1
            0, 0, -1, -1, FB_ACCEL_NONE, 39722, 48, 16, 33, 10, 96, 2,
-#else
-           0, 0, -1, -1, FB_ACCELF_TEXT, 38461, 28, 32, 12, 10, 96, 2,
-#endif
            FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,FB_VMODE_NONINTERLACED
        }
     },
@@ -265,7 +262,7 @@ static int z3fb_mode __initdata = 0;
  *    Interface used by the world
  */
 
-void retz3fb_setup(char *options, int *ints);
+void retz3fb_setup(char *options);
 
 static int retz3fb_open(struct fb_info *info, int user);
 static int retz3fb_release(struct fb_info *info, int user);
@@ -346,7 +343,7 @@ static void retz3fb_set_disp(int con, struct fb_info *info);
 static int get_video_mode(const char *name);
 
 
-/* -------------------- Hardware specific routines -------------------------- */
+/* -------------------- Hardware specific routines ------------------------- */
 
 static unsigned short find_fq(unsigned int freq)
 {
@@ -959,6 +956,21 @@ static int retz3_getcolreg(unsigned int regno, unsigned int *red,
 }
 
 
+static inline void retz3_busy(struct display *p)
+{
+       struct retz3_fb_info *zinfo = retz3info(p->fb_info);
+       volatile unsigned char *acm = zinfo->base + ACM_OFFSET;
+       unsigned char blt_status;
+
+       if (zinfo->blitbusy) {
+               do{
+                       blt_status = *((acm) + (ACM_START_STATUS + 2));
+               }while ((blt_status & 1) == 0);
+               zinfo->blitbusy = 0;
+       }
+}
+
+
 static void retz3_bitblt (struct display *p,
                          unsigned short srcx, unsigned short srcy,
                          unsigned short destx, unsigned short desty,
@@ -973,7 +985,6 @@ static void retz3_bitblt (struct display *p,
        unsigned short mod;
        unsigned long tmp;
        unsigned long pat, src, dst;
-       unsigned char blt_status;
 
        int i, xres_virtual = var->xres_virtual;
        short bpp = (var->bits_per_pixel & 0xff);
@@ -983,16 +994,7 @@ static void retz3_bitblt (struct display *p,
 
        tmp = mask | (mask << 16);
 
-#if 0
-       /*
-        * Check for blitter finished before we start messing with the
-        * pattern.
-        */
-       do{
-               blt_status = *(((volatile unsigned char *)acm) +
-                              (ACM_START_STATUS + 2));
-       }while ((blt_status & 1) == 0);
-#endif
+       retz3_busy(p);
 
        i = 0;
        do{
@@ -1042,23 +1044,7 @@ static void retz3_bitblt (struct display *p,
 
        *(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x00;
        *(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x01;
-
-       /*
-        * No reason to wait for the blitter to finish, it is better
-        * just to check if it has finished before we use it again.
-        */
-#if 1
-#if 0
-       while ((*(((volatile unsigned char *)acm) +
-                 (ACM_START_STATUS + 2)) & 1) == 0);
-#else
-       do{
-               blt_status = *(((volatile unsigned char *)acm) +
-                              (ACM_START_STATUS + 2));
-       }
-       while ((blt_status & 1) == 0);
-#endif
-#endif
+       zinfo->blitbusy = 1;
 }
 
 #if 0
@@ -1192,7 +1178,6 @@ static int retz3fb_get_var(struct fb_var_screeninfo *var, int con,
 }
 
 
-#if 1
 static void retz3fb_set_disp(int con, struct fb_info *info)
 {
        struct fb_fix_screeninfo fix;
@@ -1243,7 +1228,6 @@ static void retz3fb_set_disp(int con, struct fb_info *info)
                break;
        }
 }
-#endif
 
 
 /*
@@ -1407,7 +1391,7 @@ static struct fb_ops retz3fb_ops = {
 };
 
 
-__initfunc(void retz3fb_setup(char *options, int *ints))
+void __init retz3fb_setup(char *options, int *ints)
 {
        char *this_opt;
 
@@ -1422,7 +1406,7 @@ __initfunc(void retz3fb_setup(char *options, int *ints))
                } else if (!strncmp(this_opt, "font:", 5)) {
                        strncpy(fontname, this_opt+5, 39);
                        fontname[39] = '\0';
-               }else
+               } else
                        z3fb_mode = get_video_mode(this_opt);
        }
 }
@@ -1432,7 +1416,7 @@ __initfunc(void retz3fb_setup(char *options, int *ints))
  *    Initialization
  */
 
-__initfunc(void retz3fb_init(void))
+void __init retz3fb_init(void)
 {
        unsigned long board_addr, board_size;
        unsigned int key;
@@ -1576,11 +1560,11 @@ static void z3fb_blank(int blank, struct fb_info *info)
  *    Get a Video Mode
  */
 
-__initfunc(static int get_video_mode(const char *name))
+static int __init get_video_mode(const char *name)
 {
        short i;
 
-       for (i = 0; i <= NUM_TOTAL_MODES; i++)
+       for (i = 0; i < NUM_TOTAL_MODES; i++)
                if (!strcmp(name, retz3fb_predefined[i].name)){
                        retz3fb_default = retz3fb_predefined[i].var;
                        return i;
@@ -1613,8 +1597,8 @@ void cleanup_module(void)
  */
 
 #ifdef FBCON_HAS_CFB8
-static void fbcon_retz3_8_bmove(struct display *p, int sy, int sx,
-                               int dy, int dx, int height, int width)
+static void retz3_8_bmove(struct display *p, int sy, int sx,
+                         int dy, int dx, int height, int width)
 {
        int fontwidth = fontwidth(p);
 
@@ -1633,8 +1617,8 @@ static void fbcon_retz3_8_bmove(struct display *p, int sy, int sx,
                     0xffff);
 }
 
-static void fbcon_retz3_8_clear(struct vc_data *conp, struct display *p,
-                               int sy, int sx, int height, int width)
+static void retz3_8_clear(struct vc_data *conp, struct display *p,
+                         int sy, int sx, int height, int width)
 {
        unsigned short col;
        int fontwidth = fontwidth(p);
@@ -1657,9 +1641,42 @@ static void fbcon_retz3_8_clear(struct vc_data *conp, struct display *p,
                     col);
 }
 
+
+static void retz3_putc(struct vc_data *conp, struct display *p, int c,
+                      int yy, int xx)
+{
+       retz3_busy(p);
+       fbcon_cfb8_putc(conp, p, c, yy, xx);
+}
+
+
+static void retz3_putcs(struct vc_data *conp, struct display *p,
+                       const unsigned short *s, int count,
+                       int yy, int xx)
+{
+       retz3_busy(p);
+       fbcon_cfb8_putcs(conp, p, s, count, yy, xx);
+}
+
+
+static void retz3_revc(struct display *p, int xx, int yy)
+{
+       retz3_busy(p);
+       fbcon_cfb8_revc(p, xx, yy);
+}
+
+
+static void retz3_clear_margins(struct vc_data* conp, struct display* p,
+                               int bottom_only)
+{
+       retz3_busy(p);
+       fbcon_cfb8_clear_margins(conp, p, bottom_only);
+}
+
+
 static struct display_switch fbcon_retz3_8 = {
-    fbcon_cfb8_setup, fbcon_retz3_8_bmove, fbcon_retz3_8_clear,
-    fbcon_cfb8_putc, fbcon_cfb8_putcs, fbcon_cfb8_revc, NULL, NULL,
-    fbcon_cfb8_clear_margins, FONTWIDTH(8)
+    fbcon_cfb8_setup, retz3_8_bmove, retz3_8_clear,
+    retz3_putc, retz3_putcs, retz3_revc, NULL, NULL,
+    retz3_clear_margins, FONTWIDTH(8)
 };
 #endif
index 7e17bf1d66a114236cea73a105009565e5aea489..7a162d2ccccdd5354b356bfa08bb61465aed225a 100644 (file)
@@ -743,7 +743,7 @@ static int sbusfb_ioctl(struct inode *inode, struct file *file, u_int cmd,
      *  Setup: parse used options
      */
 
-__initfunc(void sbusfb_setup(char *options, int *ints))
+void __init sbusfb_setup(char *options, int *ints)
 {
        char *p;
        
@@ -960,8 +960,8 @@ void sbusfb_palette(int enter)
      
 extern void (*prom_palette)(int);
 
-__initfunc(static void sbusfb_init_fb(int node, int parent, int fbtype,
-                                     struct linux_sbus_device *sbdp))
+static void __init sbusfb_init_fb(int node, int parent, int fbtype,
+                                     struct linux_sbus_device *sbdp)
 {
        struct fb_fix_screeninfo *fix;
        struct fb_var_screeninfo *var;
@@ -1151,7 +1151,7 @@ static inline int known_card(char *name)
        return FBTYPE_NOTYPE;
 }
 
-__initfunc(void sbusfb_init(void))
+void __init sbusfb_init(void)
 {
        int type;
        struct linux_sbus_device *sbdp;
index 71aafc340fdb13a8e2dd14a816732719e1c10295..9dd9404e02f0b315121026dcf151b23178e917d0 100644 (file)
@@ -919,7 +919,7 @@ static int sgivwfb_mmap(struct fb_info *info, struct file *file,
   return 0;
 }
 
-__initfunc(void sgivwfb_setup(char *options, int *ints))
+void __init sgivwfb_setup(char *options, int *ints)
 {
   char *this_opt;
 
@@ -938,7 +938,7 @@ __initfunc(void sgivwfb_setup(char *options, int *ints))
 /*
  *  Initialisation
  */
-__initfunc(void sgivwfb_init(void))
+void __init sgivwfb_init(void)
 {
   printk("sgivwfb: framebuffer at 0x%lx, size %ldk\n",
         sgivwfb_mem_phys, sgivwfb_mem_size/1024);
index 59a2da71632a9b06845aa9898c77a36dbe0322a0..bb5d873c78b931f8b0ca47e726b617e778043de1 100644 (file)
@@ -297,7 +297,7 @@ struct fbgen_hwswitch xxx_switch = {
      *  Initialization
      */
 
-__initfunc(void xxxfb_init(void))
+void __init xxxfb_init(void)
 {
     fb_info.gen.fbhw = &xxx_switch;
     fb_info.gen.fbhw->detect();
@@ -345,7 +345,7 @@ void xxxfb_cleanup(struct fb_info *info)
      *  Setup
      */
 
-__initfunc(void xxxfb_setup(char *options, int *ints))
+void __init xxxfb_setup(char *options, int *ints)
 {
     /* Parse user speficied options (`video=xxxfb:') */
 }
index 8e9d2fc41541963c2cf3ab506319f9f0ff0da3ca..a579c62f38f6ecf7a78fee3569b95fdac0b6bdab 100644 (file)
@@ -206,7 +206,7 @@ static void tcx_margins (struct fb_info_sbusfb *fb, struct display *p, int x_mar
 
 static char idstring[60] __initdata = { 0 };
 
-__initfunc(char *tcxfb_init(struct fb_info_sbusfb *fb))
+char __init *tcxfb_init(struct fb_info_sbusfb *fb)
 {
        struct fb_fix_screeninfo *fix = &fb->fix;
        struct display *disp = &fb->disp;
index d7f2131de4e6f642fc05ca663670401f65854ebc..77985e9f2e1896271084c4c78757a995ad794942 100644 (file)
@@ -471,7 +471,7 @@ static void set_valkyrie_clock(unsigned char *params)
        }
 }
 
-__initfunc(static void init_valkyrie(struct fb_info_valkyrie *p))
+static void __init init_valkyrie(struct fb_info_valkyrie *p)
 {
        struct fb_par_valkyrie *par = &p->par;
        struct fb_var_screeninfo var;
@@ -584,7 +584,7 @@ static void valkyrie_set_par(const struct fb_par_valkyrie *par,
 #endif /* CONFIG_FB_COMPAT_XPMAC */
 }
 
-__initfunc(void valkyriefb_init(void))
+void __init valkyriefb_init(void)
 {
 #ifndef CONFIG_FB_OF
        struct device_node *dp;
@@ -595,7 +595,7 @@ __initfunc(void valkyriefb_init(void))
 #endif /* CONFIG_FB_OF */
 }
 
-__initfunc(void valkyrie_of_init(struct device_node *dp))
+void __init valkyrie_of_init(struct device_node *dp)
 {
        struct fb_info_valkyrie *p;
        unsigned long addr, size;
@@ -848,7 +848,7 @@ static void __init valkyrie_init_info(struct fb_info *info, struct fb_info_valky
 /*
  * Parse user speficied options (`video=valkyriefb:')
  */
-__initfunc(void valkyriefb_setup(char *options, int *ints))
+void __init valkyriefb_setup(char *options, int *ints)
 {
        char *this_opt;
 
index 78af83ef07a233d0ba3e581911597e0a901a115c..c0cb2b7f4c887dd0ead744e060f2a9b55add1fe0 100644 (file)
@@ -96,8 +96,7 @@ static int             mtrr      = 0;
 static int             currcon   = 0;
 
 static int             pmi_setpal = 0; /* pmi for palette changes ??? */
-static int             ypan       = 0;
-static int             ywrap      = 0;
+static int             ypan       = 0;  /* 0..nothing, 1..ypan, 2..ywrap */
 static unsigned short  *pmi_base  = 0;
 static void            (*pmi_start)(void);
 static void            (*pmi_pal)(void);
@@ -130,13 +129,13 @@ static int vesafb_pan_display(struct fb_var_screeninfo *var, int con,
 {
        int offset;
 
-       if (!ypan && !ywrap)
+       if (!ypan)
                return -EINVAL;
        if (var->xoffset)
                return -EINVAL;
-       if (ypan && var->yoffset+var->yres > var->yres_virtual)
+       if (var->yoffset > var->yres_virtual)
                return -EINVAL;
-       if (ywrap && var->yoffset > var->yres_virtual)
+       if ((ypan==1) && var->yoffset+var->yres > var->yres_virtual)
                return -EINVAL;
 
        offset = (var->yoffset * video_linelength + var->xoffset) / 4;
@@ -154,7 +153,7 @@ static int vesafb_pan_display(struct fb_var_screeninfo *var, int con,
 
 static int vesafb_update_var(int con, struct fb_info *info)
 {
-       if (con == currcon && (ywrap || ypan)) {
+       if (con == currcon && ypan) {
                struct fb_var_screeninfo *var = &fb_display[currcon].var;
                return vesafb_pan_display(var,con,info);
        }
@@ -172,8 +171,8 @@ static int vesafb_get_fix(struct fb_fix_screeninfo *fix, int con,
        fix->type = video_type;
        fix->visual = video_visual;
        fix->xpanstep  = 0;
-       fix->ypanstep  = (ywrap || ypan)  ? 1 : 0;
-       fix->ywrapstep =  ywrap           ? 1 : 0;
+       fix->ypanstep  = ypan     ? 1 : 0;
+       fix->ywrapstep = (ypan>1) ? 1 : 0;
        fix->line_length=video_linelength;
        return 0;
 }
@@ -245,7 +244,7 @@ static void vesafb_set_disp(int con)
        }
        memcpy(&vesafb_sw, sw, sizeof(*sw));
        display->dispsw = &vesafb_sw;
-       if (!ypan && !ywrap) {
+       if (!ypan) {
                display->scrollmode = SCROLL_YREDRAW;
                vesafb_sw.bmove = fbcon_redraw_bmove;
        }
@@ -274,7 +273,7 @@ static int vesafb_set_var(struct fb_var_screeninfo *var, int con,
        if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_TEST)
                return 0;
 
-       if (ypan || ywrap) {
+       if (ypan) {
                if (vesafb_defined.yres_virtual != var->yres_virtual) {
                        vesafb_defined.yres_virtual = var->yres_virtual;
                        if (con != -1) {
@@ -486,11 +485,11 @@ void vesafb_setup(char *options, int *ints)
                if (! strcmp(this_opt, "inverse"))
                        inverse=1;
                else if (! strcmp(this_opt, "redraw"))
-                       ywrap=0,ypan=0;
+                       ypan=0;
                else if (! strcmp(this_opt, "ypan"))
-                       ywrap=0,ypan=1;
+                       ypan=1;
                else if (! strcmp(this_opt, "ywrap"))
-                       ywrap=1,ypan=0;
+                       ypan=2;
                else if (! strcmp(this_opt, "vgapal"))
                        pmi_setpal=0;
                else if (! strcmp(this_opt, "pmipal"))
@@ -523,7 +522,7 @@ static void vesafb_blank(int blank, struct fb_info *info)
        /* Not supported */
 }
 
-__initfunc(void vesafb_init(void))
+void __init vesafb_init(void)
 {
        int i,j;
 
@@ -551,9 +550,9 @@ __initfunc(void vesafb_init(void))
        }
 
        if (screen_info.vesapm_seg < 0xc000)
-               ywrap = ypan = pmi_setpal = 0; /* not available or some DOS TSR ... */
+               ypan = pmi_setpal = 0; /* not available or some DOS TSR ... */
 
-       if (ypan || ywrap || pmi_setpal) {
+       if (ypan || pmi_setpal) {
                pmi_base  = (unsigned short*)(__PAGE_OFFSET+((unsigned long)screen_info.vesapm_seg << 4) + screen_info.vesapm_off);
                pmi_start = (void*)((char*)pmi_base + pmi_base[1]);
                pmi_pal   = (void*)((char*)pmi_base + pmi_base[2]);
@@ -571,7 +570,7 @@ __initfunc(void vesafb_init(void))
                                 * memory area and pass it in the ES register to the BIOS function.
                                 */
                                printk("vesafb: can't handle memory requests, pmi disabled\n");
-                               ywrap = ypan = pmi_setpal = 0;
+                               ypan = pmi_setpal = 0;
                        }
                }
        }
@@ -582,13 +581,13 @@ __initfunc(void vesafb_init(void))
        vesafb_defined.yres_virtual=video_size / video_linelength;
        vesafb_defined.bits_per_pixel=video_bpp;
 
-       if ((ypan || ywrap) && vesafb_defined.yres_virtual > video_height) {
+       if (ypan && vesafb_defined.yres_virtual > video_height) {
                printk("vesafb: scrolling: %s using protected mode interface, yres_virtual=%d\n",
-                      ywrap ? "ywrap" : "ypan",vesafb_defined.yres_virtual);
+                      (ypan > 1) ? "ywrap" : "ypan",vesafb_defined.yres_virtual);
        } else {
                printk("vesafb: scrolling: redraw\n");
                vesafb_defined.yres_virtual = video_height;
-               ypan = ywrap = 0;
+               ypan = 0;
        }
        video_height_virtual = vesafb_defined.yres_virtual;
 
index ccc5e2a2753afc50d2aae6039e47ff07792e5f28..f8f9b162bbd4b4b2eed52a326ce2936dd0157425 100644 (file)
@@ -406,7 +406,7 @@ static int vfb_ioctl(struct inode *inode, struct file *file, u_int cmd,
 }
 
 
-__initfunc(void vfb_setup(char *options, int *ints))
+void __init vfb_setup(char *options, int *ints)
 {
     char *this_opt;
 
@@ -429,7 +429,7 @@ __initfunc(void vfb_setup(char *options, int *ints))
      *  Initialisation
      */
 
-__initfunc(void vfb_init(void))
+void __init vfb_init(void)
 {
     if (!vfb_enable)
        return;
index 7f7b1af4dd5b23329b7420b140b12b1edbe6d6d3..7fafa8a4107014005455b567294be9366103c055 100644 (file)
@@ -1003,7 +1003,7 @@ static void vga16fb_blank(int blank, struct fb_info *fb_info)
        }
 }
 
-__initfunc(void vga16fb_init(void))
+void __init vga16_init(void)
 {
        int i,j;
 
@@ -1047,12 +1047,35 @@ __initfunc(void vga16fb_init(void))
        vga16fb_set_disp(-1, &vga16fb);
 
        if (register_framebuffer(&vga16fb.fb_info)<0)
-               return;
+               return -EINVAL;
 
        printk("fb%d: %s frame buffer device\n",
               GET_FB_IDX(vga16fb.fb_info.node), vga16fb.fb_info.modename);
+
+       return 0;
+}
+
+#ifndef MODULE
+__initfunc(void vga16fb_init(void))
+{
+    vga16_init();
 }
 
+#else /* MODULE */
+
+__initfunc(int init_module(void))
+{
+    return vga16_init();
+}
+
+void cleanup_module(void)
+{
+    unregister_framebuffer(&vga16fb.fb_info);
+    release_region(0x3c0, 32);
+    iounmap(vga16fb.video_vbase);
+}
+
+#endif
 
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
index c5fcdacfb6cbe044464b1b22bdb0515e62bd9466..dc82db05b0de4f76f0c2fd0b1ec540b34d824bff 100644 (file)
@@ -162,7 +162,7 @@ static inline void write_vga(unsigned char reg, unsigned int val)
        restore_flags(flags);
 }
 
-__initfunc(static const char *vgacon_startup(void))
+static const char __init *vgacon_startup(void)
 {
        const char *display_desc = NULL;
        u16 saved1, saved2;
index a19c1c9e507854ed06f764dfa23d0bc1602c2f0c..9324114ff06b8811b786490a18720dd3001f647b 100644 (file)
                 (*((unsigned word volatile *)(CyberRegs + reg)) = dat)
 #define wl_3d(reg,dat) \
                 (*((unsigned long volatile *)(CyberRegs + reg)) = dat)
-
 #define rl_3d(reg) \
                 (*((unsigned long volatile *)(CyberRegs + reg)))
 
+#define Select_Zorro2_FrameBuffer(flag) \
+       do { \
+               *((unsigned char volatile *)((Cyber_vcode_switch_base) + 0x08)) = \
+               ((flag * 0x40) & 0xffff); asm volatile ("nop"); \
+       } while (0)
+/*
+ *     may be needed when we initialize the board?
+ *     8bit: flag = 2, 16 bit: flag = 1, 24/32bit: flag = 0 
+ *     _when_ the board is initialized, depth doesnt matter, we allways write
+ *     to the same address, aperture seems not to matter on Z2.
+ */
+
 struct virgefb_par {
    int xres;
    int yres;
@@ -175,7 +186,10 @@ static unsigned char cv3d_on_zorro2;
  *    Predefined Video Modes
  */
 
-static struct fb_videomode virgefb_predefined[] __initdata = {
+static struct {
+    const char *name;
+    struct fb_var_screeninfo var;
+} virgefb_predefined[] __initdata = {
     {
        "640x480-8", {          /* Cybervision 8 bpp */
            640, 480, 640, 480, 0, 0, 8, 0,
@@ -236,28 +250,28 @@ static struct fb_videomode virgefb_predefined[] __initdata = {
        "1024x768-16", {         /* Cybervision 16 bpp */
            1024, 768, 1024, 768, 0, 0, 16, 0,
            {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
-           0, 0, -1, -1, 0, VIRGE16_PIXCLOCK, 64, 96, 35, 12, 112, 2,
+           0, 0, -1, -1, FB_ACCELF_TEXT, VIRGE16_PIXCLOCK, 64, 96, 35, 12, 112, 2,
            FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
        }
     }, {
        "1152x886-16", {         /* Cybervision 16 bpp */
            1152, 886, 1152, 886, 0, 0, 16, 0,
            {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
-           0, 0, -1, -1, 0, VIRGE16_PIXCLOCK, 64, 96, 35, 12, 112, 2,
+           0, 0, -1, -1, FB_ACCELF_TEXT, VIRGE16_PIXCLOCK, 64, 96, 35, 12, 112, 2,
            FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
        }
     }, {
        "1280x1024-16", {         /* Cybervision 16 bpp */
            1280, 1024, 1280, 1024, 0, 0, 16, 0,
            {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
-           0, 0, -1, -1, 0, VIRGE16_PIXCLOCK, 64, 96, 35, 12, 112, 2,
+           0, 0, -1, -1, FB_ACCELF_TEXT, VIRGE16_PIXCLOCK, 64, 96, 35, 12, 112, 2,
            FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
        }
     }, {
        "1600x1200-16", {         /* Cybervision 16 bpp */
            1600, 1200, 1600, 1200, 0, 0, 16, 0,
            {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
-           0, 0, -1, -1, 0, VIRGE16_PIXCLOCK, 64, 96, 35, 12, 112, 2,
+           0, 0, -1, -1, FB_ACCELF_TEXT, VIRGE16_PIXCLOCK, 64, 96, 35, 12, 112, 2,
            FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
        }
     }
@@ -268,10 +282,6 @@ static struct fb_videomode virgefb_predefined[] __initdata = {
 
 
 static int Cyberfb_inverse = 0;
-#if 0
-static int Cyberfb_Cyber8 = 0;        /* Use Cybervision board */
-static int Cyberfb_Cyber16 = 0;       /* Use Cybervision board */
-#endif
 
 /*
  *    Some default modes
@@ -392,6 +402,7 @@ static int Cyber_init(void)
        } else {
                CyberSize = 0x00400000; /* 4 MB */
        }
+
        memset ((char*)CyberMem, 0, CyberSize);
 
        /* Disable hardware cursor */
@@ -667,7 +678,13 @@ void Cyber_blank(int blank)
  * CV3D low-level support
  */
 
-#define Cyber3D_WaitQueue(v)    { do { while ((rl_3d(0x8504) & 0x1f00) < (((v)+2) << 8)); } while (0); }
+#define Cyber3D_WaitQueue(v) \
+{ \
+        do { \
+               while ((rl_3d(0x8504) & 0x1f00) < (((v)+2) << 8)); \
+        } \
+       while (0); \
+}
 
 static inline void Cyber3D_WaitBusy(void)
 {
@@ -699,11 +716,22 @@ unsigned long status;
   */
 
 static void Cyber3D_BitBLT(u_short curx, u_short cury, u_short destx,
-                          u_short desty, u_short width, u_short height)
+                          u_short desty, u_short width, u_short height, u_short depth)
 {
-       unsigned int blitcmd = S3V_BITBLT | S3V_DRAW | S3V_DST_8BPP;
+       unsigned int blitcmd = S3V_BITBLT | S3V_DRAW | S3V_BLT_COPY;
 
-       blitcmd |= S3V_BLT_COPY;
+       switch (depth) {
+#ifdef FBCON_HAS_CFB8
+               case 8 :
+                       blitcmd |= S3V_DST_8BPP;
+                       break;
+#endif
+#ifdef FBCON_HAS_CFB16
+               case 16 :
+                       blitcmd |= S3V_DST_16BPP;
+                       break;
+#endif
+       }
 
        /* Set drawing direction */
        /* -Y, X maj, -X (default) */
@@ -748,16 +776,29 @@ static void Cyber3D_BitBLT(u_short curx, u_short cury, u_short destx,
  */
 
 static void Cyber3D_RectFill(u_short x, u_short y, u_short width,
-                            u_short height, u_short color)
+                            u_short height, u_short color, u_short depth)
 {
        unsigned int tmp;
-       unsigned int blitcmd = S3V_RECTFILL | S3V_DRAW | S3V_DST_8BPP |
+       unsigned int blitcmd = S3V_RECTFILL | S3V_DRAW |
                S3V_BLT_CLEAR | S3V_MONO_PAT | (1 << 26) | (1 << 25);
 
        if (blit_maybe_busy)
                Cyber3D_WaitBusy();
        blit_maybe_busy = 1;
 
+       switch (depth) {
+#ifdef FBCON_HAS_CFB8
+               case 8 :
+                       blitcmd |= S3V_DST_8BPP;
+                       break;
+#endif
+#ifdef FBCON_HAS_CFB16
+               case 16 :
+                       blitcmd |= S3V_DST_16BPP;
+                       break;
+#endif
+       }
+
        tmp = color & 0xff;
        wl_3d(0xa4f4, tmp);
 
@@ -1087,7 +1128,7 @@ static struct fb_ops virgefb_ops = {
 };
 
 
-__initfunc(void virgefb_setup(char *options, int *ints))
+void __init virgefb_setup(char *options, int *ints)
 {
        char *this_opt;
 
@@ -1121,7 +1162,7 @@ __initfunc(void virgefb_setup(char *options, int *ints))
  *    Initialization
  */
 
-__initfunc(void virgefb_init(void))
+void __init virgefb_init(void)
 {
        struct virgefb_par par;
        unsigned long board_addr;
@@ -1157,7 +1198,6 @@ __initfunc(void virgefb_init(void))
        else
        {
                CyberVGARegs = (unsigned long)ioremap(board_addr +0x0c000000, 0x00010000);
-
                CyberRegs_phys = board_addr + 0x05000000;
                CyberMem_phys  = board_addr + 0x04000000;       /* was 0x04800000 */
                CyberRegs = ioremap(CyberRegs_phys, 0x00010000);
@@ -1242,7 +1282,7 @@ static void Cyberfb_blank(int blank, struct fb_info *info)
  *    Get a Video Mode
  */
 
-__initfunc(static int get_video_mode(const char *name))
+static int __init get_video_mode(const char *name)
 {
        int i;
 
@@ -1269,7 +1309,7 @@ static void fbcon_virge8_bmove(struct display *p, int sy, int sx, int dy,
         sx *= 8; dx *= 8; width *= 8;
         Cyber3D_BitBLT((u_short)sx, (u_short)(sy*fontheight(p)), (u_short)dx,
                        (u_short)(dy*fontheight(p)), (u_short)width,
-                       (u_short)(height*fontheight(p)));
+                       (u_short)(height*fontheight(p)), 8);
 }
 
 static void fbcon_virge8_clear(struct vc_data *conp, struct display *p, int sy,
@@ -1281,7 +1321,7 @@ static void fbcon_virge8_clear(struct vc_data *conp, struct display *p, int sy,
         bg = attr_bgcol_ec(p,conp);
         Cyber3D_RectFill((u_short)sx, (u_short)(sy*fontheight(p)),
                          (u_short)width, (u_short)(height*fontheight(p)),
-                         (u_short)bg);
+                         (u_short)bg, 8);
 }
 
 static void fbcon_virge8_putc(struct vc_data *conp, struct display *p, int c, int yy,
@@ -1326,10 +1366,10 @@ static struct display_switch fbcon_virge8 = {
 static void fbcon_virge16_bmove(struct display *p, int sy, int sx, int dy,
                                int dx, int height, int width)
 {
-        sx *= 16; dx *= 16; width *= 16;
+        sx *= 8; dx *= 8; width *= 8;
         Cyber3D_BitBLT((u_short)sx, (u_short)(sy*fontheight(p)), (u_short)dx,
                        (u_short)(dy*fontheight(p)), (u_short)width,
-                       (u_short)(height*fontheight(p)));
+                       (u_short)(height*fontheight(p)), 16);
 }
                 
 static void fbcon_virge16_clear(struct vc_data *conp, struct display *p, int sy,
@@ -1337,11 +1377,11 @@ static void fbcon_virge16_clear(struct vc_data *conp, struct display *p, int sy,
 {
         unsigned char bg;   
                 
-        sx *= 16; width *= 16;
+        sx *= 8; width *= 8;
         bg = attr_bgcol_ec(p,conp);
         Cyber3D_RectFill((u_short)sx, (u_short)(sy*fontheight(p)),
                          (u_short)width, (u_short)(height*fontheight(p)),
-                         (u_short)bg);
+                         (u_short)bg, 16);
 }
    
 static void fbcon_virge16_putc(struct vc_data *conp, struct display *p, int c, int yy,
index 3734b98d58a57c7038a38451cb9318c54d56c7a7..22e5576388a91ccf13343de65b79900cdc8e3e78 100644 (file)
@@ -840,7 +840,7 @@ out:
  * pressures on different devices - thus the (currently unused)
  * 'dev' parameter.
  */
-int too_many_dirty_buffers;
+static int too_many_dirty_buffers;
 
 void balance_dirty(kdev_t dev)
 {
@@ -1523,6 +1523,176 @@ out:
        return err;
 }
 
+/*
+ * For moronic filesystems that do not allow holes in file.
+ * we allow offset==PAGE_SIZE, bytes==0
+ */
+
+int block_write_cont_page(struct file *file, struct page *page, unsigned long offset, unsigned long bytes, const char * buf)
+{
+       struct dentry *dentry = file->f_dentry;
+       struct inode *inode = dentry->d_inode;
+       unsigned long block;
+       int err, partial;
+       unsigned long blocksize, start_block, end_block;
+       unsigned long start_offset, start_bytes, end_bytes;
+       unsigned long bbits, blocks, i, len;
+       struct buffer_head *bh, *head;
+       char * target_buf, *target_data;
+       unsigned long data_offset = offset;
+
+       offset = page->offset-inode->i_size;
+       if (offset < 0) 
+               offset = 0;
+       else if (offset >= data_offset)
+               offset = data_offset;
+       bytes += data_offset-offset;
+
+       target_buf = (char *)page_address(page) + offset;
+       target_data = (char *)page_address(page) + data_offset;
+
+       if (!PageLocked(page))
+               BUG();
+
+       blocksize = inode->i_sb->s_blocksize;
+       if (!page->buffers)
+               create_empty_buffers(page, inode, blocksize);
+       head = page->buffers;
+
+       bbits = inode->i_sb->s_blocksize_bits;
+       block = page->offset >> bbits;
+       blocks = PAGE_SIZE >> bbits;
+       start_block = offset >> bbits;
+       end_block = (offset + bytes - 1) >> bbits;
+       start_offset = offset & (blocksize - 1);
+       start_bytes = blocksize - start_offset;
+       if (start_bytes > bytes)
+               start_bytes = bytes;
+       end_bytes = (offset+bytes) & (blocksize - 1);
+       if (end_bytes > bytes)
+               end_bytes = bytes;
+
+       if (offset < 0 || offset > PAGE_SIZE)
+               BUG();
+       if (bytes+offset < 0 || bytes+offset > PAGE_SIZE)
+               BUG();
+       if (start_block < 0 || start_block > blocks)
+               BUG();
+       if (end_block < 0 || end_block >= blocks)
+               BUG();
+       // FIXME: currently we assume page alignment.
+       if (page->offset & (PAGE_SIZE-1))
+               BUG();
+
+       i = 0;
+       bh = head;
+       partial = 0;
+       do {
+               if (!bh)
+                       BUG();
+
+               if ((i < start_block) || (i > end_block)) {
+                       if (!buffer_uptodate(bh))
+                               partial = 1;
+                       goto skip;
+               }
+
+               /*
+                * If the buffer is not up-to-date, we need to ask the low-level
+                * FS to do something for us (we used to have assumptions about
+                * the meaning of b_blocknr etc, that's bad).
+                *
+                * If "update" is set, that means that the low-level FS should
+                * try to make sure that the block is up-to-date because we're
+                * not going to fill it completely.
+                */
+               bh->b_end_io = end_buffer_io_sync;
+               if (!buffer_mapped(bh)) {
+                       err = inode->i_op->get_block(inode, block, bh, 1);
+                       if (err)
+                               goto out;
+               }
+
+               if (!buffer_uptodate(bh) && (start_offset || (end_bytes && (i == end_block)))) {
+                       if (buffer_new(bh)) {
+                               memset(bh->b_data, 0, bh->b_size);
+                       } else {
+                               ll_rw_block(READ, 1, &bh);
+                               wait_on_buffer(bh);
+                               err = -EIO;
+                               if (!buffer_uptodate(bh))
+                                       goto out;
+                       }
+               }
+
+               len = blocksize;
+               if (start_offset) {
+                       len = start_bytes;
+                       start_offset = 0;
+               } else if (end_bytes && (i == end_block)) {
+                       len = end_bytes;
+                       end_bytes = 0;
+               }
+               err = 0;
+               if (target_buf+len<=target_data)
+                       memset(target_buf, 0, len);
+               else if (target_buf<target_data) {
+                       memset(target_buf, 0, target_data-target_buf);
+                       copy_from_user(target_data, buf,
+                                       len+target_buf-target_data);
+               } else
+                       err = copy_from_user(target_buf, buf, len);
+               target_buf += len;
+               buf += len;
+
+               /*
+                * we dirty buffers only after copying the data into
+                * the page - this way we can dirty the buffer even if
+                * the bh is still doing IO.
+                *
+                * NOTE! This also does a direct dirty balace check,
+                * rather than relying on bdflush just waking up every
+                * once in a while. This is to catch (and slow down)
+                * the processes that write tons of buffer..
+                *
+                * Note how we do NOT want to do this in the full block
+                * case: full pages are flushed not by the people who
+                * dirtied them, but by people who need memory. And we
+                * should not penalize them for somebody else writing
+                * lots of dirty pages.
+                */
+               set_bit(BH_Uptodate, &bh->b_state);
+               if (!test_and_set_bit(BH_Dirty, &bh->b_state)) {
+                       __mark_dirty(bh, 0);
+                       if (too_many_dirty_buffers)
+                               balance_dirty(bh->b_dev);
+               }
+
+               if (err) {
+                       err = -EFAULT;
+                       goto out;
+               }
+
+skip:
+               i++;
+               block++;
+               bh = bh->b_this_page;
+       } while (bh != head);
+
+       /*
+        * is this a partial write that happened to make all buffers
+        * uptodate then we can optimize away a bogus readpage() for
+        * the next read(). Here we 'discover' wether the page went
+        * uptodate as a result of this (potentially partial) write.
+        */
+       if (!partial)
+               SetPageUptodate(page);
+       return bytes;
+out:
+       ClearPageUptodate(page);
+       return err;
+}
+
 
 /*
  * IO completion routine for a buffer_head being used for kiobuf IO: we
@@ -1911,10 +2081,8 @@ static int grow_buffers(int size)
        if (!(page = __get_free_page(GFP_BUFFER)))
                return 0;
        bh = create_buffers(page, size, 0);
-       if (!bh) {
-               free_page(page);
-               return 0;
-       }
+       if (!bh)
+               goto no_buffer_head;
 
        isize = BUFSIZE_INDEX(size);
 
@@ -1944,6 +2112,10 @@ static int grow_buffers(int size)
        mem_map[MAP_NR(page)].buffers = bh;
        atomic_add(PAGE_SIZE, &buffermem);
        return 1;
+
+no_buffer_head:
+       free_page(page);
+       return 0;
 }
 
 /*
@@ -2284,12 +2456,7 @@ int bdflush(void * unused)
                                 */
                                atomic_inc(&bh->b_count);
                                spin_unlock(&lru_list_lock);
-                               if (major == LOOP_MAJOR && written > 1) {
-                                       ll_rw_block(WRITEA, 1, &bh);
-                                       if (buffer_dirty(bh))
-                                               --written;
-                               } else
-                                       ll_rw_block(WRITE, 1, &bh);
+                               ll_rw_block(WRITE, 1, &bh);
                                atomic_dec(&bh->b_count);
                                goto repeat;
                        }
index 4460e94d8c51a25de2a765c1c256e74c8ef6f071..7ab13267dd17d4470b18559b40bf1c10b1e0a8ad 100644 (file)
 #  define PRINTK(x)
 #endif
 
-struct buffer_head *fat_bread (
+struct buffer_head *fat_bread(struct super_block *sb, int block)
+{
+       return MSDOS_SB(sb)->cvf_format->cvf_bread(sb,block);
+}
+struct buffer_head *fat_getblk(struct super_block *sb, int block)
+{
+       return MSDOS_SB(sb)->cvf_format->cvf_getblk(sb,block);
+}
+void fat_brelse (struct super_block *sb, struct buffer_head *bh)
+{
+       if (bh) 
+               MSDOS_SB(sb)->cvf_format->cvf_brelse(sb,bh);
+}
+void fat_mark_buffer_dirty (
        struct super_block *sb,
-       int block)
+       struct buffer_head *bh,
+       int dirty)
 {
-       struct buffer_head *ret = NULL;
-
-       PRINTK(("fat_bread: block=0x%x\n", block));
-       /*
-        * Note that the blocksize is 512, 1024 or 2048, but the first read
-        * is always of size 1024 (or 2048). Doing readahead may be
-        * counterproductive or just plain wrong.
-        */
+       MSDOS_SB(sb)->cvf_format->cvf_mark_buffer_dirty(sb,bh,dirty);
+}
+void fat_set_uptodate (
+       struct super_block *sb,
+       struct buffer_head *bh,
+       int val)
+{
+       MSDOS_SB(sb)->cvf_format->cvf_set_uptodate(sb,bh,val);
+}
+int fat_is_uptodate(struct super_block *sb, struct buffer_head *bh)
+{
+       return MSDOS_SB(sb)->cvf_format->cvf_is_uptodate(sb,bh);
+}
+void fat_ll_rw_block (
+       struct super_block *sb,
+       int opr,
+       int nbreq,
+       struct buffer_head *bh[32])
+{
+       MSDOS_SB(sb)->cvf_format->cvf_ll_rw_block(sb,opr,nbreq,bh);
+}
 
-       if(MSDOS_SB(sb)->cvf_format &&
-          MSDOS_SB(sb)->cvf_format->cvf_bread)
-               return MSDOS_SB(sb)->cvf_format->cvf_bread(sb,block);
+struct buffer_head *default_fat_bread(struct super_block *sb, int block)
+{
+       return bread (sb->s_dev,block,512);
+}
+struct buffer_head *default_fat_getblk(struct super_block *sb, int block)
+{
+       return getblk (sb->s_dev,block,512);
+}
+void default_fat_brelse(struct super_block *sb, struct buffer_head *bh)
+{
+       brelse (bh);
+}
+void default_fat_mark_buffer_dirty (
+       struct super_block *sb,
+       struct buffer_head *bh,
+       int dirty)
+{
+       mark_buffer_dirty (bh,dirty);
+}
+void default_fat_set_uptodate (
+       struct super_block *sb,
+       struct buffer_head *bh,
+       int val)
+{
+       mark_buffer_uptodate(bh, val);
+}
+int default_fat_is_uptodate (struct super_block *sb, struct buffer_head *bh)
+{
+       return buffer_uptodate(bh);
+}
+void default_fat_ll_rw_block (
+       struct super_block *sb,
+       int opr,
+       int nbreq,
+       struct buffer_head *bh[32])
+{
+       ll_rw_block(opr,nbreq,bh);
+}
 
-       if (sb->s_blocksize == 512) {
-               ret = bread (sb->s_dev,block,512);
+struct buffer_head *bigblock_fat_bread (
+       struct super_block *sb,
+       int block)
+{
+       struct buffer_head *ret = NULL;
+       struct buffer_head *real;
+       if (sb->s_blocksize == 1024){
+               real = bread (sb->s_dev,block>>1,1024);
        } else {
-               struct buffer_head *real;
-               if (sb->s_blocksize == 1024){
-                       real = bread (sb->s_dev,block>>1,1024);
-               } else {
-                       real = bread (sb->s_dev,block>>2,2048);
-               }
-
-               if (real != NULL){
-                       ret = (struct buffer_head *)
-                               kmalloc (sizeof(struct buffer_head), GFP_KERNEL);
-                       if (ret != NULL) {
-                               /* #Specification: msdos / strategy / special device / dummy blocks
-                                * Many special device (Scsi optical disk for one) use
-                                * larger hardware sector size. This allows for higher
-                                * capacity.
-
-                                * Most of the time, the MS-DOS filesystem that sits
-                                * on this device is totally unaligned. It use logically
-                                * 512 bytes sector size, with logical sector starting
-                                * in the middle of a hardware block. The bad news is
-                                * that a hardware sector may hold data own by two
-                                * different files. This means that the hardware sector
-                                * must be read, patch and written almost all the time.
-
-                                * Needless to say that it kills write performance
-                                * on all OS.
-
-                                * Internally the linux msdos fs is using 512 bytes
-                                * logical sector. When accessing such a device, we
-                                * allocate dummy buffer cache blocks, that we stuff
-                                * with the information of a real one (1k large).
+               real = bread (sb->s_dev,block>>2,2048);
+       }
 
-                                * This strategy is used to hide this difference to
-                                * the core of the msdos fs. The slowdown is not
-                                * hidden though!
-                                */
-                               /*
-                                * The memset is there only to catch errors. The msdos
-                                * fs is only using b_data
-                                */
-                               memset (ret,0,sizeof(*ret));
-                               ret->b_data = real->b_data;
-                               if (sb->s_blocksize == 2048) {
-                                       if (block & 3) ret->b_data += (block & 3) << 9;
-                               }else{
-                                       if (block & 1) ret->b_data += 512;
-                               }
-                               ret->b_next = real;
+       if (real != NULL) {
+               ret = (struct buffer_head *)
+                       kmalloc (sizeof(struct buffer_head), GFP_KERNEL);
+               if (ret != NULL) {
+                       /* #Specification: msdos / strategy / special device / dummy blocks
+                        * Many special device (Scsi optical disk for one) use
+                        * larger hardware sector size. This allows for higher
+                        * capacity.
+
+                        * Most of the time, the MS-DOS filesystem that sits
+                        * on this device is totally unaligned. It use logically
+                        * 512 bytes sector size, with logical sector starting
+                        * in the middle of a hardware block. The bad news is
+                        * that a hardware sector may hold data own by two
+                        * different files. This means that the hardware sector
+                        * must be read, patch and written almost all the time.
+
+                        * Needless to say that it kills write performance
+                        * on all OS.
+
+                        * Internally the linux msdos fs is using 512 bytes
+                        * logical sector. When accessing such a device, we
+                        * allocate dummy buffer cache blocks, that we stuff
+                        * with the information of a real one (1k large).
+
+                        * This strategy is used to hide this difference to
+                        * the core of the msdos fs. The slowdown is not
+                        * hidden though!
+                        */
+                       /*
+                        * The memset is there only to catch errors. The msdos
+                        * fs is only using b_data
+                        */
+                       memset (ret,0,sizeof(*ret));
+                       ret->b_data = real->b_data;
+                       if (sb->s_blocksize == 2048) {
+                               if (block & 3) ret->b_data += (block & 3) << 9;
                        }else{
-                               brelse (real);
+                               if (block & 1) ret->b_data += 512;
                        }
+                       ret->b_next = real;
+               }else{
+                       brelse (real);
                }
        }
        return ret;
 }
 
-struct buffer_head *fat_getblk(struct super_block *sb, int block)
-{
-       struct buffer_head *ret = NULL;
-       PRINTK(("fat_getblk: block=0x%x\n", block));
-
-       if (MSDOS_SB(sb)->cvf_format &&
-           MSDOS_SB(sb)->cvf_format->cvf_getblk)
-               return MSDOS_SB(sb)->cvf_format->cvf_getblk(sb,block);
-
-       if (sb->s_blocksize == 512){
-               ret = getblk (sb->s_dev,block,512);
-       } else {
-               /*
-                * #Specification: msdos / special device / writing
-                * A write is always preceded by a read of the complete block
-                * (large hardware sector size). This defeat write performance.
-                * There is a possibility to optimize this when writing large
-                * chunk by making sure we are filling large block. Volunteer ?
-                */
-               ret = fat_bread (sb,block);
-       }
-       return ret;
-}
-
-void fat_brelse (
+void bigblock_fat_brelse (
        struct super_block *sb,
        struct buffer_head *bh)
 {
-       if (bh != NULL) {
-               if (MSDOS_SB(sb)->cvf_format &&
-                   MSDOS_SB(sb)->cvf_format->cvf_brelse)
-                       return MSDOS_SB(sb)->cvf_format->cvf_brelse(sb,bh);
-
-               if (sb->s_blocksize == 512){
-                       brelse (bh);
-               }else{
-                       brelse (bh->b_next);
-                       /* We can free the dummy because a new one is allocated at
-                               each fat_getblk() and fat_bread().
-                       */
-                       kfree (bh);
-               }
-       }
+       brelse (bh->b_next);
+       /*
+        * We can free the dummy because a new one is allocated at
+        * each fat_getblk() and fat_bread().
+        */
+       kfree (bh);
 }
-       
-void fat_mark_buffer_dirty (
+
+void bigblock_fat_mark_buffer_dirty (
        struct super_block *sb,
        struct buffer_head *bh,
        int dirty)
 {
-       if (MSDOS_SB(sb)->cvf_format &&
-           MSDOS_SB(sb)->cvf_format->cvf_mark_buffer_dirty) {
-               MSDOS_SB(sb)->cvf_format->cvf_mark_buffer_dirty(sb,bh,dirty);
-               return;
-       }
-       if (sb->s_blocksize != 512){
-               bh = bh->b_next;
-       }
-       mark_buffer_dirty (bh,dirty);
+       mark_buffer_dirty (bh->b_next,dirty);
 }
 
-void fat_set_uptodate (
+void bigblock_fat_set_uptodate (
        struct super_block *sb,
        struct buffer_head *bh,
        int val)
 {
-       if (MSDOS_SB(sb)->cvf_format && 
-           MSDOS_SB(sb)->cvf_format->cvf_set_uptodate) {
-               MSDOS_SB(sb)->cvf_format->cvf_set_uptodate(sb,bh,val);
-               return;
-       }
-       if (sb->s_blocksize != 512){
-               bh = bh->b_next;
-       }
-       mark_buffer_uptodate(bh, val);
+       mark_buffer_uptodate(bh->b_next, val);
 }
-int fat_is_uptodate (
+
+int bigblock_fat_is_uptodate (
        struct super_block *sb,
        struct buffer_head *bh)
 {
-       if(MSDOS_SB(sb)->cvf_format &&
-          MSDOS_SB(sb)->cvf_format->cvf_is_uptodate)
-               return MSDOS_SB(sb)->cvf_format->cvf_is_uptodate(sb,bh);
-       if (sb->s_blocksize != 512){
-               bh = bh->b_next;
-       }
-       return buffer_uptodate(bh);
+       return buffer_uptodate(bh->b_next);
 }
 
-void fat_ll_rw_block (
+void bigblock_fat_ll_rw_block (
        struct super_block *sb,
        int opr,
        int nbreq,
        struct buffer_head *bh[32])
 {
-        if (MSDOS_SB(sb)->cvf_format &&
-           MSDOS_SB(sb)->cvf_format->cvf_ll_rw_block) {
-               MSDOS_SB(sb)->cvf_format->cvf_ll_rw_block(sb,opr,nbreq,bh);
-               return;
-       }
-       if (sb->s_blocksize == 512){
-               ll_rw_block(opr,nbreq,bh);
-       }else{
-               struct buffer_head *tmp[32];
-               int i;
-               for (i=0; i<nbreq; i++){
-                       tmp[i] = bh[i]->b_next;
-               }
-               ll_rw_block(opr,nbreq,tmp);
-       }
+       struct buffer_head *tmp[32];
+       int i;
+       for (i=0; i<nbreq; i++)
+               tmp[i] = bh[i]->b_next;
+       ll_rw_block(opr,nbreq,tmp);
 }
-
index b984fe75967a864117d9bf95a41cff7c112c9686..45f4a800c42b7bb0a63cf0a7dd4a39a1b0ba53c1 100644 (file)
@@ -29,15 +29,21 @@ static struct fat_cache *fat_cache,cache[FAT_CACHE];
    new_value is != -1, that FAT entry is replaced by it. */
 
 int fat_access(struct super_block *sb,int nr,int new_value)
+{
+       return MSDOS_SB(sb)->cvf_format->fat_access(sb,nr,new_value);
+}
+
+int fat_bmap(struct inode *inode,int sector)
+{
+       return MSDOS_SB(inode->i_sb)->cvf_format->cvf_bmap(inode,sector);
+}
+
+int default_fat_access(struct super_block *sb,int nr,int new_value)
 {
        struct buffer_head *bh,*bh2,*c_bh,*c_bh2;
        unsigned char *p_first,*p_last;
        int copy,first,last,next,b;
 
-       if (MSDOS_SB(sb)->cvf_format &&
-           MSDOS_SB(sb)->cvf_format->fat_access)
-               return MSDOS_SB(sb)->cvf_format->fat_access(sb,nr,new_value);
-
        if ((unsigned) (nr-2) >= MSDOS_SB(sb)->clusters)
                return 0;
        if (MSDOS_SB(sb)->fat_bits == 32) {
@@ -265,14 +271,11 @@ int fat_get_cluster(struct inode *inode,int cluster)
        return nr;
 }
 
-int fat_smap(struct inode *inode,int sector)
+int default_fat_bmap(struct inode *inode,int sector)
 {
-       struct msdos_sb_info *sb;
+       struct msdos_sb_info *sb=MSDOS_SB(inode->i_sb);
        int cluster,offset;
 
-       sb = MSDOS_SB(inode->i_sb);
-       if (sb->cvf_format && sb->cvf_format->cvf_smap)
-               return sb->cvf_format->cvf_smap(inode,sector);
        if ((sb->fat_bits != 32) &&
            (inode->i_ino == MSDOS_ROOT_INO || (S_ISDIR(inode->i_mode) &&
             !MSDOS_I(inode)->i_start))) {
@@ -280,6 +283,8 @@ int fat_smap(struct inode *inode,int sector)
                        return 0;
                return sector+sb->dir_start;
        }
+       if (sector >= (MSDOS_I(inode)->i_realsize>>9))
+               return 0;
        cluster = sector/sb->cluster_size;
        offset = sector % sb->cluster_size;
        if (!(cluster = fat_get_cluster(inode,cluster))) return 0;
index 9dd70f8c51cb0724e4fb7c3a9ba9847b95895172..24cf1164f40be62210b7ee576f13528c6da37bda 100644 (file)
 
 #define MAX_CVF_FORMATS 3
 
+struct buffer_head *default_fat_bread(struct super_block *,int);
+struct buffer_head *default_fat_getblk(struct super_block *, int);
+struct buffer_head *bigblock_fat_bread(struct super_block *, int);
+void default_fat_brelse(struct super_block *, struct buffer_head *);
+void bigblock_fat_brelse(struct super_block *, struct buffer_head *);
+void default_fat_mark_buffer_dirty (struct super_block *,
+       struct buffer_head *, int);
+void bigblock_fat_mark_buffer_dirty (struct super_block *,
+       struct buffer_head *, int);
+void default_fat_set_uptodate (struct super_block *, struct buffer_head *,int);
+void bigblock_fat_set_uptodate (struct super_block *, struct buffer_head *,int);
+int default_fat_is_uptodate(struct super_block *, struct buffer_head *);
+int bigblock_fat_is_uptodate(struct super_block *, struct buffer_head *);
+int default_fat_access(struct super_block *sb,int nr,int new_value);
+void default_fat_ll_rw_block (
+       struct super_block *sb,
+       int opr,
+       int nbreq,
+       struct buffer_head *bh[32]);
+void bigblock_fat_ll_rw_block (
+       struct super_block *sb,
+       int opr,
+       int nbreq,
+       struct buffer_head *bh[32]);
+int default_fat_bmap(struct inode *inode,int block);
+ssize_t default_fat_file_write(
+       struct file *filp,
+       const char *buf,
+       size_t count,
+       loff_t *ppos);
+
+struct cvf_format default_cvf = {
+       0,      /* version - who cares? */      
+       "plain",
+       0,      /* flags - who cares? */
+       NULL,
+       NULL,
+       NULL,
+       default_fat_bread,
+       default_fat_getblk,
+       default_fat_brelse,
+       default_fat_mark_buffer_dirty,
+       default_fat_set_uptodate,
+       default_fat_is_uptodate,
+       default_fat_ll_rw_block,
+       default_fat_access,
+       NULL,
+       default_fat_bmap,
+       generic_file_read,
+       default_fat_file_write,
+       NULL,
+       NULL
+};
+
+struct cvf_format bigblock_cvf = {
+       0,      /* version - who cares? */      
+       "big_blocks",
+       0,      /* flags - who cares? */
+       NULL,
+       NULL,
+       NULL,
+       bigblock_fat_bread,
+       bigblock_fat_bread,
+       bigblock_fat_brelse,
+       bigblock_fat_mark_buffer_dirty,
+       bigblock_fat_set_uptodate,
+       bigblock_fat_is_uptodate,
+       bigblock_fat_ll_rw_block,
+       default_fat_access,
+       NULL,
+       default_fat_bmap,
+       NULL,
+       default_fat_file_write,
+       NULL,
+       NULL
+};
+
 struct cvf_format *cvf_formats[MAX_CVF_FORMATS]={NULL,NULL,NULL};
 int cvf_format_use_count[MAX_CVF_FORMATS]={0,0,0};
 
index 82d29a0dfd5c88a9ca3841d3fdeecb214ab4d0d5..628c0bb9c0ef1b99e70ca1397787609108015b9d 100644 (file)
@@ -605,7 +605,7 @@ int fat_add_entries(struct inode *dir,int slots, struct buffer_head **bh,
        struct super_block *sb = dir->i_sb;
        loff_t offset, curr;
        int row;
-       int res;
+       struct buffer_head *new_bh;
 
        offset = curr = 0;
        *bh = NULL;
@@ -621,11 +621,47 @@ int fat_add_entries(struct inode *dir,int slots, struct buffer_head **bh,
        }
        if ((dir->i_ino == MSDOS_ROOT_INO) && (MSDOS_SB(sb)->fat_bits != 32)) 
                return -ENOSPC;
-       if ((res = fat_add_cluster(dir)) < 0) return res;
+       new_bh = fat_extend_dir(dir);
+       if (!new_bh)
+               return -ENOSPC;
+       fat_brelse(sb, new_bh);
        do fat_get_entry(dir,&curr,bh,de,ino); while (++row<slots);
        return offset;
 }
 
+int fat_new_dir(struct inode *dir, struct inode *parent, int is_vfat)
+{
+       struct super_block *sb = dir->i_sb;
+       struct buffer_head *bh;
+       struct msdos_dir_entry *de;
+       __u16 date, time;
+
+       if ((bh = fat_extend_dir(dir)) == NULL) return -ENOSPC;
+       /* zeroed out, so... */
+       fat_date_unix2dos(dir->i_mtime,&time,&date);
+       de = (struct msdos_dir_entry*)&bh->b_data[0];
+       memcpy(de[0].name,MSDOS_DOT,MSDOS_NAME);
+       memcpy(de[1].name,MSDOS_DOTDOT,MSDOS_NAME);
+       de[0].attr = de[1].attr = ATTR_DIR;
+       de[0].time = de[1].time = CT_LE_W(time);
+       de[0].date = de[1].date = CT_LE_W(date);
+       if (is_vfat) {  /* extra timestamps */
+               de[0].ctime = de[1].ctime = CT_LE_W(time);
+               de[0].adate = de[0].cdate =
+                       de[1].adate = de[1].cdate = CT_LE_W(date);
+       }
+       de[0].start = CT_LE_W(MSDOS_I(dir)->i_logstart);
+       de[0].starthi = CT_LE_W(MSDOS_I(dir)->i_logstart>>16);
+       de[1].start = CT_LE_W(MSDOS_I(parent)->i_logstart);
+       de[1].starthi = CT_LE_W(MSDOS_I(parent)->i_logstart>>16);
+       fat_mark_buffer_dirty(sb, bh, 1);
+       fat_brelse(sb, bh);
+       dir->i_atime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+       mark_inode_dirty(dir);
+
+       return 0;
+}
+
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
  * Emacs will notice this stuff at the end of the file and automatically
index a8cd88cac4f9b637625f8042c5137f0473d2adb1..070361aa9ed9a96dce824521b6d98731ea4416a7 100644 (file)
@@ -17,9 +17,9 @@
 
 extern struct file_operations fat_dir_operations;
 
-EXPORT_SYMBOL(fat_add_cluster);
-EXPORT_SYMBOL(fat_add_cluster1);
+EXPORT_SYMBOL(fat_new_dir);
 EXPORT_SYMBOL(fat_bmap);
+EXPORT_SYMBOL(fat_get_block);
 EXPORT_SYMBOL(fat_brelse);
 EXPORT_SYMBOL(fat_cache_inval_inode);
 EXPORT_SYMBOL(fat_clear_inode);
@@ -44,9 +44,7 @@ EXPORT_SYMBOL(fat_read_super);
 EXPORT_SYMBOL(fat_search_long);
 EXPORT_SYMBOL(fat_readdir);
 EXPORT_SYMBOL(fat_scan);
-EXPORT_SYMBOL(fat_smap);
 EXPORT_SYMBOL(fat_statfs);
-EXPORT_SYMBOL(fat_truncate);
 EXPORT_SYMBOL(fat_uni2esc);
 EXPORT_SYMBOL(fat_unlock_creation);
 EXPORT_SYMBOL(fat_write_inode);
index 5d964da2b56f1d504b609a8763d126ca6551cf07..19b91b74f6731ad095398af8ef43850bc0acfe5e 100644 (file)
@@ -57,7 +57,7 @@ struct inode_operations fat_file_inode_operations = {
        NULL,                   /* rename */
        NULL,                   /* readlink */
        NULL,                   /* follow_link */
-       fat_bmap,               /* get_block */
+       fat_get_block,          /* get_block */
        block_read_full_page,   /* readpage */
        NULL,                   /* writepage */
        NULL,                   /* flushpage */
@@ -67,392 +67,117 @@ struct inode_operations fat_file_inode_operations = {
        NULL                    /* revalidate */
 };
 
-/* #Specification: msdos / special devices / mmap      
-       Mmapping does work because a special mmap is provide in that case.
-       Note that it is much less efficient than the generic_file_mmap normally
-       used since it allocate extra buffer. generic_file_mmap is used for
-       normal device (512 bytes hardware sectors).
-*/
-static struct file_operations fat_file_operations_1024 = {
-       NULL,                   /* lseek - default */
-       fat_file_read,          /* read */
-       fat_file_write,         /* write */
-       NULL,                   /* readdir - bad */
-       NULL,                   /* select v2.0.x/poll v2.1.x - default */
-       NULL,                   /* ioctl - default */
-       fat_mmap,               /* mmap */
-       NULL,                   /* no special open is needed */
-       NULL,                   /* flush */
-       NULL,                   /* release */
-       file_fsync              /* fsync */
-};
-
-/* #Specification: msdos / special devices / swap file
-       Swap file can't work on special devices with a large sector
-       size (1024 bytes hard sector). Those devices have a weird
-       MS-DOS filesystem layout. Generally a single hardware sector
-       may contain 2 unrelated logical sector. This mean that there is
-       no easy way to do a mapping between disk sector of a file and virtual
-       memory. So swap file is difficult (not available right now)
-       on those devices. Off course, Ext2 does not have this problem.
-*/
-struct inode_operations fat_file_inode_operations_1024 = {
-       &fat_file_operations_1024,      /* default file operations */
-       NULL,                   /* create */
-       NULL,                   /* lookup */
-       NULL,                   /* link */
-       NULL,                   /* unlink */
-       NULL,                   /* symlink */
-       NULL,                   /* mkdir */
-       NULL,                   /* rmdir */
-       NULL,                   /* mknod */
-       NULL,                   /* rename */
-       NULL,                   /* readlink */
-       NULL,                   /* follow_link */
-       NULL,                   /* get_block */
-       block_read_full_page,   /* readpage */
-       NULL,                   /* writepage */
-       NULL,                   /* flushpage */
-       fat_truncate,           /* truncate */
-       NULL,                   /* permission */
-       NULL,                   /* smap */
-       NULL                    /* revalidate */
-};
-
-static struct file_operations fat_file_operations_readpage = {
-       NULL,                   /* lseek - default */
-       fat_file_read,          /* read */
-       fat_file_write,         /* write */
-       NULL,                   /* readdir - bad */
-       NULL,                   /* select v2.0.x/poll v2.1.x - default */
-       NULL,                   /* ioctl - default */
-       generic_file_mmap,      /* mmap */
-       NULL,                   /* no special open is needed */
-       NULL,                   /* flush */
-       NULL,                   /* release */
-       file_fsync              /* fsync */
-};
-
-struct inode_operations fat_file_inode_operations_readpage = {
-       &fat_file_operations_readpage,  /* default file operations */
-       NULL,                   /* create */
-       NULL,                   /* lookup */
-       NULL,                   /* link */
-       NULL,                   /* unlink */
-       NULL,                   /* symlink */
-       NULL,                   /* mkdir */
-       NULL,                   /* rmdir */
-       NULL,                   /* mknod */
-       NULL,                   /* rename */
-       NULL,                   /* readlink */
-       NULL,                   /* follow_link */
-       NULL,                   /* get_block */
-       fat_readpage,           /* readpage */
-       NULL,                   /* writepage */
-       NULL,                   /* flushpage */
-       fat_truncate,           /* truncate */
-       NULL,                   /* permission */
-       NULL,                   /* smap */
-       NULL                    /* revalidate */
-};
-
-#define MSDOS_PREFETCH 32
-struct fat_pre {
-       int file_sector;/* Next sector to read in the prefetch table */
-                       /* This is relative to the file, not the disk */
-       struct buffer_head *bhlist[MSDOS_PREFETCH];     /* All buffers needed */
-       int nblist;     /* Number of buffers in bhlist */
-       int nolist;     /* index in bhlist */
-};
-/*
-       Order the prefetch of more sectors.
-*/
-static void fat_prefetch (
-       struct inode *inode,
-       struct fat_pre *pre,
-       int nb)         /* How many must we prefetch at once */
-{
-       struct super_block *sb = inode->i_sb;
-       struct buffer_head *bhreq[MSDOS_PREFETCH];      /* Buffers not */
-                                                       /* already read */
-       int nbreq = 0;                  /* Number of buffers in bhreq */
-       int i;
-       for (i=0; i<nb; i++){
-               int sector = fat_smap(inode,pre->file_sector);
-               if (sector != 0){
-                       struct buffer_head *bh;
-                       PRINTK (("fsector2 %d -> %d\n",pre->file_sector-1,sector));
-                       pre->file_sector++;
-                       bh = fat_getblk(sb, sector);
-                       if (bh == NULL) break;
-                       pre->bhlist[pre->nblist++] = bh;
-                       if (!fat_is_uptodate(sb,bh))
-                               bhreq[nbreq++] = bh;
-               }else{
-                       break;
-               }
-       }
-       if (nbreq > 0) fat_ll_rw_block (sb,READ,nbreq,bhreq);
-       for (i=pre->nblist; i<MSDOS_PREFETCH; i++) pre->bhlist[i] = NULL;
-}
-
-/*
-       Read a file into user space
-*/
-static ssize_t fat_file_read_text(
+ssize_t fat_file_read(
        struct file *filp,
        char *buf,
        size_t count,
        loff_t *ppos)
 {
        struct inode *inode = filp->f_dentry->d_inode;
-       struct super_block *sb = inode->i_sb;
-       char *start = buf;
-       char *end   = buf + count;
-       int i;
-       int left_in_file;
-       struct fat_pre pre;
-               
+       return MSDOS_SB(inode->i_sb)->cvf_format
+                       ->cvf_file_read(filp,buf,count,ppos);
+}
 
-       if (!inode) {
-               printk("fat_file_read: inode = NULL\n");
-               return -EINVAL;
+
+int fat_get_block(struct inode *inode, long iblock, struct buffer_head *bh_result, int create) {
+       unsigned long phys;
+       phys = fat_bmap(inode, iblock);
+       if (phys) {
+               bh_result->b_dev = inode->i_dev;
+               bh_result->b_blocknr = phys;
+               bh_result->b_state |= (1UL << BH_Mapped);
+               return 0;
        }
-       /* S_ISLNK allows for UMSDOS. Should never happen for normal MSDOS */
-       if (!S_ISREG(inode->i_mode) && !S_ISLNK(inode->i_mode)) {
-               printk("fat_file_read: mode = %07o\n",inode->i_mode);
-               return -EINVAL;
+       if (!create)
+               return 0;
+       if (iblock<<9 != MSDOS_I(inode)->i_realsize) {
+               BUG();
+               return -EIO;
        }
-       if (*ppos >= inode->i_size || count == 0) return 0;
-       /*
-               Tell the buffer cache which block we expect to read in advance
-               Since we are limited with the stack, we preread only MSDOS_PREFETCH
-               because we have to keep the result into the local
-               arrays pre.bhlist and bhreq.
-               
-               Each time we process one block in bhlist, we replace
-               it by a new prefetch block if needed.
-       */
-       PRINTK (("#### ino %ld pos %ld size %ld count %d\n",inode->i_ino,*ppos,inode->i_size,count));
-       {
-               /*
-                       We must prefetch complete block, so we must
-                       take in account the offset in the first block.
-               */
-               int count_max = (*ppos & (SECTOR_SIZE-1)) + count;
-               int   to_reada; /* How many block to read all at once */
-               pre.file_sector = *ppos >> SECTOR_BITS;
-               to_reada = count_max / SECTOR_SIZE;
-               if (count_max & (SECTOR_SIZE-1)) to_reada++;
-               if (filp->f_reada || !MSDOS_I(inode)->i_binary){
-                       /* Doing a read ahead on ASCII file make sure we always */
-                       /* read enough, since we don't know how many blocks */
-                       /* we really need */
-                       int ahead = read_ahead[MAJOR(inode->i_dev)];
-                       PRINTK (("to_reada %d ahead %d\n",to_reada,ahead));
-                       if (ahead == 0) ahead = 8;
-                       to_reada += ahead;
-               }
-               if (to_reada > MSDOS_PREFETCH) to_reada = MSDOS_PREFETCH;
-               pre.nblist = 0;
-               fat_prefetch (inode,&pre,to_reada);
+       if (!(iblock % MSDOS_SB(inode->i_sb)->cluster_size)) {
+               if (fat_add_cluster(inode))
+                       return -ENOSPC;
        }
-       pre.nolist = 0;
-       PRINTK (("count %d ahead %d nblist %d\n",count,read_ahead[MAJOR(inode->i_dev)],pre.nblist));
-       while ((left_in_file = inode->i_size - *ppos) > 0
-               && buf < end){
-               struct buffer_head *bh = pre.bhlist[pre.nolist];
-               char *data;
-               int size,offset;
-               if (bh == NULL) break;
-               pre.bhlist[pre.nolist] = NULL;
-               pre.nolist++;
-               if (pre.nolist == MSDOS_PREFETCH/2){
-                       memcpy (pre.bhlist,pre.bhlist+MSDOS_PREFETCH/2
-                               ,(MSDOS_PREFETCH/2)*sizeof(pre.bhlist[0]));
-                       pre.nblist -= MSDOS_PREFETCH/2;
-                       fat_prefetch (inode,&pre,MSDOS_PREFETCH/2);
-                       pre.nolist = 0;
-               }
-               PRINTK (("file_read pos %ld nblist %d %d %d\n",*ppos,pre.nblist,pre.fetched,count));
-               wait_on_buffer(bh);
-               if (!fat_is_uptodate(sb,bh)){
-                       /* read error  ? */
-                       fat_brelse (sb, bh);
-                       break;
-               }
-               offset = *ppos & (SECTOR_SIZE-1);
-               data = bh->b_data + offset;
-               size = MIN(SECTOR_SIZE-offset,left_in_file);
-               if (MSDOS_I(inode)->i_binary) {
-                       size = MIN(size,end-buf);
-                       copy_to_user(buf,data,size);
-                       buf += size;
-                       *ppos += size;
-               }else{
-                       for (; size && buf < end; size--) {
-                               char ch = *data++;
-                               ++*ppos;
-                               if (ch == 26){
-                                       *ppos = inode->i_size;
-                                       break;
-                               }else if (ch != '\r'){
-                                       put_user(ch,buf++);
-                               }
+       MSDOS_I(inode)->i_realsize+=SECTOR_SIZE;
+       phys=fat_bmap(inode, iblock);
+       if (!phys)
+               BUG();
+       bh_result->b_dev = inode->i_dev;
+       bh_result->b_blocknr = phys;
+       bh_result->b_state |= (1UL << BH_Mapped);
+       bh_result->b_state |= (1UL << BH_New);
+       return 0;
+}
+
+static int fat_write_partial_page(struct file *file, struct page *page, unsigned long offset, unsigned long bytes, const char * buf)
+{
+       struct dentry *dentry = file->f_dentry;
+       struct inode *inode = dentry->d_inode;
+       struct page *new_page, **hash;
+       unsigned long pgpos;
+       unsigned long page_cache = 0;
+       long status;
+
+       pgpos = inode->i_size & PAGE_CACHE_MASK;
+       while (pgpos < page->offset) {
+               hash = page_hash(inode, pgpos);
+repeat_find:   new_page = __find_lock_page(inode, pgpos, hash);
+               if (!new_page) {
+                       if (!page_cache) {
+                               page_cache = page_cache_alloc();
+                               if (page_cache)
+                                       goto repeat_find;
+                               status = -ENOMEM;
+                               goto out;
                        }
+                       new_page = page_cache_entry(page_cache);
+                       if (add_to_page_cache_unique(new_page,inode,pgpos,hash))
+                               goto repeat_find;
+                       page_cache = 0;
                }
-               fat_brelse(sb, bh);
+               status = block_write_cont_page(file, new_page, PAGE_SIZE, 0, NULL);
+               UnlockPage(new_page);
+               page_cache_release(new_page);
+               if (status < 0)
+                       goto out;
+               pgpos = MSDOS_I(inode)->i_realsize & PAGE_CACHE_MASK;
        }
-       PRINTK (("--- %d -> %d\n",count,(int)(buf-start)));
-       for (i=0; i<pre.nblist; i++)
-               fat_brelse (sb, pre.bhlist[i]);
-       if (start == buf)
-               return -EIO;
-       if (!IS_RDONLY(inode))
-               inode->i_atime = CURRENT_TIME;
-       filp->f_reada = 1;      /* Will be reset if a lseek is done */
-       return buf-start;
+       status = block_write_cont_page(file, page, offset, bytes, buf);
+out:
+       if (page_cache)
+               page_cache_free(page_cache);
+       return status;
 }
 
-ssize_t fat_file_read(
+ssize_t fat_file_write(
        struct file *filp,
-       char *buf,
+       const char *buf,
        size_t count,
        loff_t *ppos)
 {
        struct inode *inode = filp->f_dentry->d_inode;
-       if (MSDOS_SB(inode->i_sb)->cvf_format &&
-           MSDOS_SB(inode->i_sb)->cvf_format->cvf_file_read)
-               return MSDOS_SB(inode->i_sb)->cvf_format
-                       ->cvf_file_read(filp,buf,count,ppos);
-
-       /*
-        * MS-DOS filesystems with a blocksize > 512 may have blocks
-        * spread over several hardware sectors (unaligned), which
-        * is not something the generic routines can (or would want
-        * to) handle).
-        */
-       if (!MSDOS_I(inode)->i_binary || inode->i_sb->s_blocksize > 512)
-               return fat_file_read_text(filp, buf, count, ppos);
-       return generic_file_read(filp, buf, count, ppos);
+       struct super_block *sb = inode->i_sb;
+       return MSDOS_SB(sb)->cvf_format
+                       ->cvf_file_write(filp,buf,count,ppos);
 }
-/*
-       Write to a file either from user space
-*/
-ssize_t fat_file_write(
+
+ssize_t default_fat_file_write(
        struct file *filp,
        const char *buf,
        size_t count,
        loff_t *ppos)
 {
        struct inode *inode = filp->f_dentry->d_inode;
-       struct super_block *sb = inode->i_sb;
-       int sector,offset,size,left,written;
-       int error,carry;
-       const char *start;
-       char *to,ch;
-       struct buffer_head *bh;
-       int binary_mode = MSDOS_I(inode)->i_binary;
-
-       PRINTK(("fat_file_write: dentry=%p, inode=%p, ino=%ld\n",
-               filp->f_dentry, inode, inode->i_ino));
-       if (!inode) {
-               printk("fat_file_write: inode = NULL\n");
-               return -EINVAL;
-       }
-        if (MSDOS_SB(sb)->cvf_format &&
-           MSDOS_SB(sb)->cvf_format->cvf_file_write)
-               return MSDOS_SB(sb)->cvf_format
-                       ->cvf_file_write(filp,buf,count,ppos);
-
-       /* S_ISLNK allows for UMSDOS. Should never happen for normal MSDOS */
-       if (!S_ISREG(inode->i_mode) && !S_ISLNK(inode->i_mode)) {
-               printk("fat_file_write: mode = %07o\n",inode->i_mode);
-               return -EINVAL;
-       }
-       /* system files may be immutable */
-       if (IS_IMMUTABLE(inode))
-               return -EPERM;
-/*
- * ok, append may not work when many processes are writing at the same time
- * but so what. That way leads to madness anyway.
- */
-       if (filp->f_flags & O_APPEND)
-               *ppos = inode->i_size;
-       if (count == 0)
-               return 0;
-       if (*ppos + count > 0x7FFFFFFFLL) {
-               count = 0x7FFFFFFFLL-*ppos;
-               if (!count)
-                       return -EFBIG;
+       int retval;
+
+       retval = generic_file_write(filp, buf, count, ppos,
+                                       fat_write_partial_page);
+       if (retval > 0) {
+               inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+               MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
+               mark_inode_dirty(inode);
        }
-
-       error = carry = 0;
-       for (start = buf; count || carry; count -= size) {
-               while (!(sector = fat_smap(inode,*ppos >> SECTOR_BITS)))
-                       if ((error = fat_add_cluster(inode)) < 0) break;
-               if (error) {
-                       fat_truncate(inode);
-                       break;
-               }
-               offset = *ppos & (SECTOR_SIZE-1);
-               size = MIN(SECTOR_SIZE-offset,MAX(carry,count));
-               if (binary_mode
-                       && offset == 0
-                       && (size == SECTOR_SIZE
-                               || *ppos + size >= inode->i_size)){
-                       /* No need to read the block first since we will */
-                       /* completely overwrite it */
-                       /* or at least write past the end of file */
-                       if (!(bh = fat_getblk(sb,sector))){
-                               error = -EIO;
-                               break;
-                       }
-               } else if (!(bh = fat_bread(sb,sector))) {
-                       error = -EIO;
-                       break;
-               }
-               if (binary_mode) {
-                       copy_from_user(bh->b_data+offset,buf,written = size);
-                       buf += size;
-               } else {
-                       written = left = SECTOR_SIZE-offset;
-                       to = (char *) bh->b_data+(*ppos & (SECTOR_SIZE-1));
-                       if (carry) {
-                               *to++ = '\n';
-                               left--;
-                               carry = 0;
-                       }
-                       for (size = 0; size < count && left; size++) {
-                               get_user(ch, buf++);
-                               if (ch == '\n') {
-                                       *to++ = '\r';
-                                       left--;
-                               }
-                               if (!left) carry = 1;
-                               else {
-                                       *to++ = ch;
-                                       left--;
-                               }
-                       }
-                       written -= left;
-               }
-               update_vm_cache(inode, *ppos, bh->b_data + (*ppos & (SECTOR_SIZE-1)), written);
-               *ppos += written;
-               if (*ppos > inode->i_size) {
-                       inode->i_size = *ppos;
-                       mark_inode_dirty(inode);
-               }
-               fat_set_uptodate(sb, bh, 1);
-               fat_mark_buffer_dirty(sb, bh, 0);
-               fat_brelse(sb, bh);
-       }
-       if (start == buf)
-               return error;
-       inode->i_mtime = inode->i_ctime = CURRENT_TIME;
-       MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
-       mark_inode_dirty(inode);
-       return buf-start;
+       return retval;
 }
 
 void fat_truncate(struct inode *inode)
@@ -460,14 +185,14 @@ void fat_truncate(struct inode *inode)
        int cluster;
 
        /* Why no return value?  Surely the disk could fail... */
+       if (IS_RDONLY (inode))
+               return /* -EPERM */;
        if (IS_IMMUTABLE(inode))
                return /* -EPERM */;
-       if(inode->i_sb->s_flags&MS_RDONLY) {
-               printk("FAT: fat_truncate called though fs is read-only, uhh...\n");
-               return /* -EROFS */;
-       }
        cluster = SECTOR_SIZE*MSDOS_SB(inode->i_sb)->cluster_size;
+       MSDOS_I(inode)->i_realsize = ((inode->i_size-1) | (SECTOR_SIZE-1)) + 1;
        (void) fat_free(inode,(inode->i_size+(cluster-1))/cluster);
        MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
+       inode->i_ctime = inode->i_mtime = CURRENT_TIME;
        mark_inode_dirty(inode);
 }
index b55bfd712ed2fca5e3fb1c3484d6289831e35232..e7485d5d9872ad46ff42edac4501addca5d38d11 100644 (file)
@@ -33,6 +33,8 @@
 #include <asm/uaccess.h>
 #include <asm/unaligned.h>
 
+extern struct cvf_format default_cvf, bigblock_cvf;
+
 /* #define FAT_PARANOIA 1 */
 #define DEBUG_LEVEL 0
 #ifdef FAT_DEBUG
@@ -166,7 +168,7 @@ void fat_clear_inode(struct inode *inode)
 
 void fat_put_super(struct super_block *sb)
 {
-       if (MSDOS_SB(sb)->cvf_format) {
+       if (MSDOS_SB(sb)->cvf_format->cvf_version) {
                dec_cvf_format_use_count_by_version(MSDOS_SB(sb)->cvf_format->cvf_version);
                MSDOS_SB(sb)->cvf_format->unmount_cvf(sb);
        }
@@ -364,7 +366,6 @@ static void fat_read_root(struct inode *inode)
        struct super_block *sb = inode->i_sb;
        int nr;
 
-       MSDOS_I(inode)->i_binary = 1;
        INIT_LIST_HEAD(&MSDOS_I(inode)->i_fat_hash);
        MSDOS_I(inode)->i_location = 0;
        MSDOS_I(inode)->i_fat_inode = inode;
@@ -394,6 +395,7 @@ static void fat_read_root(struct inode *inode)
        inode->i_blocks = (inode->i_size+inode->i_blksize-1)/
                    inode->i_blksize*MSDOS_SB(sb)->cluster_size;
        MSDOS_I(inode)->i_logstart = 0;
+       MSDOS_I(inode)->i_realsize = inode->i_size;
 
        MSDOS_I(inode)->i_attrs = 0;
        inode->i_mtime = inode->i_atime = inode->i_ctime = 0;
@@ -477,10 +479,10 @@ fat_read_super(struct super_block *sb, void *data, int silent,
            sb->s_blocksize = 1024;
            set_blocksize(sb->s_dev, 1024);
          }
-       bh = fat_bread(sb, 0);
+       bh = bread(sb->s_dev, 0, sb->s_blocksize);
        unlock_super(sb);
-       if (bh == NULL || !fat_is_uptodate(sb,bh)) {
-               fat_brelse (sb, bh);
+       if (bh == NULL || !buffer_uptodate(bh)) {
+               brelse (bh);
                goto out_no_bread;
        }
 
@@ -572,7 +574,7 @@ fat_read_super(struct super_block *sb, void *data, int silent,
                    MSDOS_MAX_EXTRA || (logical_sector_size & (SECTOR_SIZE-1))
                    || !b->secs_track || !b->heads;
        }
-       fat_brelse(sb, bh);
+       brelse(bh);
        set_blocksize(sb->s_dev, blksize);
        /*
                This must be done after the brelse because the bh is a dummy
@@ -589,6 +591,10 @@ fat_read_super(struct super_block *sb, void *data, int silent,
                i = detect_cvf(sb,cvf_format);
        if (i >= 0)
                error = cvf_formats[i]->mount_cvf(sb,cvf_options);
+       else if (sb->s_blocksize == 512)
+               MSDOS_SB(sb)->cvf_format = &default_cvf;
+       else
+               MSDOS_SB(sb)->cvf_format = &bigblock_cvf;
        if (error || debug) {
                /* The MSDOS_CAN_BMAP is obsolete, but left just to remember */
                printk("[MS-DOS FS Rel. 12,FAT %d,check=%c,conv=%c,"
@@ -717,25 +723,6 @@ int fat_statfs(struct super_block *sb,struct statfs *buf, int bufsiz)
        return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
 }
 
-
-int fat_bmap(struct inode *inode,int block)
-{
-       struct msdos_sb_info *sb;
-       int cluster,offset;
-
-       sb = MSDOS_SB(inode->i_sb);
-       if (sb->cvf_format &&
-           sb->cvf_format->cvf_bmap)
-               return sb->cvf_format->cvf_bmap(inode,block);
-       if ((inode->i_ino == MSDOS_ROOT_INO) && (sb->fat_bits != 32)) {
-               return sb->dir_start + block;
-       }
-       cluster = block/sb->cluster_size;
-       offset = block % sb->cluster_size;
-       if (!(cluster = fat_get_cluster(inode,cluster))) return 0;
-       return (cluster-2)*sb->cluster_size+sb->data_start+offset;
-}
-
 static int is_exec(char *extension)
 {
        char *exe_extensions = "EXECOMBAT", *walk;
@@ -752,7 +739,6 @@ static void fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de)
        struct super_block *sb = inode->i_sb;
        int nr;
 
-       MSDOS_I(inode)->i_binary = 1;
        INIT_LIST_HEAD(&MSDOS_I(inode)->i_fat_hash);
        MSDOS_I(inode)->i_location = 0;
        MSDOS_I(inode)->i_fat_inode = inode;
@@ -789,6 +775,7 @@ static void fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de)
                                        break;
                                }
                        }
+               MSDOS_I(inode)->i_realsize = inode->i_size;
        } else { /* not a directory */
                inode->i_mode = MSDOS_MKMODE(de->attr,
                    ((IS_NOEXEC(inode) || 
@@ -796,14 +783,7 @@ static void fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de)
                       !is_exec(de->ext)))
                        ? S_IRUGO|S_IWUGO : S_IRWXUGO)
                    & ~MSDOS_SB(sb)->options.fs_umask) | S_IFREG;
-               if (MSDOS_SB(sb)->cvf_format)
-                       inode->i_op = (MSDOS_SB(sb)->cvf_format->flags & CVF_USE_READPAGE)
-                               ? &fat_file_inode_operations_readpage
-                               : &fat_file_inode_operations_1024;
-               else
-                 inode->i_op = (sb->s_blocksize == 1024 || sb->s_blocksize == 2048)
-                       ? &fat_file_inode_operations_1024
-                       : &fat_file_inode_operations;
+               inode->i_op = &fat_file_inode_operations;
                MSDOS_I(inode)->i_start = CF_LE_W(de->start);
                if (MSDOS_SB(sb)->fat_bits == 32) {
                        MSDOS_I(inode)->i_start |=
@@ -812,12 +792,11 @@ static void fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de)
                MSDOS_I(inode)->i_logstart = MSDOS_I(inode)->i_start;
                inode->i_nlink = 1;
                inode->i_size = CF_LE_L(de->size);
+               MSDOS_I(inode)->i_realsize = ((inode->i_size-1)|(SECTOR_SIZE-1))+1;
        }
        if(de->attr & ATTR_SYS)
                if (MSDOS_SB(sb)->options.sys_immutable)
                        inode->i_flags |= S_IMMUTABLE;
-       MSDOS_I(inode)->i_binary =
-           fat_is_binary(MSDOS_SB(sb)->options.conversion, de->ext);
        MSDOS_I(inode)->i_attrs = de->attr & ATTR_UNUSED;
        /* this is as close to the truth as we can get ... */
        inode->i_blksize = MSDOS_SB(sb)->cluster_size*SECTOR_SIZE;
index 4cd218d589c90c7d69dacf2916e73183fc4f261b..f8fa5da3b7a65f976712637ccdbc797e16d7f49a 100644 (file)
@@ -144,7 +144,70 @@ void fat_clusters_flush(struct super_block *sb)
  * represented by inode. The cluster is zero-initialized.
  */
 
-struct buffer_head *fat_add_cluster1(struct inode *inode)
+/* not a directory */
+
+int fat_add_cluster(struct inode *inode)
+{
+       struct super_block *sb = inode->i_sb;
+       int count,nr,limit,last,curr,file_cluster;
+       int res = -ENOSPC;
+       int cluster_size = MSDOS_SB(sb)->cluster_size;
+
+       if (!MSDOS_SB(sb)->free_clusters) return res;
+       lock_fat(sb);
+       limit = MSDOS_SB(sb)->clusters;
+       nr = limit; /* to keep GCC happy */
+       for (count = 0; count < limit; count++) {
+               nr = ((count+MSDOS_SB(sb)->prev_free) % limit)+2;
+               if (fat_access(sb,nr,-1) == 0) break;
+       }
+       MSDOS_SB(sb)->prev_free = (count+MSDOS_SB(sb)->prev_free+1) % limit;
+       if (count >= limit) {
+               MSDOS_SB(sb)->free_clusters = 0;
+               unlock_fat(sb);
+               return res;
+       }
+       fat_access(sb,nr,EOF_FAT(sb));
+       if (MSDOS_SB(sb)->free_clusters != -1)
+               MSDOS_SB(sb)->free_clusters--;
+       if (MSDOS_SB(sb)->fat_bits == 32)
+               fat_clusters_flush(sb);
+       unlock_fat(sb);
+       last = 0;
+       /* We must locate the last cluster of the file to add this
+          new one (nr) to the end of the link list (the FAT).
+          
+          Here file_cluster will be the number of the last cluster of the
+          file (before we add nr).
+          
+          last is the corresponding cluster number on the disk. We will
+          use last to plug the nr cluster. We will use file_cluster to
+          update the cache.
+       */
+       file_cluster = 0;
+       if ((curr = MSDOS_I(inode)->i_start) != 0) {
+               fat_cache_lookup(inode,INT_MAX,&last,&curr);
+               file_cluster = last;
+               while (curr && curr != -1){
+                       file_cluster++;
+                       if (!(curr = fat_access(sb, last = curr,-1))) {
+                               fat_fs_panic(sb,"File without EOF");
+                               return res;
+                       }
+               }
+       }
+       if (last) fat_access(sb,last,nr);
+       else {
+               MSDOS_I(inode)->i_start = nr;
+               MSDOS_I(inode)->i_logstart = nr;
+               mark_inode_dirty(inode);
+       }
+       fat_cache_add(inode,file_cluster,nr);
+       inode->i_blocks += cluster_size;
+       return 0;
+}
+
+struct buffer_head *fat_extend_dir(struct inode *inode)
 {
        struct super_block *sb = inode->i_sb;
        int count,nr,limit,last,curr,sector,last_sector,file_cluster;
@@ -248,30 +311,17 @@ if (last) printk("next set to %d\n",fat_access(sb,last,-1));
                fat_cache_add(inode,file_cluster,nr);
        }
        inode->i_blocks += cluster_size;
-       if (S_ISDIR(inode->i_mode)) {
-               if (inode->i_size & (SECTOR_SIZE-1)) {
-                       fat_fs_panic(sb,"Odd directory size");
-                       inode->i_size = (inode->i_size+SECTOR_SIZE) &
-                           ~(SECTOR_SIZE-1);
-               }
-               inode->i_size += SECTOR_SIZE*cluster_size;
-#ifdef DEBUG
-printk("size is %d now (%x)\n",inode->i_size,inode);
-#endif
-               mark_inode_dirty(inode);
+       if (inode->i_size & (SECTOR_SIZE-1)) {
+               fat_fs_panic(sb,"Odd directory size");
+               inode->i_size = (inode->i_size+SECTOR_SIZE) &
+                   ~(SECTOR_SIZE-1);
        }
+       inode->i_size += SECTOR_SIZE*cluster_size;
+       MSDOS_I(inode)->i_realsize += SECTOR_SIZE*cluster_size;
+       mark_inode_dirty(inode);
        return res;
 }
 
-int fat_add_cluster(struct inode *inode)
-{
-       struct buffer_head *bh = fat_add_cluster1(inode);
-       if (!bh)
-               return -ENOSPC;
-       fat_brelse(inode->i_sb, bh);
-       return 0;
-}
-
 /* Linear day numbers of the respective 1sts in non-leap years. */
 
 static int day_n[] = { 0,31,59,90,120,151,181,212,243,273,304,334,0,0,0,0 };
@@ -351,7 +401,7 @@ int fat__get_entry(struct inode *dir, loff_t *pos,struct buffer_head **bh,
                if (*bh)
                        fat_brelse(sb, *bh);
                *bh = NULL;
-               if ((sector = fat_smap(dir,offset >> SECTOR_BITS)) == -1)
+               if ((sector = fat_bmap(dir,offset >> SECTOR_BITS)) == -1)
                        return -1;
                PRINTK (("get_entry sector %d %p\n",sector,*bh));
                PRINTK (("get_entry sector apres brelse\n"));
index 8c396f3e63a0c5ee0b513d4e6599788c7f2fa6a0..060d5b26c5505ed4829f50cc65002c9b35a803de 100644 (file)
@@ -16,6 +16,8 @@
 #include <linux/stat.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
+#include <linux/locks.h>
+#include <linux/quotaops.h>
 
 #include <asm/bitops.h>
 
@@ -51,8 +53,9 @@ static unsigned long count_free(struct buffer_head *map[], unsigned numblocks, _
        return(sum);
 }
 
-void minix_free_block(struct super_block * sb, int block)
+void minix_free_block(struct inode * inode, int block)
 {
+       struct super_block * sb = inode->i_sb;
        struct buffer_head * bh;
        unsigned int bit,zone;
 
@@ -80,12 +83,15 @@ void minix_free_block(struct super_block * sb, int block)
        if (!minix_clear_bit(bit,bh->b_data))
                printk("free_block (%s:%d): bit already cleared\n",
                       kdevname(sb->s_dev), block);
+       else
+               DQUOT_FREE_BLOCK(sb, inode, 1);
        mark_buffer_dirty(bh, 1);
        return;
 }
 
-int minix_new_block(struct super_block * sb)
+int minix_new_block(struct inode * inode)
 {
+       struct super_block * sb = inode->i_sb;
        struct buffer_head * bh;
        int i,j;
 
@@ -94,6 +100,9 @@ int minix_new_block(struct super_block * sb)
                return 0;
        }
 repeat:
+       if(DQUOT_ALLOC_BLOCK(sb, inode, 1))
+               return -EDQUOT;
+
        j = 8192;
        bh = NULL;
        for (i = 0; i < sb->u.minix_sb.s_zmap_blocks; i++) {
@@ -105,6 +114,7 @@ repeat:
                return 0;
        if (minix_set_bit(j,bh->b_data)) {
                printk("new_block: bit already set");
+               DQUOT_FREE_BLOCK(sb, inode, 1);
                goto repeat;
        }
        mark_buffer_dirty(bh, 1);
@@ -222,6 +232,10 @@ void minix_free_inode(struct inode * inode)
                printk("free_inode: nonexistent imap in superblock\n");
                return;
        }
+
+       DQUOT_FREE_INODE(inode->i_sb, inode);
+       DQUOT_DROP(inode);
+
        bh = inode->i_sb->u.minix_sb.s_imap[ino >> 13];
        minix_clear_inode(inode);
        clear_inode(inode);
@@ -230,7 +244,7 @@ void minix_free_inode(struct inode * inode)
        mark_buffer_dirty(bh, 1);
 }
 
-struct inode * minix_new_inode(const struct inode * dir)
+struct inode * minix_new_inode(const struct inode * dir, int * error)
 {
        struct super_block * sb;
        struct inode * inode;
@@ -274,6 +288,20 @@ struct inode * minix_new_inode(const struct inode * dir)
        inode->i_blocks = inode->i_blksize = 0;
        insert_inode_hash(inode);
        mark_inode_dirty(inode);
+
+       unlock_super(sb);
+printk("m_n_i: allocated inode ");
+       if(DQUOT_ALLOC_INODE(sb, inode)) {
+printk("fails quota test\n");
+               sb->dq_op->drop(inode);
+               inode->i_nlink = 0;
+               iput(inode);
+               *error = -EDQUOT;
+               return NULL;
+       }
+printk("is within quota\n");
+
+       *error = 0;
        return inode;
 }
 
index ae5aa8a5a78e099d98e35fe0ab52f62aa6b6d762..b268a467650df2524cee75912426c0bd628bd441 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/stat.h>
 #include <linux/fcntl.h>
 #include <linux/errno.h>
+#include <linux/quotaops.h>
 
 #include <asm/uaccess.h>
 
@@ -212,7 +213,9 @@ int minix_create(struct inode * dir, struct dentry *dentry, int mode)
        struct buffer_head * bh;
        struct minix_dir_entry * de;
 
-       inode = minix_new_inode(dir);
+       inode = minix_new_inode(dir, &error);
+       if (error)
+               return error;
        if (!inode)
                return -ENOSPC;
        inode->i_op = &minix_file_inode_operations;
@@ -240,7 +243,9 @@ int minix_mknod(struct inode * dir, struct dentry *dentry, int mode, int rdev)
        struct buffer_head * bh;
        struct minix_dir_entry * de;
 
-       inode = minix_new_inode(dir);
+       inode = minix_new_inode(dir, &error);
+       if (error)
+               return error;
        if (!inode)
                return -ENOSPC;
        inode->i_uid = current->fsuid;
@@ -271,7 +276,9 @@ int minix_mkdir(struct inode * dir, struct dentry *dentry, int mode)
        info = &dir->i_sb->u.minix_sb;
        if (dir->i_nlink >= info->s_link_max)
                return -EMLINK;
-       inode = minix_new_inode(dir);
+       inode = minix_new_inode(dir, &error);
+       if (error)
+               return error;
        if (!inode)
                return -ENOSPC;
        inode->i_op = &minix_dir_inode_operations;
@@ -383,6 +390,7 @@ int minix_rmdir(struct inode * dir, struct dentry *dentry)
        if (!bh)
                goto end_rmdir;
        inode = dentry->d_inode;
+       DQUOT_INIT(inode);
 
        if (!empty_dir(inode)) {
                retval = -ENOTEMPTY;
@@ -422,6 +430,7 @@ int minix_unlink(struct inode * dir, struct dentry *dentry)
 
        retval = -ENOENT;
        inode = dentry->d_inode;
+       DQUOT_INIT(inode);
        bh = minix_find_entry(dir, dentry->d_name.name,
                              dentry->d_name.len, &de);
        if (!bh || de->inode != inode->i_ino)
@@ -456,7 +465,10 @@ int minix_symlink(struct inode * dir, struct dentry *dentry,
        int i;
        char c;
 
-       if (!(inode = minix_new_inode(dir)))
+       inode = minix_new_inode(dir, &i);
+       if (i)
+               return i;
+       if (!inode)
                return -ENOSPC;
 
        inode->i_mode = S_IFLNK | 0777;
@@ -554,6 +566,8 @@ int minix_rename(struct inode * old_dir, struct dentry *old_dentry,
                if (!new_inode) {
                        brelse(new_bh);
                        new_bh = NULL;
+               } else {
+                       DQUOT_INIT(new_inode);
                }
        }
        if (S_ISDIR(old_inode->i_mode)) {
index 6724d0064681aa6ffccb8e8819c8cb6a2952afb5..10457105b99164723f52875ed3ddd5f2431bb0f1 100644 (file)
@@ -66,7 +66,7 @@ repeat:
                        mark_buffer_clean(bh);
                        brelse(bh);
                }
-               minix_free_block(inode->i_sb,tmp);
+               minix_free_block(inode,tmp);
        }
        return retry;
 }
@@ -114,7 +114,7 @@ repeat:
                *ind = 0;
                mark_buffer_dirty(ind_bh, 1);
                brelse(bh);
-               minix_free_block(inode->i_sb,tmp);
+               minix_free_block(inode,tmp);
        }
        ind = (unsigned short *) ind_bh->b_data;
        for (i = 0; i < 512; i++)
@@ -126,7 +126,7 @@ repeat:
                else {
                        tmp = *p;
                        *p = 0;
-                       minix_free_block(inode->i_sb,tmp);
+                       minix_free_block(inode,tmp);
                }
        }
        brelse(ind_bh);
@@ -172,7 +172,7 @@ repeat:
                        tmp = *p;
                        *p = 0;
                        mark_inode_dirty(inode);
-                       minix_free_block(inode->i_sb,tmp);
+                       minix_free_block(inode,tmp);
                }
        }
        brelse(dind_bh);
@@ -230,7 +230,7 @@ repeat:
                        mark_buffer_clean(bh);
                        brelse(bh);
                }
-               minix_free_block(inode->i_sb,tmp);
+               minix_free_block(inode,tmp);
        }
        return retry;
 }
@@ -278,7 +278,7 @@ repeat:
                *ind = 0;
                mark_buffer_dirty(ind_bh, 1);
                brelse(bh);
-               minix_free_block(inode->i_sb,tmp);
+               minix_free_block(inode,tmp);
        }
        ind = (unsigned long *) ind_bh->b_data;
        for (i = 0; i < 256; i++)
@@ -290,7 +290,7 @@ repeat:
                else {
                        tmp = *p;
                        *p = 0;
-                       minix_free_block(inode->i_sb,tmp);
+                       minix_free_block(inode,tmp);
                }
        }
        brelse(ind_bh);
@@ -336,7 +336,7 @@ repeat:
                        tmp = *p;
                        *p = 0;
                        mark_inode_dirty(inode);
-                       minix_free_block(inode->i_sb,tmp);
+                       minix_free_block(inode,tmp);
                }
        }
        brelse(dind_bh);
@@ -382,7 +382,7 @@ repeat:
                         tmp = *p;
                         *p = 0;
                         mark_inode_dirty(inode);
-                        minix_free_block(inode->i_sb,tmp);
+                        minix_free_block(inode,tmp);
                }
        }
         brelse(tind_bh);
index fa5e4aed50779e38d548e5fe641622f1a19c67eb..7fbc9b4c186588f17a88c69d15d3ccbe13382a74 100644 (file)
@@ -385,41 +385,16 @@ int msdos_mkdir(struct inode *dir,struct dentry *dentry,int mode)
                fat_brelse(sb, bh);
                goto out_unlock;
        }
-       inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
-       mark_inode_dirty(inode);
        res = 0;
 
        dir->i_nlink++;
        inode->i_nlink = 2; /* no need to mark them dirty */
 
-       if (!(bh1 = fat_add_cluster1(inode))) {
-               res = -ENOSPC;
+       res = fat_new_dir(inode, dir, 0);
+       if (res)
                goto mkdir_error;
-       }
-       fat_brelse(sb, bh);
-       de1 = (struct msdos_dir_entry *)bh1->b_data;
-       inode->i_ctime = inode->i_mtime = CURRENT_TIME;
-       mark_inode_dirty(inode);
 
-       memcpy(de1->name,MSDOS_DOT,MSDOS_NAME);
-       de1->attr = ATTR_DIR;
-       de1->start = CT_LE_W(MSDOS_I(inode)->i_logstart);
-       de1->starthi = CT_LE_W(MSDOS_I(inode)->i_logstart >> 16);
-       fat_date_unix2dos(inode->i_mtime,&de1->time,&de1->date);
-       de1->size = 0;
-       de1->time = CT_LE_W(de1->time);
-       de1->date = CT_LE_W(de1->date);
-       de1++;
-       memcpy(de1->name,MSDOS_DOTDOT,MSDOS_NAME);
-       de1->attr = ATTR_DIR;
-       de1->start = CT_LE_W(MSDOS_I(dir)->i_logstart);
-       de1->starthi = CT_LE_W(MSDOS_I(dir)->i_logstart >> 16);
-       fat_date_unix2dos(dir->i_mtime,&de1->time,&de1->date);
-       de1->size = 0;
-       de1->time = CT_LE_W(de1->time);
-       de1->date = CT_LE_W(de1->date);
-       fat_mark_buffer_dirty(sb, bh1, 1);
-       fat_brelse(sb, bh1);
+       fat_brelse(sb, bh);
        d_instantiate(dentry, inode);
        res = 0;
 
index d90529f24e02dc45613f2a43d520593ac021573a..ee28862286f0d6e79860e60378002c34221eb9c2 100644 (file)
@@ -350,7 +350,7 @@ ncp_lookup_validate(struct dentry * dentry, int flags)
        struct ncpfs_inode_info finfo;
        __u8 __name[dentry->d_name.len + 1];
 
-       if (!dir)
+       if (!dentry->d_inode || !dir)
                return 0;
         
        server = NCP_SERVER(dir);
index 36f37c232b219a50304f821ea4979cdd1b4fef32..6f5746000acca5221c7354ba498e7c69e00b6821 100644 (file)
@@ -134,7 +134,15 @@ void ncp_update_inode2(struct inode* inode, struct nw_file_info *nwinfo)
        if ((inode->i_size)&&(inode->i_blksize)) {
                inode->i_blocks = (inode->i_size-1)/(inode->i_blksize)+1;
        }
+
        /* TODO: times? I'm not sure... */
+       inode->i_mtime = ncp_date_dos2unix(le16_to_cpu(nwinfo->i.modifyTime),
+                                          le16_to_cpu(nwinfo->i.modifyDate));
+       inode->i_ctime = ncp_date_dos2unix(le16_to_cpu(nwinfo->i.creationTime),
+                                          le16_to_cpu(nwinfo->i.creationDate));
+       inode->i_atime = ncp_date_dos2unix(0,
+                                          le16_to_cpu(nwinfo->i.lastAccessDate));
+
        NCP_FINFO(inode)->DosDirNum = nwinfo->i.DosDirNum;
        NCP_FINFO(inode)->dirEntNum = nwinfo->i.dirEntNum;
        NCP_FINFO(inode)->volNumber = nwinfo->i.volNumber;
index f4c8dfb531751fc6477d2048ad8922394d8080c5..8856feba768052e637f5e84c3448a3a8defc9108 100644 (file)
@@ -8,7 +8,7 @@
 # Note 2:  the CFLAGS definitions are now in the main makefile.
 O_TARGET := umsdos.o
 
-O_OBJS   := dir.o  file.o inode.o ioctl.o mangle.o namei.o \
+O_OBJS   := dir.o  inode.o ioctl.o mangle.o namei.o \
                rdir.o symlink.o emd.o check.o
 
 M_OBJS   := $(O_TARGET)
index e9860caae8d86463b05d86adc52ad48756303736..1eda3df939617d2225383738ed9dc2fa9316202c 100644 (file)
@@ -92,24 +92,7 @@ void check_inode (struct inode *inode)
                }
                
                printk (" (i_patched=%d)", inode->u.umsdos_i.i_patched);
-               
-               if (inode->i_op == NULL) {
-                       printk (" (i_op is NULL)\n");
-               } else if (inode->i_op == &umsdos_dir_inode_operations) {
-                       printk (" (i_op is umsdos_dir_inode_operations)\n");
-               } else if (inode->i_op == &umsdos_file_inode_operations) {
-                       printk (" (i_op is umsdos_file_inode_operations)\n");
-               } else if (inode->i_op == &umsdos_file_inode_operations_no_bmap) {
-                       printk (" (i_op is umsdos_file_inode_operations_no_bmap)\n");
-               } else if (inode->i_op == &umsdos_file_inode_operations_readpage) {
-                       printk (" (i_op is umsdos_file_inode_operations_readpage)\n");
-               } else if (inode->i_op == &umsdos_rdir_inode_operations) {
-                       printk (" (i_op is umsdos_rdir_inode_operations)\n");
-               } else if (inode->i_op == &umsdos_symlink_inode_operations) {
-                       printk (" (i_op is umsdos_symlink_inode_operations)\n");
-               } else {
-                       printk (" (i_op is UNKNOWN: %p)\n", inode->i_op);
-               }
+
        } else {
                printk (KERN_DEBUG "*   inode is NULL\n");
        }
index 34fe302d7c778cc846f1056a1d90067e5b58adcf..c09c293cf5911ca4723b7e3ad07942bc59a99275 100644 (file)
@@ -393,7 +393,6 @@ void umsdos_lookup_patch_new(struct dentry *dentry, struct umsdos_info *info)
        inode->i_uid = entry->uid;
        inode->i_gid = entry->gid;
 
-       MSDOS_I (inode)->i_binary = 1;
        /* #Specification: umsdos / i_nlink
         * The nlink field of an inode is maintained by the MSDOS file system
         * for directory and by UMSDOS for other files.  The logic is that
@@ -832,8 +831,8 @@ struct inode_operations umsdos_dir_inode_operations =
        UMSDOS_rename,          /* rename */
        NULL,                   /* readlink */
        NULL,                   /* followlink */
-       fat_bmap,               /* get_block */
-       block_read_full_page,   /* readpage */
+       NULL,                   /* get_block */
+       NULL,                   /* readpage */
        NULL,                   /* writepage */
        NULL,                   /* flushpage */
        NULL,                   /* truncate */
index d5a7a95788204464abb03503de58f452c2eeb24c..d9b00e8c96ee1b905721379a66b5a164815f0116 100644 (file)
@@ -34,7 +34,6 @@ ssize_t umsdos_file_read_kmem (       struct file *filp,
        mm_segment_t old_fs = get_fs ();
 
        set_fs (KERNEL_DS);
-       MSDOS_I (filp->f_dentry->d_inode)->i_binary = 2;
        ret = fat_file_read (filp, buf, count, &filp->f_pos);
        set_fs (old_fs);
        return ret;
@@ -54,15 +53,6 @@ ssize_t umsdos_file_write_kmem_real (struct file * filp,
        mm_segment_t old_fs = get_fs ();
        ssize_t ret;
 
-       /* note: i_binary=2 is for CVF-FAT. We put it here, instead of
-        * umsdos_file_write_kmem, since it is also wise not to compress
-        * symlinks (in the unlikely event that they are > 512 bytes and
-        * can be compressed.
-        * FIXME: should we set it when reading symlinks too?
-        */
-
-       MSDOS_I (filp->f_dentry->d_inode)->i_binary = 2;
-
        set_fs (KERNEL_DS);
        ret = fat_file_write (filp, buf, count, &filp->f_pos);
        set_fs (old_fs);
diff --git a/fs/umsdos/file.c b/fs/umsdos/file.c
deleted file mode 100644 (file)
index b930c46..0000000
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- *  linux/fs/umsdos/file.c
- *
- *  Written 1993 by Jacques Gelinas
- *      inspired from linux/fs/msdos/file.c Werner Almesberger
- *
- *  Extended MS-DOS regular file handling primitives
- */
-
-#include <linux/sched.h>
-#include <linux/fs.h>
-#include <linux/msdos_fs.h>
-#include <linux/errno.h>
-#include <linux/fcntl.h>
-#include <linux/stat.h>
-#include <linux/umsdos_fs.h>
-
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-/*
- * Read a file into user space memory
- */
-static ssize_t UMSDOS_file_read (
-                                       struct file *filp,
-                                       char *buf,
-                                       size_t count,
-                                       loff_t * ppos
-)
-{
-       struct dentry *dentry = filp->f_dentry;
-       struct inode *inode = dentry->d_inode;
-
-       int ret = fat_file_read (filp, buf, count, ppos);
-
-       /* We have to set the access time because msdos don't care */
-       if (!IS_RDONLY (inode)) {
-               inode->i_atime = CURRENT_TIME;
-               mark_inode_dirty(inode);
-       }
-       return ret;
-}
-
-
-/*
- * Write a file from user space memory
- */
-static ssize_t UMSDOS_file_write (
-                                        struct file *filp,
-                                        const char *buf,
-                                        size_t count,
-                                        loff_t * ppos)
-{
-       return fat_file_write (filp, buf, count, ppos);
-}
-
-
-/*
- * Truncate a file to 0 length.
- */
-static void UMSDOS_truncate (struct inode *inode)
-{
-       Printk (("UMSDOS_truncate\n"));
-       if (!IS_RDONLY (inode)) {
-               fat_truncate (inode);
-               inode->i_ctime = inode->i_mtime = CURRENT_TIME;
-               mark_inode_dirty(inode);
-       }
-}
-
-/* Function for normal file system (512 bytes hardware sector size) */
-struct file_operations umsdos_file_operations =
-{
-       NULL,                   /* lseek - default */
-       UMSDOS_file_read,       /* read */
-       UMSDOS_file_write,      /* write */
-       NULL,                   /* readdir - bad */
-       NULL,                   /* poll - default */
-       NULL,                   /* ioctl - default */
-       generic_file_mmap,      /* mmap */
-       NULL,                   /* no special open is needed */
-       NULL,                   /* flush */
-       NULL,                   /* release */
-       file_fsync              /* fsync */
-};
-
-struct inode_operations umsdos_file_inode_operations =
-{
-       &umsdos_file_operations,        /* default file operations */
-       NULL,                   /* create */
-       NULL,                   /* lookup */
-       NULL,                   /* link */
-       NULL,                   /* unlink */
-       NULL,                   /* symlink */
-       NULL,                   /* mkdir */
-       NULL,                   /* rmdir */
-       NULL,                   /* mknod */
-       NULL,                   /* rename */
-       NULL,                   /* readlink */
-       NULL,                   /* follow_link */
-       fat_bmap,               /* get_block */
-       block_read_full_page,   /* readpage */
-       NULL,                   /* writepage */
-       NULL,                   /* flushpage */
-       UMSDOS_truncate,        /* truncate */
-       NULL,                   /* permission */
-       fat_smap,               /* smap */
-       NULL                    /* revalidate */
-};
-
-/* For other with larger and unaligned file system */
-struct file_operations umsdos_file_operations_no_bmap =
-{
-       NULL,                   /* lseek - default */
-       UMSDOS_file_read,       /* read */
-       UMSDOS_file_write,      /* write */
-       NULL,                   /* readdir - bad */
-       NULL,                   /* poll - default */
-       NULL,                   /* ioctl - default */
-       fat_mmap,               /* mmap */
-       NULL,                   /* no special open is needed */
-       NULL,                   /* flush */
-       NULL,                   /* release */
-       file_fsync              /* fsync */
-};
-
-struct inode_operations umsdos_file_inode_operations_no_bmap =
-{
-       &umsdos_file_operations_no_bmap,        /* default file operations */
-       NULL,                   /* create */
-       NULL,                   /* lookup */
-       NULL,                   /* link */
-       NULL,                   /* unlink */
-       NULL,                   /* symlink */
-       NULL,                   /* mkdir */
-       NULL,                   /* rmdir */
-       NULL,                   /* mknod */
-       NULL,                   /* rename */
-       NULL,                   /* readlink */
-       NULL,                   /* follow link */
-       NULL,                   /* get_block */
-       NULL,                   /* readpage */
-       NULL,                   /* writepage */
-       NULL,                   /* flushpage */
-       UMSDOS_truncate,        /* truncate */
-       NULL,                   /* permission */
-       NULL,                   /* smap */
-       NULL                    /* revalidate */
-};
-
-/* For other with larger and unaligned file system with readpage */
-struct file_operations umsdos_file_operations_readpage =
-{
-       NULL,                   /* lseek - default */
-       UMSDOS_file_read,       /* read */
-       UMSDOS_file_write,      /* write */
-       NULL,                   /* readdir - bad */
-       NULL,                   /* poll - default */
-       NULL,                   /* ioctl - default */
-       generic_file_mmap,      /* mmap */
-       NULL,                   /* no special open is needed */
-       NULL,                   /* flush */
-       NULL,                   /* release */
-       file_fsync              /* fsync */
-};
-
-struct inode_operations umsdos_file_inode_operations_readpage =
-{
-       &umsdos_file_operations_readpage,       /* default file operations */
-       NULL,                   /* create */
-       NULL,                   /* lookup */
-       NULL,                   /* link */
-       NULL,                   /* unlink */
-       NULL,                   /* symlink */
-       NULL,                   /* mkdir */
-       NULL,                   /* rmdir */
-       NULL,                   /* mknod */
-       NULL,                   /* rename */
-       NULL,                   /* readlink */
-       NULL,                   /* follow link */
-       NULL,                   /* get_block */
-       fat_readpage,           /* readpage */
-       NULL,                   /* writepage */
-       NULL,                   /* flushpage */
-       UMSDOS_truncate,        /* truncate */
-       NULL,                   /* permission */
-       NULL,                   /* smap */
-       NULL                    /* revalidate */
-};
index 81806ca18950d1eaebfb2e8bf4b878dc06839a82..5a22a9f021c4aa8b1cacd9a61ad51001e61b96ba 100644 (file)
@@ -42,7 +42,7 @@ void fill_new_filp (struct file *filp, struct dentry *dentry)
        filp->f_reada = 1;
        filp->f_flags = O_RDWR;
        filp->f_dentry = dentry;
-       filp->f_op = &umsdos_file_operations;
+       filp->f_op = dentry->d_inode->i_op->default_file_ops;
 }
 
 
@@ -146,19 +146,7 @@ dentry, f_pos));
        umsdos_set_dirinfo_new(dentry, f_pos);
 
        if (S_ISREG (inode->i_mode)) {
-               if (MSDOS_SB (inode->i_sb)->cvf_format) {
-                       if (MSDOS_SB (inode->i_sb)->cvf_format->flags & CVF_USE_READPAGE) {
-                               inode->i_op = &umsdos_file_inode_operations_readpage;
-                       } else {
-                               inode->i_op = &umsdos_file_inode_operations_no_bmap;
-                       }
-               } else {
-                       if (inode->i_op->bmap != NULL) {
-                               inode->i_op = &umsdos_file_inode_operations;
-                       } else {
-                               inode->i_op = &umsdos_file_inode_operations_no_bmap;
-                       }
-               }
+               /* All set */
        } else if (S_ISDIR (inode->i_mode)) {
                umsdos_setup_dir(dentry);
        } else if (S_ISLNK (inode->i_mode)) {
index 2d08a35d81d9a669e0bee88ba75174befc8f5794..8f94230e3519a6077bdf9b587d400b5532b1232b 100644 (file)
@@ -135,7 +135,7 @@ struct inode_operations umsdos_symlink_inode_operations =
        NULL,                   /* rename */
        UMSDOS_readlink,        /* readlink */
        UMSDOS_followlink,      /* followlink */
-       fat_bmap,               /* get_block */
+       fat_get_block,          /* get_block */
        block_read_full_page,   /* readpage */
        NULL,                   /* writepage */
        NULL,                   /* flushpage */
index ad241c3cd4c30a8b21d1132a0a9852b1013fe8f1..0f23487ba3d3423decf58ccc855ddbb8d0d8bf0b 100644 (file)
@@ -982,35 +982,6 @@ int vfat_create(struct inode *dir,struct dentry* dentry,int mode)
        return 0;
 }
 
-static int vfat_create_dotdirs(struct inode *dir, struct inode *parent)
-{
-       struct super_block *sb = dir->i_sb;
-       struct buffer_head *bh;
-       struct msdos_dir_entry *de;
-       __u16 date, time;
-
-       if ((bh = fat_add_cluster1(dir)) == NULL) return -ENOSPC;
-       /* zeroed out, so... */
-       fat_date_unix2dos(dir->i_mtime,&time,&date);
-       de = (struct msdos_dir_entry*)&bh->b_data[0];
-       memcpy(de[0].name,MSDOS_DOT,MSDOS_NAME);
-       memcpy(de[1].name,MSDOS_DOTDOT,MSDOS_NAME);
-       de[0].attr = de[1].attr = ATTR_DIR;
-       de[0].ctime = de[0].time = de[1].ctime = de[1].time = CT_LE_W(time);
-       de[0].adate = de[0].cdate = de[0].date = de[1].adate =
-               de[1].cdate = de[1].date = CT_LE_W(date);
-       de[0].start = CT_LE_W(MSDOS_I(dir)->i_logstart);
-       de[0].starthi = CT_LE_W(MSDOS_I(dir)->i_logstart>>16);
-       de[1].start = CT_LE_W(MSDOS_I(parent)->i_logstart);
-       de[1].starthi = CT_LE_W(MSDOS_I(parent)->i_logstart>>16);
-       fat_mark_buffer_dirty(sb, bh, 1);
-       fat_brelse(sb, bh);
-       dir->i_atime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
-       mark_inode_dirty(dir);
-
-       return 0;
-}
-
 static void vfat_remove_entry(struct inode *dir,struct vfat_slot_info *sinfo,
      struct buffer_head *bh, struct msdos_dir_entry *de)
 {
@@ -1110,8 +1081,7 @@ int vfat_mkdir(struct inode *dir,struct dentry* dentry,int mode)
        dir->i_version = event;
        dir->i_nlink++;
        inode->i_nlink = 2; /* no need to mark them dirty */
-
-       res = vfat_create_dotdirs(inode, dir);
+       res = fat_new_dir(inode, dir, 1);
        if (res < 0)
                goto mkdir_failed;
        dentry->d_time = dentry->d_parent->d_inode->i_version;
index b3a873938378003eae16e47f92066c9165787688..9e009ce181d0ffe867a422fb00d84f7edaf14953 100644 (file)
 
 #define        SMP_CACHE_BYTES L1_CACHE_BYTES
 
+#ifdef MODULE
+#define __cacheline_aligned __attribute__((__aligned__(L1_CACHE_BYTES)))
+#else
+#define __cacheline_aligned                                    \
+  __attribute__((__aligned__(L1_CACHE_BYTES),                  \
+                __section__(".data.cacheline_aligned")))
+#endif
+
 #endif
index acae65fc6aa53bcac3f3922ac809bc936af7ec23..6e8e0d4ac9307a1f07e24c9cbd61991991f1a35d 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef __M68K_HARDIRQ_H
 #define __M68K_HARDIRQ_H
 
-#include <linux/tasks.h>
+#include <linux/threads.h>
 
 extern unsigned int local_irq_count[NR_CPUS];
 
index 169fa381cdc5e62513665d21670346df53791f3b..1614ecd0bc0567f86733c53d24b502a49f0f9c72 100644 (file)
@@ -70,6 +70,9 @@ static __inline__ int irq_cannonicalize(int irq)
 extern void (*enable_irq)(unsigned int);
 extern void (*disable_irq)(unsigned int);
 
+#define disable_irq_nosync     disable_irq
+#define enable_irq_nosync      enable_irq
+
 extern int sys_request_irq(unsigned int, 
        void (*)(int, void *, struct pt_regs *), 
        unsigned long, const char *, void *);
index 4850dd40415ea03eb29ddfe67c8c3c52f09f5a89..f857551171b359a1f64f18dcaff5483367e3f413 100644 (file)
@@ -1,13 +1,93 @@
-#ifndef __68K_MMU_CONTEXT_H
-#define __68K_MMU_CONTEXT_H
+#ifndef __M68K_MMU_CONTEXT_H
+#define __M68K_MMU_CONTEXT_H
 
-/*
- * get a new mmu context.. do we need this on the m68k?
- */
-#define get_mmu_context(x) do { } while (0)
+#include <asm/setup.h>
+#include <asm/page.h>
 
-#define init_new_context(mm)   do { } while(0)
-#define destroy_context(mm)    do { } while(0)
-#define activate_context(tsk)  do { } while(0)
+extern inline void
+init_new_context(struct task_struct *tsk, struct mm_struct *mm)
+{
+       mm->context = virt_to_phys(mm->pgd);
+}
+
+#define destroy_context(mm)            do { } while(0)
+
+extern inline void switch_mm_0230(struct mm_struct *mm)
+{
+       unsigned long crp[2] = {
+               0x80000000 | _PAGE_TABLE, mm->context
+       };
+       unsigned long tmp;
+
+       asm volatile (".chip 68030");
+
+       /* flush MC68030/MC68020 caches (they are virtually addressed) */
+       asm volatile (
+               "movec %%cacr,%0;"
+               "orw %1,%0; "
+               "movec %0,%%cacr"
+               : "=d" (tmp) : "di" (FLUSH_I_AND_D));
+
+       /* Switch the root pointer. For a 030-only kernel,
+        * avoid flushing the whole ATC, we only need to
+        * flush the user entries. The 68851 does this by
+        * itself. Avoid a runtime check here.
+        */
+       asm volatile (
+#ifdef CPU_M68030_ONLY
+               "pmovefd %0,%%crp; "
+               "pflush #0,#4"
+#else
+               "pmove %0,%%crp"
+#endif
+               : : "m" (crp[0]));
+
+       asm volatile (".chip 68k");
+}
+
+extern inline void switch_mm_0460(struct mm_struct *mm)
+{
+       asm volatile (".chip 68040");
+
+       /* flush address translation cache (user entries) */
+       asm volatile ("pflushan");
+
+       /* switch the root pointer */
+       asm volatile ("movec %0,%%urp" : : "r" (mm->context));
+
+       if (CPU_IS_060) {
+               unsigned long tmp;
+
+               /* clear user entries in the branch cache */
+               asm volatile (
+                       "movec %%cacr,%0; "
+                       "orl %1,%0; "
+                       "movec %0,%%cacr"
+                       : "=d" (tmp): "di" (0x00200000));
+       }
+
+       asm volatile (".chip 68k");
+}
+
+static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk, unsigned cpu)
+{
+       if (prev != next) {
+               if (CPU_IS_020_OR_030)
+                       switch_mm_0230(next);
+               else
+                       switch_mm_0460(next);
+       }
+}
+
+extern inline void activate_mm(struct mm_struct *prev_mm,
+                              struct mm_struct *next_mm)
+{
+       next_mm->context = virt_to_phys(next_mm->pgd);
+
+       if (CPU_IS_020_OR_030)
+               switch_mm_0230(next_mm);
+       else
+               switch_mm_0460(next_mm);
+}
 
 #endif
index 8cc546aac4fe7c140ed98264ad72949ed24d3e7d..8d2372ce0fb366f0170de430daea3f1af289e762 100644 (file)
@@ -130,6 +130,15 @@ extern inline void *__va(unsigned long physaddr)
 }
 #define MAP_NR(addr)           (__pa(addr) >> PAGE_SHIFT)
 
+#define BUG() do { \
+       printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
+       asm volatile("illegal"); \
+} while (0)
+
+#define PAGE_BUG(page) do { \
+       BUG(); \
+} while (0)
+
 #endif /* __KERNEL__ */
 
 #endif /* _M68K_PAGE_H */
index e00ff1aed6cf089750fc9b11ec0039fd83f8d558..a895528dc7e69948b0aba74443b895da53ca4dc6 100644 (file)
@@ -6,7 +6,7 @@
 
 #ifndef __ASSEMBLY__
 #include <asm/processor.h>
-#include <linux/tasks.h>
+#include <linux/threads.h>
 
 /*
  * This file contains the functions and defines necessary to modify and use
@@ -264,21 +264,6 @@ extern inline void flush_tlb_kernel_page(unsigned long addr)
 #define PTRS_PER_PGD   128
 #define USER_PTRS_PER_PGD      (TASK_SIZE/PGDIR_SIZE)
 
-/* the no. of pointers that fit on a page: this will go away */
-#define PTRS_PER_PAGE  (PAGE_SIZE/sizeof(void*))
-
-typedef pgd_t pgd_table[PTRS_PER_PGD];
-typedef pmd_t pmd_table[PTRS_PER_PMD];
-typedef pte_t pte_table[PTRS_PER_PTE];
-
-#define PGD_TABLES_PER_PAGE (PAGE_SIZE/sizeof(pgd_table))
-#define PMD_TABLES_PER_PAGE (PAGE_SIZE/sizeof(pmd_table))
-#define PTE_TABLES_PER_PAGE (PAGE_SIZE/sizeof(pte_table))
-
-typedef pgd_table pgd_tablepage[PGD_TABLES_PER_PAGE];
-typedef pmd_table pmd_tablepage[PMD_TABLES_PER_PAGE];
-typedef pte_table pte_tablepage[PTE_TABLES_PER_PAGE];
-
 /* Virtual address region for use by kernel_map() */
 #define        KMAP_START      0xd0000000
 #define        KMAP_END        0xf0000000
@@ -430,9 +415,9 @@ extern inline void pmd_set(pmd_t * pmdp, pte_t * ptep)
 {
        int i;
        unsigned long ptbl;
-       ptbl = virt_to_phys(ptep);
-       for (i = 0; i < 16; i++, ptbl += sizeof(pte_table)/16)
-               pmdp->pmd[i] = _PAGE_TABLE | _PAGE_ACCESSED | ptbl;
+       ptbl = virt_to_phys(ptep) | _PAGE_TABLE | _PAGE_ACCESSED;
+       for (i = 0; i < 16; i++, ptbl += (sizeof(pte_t)*PTRS_PER_PTE/16))
+               pmdp->pmd[i] = ptbl;
 }
 
 extern inline void pgd_set(pgd_t * pgdp, pmd_t * pmdp)
@@ -499,42 +484,6 @@ extern inline pte_t pte_mknocache(pte_t pte)
 }
 extern inline pte_t pte_mkcache(pte_t pte)     { pte_val(pte) = (pte_val(pte) & _CACHEMASK040) | m68k_supervisor_cachemode; return pte; }
 
-/* to set the page-dir */
-extern inline void SET_PAGE_DIR(struct task_struct * tsk, pgd_t * pgdir)
-{
-       tsk->tss.crp[0] = 0x80000000 | _PAGE_TABLE;
-       tsk->tss.crp[1] = virt_to_phys(pgdir);
-       if (tsk == current) {
-               if (CPU_IS_040_OR_060)
-                       __asm__ __volatile__ (".chip 68040\n\t"
-                                             "pflushan\n\t"
-                                             "movec %0,%%urp\n\t"
-                                             ".chip 68k"
-                                             : : "r" (tsk->tss.crp[1]));
-               else {
-                       unsigned long tmp;
-                       __asm__ __volatile__ ("movec  %%cacr,%0\n\t"
-                                             "orw #0x0808,%0\n\t"
-                                             "movec %0,%%cacr"
-                                             : "=d" (tmp));
-                       /* For a 030-only kernel, avoid flushing the whole
-                          ATC, we only need to flush the user entries.
-                          The 68851 does this by itself.  Avoid a runtime
-                          check here.  */
-                       __asm__ __volatile__ (
-#ifdef CPU_M68030_ONLY
-                                             ".chip 68030\n\t"
-                                             "pmovefd %0,%%crp\n\t"
-                                             ".chip 68k\n\t"
-                                             "pflush #0,#4"
-#else
-                                             "pmove %0,%%crp"
-#endif
-                                             : : "m" (tsk->tss.crp[0]));
-               }
-       }
-}
-
 #define PAGE_DIR_OFFSET(tsk,address) pgd_offset((tsk),(address))
 
 /* to find an entry in a page-table-directory */
index 3115e46c352fd0cdb2c257ca756b77a0ac0d1a27..92c4a442bce707217b2b552104022c0bb5f7098b 100644 (file)
 
 #include <asm/segment.h>
 #include <asm/fpu.h>
+#include <asm/ptrace.h>
+
+extern inline unsigned long rdusp(void) {
+       unsigned long usp;
+
+       __asm__ __volatile__("move %/usp,%0" : "=a" (usp));
+       return usp;
+}
+
+extern inline void wrusp(unsigned long usp) {
+       __asm__ __volatile__("move %0,%/usp" : : "a" (usp));
+}
 
 /*
  * User space process size: 3.75GB. This is hardcoded into a few places,
@@ -53,7 +65,7 @@ struct thread_struct {
 
 #define INIT_MMAP { &init_mm, 0, 0x40000000, NULL, __pgprot(_PAGE_PRESENT|_PAGE_ACCESSED), VM_READ | VM_WRITE | VM_EXEC, 1, NULL, NULL }
 
-#define INIT_TSS  { \
+#define INIT_THREAD  { \
        sizeof(init_stack) + (unsigned long) init_stack, 0, \
        PS_S, __KERNEL_DS, \
        {0, 0}, 0, {0,}, {0, 0, 0}, {0,}, \
@@ -73,6 +85,9 @@ static inline void start_thread(struct pt_regs * regs, unsigned long pc,
        wrusp(usp);
 }
 
+/* Forward declaration, a strange C thing */
+struct task_struct;
+
 /* Free all resources held by a thread. */
 static inline void release_thread(struct task_struct *dead_task)
 {
@@ -80,7 +95,7 @@ static inline void release_thread(struct task_struct *dead_task)
 
 extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
 
-#define copy_segments(nr, tsk, mm)     do { } while (0)
+#define copy_segments(tsk, mm)         do { } while (0)
 #define release_segments(mm)           do { } while (0)
 #define forget_segments()              do { } while (0)
 
@@ -107,6 +122,8 @@ extern inline unsigned long thread_saved_pc(struct thread_struct *t)
                return sw->retpc;
 }
 
+#define THREAD_SIZE (2*PAGE_SIZE)
+
 /* Allocation and freeing of basic task resources. */
 #define alloc_task_struct() \
        ((struct task_struct *) __get_free_pages(GFP_KERNEL,1))
index 3f981c7b68ed11882dce9f0540ffca1308daee4a..11376a494017e04c031723bf7742c48b949f0e0c 100644 (file)
@@ -28,7 +28,7 @@
   {_STK_LIM, LONG_MAX}, \
   {       0, LONG_MAX}, \
   {LONG_MAX, LONG_MAX}, \
-  {MAX_TASKS_PER_USER, MAX_TASKS_PER_USER}, \
+  {0, 0},              \
   {INR_OPEN, INR_OPEN}, \
   {LONG_MAX, LONG_MAX}, \
   {LONG_MAX, LONG_MAX}  \
index e1bdb10f44c27e981599b490c566647be532f906..c194bdb8436ca76f5832a300be3f1a49351066f1 100644 (file)
@@ -2,6 +2,7 @@
 #define _M68K_SEMAPHORE_H
 
 #include <linux/linkage.h>
+#include <linux/wait.h>
 
 #include <asm/system.h>
 #include <asm/atomic.h>
@@ -19,10 +20,45 @@ struct semaphore {
        atomic_t count;
        atomic_t waking;
        wait_queue_head_t wait;
+#if WAITQUEUE_DEBUG
+       long __magic;
+#endif
 };
 
-#define MUTEX ((struct semaphore) { ATOMIC_INIT(1), ATOMIC_INIT(0), NULL })
-#define MUTEX_LOCKED ((struct semaphore) { ATOMIC_INIT(0), ATOMIC_INIT(0), NULL })
+#if WAITQUEUE_DEBUG
+# define __SEM_DEBUG_INIT(name) \
+               , (long)&(name).__magic
+#else
+# define __SEM_DEBUG_INIT(name)
+#endif
+
+#define __SEMAPHORE_INITIALIZER(name,count) \
+{ ATOMIC_INIT(count), ATOMIC_INIT(0), __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
+       __SEM_DEBUG_INIT(name) }
+
+#define __MUTEX_INITIALIZER(name) \
+       __SEMAPHORE_INITIALIZER(name,1)
+
+#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+       struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
+
+#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
+#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
+
+extern inline void sema_init (struct semaphore *sem, int val)
+{
+       *sem = (struct semaphore)__SEMAPHORE_INITIALIZER(*sem, val);
+}
+
+static inline void init_MUTEX (struct semaphore *sem)
+{
+       sema_init(sem, 1);
+}
+
+static inline void init_MUTEX_LOCKED (struct semaphore *sem)
+{
+       sema_init(sem, 0);
+}
 
 asmlinkage void __down_failed(void /* special register calling convention */);
 asmlinkage int  __down_failed_interruptible(void  /* params in registers */);
@@ -34,8 +70,6 @@ asmlinkage int  __down_interruptible(struct semaphore * sem);
 asmlinkage int  __down_trylock(struct semaphore * sem);
 asmlinkage void __up(struct semaphore * sem);
 
-#define sema_init(sem, val)    atomic_set(&((sem)->count), val)
-
 /*
  * This is ugly, but we want the default case to fall through.
  * "down_failed" is a special asm handler that calls the C
@@ -44,6 +78,11 @@ asmlinkage void __up(struct semaphore * sem);
 extern inline void down(struct semaphore * sem)
 {
        register struct semaphore *sem1 __asm__ ("%a1") = sem;
+
+#if WAITQUEUE_DEBUG
+       CHECK_MAGIC(sem->__magic);
+#endif
+
        __asm__ __volatile__(
                "| atomic down operation\n\t"
                "subql #1,%0@\n\t"
@@ -64,6 +103,10 @@ extern inline int down_interruptible(struct semaphore * sem)
        register struct semaphore *sem1 __asm__ ("%a1") = sem;
        register int result __asm__ ("%d0");
 
+#if WAITQUEUE_DEBUG
+       CHECK_MAGIC(sem->__magic);
+#endif
+
        __asm__ __volatile__(
                "| atomic interruptible down operation\n\t"
                "subql #1,%1@\n\t"
@@ -86,6 +129,10 @@ extern inline int down_trylock(struct semaphore * sem)
        register struct semaphore *sem1 __asm__ ("%a1") = sem;
        register int result __asm__ ("%d0");
 
+#if WAITQUEUE_DEBUG
+       CHECK_MAGIC(sem->__magic);
+#endif
+
        __asm__ __volatile__(
                "| atomic down trylock operation\n\t"
                "subql #1,%1@\n\t"
@@ -112,6 +159,11 @@ extern inline int down_trylock(struct semaphore * sem)
 extern inline void up(struct semaphore * sem)
 {
        register struct semaphore *sem1 __asm__ ("%a1") = sem;
+
+#if WAITQUEUE_DEBUG
+       CHECK_MAGIC(sem->__magic);
+#endif
+
        __asm__ __volatile__(
                "| atomic up operation\n\t"
                "addql #1,%0@\n\t"
index dc5f567282cb4522e2fe184265b69468c0987be4..f27b11256675aa8d6c447194d1c7e2c3d69125d4 100644 (file)
@@ -46,6 +46,9 @@ extern inline void remove_bh(int nr)
 
 extern unsigned int local_bh_count[NR_CPUS];
 
+#define local_bh_disable()     (local_bh_count[smp_processor_id()]++)
+#define local_bh_enable()      (local_bh_count[smp_processor_id()]--)
+
 extern inline void start_bh_atomic(void)
 {
        local_bh_count[smp_processor_id()]++;
index 1c3ace986aaa57677cf1713b01ed8737537fe33b..dc4f55b2af9c56eefc9edf13626754fe676c6c62 100644 (file)
@@ -17,12 +17,14 @@ typedef struct { int gcc_is_buggy; } spinlock_t;
 #endif
 
 #define spin_lock_init(lock)   do { } while(0)
-#define spin_lock(lock)                do { } while(0)
-#define spin_trylock(lock)     do { } while(0)
+#define spin_lock(lock)                (void)(lock) /* Not "unused variable". */
+#define spin_trylock(lock)     (1)
 #define spin_unlock_wait(lock) do { } while(0)
 #define spin_unlock(lock)      do { } while(0)
 #define spin_lock_irq(lock)    cli()
 #define spin_unlock_irq(lock)  sti()
+#define spin_lock_bh(lock)     local_bh_disable()
+#define spin_unlock_bh(lock)   local_bh_enable()
 
 #define spin_lock_irqsave(lock, flags) \
        do { save_flags(flags); cli(); } while (0)
@@ -49,14 +51,18 @@ typedef struct { int gcc_is_buggy; } rwlock_t;
 #define RW_LOCK_UNLOCKED (rwlock_t) { 0 }
 #endif
 
-#define read_lock(lock)                do { } while(0)
+#define read_lock(lock)                (void)(lock) /* Not "unused variable". */
 #define read_unlock(lock)      do { } while(0)
-#define write_lock(lock)       do { } while(0)
+#define write_lock(lock)       (void)(lock) /* Not "unused variable". */
 #define write_unlock(lock)     do { } while(0)
 #define read_lock_irq(lock)    cli()
 #define read_unlock_irq(lock)  sti()
 #define write_lock_irq(lock)   cli()
 #define write_unlock_irq(lock) sti()
+#define read_lock_bh(lock)     local_bh_disable()
+#define read_unlock_bh(lock)   local_bh_enable()
+#define write_lock_bh(lock)    local_bh_disable()
+#define write_unlock_bh(lock)  local_bh_enable()
 
 #define read_lock_irqsave(lock, flags)         save_and_cli(flags)
 #define read_unlock_irqrestore(lock, flags)    restore_flags(flags)
index e39d9deafa37adacff23cee5448d079b4fa41b8f..7d1afa286b89eafa6f51025b5c41dda487211749 100644 (file)
@@ -5,17 +5,6 @@
 #include <linux/linkage.h>
 #include <asm/segment.h>
 
-extern inline unsigned long rdusp(void) {
-       unsigned long usp;
-
-       __asm__ __volatile__("move %/usp,%0" : "=a" (usp));
-       return usp;
-}
-
-extern inline void wrusp(unsigned long usp) {
-       __asm__ __volatile__("move %0,%/usp" : : "a" (usp));
-}
-
 #define prepare_to_switch()    do { } while(0)
 
 /*
index 4180f3df7c84f78a586ab66cfd5918cd29e951ca..2f6d5c3f4140475e527512f1ee7070019d4d94eb 100644 (file)
 #define __NR_olduname          109
 #define __NR_iopl              /* 110 */ not supported
 #define __NR_vhangup           111
-#define __NR_idle              112
+#define __NR_idle              /* 112 */ Obsolete
 #define __NR_vm86              /* 113 */ not supported
 #define __NR_wait4             114
 #define __NR_swapoff           115
@@ -309,7 +309,6 @@ __syscall_return(type,__res); \
  * some others too.
  */
 #define __NR__exit __NR_exit
-static inline _syscall0(int,idle)
 static inline _syscall0(int,pause)
 static inline _syscall0(int,sync)
 static inline _syscall0(pid_t,setsid)
index 8065ea904852e8a2081afa1838443eaf2aa94643..161b3f3da8e72f3feddcc39410c23a1fa6c54169 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: ide.h,v 1.14 1999/05/15 05:02:35 davem Exp $
+/* $Id: ide.h,v 1.15 1999/08/08 01:38:18 davem Exp $
  * ide.h: Ultra/PCI specific IDE glue.
  *
  * Copyright (C) 1997  David S. Miller (davem@caip.rutgers.edu)
index abea97fe0113ea59a1ca1a885e67873882305a00..c32cd815385a6cac4953415a57031a59986a32f9 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: parport.h,v 1.3 1999/08/04 03:20:03 davem Exp $
+/* $Id: parport.h,v 1.4 1999/08/08 01:38:18 davem Exp $
  * parport.h: sparc64 specific parport initialization and dma.
  *
  * Copyright (C) 1999  Eddie C. Dost  (ecd@skynet.be)
index 1c4df58f6a13957ae3f358d90f2d063a685674da..6349e45cf9bcc16cd3394062cd53efe60f7e8875 100644 (file)
@@ -27,7 +27,6 @@ struct cvf_format
   int (*fat_access) (struct super_block *sb,int nr,int new_value);
   int (*cvf_statfs) (struct super_block *sb,struct statfs *buf, int bufsiz);
   int (*cvf_bmap) (struct inode *inode,int block);
-  int (*cvf_smap) (struct inode *inode,int sector);
   ssize_t (*cvf_file_read) ( struct file *, char *, size_t, loff_t *);
   ssize_t (*cvf_file_write) ( struct file *, const char *, size_t, loff_t *);
   int (*cvf_mmap) (struct file *, struct vm_area_struct *);
index f084ca0366b17e79a352d3f4b8a38e864f402a7b..a4c86b838adb68a7df7a18d1d0d0d0d693d9747c 100644 (file)
 #define FB_AUX_TEXT_MGA_STEP16 3       /* MGA Millenium I: text, attr, 14 reserved bytes */
 #define FB_AUX_TEXT_MGA_STEP8  4       /* other MGAs:      text, attr,  6 reserved bytes */
 
+#define FB_AUX_VGA_PLANES_VGA4         0       /* 16 color planes (EGA/VGA) */
+#define FB_AUX_VGA_PLANES_CFB4         1       /* CFB4 in planes (VGA) */
+#define FB_AUX_VGA_PLANES_CFB8         2       /* CFB8 in planes (VGA) */
+
 #define FB_VISUAL_MONO01               0       /* Monochr. 1=Black 0=White */
 #define FB_VISUAL_MONO10               1       /* Monochr. 1=White 0=Black */
 #define FB_VISUAL_TRUECOLOR            2       /* True color   */
 #define FB_ACCEL_MATROX_MGAG100        20      /* Matrox G100 (Productiva G100) */
 #define FB_ACCEL_MATROX_MGAG200        21      /* Matrox G200 (Myst, Mill, ...) */
 #define FB_ACCEL_SUN_CG14      22      /* Sun cgfourteen                */
-#define FB_ACCEL_SUN_BWTWO     23      /* Sun bwtwo                     */
-#define FB_ACCEL_SUN_CGTHREE   24      /* Sun cgthree                   */
-#define FB_ACCEL_SUN_TCX       25      /* Sun tcx                       */
+#define FB_ACCEL_SUN_BWTWO     23      /* Sun bwtwo                    */
+#define FB_ACCEL_SUN_CGTHREE   24      /* Sun cgthree                  */
+#define FB_ACCEL_SUN_TCX       25      /* Sun tcx                      */
+#define FB_ACCEL_MATROX_MGAG400        26      /* Matrox G400                  */
+#define FB_ACCEL_NV3           27      /* nVidia RIVA 128              */
+#define FB_ACCEL_NV4           28      /* nVidia RIVA TNT              */
+#define FB_ACCEL_NV5           29      /* nVidia RIVA TNT2             */
 
 struct fb_fix_screeninfo {
        char id[16];                    /* identification string eg "TT Builtin" */
index c6fbe66a932a774a0f5974a5db09edbef5b68e64..b1533540d5cf0e260bec487d44bac08dcea2deee 100644 (file)
@@ -63,7 +63,7 @@ extern int max_super_blocks, nr_super_blocks;
 #define READ 0
 #define WRITE 1
 #define READA 2                /* read-ahead  - don't block if no resources */
-#define WRITEA 3       /* write-ahead - don't block if no resources */
+
 #define WRITERAW 5     /* raw write - don't play with buffer lists */
 
 #ifndef NULL
@@ -898,6 +898,7 @@ typedef int (*writepage_t)(struct file *, struct page *, unsigned long, unsigned
 extern int block_read_full_page(struct file *, struct page *);
 extern int block_write_full_page (struct file *, struct page *);
 extern int block_write_partial_page (struct file *, struct page *, unsigned long, unsigned long, const char *);
+extern int block_write_cont_page (struct file *, struct page *, unsigned long, unsigned long, const char *);
 extern int block_flushpage(struct inode *, struct page *, unsigned long);
 
 extern int generic_file_mmap(struct file *, struct vm_area_struct *);
diff --git a/include/linux/hfmodem.h b/include/linux/hfmodem.h
deleted file mode 100644 (file)
index d23108e..0000000
+++ /dev/null
@@ -1,256 +0,0 @@
-/*****************************************************************************/
-
-/*
- *      hfmodem.h  --  Linux soundcard HF FSK driver.
- *
- *      Copyright (C) 1997  Thomas Sailer (sailer@ife.ee.ethz.ch)
- *        Swiss Federal Institute of Technology (ETH), Electronics Lab
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *
- *  This is the Linux realtime sound output driver
- */
-
-/*****************************************************************************/
-
-#ifndef _HFMODEM_H
-#define _HFMODEM_H
-/* --------------------------------------------------------------------- */
-
-#include <linux/version.h>
-
-#include <linux/ioctl.h>
-#include <linux/types.h>
-#include <linux/fs.h>
-#if LINUX_VERSION_CODE >= 0x20100
-#include <linux/poll.h>
-#endif
-
-/* --------------------------------------------------------------------- */
-
-#define HFMODEM_MINOR         145
-
-#define HFMODEM_SRATE        8000
-#define HFMODEM_MAXBITS      4800   /* required for GTOR 300 baud mode */
-#define HFMODEM_MINBAUD        40
-#define HFMODEM_MAXBAUD       400
-#define HFMODEM_MAXCORRLEN   ((HFMODEM_SRATE+HFMODEM_MINBAUD-1)/HFMODEM_MINBAUD)
-
-/* --------------------------------------------------------------------- */
-
-typedef unsigned long hfmodem_time_t;
-typedef int hfmodem_soft_t;
-typedef unsigned long hfmodem_id_t;
-
-/* --------------------------------------------------------------------- */
-
-struct hfmodem_ioctl_fsk_tx_request {
-       hfmodem_time_t tstart;
-       hfmodem_time_t tinc;
-       int inv;
-       hfmodem_id_t id;
-       unsigned int nbits;
-       unsigned char *data;
-       unsigned int freq[2];
-};
-
-struct hfmodem_ioctl_fsk_rx_request {
-       hfmodem_time_t tstart;
-       hfmodem_time_t tinc;
-       unsigned int baud;
-       hfmodem_id_t id;
-       unsigned int nbits;
-       hfmodem_soft_t *data;
-       unsigned int freq[2];
-};
-
-struct hfmodem_ioctl_mixer_params {
-       int src;
-       int igain;
-       int ogain;
-};
-
-struct hfmodem_ioctl_sample_params {
-       __s16 *data;
-       int len;
-};
-
-#define HFMODEM_IOCTL_FSKTXREQUEST    _IOW('H', 0, struct hfmodem_ioctl_fsk_tx_request)
-#define HFMODEM_IOCTL_FSKRXREQUEST    _IOW('H', 1, struct hfmodem_ioctl_fsk_rx_request)
-#define HFMODEM_IOCTL_CLEARRQ         _IO('H',  3)
-#define HFMODEM_IOCTL_GETCURTIME      _IOR('H', 4, hfmodem_time_t)
-#define HFMODEM_IOCTL_WAITRQ          _IOR('H', 5, hfmodem_id_t)
-#define HFMODEM_IOCTL_MIXERPARAMS     _IOW('H', 6, struct hfmodem_ioctl_mixer_params)
-#define HFMODEM_IOCTL_SAMPLESTART     _IOW('H', 7, struct hfmodem_ioctl_sample_params)
-#define HFMODEM_IOCTL_SAMPLEFINISHED  _IO('H',  8)
-
-/* --------------------------------------------------------------------- */
-#ifdef __KERNEL__
-
-#include <linux/parport.h>
-
-#define DMA_MODE_AUTOINIT      0x10
-
-#define NR_DEVICE 1
-
-#define HFMODEM_FRAGSAMPLES (HFMODEM_SRATE/100)
-#define HFMODEM_FRAGSIZE    (HFMODEM_FRAGSAMPLES*2)
-#define HFMODEM_NUMFRAGS    8
-#define HFMODEM_EXCESSFRAGS 3
-
-#define HFMODEM_NUMRXSLOTS 20
-#define HFMODEM_NUMTXSLOTS 4
-
-#define HFMODEM_CORRELATOR_CACHE 8
-
-enum slot_st { ss_unused = 0, ss_ready, ss_oper, ss_retired };
-typedef int hfmodem_conv_t;
-
-struct hfmodem_state {
-       const struct hfmodem_scops *scops;
-
-       /* io params */
-       struct {
-               unsigned int base_addr;
-               unsigned int dma;
-               unsigned int irq;
-       } io;
-
-       struct {
-               unsigned int seriobase;
-               unsigned int pariobase;
-               unsigned int midiiobase;
-               unsigned int flags;
-               struct pardevice *pardev;
-       } ptt_out;
-
-       struct {
-               __s16 *buf;
-               unsigned int lastfrag;
-               unsigned int fragptr;
-               unsigned int last_dmaptr;
-               int ptt_frames;
-       } dma;
-
-       struct {
-               unsigned int last_tvusec;
-               unsigned long long time_cnt;
-               hfmodem_time_t lasttime;
-#ifdef __i386__
-               unsigned int starttime_lo, starttime_hi;
-#endif /* __i386__ */
-       } clk;
-
-       int active;
-       wait_queue_head_t wait;
-
-       struct {
-               __s16 *kbuf;
-               __s16 *ubuf;
-               __s16 *kptr;
-               unsigned int size;
-               int rem;
-       } sbuf;
-
-       struct {
-               hfmodem_time_t last_time; 
-               unsigned int tx_phase;
-               
-               struct hfmodem_l1_rxslot {
-                       enum slot_st state;
-                       hfmodem_time_t tstart, tinc;
-                       hfmodem_soft_t *data;
-                       hfmodem_soft_t *userdata;
-                       unsigned int nbits;
-                       unsigned int cntbits;
-                       hfmodem_id_t id;
-                       unsigned int corrlen;
-                       hfmodem_conv_t scale;
-                       unsigned int corr_cache;
-               } rxslots[HFMODEM_NUMRXSLOTS];
-               
-               struct hfmodem_l1_txslot {
-                       enum slot_st state;
-                       hfmodem_time_t tstart, tinc;
-                       unsigned char *data;
-                       unsigned int nbits;
-                       unsigned int cntbits;
-                       hfmodem_id_t id;
-                       unsigned char inv;
-                       unsigned int phinc;
-                       unsigned int phase_incs[2];
-               } txslots[HFMODEM_NUMTXSLOTS];
-       } l1;
-};
-
-struct hfmodem_correlator_cache {
-       int refcnt;
-       int lru;
-       unsigned short phase_incs[2];
-       hfmodem_conv_t correlator[2][2][HFMODEM_MAXCORRLEN];
-};
-
-struct hfmodem_scops {
-       unsigned int extent;
-
-       void (*init)(struct hfmodem_state *dev);
-       void (*prepare_input)(struct hfmodem_state *dev);
-       void (*trigger_input)(struct hfmodem_state *dev);
-       void (*prepare_output)(struct hfmodem_state *dev);
-       void (*trigger_output)(struct hfmodem_state *dev);
-       void (*stop)(struct hfmodem_state *dev);
-       unsigned int (*intack)(struct hfmodem_state *dev);
-       void (*mixer)(struct hfmodem_state *dev, int src, int igain, int ogain);
-};
-
-/* --------------------------------------------------------------------- */
-
-extern int hfmodem_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
-#if LINUX_VERSION_CODE >= 0x20100
-extern unsigned int hfmodem_poll(struct file *file, poll_table *wait);
-#else
-extern int hfmodem_select(struct inode *inode, struct file *file, int sel_type, select_table *wait);
-#endif
-
-extern void hfmodem_clear_rq(struct hfmodem_state *dev);
-extern void hfmodem_input_samples(struct hfmodem_state *dev, hfmodem_time_t tstart, 
-                               hfmodem_time_t tinc, __s16 *samples);
-extern int hfmodem_output_samples(struct hfmodem_state *dev, hfmodem_time_t tstart, 
-                               hfmodem_time_t tinc, __s16 *samples);
-extern long hfmodem_next_tx_event(struct hfmodem_state *dev, hfmodem_time_t curr);
-extern void hfmodem_finish_pending_rx_requests(struct hfmodem_state *dev);
-extern void hfmodem_wakeup(struct hfmodem_state *dev);
-
-
-extern int hfmodem_sbcprobe(struct hfmodem_state *dev);
-extern int hfmodem_wssprobe(struct hfmodem_state *dev);
-
-extern void hfmodem_refclock_probe(void);
-extern void hfmodem_refclock_init(struct hfmodem_state *dev);
-extern hfmodem_time_t hfmodem_refclock_current(struct hfmodem_state *dev, hfmodem_time_t expected, int exp_valid);
-
-/* --------------------------------------------------------------------- */
-
-extern const char hfmodem_drvname[];
-extern const char hfmodem_drvinfo[];
-
-extern struct hfmodem_state hfmodem_state[NR_DEVICE];
-extern struct hfmodem_correlator_cache hfmodem_correlator_cache[HFMODEM_CORRELATOR_CACHE];
-
-/* --------------------------------------------------------------------- */
-#endif /* __KERNEL__ */
-/* --------------------------------------------------------------------- */
-#endif /* _HFMODEM_H */
index b730d20a3352896f58edfad98024c42f15d616be..dcfbca271719ad6bf4a918050bf868cce4924c2d 100644 (file)
@@ -100,11 +100,11 @@ extern int minix_link(struct dentry * old_dentry, struct inode * dir, struct den
 extern int minix_mknod(struct inode * dir, struct dentry *dentry, int mode, int rdev);
 extern int minix_rename(struct inode * old_dir, struct dentry *old_dentry,
                        struct inode * new_dir, struct dentry *new_dentry);
-extern struct inode * minix_new_inode(const struct inode * dir);
+extern struct inode * minix_new_inode(const struct inode * dir, int * error);
 extern void minix_free_inode(struct inode * inode);
 extern unsigned long minix_count_free_inodes(struct super_block *sb);
-extern int minix_new_block(struct super_block * sb);
-extern void minix_free_block(struct super_block * sb, int block);
+extern int minix_new_block(struct inode * inode);
+extern void minix_free_block(struct inode * inode, int block);
 extern unsigned long minix_count_free_blocks(struct super_block *sb);
 
 extern int minix_bmap(struct inode *,int);
index 815266a054bb022485fb3bffda9f2dd3acdd9925..199b890cb282893699bceac411c7f6664dbf380f 100644 (file)
@@ -152,6 +152,7 @@ typedef struct page {
 #define PG_Slab                         8
 #define PG_swap_cache           9
 #define PG_skip                        10
+#define PG_swap_entry          11
                                /* bits 21-30 unused */
 #define PG_reserved            31
 
@@ -292,8 +293,6 @@ extern inline unsigned long get_free_page(int gfp_mask)
        return page;
 }
 
-extern int low_on_memory;
-
 /* memory.c & swap.c*/
 
 #define free_page(addr) free_pages((addr),0)
index f9ef19e8ceac9c96ab1e5e99264cc39cfa136519..3a7f286228c4b91024a2ff93f1e102d3d1602f2a 100644 (file)
@@ -196,7 +196,7 @@ extern int fat_is_binary(char conversion,char *extension);
 extern void lock_fat(struct super_block *sb);
 extern void unlock_fat(struct super_block *sb);
 extern int fat_add_cluster(struct inode *inode);
-extern struct buffer_head *fat_add_cluster1(struct inode *inode);
+extern struct buffer_head *fat_extend_dir(struct inode *inode);
 extern int date_dos2unix(__u16 time, __u16 date);
 extern void fat_fs_panic(struct super_block *s,const char *msg);
 extern void fat_lock_creation(void);
@@ -225,7 +225,6 @@ void fat_clusters_flush(struct super_block *sb);
 
 /* fat.c */
 extern int fat_access(struct super_block *sb,int nr,int new_value);
-extern int fat_smap(struct inode *inode,int sector);
 extern int fat_free(struct inode *inode,int skip);
 void fat_cache_inval_inode(struct inode *inode);
 void fat_cache_inval_dev(kdev_t device);
@@ -237,6 +236,7 @@ int fat_get_cluster(struct inode *inode,int cluster);
 /* inode.c */
 extern void fat_hash_init(void);
 extern int fat_bmap(struct inode *inode,int block);
+extern int fat_get_block(struct inode *, long, struct buffer_head *, int);
 extern int fat_notify_change(struct dentry *, struct iattr *);
 extern void fat_clear_inode(struct inode *inode);
 extern void fat_delete_inode(struct inode *inode);
@@ -261,6 +261,7 @@ extern int fat_dir_ioctl(struct inode * inode, struct file * filp,
 int fat_add_entries(struct inode *dir,int slots, struct buffer_head **bh,
                  struct msdos_dir_entry **de, int *ino);
 int fat_dir_empty(struct inode *dir);
+int fat_new_dir(struct inode *inode, struct inode *parent, int is_vfat);
 
 /* file.c */
 extern struct inode_operations fat_file_inode_operations;
index b2381f6d4f90d8435269bc78da41e97bea57a2dc..bcb37bb80ef1c74122404fcf018a2a33a13ac210 100644 (file)
@@ -10,12 +10,10 @@ struct msdos_inode_info {
        int i_logstart; /* logical first cluster */
        int i_attrs;    /* unused attribute bits */
        int i_ctime_ms; /* unused change time in milliseconds */
-       int i_busy;     /* file is either deleted but still open, or
-                          inconsistent (mkdir) */
-       int i_binary;   /* file contains non-text data */
        int i_location; /* on-disk position of directory entry or 0 */
        struct inode *i_fat_inode;      /* struct inode of this one */
        struct list_head i_fat_hash;    /* hash by i_location */
+       int i_realsize;
 };
 
 #endif
index 60fae4f811405a5634e90b803b2d0b0cbbb6dfbb..ea7c1bc7fb6cb4585502751a1695551c8e284204 100644 (file)
@@ -491,7 +491,7 @@ extern void dec_parport_count(void);
 extern void inc_parport_count(void);
 
 /* If PC hardware is the only type supported, we can optimise a bit.  */
-#if (defined(CONFIG_PARPORT_PC) || defined(CONFIG_PARPORT_PC_MODULE)) && !(defined(CONFIG_PARPORT_AX) || defined(CONFIG_PARPORT_AX_MODULE)) && !(defined(CONFIG_PARPORT_ARC) || defined(CONFIG_PARPORT_ARC_MODULE)) && !(defined(CONFIG_PARPORT_AMIGA) || defined(CONFIG_PARPORT_AMIGA_MODULE)) && !(defined(CONFIG_PARPORT_MFC3) || defined(CONFIG_PARPORT_MFC3_MODULE)) && !(defined(CONFIG_PARPORT_ATARI) || defined(CONFIG_PARPORT_ATARI_MODULE)) && !defined(CONFIG_PARPORT_OTHER)
+#if (defined(CONFIG_PARPORT_PC) || defined(CONFIG_PARPORT_PC_MODULE)) && !(defined(CONFIG_PARPORT_AX) || defined(CONFIG_PARPORT_AX_MODULE)) && !(defined(CONFIG_PARPORT_ARC) || defined(CONFIG_PARPORT_ARC_MODULE)) && !(defined(CONFIG_PARPORT_AMIGA) || defined(CONFIG_PARPORT_AMIGA_MODULE)) && !(defined(CONFIG_PARPORT_MFC3) || defined(CONFIG_PARPORT_MFC3_MODULE)) && !(defined(CONFIG_PARPORT_ATARI) || defined(CONFIG_PARPORT_ATARI_MODULE)) && !defined(CONFIG_PARPORT_OTHER) && !(defined(CONFIG_USB_USS720) || defined(CONFIG_USB_USS720_MODULE))
 #undef PARPORT_NEED_GENERIC_OPS
 #include <linux/parport_pc.h>
 #define parport_write_data(p,x)            parport_pc_write_data(p,x)
index 0b46d3b735abc5a90ce6468e727e0e086e2a84b4..3097a8db26f2e26ce33ebc2af2e994cbaa74cc5b 100644 (file)
@@ -51,6 +51,7 @@ extern kmem_cache_t *kmem_find_general_cachep(size_t);
 extern kmem_cache_t *kmem_cache_create(const char *, size_t, size_t, unsigned long,
                                       void (*)(void *, kmem_cache_t *, unsigned long),
                                       void (*)(void *, kmem_cache_t *, unsigned long));
+extern int kmem_cache_destroy(kmem_cache_t *);
 extern int kmem_cache_shrink(kmem_cache_t *);
 extern void *kmem_cache_alloc(kmem_cache_t *, int);
 extern void kmem_cache_free(kmem_cache_t *, void *);
index da5665a5be4ad62f7112cef0654d8163c94ae99a..9f3d82424e2af79055a08e018ab5382a930190fa 100644 (file)
@@ -100,6 +100,8 @@ struct page * lookup_swap_cache(unsigned long);
 extern struct page * read_swap_cache_async(unsigned long, int);
 #define read_swap_cache(entry) read_swap_cache_async(entry, 1);
 extern int FASTCALL(swap_count(unsigned long));
+extern unsigned long acquire_swap_entry(struct page *page);
+
 /*
  * Make these inline later once they are working properly.
  */
index 14bdb829d4cd9ff82efcdac5fee1c69f14233337..395226a23c443d47cc29c19c2d2d8c27a1174984 100644 (file)
@@ -174,10 +174,6 @@ struct umsdos_ioctl {
 #endif
 
 extern struct inode_operations umsdos_dir_inode_operations;
-extern struct file_operations umsdos_file_operations;
-extern struct inode_operations umsdos_file_inode_operations;
-extern struct inode_operations umsdos_file_inode_operations_no_bmap;
-extern struct inode_operations umsdos_file_inode_operations_readpage;
 extern struct inode_operations umsdos_symlink_inode_operations;
 extern int init_umsdos_fs (void);
 
index 01302010ddea1292c584ad4ec9cab55ee7d9d44d..b58ba6d058b28ea44f30f51be09010e3199f4985 100644 (file)
@@ -95,6 +95,7 @@ EXPORT_SYMBOL(free_pages);
 EXPORT_SYMBOL(__free_page);
 EXPORT_SYMBOL(kmem_find_general_cachep);
 EXPORT_SYMBOL(kmem_cache_create);
+EXPORT_SYMBOL(kmem_cache_destroy);
 EXPORT_SYMBOL(kmem_cache_shrink);
 EXPORT_SYMBOL(kmem_cache_alloc);
 EXPORT_SYMBOL(kmem_cache_free);
@@ -169,6 +170,7 @@ EXPORT_SYMBOL(add_blkdev_randomness);
 EXPORT_SYMBOL(block_read_full_page);
 EXPORT_SYMBOL(block_write_full_page);
 EXPORT_SYMBOL(block_write_partial_page);
+EXPORT_SYMBOL(block_write_cont_page);
 EXPORT_SYMBOL(block_flushpage);
 EXPORT_SYMBOL(generic_file_read);
 EXPORT_SYMBOL(generic_file_write);
index fe46e3d85a034bba157fe019630f15ebed87d79b..e49a35077eb6af45e2d7c19434410e8695048511 100644 (file)
@@ -145,7 +145,7 @@ struct resource * __request_region(struct resource *parent, unsigned long start,
 
                write_lock(&resource_lock);
 
-               while (!(parent->flags & IORESOURCE_BUSY)) {
+               for (;;) {
                        struct resource *conflict;
 
                        conflict = __request_resource(parent, res);
@@ -153,7 +153,8 @@ struct resource * __request_region(struct resource *parent, unsigned long start,
                                break;
                        if (conflict != parent) {
                                parent = conflict;
-                               continue;
+                               if (!(conflict->flags & IORESOURCE_BUSY))
+                                       continue;
                        }
 
                        /* Uhhuh, that didn't work out.. */
index 40a5ca73616413390a929266f48a9c838d437871..31da54029bad99e451fb76bf0b3687d3663e24b8 100644 (file)
@@ -212,8 +212,6 @@ repeat:
        spin_unlock(&pagecache_lock);
 }
 
-extern atomic_t too_many_dirty_buffers;
-
 int shrink_mmap(int priority, int gfp_mask)
 {
        static unsigned long clock = 0;
@@ -1866,21 +1864,22 @@ repeat_find:
 
                status = write_one_page(file, page, offset, bytes, buf);
 
+               if (status >= 0) {
+                       written += status;
+                       count -= status;
+                       pos += status;
+                       buf += status;
+                       if (pos > inode->i_size)
+                               inode->i_size = pos;
+               }
                /* Mark it unlocked again and drop the page.. */
                UnlockPage(page);
                page_cache_release(page);
 
                if (status < 0)
                        break;
-
-               written += status;
-               count -= status;
-               pos += status;
-               buf += status;
        }
        *ppos = pos;
-       if (pos > inode->i_size)
-               inode->i_size = pos;
 
        if (page_cache)
                page_cache_free(page_cache);
index 992ed781af0b2fd0f0415c6ed5505fb0f150fd99..91d9bc6ce4ed81a7094e80501353c8a2f9ef1b60 100644 (file)
@@ -992,6 +992,7 @@ static int do_swap_page(struct task_struct * tsk,
 
        pte = mk_pte(page_address(page), vma->vm_page_prot);
 
+       set_bit(PG_swap_entry, &page->flags);
        if (write_access && !is_page_shared(page)) {
                delete_from_swap_cache(page);
                pte = pte_mkwrite(pte_mkdirty(pte));
index 22ce7ac00fbbc25ceb9b80182a4fa86fb5bbacfb..2b8c1b593365e50d79bf5bc954633ad9d53f2039 100644 (file)
@@ -194,8 +194,6 @@ do { unsigned long size = 1 << high; \
        set_page_count(map, 1); \
 } while (0)
 
-int low_on_memory = 0;
-
 unsigned long __get_free_pages(int gfp_mask, unsigned long order)
 {
        unsigned long flags;
@@ -221,6 +219,7 @@ unsigned long __get_free_pages(int gfp_mask, unsigned long order)
         */
        if (!(current->flags & PF_MEMALLOC)) {
                int freed;
+               static int low_on_memory = 0;
 
                if (nr_free_pages > freepages.min) {
                        if (!low_on_memory)
index 0f7e6d199c9c60bc95db1f0985209a14a39c54e7..e830dcf49d8932a575def6704d170dd2cb90c889 100644 (file)
@@ -99,44 +99,18 @@ static void rw_swap_page_base(int rw, unsigned long entry, struct page *page, in
        } else if (p->swap_file) {
                struct inode *swapf = p->swap_file->d_inode;
                int i;
-               if (swapf->i_op->get_block == NULL
-                       && swapf->i_op->smap != NULL){
-                       /*
-                               With MS-DOS, we use msdos_smap which returns
-                               a sector number (not a cluster or block number).
-                               It is a patch to enable the UMSDOS project.
-                               Other people are working on better solution.
-
-                               It sounds like ll_rw_swap_file defined
-                               its operation size (sector size) based on
-                               PAGE_SIZE and the number of blocks to read.
-                               So using get_block or smap should work even if
-                               smap will require more blocks.
-                       */
-                       int j;
-                       unsigned int block = offset << 3;
-
-                       for (i=0, j=0; j< PAGE_SIZE ; i++, j += 512){
-                               if (!(zones[i] = swapf->i_op->smap(swapf,block++))) {
-                                       printk("rw_swap_page: bad swap file\n");
-                                       return;
-                               }
+               int j;
+               unsigned int block = offset
+                       << (PAGE_SHIFT - swapf->i_sb->s_blocksize_bits);
+
+               block_size = swapf->i_sb->s_blocksize;
+               for (i=0, j=0; j< PAGE_SIZE ; i++, j += block_size)
+                       if (!(zones[i] = bmap(swapf,block++))) {
+                               printk("rw_swap_page: bad swap file\n");
+                               return;
                        }
-                       block_size = 512;
-               }else{
-                       int j;
-                       unsigned int block = offset
-                               << (PAGE_SHIFT - swapf->i_sb->s_blocksize_bits);
-
-                       block_size = swapf->i_sb->s_blocksize;
-                       for (i=0, j=0; j< PAGE_SIZE ; i++, j += block_size)
-                               if (!(zones[i] = bmap(swapf,block++))) {
-                                       printk("rw_swap_page: bad swap file\n");
-                                       return;
-                               }
-                       zones_used = i;
-                       dev = swapf->i_dev;
-               }
+               zones_used = i;
+               dev = swapf->i_dev;
        } else {
                printk(KERN_ERR "rw_swap_page: no swap file or device\n");
                put_page(page);
index e46cae05e76788346bbc27cd33e4a7ce0cbfd277..a5dac65fbf7b1f150c88ef732c398596403d888b 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -3,6 +3,8 @@
  * Written by Mark Hemment, 1996/97.
  * (markhe@nextd.demon.co.uk)
  *
+ * kmem_cache_destroy() + some cleanup - 1999 Andrea Arcangeli
+ *
  * 11 April '97.  Started multi-threading - markhe
  *     The global cache-chain is protected by the semaphore 'cache_chain_sem'.
  *     The sem is only needed when accessing/extending the cache-chain, which
@@ -979,6 +981,59 @@ opps:
        return cachep;
 }
 
+/*
+ * This check if the kmem_cache_t pointer is chained in the cache_cache
+ * list. -arca
+ */
+static int is_chained_kmem_cache(kmem_cache_t * cachep)
+{
+       kmem_cache_t * searchp;
+       int ret = 0;
+
+       /* Find the cache in the chain of caches. */
+       down(&cache_chain_sem);
+       for (searchp = &cache_cache; searchp->c_nextp != &cache_cache;
+            searchp = searchp->c_nextp)
+       {
+               if (searchp->c_nextp != cachep)
+                       continue;
+
+               /* Accessing clock_searchp is safe - we hold the mutex. */
+               if (cachep == clock_searchp)
+                       clock_searchp = cachep->c_nextp;
+               ret = 1;
+               break;
+       }
+       up(&cache_chain_sem);
+
+       return ret;
+}
+
+/* returns 0 if every slab is been freed -arca */
+static int __kmem_cache_shrink(kmem_cache_t *cachep)
+{
+       kmem_slab_t     *slabp;
+       int     ret;
+
+       spin_lock_irq(&cachep->c_spinlock);
+
+       /* If the cache is growing, stop shrinking. */
+       while (!cachep->c_growing) {
+               slabp = cachep->c_lastp;
+               if (slabp->s_inuse || slabp == kmem_slab_end(cachep))
+                       break;
+               kmem_slab_unlink(slabp);
+               spin_unlock_irq(&cachep->c_spinlock);
+               kmem_slab_destroy(cachep, slabp);
+               spin_lock_irq(&cachep->c_spinlock);
+       }
+       ret = 1;
+       if (cachep->c_lastp == kmem_slab_end(cachep))
+               ret = 0;                /* Cache is empty. */
+       spin_unlock_irq(&cachep->c_spinlock);
+       return ret;
+}
+
 /* Shrink a cache.  Releases as many slabs as possible for a cache.
  * It is expected this function will be called by a module when it is
  * unloaded.  The cache is _not_ removed, this creates too many problems and
@@ -990,10 +1045,6 @@ opps:
 int
 kmem_cache_shrink(kmem_cache_t *cachep)
 {
-       kmem_cache_t    *searchp;
-       kmem_slab_t     *slabp;
-       int     ret;
-
        if (!cachep) {
                printk(KERN_ERR "kmem_shrink: NULL ptr\n");
                return 2;
@@ -1003,43 +1054,77 @@ kmem_cache_shrink(kmem_cache_t *cachep)
                return 2;
        }
 
+       if (!is_chained_kmem_cache(cachep))
+       {
+               printk(KERN_ERR "kmem_shrink: Invalid cache addr %p\n",
+                      cachep);
+               return 2;
+       }
+
+       return __kmem_cache_shrink(cachep);
+}
+
+/*
+ * Remove a kmem_cache_t object from the slab cache. When returns 0 it
+ * completed succesfully. -arca
+ */
+int kmem_cache_destroy(kmem_cache_t * cachep)
+{
+       kmem_cache_t * prev;
+       int ret;
+
+       if (!cachep) {
+               printk(KERN_ERR "kmem_destroy: NULL ptr\n");
+               return 1;
+       }
+       if (in_interrupt()) {
+               printk(KERN_ERR "kmem_destroy: Called during int - %s\n",
+                      cachep->c_name);
+               return 1;
+       }
+
+       ret = 0;
        /* Find the cache in the chain of caches. */
-       down(&cache_chain_sem);         /* Semaphore is needed. */
-       searchp = &cache_cache;
-       for (;searchp->c_nextp != &cache_cache; searchp = searchp->c_nextp) {
-               if (searchp->c_nextp != cachep)
+       down(&cache_chain_sem);
+       for (prev = &cache_cache; prev->c_nextp != &cache_cache;
+            prev = prev->c_nextp)
+       {
+               if (prev->c_nextp != cachep)
                        continue;
 
                /* Accessing clock_searchp is safe - we hold the mutex. */
                if (cachep == clock_searchp)
                        clock_searchp = cachep->c_nextp;
-               goto found;
+
+               /* remove the cachep from the cache_cache list. -arca */
+               prev->c_nextp = cachep->c_nextp;
+
+               ret = 1;
+               break;
        }
        up(&cache_chain_sem);
-       printk(KERN_ERR "kmem_shrink: Invalid cache addr %p\n", cachep);
-       return 2;
-found:
-       /* Release the semaphore before getting the cache-lock.  This could
-        * mean multiple engines are shrinking the cache, but so what.
-        */
-       up(&cache_chain_sem);
-       spin_lock_irq(&cachep->c_spinlock);
 
-       /* If the cache is growing, stop shrinking. */
-       while (!cachep->c_growing) {
-               slabp = cachep->c_lastp;
-               if (slabp->s_inuse || slabp == kmem_slab_end(cachep))
-                       break;
-               kmem_slab_unlink(slabp);
-               spin_unlock_irq(&cachep->c_spinlock);
-               kmem_slab_destroy(cachep, slabp);
-               spin_lock_irq(&cachep->c_spinlock);
+       if (!ret)
+       {
+               printk(KERN_ERR "kmem_destroy: Invalid cache addr %p\n",
+                      cachep);
+               return 1;
        }
-       ret = 1;
-       if (cachep->c_lastp == kmem_slab_end(cachep))
-               ret--;          /* Cache is empty. */
-       spin_unlock_irq(&cachep->c_spinlock);
-       return ret;
+
+       if (__kmem_cache_shrink(cachep))
+       {
+               printk(KERN_ERR "kmem_destroy: Can't free all objects %p\n",
+                      cachep);
+               down(&cache_chain_sem);
+               cachep->c_nextp = cache_cache.c_nextp;
+               cache_cache.c_nextp = cachep;
+               up(&cache_chain_sem);
+               return 1;
+       }
+
+       kmem_cache_free(&cache_cache, cachep);
+
+       return 0;
 }
 
 /* Get the memory for a slab management obj. */
index 2aa17d3a400a0088f1248d5f8309b06d5569420b..7116cfd5c55554b2632cce8498b4d8a0922986e8 100644 (file)
@@ -274,6 +274,8 @@ void free_page_and_swap_cache(unsigned long addr)
        }
        UnlockPage(page);
        
+       clear_bit(PG_swap_entry, &page->flags);
+
        __free_page(page);
 }
 
index 5a7a148ea8cc48e5bb79dcb0e5d376c27e1828c0..1e262cbcd49b6f0f26ae95aa6595f343117e5065 100644 (file)
@@ -126,15 +126,17 @@ void swap_free(unsigned long entry)
        offset = SWP_OFFSET(entry);
        if (offset >= p->max)
                goto bad_offset;
-       if (offset < p->lowest_bit)
-               p->lowest_bit = offset;
-       if (offset > p->highest_bit)
-               p->highest_bit = offset;
        if (!p->swap_map[offset])
                goto bad_free;
        if (p->swap_map[offset] < SWAP_MAP_MAX) {
                if (!--p->swap_map[offset])
+               {
+                       if (offset < p->lowest_bit)
+                               p->lowest_bit = offset;
+                       if (offset > p->highest_bit)
+                               p->highest_bit = offset;
                        nr_swap_pages++;
+               }
        }
 #ifdef DEBUG_SWAP
        printk("DebugVM: swap_free(entry %08lx, count now %d)\n",
@@ -157,6 +159,44 @@ bad_free:
        goto out;
 }
 
+/* needs the big kernel lock */
+unsigned long acquire_swap_entry(struct page *page)
+{
+       struct swap_info_struct * p;
+       unsigned long offset, type;
+       unsigned long entry;
+
+       if (!test_bit(PG_swap_entry, &page->flags))
+               goto new_swap_entry;
+
+       /* We have the old entry in the page offset still */
+       entry = page->offset;
+       if (!entry)
+               goto new_swap_entry;
+       type = SWP_TYPE(entry);
+       if (type & SHM_SWP_TYPE)
+               goto new_swap_entry;
+       if (type >= nr_swapfiles)
+               goto new_swap_entry;
+       p = type + swap_info;
+       if ((p->flags & SWP_WRITEOK) != SWP_WRITEOK)
+               goto new_swap_entry;
+       offset = SWP_OFFSET(entry);
+       if (offset >= p->max)
+               goto new_swap_entry;
+       /* Has it been re-used for something else? */
+       if (p->swap_map[offset])
+               goto new_swap_entry;
+
+       /* We're cool, we can just use the old one */
+       p->swap_map[offset] = 1;
+       nr_swap_pages--;
+       return entry;
+
+new_swap_entry:
+       return get_swap_page();
+}
+
 /*
  * The swap entry has been read in advance, and we return 1 to indicate
  * that the page has been used or is no longer needed.
@@ -495,7 +535,6 @@ asmlinkage int sys_swapon(const char * specialfile, int swap_flags)
        static int least_priority = 0;
        union swap_header *swap_header = 0;
        int swap_header_version;
-       int lock_map_size = PAGE_SIZE;
        int nr_good_pages = 0;
        unsigned long maxpages;
        int swapfilesize;
@@ -664,7 +703,6 @@ asmlinkage int sys_swapon(const char * specialfile, int swap_flags)
                nr_good_pages = swap_header->info.last_page -
                                swap_header->info.nr_badpages -
                                1 /* header page */;
-               lock_map_size = (p->max + 7) / 8;
                if (error) 
                        goto bad_swap;
        }
index ed412d620ca6c85bcda3f492f4e753b955ffd12e..6ea7e979152b334ef4be6ec3f8ffb6be8608475d 100644 (file)
@@ -54,7 +54,7 @@ static int try_to_swap_out(struct vm_area_struct* vma, unsigned long address, pt
         * Dont be too eager to get aging right if
         * memory is dangerously low.
         */
-       if (!low_on_memory && pte_young(pte)) {
+       if (pte_young(pte)) {
                /*
                 * Transfer the "accessed" bit from the page
                 * tables to the global page map.
@@ -153,7 +153,7 @@ drop_pte:
         * we have the swap cache set up to associate the
         * page with that swap entry.
         */
-       entry = get_swap_page();
+       entry = acquire_swap_entry(page);
        if (!entry)
                goto out_failed_unlock; /* No swap space left */