]> git.hungrycats.org Git - linux/commitdiff
v2.4.8.1 -> v2.4.8.2
authorLinus Torvalds <torvalds@athlon.transmeta.com>
Tue, 5 Feb 2002 04:10:01 +0000 (20:10 -0800)
committerLinus Torvalds <torvalds@athlon.transmeta.com>
Tue, 5 Feb 2002 04:10:01 +0000 (20:10 -0800)
  - me: fix forgotten nfsd usage of filldir off_t -> loff_t change
  - Alan Cox: more driver merges

79 files changed:
CREDITS
Documentation/devices.txt
Documentation/parisc/mm [deleted file]
Documentation/usb/philips.txt
MAINTAINERS
Makefile
arch/arm/config.in
arch/arm/def-configs/pleb [new file with mode: 0644]
arch/arm/kernel/head-armv.S
arch/arm/kernel/process.c
arch/arm/mach-anakin/arch.c
arch/arm/mach-sa1100/assabet.c
arch/arm/mach-sa1100/bitsy.c
arch/arm/mach-sa1100/cpu-sa1110.c
arch/arm/mach-sa1100/dma-sa1100.c
arch/arm/mach-sa1100/dma-sa1111.c
arch/arm/mach-sa1100/dma.h
arch/arm/mach-sa1100/generic.c
arch/arm/mach-sa1100/lart.c
arch/arm/mach-sa1100/leds-cerf.c
arch/arm/mach-sa1100/leds-lart.c
arch/arm/mach-sa1100/leds-simpad.c
arch/arm/mach-sa1100/neponset.c
arch/arm/mach-sa1100/pleb.c
arch/arm/mach-sa1100/sa1111-pcibuf.c
arch/arm/mach-sa1100/sa1111.c
arch/arm/mach-sa1100/sherman.c
arch/arm/mach-sa1100/simpad.c
arch/arm/mm/fault-armv.c
arch/arm/tools/mach-types
drivers/char/tty_io.c
drivers/char/tty_ioctl.c
drivers/char/vt.c
drivers/isdn/eicon/common.c
drivers/isdn/eicon/linchr.c
drivers/isdn/eicon/linsys.c
drivers/isdn/eicon/uxio.h
drivers/net/depca.c.orig [deleted file]
drivers/pci/pci.c
drivers/pci/pci.ids
drivers/pcmcia/bulkmem.c
drivers/scsi/advansys.c
drivers/scsi/aic7xxx/aic7770.c
drivers/scsi/aic7xxx/aic7770_linux.c
drivers/scsi/aic7xxx/aic7xxx.c
drivers/scsi/aic7xxx/aic7xxx_93cx6.c
drivers/scsi/aic7xxx/aic7xxx_linux.c
drivers/scsi/aic7xxx/aic7xxx_linux_pci.c
drivers/scsi/aic7xxx/aic7xxx_pci.c
drivers/scsi/aic7xxx/aic7xxx_proc.c
drivers/scsi/aic7xxx/aicasm/aicasm.c
drivers/scsi/aic7xxx/aicasm/aicasm_symbol.c
drivers/sound/emu10k1/audio.c
drivers/sound/emu10k1/main.c
drivers/sound/i810_audio.c
drivers/usb/CDCEther.c [new file with mode: 0644]
drivers/usb/CDCEther.h [new file with mode: 0644]
drivers/usb/kaweth.c [new file with mode: 0644]
drivers/usb/kawethfw.h [new file with mode: 0644]
drivers/video/acornfb.c
drivers/video/acornfb.h
drivers/video/cyber2000fb.c
drivers/video/sa1100fb.c
drivers/video/sa1100fb.h [new file with mode: 0644]
fs/hpfs/file.c
fs/hpfs/inode.c
fs/nfs/file.c
fs/nfsd/nfsfh.c
fs/sysv/file.c
fs/ufs/file.c
include/asm-arm/arch-sa1100/SA-1100.h
include/asm-arm/arch-sa1100/assabet.h
include/asm-arm/arch-sa1100/ide.h
include/asm-arm/arch-sa1100/lart.h
include/asm-arm/arch-sa1100/simpad.h
include/asm-arm/keyboard.h
include/asm-arm/proc-armv/cache.h
ipc/util.c
kernel/ksyms.c

diff --git a/CREDITS b/CREDITS
index 155c8dc39bb46f5fdc9218e3fcc389c112f2e081..a0054bf2a4878529c5b96377dc1110573f068456 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -948,6 +948,15 @@ S: 1150 Ringwood Court
 S: San Jose, California 95131
 S: USA
 
+N: Fernando Fuganti
+E: fuganti@conectiva.com.br
+E: fuganti@netbank.com.br
+D: random kernel hacker, ZF MachZ Watchdog driver
+S: Conectiva S.A.
+S: R. Tocantins, 89 - Cristo Rei
+S: 80050-430 - Curitiba - ParanĂ¡
+S: Brazil
+
 N: Nigel Gamble
 E: nigel@nrg.org
 E: nigel@sgi.com
index f6ea7d6c27e6b86bd09d407f1ad4099722648b35..ff8124ac73b69baca85bf937f5affd6f1f8f6474 100644 (file)
@@ -1,17 +1,19 @@
+
                       LINUX ALLOCATED DEVICES
             Maintained by H. Peter Anvin <device@lanana.org>
 
-                  Last revised: December 29, 2000
+                     Last revised: 3 June 2001
 
 This list is the Linux Device List, the official registry of allocated
 device numbers and /dev directory nodes for the Linux operating
 system.
 
-The latest version of this list is included with the Linux kernel
-sources.  It is also available separately from 
-http://www.kernel.org/pub/linux/docs/device-list/ or
-ftp://ftp.kernel.org/pub/linux/docs/device-list/.  The LaTeX version
-of this document is no longer maintained.
+The latest version of this list is available from
+http://www.lanana.org/docs/device-list/ or
+ftp://ftp.kernel.org/pub/linux/docs/device-list/.  This version may be
+newer than the one distributed with the Linux kernel.
+
+The LaTeX version of this document is no longer maintained.
 
 This document is included by reference into the Filesystem Hierarchy
 Standard (FHS).         The FHS is available from http://www.pathname.com/fhs/.
@@ -38,6 +40,13 @@ reply.
 
          **** DEVICE DRIVERS AUTHORS PLEASE READ THIS ****
 
+THE DEVICE REGISTRY IS OFFICIALLY FROZEN FOR LINUS TORVALDS' KERNEL
+TREE.  At Linus' request, no more allocations will be made official
+for Linus' kernel tree; the 3 June 2001 version of this list is the
+official final version of this registry.  At Alan Cox' request,
+however, the registry will continue to be maintained for the -ac
+series of kernels, and registrations will be accepted.
+
 To have a major number allocated, or a minor number in situations
 where that applies (e.g. busmice), please contact me with the
 appropriate device information.         Also, if you have additional
@@ -391,12 +400,25 @@ Your cooperation is appreciated.
                199 = /dev/scanners/cuecat :CueCat barcode scanner
                200 = /dev/net/tun      TAP/TUN network device
                201 = /dev/button/gulpb Transmeta GULP-B buttons
-               204 = /dev/video/em8300     EM8300 DVD decoder control
-               205 = /dev/video/em8300_mv  EM8300 DVD decoder video
-               206 = /dev/video/em8300_ma  EM8300 DVD decoder audio
-               207 = /dev/video/em8300_sp  EM8300 DVD decoder subpicture
-               208 = /dev/compaq/cpqphpc Compaq PCI Hot Plug Controller
-               209 = /dev/compaq/cpqrid  Compaq Remote Insight Driver
+               204 = /dev/video/em8300         EM8300 DVD decoder control
+               205 = /dev/video/em8300_mv      EM8300 DVD decoder video
+               206 = /dev/video/em8300_ma      EM8300 DVD decoder audio
+               207 = /dev/video/em8300_sp      EM8300 DVD decoder subpicture
+               208 = /dev/compaq/cpqphpc       Compaq PCI Hot Plug Controller
+               209 = /dev/compaq/cpqrid        Compaq Remote Insight Driver
+               210 = /dev/impi/bt      IMPI coprocessor block transfer 
+               211 = /dev/impi/smic    IMPI coprocessor stream interface
+               212 = /dev/watchdogs/0  First watchdog device
+               213 = /dev/watchdogs/1  Second watchdog device
+               214 = /dev/watchdogs/2  Third watchdog device
+               215 = /dev/watchdogs/3  Fourth watchdog device
+               216 = /dev/fujitsu/apanel       Fujitsu/Siemens application panel
+               217 = /dev/ni/natmotn           National Instruments Motion
+               218 = /dev/kchuid       Inter-process chuid control
+               219 = /dev/modems/mwave MWave modem firmware upload
+               220 = /dev/mptctl       Message passing technology (MPT) control
+               221 = /dev/mvista/hssdsi        Montavista PICMG hot swap system driver
+               222 = /dev/mvista/hasi          Montavista PICMG high availability
                240-255                 Reserved for local use
 
  11 char       Raw keyboard device
@@ -430,14 +452,19 @@ Your cooperation is appreciated.
                  1 = /dev/dos_cd1      Second MSCDEX CD-ROM
                    ...
 
- 13 char       PC speaker (OBSOLETE)
-                 0 = /dev/pcmixer      Emulates /dev/mixer
-                 1 = /dev/pcsp         Emulates /dev/dsp (8-bit)
-                 4 = /dev/pcaudio      Emulates /dev/audio
-                 5 = /dev/pcsp16       Emulates /dev/dsp (16-bit)
+ 13 char       Input core
+                 0 = /dev/input/js0    First joystick
+                 1 = /dev/input/js1    Second joystick
+                   ...
+                32 = /dev/input/mouse0 First mouse
+                33 = /dev/input/mouse1 Second mouse
+                   ...
+                63 = /dev/input/mice   Unified mouse
+                64 = /dev/input/event0 First event queue
+                65 = /dev/input/event1 Second event queue
+                   ...
 
-               The current PC speaker driver uses the Open Sound
-               System interface, and these devices are obsolete.
+               Each device type has 5 bits (32 minors).
 
     block      8-bit MFM/RLL/IDE controller
                  0 = /dev/xda          First XT disk whole disk
@@ -664,13 +691,12 @@ Your cooperation is appreciated.
                    ...
                 31 = /dev/fb31         32nd frame buffer
 
-               Backward compatibility aliases {2.6}
-
-                32 = /dev/fb1          Second frame buffer
+               For backwards compatibility {2.6} the following
+               progression is also handled by current kernels:
+                 0 = /dev/fb0
+                32 = /dev/fb1
                    ...
-               224 = /dev/fb7          Eighth frame buffer
-
-               All additional minor numbers are reserved.
+               224 = /dev/fb7
 
     block      Aztech/Orchid/Okano/Wearnes CD-ROM
                  0 = /dev/aztcd        Aztech CD-ROM
@@ -945,7 +971,7 @@ Your cooperation is appreciated.
                  0 = /dev/rd/c0d0      First disk, whole disk
                  8 = /dev/rd/c0d1      Second disk, whole disk
                    ...
-               248 = /dev/rd/c0d15     16th disk, whole disk
+               248 = /dev/rd/c0d15     32nd disk, whole disk
 
                For partitions add:
                  0 = /dev/rd/c?d?      Whole disk
@@ -961,7 +987,7 @@ Your cooperation is appreciated.
                  0 = /dev/rd/c1d0      First disk, whole disk
                  8 = /dev/rd/c1d1      Second disk, whole disk
                    ...
-               248 = /dev/rd/c1d15     16th disk, whole disk
+               248 = /dev/rd/c1d31     32nd disk, whole disk
 
                Partitions are handled as for major 48.
 
@@ -971,7 +997,7 @@ Your cooperation is appreciated.
                  0 = /dev/rd/c2d0      First disk, whole disk
                  8 = /dev/rd/c2d1      Second disk, whole disk
                    ...
-               248 = /dev/rd/c2d15     16th disk, whole disk
+               248 = /dev/rd/c2d31     32nd disk, whole disk
 
  51 char       Baycom radio modem
                  0 = /dev/bc0          First Baycom radio modem
@@ -981,7 +1007,7 @@ Your cooperation is appreciated.
                  0 = /dev/rd/c3d0      First disk, whole disk
                  8 = /dev/rd/c3d1      Second disk, whole disk
                    ...
-               248 = /dev/rd/c3d15     16th disk, whole disk
+               248 = /dev/rd/c3d31     32nd disk, whole disk
 
                Partitions are handled as for major 48.
 
@@ -994,7 +1020,7 @@ Your cooperation is appreciated.
                  0 = /dev/rd/c4d0      First disk, whole disk
                  8 = /dev/rd/c4d1      Second disk, whole disk
                    ...
-               248 = /dev/rd/c4d15     16th disk, whole disk
+               248 = /dev/rd/c4d31     32nd disk, whole disk
 
                Partitions are handled as for major 48.
 
@@ -1016,7 +1042,7 @@ Your cooperation is appreciated.
                  0 = /dev/rd/c5d0      First disk, whole disk
                  8 = /dev/rd/c5d1      Second disk, whole disk
                    ...
-               248 = /dev/rd/c5d15     16th disk, whole disk
+               248 = /dev/rd/c5d31     32nd disk, whole disk
 
                Partitions are handled as for major 48.
 
@@ -1033,7 +1059,7 @@ Your cooperation is appreciated.
                  0 = /dev/rd/c6d0      First disk, whole disk
                  8 = /dev/rd/c6d1      Second disk, whole disk
                    ...
-               248 = /dev/rd/c6d15     16th disk, whole disk
+               248 = /dev/rd/c6d31     32nd disk, whole disk
 
                Partitions are handled as for major 48.
 
@@ -1043,7 +1069,7 @@ Your cooperation is appreciated.
                  0 = /dev/rd/c7d0      First disk, whole disk
                  8 = /dev/rd/c7d1      Second disk, whole disk
                    ...
-               248 = /dev/rd/c7d15     16th disk, whole disk
+               248 = /dev/rd/c7d31     32nd disk, whole disk
 
                Partitions are handled as for major 48.
 
@@ -1541,7 +1567,6 @@ Your cooperation is appreciated.
                Partitions are handled the same way as for the first
                interface (see major number 3).
 
-
  89 char       I2C bus interface
                  0 = /dev/i2c-0        First I2C adapter
                  1 = /dev/i2c-1        Second I2C adapter
@@ -1610,23 +1635,29 @@ Your cooperation is appreciated.
                  1 = /dev/dcxx1        Second capture card
                    ...
 
+    block      IBM S/390 DASD block storage
+                 0 = /dev/dasda        First DASD device, major
+                 1 = /dev/dasda1       First DASD device, block 1
+                 2 = /dev/dasda2       First DASD device, block 2
+                 3 = /dev/dasda3       First DASD device, block 3
+                 4 = /dev/dasdb        Second DASD device, major
+                 5 = /dev/dasdb1       Second DASD device, block 1
+                 6 = /dev/dasdb2       Second DASD device, block 2
+                 7 = /dev/dasdb3       Second DASD device, block 3
+                   ...
+
  95 char       IP filter
                  0 = /dev/ipl          Filter control device/log file
                  1 = /dev/ipnat        NAT control device/log file
                  2 = /dev/ipstate      State information log file
                  3 = /dev/ipauth       Authentication control device/log file
-
-    block      IBM S/390 DASD block storage
-                 0 = /dev/dasd0        First DASD device, major
-                 1 = /dev/dasd0a       First DASD device, block 1
-                 2 = /dev/dasd0b       First DASD device, block 2
-                 3 = /dev/dasd0c       First DASD device, block 3
-                 4 = /dev/dasd1        Second DASD device, major
-                 5 = /dev/dasd1a       Second DASD device, block 1
-                 6 = /dev/dasd1b       Second DASD device, block 2
-                 7 = /dev/dasd1c       Second DASD device, block 3
                    ...         
 
+    block      IBM S/390 VM/ESA minidisk
+                 0 = /dev/mnda         First VM/ESA minidisk
+                 1 = /dev/mndb         Second VM/ESA minidisk
+                   ...
+
  96 char       Parallel port ATAPI tape devices
                  0 = /dev/pt0          First parallel port ATAPI tape
                  1 = /dev/pt1          Second parallel port ATAPI tape
@@ -1635,11 +1666,6 @@ Your cooperation is appreciated.
                129 = /dev/npt1         Second p.p. ATAPI tape, no rewind
                    ...
 
-    block      IBM S/390 VM/ESA minidisk
-                 0 = /dev/msd0         First VM/ESA minidisk
-                 1 = /dev/msd1         Second VM/ESA minidisk
-                   ...
-
  97 char       Parallel port generic ATAPI interface
                  0 = /dev/pg0          First parallel port ATAPI device
                  1 = /dev/pg1          Second parallel port ATAPI device
@@ -1706,6 +1732,16 @@ Your cooperation is appreciated.
                  2 = /dev/tlk2         Third Teletext decoder
                  3 = /dev/tlk3         Fourth Teletext decoder
 
+    block      Compressed block device
+                 0 = /dev/cbd/a        First compressed block device, whole device
+                16 = /dev/cbd/b        Second compressed block device, whole device
+                   ...
+               240 = /dev/cbd/p        16th compressed block device, whole device
+
+               Partitions are handled in the same way as for IDE
+               disks (see major number 3) except that the limit on
+               partitions is 15.
+
 103 char       Arla network file system
                  0 = /dev/xfs0         Arla XFS
 
@@ -1837,11 +1873,30 @@ Your cooperation is appreciated.
                There is currently a device-naming conflict between
                these and PAM multimodems (major 78).
 
+    block      IBM iSeries virtual disk
+                 0 = /dev/iseries/vda  First virtual disk, whole disk
+                 8 = /dev/iseries/vdb  Second virtual disk, whole disk
+                   ...
+               200 = /dev/iseries/vdz  26th virtual disk, whole disk
+               208 = /dev/iseries/vdaa 27th virtual disk, whole disk
+                   ...
+               240 = /dev/iseries/vdaf 32nd virtual disk, whole disk
+
+               Partitions are handled in the same way as for IDE
+               disks (see major number 3) except that the limit on
+               partitions is 7.
+
 113 char       ISI serial card - alternate devices
                  0 = /dev/cum0         Callout device for ttyM0
                  1 = /dev/cum1         Callout device for ttyM1
                    ...
 
+    block      IBM iSeries virtual CD-ROM
+
+                 0 = /dev/iseries/vcda First virtual CD-ROM
+                 1 = /dev/iseries/vcdb Second virtual CD-ROM
+                   ...
+
 114 char       Picture Elements ISE board
                  0 = /dev/ise0         First ISE board
                  1 = /dev/ise1         Second ISE board
@@ -2005,9 +2060,9 @@ Your cooperation is appreciated.
                    ...
 
 162 char       Raw block device interface
-                 0 = /dev/raw          Raw I/O control device
-                 1 = /dev/raw1         First raw I/O device
-                 2 = /dev/raw2         Second raw I/O device
+                 0 = /dev/rawctl       Raw I/O control device
+                 1 = /dev/raw/raw1     First raw I/O device
+                 2 = /dev/raw/raw2     Second raw I/O device
                    ...
 
 163 char       Radio Tech BIM-XXX-RS232 radio modem
@@ -2219,7 +2274,22 @@ Your cooperation is appreciated.
                    ...
                255 = /dev/nvidiactl            Nvidia card control device
 
-196-197                UNASSIGNED
+196 char       Tormenta T1 card
+                 0 = /dev/tor/0                Master control channel for all cards
+                 1 = /dev/tor/1                First DS0
+                 2 = /dev/tor/2                Second DS0
+                   ...
+                48 = /dev/tor/48               48th DS0
+                49 = /dev/tor/49               First pseudo-channel
+                50 = /dev/tor/50               Second pseudo-channel
+                   ...
+
+197 char       OpenTNF tracing facility
+                 0 = /dev/tnf/t0               Trace 0 data extraction
+                 1 = /dev/tnf/t1               Trace 1 data extraction
+                   ...
+               128 = /dev/tnf/status           Tracing facility status
+               130 = /dev/tnf/trace            Tracing device
 
 198 char       Total Impact TPMP2 quad coprocessor PCI card
                  0 = /dev/tpmp2/0              First card
@@ -2288,6 +2358,9 @@ Your cooperation is appreciated.
                 16 = /dev/ttyAM0               ARM "AMBA" serial port 0
                    ...
                 31 = /dev/ttyAM15              ARM "AMBA" serial port 15
+                32 = /dev/ttyDB0               DataBooster serial port 0
+                   ...
+                39 = /dev/ttyDB7               DataBooster serial port 7
 
 205 char       Low-density serial ports (alternate device)
                  0 = /dev/culu0                Callout device for ttyLU0
@@ -2309,6 +2382,9 @@ Your cooperation is appreciated.
                 16 = /dev/cuam0                Callout device for ttyAM0
                    ...
                 31 = /dev/cuam15               Callout device for ttyAM15
+                32 = /dev/cudb0                Callout device for ttyDB0
+                   ...
+                39 = /dev/cudb7                Callout device for ttyDB7
 
 206 char       OnStream SC-x0 tape devices
                  0 = /dev/osst0                First OnStream SCSI tape, mode 0
@@ -2450,7 +2526,59 @@ Your cooperation is appreciated.
                  1 = /dev/cuy1                 Callout device for ttyY1
                    ...
 
-226-239                UNASSIGNED
+226 char       Direct Rendering Infrastructure (DRI)
+                 0 = /dev/dri/card0            First graphics card
+                 1 = /dev/dri/card1            Second graphics card
+                   ...
+
+227 char       IBM 3270 terminal block-mode access
+                 0 = /dev/3270/tub             Controlling interface
+                 1 = /dev/3270/tub1            First 3270 terminal
+                 2 = /dev/3270/tub2            Second 3270 terminal
+                   ...
+
+228 char       IBM 3270 terminal Unix tty access
+                 1 = /dev/3270/tty1            First 3270 terminal
+                 2 = /dev/3270/tty2            Seconds 3270 terminal
+                   ...
+
+229 char       IBM iSeries virtual console
+                 0 = /dev/iseries/vtty0        First console port
+                 1 = /dev/iseries/vtty1        Second console port
+                   ...
+
+230 char       IBM iSeries virtual tape
+                 0 = /dev/iseries/vt0          First virtual tape, mode 0
+                 1 = /dev/iseries/vt1          Second virtual tape, mode 0
+                   ...
+                32 = /dev/iseries/vt0l         First virtual tape, mode 1
+                33 = /dev/iseries/vt1l         Second virtual tape, mode 1
+                   ...
+                64 = /dev/iseries/vt0m         First virtual tape, mode 2
+                65 = /dev/iseries/vt1m         Second virtual tape, mode 2
+                   ...
+                96 = /dev/iseries/vt0a         First virtual tape, mode 3
+                97 = /dev/iseries/vt1a         Second virtual tape, mode 3
+                     ...
+               128 = /dev/iseries/nvt0         First virtual tape, mode 0, no rewind
+               129 = /dev/iseries/nvt1         Second virtual tape, mode 0, no rewind
+                   ...
+               160 = /dev/iseries/nvt0l        First virtual tape, mode 1, no rewind
+               161 = /dev/iseries/nvt1l        Second virtual tape, mode 1, no rewind
+                   ...
+               192 = /dev/iseries/nvt0m        First virtual tape, mode 2, no rewind
+               193 = /dev/iseries/nvt1m        Second virtual tape, mode 2, no rewind
+                   ...
+               224 = /dev/iseries/nvt0a        First virtual tape, mode 3, no rewind
+               225 = /dev/iseries/nvt1a        Second virtual tape, mode 3, no rewind
+                   ...
+
+               "No rewind" refers to the omission of the default
+               automatic rewind on device close.  The MTREW or MTOFFL
+               ioctl()'s can be used to rewind the tape regardless of
+               the device used to access it.
+
+231-239                UNASSIGNED
 
 240-254                LOCAL/EXPERIMENTAL USE
 
@@ -2647,3 +2775,4 @@ for the slaves; the slaves are named with decimal integers (/dev/pts/#
 in our notation).  This removes the problem of exhausting the
 namespace and enables the kernel to automatically create the device
 nodes for the slaves on demand using the "devpts" filesystem.
+
diff --git a/Documentation/parisc/mm b/Documentation/parisc/mm
deleted file mode 100644 (file)
index d53b295..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-
-The current state of Linux/PA-RISC mm is BROKEN.
-
-Someone needs to sit down and thoroughly rewrite all the cache flushing
-macro definitions.  Here are some of the problems, followed by what I
-think needs to be done about them.
-
-(1) We're using fdce / fice everywhere.  This has to stop (except in
-the routines which flush the entire cache).  The right instructions to
-be using are fdc/fic.
-
-(2) fdc/fic will throw exceptions if the address they reference isn't
-mapped.  Therefore we need to check the page is mapped before flushing
-(we're guaranteed not to have the page dirty if we don't have a software
-mapping for it any longer, right?)
-
-(3) the flush macros are right now tunnelled down to one routine to flush
-the data cache and one routine to flush the insn cache.  this is wrong.
-we should take hints from how we're called and optimise our routines
-accordingly.
-
-(4) fdc/fic actually take space register arguments.  fic takes an 3-bit sr
-argument and fdc takes a 2-bit sr argument.  right now, there's a lot of
-pissing about with %sr1 and all the macros use %sr1.  This is crazy.  We
-normally _know_ what's being referred to, and it's the current task.  So
-if we want to flush that, just use %sr3.  If it happens to be kernel,
-use %sr0 for fdc and %sr4 for fic.
-
-(5) we need to write flush_kernel_dcache_range and use it on kernel
-addresses.  all the macros are defined to work on the _current task's_
-virtual address space.
index f5df3bb5c1153779dccbd7077580807f04a918f9..2691c9ba09160a57575e1620b28ae466f1177af4 100644 (file)
@@ -1,5 +1,5 @@
 This file contains some additional information for the Philips webcams.
-E-mail: webcam@smcc.demon.nl                        Last updated: 2001-04-25
+E-mail: webcam@smcc.demon.nl                        Last updated: 2001-07-27
 
 The main webpage for the Philips driver is http://www.smcc.demon.nl/webcam/.
 It contains a lot of extra information, a FAQ, and the binary plugin
@@ -29,10 +29,9 @@ fps
 
 palette
    Specifies the desired colour order that should be delivered by read() and
-   mmap(). The string can be one of bgr24, rgb24, rgb32, bgr32, yuyv,
-   yuv420, yuv420p. If the tool you use produces odd colours (more
-   specificly, red and blue are swapped), try palette=bgr24 or
-   palette=rgb24.
+   mmap(). The string can be one of yuv420 or yuv420p; however, yuv420 will
+   be phased out, leaving only yuv420p, so this option will disappear
+   entirely.
 
    Only the native yuv420/yuv420p format is supported by the in kernel driver. 
    If you want to use other formats with in-kernel conversion download the
@@ -73,7 +72,7 @@ power_save
 
 compression (only useful with the plugin)
    With this option you can control the compression factor that the camera
-   use to squeeze the image through the USB bus. You can set the 
+   uses to squeeze the image through the USB bus. You can set the 
    parameter between 0 and 3:
      0 = prefer uncompressed images; if the requested mode is not available
          in an uncompressed format, the driver will silently switch to low
@@ -83,7 +82,7 @@ compression (only useful with the plugin)
      3 = high compression.
       
    High compression takes less bandwidth of course, but it could also
-   introduce some unwanted artefacts. The default is 2, medium compression. 
+   introduce some unwanted artefacts. The default is 2, medium compression.
    See the FAQ on the website for an overview of which modes require
    compression.
       
@@ -91,7 +90,6 @@ compression (only useful with the plugin)
    The 645 and 646 have fixed compression parameters.      
 
 trace
-
    In order to better detect problems, it is now possible to turn on a
    'trace' of some of the calls the module makes; it logs all items in your
    kernel log at debug level.
index bfd7a51f71fe0c706846ca7c40720f078a87717e..b28e20b640dbba42fca1dae99fd82117eaee32e8 100644 (file)
@@ -227,6 +227,12 @@ M: axboe@suse.de
 L:     linux-kernel@vger.kernel.org
 S:     Maintained
 
+BLUETOOTH SUBSYSTEM (BlueZ)
+P:     Maxim Krasnyansky
+M:     maxk@qualcomm.com
+W:     http://bluez.sf.net
+S:     Maintained
+
 BTTV VIDEO4LINUX DRIVER
 P:     Gerd Knorr
 M:     kraxel@goldbach.in-berlin.de
@@ -500,6 +506,13 @@ M: Remy.Card@linux.org
 L:     linux-kernel@vger.kernel.org
 S:     Maintained
 
+FARSYNC SYNCHRONOUS DRIVER
+P:     Bob Dunlop
+M:     rjd@xyzzy.clara.co.uk
+M:     bob.dunlop@farsite.co.uk
+W:     http://www.farsite.co.uk/
+S:     Supported
+
 FILE LOCKING (flock() and fcntl()/lockf())
 P:     Matthew Wilcox
 M:     matthew@wil.cx
@@ -637,7 +650,7 @@ S:      Supported
 IDE DRIVER [GENERAL]
 P:     Andre Hedrick
 M:     andre@linux-ide.org
-M:     ahedrick@atipa.com
+M:     andre@aslab.com
 M:     andre@suse.com
 L:     linux-kernel@vger.kernel.org
 W:     http://www.kernel.org/pub/linux/kernel/people/hedrick/
@@ -693,6 +706,12 @@ M: andreas.bombe@munich.netsurf.de
 L:     linux1394-devel@lists.sourceforge.net
 S:     Maintained
 
+IMS TWINTURBO FRAMEBUFFER DRIVER
+P:     Paul Mundt
+M:     lethal@chaoticdreams.org
+L:     linux-fbdev-devel@lists.sourceforge.net
+S:     Maintained
+
 INTEL APIC/IOAPIC, LOWLEVEL X86 SMP SUPPORT
 P:     Ingo Molnar
 M:     mingo@redhat.com
@@ -1601,6 +1620,13 @@ W:       http://www.qsl.net/dl1bke/
 L:     linux-hams@vger.kernel.org
 S:     Maintained
 
+ZF MACHZ WATCHDOG
+P:     Fernando Fuganti
+M:     fuganti@conectiva.com.br
+M:     fuganti@netbank.com.br
+W:     http://cvs.conectiva.com.br/drivers/ZFL-watchdog/
+S:     Maintained
+
 ZR36120 VIDEO FOR LINUX DRIVER
 P:     Pauline Middelink
 M:     middelin@polyware.nl
@@ -1608,12 +1634,6 @@ W:       http://www.polyware.nl/~middelin/En/hobbies.html
 W:     http://www.polyware.nl/~middelin/hobbies.html
 S:     Maintained
 
-Bluetooth Subsystem (BlueZ)
-P:     Maxim Krasnyansky
-M:     maxk@qualcomm.com
-W:     http://bluez.sf.net
-S:     Maintained
-
 THE REST
 P:     Linus Torvalds
 S:     Buried alive in reporters
index 11bd772537014b7620d990f3945a8ec67064a148..595aaffd9bfc0b634acbf27ce5abab28dbad93c8 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
 SUBLEVEL = 9
-EXTRAVERSION =-pre1
+EXTRAVERSION =-pre2
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
index 08eac965fd436504c071446d02e7f7a09da68496..9197447e1f97202a65a2692f477ad13c4d7ca326 100644 (file)
@@ -483,8 +483,8 @@ if [ "$CONFIG_VT" = "y" ]; then
         "$CONFIG_ARCH_INTEGRATOR" = "y" -o \
         "$CONFIG_ARCH_TBOX" = "y" -o       \
         "$CONFIG_ARCH_CLPS7500" = "y" -o   \
-       "$CONFIG_ARCH_P720T" = "y" -o      \
-       "$CONFIG_ARCH_ANAKIN" = "y" ]; then
+        "$CONFIG_ARCH_P720T" = "y" -o      \
+        "$CONFIG_ARCH_ANAKIN" = "y" ]; then
       define_bool CONFIG_PC_KEYMAP y
    fi
    if [ "$CONFIG_ARCH_ACORN" != "y" -a "$CONFIG_ARCH_EBSA110" != "y" ]; then
diff --git a/arch/arm/def-configs/pleb b/arch/arm/def-configs/pleb
new file mode 100644 (file)
index 0000000..ebecfa8
--- /dev/null
@@ -0,0 +1,535 @@
+#
+# Automatically generated by make menuconfig: don't edit
+#
+CONFIG_ARM=y
+# CONFIG_EISA is not set
+# CONFIG_SBUS is not set
+# CONFIG_MCA is not set
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+# CONFIG_OBSOLETE is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_ARCA5K is not set
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_RPC is not set
+CONFIG_ARCH_SA1100=y
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_ANAKIN is not set
+
+#
+# Archimedes/A5000 Implementations
+#
+# CONFIG_ARCH_ARC is not set
+# CONFIG_ARCH_A5K is not set
+
+#
+# Footbridge Implementations
+#
+# CONFIG_ARCH_CATS is not set
+# CONFIG_ARCH_PERSONAL_SERVER is not set
+# CONFIG_ARCH_EBSA285_ADDIN is not set
+# CONFIG_ARCH_EBSA285_HOST is not set
+# CONFIG_ARCH_NETWINDER is not set
+
+#
+# SA11x0 Implementations
+#
+# CONFIG_SA1100_ASSABET is not set
+# CONFIG_ASSABET_NEPONSET is not set
+# CONFIG_SA1100_BRUTUS is not set
+# CONFIG_SA1100_CERF is not set
+# CONFIG_SA1100_BITSY is not set
+# CONFIG_SA1100_EXTENEX1 is not set
+# CONFIG_SA1100_FLEXANET is not set
+# CONFIG_SA1100_FREEBIRD is not set
+# CONFIG_SA1100_GRAPHICSCLIENT is not set
+# CONFIG_SA1100_JORNADA720 is not set
+# CONFIG_SA1100_HUW_WEBPANEL is not set
+# CONFIG_SA1100_ITSY is not set
+# CONFIG_SA1100_LART is not set
+# CONFIG_SA1100_NANOENGINE is not set
+# CONFIG_SA1100_OMNIMETER is not set
+# CONFIG_SA1100_PANGOLIN is not set
+CONFIG_SA1100_PLEB=y
+# CONFIG_SA1100_SHERMAN is not set
+# CONFIG_SA1100_PFS168 is not set
+# CONFIG_SA1100_VICTOR is not set
+# CONFIG_SA1100_XP860 is not set
+# CONFIG_SA1100_YOPY is not set
+# CONFIG_SA1100_USB is not set
+# CONFIG_SA1100_USB_NETLINK is not set
+# CONFIG_SA1100_USB_CHAR is not set
+
+#
+# CLPS711X/EP721X Implementations
+#
+# CONFIG_ARCH_P720T is not set
+# CONFIG_ARCH_ACORN is not set
+# CONFIG_FOOTBRIDGE is not set
+# CONFIG_FOOTBRIDGE_HOST is not set
+# CONFIG_FOOTBRIDGE_ADDIN is not set
+CONFIG_CPU_32=y
+# CONFIG_CPU_26 is not set
+# CONFIG_CPU_32v3 is not set
+CONFIG_CPU_32v4=y
+# CONFIG_CPU_ARM610 is not set
+# CONFIG_CPU_ARM710 is not set
+# CONFIG_CPU_ARM720T is not set
+# CONFIG_CPU_ARM920T is not set
+# CONFIG_CPU_ARM1020 is not set
+# CONFIG_CPU_SA110 is not set
+CONFIG_CPU_SA1100=y
+CONFIG_DISCONTIGMEM=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+
+#
+# General setup
+#
+# CONFIG_PCI is not set
+# CONFIG_ISA is not set
+# CONFIG_ISA_DMA is not set
+CONFIG_CPU_FREQ=y
+# CONFIG_HOTPLUG is not set
+# CONFIG_PCMCIA is not set
+CONFIG_NET=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_FASTFPE is not set
+CONFIG_KCORE_ELF=y
+# CONFIG_KCORE_AOUT is not set
+CONFIG_BINFMT_AOUT=y
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_PM is not set
+# CONFIG_APM is not set
+# CONFIG_ARTHUR is not set
+CONFIG_CMDLINE="console=ttySA0,9600"
+# CONFIG_PFS168_CMDLINE is not set
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_AMDSTD is not set
+# CONFIG_MTD_SHARP is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_JEDEC is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_SUN_UFLASH is not set
+# CONFIG_MTD_NORA is not set
+# CONFIG_MTD_PNC2000 is not set
+# CONFIG_MTD_RPXLITE is not set
+# CONFIG_MTD_SC520CDP is not set
+# CONFIG_MTD_NETSC520 is not set
+# CONFIG_MTD_SBC_GXX is not set
+# CONFIG_MTD_ELAN_104NC is not set
+# CONFIG_MTD_SA1100 is not set
+# CONFIG_MTD_SA1100_REDBOOT_PARTITIONS is not set
+# CONFIG_MTD_SA1100_BOOTLDR_PARTITIONS is not set
+# CONFIG_MTD_DC21285 is not set
+# CONFIG_MTD_IQ80310 is not set
+# CONFIG_MTD_DBOX2 is not set
+# CONFIG_MTD_CSTM_MIPS_IXX is not set
+# CONFIG_MTD_CFI_FLAGADM is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_MIXMEM is not set
+# CONFIG_MTD_OCTAGON is not set
+# CONFIG_MTD_VMAX is not set
+# CONFIG_MTD_OCELOT is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_DOC1000 is not set
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOCPROBE is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# Plug and Play configuration
+#
+# CONFIG_PNP is not set
+# CONFIG_ISAPNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+# CONFIG_BLK_DEV_MD is not set
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
+# CONFIG_BLK_DEV_LVM is not set
+
+#
+# Networking options
+#
+CONFIG_PACKET=m
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_FILTER is not set
+CONFIG_UNIX=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+CONFIG_INET_ECN=y
+CONFIG_SYN_COOKIES=y
+# CONFIG_IPV6 is not set
+# CONFIG_KHTTPD is not set
+# CONFIG_ATM is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+CONFIG_DUMMY=m
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+# CONFIG_NET_ETHERNET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_ACENIC_OMIT_TIGON_I is not set
+# CONFIG_MYRI_SBUS is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PLIP is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_NET_FC is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# ATA/IDE/MFM/RLL support
+#
+# CONFIG_IDE is not set
+# CONFIG_BLK_DEV_IDE_MODES is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI support
+#
+# CONFIG_SCSI is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+# CONFIG_I2O_BLOCK is not set
+# CONFIG_I2O_LAN is not set
+# CONFIG_I2O_SCSI is not set
+# CONFIG_I2O_PROC is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input core support
+#
+# CONFIG_INPUT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL is not set
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_SERIAL_21285 is not set
+# CONFIG_SERIAL_21285_OLD is not set
+# CONFIG_SERIAL_21285_CONSOLE is not set
+CONFIG_SERIAL_SA1100=y
+# CONFIG_SERIAL_SA1100_OLD is not set
+CONFIG_SERIAL_SA1100_CONSOLE=y
+CONFIG_SA1100_DEFAULT_BAUDRATE=9600
+# CONFIG_SERIAL_AMBA is not set
+# CONFIG_SERIAL_AMBA_CONSOLE is not set
+# CONFIG_SERIAL_CLPS711X is not set
+# CONFIG_SERIAL_CLPS711X_CONSOLE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+# CONFIG_UCB1200 is not set
+# CONFIG_TOUCHSCREEN_UCB1200 is not set
+# CONFIG_AUDIO_UCB1200 is not set
+# CONFIG_ADC_UCB1200 is not set
+# CONFIG_TOUCHSCREEN_BITSY is not set
+CONFIG_PROFILER=y
+# CONFIG_PFS168_SPI is not set
+# CONFIG_PFS168_DTMF is not set
+# CONFIG_PFS168_MISC is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_MOUSE is not set
+
+#
+# Joysticks
+#
+# CONFIG_JOYSTICK is not set
+# CONFIG_QIC02_TAPE is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_INTEL_RNG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+CONFIG_SA1100_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# File systems
+#
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_ADFS_FS_RW is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_UMSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+# CONFIG_CRAMFS is not set
+CONFIG_TMPFS=y
+# CONFIG_RAMFS is not set
+# CONFIG_ISO9660_FS is not set
+# CONFIG_JOLIET is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_NTFS_FS is not set
+# CONFIG_NTFS_RW is not set
+# CONFIG_HPFS_FS is not set
+CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_MOUNT is not set
+# CONFIG_DEVFS_DEBUG is not set
+CONFIG_DEVPTS_FS=y
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_EXT2_FS=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
+
+#
+# Network File Systems
+#
+# CONFIG_CODA_FS is not set
+# CONFIG_NFS_FS is not set
+# CONFIG_NFS_V3 is not set
+# CONFIG_ROOT_NFS is not set
+# CONFIG_NFSD is not set
+# CONFIG_NFSD_V3 is not set
+# CONFIG_SUNRPC is not set
+# CONFIG_LOCKD is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_SMB_NLS is not set
+# CONFIG_NLS is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BLUEZ is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_NO_FRAME_POINTER is not set
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_INFO is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_NO_PGT_CACHE is not set
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_DC21285_PORT is not set
+# CONFIG_DEBUG_CLPS711X_UART2 is not set
index e9db5da41c948005a3eb8b10049349d6ed66dfbb..54190abbb6a6e879731271b84de6b0b5d2f385f3 100644 (file)
@@ -248,12 +248,12 @@ __create_page_tables:
                /*
                 * Ensure that the first section of RAM is present.
                 * we assume that:
-                *  1. the RAM is aligned to a 128MB boundary
-                *  2. the kernel is executing in the same 128MB chunk
+                *  1. the RAM is aligned to a 32MB boundary
+                *  2. the kernel is executing in the same 32MB chunk
                 *     as the start of RAM.
                 */
-               bic     r0, r0, #0x07f00000 >> 18       @ round down
-               and     r2, r5, #0xf8000000             @ round down
+               bic     r0, r0, #0x01f00000 >> 18       @ round down
+               and     r2, r5, #0xfe000000             @ round down
                add     r3, r8, r2                      @ flags + rambase
                str     r3, [r0]
 
index 5c9d87a7d00be45bde4921250d174dae818cc580..ac24e4bf546eaef58ea577b3d30e465e2f6d944e 100644 (file)
@@ -124,7 +124,7 @@ void machine_power_off(void)
                pm_power_off();
 }
 
-void machine_restart(char * __unused)
+void machine_restart(void * __unused)
 {
        /*
         * Clean and disable cache, and turn off interrupts
index 7c0177a275a01d40d344a01559e3fde5cd7d7421..4361fabc727c557da2f351d64b5a998751a9580d 100644 (file)
@@ -28,7 +28,7 @@ extern void genarch_init_irq(void);
 
 static void __init
 fixup_anakin(struct machine_desc *desc, struct param_struct *unused,
-            char **cmdline, struct meminfo *mi)
+             char **cmdline, struct meminfo *mi)
 {
        ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
        setup_ramdisk(1, 0, 0, CONFIG_BLK_DEV_RAM_SIZE);
index 57d2daf4624d0d172ebd4bc6c8d431bf8f26ffaf..9d6d8299477d118592db509a544588736f9dee58 100644 (file)
@@ -39,7 +39,7 @@ EXPORT_SYMBOL(SCR_value);
 
 static int __init assabet_init(void)
 {
-       if (machine_has_neponset()) {
+       if (machine_is_assabet() && machine_has_neponset()) {
                /*
                 * Angel sets this, but other bootloaders may not.
                 *
@@ -167,6 +167,8 @@ static struct map_desc assabet_io_desc[] __initdata = {
   { 0xe8000000, 0x00000000, 0x02000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 0 */
   { 0xf1000000, 0x12000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* Board Control Register */
   { 0xf2800000, 0x4b800000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* MQ200 */
+  /*  f3000000 - neponset system registers */
+  /*  f4000000 - neponset SA1111 registers */
   LAST_DESC
 };
 
index dc454d89cc707fb388787c3dc165977bb85036b4..ebb8710e24915c0d6b9aad8b7472e8cd7d69835c 100644 (file)
@@ -51,9 +51,9 @@ static void bitsy_uart_set_mctrl(struct uart_port *port, u_int mctrl)
 {
        if (port->mapbase == _Ser3UTCR0) {
                if (mctrl & TIOCM_RTS)
-                       GPSR = GPIO_BITSY_COM_RTS;
-               else
                        GPCR = GPIO_BITSY_COM_RTS;
+               else
+                       GPSR = GPIO_BITSY_COM_RTS;
        }
 }
 
@@ -63,9 +63,9 @@ static int bitsy_uart_get_mctrl(struct uart_port *port)
 
        if (port->mapbase == _Ser3UTCR0) {
                int gplr = GPLR;
-               if (!(gplr & GPIO_BITSY_COM_DCD))
+               if (gplr & GPIO_BITSY_COM_DCD)
                        ret &= ~TIOCM_CD;
-               if (!(gplr & GPIO_BITSY_COM_CTS))
+               if (gplr & GPIO_BITSY_COM_CTS)
                        ret &= ~TIOCM_CTS;
        }
 
@@ -150,7 +150,7 @@ static struct sa1100_port_fns bitsy_port_fns __initdata = {
 static struct map_desc bitsy_io_desc[] __initdata = {
  /* virtual     physical    length      domain     r  w  c  b */
   { 0xe8000000, 0x00000000, 0x02000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 0 */
-  { 0xf0000000, 0x49000000, 0x01000000, DOMAIN_IO, 1, 1, 0, 0 }, /* EGPIO 0 */
+  { 0xf0000000, 0x49000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* EGPIO 0 */
   { 0xf1000000, 0x10000000, 0x02000000, DOMAIN_IO, 1, 1, 0, 0 }, /* static memory bank 2 */
   { 0xf3000000, 0x40000000, 0x02000000, DOMAIN_IO, 1, 1, 0, 0 }, /* static memory bank 4 */
   LAST_DESC
index 28eab578ef5e2983373483c91e7f5ed6876d6997..b236133e437e01642d5eed8d7e09b3e71f7110c2 100644 (file)
@@ -3,7 +3,7 @@
  *
  *  Copyright (C) 2001 Russell King
  *
- *  $Id: cpu-sa1110.c,v 1.2 2001/07/24 20:25:25 rmk Exp $
+ *  $Id: cpu-sa1110.c,v 1.3 2001/08/12 15:41:53 rmk Exp $
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -48,7 +48,7 @@ struct sdram_params {
        u_short refresh;        /* refresh time for array (us)   */
 };
 
-static struct sdram_params tc59sm716_cl2_params = {
+static struct sdram_params tc59sm716_cl2_params __initdata = {
        rows:               12,
        tck:                10,
        trcd:               20,
@@ -58,7 +58,7 @@ static struct sdram_params tc59sm716_cl2_params = {
        cas_latency:         2,
 };
 
-static struct sdram_params tc59sm716_cl3_params = {
+static struct sdram_params tc59sm716_cl3_params __initdata = {
        rows:               12,
        tck:                 8,
        trcd:               20,
@@ -68,6 +68,8 @@ static struct sdram_params tc59sm716_cl3_params = {
        cas_latency:         3,
 };
 
+static struct sdram_params sdram_params;
+
 /*
  * Given a period in ns and frequency in khz, calculate the number of
  * cycles of frequency in period.  Note that we round up to the next
@@ -205,7 +207,14 @@ static int
 sdram_notifier(struct notifier_block *nb, unsigned long val, void *data)
 {
        struct cpufreq_info *ci = data;
-       struct sdram_params *sdram = &tc59sm716_cl3_params;
+       struct sdram_params *sdram = &sdram_params;
+
+       /* were we initialised? */
+       if (sdram->cas_latency == 0) {
+               struct cpufreq_minmax *m = data;
+               m->min_freq = m->max_freq = m->cur_freq;
+               return 0;
+       }
 
        switch (val) {
        case CPUFREQ_MINMAX:
@@ -247,11 +256,24 @@ static struct notifier_block sa1110_clkchg_block = {
 
 static int __init sa1110_sdram_init(void)
 {
-       struct sdram_params *sdram = &tc59sm716_cl3_params;
+       struct sdram_params *sdram = NULL;
        unsigned int cur_freq = cpufreq_get(smp_processor_id());
+       int ret = -ENODEV;
+
+       if (machine_is_assabet())
+               sdram = &tc59sm716_cl3_params;
 
-       sdram_update_timing(cur_freq, sdram);
-       sdram_update_refresh(cur_freq, sdram);
+       if (sdram) {
+               printk(KERN_DEBUG "SDRAM: tck: %d trcd: %d trp: %d"
+                       " twr: %d refresh: %d cas_latency: %d",
+                       sdram->tck, sdram->trcd, sdram->trp,
+                       sdram->twr, sdram->refresh, sdram->cas_latency);
+
+               memcpy(&sdram_params, sdram, sizeof(sdram_params));
+
+               sdram_update_timing(cur_freq, &sdram_params);
+               sdram_update_refresh(cur_freq, &sdram_params);
+       }
 
        return cpufreq_register_notifier(&sa1110_clkchg_block);
 }
index 8aab7aaaffe572b7d1d5af55788d552e0e84105f..b69656de7e17feeaffdd1ac013513e1008e78d38 100644 (file)
@@ -115,7 +115,7 @@ static void process_dma(sa1100_dma_t * dma)
        for (;;) {
                buf = dma->tail;
 
-               if (!buf) {
+               if (!buf || dma->stopped) {
                        /* no more data available */
                        DPRINTK("process: no more buf (dma %s)\n",
                                dma->curr ? "active" : "inactive");
@@ -388,11 +388,16 @@ int sa1100_dma_get_current(dmach_t channel, void **buf_id, dma_addr_t *addr)
                        *addr = buf->dma_ptr;
                DPRINTK("curr_pos: b=%#x a=%#x\n", (int)dma->curr->id, *addr);
                ret = 0;
+       } else if (dma->tail && dma->stopped) {
+               dma_buf_t *buf = dma->tail;
+               if (buf_id)
+                       *buf_id = buf->id;
+               *addr = buf->dma_ptr;
+               ret = 0;
        } else {
                if (buf_id)
                        *buf_id = NULL;
                *addr = 0;
-               DPRINTK("curr_pos: spinning\n");
                ret = -ENXIO;
        }
        local_irq_restore(flags);
@@ -403,11 +408,36 @@ int sa1100_dma_get_current(dmach_t channel, void **buf_id, dma_addr_t *addr)
 int sa1100_dma_stop(dmach_t channel)
 {
        sa1100_dma_t *dma = &dma_chan[channel];
+       int flags;
 
        if (channel_is_sa1111_sac(channel))
                return sa1111_dma_stop(channel);
 
+       if (dma->stopped)
+               return 0;
+       local_irq_save(flags);
+       dma->stopped = 1;
+       /*
+        * Stop DMA and tweak state variables so everything could restart
+        * from there when resume/wakeup occurs.
+        */
        dma->regs->ClrDCSR = DCSR_RUN | DCSR_IE;
+       if (dma->curr) {
+               dma_buf_t *buf = dma->curr;
+               if (dma->spin_ref <= 0) {
+                       dma_addr_t curpos;
+                       sa1100_dma_get_current(channel, NULL, &curpos);
+                       buf->size += buf->dma_ptr - curpos;
+                       buf->dma_ptr = curpos;
+               }
+               buf->ref = 0;
+               dma->tail = buf;
+               dma->curr = NULL;
+       }
+       dma->spin_ref = 0;
+       dma->regs->ClrDCSR = DCSR_STRTA|DCSR_STRTB;
+       process_dma(dma);
+       local_irq_restore(flags);
        return 0;
 }
 
@@ -422,7 +452,15 @@ int sa1100_dma_resume(dmach_t channel)
        if (channel_is_sa1111_sac(channel))
                return sa1111_dma_resume(channel);
 
-       dma->regs->SetDCSR = DCSR_RUN | DCSR_IE;
+       if (dma->stopped) {
+               int flags;
+               save_flags_cli(flags);
+               dma->regs->ClrDCSR = DCSR_STRTA|DCSR_STRTB|DCSR_RUN|DCSR_IE;
+               dma->stopped = 0;
+               dma->spin_ref = 0;
+               process_dma(dma);
+               restore_flags(flags);
+       }
        return 0;
 }
 
@@ -445,9 +483,9 @@ int sa1100_dma_flush_all(dmach_t channel)
        if (!buf)
                buf = dma->tail;
        dma->head = dma->tail = dma->curr = NULL;
+       dma->stopped = 0;
        dma->spin_ref = 0;
-       if (dma->spin_size)
-               process_dma(dma);
+       process_dma(dma);
        local_irq_restore(flags);
        while (buf) {
                next_buf = buf->next;
@@ -502,7 +540,8 @@ EXPORT_SYMBOL(sa1100_free_dma);
 
 int sa1100_dma_sleep(dmach_t channel)
 {
-       sa1100_dma_t *dma = &dma_chan[channel];
+        sa1100_dma_t *dma = &dma_chan[channel];
+       int orig_state;
 
        if ((unsigned)channel >= MAX_SA1100_DMA_CHANNELS || !dma->in_use)
                return -EINVAL;
@@ -515,28 +554,17 @@ int sa1100_dma_sleep(dmach_t channel)
                return 0;
        }
 
-       /*
-        * Stop DMA and tweak state variables so everything could restart
-        * from there when wakeup occurs.
-        */
-       dma->regs->ClrDCSR = DCSR_RUN | DCSR_IE;
-       if (dma->curr) {
-               dma_buf_t *buf = dma->curr;
-               dma_addr_t curpos;
-               sa1100_dma_get_current(channel, NULL, &curpos);
-               buf->size += buf->dma_ptr - curpos;
-               buf->dma_ptr = curpos;
-               buf->ref = 0;
-               dma->tail = buf;
-               dma->curr = NULL;
-       }
+       orig_state = dma->stopped;
+       sa1100_dma_stop(channel);
+       dma->regs->ClrDCSR = DCSR_RUN | DCSR_IE | DCSR_STRTA | DCSR_STRTB;
+       dma->stopped = orig_state;
        dma->spin_ref = 0;
        return 0;
 }
 
 int sa1100_dma_wakeup(dmach_t channel)
 {
-       sa1100_dma_t *dma = &dma_chan[channel];
+        sa1100_dma_t *dma = &dma_chan[channel];
        dma_regs_t *regs;
        int flags;
 
index 7ce7fe346fa9b97eb7c29c91fa9158160de099a6..23cfef671f902cad4ae3bbf8136c21efaf193661 100644 (file)
@@ -236,7 +236,6 @@ int sa1111_sac_request_dma(dmach_t *channel, const char *device_id,
        dma->device_id = device_id;
        dma->callback = NULL;
        dma->spin_size = 0;
-       dma->ready = 1;
 
        return 0;
 }
index 0dfecb6ce65a0d56dbac92bed4f5525a38344865..22b08cd84981b29a99a557844f4f87e1f257b9b3 100644 (file)
@@ -34,7 +34,7 @@ typedef struct {
        dma_buf_t *head;        /* where to insert buffers */
        dma_buf_t *tail;        /* where to remove buffers */
        dma_buf_t *curr;        /* buffer currently DMA'ed */
-       int ready;              /* 1 if DMA can occur */
+       int stopped;            /* 1 if DMA is stalled */
        dma_regs_t *regs;       /* points to appropriate DMA registers */
        int irq;                /* IRQ used by the channel */
        dma_callback_t callback; /* ... to call when buffers are done */
index edf9d0dbdc244cf2fcaff3690a10868be39f7620..08ac54616c0a61b085cef958975bac6901221003 100644 (file)
@@ -160,10 +160,10 @@ static struct map_desc standard_io_desc[] __initdata = {
  /* virtual     physical    length      domain     r  w  c  b */
   { 0xf6000000, 0x20000000, 0x01000000, DOMAIN_IO, 1, 1, 0, 0 }, /* PCMCIA0 IO */
   { 0xf7000000, 0x30000000, 0x01000000, DOMAIN_IO, 1, 1, 0, 0 }, /* PCMCIA1 IO */
-  { 0xf8000000, 0x80000000, 0x02000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCM */
-  { 0xfa000000, 0x90000000, 0x02000000, DOMAIN_IO, 0, 1, 0, 0 }, /* SCM */
-  { 0xfc000000, 0xa0000000, 0x02000000, DOMAIN_IO, 0, 1, 0, 0 }, /* MER */
-  { 0xfe000000, 0xb0000000, 0x01f00000, DOMAIN_IO, 0, 1, 0, 0 }, /* LCD + DMA */
+  { 0xf8000000, 0x80000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCM */
+  { 0xfa000000, 0x90000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* SCM */
+  { 0xfc000000, 0xa0000000, 0x00100000, DOMAIN_IO, 0, 1, 0, 0 }, /* MER */
+  { 0xfe000000, 0xb0000000, 0x00200000, DOMAIN_IO, 0, 1, 0, 0 }, /* LCD + DMA */
   LAST_DESC
 };
 
index 7d01141033b9b14542832be6d0a0cde0a2db591b..5594d6ebe6044a94c824d161a10042b6e750d7f9 100644 (file)
 #include "generic.h"
 
 
-static void __init
-fixup_lart(struct machine_desc *desc, struct param_struct *params,
-          char **cmdline, struct meminfo *mi)
-{
-       /*
-        * Note that LART is a special case - it doesn't use physical
-        * address line A23 on the DRAM, so we effectively have 4 * 8MB
-        * in two SA1100 banks.
-        */
-       SET_BANK( 0, 0xc0000000, 8*1024*1024 );
-       SET_BANK( 1, 0xc1000000, 8*1024*1024 );
-       SET_BANK( 2, 0xc8000000, 8*1024*1024 );
-       SET_BANK( 3, 0xc9000000, 8*1024*1024 );
-       SET_BANK( 4, 0xd0000000, 64*1024*1024 );
-       SET_BANK( 5, 0xd8000000, 64*1024*1024 );
-
-       /* make this 5 if you have the 64MB expansion card, or
-        * 6 if you have two 64MB expansion cards */
-       mi->nr_banks = 4;
-
-       ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
-       setup_ramdisk(1, 0, 0, 8192);
-       setup_initrd(0xc0400000, 4*1024*1024);
-}
-
 static struct map_desc lart_io_desc[] __initdata = {
  /* virtual     physical    length      domain     r  w  c  b */
   { 0xe8000000, 0x00000000, 0x00400000, DOMAIN_IO, 1, 1, 0, 0 }, /* main flash memory */
@@ -55,6 +30,7 @@ static void __init lart_map_io(void)
 
        sa1100_register_uart(0, 3);
        sa1100_register_uart(1, 1);
+       sa1100_register_uart(2, 2);
        GAFR |= (GPIO_UART_TXD | GPIO_UART_RXD);
        GPDR |= GPIO_UART_TXD;
        GPDR &= ~GPIO_UART_RXD;
@@ -63,7 +39,7 @@ static void __init lart_map_io(void)
 
 MACHINE_START(LART, "LART")
        BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
-       FIXUP(fixup_lart)
+       BOOT_PARAMS(0xc0000100)
        MAPIO(lart_map_io)
        INITIRQ(sa1100_init_irq)
 MACHINE_END
index eb97a903e549362a49089746e0476999b2c9baa5..f6635a2d0e8303de319e169e6bbf5b88ccb7362a 100644 (file)
@@ -27,85 +27,85 @@ static unsigned int hw_led_state;
 
 void cerf_leds_event(led_event_t evt)
 {
-       unsigned long flags;
+        unsigned long flags;
 
        local_irq_save(flags);
 
-       switch (evt) {
-       case led_start:
-               hw_led_state = LED_MASK;
-               led_state = LED_STATE_ENABLED;
-               break;
-
-       case led_stop:
-               led_state &= ~LED_STATE_ENABLED;
-               break;
-
-       case led_claim:
-               led_state |= LED_STATE_CLAIMED;
-               hw_led_state = LED_MASK;
-               break;
-       case led_release:
-               led_state &= ~LED_STATE_CLAIMED;
-               hw_led_state = LED_MASK;
-               break;
+        switch (evt) {
+        case led_start:
+                hw_led_state = LED_MASK;
+                led_state = LED_STATE_ENABLED;
+                break;
+
+        case led_stop:
+                led_state &= ~LED_STATE_ENABLED;
+                break;
+
+        case led_claim:
+                led_state |= LED_STATE_CLAIMED;
+                hw_led_state = LED_MASK;
+                break;
+        case led_release:
+                led_state &= ~LED_STATE_CLAIMED;
+                hw_led_state = LED_MASK;
+                break;
 
 #ifdef CONFIG_LEDS_TIMER
-       case led_timer:
-               if (!(led_state & LED_STATE_CLAIMED))
-                       hw_led_state ^= LED_D0;
-               break;
+        case led_timer:
+                if (!(led_state & LED_STATE_CLAIMED))
+                        hw_led_state ^= LED_D0;
+                break;
 #endif
 
 #ifdef CONFIG_LEDS_CPU
-       case led_idle_start:
-               if (!(led_state & LED_STATE_CLAIMED))
-                       hw_led_state &= ~LED_D1;
-               break;
-
-       case led_idle_end:
-               if (!(led_state & LED_STATE_CLAIMED))
-                       hw_led_state |= LED_D1;
-               break;
+        case led_idle_start:
+                if (!(led_state & LED_STATE_CLAIMED))
+                        hw_led_state &= ~LED_D1;
+                break;
+
+        case led_idle_end:
+                if (!(led_state & LED_STATE_CLAIMED))
+                        hw_led_state |= LED_D1;
+                break;
 #endif
-       case led_green_on:
-               if (!(led_state & LED_STATE_CLAIMED))
-                       hw_led_state &= ~LED_D2;
-               break;
-
-       case led_green_off:
-               if (!(led_state & LED_STATE_CLAIMED))
-                       hw_led_state |= LED_D2;
-               break;
-
-       case led_amber_on:
-               if (!(led_state & LED_STATE_CLAIMED))
-                       hw_led_state &= ~LED_D3;
-               break;
-
-       case led_amber_off:
-               if (!(led_state & LED_STATE_CLAIMED))
-                       hw_led_state |= LED_D3;
-               break;
-
-       case led_red_on:
-               if (!(led_state & LED_STATE_CLAIMED))
-                       hw_led_state &= ~LED_D1;
-               break;
-
-       case led_red_off:
-               if (!(led_state & LED_STATE_CLAIMED))
-                       hw_led_state |= LED_D1;
-               break;
-
-       default:
-               break;
-       }
-
-       if  (led_state & LED_STATE_ENABLED) {
-               GPSR = hw_led_state;
-               GPCR = hw_led_state ^ LED_MASK;
-       }
+        case led_green_on:
+                if (!(led_state & LED_STATE_CLAIMED))
+                        hw_led_state &= ~LED_D2;
+                break;
+
+        case led_green_off:
+                if (!(led_state & LED_STATE_CLAIMED))
+                        hw_led_state |= LED_D2;
+                break;
+
+        case led_amber_on:
+                if (!(led_state & LED_STATE_CLAIMED))
+                        hw_led_state &= ~LED_D3;
+                break;
+
+        case led_amber_off:
+                if (!(led_state & LED_STATE_CLAIMED))
+                        hw_led_state |= LED_D3;
+                break;
+
+        case led_red_on:
+                if (!(led_state & LED_STATE_CLAIMED))
+                        hw_led_state &= ~LED_D1;
+                break;
+
+        case led_red_off:
+                if (!(led_state & LED_STATE_CLAIMED))
+                        hw_led_state |= LED_D1;
+                break;
+
+        default:
+                break;
+        }
+
+        if  (led_state & LED_STATE_ENABLED) {
+                GPSR = hw_led_state;
+                GPCR = hw_led_state ^ LED_MASK;
+        }
 
        local_irq_restore(flags);
 }
index 241e6583694bc632d3ddcd550e30215d92c97523..18750149071306a08bf6d62194764f85332228a6 100644 (file)
@@ -66,7 +66,7 @@ void lart_leds_event(led_event_t evt)
 #ifdef CONFIG_LEDS_CPU
        case led_idle_start:
                /* The LART people like the LED to be off when the
-                  system is idle... */
+                   system is idle... */
                if (!(led_state & LED_STATE_CLAIMED))
                        hw_led_state &= ~LED_23;
                break;
index d89df5b6ae292201503b3930460be278a6327ffa..8aabaad92174ea9f737aa0d3263f4cb4a395fc55 100644 (file)
@@ -31,7 +31,7 @@ void simpad_leds_event(led_event_t evt)
        switch (evt)
        {
        case led_start:
-               hw_led_state = LED_GREEN;
+               hw_led_state = LED_GREEN;
                led_state = LED_STATE_ENABLED;
                break;
 
index 26c9659120e2b614d9ce655b7a6572753ce6f96b..f5da3a28f6fe09e35591f155d1d641563de649b4 100644 (file)
@@ -74,6 +74,10 @@ static void __init neponset_init_irq(void)
 
 static int __init neponset_init(void)
 {
+       /* only on assabet */
+       if (!machine_is_assabet())
+               return 0;
+
        if (machine_has_neponset()) {
                LEDS = WHOAMI;
 
@@ -108,7 +112,7 @@ __initcall(neponset_init);
 
 static struct map_desc neponset_io_desc[] __initdata = {
  /* virtual     physical    length      domain     r  w  c  b */
-  { 0xf0000000, 0x10000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* System Registers */
+  { 0xf3000000, 0x10000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* System Registers */
   { 0xf4000000, 0x40000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* SA-1111 */
   LAST_DESC
 };
index 1b382fabd276535f1d23283862a7f9188018cad2..6003b5d71d6be5862afe368671143b1cde676f5e 100644 (file)
 
 #include "generic.h"
 
+static void __init
+fixup_pleb(struct machine_desc *desc, struct param_struct *params,
+           char **cmdline, struct meminfo *mi)
+{
+       SET_BANK(0, 0xc0000000, 16*1024*1024);
+       SET_BANK(1, 0xc8000000, 16*1024*1024);
+       SET_BANK(2, 0xd0000000, 16*1024*1024);
+       SET_BANK(3, 0xd8000000, 16*1024*1024);
+
+       /* make this 4 a second memory card is used to make 64MB */
+       /* make it 1 if a 16MB memory card is used */
+       mi->nr_banks = 2; /* Default 32MB */
+
+       ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
+       setup_ramdisk(1, 0, 0, 8192);
+       setup_initrd(0xc0400000, 4*1024*1024);
+}
 
 static struct map_desc pleb_io_desc[] __initdata = {
  /* virtual     physical    length      domain     r  w  c  b */
@@ -29,10 +46,16 @@ static void __init pleb_map_io(void)
        iotable_init(pleb_io_desc);
 
        sa1100_register_uart(0, 3);
+        sa1100_register_uart(1, 1);
+        GAFR |= (GPIO_UART_TXD | GPIO_UART_RXD);
+        GPDR |= GPIO_UART_TXD;
+        GPDR &= ~GPIO_UART_RXD;
+        PPAR |= PPAR_UPR;
 }
 
 MACHINE_START(PLEB, "PLEB")
        BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
+       FIXUP(fixup_pleb)
        MAPIO(pleb_map_io)
        INITIRQ(sa1100_init_irq)
 MACHINE_END
index f725c97c80a94ef9fb616fe9a0d1646191bdec90..a9f2c6ad40add9159301c8559e7829234e1d3333 100644 (file)
@@ -20,6 +20,8 @@
 #include <linux/slab.h>
 #include <linux/pci.h>
 
+#include "pcipool.h"
+
 /*
  * simple buffer allocator for copying of unsafe to safe buffers
  * uses __alloc/__free for actual buffers
index f725e5dd45c9f2d1251040b38aa62953cc3d4dec..f9eeeb6ae4e158a6e52fd96d1fbfe6b949a13ea8 100644 (file)
@@ -300,8 +300,8 @@ static int __init sa1111_ohci_hcd_init(void)
 
        /* take out of reset */
        /* set power sense and control lines (this from the diags code) */
-       *Reset = ( PwrSensePolLow << 6 )
-              | ( PwrCtrlPolLow << 7 );
+        *Reset = ( PwrSensePolLow << 6 )
+               | ( PwrCtrlPolLow << 7 );
 
        *Status = 0;
 
index 739b734cd53b4f12a5782bde02b49b7d8ccede43..254ac3af45dfb5bc04c40fc1333bb50f74effc54 100644 (file)
@@ -45,8 +45,8 @@ static void __init sherman_map_io(void)
 }
 
 MACHINE_START(SHERMAN, "Blazie Engineering Sherman")
-       BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
-       FIXUP(fixup_sherman)
-       MAPIO(sherman_map_io)
+        BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
+        FIXUP(fixup_sherman)
+        MAPIO(sherman_map_io)
        INITIRQ(sa1100_init_irq)
 MACHINE_END
index 47cfaadeaccff29e146546823092e1b91f9917e6..30864aca5fe5c6e5b932f8c371bb5eaf6a669d40 100644 (file)
@@ -66,7 +66,7 @@ static void __init simpad_map_io(void)
        iotable_init(simpad_io_desc);
 
        sa1100_register_uart(0, 3);
-       sa1100_register_uart(1, 1);
+        sa1100_register_uart(1, 1);
 }
 
 
index 46bf90ecdfa8fcb9bee4d9fe6cb2f383c3e7af39..3b89befcf67f0a72597de466b42835a6ed7fcd63 100644 (file)
@@ -631,15 +631,119 @@ do_PrefetchAbort(unsigned long addr, struct pt_regs *regs)
 }
 
 /*
- * if PG_dcache_dirty is set for the page, we need to ensure that any
- * cache entries for the kernels virtual memory range are written
- * back to the page.
+ * We take the easy way out of this problem - we make the
+ * PTE uncacheable.  However, we leave the write buffer on.
  */
-void check_pgcache_dirty(struct page *page)
+static void adjust_pte(struct vm_area_struct *vma, unsigned long address)
 {
-       if (VALID_PAGE(page) && page->mapping &&
-           test_and_clear_bit(PG_dcache_dirty, &page->flags)) {
+       pgd_t *pgd;
+       pmd_t *pmd;
+       pte_t *pte, entry;
+
+       pgd = pgd_offset(vma->vm_mm, address);
+       if (pgd_none(*pgd))
+               return;
+       if (pgd_bad(*pgd))
+               goto bad_pgd;
+
+       pmd = pmd_offset(pgd, address);
+       if (pmd_none(*pmd))
+               return;
+       if (pmd_bad(*pmd))
+               goto bad_pmd;
+
+       pte = pte_offset(pmd, address);
+       entry = *pte;
+
+       /*
+        * If this page isn't present, or is already setup to
+        * fault (ie, is old), we can safely ignore any issues.
+        */
+       if (pte_present(entry) && pte_val(entry) & L_PTE_CACHEABLE) {
+               flush_cache_page(vma, address);
+               pte_val(entry) &= ~L_PTE_CACHEABLE;
+               set_pte(pte, entry);
+               flush_tlb_page(vma, address);
+       }
+       return;
+
+bad_pgd:
+       pgd_ERROR(*pgd);
+       pgd_clear(pgd);
+       return;
+
+bad_pmd:
+       pmd_ERROR(*pmd);
+       pmd_clear(pmd);
+       return;
+}
+
+/*
+ * Take care of architecture specific things when placing a new PTE into
+ * a page table, or changing an existing PTE.  Basically, there are two
+ * things that we need to take care of:
+ *
+ *  1. If PG_dcache_dirty is set for the page, we need to ensure
+ *     that any cache entries for the kernels virtual memory
+ *     range are written back to the page.
+ *  2. If we have multiple shared mappings of the same space in
+ *     an object, we need to deal with the cache aliasing issues.
+ *
+ * Note that the page_table_lock will be held.
+ */
+void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, pte_t pte)
+{
+       struct page *page = pte_page(pte);
+       struct vm_area_struct *mpnt;
+       struct mm_struct *mm;
+       unsigned long pgoff;
+       int aliases;
+
+       if (!VALID_PAGE(page) || !page->mapping)
+               return;
+
+       if (test_and_clear_bit(PG_dcache_dirty, &page->flags)) {
                unsigned long kvirt = (unsigned long)page_address(page);
                cpu_cache_clean_invalidate_range(kvirt, kvirt + PAGE_SIZE, 0);
        }
+
+       mm = vma->vm_mm;
+       pgoff = (addr - vma->vm_start) >> PAGE_SHIFT;
+       aliases = 0;
+
+       /*
+        * If we have any shared mappings that are in the same mm
+        * space, then we need to handle them specially to maintain
+        * cache coherency.
+        */
+       for (mpnt = page->mapping->i_mmap_shared; mpnt;
+            mpnt = mpnt->vm_next_share) {
+               unsigned long off;
+
+               /*
+                * If this VMA is not in our MM, we can ignore it.
+                * Note that we intentionally don't mask out the VMA
+                * that we are fixing up.
+                */
+               if (mpnt->vm_mm != mm && mpnt != vma)
+                       continue;
+
+               /*
+                * If the page isn't in this VMA, we can also ignore it.
+                */
+               if (pgoff < mpnt->vm_pgoff)
+                       continue;
+
+               off = pgoff - mpnt->vm_pgoff;
+               if (off >= (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT)
+                       continue;
+
+               /*
+                * Ok, it is within mpnt.  Fix it up.
+                */
+               adjust_pte(mpnt, mpnt->vm_start + (off << PAGE_SHIFT));
+               aliases ++;
+       }
+       if (aliases)
+               adjust_pte(vma, addr);
 }
index fcaac50b56c6186ced4b10973364c3a83c41f7b4..676bdaa8a4f0788f4874fe3fa409ec1cf2ccf58d 100644 (file)
@@ -6,7 +6,7 @@
 # To add an entry into this database, please see Documentation/arm/README,
 # or contact rmk@arm.linux.org.uk
 #
-# Last update: Wed Jul 25 10:07:10 2001
+# Last update: Thu Aug 9 22:46:02 2001
 #
 # machine_is_xxx       CONFIG_xxxx             MACH_TYPE_xxx           number
 #
@@ -114,3 +114,4 @@ sa1100_elf          SA1100_SA1100_ELF       SA1100_ELF              102
 gator                  SA1100_GATOR            GATOR                   103
 granite                        ARCH_GRANITE            GRANITE                 104
 consus                 SA1100_CONSUS           CONSUS                  105
+aaec2000_aaed20                ARCH_AAEC2000_AAED2000  AAEC2000_AAED2000       106
index a1f398d8f3ca8b2f8262961746d4400f67bf66f2..9d8a1f27f9226d6c32adc626d73907fe363c4537 100644 (file)
 #ifdef CONFIG_VT
 extern void con_init_devfs (void);
 #endif
-extern int rio_init(void);
 
 #define CONSOLE_DEV MKDEV(TTY_MAJOR,0)
 #define TTY_DEV MKDEV(TTYAUX_MAJOR,0)
@@ -154,7 +153,7 @@ extern void hwc_tty_init(void);
 extern void con3215_init(void);
 extern void tty3215_init(void);
 extern void tub3270_con_init(void);
-extern void tub3270_initfunc(void);
+extern void tub3270_init(void);
 extern void rs285_console_init(void);
 extern void sa1100_rs_console_init(void);
 extern void sgi_serial_console_init(void);
@@ -400,13 +399,8 @@ static int hung_up_tty_ioctl(struct inode * inode, struct file * file,
        return cmd == TIOCSPGRP ? -ENOTTY : -EIO;
 }
 
-static loff_t tty_lseek(struct file * file, loff_t offset, int orig)
-{
-       return -ESPIPE;
-}
-
 static struct file_operations tty_fops = {
-       llseek:         tty_lseek,
+       llseek:         no_llseek,
        read:           tty_read,
        write:          tty_write,
        poll:           tty_poll,
@@ -417,7 +411,7 @@ static struct file_operations tty_fops = {
 };
 
 static struct file_operations hung_up_tty_fops = {
-       llseek:         tty_lseek,
+       llseek:         no_llseek,
        read:           hung_up_tty_read,
        write:          hung_up_tty_write,
        poll:           hung_up_tty_poll,
@@ -2194,7 +2188,9 @@ void __init console_init(void)
 #if (defined(CONFIG_8xx) || defined(CONFIG_8260))
        console_8xx_init();
 #elif defined(CONFIG_MAC_SERIAL)
-       mac_scc_console_init();
+       mac_scc_console_init();
+#elif defined(CONFIG_PARISC)
+       pdc_console_init();
 #elif defined(CONFIG_SERIAL)
        serial_console_init();
 #endif /* CONFIG_8xx */
@@ -2211,15 +2207,18 @@ void __init console_init(void)
        sci_console_init();
 #endif
 #endif
-#ifdef CONFIG_3215
-        con3215_init();
-#endif
-#ifdef CONFIG_3270_CONSOLE
+#ifdef CONFIG_TN3270_CONSOLE
        tub3270_con_init();
 #endif
+#ifdef CONFIG_TN3215
+       con3215_init();
+#endif
 #ifdef CONFIG_HWC
         hwc_console_init();
 #endif
+#ifdef CONFIG_STDIO_CONSOLE
+       stdio_console_init();
+#endif
 #ifdef CONFIG_SERIAL_21285_CONSOLE
        rs285_console_init();
 #endif
@@ -2309,6 +2308,7 @@ void __init tty_init(void)
 
        kbd_init();
 #endif
+
 #ifdef CONFIG_ESPSERIAL  /* init ESP before rs, so rs doesn't see the port */
        espserial_init();
 #endif
@@ -2342,9 +2342,6 @@ void __init tty_init(void)
 #ifdef CONFIG_SPECIALIX
        specialix_init();
 #endif
-#ifdef CONFIG_RIO
-       rio_init();
-#endif
 #if (defined(CONFIG_8xx) || defined(CONFIG_8260))
        rs_8xx_init();
 #endif /* CONFIG_8xx */
@@ -2358,10 +2355,10 @@ void __init tty_init(void)
 #ifdef CONFIG_VT
        vcs_init();
 #endif
-#ifdef CONFIG_3270
-       tub3270_initfunc();
+#ifdef CONFIG_TN3270
+       tub3270_init();
 #endif
-#ifdef CONFIG_3215
+#ifdef CONFIG_TN3215
        tty3215_init();
 #endif
 #ifdef CONFIG_HWC
index c05b80392980542a6786a1f058844e375d961c10..2946ec1a9c71854942b7c6588e073134f333dcf5 100644 (file)
@@ -47,7 +47,7 @@ void tty_wait_until_sent(struct tty_struct * tty, long timeout)
 #ifdef TTY_DEBUG_WAIT_UNTIL_SENT
        char buf[64];
        
-       printk("%s wait until sent...\n", tty_name(tty, buf));
+       printk(KERN_DEBUG "%s wait until sent...\n", tty_name(tty, buf));
 #endif
        if (!tty->driver.chars_in_buffer)
                return;
@@ -56,7 +56,7 @@ void tty_wait_until_sent(struct tty_struct * tty, long timeout)
                timeout = MAX_SCHEDULE_TIMEOUT;
        do {
 #ifdef TTY_DEBUG_WAIT_UNTIL_SENT
-               printk("waiting %s...(%d)\n", tty_name(tty, buf),
+               printk(KERN_DEBUG "waiting %s...(%d)\n", tty_name(tty, buf),
                       tty->driver.chars_in_buffer(tty));
 #endif
                set_current_state(TASK_INTERRUPTIBLE);
@@ -82,7 +82,7 @@ static void unset_locked_termios(struct termios *termios,
 #define NOSET_MASK(x,y,z) (x = ((x) & ~(z)) | ((y) & (z)))
 
        if (!locked) {
-               printk("Warning?!? termios_locked is NULL.\n");
+               printk(KERN_WARNING "Warning?!? termios_locked is NULL.\n");
                return;
        }
 
index a55238a8a6e4b7ead1a9681a270bb935dc13999b..29bb95ff6d67407bf58dbb6d3580710d5f269329 100644 (file)
@@ -7,6 +7,7 @@
  *  Dynamic keymap and string allocation - aeb@cwi.nl - May 1994
  *  Restrict VT switching via ioctl() - grif@cs.ucr.edu - Dec 1995
  *  Some code moved for less code duplication - Andi Kleen - Mar 1997
+ *  Check put/get_user, cleanups - acme@conectiva.com.br - Jun 2001
  */
 
 #include <linux/config.h>
@@ -287,8 +288,10 @@ do_kdgkb_ioctl(int cmd, struct kbsentry *user_kdgkb, int perm)
                p = func_table[i];
                if(p)
                        for ( ; *p && sz; p++, sz--)
-                               put_user(*p, q++);
-               put_user('\0', q);
+                               if (put_user(*p, q++))
+                                       return -EFAULT;
+               if (put_user('\0', q))
+                       return -EFAULT;
                return ((p && *p) ? -EOVERFLOW : 0);
        case KDSKBSENT:
                if (!perm)
@@ -739,10 +742,8 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                struct vt_stat *vtstat = (struct vt_stat *)arg;
                unsigned short state, mask;
 
-               i = verify_area(VERIFY_WRITE,(void *)vtstat, sizeof(struct vt_stat));
-               if (i)
-                       return i;
-               put_user(fg_console + 1, &vtstat->v_active);
+               if (put_user(fg_console + 1, &vtstat->v_active))
+                       return -EFAULT;
                state = 1;      /* /dev/tty0 is always open */
                for (i = 0, mask = 2; i < MAX_NR_CONSOLES && mask; ++i, mask <<= 1)
                        if (VT_IS_IN_USE(i))
@@ -878,11 +879,9 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                ushort ll,cc;
                if (!perm)
                        return -EPERM;
-               i = verify_area(VERIFY_READ, (void *)vtsizes, sizeof(struct vt_sizes));
-               if (i)
-                       return i;
-               get_user(ll, &vtsizes->v_rows);
-               get_user(cc, &vtsizes->v_cols);
+               if (get_user(ll, &vtsizes->v_rows) ||
+                   get_user(cc, &vtsizes->v_cols))
+                       return -EFAULT;
                return vc_resize_all(ll, cc);
        }
 
@@ -892,15 +891,15 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                ushort ll,cc,vlin,clin,vcol,ccol;
                if (!perm)
                        return -EPERM;
-               i = verify_area(VERIFY_READ, (void *)vtconsize, sizeof(struct vt_consize));
-               if (i)
-                       return i;
-               get_user(ll, &vtconsize->v_rows);
-               get_user(cc, &vtconsize->v_cols);
-               get_user(vlin, &vtconsize->v_vlin);
-               get_user(clin, &vtconsize->v_clin);
-               get_user(vcol, &vtconsize->v_vcol);
-               get_user(ccol, &vtconsize->v_ccol);
+               if (verify_area(VERIFY_READ, (void *)vtconsize,
+                               sizeof(struct vt_consize)))
+                       return -EFAULT;
+               __get_user(ll, &vtconsize->v_rows);
+               __get_user(cc, &vtconsize->v_cols);
+               __get_user(vlin, &vtconsize->v_vlin);
+               __get_user(clin, &vtconsize->v_clin);
+               __get_user(vcol, &vtconsize->v_vcol);
+               __get_user(ccol, &vtconsize->v_ccol);
                vlin = vlin ? vlin : video_scan_lines;
                if ( clin )
                  {
@@ -1067,10 +1066,6 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
 
                        if (!perm)
                                return -EPERM;
-                       i = verify_area(VERIFY_READ, (void *) arg,
-                                       sizeof(struct vc_mode));
-                       if (i)
-                               return i;
                        if (copy_from_user(&mode, (void *) arg, sizeof(mode)))
                                return -EFAULT;
                        return console_setmode(&mode, cmd == VC_SETMODE);
@@ -1088,10 +1083,6 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
                                   was changed from 0x766a to 0x766c */
                                return console_powermode((int) arg);
                        }
-                       i = verify_area(VERIFY_READ, (void *) arg,
-                                       sizeof(int));
-                       if (i)
-                               return i;
                        if (get_user(cmap_size, (int *) arg))
                                return -EFAULT;
                        if (cmap_size % 3)
index 91eeaf382dcd9d42864373778d2074f7fa17e6e3..014064b22aa696aa92321436230cc186fadac675 100644 (file)
@@ -37,9 +37,6 @@
 #define DIVAS_IRQ_RESET                0xC18
 #define DIVAS_IRQ_RESET_VAL    0xFE
 
-#define        PCI_LATENCY     PCI_LATENCY_TIMER
-#define PCI_INTERRUPT  PCI_INTERRUPT_LINE
-
 #define TEST_INT_DIVAS         0x11
 #define TEST_INT_DIVAS_BRI     0x12
 #define TEST_INT_DIVAS_Q       0x13
@@ -478,7 +475,6 @@ void card_isr (void *dev_id)
 int DivasCardNew(dia_card_t *card_info)
 {
        card_t *card;
-       byte b;
        static boolean_t first_call = TRUE;
        boolean_t NeedISRandReset = FALSE;
 
@@ -567,10 +563,6 @@ int DivasCardNew(dia_card_t *card_info)
                        return -1;
                }
 
-               b = card->cfg.irq;
-
-               UxPciConfigWrite(card->hw, sizeof(b), PCI_INTERRUPT_LINE, &b);
-
                if (card_info->card_type != DIA_CARD_TYPE_DIVA_SERVER_Q)
                {
                        if ((*card->card_reset)(card))
@@ -670,7 +662,7 @@ static int idi_register(card_t *card, byte channels)
                return -1;
        }
 
-       bzero(card->e_tbl, sizeof(E_INFO) * num_entities);
+       memset(card->e_tbl, 0, sizeof(E_INFO) * num_entities);
        card->e_max = num_entities;
 
     DIVA_DIDD_Read(d, sizeof(d));
index 2e598ab80aaf6b1d618dfd4450fe2c83b34e8ce1..017a85aca479c2c87b9c11e1660098b236e251aa 100644 (file)
@@ -37,7 +37,6 @@
 
 extern int DivasCardNext;
 void UxPause(long ms);
-void bcopy(void *pSource, void *pDest, dword dwLength);
 int DivasGetMem(mem_block_t *);
 
 #define DIA_IOCTL_UNLOCK 12
@@ -157,11 +156,8 @@ unsigned int do_poll(struct file *pFile, struct poll_table_struct *pPollTable)
 {
        word wMask = 0;
 
-    if (!DivasLogFifoEmpty())
-    {
+       if (!DivasLogFifoEmpty())
                wMask |= POLLIN | POLLRDNORM;
-       }
-
        return wMask;
 }
 
@@ -174,14 +170,14 @@ ssize_t do_read(struct file *pFile, char *pUserBuffer, size_t BufferSize, loff_t
        {
                printk(KERN_WARNING "Divas: Divalog buffer specifed a size that is too small (%d - %d required)\n",
                        BufferSize, sizeof(klog_t));
-               return 0;
+               return -EIO;
        }
 
        pHeadItem = (klog_t *) DivasLogFifoRead();
 
        if (pHeadItem)
        {
-               bcopy(pHeadItem, pClientLogBuffer, sizeof(klog_t));
+               memcpy(pClientLogBuffer, pHeadItem, sizeof(klog_t));
                kfree(pHeadItem);
                return sizeof(klog_t);
        }
index 30de1cc6d9a9fac039d202748199940ade879bfb..3288f2983153f7c0649da73ff38646701daf1ce4 100644 (file)
@@ -38,18 +38,6 @@ struct pt_regs;
 
 #include "uxio.h"
 
-#ifdef MODULE
-void bcopy(void *pSource, void *pDest, dword dwLength)
-{
-       memcpy(pDest, pSource, dwLength);
-}
-#endif
-
-void bzero(void *pDataArea, dword dwLength)
-{
-       memset(pDataArea, 0, dwLength);
-}
-
 int Divas4BRIInitPCI(card_t *card, dia_card_t *cfg)
 {
        /* Use UxPciConfigWrite routines to initialise PCI config space */
index e3302830b7d509bbfa064f73142cc799eee84916..7acae3e7809df704be1b95c77ad6b21e2f23123f 100644 (file)
@@ -58,10 +58,6 @@ struct ux_diva_card_s
        isr_fn_t        *user_isr;
 };
 
-void bcopy(void *pSource, void *pDest, dword dwLength);
-void bzero(void *pDataArea, dword dwLength);
-
-
 /*
  * Get a card handle to enable card to be accessed
  */
diff --git a/drivers/net/depca.c.orig b/drivers/net/depca.c.orig
deleted file mode 100644 (file)
index 9e14f54..0000000
+++ /dev/null
@@ -1,2086 +0,0 @@
-/*  depca.c: A DIGITAL DEPCA  & EtherWORKS ethernet driver for linux.
-
-    Written 1994, 1995 by David C. Davies.
-
-
-                      Copyright 1994 David C. Davies
-                                  and 
-                        United States Government
-        (as represented by the Director, National Security Agency).  
-
-               Copyright 1995  Digital Equipment Corporation.
-
-
-    This software may be used and distributed according to the terms of
-    the GNU General Public License, incorporated herein by reference.
-
-    This driver is written for the Digital Equipment Corporation series
-    of DEPCA and EtherWORKS ethernet cards:
-
-        DEPCA       (the original)
-       DE100
-       DE101
-       DE200 Turbo
-       DE201 Turbo
-       DE202 Turbo (TP BNC)
-       DE210
-       DE422       (EISA)
-
-    The  driver has been tested on DE100, DE200 and DE202 cards  in  a
-    relatively busy network. The DE422 has been tested a little.
-
-    This  driver will NOT work   for the DE203,  DE204  and DE205 series  of
-    cards,  since they have  a  new custom ASIC in   place of the AMD  LANCE
-    chip.  See the 'ewrk3.c'   driver in the  Linux  source tree for running
-    those cards.
-
-    I have benchmarked the driver with a  DE100 at 595kB/s to (542kB/s from)
-    a DECstation 5000/200.
-
-    The author may be reached at davies@maniac.ultranet.com
-
-    =========================================================================
-
-    The  driver was originally based  on   the 'lance.c' driver from  Donald
-    Becker   which  is included with  the  standard  driver distribution for
-    linux.  V0.4  is  a complete  re-write  with only  the kernel  interface
-    remaining from the original code.
-
-    1) Lance.c code in /linux/drivers/net/
-    2) "Ethernet/IEEE 802.3 Family. 1992 World Network Data Book/Handbook",
-       AMD, 1992 [(800) 222-9323].
-    3) "Am79C90 CMOS Local Area Network Controller for Ethernet (C-LANCE)",
-       AMD, Pub. #17881, May 1993.
-    4) "Am79C960 PCnet-ISA(tm), Single-Chip Ethernet Controller for ISA",
-       AMD, Pub. #16907, May 1992
-    5) "DEC EtherWORKS LC Ethernet Controller Owners Manual",
-       Digital Equipment corporation, 1990, Pub. #EK-DE100-OM.003
-    6) "DEC EtherWORKS Turbo Ethernet Controller Owners Manual",
-       Digital Equipment corporation, 1990, Pub. #EK-DE200-OM.003
-    7) "DEPCA Hardware Reference Manual", Pub. #EK-DEPCA-PR
-       Digital Equipment Corporation, 1989
-    8) "DEC EtherWORKS Turbo_(TP BNC) Ethernet Controller Owners Manual",
-       Digital Equipment corporation, 1991, Pub. #EK-DE202-OM.001
-    
-
-    Peter Bauer's depca.c (V0.5) was referred to when debugging V0.1 of this
-    driver.
-
-    The original DEPCA  card requires that the  ethernet ROM address counter
-    be enabled to count and has an 8 bit NICSR.  The ROM counter enabling is
-    only  done when a  0x08 is read as the  first address octet (to minimise
-    the chances  of writing over some  other hardware's  I/O register).  The
-    NICSR accesses   have been changed  to  byte accesses  for all the cards
-    supported by this driver, since there is only one  useful bit in the MSB
-    (remote boot timeout) and it  is not used.  Also, there  is a maximum of
-    only 48kB network  RAM for this  card.  My thanks  to Torbjorn Lindh for
-    help debugging all this (and holding my feet to  the fire until I got it
-    right).
-
-    The DE200  series  boards have  on-board 64kB  RAM for  use  as a shared
-    memory network  buffer. Only the DE100  cards make use  of a  2kB buffer
-    mode which has not  been implemented in  this driver (only the 32kB  and
-    64kB modes are supported [16kB/48kB for the original DEPCA]).
-
-    At the most only 2 DEPCA cards can  be supported on  the ISA bus because
-    there is only provision  for two I/O base addresses  on each card (0x300
-    and 0x200). The I/O address is detected by searching for a byte sequence
-    in the Ethernet station address PROM at the expected I/O address for the
-    Ethernet  PROM.   The shared memory  base   address  is 'autoprobed'  by
-    looking  for the self  test PROM  and detecting the  card name.   When a
-    second  DEPCA is  detected,  information  is   placed in the   base_addr
-    variable of the  next device structure (which  is created if necessary),
-    thus  enabling ethif_probe  initialization  for the device.  More than 2
-    EISA cards can  be  supported, but  care will  be  needed assigning  the
-    shared memory to ensure that each slot has the  correct IRQ, I/O address
-    and shared memory address assigned.
-
-    ************************************************************************
-
-    NOTE: If you are using two  ISA DEPCAs, it is  important that you assign
-    the base memory addresses correctly.   The  driver autoprobes I/O  0x300
-    then 0x200.  The  base memory address for  the first device must be less
-    than that of the second so that the auto probe will correctly assign the
-    I/O and memory addresses on the same card.  I can't think of a way to do
-    this unambiguously at the moment, since there is nothing on the cards to
-    tie I/O and memory information together.
-
-    I am unable  to  test  2 cards   together for now,    so this  code   is
-    unchecked. All reports, good or bad, are welcome.
-
-    ************************************************************************
-
-    The board IRQ   setting must be  at an  unused IRQ which  is auto-probed
-    using Donald Becker's autoprobe routines. DEPCA and DE100 board IRQs are
-    {2,3,4,5,7}, whereas the  DE200 is at {5,9,10,11,15}.  Note that IRQ2 is
-    really IRQ9 in machines with 16 IRQ lines.
-
-    No 16MB memory  limitation should exist with this  driver as DMA is  not
-    used and the common memory area is in low memory on the network card (my
-    current system has 20MB and I've not had problems yet).
-
-    The ability to load this driver as a loadable module has been added. To
-    utilise this ability, you have to do <8 things:
-
-    0) have a copy of the loadable modules code installed on your system.
-    1) copy depca.c from the  /linux/drivers/net directory to your favourite
-    temporary directory.
-    2) if you wish, edit the  source code near  line 1530 to reflect the I/O
-    address and IRQ you're using (see also 5).
-    3) compile  depca.c, but include -DMODULE in  the command line to ensure
-    that the correct bits are compiled (see end of source code).
-    4) if you are wanting to add a new  card, goto 5. Otherwise, recompile a
-    kernel with the depca configuration turned off and reboot.
-    5) insmod depca.o [irq=7] [io=0x200] [mem=0xd0000] [adapter_name=DE100]
-       [Alan Cox: Changed the code to allow command line irq/io assignments]
-       [Dave Davies: Changed the code to allow command line mem/name
-                                                                assignments]
-    6) run the net startup bits for your eth?? interface manually 
-    (usually /etc/rc.inet[12] at boot time). 
-    7) enjoy!
-
-    Note that autoprobing is not allowed in loadable modules - the system is
-    already up and running and you're messing with interrupts.
-
-    To unload a module, turn off the associated interface 
-    'ifconfig eth?? down' then 'rmmod depca'.
-
-    To assign a base memory address for the shared memory  when running as a
-    loadable module, see 5 above.  To include the adapter  name (if you have
-    no PROM  but know the card name)  also see 5  above. Note that this last
-    option  will not work  with kernel  built-in  depca's. 
-
-    The shared memory assignment for a loadable module  makes sense to avoid
-    the 'memory autoprobe' picking the wrong shared memory  (for the case of
-    2 depca's in a PC).
-
-    ************************************************************************
-    Support for MCA EtherWORKS cards added 11-3-98.
-    Verified to work with up to 2 DE212 cards in a system (although not
-      fully stress-tested).  
-
-    Currently known bugs/limitations:
-
-    Note:  with the MCA stuff as a module, it trusts the MCA configuration,
-           not the command line for IRQ and memory address.  You can
-           specify them if you want, but it will throw your values out.
-           You still have to pass the IO address it was configured as
-           though.
-
-    ************************************************************************
-    TO DO:
-    ------
-
-
-    Revision History
-    ----------------
-
-    Version   Date        Description
-  
-      0.1     25-jan-94   Initial writing.
-      0.2     27-jan-94   Added LANCE TX hardware buffer chaining.
-      0.3      1-feb-94   Added multiple DEPCA support.
-      0.31     4-feb-94   Added DE202 recognition.
-      0.32    19-feb-94   Tidy up. Improve multi-DEPCA support.
-      0.33    25-feb-94   Fix DEPCA ethernet ROM counter enable.
-                          Add jabber packet fix from murf@perftech.com
-                         and becker@super.org
-      0.34     7-mar-94   Fix DEPCA max network memory RAM & NICSR access.
-      0.35     8-mar-94   Added DE201 recognition. Tidied up.
-      0.351   30-apr-94   Added EISA support. Added DE422 recognition.
-      0.36    16-may-94   DE422 fix released.
-      0.37    22-jul-94   Added MODULE support
-      0.38    15-aug-94   Added DBR ROM switch in depca_close(). 
-                          Multi DEPCA bug fix.
-      0.38axp 15-sep-94   Special version for Alpha AXP Linux V1.0.
-      0.381   12-dec-94   Added DE101 recognition, fix multicast bug.
-      0.382    9-feb-95   Fix recognition bug reported by <bkm@star.rl.ac.uk>.
-      0.383   22-feb-95   Fix for conflict with VESA SCSI reported by
-                          <stromain@alf.dec.com>
-      0.384   17-mar-95   Fix a ring full bug reported by <bkm@star.rl.ac.uk>
-      0.385    3-apr-95   Fix a recognition bug reported by 
-                                                <ryan.niemi@lastfrontier.com>
-      0.386   21-apr-95   Fix the last fix...sorry, must be galloping senility
-      0.40    25-May-95   Rewrite for portability & updated.
-                          ALPHA support from <jestabro@amt.tay1.dec.com>
-      0.41    26-Jun-95   Added verify_area() calls in depca_ioctl() from
-                          suggestion by <heiko@colossus.escape.de>
-      0.42    27-Dec-95   Add 'mem' shared memory assignment for loadable 
-                          modules.
-                          Add 'adapter_name' for loadable modules when no PROM.
-                         Both above from a suggestion by 
-                         <pchen@woodruffs121.residence.gatech.edu>.
-                         Add new multicasting code.
-      0.421   22-Apr-96          Fix alloc_device() bug <jari@markkus2.fimr.fi>
-      0.422   29-Apr-96          Fix depca_hw_init() bug <jari@markkus2.fimr.fi>
-      0.423    7-Jun-96   Fix module load bug <kmg@barco.be>
-      0.43    16-Aug-96   Update alloc_device() to conform to de4x5.c
-      0.44     1-Sep-97   Fix *_probe() to test check_region() first - bug
-                           reported by <mmogilvi@elbert.uccs.edu>
-      0.45     3-Nov-98   Added support for MCA EtherWORKS (DE210/DE212) cards
-                           by <tymm@computer.org> 
-      0.451    5-Nov-98   Fixed mca stuff cuz I'm a dummy. <tymm@computer.org>
-      0.5     14-Nov-98   Re-spin for 2.1.x kernels.
-      0.51    27-Jun-99   Correct received packet length for CRC from
-                           report by <worm@dkik.dk>
-      0.52    16-Oct-00   Fixes for 2.3 io memory accesses
-                          Fix show-stopper (ints left masked) in depca_interrupt
-                          by <peterd@pnd-pc.demon.co.uk>
-      0.53    12-Jan-01          Release resources on failure, bss tidbits
-                          by acme@conectiva.com.br
-
-    =========================================================================
-*/
-
-#include <linux/config.h>
-#include <linux/module.h>
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/ptrace.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <asm/uaccess.h>
-#include <asm/bitops.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-
-#include <linux/time.h>
-#include <linux/types.h>
-#include <linux/unistd.h>
-#include <linux/ctype.h>
-
-#ifdef CONFIG_MCA
-#include <linux/mca.h>
-#endif
-
-#include "depca.h"
-
-static char version[] __initdata =
-       "depca.c:v0.53 2001/1/12 davies@maniac.ultranet.com\n";
-
-#ifdef DEPCA_DEBUG
-static int depca_debug = DEPCA_DEBUG;
-#else
-static int depca_debug = 1;
-#endif
-
-#define DEPCA_NDA 0xffe0            /* No Device Address */
-
-#define TX_TIMEOUT (1*HZ)
-
-/*
-** Ethernet PROM defines
-*/
-#define PROBE_LENGTH    32
-#define ETH_PROM_SIG    0xAA5500FFUL
-
-/*
-** Set the number of Tx and Rx buffers. Ensure that the memory requested
-** here is <= to the amount of shared memory set up by the board switches.
-** The number of descriptors MUST BE A POWER OF 2.
-**
-** total_memory = NUM_RX_DESC*(8+RX_BUFF_SZ) + NUM_TX_DESC*(8+TX_BUFF_SZ)
-*/
-#define NUM_RX_DESC     8               /* Number of RX descriptors */
-#define NUM_TX_DESC     8               /* Number of TX descriptors */
-#define RX_BUFF_SZ     1536            /* Buffer size for each Rx buffer */
-#define TX_BUFF_SZ     1536            /* Buffer size for each Tx buffer */
-
-#define CRC_POLYNOMIAL_BE 0x04c11db7UL  /* Ethernet CRC, big endian */
-#define CRC_POLYNOMIAL_LE 0xedb88320UL  /* Ethernet CRC, little endian */
-
-/*
-** EISA bus defines
-*/
-#define DEPCA_EISA_IO_PORTS 0x0c00       /* I/O port base address, slot 0 */
-#define MAX_EISA_SLOTS 16
-#define EISA_SLOT_INC 0x1000
-
-/*
-** ISA Bus defines
-*/
-#define DEPCA_RAM_BASE_ADDRESSES {0xc0000,0xd0000,0xe0000,0x00000}
-#define DEPCA_IO_PORTS {0x300, 0x200, 0}
-#define DEPCA_TOTAL_SIZE 0x10
-static short mem_chkd;
-
-/*
-** Adapter ID for the MCA EtherWORKS DE210/212 adapter
-*/
-#define DE212_ID 0x6def
-
-/*
-** Name <-> Adapter mapping
-*/
-#define DEPCA_SIGNATURE {"DEPCA",\
-                        "DE100","DE101",\
-                         "DE200","DE201","DE202",\
-                        "DE210","DE212",\
-                         "DE422",\
-                         ""}
-static enum {
-  DEPCA, de100, de101, de200, de201, de202, de210, de212, de422, unknown
-} adapter;
-
-/*
-** Miscellaneous info...
-*/
-#define DEPCA_STRLEN 16
-#define MAX_NUM_DEPCAS 2
-
-/*
-** Memory Alignment. Each descriptor is 4 longwords long. To force a
-** particular alignment on the TX descriptor, adjust DESC_SKIP_LEN and
-** DESC_ALIGN. ALIGN aligns the start address of the private memory area
-** and hence the RX descriptor ring's first entry. 
-*/
-#define ALIGN4      ((u_long)4 - 1)       /* 1 longword align */
-#define ALIGN8      ((u_long)8 - 1)       /* 2 longword (quadword) align */
-#define ALIGN         ALIGN8              /* Keep the LANCE happy... */
-
-/*
-** The DEPCA Rx and Tx ring descriptors. 
-*/
-struct depca_rx_desc {
-    volatile s32 base;
-    s16 buf_length;            /* This length is negative 2's complement! */
-    s16 msg_length;            /* This length is "normal". */
-};
-
-struct depca_tx_desc {
-    volatile s32 base;
-    s16 length;                        /* This length is negative 2's complement! */
-    s16 misc;                   /* Errors and TDR info */
-};
-
-#define LA_MASK 0x0000ffff      /* LANCE address mask for mapping network RAM
-                                  to LANCE memory address space */
-
-/*
-** The Lance initialization block, described in databook, in common memory.
-*/
-struct depca_init {
-    u16 mode;                  /* Mode register */
-    u8  phys_addr[ETH_ALEN];   /* Physical ethernet address */
-    u8  mcast_table[8];                /* Multicast Hash Table. */
-    u32 rx_ring;               /* Rx ring base pointer & ring length */
-    u32 tx_ring;               /* Tx ring base pointer & ring length */
-};
-
-#define DEPCA_PKT_STAT_SZ 16
-#define DEPCA_PKT_BIN_SZ  128                /* Should be >=100 unless you
-                                                increase DEPCA_PKT_STAT_SZ */
-struct depca_private {
-    char devname[DEPCA_STRLEN];    /* Device Product String                  */
-    char adapter_name[DEPCA_STRLEN];/* /proc/ioports string                  */
-    char adapter;                  /* Adapter type                           */
-    char mca_slot;                 /* MCA slot, if MCA else -1               */
-    struct depca_init  init_block;/* Shadow Initialization block            */
-/* CPU address space fields */
-    struct depca_rx_desc *rx_ring; /* Pointer to start of RX descriptor ring */
-    struct depca_tx_desc *tx_ring; /* Pointer to start of TX descriptor ring */
-    void *rx_buff[NUM_RX_DESC];    /* CPU virt address of sh'd memory buffs  */
-    void *tx_buff[NUM_TX_DESC];    /* CPU virt address of sh'd memory buffs  */
-    void *sh_mem;                  /* CPU mapped virt address of device RAM  */
-/* Device address space fields */
-    u_long device_ram_start;       /* Start of RAM in device addr space      */
-/* Offsets used in both address spaces */
-    u_long rx_ring_offset;         /* Offset from start of RAM to rx_ring    */
-    u_long tx_ring_offset;         /* Offset from start of RAM to tx_ring    */
-    u_long buffs_offset;          /* LANCE Rx and Tx buffers start address. */
-/* Kernel-only (not device) fields */
-    int        rx_new, tx_new;            /* The next free ring entry               */
-    int rx_old, tx_old;                   /* The ring entries to be free()ed.       */
-    struct net_device_stats stats;
-    spinlock_t lock;
-    struct {                       /* Private stats counters                 */
-       u32 bins[DEPCA_PKT_STAT_SZ];
-       u32 unicast;
-       u32 multicast;
-       u32 broadcast;
-       u32 excessive_collisions;
-       u32 tx_underruns;
-       u32 excessive_underruns;
-    } pktStats;
-    int txRingMask;                /* TX ring mask                           */
-    int rxRingMask;                /* RX ring mask                           */
-    s32 rx_rlen;                   /* log2(rxRingMask+1) for the descriptors */
-    s32 tx_rlen;                   /* log2(txRingMask+1) for the descriptors */
-};
-
-/*
-** The transmit ring full condition is described by the tx_old and tx_new
-** pointers by:
-**    tx_old            = tx_new    Empty ring
-**    tx_old            = tx_new+1  Full ring
-**    tx_old+txRingMask = tx_new    Full ring  (wrapped condition)
-*/
-#define TX_BUFFS_AVAIL ((lp->tx_old<=lp->tx_new)?\
-                        lp->tx_old+lp->txRingMask-lp->tx_new:\
-                         lp->tx_old               -lp->tx_new-1)
-
-/*
-** Public Functions
-*/
-static int    depca_open(struct net_device *dev);
-static int    depca_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static void   depca_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static int    depca_close(struct net_device *dev);
-static int    depca_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-static void   depca_tx_timeout (struct net_device *dev);
-static struct net_device_stats *depca_get_stats(struct net_device *dev);
-static void   set_multicast_list(struct net_device *dev);
-
-/*
-** Private functions
-*/
-static int    depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_slot);
-static void   depca_init_ring(struct net_device *dev);
-static int    depca_rx(struct net_device *dev);
-static int    depca_tx(struct net_device *dev);
-
-static void   LoadCSRs(struct net_device *dev);
-static int    InitRestartDepca(struct net_device *dev);
-static void   DepcaSignature(char *name, u_long paddr);
-static int    DevicePresent(u_long ioaddr);
-static int    get_hw_addr(struct net_device *dev);
-static int    EISA_signature(char *name, s32 eisa_id);
-static void   SetMulticastFilter(struct net_device *dev);
-static void   isa_probe(struct net_device *dev, u_long iobase);
-static void   eisa_probe(struct net_device *dev, u_long iobase);
-#ifdef CONFIG_MCA      
-static void   mca_probe(struct net_device *dev, u_long iobase);
-#endif
-static struct net_device *alloc_device(struct net_device *dev, u_long iobase);
-static int    depca_dev_index(char *s);
-static struct net_device *insert_device(struct net_device *dev, u_long iobase, int (*init)(struct net_device *));
-static int    load_packet(struct net_device *dev, struct sk_buff *skb);
-static void   depca_dbg_open(struct net_device *dev);
-
-#ifdef MODULE
-int           init_module(void);
-void          cleanup_module(void);
-static int    autoprobed = 1, loading_module = 1;
-# else
-static u_char de1xx_irq[] __initdata = {2,3,4,5,7,9,0};
-static u_char de2xx_irq[] __initdata = {5,9,10,11,15,0};
-static u_char de422_irq[] __initdata = {5,9,10,11,0};
-static u_char *depca_irq;
-static int    autoprobed, loading_module;
-#endif /* MODULE */
-
-static char   name[DEPCA_STRLEN];
-static int    num_depcas, num_eth;
-static int    mem;                       /* For loadable module assignment
-                                              use insmod mem=0x????? .... */
-static char   *adapter_name; /* = '\0';     If no PROM when loadable module
-                                             use insmod adapter_name=DE??? ...
-                                             bss initializes this to zero
-                                          */
-/*
-** Miscellaneous defines...
-*/
-#define STOP_DEPCA \
-    outw(CSR0, DEPCA_ADDR);\
-    outw(STOP, DEPCA_DATA)
-
-int __init 
-depca_probe(struct net_device *dev)
-{
-  int tmp = num_depcas, status = -ENODEV;
-  u_long iobase = dev->base_addr;
-
-  SET_MODULE_OWNER(dev);
-
-  if ((iobase == 0) && loading_module){
-    printk("Autoprobing is not supported when loading a module based driver.\n");
-    status = -EIO;
-  } else {
-#ifdef CONFIG_MCA      
-    mca_probe(dev, iobase);
-#endif
-    isa_probe(dev, iobase);
-    eisa_probe(dev, iobase);
-
-    if ((tmp == num_depcas) && (iobase != 0) && loading_module) {
-      printk("%s: depca_probe() cannot find device at 0x%04lx.\n", dev->name, 
-                                                                      iobase);
-    }
-
-    /*
-    ** Walk the device list to check that at least one device
-    ** initialised OK
-    */
-    for (; (dev->priv == NULL) && (dev->next != NULL); dev = dev->next);
-
-    if (dev->priv) status = 0;
-    if (iobase == 0) autoprobed = 1;
-  }
-
-  return status;
-}
-
-static int __init 
-depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_slot)
-{
-       struct depca_private *lp;
-       int i, j, offset, netRAM, mem_len, status=0;
-       s16 nicsr;
-       u_long mem_start=0, mem_base[] = DEPCA_RAM_BASE_ADDRESSES;
-
-       STOP_DEPCA;
-
-       nicsr = inb(DEPCA_NICSR);
-       nicsr = ((nicsr & ~SHE & ~RBE & ~IEN) | IM);
-       outb(nicsr, DEPCA_NICSR);
-
-       if (inw(DEPCA_DATA) != STOP) {
-               return -ENXIO;
-       }
-
-       do {
-               strcpy(name, (adapter_name ? adapter_name : ""));
-               mem_start = (mem ? mem & 0xf0000 : mem_base[mem_chkd++]);
-               DepcaSignature(name, mem_start);
-       } while (!mem && mem_base[mem_chkd] && (adapter == unknown));
-
-       if ((adapter == unknown) || !mem_start) { /* DEPCA device not found */
-               return -ENXIO;
-       }
-
-       dev->base_addr = ioaddr;
-
-       if (mca_slot != -1) {
-               printk("%s: %s at 0x%04lx (MCA slot %d)", dev->name, name, 
-                                                         ioaddr, mca_slot);
-       } else if ((ioaddr & 0x0fff) == DEPCA_EISA_IO_PORTS) { /* EISA slot address */
-               printk("%s: %s at 0x%04lx (EISA slot %d)", 
-                      dev->name, name, ioaddr, (int)((ioaddr>>12)&0x0f));
-       } else {                             /* ISA port address */
-               printk("%s: %s at 0x%04lx", dev->name, name, ioaddr);
-       }
-
-       printk(", h/w address ");
-       status = get_hw_addr(dev);
-       if (status != 0) {
-               printk("      which has an Ethernet PROM CRC error.\n");
-               return -ENXIO;
-       }
-       for (i=0; i<ETH_ALEN - 1; i++) { /* get the ethernet address */
-               printk("%2.2x:", dev->dev_addr[i]);
-       }
-       printk("%2.2x", dev->dev_addr[i]);
-
-       /* Set up the maximum amount of network RAM(kB) */
-       netRAM = ((adapter != DEPCA) ? 64 : 48);
-       if ((nicsr & _128KB) && (adapter == de422))
-               netRAM = 128;
-       offset = 0x0000;
-
-       /* Shared Memory Base Address */ 
-       if (nicsr & BUF) {
-               offset = 0x8000;        /* 32kbyte RAM offset*/
-               nicsr &= ~BS;           /* DEPCA RAM in top 32k */
-               netRAM -= 32;
-       }
-       mem_start += offset;            /* (E)ISA start address */
-       if ((mem_len = (NUM_RX_DESC*(sizeof(struct depca_rx_desc)+RX_BUFF_SZ) +
-                       NUM_TX_DESC*(sizeof(struct depca_tx_desc)+TX_BUFF_SZ) +
-                       sizeof(struct depca_init)))
-           > (netRAM<<10)) {
-               printk(",\n       requests %dkB RAM: only %dkB is available!\n",
-                       (mem_len >> 10), netRAM);
-               return -ENXIO;
-       }
-
-       printk(",\n      has %dkB RAM at 0x%.5lx", netRAM, mem_start);
-
-       /* Enable the shadow RAM. */
-       if (adapter != DEPCA) {
-               nicsr |= SHE;
-               outb(nicsr, DEPCA_NICSR);
-       }
-       /* Define the device private memory */
-       dev->priv = (void *) kmalloc(sizeof(struct depca_private), GFP_KERNEL);
-       if (dev->priv == NULL)
-               return -ENOMEM;
-       lp = (struct depca_private *)dev->priv;
-       memset((char *)dev->priv, 0, sizeof(struct depca_private));
-       lp->adapter = adapter;
-       lp->mca_slot = mca_slot;
-       lp->lock = SPIN_LOCK_UNLOCKED;
-       sprintf(lp->adapter_name,"%s (%s)", name, dev->name);
-       status = -EBUSY;
-       if (!request_region(ioaddr, DEPCA_TOTAL_SIZE, lp->adapter_name)) {
-               printk(KERN_ERR "depca: I/O resource 0x%x @ 0x%lx busy\n",
-                      DEPCA_TOTAL_SIZE, ioaddr);
-               goto out_priv;
-       }
-
-       /* Initialisation Block */
-       lp->sh_mem = ioremap(mem_start, mem_len);
-       status = -EIO;
-       if (lp->sh_mem == NULL) {
-               printk(KERN_ERR "depca: cannot remap ISA memory, aborting\n");
-               goto out_region;
-       }
-       lp->device_ram_start = mem_start & LA_MASK;
-       
-       offset = 0;
-       offset += sizeof(struct depca_init);
-
-       /* Tx & Rx descriptors (aligned to a quadword boundary) */
-       offset = (offset + ALIGN) & ~ALIGN;
-       lp->rx_ring = (struct depca_rx_desc *)(lp->sh_mem + offset);
-       lp->rx_ring_offset = offset;
-
-       offset += (sizeof(struct depca_rx_desc) * NUM_RX_DESC);
-       lp->tx_ring = (struct depca_tx_desc *)(lp->sh_mem + offset);
-       lp->tx_ring_offset = offset;
-
-       offset += (sizeof(struct depca_tx_desc) * NUM_TX_DESC);
-
-       lp->buffs_offset = offset;
-
-       /* Finish initialising the ring information. */
-       lp->rxRingMask = NUM_RX_DESC - 1;
-       lp->txRingMask = NUM_TX_DESC - 1;
-
-       /* Calculate Tx/Rx RLEN size for the descriptors. */
-       for (i=0, j = lp->rxRingMask; j>0; i++) {
-               j >>= 1;
-       }
-       lp->rx_rlen = (s32)(i << 29);
-       for (i=0, j = lp->txRingMask; j>0; i++) {
-               j >>= 1;
-       }
-       lp->tx_rlen = (s32)(i << 29);
-
-       /* Load the initialisation block */
-       depca_init_ring(dev);
-
-       /* Initialise the control and status registers */
-       LoadCSRs(dev);
-
-       /* Enable DEPCA board interrupts for autoprobing */
-       nicsr = ((nicsr & ~IM)|IEN);
-       outb(nicsr, DEPCA_NICSR);
-
-       /* To auto-IRQ we enable the initialization-done and DMA err,
-          interrupts. For now we will always get a DMA error. */
-       if (dev->irq < 2) {
-#ifndef MODULE
-               unsigned char irqnum;
-               autoirq_setup(0);
-
-               /* Assign the correct irq list */
-               switch (lp->adapter) {
-               case DEPCA:
-               case de100:
-               case de101:
-                       depca_irq = de1xx_irq;
-                       break;
-               case de200:
-               case de201:
-               case de202:
-               case de210:
-               case de212:
-                       depca_irq = de2xx_irq;
-                       break;
-               case de422:
-                       depca_irq = de422_irq;
-                       break;
-               }
-
-               /* Trigger an initialization just for the interrupt. */
-               outw(INEA | INIT, DEPCA_DATA);
-         
-               irqnum = autoirq_report(1);
-               status = -ENXIO;
-               if (!irqnum) {
-                       printk(" and failed to detect IRQ line.\n");
-                       goto out_region;
-               } else {
-                       for (dev->irq=0,i=0; (depca_irq[i]) && (!dev->irq); i++)
-                               if (irqnum == depca_irq[i]) {
-                                       dev->irq = irqnum;
-                                       printk(" and uses IRQ%d.\n", dev->irq);
-                               }
-             
-                       status = -ENXIO;
-                       if (!dev->irq) {
-                               printk(" but incorrect IRQ line detected.\n");
-                               goto out_region;
-                       }
-               }
-#endif /* MODULE */
-       } else {
-               printk(" and assigned IRQ%d.\n", dev->irq);
-       }
-
-       if (depca_debug > 1) {
-               printk(version);
-       }
-
-       /* The DEPCA-specific entries in the device structure. */
-       dev->open = &depca_open;
-       dev->hard_start_xmit = &depca_start_xmit;
-       dev->stop = &depca_close;
-       dev->get_stats = &depca_get_stats;
-       dev->set_multicast_list = &set_multicast_list;
-       dev->do_ioctl = &depca_ioctl;
-       dev->tx_timeout = depca_tx_timeout;
-       dev->watchdog_timeo = TX_TIMEOUT;
-
-       dev->mem_start = 0;
-
-       /* Fill in the generic field of the device structure. */
-       ether_setup(dev);
-       return 0;
-out_region:
-       release_region(ioaddr, DEPCA_TOTAL_SIZE);
-out_priv:
-       kfree(dev->priv);
-       dev->priv = NULL;
-       return status;
-}
-
-\f
-static int
-depca_open(struct net_device *dev)
-{
-  struct depca_private *lp = (struct depca_private *)dev->priv;
-  u_long ioaddr = dev->base_addr;
-  s16 nicsr;
-  int status = 0;
-
-  STOP_DEPCA;
-  nicsr = inb(DEPCA_NICSR);
-
-  /* Make sure the shadow RAM is enabled */
-  if (lp->adapter != DEPCA) {
-    nicsr |= SHE;
-    outb(nicsr, DEPCA_NICSR);
-  }
-
-  /* Re-initialize the DEPCA... */
-  depca_init_ring(dev);
-  LoadCSRs(dev);
-
-  depca_dbg_open(dev);
-
-  if (request_irq(dev->irq, &depca_interrupt, 0, lp->adapter_name, dev)) {
-    printk("depca_open(): Requested IRQ%d is busy\n",dev->irq);
-    status = -EAGAIN;
-  } else {
-
-    /* Enable DEPCA board interrupts and turn off LED */
-    nicsr = ((nicsr & ~IM & ~LED)|IEN);
-    outb(nicsr, DEPCA_NICSR);
-    outw(CSR0,DEPCA_ADDR);
-    
-    netif_start_queue(dev);
-    
-    status = InitRestartDepca(dev);
-
-    if (depca_debug > 1){
-      printk("CSR0: 0x%4.4x\n",inw(DEPCA_DATA));
-      printk("nicsr: 0x%02x\n",inb(DEPCA_NICSR));
-    }
-  }
-  return status;
-}
-
-/* Initialize the lance Rx and Tx descriptor rings. */
-static void
-depca_init_ring(struct net_device *dev)
-{
-       struct depca_private *lp = (struct depca_private *)dev->priv;
-       u_int i;
-       u_long offset;
-
-       /* Lock out other processes whilst setting up the hardware */
-       netif_stop_queue(dev);
-
-       lp->rx_new = lp->tx_new = 0;
-       lp->rx_old = lp->tx_old = 0;
-
-       /* Initialize the base address and length of each buffer in the ring */
-       for (i = 0; i <= lp->rxRingMask; i++) {
-               offset = lp->buffs_offset + i*RX_BUFF_SZ;
-               writel((lp->device_ram_start + offset) | R_OWN,
-                      &lp->rx_ring[i].base);
-               writew(-RX_BUFF_SZ, &lp->rx_ring[i].buf_length);
-               lp->rx_buff[i] = lp->sh_mem + offset;
-       }
-
-       for (i = 0; i <= lp->txRingMask; i++) {
-               offset = lp->buffs_offset + (i + lp->rxRingMask+1)*TX_BUFF_SZ;
-               writel((lp->device_ram_start + offset) & 0x00ffffff,
-                      &lp->tx_ring[i].base);
-               lp->tx_buff[i] = lp->sh_mem + offset;
-       }
-
-       /* Set up the initialization block */
-       lp->init_block.rx_ring = (lp->device_ram_start + lp->rx_ring_offset) | lp->rx_rlen;
-       lp->init_block.tx_ring = (lp->device_ram_start + lp->tx_ring_offset) | lp->tx_rlen;
-
-       SetMulticastFilter(dev);
-
-       for (i = 0; i < ETH_ALEN; i++) {
-               lp->init_block.phys_addr[i] = dev->dev_addr[i];
-       }
-
-       lp->init_block.mode = 0x0000;            /* Enable the Tx and Rx */
-}
-
-
-static void depca_tx_timeout (struct net_device *dev)
-{
-       u_long ioaddr = dev->base_addr;
-
-       printk ("%s: transmit timed out, status %04x, resetting.\n",
-               dev->name, inw (DEPCA_DATA));
-
-       STOP_DEPCA;
-       depca_init_ring (dev);
-       LoadCSRs (dev);
-       dev->trans_start = jiffies;
-       netif_wake_queue (dev);
-       InitRestartDepca (dev);
-}
-
-
-/* 
-** Writes a socket buffer to TX descriptor ring and starts transmission 
-*/
-static int depca_start_xmit (struct sk_buff *skb, struct net_device *dev)
-{
-       struct depca_private *lp = (struct depca_private *) dev->priv;
-       u_long ioaddr = dev->base_addr;
-       int status = 0;
-
-       /* Transmitter timeout, serious problems. */
-       if (skb->len < 1)
-               goto out;
-
-       netif_stop_queue (dev);
-
-       if (TX_BUFFS_AVAIL) {   /* Fill in a Tx ring entry */
-               status = load_packet (dev, skb);
-
-               if (!status) {
-                       /* Trigger an immediate send demand. */
-                       outw (CSR0, DEPCA_ADDR);
-                       outw (INEA | TDMD, DEPCA_DATA);
-
-                       dev->trans_start = jiffies;
-                       dev_kfree_skb (skb);
-               }
-               if (TX_BUFFS_AVAIL)
-                       netif_start_queue (dev);
-       } else
-               status = -1;
-
-out:
-       return status;
-}
-
-/*
-** The DEPCA interrupt handler. 
-*/
-static void depca_interrupt (int irq, void *dev_id, struct pt_regs *regs)
-{
-       struct net_device *dev = dev_id;
-       struct depca_private *lp;
-       s16 csr0, nicsr;
-       u_long ioaddr;
-
-       if (dev == NULL) {
-               printk ("depca_interrupt(): irq %d for unknown device.\n", irq);
-               return;
-       }
-
-       lp = (struct depca_private *) dev->priv;
-       ioaddr = dev->base_addr;
-
-       spin_lock (&lp->lock);
-
-       /* mask the DEPCA board interrupts and turn on the LED */
-       nicsr = inb (DEPCA_NICSR);
-       nicsr |= (IM | LED);
-       outb (nicsr, DEPCA_NICSR);
-
-       outw (CSR0, DEPCA_ADDR);
-       csr0 = inw (DEPCA_DATA);
-
-       /* Acknowledge all of the current interrupt sources ASAP. */
-       outw (csr0 & INTE, DEPCA_DATA);
-
-       if (csr0 & RINT)        /* Rx interrupt (packet arrived) */
-               depca_rx (dev);
-
-       if (csr0 & TINT)        /* Tx interrupt (packet sent) */
-               depca_tx (dev);
-
-       /* Any resources available? */
-       if ((TX_BUFFS_AVAIL >= 0) && netif_queue_stopped(dev)) {
-               netif_wake_queue (dev);
-       }
-
-       /* Unmask the DEPCA board interrupts and turn off the LED */
-       nicsr = (nicsr & ~IM & ~LED);
-       outb (nicsr, DEPCA_NICSR);
-
-       spin_unlock (&lp->lock);
-}
-
-
-static int
-depca_rx(struct net_device *dev)
-{
-  struct depca_private *lp = (struct depca_private *)dev->priv;
-  int i, entry;
-  s32 status;
-
-  for (entry=lp->rx_new; 
-       !(readl(&lp->rx_ring[entry].base) & R_OWN);
-       entry=lp->rx_new){
-    status = readl(&lp->rx_ring[entry].base) >> 16 ;
-    if (status & R_STP) {                      /* Remember start of frame */
-      lp->rx_old = entry;
-    }
-    if (status & R_ENP) {                      /* Valid frame status */
-      if (status & R_ERR) {                   /* There was an error. */
-       lp->stats.rx_errors++;                 /* Update the error stats. */
-       if (status & R_FRAM) lp->stats.rx_frame_errors++;
-       if (status & R_OFLO) lp->stats.rx_over_errors++;
-       if (status & R_CRC)  lp->stats.rx_crc_errors++;
-       if (status & R_BUFF) lp->stats.rx_fifo_errors++;
-      } else { 
-       short len, pkt_len = readw(&lp->rx_ring[entry].msg_length) - 4;
-       struct sk_buff *skb;
-
-       skb = dev_alloc_skb(pkt_len+2);
-       if (skb != NULL) {
-         unsigned char *buf;
-         skb_reserve(skb,2);               /* 16 byte align the IP header */
-         buf = skb_put(skb,pkt_len);
-         skb->dev = dev;
-         if (entry < lp->rx_old) {         /* Wrapped buffer */
-           len = (lp->rxRingMask - lp->rx_old + 1) * RX_BUFF_SZ;
-           memcpy_fromio(buf, lp->rx_buff[lp->rx_old], len);
-           memcpy_fromio(buf + len, lp->rx_buff[0], pkt_len-len);
-         } else {                          /* Linear buffer */
-           memcpy_fromio(buf, lp->rx_buff[lp->rx_old], pkt_len);
-         }
-
-         /* 
-         ** Notify the upper protocol layers that there is another 
-         ** packet to handle
-         */
-         skb->protocol=eth_type_trans(skb,dev);
-         netif_rx(skb);
-
-         /*
-         ** Update stats
-         */
-         dev->last_rx = jiffies;
-         lp->stats.rx_packets++;
-         lp->stats.rx_bytes += pkt_len;
-         for (i=1; i<DEPCA_PKT_STAT_SZ-1; i++) {
-           if (pkt_len < (i*DEPCA_PKT_BIN_SZ)) {
-             lp->pktStats.bins[i]++;
-             i = DEPCA_PKT_STAT_SZ;
-           }
-         }
-         if (buf[0] & 0x01) {              /* Multicast/Broadcast */
-           if ((*(s16 *)&buf[0] == -1) &&
-               (*(s16 *)&buf[2] == -1) &&
-               (*(s16 *)&buf[4] == -1)) {
-             lp->pktStats.broadcast++;
-           } else {
-             lp->pktStats.multicast++;
-           }
-         } else if ((*(s16 *)&buf[0] == *(s16 *)&dev->dev_addr[0]) &&
-                    (*(s16 *)&buf[2] == *(s16 *)&dev->dev_addr[2]) &&
-                    (*(s16 *)&buf[4] == *(s16 *)&dev->dev_addr[4])) {
-           lp->pktStats.unicast++;
-         }
-         
-         lp->pktStats.bins[0]++;           /* Duplicates stats.rx_packets */
-         if (lp->pktStats.bins[0] == 0) {  /* Reset counters */
-           memset((char *)&lp->pktStats, 0, sizeof(lp->pktStats));
-         }
-       } else {
-         printk("%s: Memory squeeze, deferring packet.\n", dev->name);
-         lp->stats.rx_dropped++;       /* Really, deferred. */
-         break;
-       }
-      }
-      /* Change buffer ownership for this last frame, back to the adapter */
-      for (; lp->rx_old!=entry; lp->rx_old=(++lp->rx_old)&lp->rxRingMask) {
-       writel(readl(&lp->rx_ring[lp->rx_old].base) | R_OWN, 
-                                               &lp->rx_ring[lp->rx_old].base);
-      }
-      writel(readl(&lp->rx_ring[entry].base) | R_OWN, &lp->rx_ring[entry].base);
-    }
-
-    /*
-    ** Update entry information
-    */
-    lp->rx_new = (++lp->rx_new) & lp->rxRingMask;
-    }
-
-    return 0;
-}
-
-/*
-** Buffer sent - check for buffer errors.
-*/
-static int
-depca_tx(struct net_device *dev)
-{
-  struct depca_private *lp = (struct depca_private *)dev->priv;
-  int entry;
-  s32 status;
-  u_long ioaddr = dev->base_addr;
-
-  for (entry = lp->tx_old; entry != lp->tx_new; entry = lp->tx_old) {
-    status = readl(&lp->tx_ring[entry].base) >> 16 ;
-
-    if (status < 0) {                          /* Packet not yet sent! */
-      break;
-    } else if (status & T_ERR) {               /* An error occurred. */
-      status = readl(&lp->tx_ring[entry].misc);
-      lp->stats.tx_errors++;
-      if (status & TMD3_RTRY) lp->stats.tx_aborted_errors++;
-      if (status & TMD3_LCAR) lp->stats.tx_carrier_errors++;
-      if (status & TMD3_LCOL) lp->stats.tx_window_errors++;
-      if (status & TMD3_UFLO) lp->stats.tx_fifo_errors++;
-      if (status & (TMD3_BUFF | TMD3_UFLO)) {
-       /* Trigger an immediate send demand. */
-       outw(CSR0, DEPCA_ADDR);
-       outw(INEA | TDMD, DEPCA_DATA);
-      }
-    } else if (status & (T_MORE | T_ONE)) {
-      lp->stats.collisions++;
-    } else {
-      lp->stats.tx_packets++;
-    }
-
-    /* Update all the pointers */
-    lp->tx_old = (++lp->tx_old) & lp->txRingMask;
-  }
-
-  return 0;
-}
-
-static int
-depca_close(struct net_device *dev)
-{
-  struct depca_private *lp = (struct depca_private *)dev->priv;
-  s16 nicsr;
-  u_long ioaddr = dev->base_addr;
-
-  netif_stop_queue(dev);
-
-  outw(CSR0, DEPCA_ADDR);
-
-  if (depca_debug > 1) {
-    printk("%s: Shutting down ethercard, status was %2.2x.\n",
-          dev->name, inw(DEPCA_DATA));
-  }
-
-  /* 
-  ** We stop the DEPCA here -- it occasionally polls
-  ** memory if we don't. 
-  */
-  outw(STOP, DEPCA_DATA);
-
-  /*
-  ** Give back the ROM in case the user wants to go to DOS
-  */
-  if (lp->adapter != DEPCA) {
-    nicsr = inb(DEPCA_NICSR);
-    nicsr &= ~SHE;
-    outb(nicsr, DEPCA_NICSR);
-  }
-
-  /*
-  ** Free the associated irq
-  */
-  free_irq(dev->irq, dev);
-  return 0;
-}
-
-static void LoadCSRs(struct net_device *dev)
-{
-  struct depca_private *lp = (struct depca_private *)dev->priv;
-  u_long ioaddr = dev->base_addr;
-
-  outw(CSR1, DEPCA_ADDR);                /* initialisation block address LSW */
-  outw((u16)lp->device_ram_start, DEPCA_DATA);
-  outw(CSR2, DEPCA_ADDR);                /* initialisation block address MSW */
-  outw((u16)(lp->device_ram_start >> 16), DEPCA_DATA);
-  outw(CSR3, DEPCA_ADDR);                /* ALE control */
-  outw(ACON, DEPCA_DATA);
-
-  outw(CSR0, DEPCA_ADDR);                /* Point back to CSR0 */
-
-  return;
-}
-
-static int InitRestartDepca(struct net_device *dev)
-{
-  struct depca_private *lp = (struct depca_private *)dev->priv;
-  u_long ioaddr = dev->base_addr;
-  int i, status=0;
-
-  /* Copy the shadow init_block to shared memory */
-  memcpy_toio(lp->sh_mem, &lp->init_block, sizeof(struct depca_init));
-
-  outw(CSR0, DEPCA_ADDR);                /* point back to CSR0 */
-  outw(INIT, DEPCA_DATA);                /* initialize DEPCA */
-
-  /* wait for lance to complete initialisation */
-  for (i=0;(i<100) && !(inw(DEPCA_DATA) & IDON); i++); 
-
-  if (i!=100) {
-    /* clear IDON by writing a "1", enable interrupts and start lance */
-    outw(IDON | INEA | STRT, DEPCA_DATA);
-    if (depca_debug > 2) {
-      printk("%s: DEPCA open after %d ticks, init block 0x%08lx csr0 %4.4x.\n",
-            dev->name, i, virt_to_phys(lp->sh_mem), inw(DEPCA_DATA));
-    }
-  } else {
-    printk("%s: DEPCA unopen after %d ticks, init block 0x%08lx csr0 %4.4x.\n",
-            dev->name, i, virt_to_phys(lp->sh_mem), inw(DEPCA_DATA));
-    status = -1;
-  }
-
-  return status;
-}
-
-static struct net_device_stats *
-depca_get_stats(struct net_device *dev)
-{
-    struct depca_private *lp = (struct depca_private *)dev->priv;
-
-    /* Null body since there is no framing error counter */
-
-    return &lp->stats;
-}
-
-/*
-** Set or clear the multicast filter for this adaptor.
-*/
-static void
-set_multicast_list(struct net_device *dev)
-{
-  struct depca_private *lp = (struct depca_private *)dev->priv;
-  u_long ioaddr = dev->base_addr;
-  
-  if (dev) {
-    netif_stop_queue(dev);
-    while(lp->tx_old != lp->tx_new);  /* Wait for the ring to empty */
-
-    STOP_DEPCA;                       /* Temporarily stop the depca.  */
-    depca_init_ring(dev);             /* Initialize the descriptor rings */
-
-    if (dev->flags & IFF_PROMISC) {   /* Set promiscuous mode */
-      lp->init_block.mode |= PROM;
-    } else {
-      SetMulticastFilter(dev);
-      lp->init_block.mode &= ~PROM;   /* Unset promiscuous mode */
-    }
-
-    LoadCSRs(dev);                    /* Reload CSR3 */
-    InitRestartDepca(dev);            /* Resume normal operation. */
-    netif_start_queue(dev);           /* Unlock the TX ring */
-  }
-}
-
-/*
-** Calculate the hash code and update the logical address filter
-** from a list of ethernet multicast addresses.
-** Big endian crc one liner is mine, all mine, ha ha ha ha!
-** LANCE calculates its hash codes big endian.
-*/
-static void SetMulticastFilter(struct net_device *dev)
-{
-  struct depca_private *lp = (struct depca_private *)dev->priv;
-  struct dev_mc_list *dmi=dev->mc_list;
-  char *addrs;
-  int i, j, bit, byte;
-  u16 hashcode;
-  s32 crc, poly = CRC_POLYNOMIAL_BE;
-
-  if (dev->flags & IFF_ALLMULTI) {         /* Set all multicast bits */
-    for (i=0; i<(HASH_TABLE_LEN>>3); i++) {
-      lp->init_block.mcast_table[i] = (char)0xff;
-    }
-  } else {
-    for (i=0; i<(HASH_TABLE_LEN>>3); i++){ /* Clear the multicast table */
-      lp->init_block.mcast_table[i]=0;
-    }
-                                           /* Add multicast addresses */
-    for (i=0;i<dev->mc_count;i++) {        /* for each address in the list */
-      addrs=dmi->dmi_addr;
-      dmi=dmi->next;
-      if ((*addrs & 0x01) == 1) {          /* multicast address? */ 
-       crc = 0xffffffff;                  /* init CRC for each address */
-       for (byte=0;byte<ETH_ALEN;byte++) {/* for each address byte */
-                                          /* process each address bit */ 
-         for (bit = *addrs++,j=0;j<8;j++, bit>>=1) {
-           crc = (crc << 1) ^ ((((crc<0?1:0) ^ bit) & 0x01) ? poly : 0);
-         }
-       }
-       hashcode = (crc & 1);              /* hashcode is 6 LSb of CRC ... */
-       for (j=0;j<5;j++) {                /* ... in reverse order. */
-         hashcode = (hashcode << 1) | ((crc>>=1) & 1);
-       }                                      
-       
-       
-       byte = hashcode >> 3;              /* bit[3-5] -> byte in filter */
-       bit = 1 << (hashcode & 0x07);      /* bit[0-2] -> bit in byte */
-       lp->init_block.mcast_table[byte] |= bit;
-      }
-    }
-  }
-
-  return;
-}
-
-#ifdef CONFIG_MCA
-/*
-** Microchannel bus I/O device probe
-*/
-static void __init 
-mca_probe(struct net_device *dev, u_long ioaddr)
-{
-    unsigned char pos[2];
-    unsigned char where;
-    unsigned long iobase;
-    int irq;
-    int slot = 0;
-
-    /*
-    ** See if we've been here before.
-    */
-    if ((!ioaddr && autoprobed) || (ioaddr && !loading_module)) return;   
-
-    if (MCA_bus) {
-       /*
-       ** Search for the adapter.  If an address has been given, search 
-       ** specifically for the card at that address.  Otherwise find the
-       ** first card in the system.
-       */
-       while ((dev!=NULL) && 
-              ((slot=mca_find_adapter(DE212_ID, slot)) != MCA_NOTFOUND)) {
-           pos[0] = mca_read_stored_pos(slot, 2);
-           pos[1] = mca_read_stored_pos(slot, 3);
-
-           /*
-           ** IO of card is handled by bits 1 and 2 of pos0.    
-           **
-           **    bit2 bit1    IO
-           **       0    0    0x2c00
-           **       0    1    0x2c10
-           **       1    0    0x2c20
-           **       1    1    0x2c30
-           */
-           where = (pos[0] & 6) >> 1;
-           iobase = 0x2c00 + (0x10 * where);
-              
-           if ((ioaddr) && (ioaddr != iobase)) {
-               /*
-               ** Card was found, but not at the right IO location. Continue 
-               ** scanning from the next MCA slot up for another card.
-               */
-               slot++;
-               continue;
-           }
-
-           /*
-           ** Found the adapter we were looking for. Now start setting it up.
-           ** 
-           ** First work on decoding the IRQ.  It's stored in the lower 4 bits
-           ** of pos1.  Bits are as follows (from the ADF file):
-           **
-           **      Bits           
-           **   3   2   1   0    IRQ 
-           **   --------------------
-           **   0   0   1   0     5
-           **   0   0   0   1     9
-           **   0   1   0   0    10
-           **   1   0   0   0    11
-           **/
-           where = pos[1] & 0x0f;
-           switch(where) {       
-           case 1:
-               irq = 9;
-               break;
-           case 2:
-               irq = 5;
-               break;
-           case 4:
-               irq = 10;
-               break;
-           case 8:
-               irq = 11;
-               break;
-           default:
-               printk("%s: mca_probe IRQ error.  You should never get here (%d).\n", dev->name, where);
-               return;
-           }  
-           /*
-           ** Shared memory address of adapter is stored in bits 3-5 of pos0.
-           ** They are mapped as follows:
-           **
-           **    Bit
-           **   5  4  3       Memory Addresses
-           **   0  0  0       C0000-CFFFF (64K)
-           **   1  0  0       C8000-CFFFF (32K)
-           **   0  0  1       D0000-DFFFF (64K)
-           **   1  0  1       D8000-DFFFF (32K)
-           **   0  1  0       E0000-EFFFF (64K)
-           **   1  1  0       E8000-EFFFF (32K)
-           */ 
-           where = (pos[0] & 0x18) >> 3; 
-           mem = 0xc0000 + (where * 0x10000);
-           if (pos[0] & 0x20) {
-               mem += 0x8000;
-           }
-       
-           /*
-           ** Get everything allocated and initialized...  (almost just
-           ** like the ISA and EISA probes)
-           */
-           if (DevicePresent(iobase) != 0) {
-               /*
-               ** If the MCA configuration says the card should be here,
-               ** it really should be here.
-               */
-               printk(KERN_ERR "%s: MCA reports card at 0x%lx but it is not
-responding.\n", dev->name, iobase);
-           }
-       
-           if (check_region(iobase, DEPCA_TOTAL_SIZE) == 0) {
-               if ((dev = alloc_device(dev, iobase)) != NULL) {
-                   dev->irq = irq;
-                   if (depca_hw_init(dev, iobase, slot) == 0) {       
-                       /*
-                       ** Adapter initialized correctly:  Name it in
-                       ** /proc/mca.
-                       */
-                       mca_set_adapter_name(slot, "DE210/212 Ethernet Adapter");
-                       mca_mark_as_used(slot);
-                       num_depcas++;
-                   }
-                   num_eth++;
-               }
-           } else if (autoprobed) {
-               printk(KERN_WARNING "%s: region already allocated at 0x%04lx.\n", dev->name, iobase);
-           }
-       
-           /*
-           ** If this is a probe by a module, return after setting up the
-           ** given card.
-           */
-           if (ioaddr) return;
-       
-           /*
-           ** Set up to check the next slot and loop.
-           */
-           slot++;
-       }
-    }
-
-    return;
-}
-#endif
-
-/*
-** ISA bus I/O device probe
-*/
-static void __init 
-isa_probe(struct net_device *dev, u_long ioaddr)
-{
-  int i = num_depcas, maxSlots;
-  s32 ports[] = DEPCA_IO_PORTS;
-
-  if (!ioaddr && autoprobed) return ;          /* Been here before ! */
-  if (ioaddr > 0x400) return;                  /* EISA Address */
-  if (i >= MAX_NUM_DEPCAS) return;             /* Too many ISA adapters */
-
-  if (ioaddr == 0) {                           /* Autoprobing */
-    maxSlots = MAX_NUM_DEPCAS;
-  } else {                                     /* Probe a specific location */
-    ports[i] = ioaddr;
-    maxSlots = i + 1;
-  }
-
-  for (; (i<maxSlots) && (dev!=NULL) && ports[i]; i++) {
-    if (check_region(ports[i], DEPCA_TOTAL_SIZE) == 0) {
-      if (DevicePresent(ports[i]) == 0) { 
-       if ((dev = alloc_device(dev, ports[i])) != NULL) {
-         if (depca_hw_init(dev, ports[i], -1) == 0) {
-           num_depcas++;
-         }
-         num_eth++;
-       }
-      }
-    } else if (autoprobed) {
-      printk("%s: region already allocated at 0x%04x.\n", dev->name, ports[i]);
-    }
-  }
-
-  return;
-}
-
-/*
-** EISA bus I/O device probe. Probe from slot 1 since slot 0 is usually
-** the motherboard. Upto 15 EISA devices are supported.
-*/
-static void __init 
-eisa_probe(struct net_device *dev, u_long ioaddr)
-{
-  int i, maxSlots;
-  u_long iobase;
-  char name[DEPCA_STRLEN];
-
-  if (!ioaddr && autoprobed) return ;            /* Been here before ! */
-  if ((ioaddr < 0x400) && (ioaddr > 0)) return;  /* ISA Address */
-
-  if (ioaddr == 0) {                           /* Autoprobing */
-    iobase = EISA_SLOT_INC;                    /* Get the first slot address */
-    i = 1;
-    maxSlots = MAX_EISA_SLOTS;
-  } else {                                     /* Probe a specific location */
-    iobase = ioaddr;
-    i = (ioaddr >> 12);
-    maxSlots = i + 1;
-  }
-  if ((iobase & 0x0fff) == 0) iobase += DEPCA_EISA_IO_PORTS;
-
-  for (; (i<maxSlots) && (dev!=NULL); i++, iobase+=EISA_SLOT_INC) {
-    if (check_region(iobase, DEPCA_TOTAL_SIZE) == 0) {
-      if (EISA_signature(name, EISA_ID)) {
-       if (DevicePresent(iobase) == 0) { 
-         if ((dev = alloc_device(dev, iobase)) != NULL) {
-           if (depca_hw_init(dev, iobase, -1) == 0) {
-             num_depcas++;
-           }
-           num_eth++;
-         }
-       }
-      }
-    } else if (autoprobed) {
-      printk("%s: region already allocated at 0x%04lx.\n", dev->name, iobase);
-    }
-  }
-
-  return;
-}
-
-/*
-** Search the entire 'eth' device list for a fixed probe. If a match isn't
-** found then check for an autoprobe or unused device location. If they
-** are not available then insert a new device structure at the end of
-** the current list.
-*/
-static struct net_device * __init 
-alloc_device(struct net_device *dev, u_long iobase)
-{
-    struct net_device *adev = NULL;
-    int fixed = 0, new_dev = 0;
-
-    num_eth = depca_dev_index(dev->name);
-    if (loading_module) return dev;
-    
-    while (1) {
-       if (((dev->base_addr == DEPCA_NDA) || (dev->base_addr==0)) && !adev) {
-           adev=dev;
-       } else if ((dev->priv == NULL) && (dev->base_addr==iobase)) {
-           fixed = 1;
-       } else {
-           if (dev->next == NULL) {
-               new_dev = 1;
-           } else if (strncmp(dev->next->name, "eth", 3) != 0) {
-               new_dev = 1;
-           }
-       }
-       if ((dev->next == NULL) || new_dev || fixed) break;
-       dev = dev->next;
-       num_eth++;
-    }
-    if (adev && !fixed) {
-       dev = adev;
-       num_eth = depca_dev_index(dev->name);
-       new_dev = 0;
-    }
-
-    if (((dev->next == NULL) &&  
-       ((dev->base_addr != DEPCA_NDA) && (dev->base_addr != 0)) && !fixed) ||
-       new_dev) {
-       num_eth++;                         /* New device */
-       dev = insert_device(dev, iobase, depca_probe);
-    }
-    
-    return dev;
-}
-
-/*
-** If at end of eth device list and can't use current entry, malloc
-** one up. If memory could not be allocated, print an error message.
-*/
-static struct net_device * __init 
-insert_device(struct net_device *dev, u_long iobase, int (*init)(struct net_device *))
-{
-    struct net_device *new;
-
-    new = (struct net_device *)kmalloc(sizeof(struct net_device), GFP_KERNEL);
-    if (new == NULL) {
-       printk("eth%d: Device not initialised, insufficient memory\n",num_eth);
-       return NULL;
-    } else {
-       new->next = dev->next;
-       dev->next = new;
-       dev = dev->next;               /* point to the new device */
-       if (num_eth > 9999) {
-           sprintf(dev->name,"eth????");/* New device name */
-       } else {
-           sprintf(dev->name,"eth%d", num_eth);/* New device name */
-       }
-       dev->base_addr = iobase;       /* assign the io address */
-       dev->init = init;              /* initialisation routine */
-    }
-
-    return dev;
-}
-
-static int __init 
-depca_dev_index(char *s)
-{
-    int i=0, j=0;
-
-    for (;*s; s++) {
-       if (isdigit(*s)) {
-           j=1;
-           i = (i * 10) + (*s - '0');
-       } else if (j) break;
-    }
-
-    return i;
-}
-
-/*
-** Look for a particular board name in the on-board Remote Diagnostics
-** and Boot (readb) ROM. This will also give us a clue to the network RAM
-** base address.
-*/
-static void __init 
-DepcaSignature(char *name, u_long paddr)
-{
-  u_int i,j,k;
-  const char *signatures[] = DEPCA_SIGNATURE;
-  void *ptr;
-  char tmpstr[16];
-
-  /* Copy the first 16 bytes of ROM */
-  ptr = ioremap(paddr + 0xc000, 16);
-  if (ptr == NULL) {
-         printk(KERN_ERR "depca: I/O remap failed at %lx\n", paddr+0xc000);
-         adapter = unknown;
-         return;
-  }
-  for (i=0;i<16;i++) {
-    tmpstr[i] = readb(ptr + i);
-  }
-  iounmap(ptr);
-
-  /* Check if PROM contains a valid string */
-  for (i=0;*signatures[i]!='\0';i++) {
-    for (j=0,k=0;j<16 && k<strlen(signatures[i]);j++) {
-      if (signatures[i][k] == tmpstr[j]) {              /* track signature */
-       k++;
-      } else {                     /* lost signature; begin search again */
-       k=0;
-      }
-    }
-    if (k == strlen(signatures[i])) break;
-  }
-
-  /* Check if name string is valid, provided there's no PROM */
-  if (*name && (i == unknown)) {
-    for (i=0;*signatures[i]!='\0';i++) {
-      if (strcmp(name,signatures[i]) == 0) break;
-    }
-  }
-
-  /* Update search results */
-  strcpy(name,signatures[i]);
-  adapter = i;
-
-  return;
-}
-
-/*
-** Look for a special sequence in the Ethernet station address PROM that
-** is common across all DEPCA products. Note that the original DEPCA needs
-** its ROM address counter to be initialized and enabled. Only enable
-** if the first address octet is a 0x08 - this minimises the chances of
-** messing around with some other hardware, but it assumes that this DEPCA
-** card initialized itself correctly.
-** 
-** Search the Ethernet address ROM for the signature. Since the ROM address
-** counter can start at an arbitrary point, the search must include the entire
-** probe sequence length plus the (length_of_the_signature - 1).
-** Stop the search IMMEDIATELY after the signature is found so that the
-** PROM address counter is correctly positioned at the start of the
-** ethernet address for later read out.
-*/
-static int __init 
-DevicePresent(u_long ioaddr)
-{
-  union {
-    struct {
-      u32 a;
-      u32 b;
-    } llsig;
-    char Sig[sizeof(u32) << 1];
-  } dev;
-  short sigLength=0;
-  s8 data;
-  s16 nicsr;
-  int i, j, status = 0;
-
-  data = inb(DEPCA_PROM);                /* clear counter on DEPCA */
-  data = inb(DEPCA_PROM);                /* read data */
-
-  if (data == 0x08) {                    /* Enable counter on DEPCA */
-    nicsr = inb(DEPCA_NICSR);
-    nicsr |= AAC;
-    outb(nicsr, DEPCA_NICSR);
-  }
-  
-  dev.llsig.a = ETH_PROM_SIG;
-  dev.llsig.b = ETH_PROM_SIG;
-  sigLength = sizeof(u32) << 1;
-
-  for (i=0,j=0;j<sigLength && i<PROBE_LENGTH+sigLength-1;i++) {
-    data = inb(DEPCA_PROM);
-    if (dev.Sig[j] == data) {    /* track signature */
-      j++;
-    } else {                     /* lost signature; begin search again */
-      if (data == dev.Sig[0]) {  /* rare case.... */
-       j=1;
-      } else {
-       j=0;
-      }
-    }
-  }
-
-  if (j!=sigLength) {
-    status = -ENODEV;           /* search failed */
-  }
-
-  return status;
-}
-
-/*
-** The DE100 and DE101 PROM accesses were made non-standard for some bizarre
-** reason: access the upper half of the PROM with x=0; access the lower half
-** with x=1.
-*/
-static int __init 
-get_hw_addr(struct net_device *dev)
-{
-  u_long ioaddr = dev->base_addr;
-  int i, k, tmp, status = 0;
-  u_short j, x, chksum;
-
-  x = (((adapter == de100) || (adapter == de101)) ? 1 : 0);
-
-  for (i=0,k=0,j=0;j<3;j++) {
-    k <<= 1 ;
-    if (k > 0xffff) k-=0xffff;
-
-    k += (u_char) (tmp = inb(DEPCA_PROM + x));
-    dev->dev_addr[i++] = (u_char) tmp;
-    k += (u_short) ((tmp = inb(DEPCA_PROM + x)) << 8);
-    dev->dev_addr[i++] = (u_char) tmp;
-
-    if (k > 0xffff) k-=0xffff;
-  }
-  if (k == 0xffff) k=0;
-
-  chksum = (u_char) inb(DEPCA_PROM + x);
-  chksum |= (u_short) (inb(DEPCA_PROM + x) << 8);
-  if (k != chksum) status = -1;
-
-  return status;
-}
-
-/*
-** Load a packet into the shared memory
-*/
-static int load_packet(struct net_device *dev, struct sk_buff *skb)
-{
-  struct depca_private *lp = (struct depca_private *)dev->priv;
-  int i, entry, end, len, status = 0;
-
-  entry = lp->tx_new;                                 /* Ring around buffer number. */
-  end = (entry + (skb->len - 1) / TX_BUFF_SZ) & lp->txRingMask;
-  if (!(readl(&lp->tx_ring[end].base) & T_OWN)) {/* Enough room? */
-    /* 
-    ** Caution: the write order is important here... don't set up the
-    ** ownership rights until all the other information is in place.
-    */
-    if (end < entry) {                         /* wrapped buffer */
-      len = (lp->txRingMask - entry + 1) * TX_BUFF_SZ;
-      memcpy_toio(lp->tx_buff[entry], skb->data, len);
-      memcpy_toio(lp->tx_buff[0], skb->data + len, skb->len - len);
-    } else {                                   /* linear buffer */
-      memcpy_toio(lp->tx_buff[entry], skb->data, skb->len);
-    }
-
-    /* set up the buffer descriptors */
-    len = (skb->len < ETH_ZLEN) ? ETH_ZLEN : skb->len;
-    for (i = entry; i != end; i = (++i) & lp->txRingMask) {
-                                               /* clean out flags */
-      writel(readl(&lp->tx_ring[i].base) & ~T_FLAGS, &lp->tx_ring[i].base);
-      writew(0x0000, &lp->tx_ring[i].misc);    /* clears other error flags */
-      writew(-TX_BUFF_SZ, &lp->tx_ring[i].length);/* packet length in buffer */
-      len -= TX_BUFF_SZ;
-    }
-                                               /* clean out flags */
-    writel(readl(&lp->tx_ring[end].base) & ~T_FLAGS, &lp->tx_ring[end].base);
-    writew(0x0000, &lp->tx_ring[end].misc);    /* clears other error flags */
-    writew(-len, &lp->tx_ring[end].length);    /* packet length in last buff */
-
-                                               /* start of packet */
-    writel(readl(&lp->tx_ring[entry].base) | T_STP, &lp->tx_ring[entry].base);
-                                               /* end of packet */
-    writel(readl(&lp->tx_ring[end].base) | T_ENP, &lp->tx_ring[end].base);
-
-    for (i=end; i!=entry; --i) {
-                                               /* ownership of packet */
-      writel(readl(&lp->tx_ring[i].base) | T_OWN, &lp->tx_ring[i].base);
-      if (i == 0) i=lp->txRingMask+1;
-    }   
-    writel(readl(&lp->tx_ring[entry].base) | T_OWN, &lp->tx_ring[entry].base);
-    lp->tx_new = (++end) & lp->txRingMask;     /* update current pointers */
-  } else {
-    status = -1;
-  }
-
-  return status;
-}
-
-/*
-** Look for a particular board name in the EISA configuration space
-*/
-static int __init 
-EISA_signature(char *name, s32 eisa_id)
-{
-  u_int i;
-  const char *signatures[] = DEPCA_SIGNATURE;
-  char ManCode[DEPCA_STRLEN];
-  union {
-    s32 ID;
-    char Id[4];
-  } Eisa;
-  int status = 0;
-
-  *name = '\0';
-  Eisa.ID = inl(eisa_id);
-
-  ManCode[0]=(((Eisa.Id[0]>>2)&0x1f)+0x40);
-  ManCode[1]=(((Eisa.Id[1]&0xe0)>>5)+((Eisa.Id[0]&0x03)<<3)+0x40);
-  ManCode[2]=(((Eisa.Id[2]>>4)&0x0f)+0x30);
-  ManCode[3]=(( Eisa.Id[2]&0x0f)+0x30);
-  ManCode[4]=(((Eisa.Id[3]>>4)&0x0f)+0x30);
-  ManCode[5]='\0';
-
-  for (i=0;(*signatures[i] != '\0') && (*name == '\0');i++) {
-    if (strstr(ManCode, signatures[i]) != NULL) {
-      strcpy(name,ManCode);
-      status = 1;
-    }
-  }
-
-  return status;
-}
-
-static void depca_dbg_open(struct net_device *dev)
-{
-  struct depca_private *lp = (struct depca_private *)dev->priv;
-  u_long ioaddr = dev->base_addr;
-  struct depca_init *p = &lp->init_block;
-  int i; 
-
-  if (depca_debug > 1){
-    /* Do not copy the shadow init block into shared memory */
-    /* Debugging should not affect normal operation! */
-    /* The shadow init block will get copied across during InitRestartDepca */
-    printk("%s: depca open with irq %d\n",dev->name,dev->irq);
-    printk("Descriptor head addresses (CPU):\n");
-    printk("        0x%lx  0x%lx\n",(u_long)lp->rx_ring, (u_long)lp->tx_ring);
-    printk("Descriptor addresses (CPU):\nRX: ");
-    for (i=0;i<lp->rxRingMask;i++){
-      if (i < 3) {
-       printk("0x%8.8lx ", (long) &lp->rx_ring[i].base);
-      }
-    }
-    printk("...0x%8.8lx\n", (long) &lp->rx_ring[i].base);
-    printk("TX: ");
-    for (i=0;i<lp->txRingMask;i++){
-      if (i < 3) {
-       printk("0x%8.8lx ", (long) &lp->tx_ring[i].base);
-      }
-    }
-    printk("...0x%8.8lx\n", (long) &lp->tx_ring[i].base);
-    printk("\nDescriptor buffers (Device):\nRX: ");
-    for (i=0;i<lp->rxRingMask;i++){
-      if (i < 3) {
-       printk("0x%8.8x  ", readl(&lp->rx_ring[i].base));
-      }
-    }
-    printk("...0x%8.8x\n", readl(&lp->rx_ring[i].base));
-    printk("TX: ");
-    for (i=0;i<lp->txRingMask;i++){
-      if (i < 3) {
-       printk("0x%8.8x  ", readl(&lp->tx_ring[i].base));
-      }
-    }
-    printk("...0x%8.8x\n", readl(&lp->tx_ring[i].base));
-    printk("Initialisation block at 0x%8.8lx(Phys)\n",virt_to_phys(lp->sh_mem));
-    printk("        mode: 0x%4.4x\n",p->mode);
-    printk("        physical address: ");
-    for (i=0;i<ETH_ALEN-1;i++){
-      printk("%2.2x:", p->phys_addr[i]);
-    }
-    printk("%2.2x\n", p->phys_addr[i]);
-    printk("        multicast hash table: ");
-    for (i=0;i<(HASH_TABLE_LEN >> 3)-1;i++){
-      printk("%2.2x:", p->mcast_table[i]);
-    }
-    printk("%2.2x\n", p->mcast_table[i]);
-    printk("        rx_ring at: 0x%8.8x\n", p->rx_ring);
-    printk("        tx_ring at: 0x%8.8x\n", p->tx_ring);
-    printk("buffers (Phys): 0x%8.8lx\n",virt_to_phys(lp->sh_mem)+lp->buffs_offset);
-    printk("Ring size:\nRX: %d  Log2(rxRingMask): 0x%8.8x\n", 
-          (int)lp->rxRingMask + 1, 
-          lp->rx_rlen);
-    printk("TX: %d  Log2(txRingMask): 0x%8.8x\n", 
-          (int)lp->txRingMask + 1, 
-          lp->tx_rlen);
-    outw(CSR2,DEPCA_ADDR);
-    printk("CSR2&1: 0x%4.4x",inw(DEPCA_DATA));
-    outw(CSR1,DEPCA_ADDR);
-    printk("%4.4x\n",inw(DEPCA_DATA));
-    outw(CSR3,DEPCA_ADDR);
-    printk("CSR3: 0x%4.4x\n",inw(DEPCA_DATA));
-  }
-
-  return;
-}
-
-/*
-** Perform IOCTL call functions here. Some are privileged operations and the
-** effective uid is checked in those cases.
-** All multicast IOCTLs will not work here and are for testing purposes only.
-*/
-static int depca_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-{
-  struct depca_private *lp = (struct depca_private *)dev->priv;
-  struct depca_ioctl *ioc = (struct depca_ioctl *) &rq->ifr_data;
-  int i, status = 0;
-  u_long ioaddr = dev->base_addr;
-  union {
-    u8  addr[(HASH_TABLE_LEN * ETH_ALEN)];
-    u16 sval[(HASH_TABLE_LEN * ETH_ALEN) >> 1];
-    u32 lval[(HASH_TABLE_LEN * ETH_ALEN) >> 2];
-  } tmp;
-
-  switch(ioc->cmd) {
-  case DEPCA_GET_HWADDR:             /* Get the hardware address */
-    for (i=0; i<ETH_ALEN; i++) {
-      tmp.addr[i] = dev->dev_addr[i];
-    }
-    ioc->len = ETH_ALEN;
-    if (copy_to_user(ioc->data, tmp.addr, ioc->len))
-      return -EFAULT;
-    break;
-
-  case DEPCA_SET_HWADDR:             /* Set the hardware address */
-    if (!capable(CAP_NET_ADMIN)) return -EPERM;
-    if (copy_from_user(tmp.addr, ioc->data, ETH_ALEN))
-      return -EFAULT;
-    for (i=0; i<ETH_ALEN; i++) {
-      dev->dev_addr[i] = tmp.addr[i];
-    }
-    netif_stop_queue(dev);
-    while(lp->tx_old != lp->tx_new);    /* Wait for the ring to empty */
-
-    STOP_DEPCA;                         /* Temporarily stop the depca.  */
-    depca_init_ring(dev);               /* Initialize the descriptor rings */
-    LoadCSRs(dev);                      /* Reload CSR3 */
-    InitRestartDepca(dev);              /* Resume normal operation. */
-    netif_start_queue(dev);             /* Unlock the TX ring */
-    break;
-
-  case DEPCA_SET_PROM:               /* Set Promiscuous Mode */
-    if (!capable(CAP_NET_ADMIN)) return -EPERM;
-    netif_stop_queue(dev);
-    while(lp->tx_old != lp->tx_new);    /* Wait for the ring to empty */
-
-    STOP_DEPCA;                         /* Temporarily stop the depca.  */
-    depca_init_ring(dev);               /* Initialize the descriptor rings */
-    lp->init_block.mode |= PROM;        /* Set promiscuous mode */
-
-    LoadCSRs(dev);                      /* Reload CSR3 */
-    InitRestartDepca(dev);              /* Resume normal operation. */
-    netif_start_queue(dev);             /* Unlock the TX ring */
-    break;
-
-  case DEPCA_CLR_PROM:               /* Clear Promiscuous Mode */
-    if (!capable(CAP_NET_ADMIN)) return -EPERM;
-    netif_stop_queue(dev);
-    while(lp->tx_old != lp->tx_new);    /* Wait for the ring to empty */
-
-    STOP_DEPCA;                         /* Temporarily stop the depca.  */
-    depca_init_ring(dev);               /* Initialize the descriptor rings */
-    lp->init_block.mode &= ~PROM;       /* Clear promiscuous mode */
-
-    LoadCSRs(dev);                      /* Reload CSR3 */
-    InitRestartDepca(dev);              /* Resume normal operation. */
-    netif_start_queue(dev);             /* Unlock the TX ring */
-    break;
-
-  case DEPCA_SAY_BOO:                /* Say "Boo!" to the kernel log file */
-    printk("%s: Boo!\n", dev->name);
-    break;
-
-  case DEPCA_GET_MCA:                /* Get the multicast address table */
-    ioc->len = (HASH_TABLE_LEN >> 3);
-    if (copy_to_user(ioc->data, lp->init_block.mcast_table, ioc->len))
-      return -EFAULT;
-    break;
-
-  case DEPCA_SET_MCA:                /* Set a multicast address */
-    if (!capable(CAP_NET_ADMIN)) return -EPERM;
-    if (copy_from_user(tmp.addr, ioc->data, ETH_ALEN * ioc->len))
-      return -EFAULT;
-    set_multicast_list(dev);
-    break;
-
-  case DEPCA_CLR_MCA:                /* Clear all multicast addresses */
-    if (!capable(CAP_NET_ADMIN)) return -EPERM;
-    set_multicast_list(dev);
-    break;
-
-  case DEPCA_MCA_EN:                 /* Enable pass all multicast addressing */
-    if (!capable(CAP_NET_ADMIN)) return -EPERM;
-      set_multicast_list(dev);
-    break;
-
-  case DEPCA_GET_STATS:              /* Get the driver statistics */
-    cli();
-    ioc->len = sizeof(lp->pktStats);
-    if (copy_to_user(ioc->data, &lp->pktStats, ioc->len))
-      status = -EFAULT;
-    sti();
-    break;
-
-  case DEPCA_CLR_STATS:              /* Zero out the driver statistics */
-    if (!capable(CAP_NET_ADMIN)) return -EPERM;
-    cli();
-    memset(&lp->pktStats, 0, sizeof(lp->pktStats));
-    sti();
-    break;
-
-  case DEPCA_GET_REG:                /* Get the DEPCA Registers */
-    i=0;
-    tmp.sval[i++] = inw(DEPCA_NICSR);
-    outw(CSR0, DEPCA_ADDR);              /* status register */
-    tmp.sval[i++] = inw(DEPCA_DATA);
-    memcpy(&tmp.sval[i], &lp->init_block, sizeof(struct depca_init));
-    ioc->len = i+sizeof(struct depca_init);
-    if (copy_to_user(ioc->data, tmp.addr, ioc->len))
-      return -EFAULT;
-    break;
-
-  default:
-    return -EOPNOTSUPP;
-  }
-
-  return status;
-}
-
-#ifdef MODULE
-static struct net_device thisDepca;
-static int irq=7;      /* EDIT THESE LINE FOR YOUR CONFIGURATION */
-static int io=0x200;    /* Or use the irq= io= options to insmod */
-MODULE_PARM(irq, "i");
-MODULE_PARM(io, "i");
-MODULE_PARM_DESC(irq, "DEPCA IRQ number");
-MODULE_PARM_DESC(io, "DEPCA I/O base address");
-
-/* See depca_probe() for autoprobe messages when a module */   
-int
-init_module(void)
-{
-  thisDepca.irq=irq;
-  thisDepca.base_addr=io;
-  thisDepca.init = depca_probe;
-
-  if (register_netdev(&thisDepca) != 0)
-    return -EIO;
-
-  return 0;
-}
-
-void
-cleanup_module(void)
-{
-  struct depca_private *lp = thisDepca.priv;
-  if (lp) {
-    iounmap(lp->sh_mem);
-#ifdef CONFIG_MCA      
-    if(lp->mca_slot != -1)
-      mca_mark_as_unused(lp->mca_slot);
-#endif                 
-    kfree(lp);
-    thisDepca.priv = NULL;
-  }
-  thisDepca.irq=0;
-
-  unregister_netdev(&thisDepca);
-  release_region(thisDepca.base_addr, DEPCA_TOTAL_SIZE);
-}
-#endif /* MODULE */
-
-\f
-/*
- * Local variables:
- *  compile-command: "gcc -D__KERNEL__ -I/linux/include -Wall -Wstrict-prototypes -fomit-frame-pointer -fno-strength-reduce -malign-loops=2 -malign-jumps=2 -malign-functions=2 -O2 -m486 -c depca.c"
- *
- *  compile-command: "gcc -D__KERNEL__ -DMODULE -I/linux/include -Wall -Wstrict-prototypes -fomit-frame-pointer -fno-strength-reduce -malign-loops=2 -malign-jumps=2 -malign-functions=2 -O2 -m486 -c depca.c"
- * End:
- */
index d319f89faa81d8bed3674cfa4b569288ee757f25..18967c9f6d3eee687670bd66f44b0c2737f75a72 100644 (file)
@@ -290,6 +290,15 @@ pci_set_power_state(struct pci_dev *dev, int state)
        /* enter specified state */
        pci_write_config_word(dev, pm + PCI_PM_CTRL, pmcsr);
 
+       /* Mandatory power management transition delays */
+       /* see PCI PM 1.1 5.6.1 table 18 */
+       if(state == 3 || dev->current_state == 3)
+       {
+               set_current_state(TASK_UNINTERRUPTIBLE);
+               schedule_timeout(HZ/100);
+       }
+       else if(state == 2 || dev->current_state == 2)
+               udelay(200);
        dev->current_state = state;
 
        return 0;
index 5d43181418a727288c803a964f870ce0c155e27e..4aff48a3c3f5d759fa50a195968982eaeeae715d 100644 (file)
 1607  Lava Semiconductor Manufacturing Inc
 1608  Automated Wagering International
 1609  Scimetric Instruments Inc
+1619  FarSite Communications Ltd
+       0400  FarSync T2P (2 port X.21/V.35/V.24)
+       0440  FarSync T4P (4 port X.21/V.35/V.24)
 1668  Action Tec Electronics Inc
 1813  Ambient Technologies Inc
 1a08  Sierra semiconductor
index 3f7f7e8bd193c1ed7a665db5d0a94f2639536b90..e4757451ab179272b91b9c667a27885a7ed828e0 100644 (file)
@@ -211,7 +211,7 @@ static void handle_erase_timeout(u_long arg)
     retry_erase((erase_busy_t *)arg, MTD_REQ_TIMEOUT);
 }
 
-static void setup_erase_request(client_handle_t handle, eraseq_entry_t *erase)
+static int setup_erase_request(client_handle_t handle, eraseq_entry_t *erase)
 {
     erase_busy_t *busy;
     region_info_t *info;
@@ -229,6 +229,8 @@ static void setup_erase_request(client_handle_t handle, eraseq_entry_t *erase)
        else {
            erase->State = 1;
            busy = kmalloc(sizeof(erase_busy_t), GFP_KERNEL);
+           if (!busy)
+               return CS_GENERAL_FAILURE;
            busy->erase = erase;
            busy->client = handle;
            init_timer(&busy->timeout);
@@ -238,6 +240,7 @@ static void setup_erase_request(client_handle_t handle, eraseq_entry_t *erase)
            retry_erase(busy, 0);
        }
     }
+    return CS_SUCCESS;
 } /* setup_erase_request */
 
 /*======================================================================
@@ -322,7 +325,7 @@ int MTDHelperEntry(int func, void *a1, void *a2)
     
 ======================================================================*/
 
-static void setup_regions(client_handle_t handle, int attr,
+static int setup_regions(client_handle_t handle, int attr,
                          memory_handle_t *list)
 {
     int i, code, has_jedec, has_geo;
@@ -337,7 +340,7 @@ static void setup_regions(client_handle_t handle, int attr,
 
     code = (attr) ? CISTPL_DEVICE_A : CISTPL_DEVICE;
     if (read_tuple(handle, code, &device) != CS_SUCCESS)
-       return;
+       return CS_GENERAL_FAILURE;
     code = (attr) ? CISTPL_JEDEC_A : CISTPL_JEDEC_C;
     has_jedec = (read_tuple(handle, code, &jedec) == CS_SUCCESS);
     if (has_jedec && (device.ndev != jedec.nid)) {
@@ -360,6 +363,8 @@ static void setup_regions(client_handle_t handle, int attr,
        if ((device.dev[i].type != CISTPL_DTYPE_NULL) &&
            (device.dev[i].size != 0)) {
            r = kmalloc(sizeof(*r), GFP_KERNEL);
+           if (!r)
+               return CS_GENERAL_FAILURE;
            r->region_magic = REGION_MAGIC;
            r->state = 0;
            r->dev_info[0] = '\0';
@@ -384,6 +389,7 @@ static void setup_regions(client_handle_t handle, int attr,
        }
        offset += device.dev[i].size;
     }
+    return CS_SUCCESS;
 } /* setup_regions */
 
 /*======================================================================
@@ -417,8 +423,10 @@ int pcmcia_get_first_region(client_handle_t handle, region_info_t *rgn)
     
     if ((handle->Attributes & INFO_MASTER_CLIENT) &&
        (!(s->state & SOCKET_REGION_INFO))) {
-       setup_regions(handle, 0, &s->c_region);
-       setup_regions(handle, 1, &s->a_region);
+       if (setup_regions(handle, 0, &s->c_region) != CS_SUCCESS)
+           return CS_GENERAL_FAILURE;
+       if (setup_regions(handle, 1, &s->a_region) != CS_SUCCESS)
+           return CS_GENERAL_FAILURE;
        s->state |= SOCKET_REGION_INFO;
     }
 
index 00b3eba885259781509180b2d484b7f7350d152a..e84b0e6b3260726dd4242379ac62c0e4984d96b6 100644 (file)
 #include <linux/types.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/proc_fs.h>
 #include <linux/init.h>
index 2300f5d1beccfd99eb97ad2d7a1245590d45f80b..758b6c4655fc440fabaf534c80e519c10562a8ca 100644 (file)
@@ -15,7 +15,7 @@
  *    derived from this software without specific prior written permission.
  *
  * Alternatively, this software may be distributed under the terms of the
- * GNU Public License ("GPL").
+ * GNU General Public License ("GPL").
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
index e9019e9e71d944ebc565ff32834e34c35e77750b..63eb12b912e92420c0f67b2bafa390a6a177248b 100644 (file)
@@ -14,7 +14,7 @@
  *    derived from this software without specific prior written permission.
  *
  * Alternatively, this software may be distributed under the terms of the
- * GNU Public License ("GPL").
+ * GNU General Public License ("GPL").
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
index 77f11ef9779dab21c51233e7746cecd1153bccd1..5d0d9dc0c36ed372e11b7da2d6b48de3eeff41f6 100644 (file)
@@ -14,7 +14,7 @@
  *    derived from this software without specific prior written permission.
  *
  * Alternatively, this software may be distributed under the terms of the
- * GNU Public License ("GPL").
+ * GNU General Public License ("GPL").
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
index a4da0996f053ab41f02c006fadf3b42e58413874..ca789ab97353459f7cc082894c84ee6c9b46b283 100644 (file)
@@ -14,7 +14,7 @@
  *    derived from this software without specific prior written permission.
  *
  * Alternatively, this software may be distributed under the terms of the
- * GNU Public License ("GPL").
+ * GNU General Public License ("GPL").
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
index 47ffb4ec43bac4245a21b037072dc81b5cf702b0..916d7b48c4555f1b84878dd5d96926110aaf8c89 100644 (file)
@@ -52,7 +52,7 @@
  *    derived from this software without specific prior written permission.
  *
  * Alternatively, this software may be distributed under the terms of the
- * GNU Public License ("GPL").
+ * GNU General Public License ("GPL").
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
index b037e306971f63356e8565d3388db819d818dc3a..9b8465b4a748b4c84beefe232124cfd158c6ea77 100644 (file)
@@ -14,7 +14,7 @@
  *    derived from this software without specific prior written permission.
  *
  * Alternatively, this software may be distributed under the terms of the
- * GNU Public License ("GPL").
+ * GNU General Public License ("GPL").
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
index 8f77057f0b5b749c0c19d831a84091221fe4ab66..4e93f37b59a28bc6a17becbb696d873975845e9a 100644 (file)
@@ -16,7 +16,7 @@
  *    derived from this software without specific prior written permission.
  *
  * Alternatively, this software may be distributed under the terms of the
- * GNU Public License ("GPL").
+ * GNU General Public License ("GPL").
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
index f5a79c106963993d6e3b574bc08b789c8c9ca94d..4b87bbe3e5afb9a1451566b61ec107d488e28da1 100644 (file)
@@ -12,7 +12,7 @@
  *    derived from this software without specific prior written permission.
  *
  * Alternatively, this software may be distributed under the terms of the
- * GNU Public License ("GPL").
+ * GNU General Public License ("GPL").
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
index 7f95c89d25dcc62b7186f8f6668994c522f6a1e3..cdc7e2a998e240d8b1e5756359e4730b6a61d209 100644 (file)
@@ -14,7 +14,7 @@
  *    derived from this software without specific prior written permission.
  *
  * Alternatively, this software may be distributed under the terms of the
- * GNU Public License ("GPL").
+ * GNU General Public License ("GPL").
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
index 0dd2d8f343876a8ad3b68825ff055536dee34298..c64cb692b06b0781ca8b6bfadb12a7941af3b2a4 100644 (file)
@@ -14,7 +14,7 @@
  *    derived from this software without specific prior written permission.
  *
  * Alternatively, this software may be distributed under the terms of the
- * GNU Public License ("GPL").
+ * GNU General Public License ("GPL").
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
index d944786c6fb31819422c8d35cf5ebf11fb761e9a..15b5e3fb5de0f50fd2428f9d846fed0e15c64011 100644 (file)
@@ -1218,7 +1218,6 @@ match:
                tasklet_init(&woinst->timer.tasklet, emu10k1_waveout_bh, (unsigned long) wave_dev);
                wave_dev->woinst = woinst;
                emu10k1_waveout_setformat(wave_dev, &woinst->format);
-
        }
 
        file->private_data = (void *) wave_dev;
@@ -1261,7 +1260,7 @@ static int emu10k1_audio_release(struct inode *inode, struct file *file)
 
                spin_unlock_irqrestore(&woinst->lock, flags);
                /* wait for the tasklet (bottom-half) to finish */
-               tasklet_unlock_wait(&woinst->timer.tasklet);
+               tasklet_kill(&woinst->timer.tasklet);
                kfree(wave_dev->woinst);
        }
 
@@ -1275,7 +1274,7 @@ static int emu10k1_audio_release(struct inode *inode, struct file *file)
                }
 
                spin_unlock_irqrestore(&wiinst->lock, flags);
-               tasklet_unlock_wait(&wiinst->timer.tasklet);
+               tasklet_kill(&wiinst->timer.tasklet);
                kfree(wave_dev->wiinst);
        }
 
@@ -1491,6 +1490,9 @@ void emu10k1_wavein_bh(unsigned long refdata)
        u32 bytestocopy;
        unsigned long flags;
 
+       if (!wiinst)
+               return;
+
        spin_lock_irqsave(&wiinst->lock, flags);
 
        if (!(wiinst->state & WAVE_STATE_STARTED)) {
@@ -1518,6 +1520,9 @@ void emu10k1_waveout_bh(unsigned long refdata)
        u32 bytestocopy;
        unsigned long flags;
 
+       if (!woinst)
+               return;
+
        spin_lock_irqsave(&woinst->lock, flags);
 
        if (!(woinst->state & WAVE_STATE_STARTED)) {
index 01ca8df1137f51d5053c1931efcd41d4c8ed7c04..950ca1ec9b61e2e0a454140dc4e20bb51dc63354 100644 (file)
@@ -370,10 +370,10 @@ err_out1:
 
 static void __devinit emu10k1_midi_cleanup(struct emu10k1_card *card)
 {
-    tasklet_unlock_wait(&card->mpuout->tasklet);
+    tasklet_kill(&card->mpuout->tasklet);
     kfree(card->mpuout);
 
-    tasklet_unlock_wait(&card->mpuin->tasklet);
+    tasklet_kill(&card->mpuin->tasklet);
     kfree(card->mpuin);
 
 #ifdef EMU10K1_SEQUENCER
index 79029520b1a02e6b2ca71d7e6386656ea37221ed..f3b0922799386c0eaa06073da3f09fd2c048921f 100644 (file)
@@ -1451,7 +1451,7 @@ static int i810_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
                if (get_user(val, (int *)arg))
                        return -EFAULT;
                if(val==0) {
-                       ret = -EINVAL;
+                       return -EINVAL;
                } else {
                        ret = 1;
                }
diff --git a/drivers/usb/CDCEther.c b/drivers/usb/CDCEther.c
new file mode 100644 (file)
index 0000000..0b8d2bc
--- /dev/null
@@ -0,0 +1,1279 @@
+// Portions of this file taken from 
+// Petko Manolov - Petkan (petkan@dce.bg)
+// from his driver pegasus.c
+
+/*
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/usb.h>
+#include <linux/module.h>
+#include "CDCEther.h"
+
+static const char *version = __FILE__ ": v0.98.4 4 July 2001 Brad Hards and another";
+
+// We will attempt to probe anything that is in the
+// communication device class...
+// We will sort through them later.
+static struct usb_device_id CDCEther_ids[] = {
+       { USB_DEVICE_INFO(2, 0, 0) },
+       { }
+};
+
+//////////////////////////////////////////////////////////////////////////////
+// Callback routines from USB device /////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+static void read_bulk_callback( struct urb *urb )
+{
+       ether_dev_t *ether_dev = urb->context;
+       struct net_device *net;
+       int count = urb->actual_length, res;
+       struct sk_buff  *skb;
+
+       // Sanity check 
+       if ( !ether_dev || !(ether_dev->flags & CDC_ETHER_RUNNING) ) {
+               dbg("BULK IN callback but driver is not active!");
+               return;
+       }
+
+       net = ether_dev->net;
+       if ( !netif_device_present(net) ) {
+               // Somebody killed our network interface...
+               return;
+       }
+
+       if ( ether_dev->flags & CDC_ETHER_RX_BUSY ) {
+               // Are we already trying to receive a frame???
+               ether_dev->stats.rx_errors++;
+               dbg("ether_dev Rx busy");
+               return;
+       }
+
+       // We are busy, leave us alone!
+       ether_dev->flags |= CDC_ETHER_RX_BUSY;
+
+       switch ( urb->status ) {
+               case USB_ST_NOERROR:
+                       break;
+               case USB_ST_NORESPONSE:
+                       dbg( "no repsonse in BULK IN" );
+                       ether_dev->flags &= ~CDC_ETHER_RX_BUSY;
+                       break;
+               default:
+                       dbg( "%s: RX status %d", net->name, urb->status );
+                       goto goon;
+       }
+
+       // Check to make sure we got some data...
+       if ( !count ) {
+               // We got no data!!!
+               goto goon;
+       }
+
+       // Tell the kernel we want some memory
+       if ( !(skb = dev_alloc_skb(count)) ) {
+               // We got no receive buffer.
+               goto goon;
+       }
+
+       // Here's where it came from
+       skb->dev = net;
+       
+       // Now we copy it over
+       eth_copy_and_sum(skb, ether_dev->rx_buff, count, 0);
+       
+       // Not sure
+       skb_put(skb, count);
+       // Not sure here either
+       skb->protocol = eth_type_trans(skb, net);
+       
+       // Ship it off to the kernel
+       netif_rx(skb);
+       
+       // update out statistics
+       ether_dev->stats.rx_packets++;
+       ether_dev->stats.rx_bytes += count;
+
+goon:
+       // Prep the USB to wait for another frame
+       FILL_BULK_URB( &ether_dev->rx_urb, ether_dev->usb,
+                       usb_rcvbulkpipe(ether_dev->usb, ether_dev->data_ep_in),
+                       ether_dev->rx_buff, ether_dev->wMaxSegmentSize, 
+                       read_bulk_callback, ether_dev );
+                       
+       // Give this to the USB subsystem so it can tell us 
+       // when more data arrives.
+       if ( (res = usb_submit_urb(&ether_dev->rx_urb)) ) {
+               warn( __FUNCTION__ " failed submint rx_urb %d", res);
+       }
+       
+       // We are no longer busy, show us the frames!!!
+       ether_dev->flags &= ~CDC_ETHER_RX_BUSY;
+}
+
+static void write_bulk_callback( struct urb *urb )
+{
+       ether_dev_t *ether_dev = urb->context;
+
+       // Sanity check
+       if ( !ether_dev || !(ether_dev->flags & CDC_ETHER_RUNNING) ) {
+               // We are insane!!!
+               err( "write_bulk_callback: device not running" );
+               return;
+       }
+
+       // Do we still have a valid kernel network device?
+       if ( !netif_device_present(ether_dev->net) ) {
+               // Someone killed our network interface.
+               err( "write_bulk_callback: net device not present" );
+               return;
+       }
+
+       // Hmm...  What on Earth could have happened???
+       if ( urb->status ) {
+               info("%s: TX status %d", ether_dev->net->name, urb->status);
+       }
+
+       // Update the network interface and tell it we are
+       // ready for another frame
+       ether_dev->net->trans_start = jiffies;
+       netif_wake_queue( ether_dev->net );
+}
+
+//static void intr_callback( struct urb *urb )
+//{
+//     ether_dev_t *ether_dev = urb->context;
+//     struct net_device *net;
+//     __u8    *d;
+//
+//     if ( !ether_dev )
+//             return;
+//             
+//     switch ( urb->status ) {
+//             case USB_ST_NOERROR:
+//                     break;
+//             case USB_ST_URB_KILLED:
+//                     return;
+//             default:
+//                     info("intr status %d", urb->status);
+//     }
+//
+//     d = urb->transfer_buffer;
+//     net = ether_dev->net;
+//     if ( d[0] & 0xfc ) {
+//             ether_dev->stats.tx_errors++;
+//             if ( d[0] & TX_UNDERRUN )
+//                     ether_dev->stats.tx_fifo_errors++;
+//             if ( d[0] & (EXCESSIVE_COL | JABBER_TIMEOUT) )
+//                     ether_dev->stats.tx_aborted_errors++;
+//             if ( d[0] & LATE_COL )
+//                     ether_dev->stats.tx_window_errors++;
+//             if ( d[0] & (NO_CARRIER | LOSS_CARRIER) )
+//                     ether_dev->stats.tx_carrier_errors++;
+//     }
+//}
+
+//////////////////////////////////////////////////////////////////////////////
+// Routines for turning net traffic on and off on the USB side ///////////////
+//////////////////////////////////////////////////////////////////////////////
+
+static inline int enable_net_traffic( ether_dev_t *ether_dev )
+{
+       struct usb_device *usb = ether_dev->usb;
+
+       // Here would be the time to set the data interface to the configuration where
+       // it has two endpoints that use a protocol we can understand.
+
+       if (usb_set_interface( usb, 
+                               ether_dev->data_bInterfaceNumber, 
+                               ether_dev->data_bAlternateSetting_with_traffic ) )  {
+               err("usb_set_interface() failed" );
+               err("Attempted to set interface %d", ether_dev->data_bInterfaceNumber);
+               err("To alternate setting       %d", ether_dev->data_bAlternateSetting_with_traffic);
+               return -1;
+       }
+       return 0;
+}
+
+static inline void disable_net_traffic( ether_dev_t *ether_dev )
+{
+       // The thing to do is to set the data interface to the alternate setting that has
+       // no endpoints.  This is what the spec suggests.
+
+       if (ether_dev->data_interface_altset_num_without_traffic >= 0 ) {
+               if (usb_set_interface( ether_dev->usb, 
+                                       ether_dev->data_bInterfaceNumber, 
+                                       ether_dev->data_bAlternateSetting_without_traffic ) )   {
+                       err("usb_set_interface() failed");
+               }
+       } else {
+               // Some devices just may not support this...
+               warn("No way to disable net traffic");
+       }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Callback routines for kernel Ethernet Device //////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+static void CDCEther_tx_timeout( struct net_device *net )
+{
+       ether_dev_t *ether_dev = net->priv;
+
+       // Sanity check
+       if ( !ether_dev ) {
+               // Seems to be a case of insanity here
+               return;
+       }
+
+       // Tell syslog we are hosed.
+       warn("%s: Tx timed out.", net->name);
+       
+       // Tear the waiting frame off the list
+       ether_dev->tx_urb.transfer_flags |= USB_ASYNC_UNLINK;
+       usb_unlink_urb( &ether_dev->tx_urb );
+       
+       // Update statistics
+       ether_dev->stats.tx_errors++;
+}
+
+static int CDCEther_start_xmit( struct sk_buff *skb, struct net_device *net )
+{
+       ether_dev_t     *ether_dev = net->priv;
+       int     count;
+       int     res;
+
+       // If we are told to transmit an ethernet frame that fits EXACTLY 
+       // into an integer number of USB packets, we force it to send one 
+       // more byte so the device will get a runt USB packet signalling the 
+       // end of the ethernet frame
+       if ( (skb->len) ^ (ether_dev->data_ep_out_size) ) {
+               // It was not an exact multiple
+               // no need to add anything extra
+               count = skb->len;
+       } else {
+               // Add one to make it NOT an exact multiple
+               count = skb->len + 1;
+       }
+
+       // Tell the kernel, "No more frames 'til we are done
+       // with this one.'
+       netif_stop_queue( net );
+
+       // Copy it from kernel memory to OUR memory
+       memcpy(ether_dev->tx_buff, skb->data, skb->len);
+
+       // Fill in the URB for shipping it out.
+       FILL_BULK_URB( &ether_dev->tx_urb, ether_dev->usb,
+                       usb_sndbulkpipe(ether_dev->usb, ether_dev->data_ep_out),
+                       ether_dev->tx_buff, ether_dev->wMaxSegmentSize, 
+                       write_bulk_callback, ether_dev );
+
+       // Tell the URB how much it will be transporting today
+       ether_dev->tx_urb.transfer_buffer_length = count;
+       
+       // Send the URB on its merry way.
+       if ((res = usb_submit_urb(&ether_dev->tx_urb)))  {
+               // Hmm...  It didn't go. Tell someone...
+               warn("failed tx_urb %d", res);
+               // update some stats...
+               ether_dev->stats.tx_errors++;
+               // and tell the kernel to give us another.
+               // Maybe we'll get it right next time.
+               netif_start_queue( net );
+       } else {
+               // Okay, it went out.
+               // Update statistics
+               ether_dev->stats.tx_packets++;
+               ether_dev->stats.tx_bytes += skb->len;
+               // And tell the kernel when the last transmit occurred.
+               net->trans_start = jiffies;
+       }
+
+       // We are done with the kernel's memory
+       dev_kfree_skb(skb);
+
+       // We are done here.
+       return 0;
+}
+
+static struct net_device_stats *CDCEther_netdev_stats( struct net_device *net )
+{
+       // Easy enough!
+       return &((ether_dev_t *)net->priv)->stats;
+}
+
+static int CDCEther_open(struct net_device *net)
+{
+       ether_dev_t *ether_dev = (ether_dev_t *)net->priv;
+       int     res;
+
+       // We are finally getting used!
+       MOD_INC_USE_COUNT;
+
+       // Turn on the USB and let the packets flow!!!
+       if ( (res = enable_net_traffic( ether_dev )) ) {
+               err( __FUNCTION__ "can't enable_net_traffic() - %d", res );
+               MOD_DEC_USE_COUNT;
+               return -EIO;
+       }
+
+       // Prep a receive URB
+       FILL_BULK_URB( &ether_dev->rx_urb, ether_dev->usb,
+                       usb_rcvbulkpipe(ether_dev->usb, ether_dev->data_ep_in),
+                       ether_dev->rx_buff, ether_dev->wMaxSegmentSize, 
+                       read_bulk_callback, ether_dev );
+
+       // Put it out there so the device can send us stuff
+       if ( (res = usb_submit_urb(&ether_dev->rx_urb)) )
+       {
+               // Hmm...  Okay...
+               warn( __FUNCTION__ " failed rx_urb %d", res );
+       }
+
+       // Tell the kernel we are ready to start receiving from it
+       netif_start_queue( net );
+       
+       // We are up and running.
+       ether_dev->flags |= CDC_ETHER_RUNNING;
+
+       // Let's get ready to move frames!!!
+       return 0;
+}
+
+static int CDCEther_close( struct net_device *net )
+{
+       ether_dev_t     *ether_dev = net->priv;
+
+       // We are no longer running.
+       ether_dev->flags &= ~CDC_ETHER_RUNNING;
+       
+       // Tell the kernel to stop sending us stuff
+       netif_stop_queue( net );
+       
+       // If we are not already unplugged, turn off USB
+       // traffic
+       if ( !(ether_dev->flags & CDC_ETHER_UNPLUG) ) {
+               disable_net_traffic( ether_dev );
+       }
+
+       // We don't need the URBs anymore.
+       usb_unlink_urb( &ether_dev->rx_urb );
+       usb_unlink_urb( &ether_dev->tx_urb );
+       usb_unlink_urb( &ether_dev->intr_urb );
+       
+       // We are not being used now.
+       MOD_DEC_USE_COUNT;
+
+       // That's it.  I'm done.
+       return 0;
+}
+
+static int CDCEther_ioctl( struct net_device *net, struct ifreq *rq, int cmd )
+{
+       //__u16 *data = (__u16 *)&rq->ifr_data;
+       //ether_dev_t   *ether_dev = net->priv;
+
+       // No support here yet.
+       // Do we need support???
+       switch(cmd) {
+               case SIOCDEVPRIVATE:
+                       return -EOPNOTSUPP;
+               case SIOCDEVPRIVATE+1:
+                       return -EOPNOTSUPP;
+               case SIOCDEVPRIVATE+2:
+                       //return 0;
+                       return -EOPNOTSUPP;
+               default:
+                       return -EOPNOTSUPP;
+       }
+}
+
+static void CDCEther_set_multicast( struct net_device *net )
+{
+       ether_dev_t *ether_dev = net->priv;
+
+       // Tell the kernel to stop sending us frames while we get this
+       // all set up.
+       netif_stop_queue(net);
+
+       // Do what we are told.
+       if (net->flags & IFF_PROMISC) {
+               // TODO - Turn on promiscuous mode
+               info( "%s: Promiscuous mode enabled", net->name);
+       } else if (net->flags & IFF_ALLMULTI){
+               // TODO - Here we need to tell the device to block ALL multicast traffic.
+               info("%s: set allmulti", net->name);
+       } else if (net->mc_count > ether_dev->wNumberMCFilters) {
+               // TODO - Here we need to set multicast filters, but
+               // There are more than our limit...  Hmm...
+               info("%s: set too many MC filters", net->name);
+       } else {
+               // TODO - Here we are supposed to set SOME of the multicast filters.
+               // I must learn how to do this...
+               //info("%s: set Rx mode", net->name);
+       }
+
+       // Tell the kernel to start giving frames to us again.
+       netif_wake_queue(net);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Routines used to parse out the Functional Descriptors /////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+static int parse_header_functional_descriptor( int *bFunctionLength, 
+                                               int bDescriptorType, 
+                                               int bDescriptorSubtype,
+                                               unsigned char *data,
+                                               ether_dev_t *ether_dev,
+                                               int *requirements )
+{
+       // Check to make sure we haven't seen one of these already.
+       if ( (~*requirements) & REQ_HDR_FUNC_DESCR ) {
+               err( "Multiple Header Functional Descriptors found." );
+               return -1;
+       }
+       
+       // Is it the right size???
+       if (*bFunctionLength != 5) {
+               info( "Invalid length in Header Functional Descriptor" );
+               // This is a hack to get around a particular device (NO NAMES)
+               // It has this function length set to the length of the
+               // whole class-specific descriptor
+               *bFunctionLength = 5;
+       }
+       
+       // Nothing extremely useful here.
+       // We'll keep it for posterity
+       ether_dev->bcdCDC = data[0] + (data[1] << 8);
+       dbg( "Found Header descriptor, CDC version %x", ether_dev->bcdCDC);
+
+       // We've seen one of these
+       *requirements &= ~REQ_HDR_FUNC_DESCR;
+       
+       // It's all good.
+       return 0;
+}
+
+static int parse_union_functional_descriptor( int *bFunctionLength, 
+                                              int bDescriptorType, 
+                                              int bDescriptorSubtype,
+                                              unsigned char *data,
+                                              ether_dev_t *ether_dev,
+                                              int *requirements )
+{
+       // Check to make sure we haven't seen one of these already.
+       if ( (~*requirements) & REQ_UNION_FUNC_DESCR ) {
+               err( "Multiple Union Functional Descriptors found." );
+               return -1;
+       }
+
+       // Is it the right size?
+       if (*bFunctionLength != 5) {
+               // It is NOT the size we expected.
+               err( "Unsupported length in Union Functional Descriptor" );
+               return -1;
+       }
+       
+       // Sanity check of sorts
+       if (ether_dev->comm_interface != data[0]) {
+               // This tells us that we are chasing the wrong comm
+               // interface or we are crazy or something else weird.
+               if (ether_dev->comm_interface == data[1]) {
+                       info( "Probably broken Union descriptor, fudging data interface" );
+                       // We'll need this in a few microseconds, 
+                       // so guess here, and hope for the best
+                       ether_dev->data_interface = data[0];
+               } else {
+                       err( "Union Functional Descriptor is broken beyond repair" );
+                       return -1;
+               }
+       } else{ // Descriptor is OK
+                       // We'll need this in a few microseconds!
+               ether_dev->data_interface = data[1];
+       }
+
+       // We've seen one of these now.
+       *requirements &= ~REQ_UNION_FUNC_DESCR;
+       
+       // Done
+       return 0;
+}
+
+static int parse_ethernet_functional_descriptor( int *bFunctionLength, 
+                                                 int bDescriptorType, 
+                                                 int bDescriptorSubtype,
+                                                 unsigned char *data,
+                                                 ether_dev_t *ether_dev,
+                                                 int *requirements )
+{
+       // Check to make sure we haven't seen one of these already.
+       if ( (~*requirements) & REQ_ETH_FUNC_DESCR ) {
+               err( "Multiple Ethernet Functional Descriptors found." );
+               return -1;
+       }
+       
+       // Is it the right size?
+       if (*bFunctionLength != 13) {
+               err( "Invalid length in Ethernet Networking Functional Descriptor" );
+               return -1;
+       }
+       
+       // Lots of goodies from this one.  They are all important.
+       ether_dev->iMACAddress = data[0];
+       ether_dev->bmEthernetStatistics = data[1] + (data[2] << 8) + (data[3] << 16) + (data[4] << 24);
+       ether_dev->wMaxSegmentSize = data[5] + (data[6] << 8);
+       ether_dev->wNumberMCFilters = (data[7] + (data[8] << 8)) & 0x00007FFF;
+       ether_dev->bNumberPowerFilters = data[9];
+       
+       // We've seen one of these now.
+       *requirements &= ~REQ_ETH_FUNC_DESCR;
+       
+       // That's all she wrote.
+       return 0;
+}
+
+static int parse_protocol_unit_functional_descriptor( int *bFunctionLength, 
+                                                      int bDescriptorType, 
+                                                      int bDescriptorSubtype,
+                                                      unsigned char *data,
+                                                      ether_dev_t *ether_dev,
+                                                      int *requirements )
+{
+       // There should only be one type if we are sane
+       if (bDescriptorType != CS_INTERFACE) {
+               info( "Invalid bDescriptorType found." );
+               return -1;
+       }
+
+       // The Subtype tells the tale.
+       switch (bDescriptorSubtype){
+               case 0x00:      // Header Functional Descriptor
+                       return parse_header_functional_descriptor( bFunctionLength,
+                                                                  bDescriptorType,
+                                                                  bDescriptorSubtype,
+                                                                  data,
+                                                                  ether_dev,
+                                                                  requirements );
+                       break;
+               case 0x06:      // Union Functional Descriptor
+                       return parse_union_functional_descriptor( bFunctionLength,
+                                                                 bDescriptorType,
+                                                                 bDescriptorSubtype,
+                                                                 data,
+                                                                 ether_dev,
+                                                                 requirements );
+                       break;
+               case 0x0F:      // Ethernet Networking Functional Descriptor
+                       return parse_ethernet_functional_descriptor( bFunctionLength,
+                                                                    bDescriptorType,
+                                                                    bDescriptorSubtype,
+                                                                    data,
+                                                                    ether_dev,
+                                                                    requirements );
+                       break;
+               default:        // We don't support this at this time...
+                       // However that doesn't necessarily indicate an error.
+                       dbg( "Unexpected header type %x:", bDescriptorSubtype );
+                       return 0;
+       }
+       // How did we get here???
+       return -1;
+}
+
+static int parse_ethernet_class_information( unsigned char *data, int length, ether_dev_t *ether_dev )
+{
+       int loc = 0;
+       int rc;
+       int bFunctionLength;
+       int bDescriptorType;
+       int bDescriptorSubtype;
+       int requirements = REQUIREMENTS_TOTAL;
+
+       // As long as there is something here, we will try to parse it
+       while (loc < length) {
+               // Length
+               bFunctionLength = data[loc];
+               loc++;
+               
+               // Type
+               bDescriptorType = data[loc];
+               loc++;
+               
+               // Subtype
+               bDescriptorSubtype = data[loc];
+               loc++;
+               
+               // ship this off to be processed elsewhere.
+               rc = parse_protocol_unit_functional_descriptor( &bFunctionLength, 
+                                                               bDescriptorType, 
+                                                               bDescriptorSubtype, 
+                                                               &data[loc],
+                                                               ether_dev,
+                                                               &requirements );
+               // Did it process okay?
+               if (rc) {
+                       // Something was hosed somewhere.
+                       // No need to continue;
+                       err("Bad descriptor parsing: %x", rc );
+                       return -1;
+               }
+               // We have already taken three bytes.
+               loc += (bFunctionLength - 3);
+       }
+       // Check to see if we got everything we need.
+       if (requirements) {
+               // We missed some of the requirements...
+               err( "Not all required functional descriptors present 0x%08X", requirements );
+               return -1;
+       }
+       // We got everything.
+       return 0;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Routine to check for the existence of the Functional Descriptors //////////
+//////////////////////////////////////////////////////////////////////////////
+
+static int find_and_parse_ethernet_class_information( struct usb_device *device, ether_dev_t *ether_dev )
+{
+       struct usb_config_descriptor *conf = NULL;
+       struct usb_interface *comm_intf_group = NULL;
+       struct usb_interface_descriptor *comm_intf = NULL;
+       int rc = -1;
+       // The assumption here is that find_ethernet_comm_interface
+       // and find_valid_configuration 
+       // have already filled in the information about where to find
+       // the a valid commication interface.
+
+       conf = &( device->config[ether_dev->configuration_num] );
+       comm_intf_group = &( conf->interface[ether_dev->comm_interface] );
+       comm_intf = &( comm_intf_group->altsetting[ether_dev->comm_interface_altset_num] );
+       // Let's check and see if it has the extra information we need...
+
+       if (comm_intf->extralen > 0) {
+               // This is where the information is SUPPOSED to be.
+               rc = parse_ethernet_class_information( comm_intf->extra, comm_intf->extralen, ether_dev );
+       } else if (conf->extralen > 0) {
+               // This is a hack.  The spec says it should be at the interface 
+               // location checked above.  However I have seen it here also.
+               // This is the same device that requires the functional descriptor hack above
+               warn( "Ethernet information found at device configuration.  This is broken." );
+               rc = parse_ethernet_class_information( conf->extra, conf->extralen, ether_dev );
+       } else  {
+               // I don't know where else to look.
+               warn( "No ethernet information found." );
+               rc = -1;
+       }
+       return rc;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Routines to verify the data interface /////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+static int get_data_interface_endpoints( struct usb_device *device, ether_dev_t *ether_dev )
+{
+       struct usb_config_descriptor *conf = NULL;
+       struct usb_interface *data_intf_group = NULL;
+       struct usb_interface_descriptor *data_intf = NULL;
+       
+       // Walk through and get to the data interface we are checking.
+       conf = &( device->config[ether_dev->configuration_num] );
+       data_intf_group = &( conf->interface[ether_dev->data_interface] );
+       data_intf = &( data_intf_group->altsetting[ether_dev->data_interface_altset_num_with_traffic] );
+
+       // Start out assuming we won't find anything we can use
+       ether_dev->data_ep_in = 0;
+       ether_dev->data_ep_out = 0;
+       
+       // If these are not BULK endpoints, we don't want them
+       if ( data_intf->endpoint[0].bmAttributes != 0x02 ) {
+               return -1;
+       } if ( data_intf->endpoint[1].bmAttributes != 0x02 ) {
+               return -1;
+       }
+
+       // Check the first endpoint to see if it is IN or OUT
+       if ( data_intf->endpoint[0].bEndpointAddress & 0x80 ) {
+               // This endpoint is IN
+               ether_dev->data_ep_in = data_intf->endpoint[0].bEndpointAddress & 0x7F;
+       } else {
+               // This endpoint is OUT
+               ether_dev->data_ep_out = data_intf->endpoint[0].bEndpointAddress & 0x7F;
+               ether_dev->data_ep_out_size = data_intf->endpoint[0].wMaxPacketSize;
+       }
+
+       // Check the second endpoint to see if it is IN or OUT
+       if ( data_intf->endpoint[1].bEndpointAddress & 0x80 ) {
+               // This endpoint is IN
+               ether_dev->data_ep_in = data_intf->endpoint[1].bEndpointAddress & 0x7F;
+       } else  {
+               // This endpoint is OUT
+               ether_dev->data_ep_out = data_intf->endpoint[1].bEndpointAddress & 0x7F;
+               ether_dev->data_ep_out_size = data_intf->endpoint[1].wMaxPacketSize;
+       }
+       
+       // Now make sure we got both an IN and an OUT
+       if (ether_dev->data_ep_in && ether_dev->data_ep_out) {
+               // We did get both, we are in good shape...
+               info( "detected BULK OUT packets of size %d", ether_dev->data_ep_out_size );
+               return 0;
+       }
+       return -1;
+}
+
+static int verify_ethernet_data_interface( struct usb_device *device, ether_dev_t *ether_dev )
+{
+       struct usb_config_descriptor *conf = NULL;
+       struct usb_interface *data_intf_group = NULL;
+       struct usb_interface_descriptor *data_intf = NULL;
+       int rc = -1;
+       int status;
+       int altset_num;
+
+       // The assumption here is that parse_ethernet_class_information()
+       // and find_valid_configuration() 
+       // have already filled in the information about where to find
+       // a data interface
+       conf = &( device->config[ether_dev->configuration_num] );
+       data_intf_group = &( conf->interface[ether_dev->data_interface] );
+
+       // start out assuming we won't find what we are looking for.
+       ether_dev->data_interface_altset_num_with_traffic = -1;
+       ether_dev->data_bAlternateSetting_with_traffic = -1;
+       ether_dev->data_interface_altset_num_without_traffic = -1;
+       ether_dev->data_bAlternateSetting_without_traffic = -1;
+
+       // Walk through every possible setting for this interface until
+       // we find what makes us happy.
+       for ( altset_num = 0; altset_num < data_intf_group->num_altsetting; altset_num++ ) {
+               data_intf = &( data_intf_group->altsetting[altset_num] );
+
+               // Is this a data interface we like?
+               if ( ( data_intf->bInterfaceClass == 0x0A )
+                  && ( data_intf->bInterfaceSubClass == 0x00 )
+                  && ( data_intf->bInterfaceProtocol == 0x00 ) ) {
+                       if ( data_intf->bNumEndpoints == 2 ) {
+                               // We are required to have one of these.
+                               // An interface with 2 endpoints to send Ethernet traffic back and forth
+                               // It actually may be possible that the device might only
+                               // communicate in a vendor specific manner.
+                               // That would not be very nice.
+                               // We can add that one later.
+                               ether_dev->data_bInterfaceNumber = data_intf->bInterfaceNumber;
+                               ether_dev->data_interface_altset_num_with_traffic = altset_num;
+                               ether_dev->data_bAlternateSetting_with_traffic = data_intf->bAlternateSetting;
+                               status = get_data_interface_endpoints( device, ether_dev );
+                               if (!status) {
+                                       rc = 0;
+                               }
+                       }
+                       if ( data_intf->bNumEndpoints == 0 ) {
+                               // According to the spec we are SUPPOSED to have one of these
+                               // In fact the device is supposed to come up in this state.
+                               // However, I have seen a device that did not have such an interface.
+                               // So it must be just optional for our driver...
+                               ether_dev->data_bInterfaceNumber = data_intf->bInterfaceNumber;
+                               ether_dev->data_interface_altset_num_without_traffic = altset_num;
+                               ether_dev->data_bAlternateSetting_without_traffic = data_intf->bAlternateSetting;
+                       }
+               }
+       }
+       return rc;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Routine to find a communication interface /////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+static int find_ethernet_comm_interface( struct usb_device *device, ether_dev_t *ether_dev )
+{
+       struct usb_config_descriptor *conf = NULL;
+       struct usb_interface *comm_intf_group = NULL;
+       struct usb_interface_descriptor *comm_intf = NULL;
+       int intf_num;
+       int altset_num;
+       int rc;
+
+       conf = &( device->config[ether_dev->configuration_num] );
+
+       // We need to check and see if any of these interfaces are something we want.
+       // Walk through each interface one at a time
+       for ( intf_num = 0; intf_num < conf->bNumInterfaces; intf_num++ ) {
+               comm_intf_group = &( conf->interface[intf_num] );
+               // Now for each of those interfaces, check every possible
+               // alternate setting.
+               for ( altset_num = 0; altset_num < comm_intf_group->num_altsetting; altset_num++ ) {
+                       comm_intf = &( comm_intf_group->altsetting[altset_num] );
+
+                       // Is this a communication class of interface of the
+                       // ethernet subclass variety.
+                       if ( ( comm_intf->bInterfaceClass == 0x02 )
+                          && ( comm_intf->bInterfaceSubClass == 0x06 )
+                          && ( comm_intf->bInterfaceProtocol == 0x00 ) ) {
+                               if ( comm_intf->bNumEndpoints == 1 ) {
+                                       // Good, we found one, we will try this one
+                                       // Fill in the structure...
+                                       ether_dev->comm_interface = intf_num;
+                                       ether_dev->comm_bInterfaceNumber = comm_intf->bInterfaceNumber;
+                                       ether_dev->comm_interface_altset_num = altset_num;
+                                       ether_dev->comm_bAlternateSetting = comm_intf->bAlternateSetting;
+
+                                       // Look for the Ethernet Functional Descriptors
+                                       rc = find_and_parse_ethernet_class_information( device, ether_dev );
+                                       if (rc) {
+                                               // Nope this was no good after all.
+                                               continue;
+                                       }
+
+                                       // Check that we really can talk to the data
+                                       // interface 
+                                       // This includes # of endpoints, protocols,
+                                       // etc.
+                                       rc = verify_ethernet_data_interface( device, ether_dev );
+                                       if (rc) {
+                                               // We got something we didn't like
+                                               continue;
+                                       }
+                                       // This communication interface seems to give us everything
+                                       // we require.  We have all the ethernet info we need.
+                                       // Let's get out of here and go home right now.
+                                       return 0;
+                               } else {
+                                        // bNumEndPoints != 1
+                                       // We found an interface that had the wrong number of 
+                                       // endpoints but would have otherwise been okay
+                               } // end bNumEndpoints check.
+                       } // end interface specifics check.
+               } // end for altset_num
+       } // end for intf_num
+       return -1;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Routine to go through all configurations and find one that ////////////////
+// is an Ethernet Networking Device //////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+static int find_valid_configuration( struct usb_device *device, ether_dev_t *ether_dev )
+{
+       struct usb_config_descriptor *conf = NULL;
+       int conf_num;
+       int rc;
+
+       // We will try each and every possible configuration
+       for ( conf_num = 0; conf_num < device->descriptor.bNumConfigurations; conf_num++ ) {
+               conf = &( device->config[conf_num] );
+
+               // Our first requirement : 2 interfaces
+               if ( conf->bNumInterfaces != 2 ) {
+                       // I currently don't know how to handle devices with any number of interfaces
+                       // other than 2.
+                       continue;
+               }
+
+               // This one passed our first check, fill in some 
+               // useful data
+               ether_dev->configuration_num = conf_num;
+               ether_dev->bConfigurationValue = conf->bConfigurationValue;
+
+               // Now run it through the ringers and see what comes
+               // out the other side.
+               rc = find_ethernet_comm_interface( device, ether_dev );
+
+               // Check if we found an ethernet Communcation Device
+               if ( !rc ) {
+                       // We found one.
+                       return 0;
+               }
+       }
+       // None of the configurations suited us.
+       return -1;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Routine that checks a given configuration to see if any driver ////////////
+// has claimed any of the devices interfaces /////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+static int check_for_claimed_interfaces( struct usb_config_descriptor *config )
+{
+       struct usb_interface *comm_intf_group;
+       int intf_num;
+
+       // Go through all the interfaces and make sure none are 
+       // claimed by anybody else.
+       for ( intf_num = 0; intf_num < config->bNumInterfaces; intf_num++ ) {
+               comm_intf_group = &( config->interface[intf_num] );
+               if ( usb_interface_claimed( comm_intf_group ) ) {
+                       // Somebody has beat us to this guy.
+                       // We can't change the configuration out from underneath of whoever
+                       // is using this device, so we will go ahead and give up.
+                       return -1;
+               }
+       }
+       // We made it all the way through.
+       // I guess no one has claimed any of these interfaces.
+       return 0;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Routines to ask for and set the kernel network interface's MAC address ////
+// Used by driver's probe routine ////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+static inline unsigned char hex2dec( unsigned char digit )
+{
+       // Is there a standard way to do this???
+       // I have written this code TOO MANY times.
+       if ( (digit >= '0') && (digit <= '9') ) {
+               return (digit - '0');
+       }
+       if ( (digit >= 'a') && (digit <= 'f') ) {
+               return (digit - 'a' + 10);
+       }
+       if ( (digit >= 'A') && (digit <= 'F') ) {
+               return (digit - 'A' + 10);
+       }
+       return 0;
+}
+
+static void set_ethernet_addr( ether_dev_t *ether_dev )
+{
+       unsigned char   mac_addr[6];
+       int             i;
+       int             len;
+       unsigned char   buffer[13];
+
+       // Let's assume we don't get anything...
+       mac_addr[0] = 0x00;
+       mac_addr[1] = 0x00;
+       mac_addr[2] = 0x00;
+       mac_addr[3] = 0x00;
+       mac_addr[4] = 0x00;
+       mac_addr[5] = 0x00;
+
+       // Let's ask the device...
+       len = usb_string(ether_dev->usb, ether_dev->iMACAddress, buffer, 13);
+
+       // Sanity check!
+       if (len != 12)  {
+               // You gotta love failing sanity checks
+               err("Attempting to get MAC address returned %d bytes", len);
+               return;
+       }
+
+       // Fill in the mac_addr
+       for (i = 0; i < 6; i++) {
+               mac_addr[i] = ( hex2dec( buffer[2 * i] ) << 4 ) + hex2dec( buffer[2 * i + 1] );
+       }
+
+       // Now copy it over to the kernel's network driver.
+       memcpy( ether_dev->net->dev_addr, mac_addr, sizeof(mac_addr) );
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Routine to print to syslog information about the driver ///////////////////
+// Used by driver's probe routine ////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+void log_device_info(ether_dev_t *ether_dev)
+{
+       int len;
+       int string_num;
+       unsigned char manu[256];
+       unsigned char prod[256];
+       unsigned char sern[256];
+       unsigned char *mac_addr;
+
+       // Default empty strings in case we don't find a real one
+       manu[0] = 0x00;
+       prod[0] = 0x00;
+       sern[0] = 0x00;
+
+       // Try to get the device Manufacturer
+       string_num = ether_dev->usb->descriptor.iManufacturer;
+       if (string_num) {
+               // Put it into its buffer
+               len = usb_string(ether_dev->usb, string_num, manu, 255);
+               // Just to be safe
+               manu[len] = 0x00;
+       }
+
+       // Try to get the device Product Name
+       string_num = ether_dev->usb->descriptor.iProduct;
+       if (string_num) {
+               // Put it into its buffer
+               len = usb_string(ether_dev->usb, string_num, prod, 255);
+               // Just to be safe
+               prod[len] = 0x00;
+       }
+
+       // Try to get the device Serial Number
+       string_num = ether_dev->usb->descriptor.iSerialNumber;
+       if (string_num) {
+               // Put it into its buffer
+               len = usb_string(ether_dev->usb, string_num, sern, 255);
+               // Just to be safe
+               sern[len] = 0x00;
+       }
+
+       // This makes it easier for us to print
+       mac_addr = ether_dev->net->dev_addr;
+
+       // Now send everything we found to the syslog
+       info( "%s: %s %s %s %02X:%02X:%02X:%02X:%02X:%02X", 
+             ether_dev->net->name, manu, prod, sern, mac_addr[0], 
+             mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], 
+             mac_addr[5] );
+}
+
+/* Forward declaration */
+static struct usb_driver CDCEther_driver ;
+
+//////////////////////////////////////////////////////////////////////////////
+// Module's probe routine ////////////////////////////////////////////////////
+// claims interfaces if they are for an Ethernet CDC /////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+static void * CDCEther_probe( struct usb_device *usb, unsigned int ifnum,
+                            const struct usb_device_id *id)
+{
+       struct net_device       *net;
+       ether_dev_t             *ether_dev;
+       int                     rc;
+
+       // First we should check the active configuration to see if 
+       // any other driver has claimed any of the interfaces.
+       if ( check_for_claimed_interfaces( usb->actconfig ) ) {
+               // Someone has already put there grubby paws on this device.
+               // We don't want it now...
+               return NULL;
+       }
+
+       // We might be finding a device we can use.
+       // We all go ahead and allocate our storage space.
+       // We need to because we have to start filling in the data that
+       // we are going to need later.
+       if(!(ether_dev = kmalloc(sizeof(ether_dev_t), GFP_KERNEL))) {
+               err("out of memory allocating device structure");
+               return NULL;
+       }
+
+       // Zero everything out.
+       memset(ether_dev, 0, sizeof(ether_dev_t));
+
+       // Let's see if we can find a configuration we can use.
+       rc = find_valid_configuration( usb, ether_dev );
+       if (rc) {
+               // Nope we couldn't find one we liked.
+               // This device was not meant for us to control.
+               kfree( ether_dev );
+               return  NULL;
+       }
+
+       // Now that we FOUND a configuration. let's try to make the 
+       // device go into it.
+       if ( usb_set_configuration( usb, ether_dev->bConfigurationValue ) ) {
+               err("usb_set_configuration() failed");
+               kfree( ether_dev );
+               return NULL;
+       }
+
+       // Now set the communication interface up as required.
+       if (usb_set_interface(usb, ether_dev->comm_bInterfaceNumber, ether_dev->comm_bAlternateSetting)) {
+               err("usb_set_interface() failed");
+               kfree( ether_dev );
+               return NULL;
+       }
+
+       // Only turn traffic on right now if we must...
+       if (ether_dev->data_interface_altset_num_without_traffic >= 0)  {
+               // We found an alternate setting for the data
+               // interface that allows us to turn off traffic.
+               // We should use it.
+               if (usb_set_interface( usb, 
+                                      ether_dev->data_bInterfaceNumber, 
+                                      ether_dev->data_bAlternateSetting_without_traffic)) {
+                       err("usb_set_interface() failed");
+                       kfree( ether_dev );
+                       return NULL;
+               }
+       } else  {
+               // We didn't find an alternate setting for the data
+               // interface that would let us turn off traffic.
+               // Oh well, let's go ahead and do what we must...
+               if (usb_set_interface( usb, 
+                                      ether_dev->data_bInterfaceNumber, 
+                                      ether_dev->data_bAlternateSetting_with_traffic)) {
+                       err("usb_set_interface() failed");
+                       kfree( ether_dev );
+                       return NULL;
+               }
+       }
+
+       // Now we need to get a kernel Ethernet interface.
+       net = init_etherdev( NULL, 0 );
+       if ( !net ) {
+               // Hmm...  The kernel is not sharing today...
+               // Fine, we didn't want it anyway...
+               err( "Unable to initialize ethernet device" );
+               kfree( ether_dev );
+               return  NULL;
+       }
+
+       // Now that we have an ethernet device, let's set it up
+       // (And I don't mean "set [it] up the bomb".)
+       net->priv = ether_dev;
+       net->open = CDCEther_open;
+       net->stop = CDCEther_close;
+       net->watchdog_timeo = CDC_ETHER_TX_TIMEOUT;
+       net->tx_timeout = CDCEther_tx_timeout;   // TX timeout function
+       net->do_ioctl = CDCEther_ioctl;
+       net->hard_start_xmit = CDCEther_start_xmit;
+       net->set_multicast_list = CDCEther_set_multicast;
+       net->get_stats = CDCEther_netdev_stats;
+       net->mtu = ether_dev->wMaxSegmentSize - 14;
+
+       // We'll keep track of this information for later...
+       ether_dev->usb = usb;
+       ether_dev->net = net;
+       
+       // and don't forget the MAC address.
+       set_ethernet_addr( ether_dev );
+
+       // Send a message to syslog about what we are handling
+       log_device_info( ether_dev );
+
+       // I claim this interface to be a CDC Ethernet Networking device
+       usb_driver_claim_interface( &CDCEther_driver, 
+                                   &(usb->config[ether_dev->configuration_num].interface[ether_dev->comm_interface]), 
+                                   ether_dev );
+       // I claim this interface to be a CDC Ethernet Networking device
+       usb_driver_claim_interface( &CDCEther_driver, 
+                                   &(usb->config[ether_dev->configuration_num].interface[ether_dev->data_interface]), 
+                                   ether_dev );
+
+       // Does this REALLY do anything???
+       usb_inc_dev_use( usb );
+
+       // TODO - last minute HACK
+       ether_dev->comm_ep_in = 5;
+
+       // Okay, we are finally done...
+       return NULL;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+// Module's disconnect routine ///////////////////////////////////////////////
+// Called when the driver is unloaded or the device is unplugged /////////////
+// (Whichever happens first assuming the driver suceeded at its probe) ///////
+//////////////////////////////////////////////////////////////////////////////
+
+static void CDCEther_disconnect( struct usb_device *usb, void *ptr )
+{
+       ether_dev_t *ether_dev = ptr;
+
+       // Sanity check!!!
+       if ( !ether_dev || !ether_dev->usb ) {
+               // We failed.  We are insane!!!
+               warn("unregistering non-existant device");
+               return;
+       }
+
+       // Make sure we fail the sanity check if we try this again.
+       ether_dev->usb = NULL;
+       
+       // It is possible that this function is called before
+       // the "close" function.
+       // This tells the close function we are already disconnected
+       ether_dev->flags |= CDC_ETHER_UNPLUG;
+       
+       // We don't need the network device any more
+       unregister_netdev( ether_dev->net );
+       
+       // For sanity checks
+       ether_dev->net = NULL;
+
+       // I ask again, does this do anything???
+       usb_dec_dev_use( usb );
+
+       // We are done with this interface
+       usb_driver_release_interface( &CDCEther_driver, 
+                                     &(usb->config[ether_dev->configuration_num].interface[ether_dev->comm_interface]) );
+
+       // We are done with this interface too
+       usb_driver_release_interface( &CDCEther_driver, 
+                                     &(usb->config[ether_dev->configuration_num].interface[ether_dev->data_interface]) );
+
+       // No more tied up kernel memory
+       kfree( ether_dev );
+       
+       // This does no good, but it looks nice!
+       ether_dev = NULL;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Driver info ///////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+static struct usb_driver CDCEther_driver = {
+       name:           "CDCEther",
+       probe:          CDCEther_probe,
+       disconnect:     CDCEther_disconnect,
+       id_table:       CDCEther_ids,
+};
+
+//////////////////////////////////////////////////////////////////////////////
+// init and exit routines called when driver is installed and uninstalled ////
+//////////////////////////////////////////////////////////////////////////////
+
+int __init CDCEther_init(void)
+{
+       info( "%s", version );
+       return usb_register( &CDCEther_driver );
+}
+
+void __exit CDCEther_exit(void)
+{
+       usb_deregister( &CDCEther_driver );
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Module info ///////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+module_init( CDCEther_init );
+module_exit( CDCEther_exit );
+
+MODULE_AUTHOR("Brad Hards and another");
+MODULE_DESCRIPTION("USB CDC Ethernet driver");
+
+MODULE_DEVICE_TABLE (usb, CDCEther_ids);
+
+//////////////////////////////////////////////////////////////////////////////
+// End of file ///////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
diff --git a/drivers/usb/CDCEther.h b/drivers/usb/CDCEther.h
new file mode 100644 (file)
index 0000000..632ab49
--- /dev/null
@@ -0,0 +1,88 @@
+// Portions of this file taken from 
+// Petko Manolov - Petkan (petkan@dce.bg)
+// from his driver pegasus.h
+
+/*
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#define CS_INTERFACE                   0x24
+
+#define        CDC_ETHER_MAX_MTU               1536
+
+#define        CDC_ETHER_PRESENT               0x00000001
+#define        CDC_ETHER_RUNNING               0x00000002
+#define        CDC_ETHER_TX_BUSY               0x00000004
+#define        CDC_ETHER_RX_BUSY               0x00000008
+#define        CDC_ETHER_UNPLUG                0x00000040
+
+#define        CDC_ETHER_TX_TIMEOUT    (HZ*10)
+
+#define        TX_UNDERRUN                             0x80
+#define        EXCESSIVE_COL                   0x40
+#define        LATE_COL                                0x20
+#define        NO_CARRIER                              0x10
+#define        LOSS_CARRIER                    0x08
+#define        JABBER_TIMEOUT                  0x04
+
+#define        CDC_ETHER_REQT_READ             0xc0
+#define        CDC_ETHER_REQT_WRITE    0x40
+#define        CDC_ETHER_REQ_GET_REGS  0xf0
+#define        CDC_ETHER_REQ_SET_REGS  0xf1
+#define        CDC_ETHER_REQ_SET_REG   PIPERIDER_REQ_SET_REGS
+#define        ALIGN(x)                x __attribute__((aligned(L1_CACHE_BYTES)))
+
+typedef struct _ether_dev_t {
+       struct usb_device       *usb;
+       struct net_device       *net;
+       struct net_device_stats stats;
+       unsigned                flags;
+       int                     configuration_num;
+       int                     bConfigurationValue;
+       int                     comm_interface;
+       int                     comm_bInterfaceNumber;
+       int                     comm_interface_altset_num;
+       int                     comm_bAlternateSetting;
+       int                     comm_ep_in;
+       int                     data_interface;
+       int                     data_bInterfaceNumber;
+       int                     data_interface_altset_num_with_traffic;
+       int                     data_bAlternateSetting_with_traffic;
+       int                     data_interface_altset_num_without_traffic;
+       int                     data_bAlternateSetting_without_traffic;
+       int                     data_ep_in;
+       int                     data_ep_out;
+       int                     data_ep_out_size;
+       __u16                   bcdCDC;
+       __u8                    iMACAddress;
+       __u32                   bmEthernetStatistics;
+       __u16                   wMaxSegmentSize;
+       __u16                   wNumberMCFilters;
+       __u8                    bNumberPowerFilters;
+       int                     intr_interval;
+       struct urb              rx_urb, tx_urb, intr_urb;
+       unsigned char           ALIGN(rx_buff[CDC_ETHER_MAX_MTU]);
+       unsigned char           ALIGN(tx_buff[CDC_ETHER_MAX_MTU]);
+       unsigned char           ALIGN(intr_buff[8]);
+} ether_dev_t;
+
+#define REQ_HDR_FUNC_DESCR     0x0001
+#define REQ_UNION_FUNC_DESCR   0x0002
+#define REQ_ETH_FUNC_DESCR     0x0004
+#define REQUIREMENTS_TOTAL     0x0007
+
+
+
diff --git a/drivers/usb/kaweth.c b/drivers/usb/kaweth.c
new file mode 100644 (file)
index 0000000..9b72ff9
--- /dev/null
@@ -0,0 +1,1054 @@
+/****************************************************************
+ *
+ *     kaweth.c - driver for KL5KUSB101 based USB->Ethernet
+ *
+ *     (c) 2000 Interlan Communications
+ *     (c) 2000 Stephane Alnet
+ *     (C) 2001 Brad Hards
+ *
+ *     Original author: The Zapman <zapman@interlan.net>
+ *     Inspired by, and much credit goes to Michael Rothwell 
+ *     <rothwell@interlan.net> for the test equipment, help, and patience
+ *     Based off of (and with thanks to) Petko Manolov's pegaus.c driver.
+ *     Also many thanks to Joel Silverman and Ed Surprenant at Kawasaki 
+ *     for providing the firmware and driver resources.
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2, or 
+ *     (at your option) any later version.
+ *
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ *     You should have received a copy of the GNU General Public License
+ *     along with this program; if not, write to the Free Software Foundation,
+ *     Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 
+ *
+ ****************************************************************/
+
+/* TODO:
+ * Fix in_interrupt() problem
+ * Develop test procedures for USB net interfaces
+ * Run test procedures
+ * Fix bugs from previous two steps
+ * Snoop other OSs for any tricks we're not doing
+ * SMP locking
+ * Reduce arbitrary timeouts 
+ * Smart multicast support 
+ * Temporary MAC change support
+ * Tunable SOFs parameter - ioctl()?
+ * Ethernet stats collection
+ * Code formatting improvements
+ */
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/usb.h>
+#include <linux/types.h>
+#include <asm/semaphore.h>
+
+#define DEBUG
+
+#ifdef DEBUG
+#define kaweth_dbg(format, arg...) printk(KERN_DEBUG __FILE__ ": " format "\n" ,##arg)
+#else
+#define kaweth_dbg(format, arg...) do {} while (0)
+#endif
+#define kaweth_err(format, arg...) printk(KERN_ERR __FILE__ ": " format "\n" ,##arg)
+#define kaweth_info(format, arg...) printk(KERN_INFO __FILE__ ": " format "\n" , ##arg)
+#define kaweth_warn(format, arg...) printk(KERN_WARNING __FILE__ ": " format "\n" , ##arg)
+
+
+#include "kawethfw.h"
+
+#define KAWETH_MTU                     1514
+#define KAWETH_BUF_SIZE                        1664
+#define KAWETH_TX_TIMEOUT              (5 * HZ)
+#define KAWETH_FIRMWARE_BUF_SIZE       4096
+#define KAWETH_CONTROL_TIMEOUT         (30 * HZ)
+
+#define KAWETH_STATUS_BROKEN           0x0000001
+#define KAWETH_STATUS_CLOSING          0x0000002
+
+#define KAWETH_PACKET_FILTER_PROMISCUOUS       0x01
+#define KAWETH_PACKET_FILTER_ALL_MULTICAST     0x02
+#define KAWETH_PACKET_FILTER_DIRECTED          0x04
+#define KAWETH_PACKET_FILTER_BROADCAST         0x08
+#define KAWETH_PACKET_FILTER_MULTICAST         0x10
+
+/* Table 7 */
+#define KAWETH_COMMAND_GET_ETHERNET_DESC       0x00
+#define KAWETH_COMMAND_MULTICAST_FILTERS        0x01
+#define KAWETH_COMMAND_SET_PACKET_FILTER       0x02
+#define KAWETH_COMMAND_STATISTICS               0x03
+#define KAWETH_COMMAND_SET_TEMP_MAC            0x06
+#define KAWETH_COMMAND_GET_TEMP_MAC             0x07
+#define KAWETH_COMMAND_SET_URB_SIZE            0x08
+#define KAWETH_COMMAND_SET_SOFS_WAIT           0x09
+#define KAWETH_COMMAND_SCAN                    0xFF
+
+#define KAWETH_SOFS_TO_WAIT                    0x05
+
+
+MODULE_AUTHOR("Michael Zappe <zapman@interlan.net>, Stephane Alnet <stephane@u-picardie.fr> and Brad Hards <bhards@bigpond.net.au>");
+MODULE_DESCRIPTION("KL5USB101 USB Ethernet driver");
+
+static void *kaweth_probe(
+            struct usb_device *dev,             /* the device */
+            unsigned ifnum,                     /* what interface */
+            const struct usb_device_id *id      /* from id_table */
+       );
+static void kaweth_disconnect(struct usb_device *dev, void *ptr);
+int kaweth_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe,
+                               devrequest *cmd, void *data, int len,
+                               int timeout);
+
+/****************************************************************
+ *     usb_device_id
+ ****************************************************************/
+static struct usb_device_id usb_klsi_table[] = {
+       { USB_DEVICE(0x03e8, 0x0008) }, /* AOX Endpoints USB Ethernet */ 
+       { USB_DEVICE(0x04bb, 0x0901) }, /* I-O DATA USB-ET/T */
+       { USB_DEVICE(0x0506, 0x03e8) }, /* 3Com 3C19250 */ 
+       { USB_DEVICE(0x0557, 0x2002) }, /* ATEN USB Ethernet */ 
+       { USB_DEVICE(0x0557, 0x4000) }, /* D-Link DSB-650C */ 
+       { USB_DEVICE(0x0565, 0x0002) }, /* Peracom Enet */
+       { USB_DEVICE(0x0565, 0x0005) }, /* Peracom Enet2 */ 
+       { USB_DEVICE(0x05e9, 0x0008) }, /* KLSI KL5KUSB101B */
+       { USB_DEVICE(0x05e9, 0x0009) }, /* KLSI KL5KUSB101B (Board change) */
+       { USB_DEVICE(0x066b, 0x2202) }, /* Linksys USB10T */ 
+       { USB_DEVICE(0x06e1, 0x0008) }, /* ADS USB-10BT */ 
+       { USB_DEVICE(0x06e1, 0x0009) }, /* ADS USB-10BT */ 
+       { USB_DEVICE(0x0707, 0x0100) }, /* SMC 2202USB */ 
+       { USB_DEVICE(0x07aa, 0x0001) }, /* Correga K.K. */ 
+       { USB_DEVICE(0x07b8, 0x4000) }, /* D-Link DU-E10 */
+       { USB_DEVICE(0x0846, 0x1001) }, /* NetGear EA-101 */
+       { USB_DEVICE(0x0846, 0x1002) }, /* NetGear EA-101 */
+       { USB_DEVICE(0x085a, 0x0008) }, /* PortGear Ethernet Adapter */
+       { USB_DEVICE(0x085a, 0x0009) }, /* PortGear Ethernet Adapter */
+       { USB_DEVICE(0x087d, 0x5704) }, /* Jaton USB Ethernet Device Adapter */
+       { USB_DEVICE(0x0951, 0x0008) }, /* Kingston Technology USB Ethernet Adapter */
+       { USB_DEVICE(0x095a, 0x3003) }, /* Portsmith Express Ethernet Adapter */
+       { USB_DEVICE(0x10bd, 0x1427) }, /* ASANTE USB To Ethernet Adapter */
+       { USB_DEVICE(0x1342, 0x0204) }, /* Mobility USB-Ethernet Adapter */
+       { USB_DEVICE(0x13d2, 0x0400) }, /* Shark Pocket Adapter */
+       { USB_DEVICE(0x1645, 0x0005) }, /* Entrega E45 */ 
+       { USB_DEVICE(0x1645, 0x0008) }, /* Entrega USB Ethernet Adapter */ 
+       { USB_DEVICE(0x1645, 0x8005) }, /* PortGear Ethernet Adapter */ 
+       { USB_DEVICE(0x2001, 0x4000) }, /* D-link DSB-650C */
+       {} /* Null terminator */
+};
+
+MODULE_DEVICE_TABLE (usb, usb_klsi_table);
+
+/****************************************************************
+ *     kaweth_driver
+ ****************************************************************/
+static struct usb_driver kaweth_driver = {
+       name:           "kaweth",
+       probe:          kaweth_probe,
+       disconnect:     kaweth_disconnect,
+       id_table:       usb_klsi_table,
+};
+
+typedef __u8 eth_addr_t[6];
+
+/****************************************************************
+ *     usb_eth_dev
+ ****************************************************************/
+struct usb_eth_dev {
+       char *name;
+       __u16 vendor;
+       __u16 device;
+       void *pdata;
+};
+
+/****************************************************************
+ *     kaweth_ethernet_configuration
+ *     Refer Table 8
+ ****************************************************************/
+struct kaweth_ethernet_configuration
+{
+       __u8 size;
+       __u8 reserved1;
+       __u8 reserved2;
+       eth_addr_t hw_addr;
+       __u32 statistics_mask;
+       __u16 segment_size;
+       __u16 max_multicast_filters;
+       __u8 reserved3;
+} __attribute__ ((packed));
+
+/****************************************************************
+ *     kaweth_device
+ ****************************************************************/
+struct kaweth_device
+{
+       spinlock_t device_lock;
+
+       __u32 status;
+
+       struct usb_device *dev;
+       struct net_device *net;
+       wait_queue_head_t control_wait;
+
+       struct urb *rx_urb;
+       struct urb *tx_urb;
+       
+       __u8 firmware_buf[KAWETH_FIRMWARE_BUF_SIZE];
+       __u8 tx_buf[KAWETH_BUF_SIZE];
+       __u8 rx_buf[KAWETH_BUF_SIZE];
+       __u16 packet_filter_bitmap;
+
+       struct kaweth_ethernet_configuration configuration;
+
+       struct net_device_stats stats;
+} __attribute__ ((packed));
+
+
+/****************************************************************
+ *     kaweth_control
+ ****************************************************************/
+static int kaweth_control(struct kaweth_device *kaweth,
+                         unsigned int pipe, 
+                         __u8 request, 
+                         __u8 requesttype, 
+                         __u16 value, 
+                         __u16 index,
+                         void *data, 
+                         __u16 size, 
+                         int timeout)
+{
+       devrequest *dr;
+
+       kaweth_dbg("kaweth_control()");
+
+       if(in_interrupt()) {
+               kaweth_dbg("in_interrupt()");
+               return -EBUSY;
+       }
+
+       dr = kmalloc(sizeof(devrequest), 
+                     in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
+
+       if(!dr)
+       {
+               kaweth_dbg("kmalloc() failed");
+               return -ENOMEM;
+       }
+       
+       dr->requesttype = requesttype;
+       dr->request = request;
+       dr->value = value;
+       dr->index = index;
+       dr->length = size;
+
+       return kaweth_internal_control_msg(kaweth->dev,
+                                       pipe,
+                                       dr,
+                                       data,
+                                       size,
+                                       timeout);
+}
+
+/****************************************************************
+ *     kaweth_read_configuration
+ ****************************************************************/
+static int kaweth_read_configuration(struct kaweth_device *kaweth)
+{
+       int retval;
+
+       kaweth_dbg("Reading kaweth configuration");
+
+       retval = kaweth_control(kaweth,
+                               usb_rcvctrlpipe(kaweth->dev, 0),
+                               KAWETH_COMMAND_GET_ETHERNET_DESC,
+                               USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_DEVICE,
+                               0,
+                               0,
+                               (void *)&kaweth->configuration,
+                               sizeof(kaweth->configuration),
+                               KAWETH_CONTROL_TIMEOUT);
+
+       return retval;
+}
+
+/****************************************************************
+ *     kaweth_set_urb_size
+ ****************************************************************/
+static int kaweth_set_urb_size(struct kaweth_device *kaweth, __u16 urb_size)
+{
+       int retval;
+
+       kaweth_dbg("Setting URB size to %d", (unsigned)urb_size);
+
+       retval = kaweth_control(kaweth,
+                               usb_sndctrlpipe(kaweth->dev, 0),
+                               KAWETH_COMMAND_SET_URB_SIZE,
+                               USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
+                               urb_size,
+                               0,
+                               (void *)&kaweth->firmware_buf,
+                               0,
+                               KAWETH_CONTROL_TIMEOUT);
+
+       return retval;
+}
+
+/****************************************************************
+ *     kaweth_set_sofs_wait
+ ****************************************************************/
+static int kaweth_set_sofs_wait(struct kaweth_device *kaweth, __u16 sofs_wait)
+{
+       int retval;
+
+       kaweth_dbg("Set SOFS wait to %d", (unsigned)sofs_wait);
+
+       retval = kaweth_control(kaweth,
+                               usb_sndctrlpipe(kaweth->dev, 0),
+                               KAWETH_COMMAND_SET_SOFS_WAIT,
+                               USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
+                               sofs_wait,
+                               0,
+                               (void *)&kaweth->firmware_buf,
+                               0,
+                               KAWETH_CONTROL_TIMEOUT);
+
+       return retval;
+}
+
+/****************************************************************
+ *     kaweth_set_receive_filter
+ ****************************************************************/
+static int kaweth_set_receive_filter(struct kaweth_device *kaweth,
+                                    __u16 receive_filter)
+{
+       int retval;
+
+       kaweth_dbg("Set receive filter to %d", (unsigned)receive_filter);
+
+       retval = kaweth_control(kaweth,
+                               usb_sndctrlpipe(kaweth->dev, 0),
+                               KAWETH_COMMAND_SET_PACKET_FILTER,
+                               USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
+                               receive_filter,
+                               0,
+                               (void *)&kaweth->firmware_buf,
+                               0,
+                               KAWETH_CONTROL_TIMEOUT);
+
+       return retval;
+}
+
+/****************************************************************
+ *     kaweth_download_firmware
+ ****************************************************************/
+static int kaweth_download_firmware(struct kaweth_device *kaweth, 
+                                   __u8 *data, 
+                                   __u16 data_len,
+                                   __u8 interrupt,
+                                   __u8 type)
+{      
+       if(data_len > KAWETH_FIRMWARE_BUF_SIZE) {
+               kaweth_err("Firmware too big: %d", data_len);
+               return -ENOSPC;
+       }
+       
+       memcpy(kaweth->firmware_buf, data, data_len);
+       
+       kaweth->firmware_buf[2] = (data_len & 0xFF) - 7;
+       kaweth->firmware_buf[3] = data_len >> 8;
+       kaweth->firmware_buf[4] = type;
+       kaweth->firmware_buf[5] = interrupt;
+
+       kaweth_dbg("Downloading firmware at %x to kaweth device at %x", 
+           (int)data, 
+           (int)kaweth);
+       kaweth_dbg("Firmware length: %d", data_len);
+
+       return kaweth_control(kaweth,
+                             usb_sndctrlpipe(kaweth->dev, 0),
+                             KAWETH_COMMAND_SCAN,
+                             USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
+                             0,
+                             0,
+                             (void *)&kaweth->firmware_buf,
+                             data_len,
+                             KAWETH_CONTROL_TIMEOUT);
+}
+
+/****************************************************************
+ *     kaweth_trigger_firmware
+ ****************************************************************/
+static int kaweth_trigger_firmware(struct kaweth_device *kaweth,
+                                  __u8 interrupt)
+{
+       kaweth->firmware_buf[0] = 0xB6;
+       kaweth->firmware_buf[1] = 0xC3;
+       kaweth->firmware_buf[2] = 0x01;
+       kaweth->firmware_buf[3] = 0x00;
+       kaweth->firmware_buf[4] = 0x06;
+       kaweth->firmware_buf[5] = interrupt;
+       kaweth->firmware_buf[6] = 0x00;
+       kaweth->firmware_buf[7] = 0x00;
+       
+       kaweth_dbg("Triggering firmware");
+
+       return kaweth_control(kaweth,
+                             usb_sndctrlpipe(kaweth->dev, 0),
+                             KAWETH_COMMAND_SCAN,
+                             USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
+                             0,
+                             0,
+                             (void *)&kaweth->firmware_buf,
+                             8,
+                             KAWETH_CONTROL_TIMEOUT);
+}
+
+/****************************************************************
+ *     kaweth_reset
+ ****************************************************************/
+static int kaweth_reset(struct kaweth_device *kaweth)
+{
+       int result;
+
+       kaweth_dbg("kaweth_reset(%p)", kaweth);
+       result = kaweth_control(kaweth,
+                               usb_sndctrlpipe(kaweth->dev, 0),
+                               USB_REQ_SET_CONFIGURATION, 
+                               0, 
+                               kaweth->dev->config[0].bConfigurationValue,
+                               0, 
+                               NULL, 
+                               0, 
+                               KAWETH_CONTROL_TIMEOUT);
+
+       udelay(10000);
+
+       kaweth_dbg("kaweth_reset() returns %d.",result);
+
+       return result;
+}
+
+static void kaweth_usb_receive(struct urb *);
+
+/****************************************************************
+ *     kaweth_resubmit_rx_urb
+ ****************************************************************/
+static inline void kaweth_resubmit_rx_urb(struct kaweth_device *kaweth)
+{
+       int result;
+
+       memset(kaweth->rx_urb, 0, sizeof(*kaweth->rx_urb));
+
+       FILL_BULK_URB(kaweth->rx_urb,
+                     kaweth->dev,
+                     usb_rcvbulkpipe(kaweth->dev, 1),
+                     kaweth->rx_buf,
+                     KAWETH_BUF_SIZE,
+                     kaweth_usb_receive,
+                     kaweth);
+
+       if((result = usb_submit_urb(kaweth->rx_urb))) {
+               kaweth_err("resubmitting rx_urb %d failed", result);
+       }
+}
+
+static void kaweth_async_set_rx_mode(struct kaweth_device *kaweth);
+
+/****************************************************************
+ *     kaweth_usb_receive
+ ****************************************************************/
+static void kaweth_usb_receive(struct urb *urb)
+{
+       struct kaweth_device *kaweth = urb->context;
+       struct net_device *net = kaweth->net;
+       
+       int count = urb->actual_length;
+       int count2 = urb->transfer_buffer_length;
+                       
+       __u16 pkt_len = *(__u16 *)kaweth->rx_buf;
+
+       struct sk_buff *skb;
+
+       if(kaweth->status & KAWETH_STATUS_CLOSING) {
+               return;
+       }
+       
+       if(urb->status && urb->status != -EREMOTEIO && count != 1) { 
+               kaweth_err("%s RX status: %d count: %d packet_len: %d",
+                           net->name, 
+                          urb->status,
+                          count, 
+                          (int)pkt_len);
+               kaweth_resubmit_rx_urb(kaweth);
+                return;
+       }
+
+       if(kaweth->net && (count > 2)) {
+               if(pkt_len > (count - 2)) {
+                       kaweth_err("Packet length too long for USB frame (pkt_len: %x, count: %x)",pkt_len, count);
+                       kaweth_err("Packet len & 2047: %x", pkt_len & 2047);
+                       kaweth_err("Count 2: %x", count2);
+                       kaweth_resubmit_rx_urb(kaweth);
+                        return;
+                }
+               
+               if(!(skb = dev_alloc_skb(pkt_len+2))) {
+                       kaweth_resubmit_rx_urb(kaweth);
+                        return;
+               }
+
+               skb->dev = net;
+
+               eth_copy_and_sum(skb, kaweth->rx_buf + 2, pkt_len, 0);
+               
+               skb_put(skb, pkt_len);
+
+               skb->protocol = eth_type_trans(skb, net);
+               
+               netif_rx(skb);
+               
+               kaweth->stats.rx_packets++;
+               kaweth->stats.rx_bytes += pkt_len;
+       }
+
+       kaweth_resubmit_rx_urb(kaweth);
+}
+
+/****************************************************************
+ *     kaweth_open
+ ****************************************************************/
+static int kaweth_open(struct net_device *net)
+{
+       struct kaweth_device *kaweth = (struct kaweth_device *)net->priv;
+
+       kaweth_dbg("Dev usage: %d", kaweth->dev->refcnt.counter);
+
+       kaweth_dbg("Opening network device.");
+
+       kaweth_resubmit_rx_urb(kaweth);
+
+       netif_start_queue(net);
+
+       MOD_INC_USE_COUNT;
+
+       kaweth_async_set_rx_mode(kaweth);
+       return 0;
+}
+
+/****************************************************************
+ *     kaweth_close
+ ****************************************************************/
+static int kaweth_close(struct net_device *net)
+{
+       struct kaweth_device *kaweth = net->priv;
+
+       netif_stop_queue(net);
+
+       kaweth->status |= KAWETH_STATUS_CLOSING;
+
+       usb_unlink_urb(kaweth->rx_urb);
+
+       kaweth->status &= ~KAWETH_STATUS_CLOSING;
+
+       MOD_DEC_USE_COUNT;
+
+       printk("Dev usage: %d", kaweth->dev->refcnt.counter);
+
+       return 0;
+}
+
+/****************************************************************
+ *     kaweth_ioctl
+ ****************************************************************/
+static int kaweth_ioctl(struct net_device *net, struct ifreq *rq, int cmd)
+{
+       return -EOPNOTSUPP;
+}
+
+/****************************************************************
+ *     kaweth_usb_transmit_complete
+ ****************************************************************/
+static void kaweth_usb_transmit_complete(struct urb *urb)
+{
+       struct kaweth_device *kaweth = urb->context;
+
+       spin_lock(&kaweth->device_lock);
+
+       if (urb->status)
+               kaweth_dbg("%s: TX status %d.", kaweth->net->name, urb->status);
+
+       netif_wake_queue(kaweth->net);
+
+       spin_unlock(&kaweth->device_lock);
+}
+
+/****************************************************************
+ *     kaweth_start_xmit
+ ****************************************************************/
+static int kaweth_start_xmit(struct sk_buff *skb, struct net_device *net)
+{
+       struct kaweth_device *kaweth = net->priv;
+       int count = skb->len;
+       
+       int res;
+
+       spin_lock(&kaweth->device_lock);
+
+       kaweth_async_set_rx_mode(kaweth);
+       netif_stop_queue(net);
+
+       *((__u16 *)kaweth->tx_buf) = skb->len;
+
+       memcpy(kaweth->tx_buf + 2, skb->data, skb->len);
+
+       memset(kaweth->tx_urb, 0, sizeof(*kaweth->tx_urb));
+
+       FILL_BULK_URB(kaweth->tx_urb,
+                     kaweth->dev,
+                     usb_sndbulkpipe(kaweth->dev, 2),
+                     kaweth->tx_buf,
+                     count + 2,
+                     kaweth_usb_transmit_complete,
+                     kaweth);
+
+       if((res = usb_submit_urb(kaweth->tx_urb)))
+       {
+               kaweth_warn("kaweth failed tx_urb %d", res);
+               kaweth->stats.tx_errors++;
+               
+               netif_start_queue(net);
+       } 
+       else 
+       {
+               kaweth->stats.tx_packets++;
+               kaweth->stats.tx_bytes += skb->len;
+               net->trans_start = jiffies;
+       }
+
+       dev_kfree_skb(skb);
+
+       spin_unlock(&kaweth->device_lock);
+
+       return 0;
+}
+
+/****************************************************************
+ *     kaweth_set_rx_mode
+ ****************************************************************/
+static void kaweth_set_rx_mode(struct net_device *net)
+{
+       struct kaweth_device *kaweth = net->priv;
+       
+       __u16 packet_filter_bitmap = KAWETH_PACKET_FILTER_DIRECTED |
+                                     KAWETH_PACKET_FILTER_BROADCAST |
+                                    KAWETH_PACKET_FILTER_MULTICAST;
+
+       kaweth_dbg("Setting Rx mode to %d", packet_filter_bitmap);
+
+       netif_stop_queue(net);
+
+       if (net->flags & IFF_PROMISC) {
+               packet_filter_bitmap |= KAWETH_PACKET_FILTER_PROMISCUOUS;
+       } 
+       else if ((net->mc_count) || (net->flags & IFF_ALLMULTI)) {
+               packet_filter_bitmap |= KAWETH_PACKET_FILTER_ALL_MULTICAST;
+       }
+
+       kaweth->packet_filter_bitmap = packet_filter_bitmap;
+       netif_wake_queue(net);
+}
+
+/****************************************************************
+ *     kaweth_async_set_rx_mode
+ ****************************************************************/
+static void kaweth_async_set_rx_mode(struct kaweth_device *kaweth)
+{
+       __u16 packet_filter_bitmap = kaweth->packet_filter_bitmap;
+       kaweth->packet_filter_bitmap = 0;       
+       if(packet_filter_bitmap == 0) return;
+
+       {
+       int result;
+       result = kaweth_control(kaweth,
+                               usb_sndctrlpipe(kaweth->dev, 0),
+                               KAWETH_COMMAND_SET_PACKET_FILTER,
+                               USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
+                               packet_filter_bitmap,
+                               0,
+                               (void *)&kaweth->firmware_buf,
+                               0,
+                               KAWETH_CONTROL_TIMEOUT);
+
+       if(result < 0) {
+               kaweth_err("Failed to set Rx mode: %d", result);
+       }
+       else {
+               kaweth_dbg("Set Rx mode to %d", packet_filter_bitmap);
+       }
+       }
+}
+
+/****************************************************************
+ *     kaweth_netdev_stats
+ ****************************************************************/
+static struct net_device_stats *kaweth_netdev_stats(struct net_device *dev)
+{
+       return &((struct kaweth_device *)dev->priv)->stats;
+}
+
+/****************************************************************
+ *     kaweth_tx_timeout
+ ****************************************************************/
+static void kaweth_tx_timeout(struct net_device *net)
+{
+       struct kaweth_device *kaweth = net->priv;
+
+       kaweth_warn("%s: Tx timed out. Resetting.", net->name);
+       kaweth->stats.tx_errors++;
+       net->trans_start = jiffies;
+
+       usb_unlink_urb(kaweth->tx_urb);
+
+       netif_wake_queue(net);
+}
+
+/****************************************************************
+ *     kaweth_probe
+ ****************************************************************/
+static void *kaweth_probe(
+            struct usb_device *dev,             /* the device */
+            unsigned ifnum,                      /* what interface */
+            const struct usb_device_id *id      /* from id_table */
+       )
+{
+       struct kaweth_device *kaweth;
+       const eth_addr_t bcast_addr = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+       int result = 0;
+
+       kaweth_dbg("Kawasaki Device Probe (Device number:%d): 0x%4.4x:0x%4.4x:0x%4.4x",
+                dev->devnum, 
+                (int)dev->descriptor.idVendor, 
+                (int)dev->descriptor.idProduct,
+                (int)dev->descriptor.bcdDevice);
+
+       kaweth_dbg("Device at %p", dev);
+
+       kaweth_dbg("Descriptor length: %x type: %x", 
+                (int)dev->descriptor.bLength,
+                (int)dev->descriptor.bDescriptorType);
+
+       if(!(kaweth = kmalloc(sizeof(struct kaweth_device), GFP_KERNEL))) {
+               kaweth_dbg("out of memory allocating device structure\n");
+               return NULL;
+       }
+
+       memset(kaweth, 0, sizeof(struct kaweth_device));
+
+       kaweth->dev = dev;
+       kaweth->status = 0;
+       kaweth->net = NULL;
+       kaweth->device_lock = SPIN_LOCK_UNLOCKED;
+               
+       kaweth_dbg("Resetting.");
+
+       kaweth_reset(kaweth);
+
+       /*
+        * If high byte of bcdDevice is nonzero, firmware is already
+        * downloaded. Don't try to do it again, or we'll hang the device.
+        */
+
+       if (dev->descriptor.bcdDevice >> 8) {
+               kaweth_info("Firmware present in device.");
+       } else {
+               /* Download the firmware */
+               kaweth_info("Downloading firmware...");
+               if ((result = kaweth_download_firmware(kaweth, 
+                                                     kaweth_new_code, 
+                                                     len_kaweth_new_code, 
+                                                     100, 
+                                                     2)) < 0) {
+                       kaweth_err("Error downloading firmware (%d)", result);
+                       kfree(kaweth);
+                       return NULL;
+               }
+
+               if ((result = kaweth_download_firmware(kaweth, 
+                                                     kaweth_new_code_fix, 
+                                                     len_kaweth_new_code_fix, 
+                                                     100, 
+                                                     3)) < 0) {
+                       kaweth_err("Error downloading firmware fix (%d)", result);
+                       kfree(kaweth);
+                       return NULL;
+               }
+
+               if ((result = kaweth_download_firmware(kaweth,
+                                                     kaweth_trigger_code,
+                                                     len_kaweth_trigger_code,
+                                                     126,
+                                                     2)) < 0) {
+                       kaweth_err("Error downloading trigger code (%d)", result);
+                       kfree(kaweth);
+                       return NULL;
+               }
+
+               if ((result = kaweth_download_firmware(kaweth,
+                                                     kaweth_trigger_code_fix,
+                                                     len_kaweth_trigger_code_fix,
+                                                     126,
+                                                     3)) < 0) {
+                       kaweth_err("Error downloading trigger code fix (%d)", result);
+                       kfree(kaweth);
+                       return NULL;
+               }
+
+
+               if ((result = kaweth_trigger_firmware(kaweth, 126)) < 0) {
+                       kaweth_err("Error triggering firmware (%d)", result);
+                       kfree(kaweth);
+                       return NULL;
+               }
+
+               /* Device will now disappear for a moment...  */
+               kaweth_info("Firmware loaded.  I'll be back...");
+               return NULL;
+       }
+
+       result = kaweth_read_configuration(kaweth);
+
+       if(result < 0) {
+               kaweth_err("Error reading configuration (%d), no net device created", result);
+               kfree(kaweth);
+               return NULL;
+       }
+
+       kaweth_info("Statistics collection: %x", kaweth->configuration.statistics_mask);
+       kaweth_info("Multicast filter limit: %x", kaweth->configuration.max_multicast_filters & ((1 << 15) - 1));
+       kaweth_info("MTU: %d", kaweth->configuration.segment_size);
+       kaweth_info("Read MAC address %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x",
+                (int)kaweth->configuration.hw_addr[0],
+                (int)kaweth->configuration.hw_addr[1],
+                (int)kaweth->configuration.hw_addr[2],
+                (int)kaweth->configuration.hw_addr[3],
+                (int)kaweth->configuration.hw_addr[4],
+                (int)kaweth->configuration.hw_addr[5]);
+
+       if(!memcmp(&kaweth->configuration.hw_addr,
+                   &bcast_addr, 
+                  sizeof(bcast_addr))) {
+               kaweth_err("Firmware not functioning properly, no net device created");
+               kfree(kaweth);
+               return NULL;
+       }
+
+       if(kaweth_set_urb_size(kaweth, KAWETH_BUF_SIZE) < 0) {
+               kaweth_dbg("Error setting URB size");
+               return kaweth;
+       }
+       
+       if(kaweth_set_sofs_wait(kaweth, KAWETH_SOFS_TO_WAIT) < 0) {
+               kaweth_err("Error setting SOFS wait");
+               return kaweth;
+       }
+
+       result = kaweth_set_receive_filter(kaweth, 
+                                           KAWETH_PACKET_FILTER_DIRECTED |
+                                           KAWETH_PACKET_FILTER_BROADCAST |
+                                           KAWETH_PACKET_FILTER_MULTICAST);
+
+       if(result < 0) {
+               kaweth_err("Error setting receive filter");
+               return kaweth;
+       }
+       
+       kaweth_dbg("Initializing net device.");
+
+       kaweth->tx_urb = usb_alloc_urb(0);
+       kaweth->rx_urb = usb_alloc_urb(0);
+
+       kaweth->net = init_etherdev(0, 0);
+
+       memcpy(kaweth->net->broadcast, &bcast_addr, sizeof(bcast_addr));
+       memcpy(kaweth->net->dev_addr, 
+               &kaweth->configuration.hw_addr,
+               sizeof(kaweth->configuration.hw_addr));
+        
+       kaweth->net->priv = kaweth;
+       kaweth->net->open = kaweth_open;
+       kaweth->net->stop = kaweth_close;
+
+       kaweth->net->watchdog_timeo = KAWETH_TX_TIMEOUT;
+       kaweth->net->tx_timeout = kaweth_tx_timeout;
+       
+       kaweth->net->do_ioctl = kaweth_ioctl;
+       kaweth->net->hard_start_xmit = kaweth_start_xmit;
+       kaweth->net->set_multicast_list = kaweth_set_rx_mode;
+       kaweth->net->get_stats = kaweth_netdev_stats;
+       kaweth->net->mtu = kaweth->configuration.segment_size;
+
+       memset(&kaweth->stats, 0, sizeof(kaweth->stats));
+
+       kaweth_info("kaweth interface created at %s", kaweth->net->name);
+                                                               
+       kaweth_dbg("Kaweth probe returning.");
+
+       return kaweth;
+}
+
+/****************************************************************
+ *     kaweth_disconnect
+ ****************************************************************/
+static void kaweth_disconnect(struct usb_device *dev, void *ptr)
+{
+       struct kaweth_device *kaweth = ptr;
+
+       kaweth_info("Unregistering");
+
+       if (!kaweth) {
+               kaweth_warn("unregistering non-existant device");
+               return;
+       }
+
+       if(kaweth->net) {
+               if(kaweth->net->flags & IFF_UP) {
+                       kaweth_dbg("Closing net device");
+                       dev_close(kaweth->net);
+               }
+
+               kaweth_dbg("Unregistering net device");
+               unregister_netdev(kaweth->net);
+       }
+
+       usb_free_urb(kaweth->rx_urb);
+       usb_free_urb(kaweth->tx_urb);
+
+       kfree(kaweth);
+}
+
+
+/*-------------------------------------------------------------------*
+ * completion handler for compatibility wrappers (sync control/bulk) *
+ *-------------------------------------------------------------------*/
+static void usb_api_blocking_completion(urb_t *urb)
+{
+        api_wrapper_data *awd = (api_wrapper_data *)urb->context;
+
+        if (waitqueue_active(awd->wakeup)) {
+                wake_up(awd->wakeup);
+       }
+
+}
+
+/*-------------------------------------------------------------------*
+ *                         COMPATIBILITY STUFF                       *
+ *-------------------------------------------------------------------*/
+
+// Starts urb and waits for completion or timeout
+static int usb_start_wait_urb(urb_t *urb, int timeout, int* actual_length)
+{
+        DECLARE_WAITQUEUE(wait, current);
+        DECLARE_WAIT_QUEUE_HEAD(wqh);
+        api_wrapper_data awd;
+        int status;
+
+        awd.wakeup = &wqh;
+        init_waitqueue_head(&wqh);
+        current->state = TASK_INTERRUPTIBLE;
+        add_wait_queue(&wqh, &wait);
+        urb->context = &awd;
+        status = usb_submit_urb(urb);
+        if (status) {
+                // something went wrong
+                usb_free_urb(urb);
+                current->state = TASK_RUNNING;
+                remove_wait_queue(&wqh, &wait);
+                return status;
+        }
+
+        if (urb->status == -EINPROGRESS) {
+                while (timeout && urb->status == -EINPROGRESS)
+                        status = timeout = schedule_timeout(timeout);
+        } 
+       else {
+                status = 1;
+       }
+
+        current->state = TASK_RUNNING;
+        remove_wait_queue(&wqh, &wait);
+
+        if (!status) {
+                // timeout
+                kaweth_warn("usb_control/bulk_msg: timeout");
+                usb_unlink_urb(urb);  // remove urb safely
+                status = -ETIMEDOUT;
+        }
+       else {
+                status = urb->status;
+       }
+
+        if (actual_length) {
+                *actual_length = urb->actual_length;
+       }
+
+        usb_free_urb(urb);
+        return status;
+}
+
+/*-------------------------------------------------------------------*/
+// returns status (negative) or length (positive)
+int kaweth_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe,
+                            devrequest *cmd,  void *data, int len, int timeout)
+{
+        urb_t *urb;
+        int retv;
+        int length;
+
+        urb = usb_alloc_urb(0);
+        if (!urb)
+                return -ENOMEM;
+
+        FILL_CONTROL_URB(urb, usb_dev, pipe, (unsigned char*)cmd, data,
+                        len, (usb_complete_t)usb_api_blocking_completion,0);
+
+        retv = usb_start_wait_urb(urb, timeout, &length);
+        if (retv < 0) {
+                return retv;
+       }
+        else {
+                return length;
+       }
+}
+
+
+/****************************************************************
+ *     kaweth_init
+ ****************************************************************/
+int __init kaweth_init(void)
+{
+       kaweth_dbg("Driver loading");
+       return usb_register(&kaweth_driver);
+}
+
+/****************************************************************
+ *     kaweth_exit
+ ****************************************************************/
+void __exit kaweth_exit(void)
+{
+       usb_deregister(&kaweth_driver);
+}
+
+module_init(kaweth_init);
+module_exit(kaweth_exit);
+
diff --git a/drivers/usb/kawethfw.h b/drivers/usb/kawethfw.h
new file mode 100644 (file)
index 0000000..2b35bae
--- /dev/null
@@ -0,0 +1,557 @@
+/******************************************/
+/* NOTE: B6/C3 is data header signature   */
+/*       0xAA/0xBB is data length = total */
+/*       bytes - 7, 0xCC is type, 0xDD is */
+/*       interrupt to use.                */
+/******************************************/
+
+/****************************************************************
+ *     kaweth_trigger_code
+ ****************************************************************/
+static __u8 kaweth_trigger_code[] = 
+{
+    0xB6, 0xC3, 0xAA, 0xBB, 0xCC, 0xDD,
+    0xc8, 0x07, 0xa0, 0x00, 0xf0, 0x07, 0x5e, 0x00,
+    0x06, 0x00, 0xf0, 0x07, 0x0a, 0x00, 0x08, 0x00,
+    0xf0, 0x09, 0x00, 0x00, 0x02, 0x00, 0xe7, 0x07,
+    0x36, 0x00, 0x00, 0x00, 0xf0, 0x07, 0x00, 0x00,
+    0x04, 0x00, 0xe7, 0x07, 0x50, 0xc3, 0x10, 0xc0,
+    0xf0, 0x09, 0x0e, 0xc0, 0x00, 0x00, 0xe7, 0x87,
+    0x01, 0x00, 0x0e, 0xc0, 0x97, 0xcf, 0xd7, 0x09,
+    0x00, 0xc0, 0x17, 0x02, 0xc8, 0x07, 0xa0, 0x00,
+    0xe7, 0x17, 0x50, 0xc3, 0x10, 0xc0, 0x30, 0xd8,
+    0x04, 0x00, 0x30, 0x5c, 0x08, 0x00, 0x04, 0x00,
+    0xb0, 0xc0, 0x06, 0x00, 0xc8, 0x05, 0xe7, 0x05,
+    0x00, 0xc0, 0xc0, 0xdf, 0x97, 0xcf, 0x49, 0xaf,
+    0xc0, 0x07, 0x00, 0x00, 0x60, 0xaf, 0x4a, 0xaf,
+    0x00, 0x0c, 0x0c, 0x00, 0x40, 0xd2, 0x00, 0x1c,
+    0x0c, 0x00, 0x40, 0xd2, 0x30, 0x00, 0x08, 0x00,
+    0xf0, 0x07, 0x00, 0x00, 0x04, 0x00, 0xf0, 0x07,
+    0x86, 0x00, 0x06, 0x00, 0x67, 0xcf, 0x27, 0x0c,
+    0x02, 0x00, 0x00, 0x00, 0x27, 0x0c, 0x00, 0x00,
+    0x0e, 0xc0, 0x49, 0xaf, 0x64, 0xaf, 0xc0, 0x07,
+    0x00, 0x00, 0x4b, 0xaf, 0x4a, 0xaf, 0x5a, 0xcf,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x94, 0x00, 0x05, 0x00,
+    0x00, 0x00
+};
+/****************************************************************
+ *     kaweth_trigger_code_fix
+ ****************************************************************/
+static __u8 kaweth_trigger_code_fix[] = 
+{
+    0xB6, 0xC3, 0xAA, 0xBB, 0xCC, 0xDD,
+    0x02, 0x00, 0x06, 0x00, 0x18, 0x00, 0x3e, 0x00,
+    0x80, 0x00, 0x98, 0x00, 0xaa, 0x00,
+    0x00, 0x00
+};
+
+/****************************************************************
+ *     kaweth_new_code
+ ****************************************************************/
+static __u8 kaweth_new_code[] = 
+{
+    0xB6, 0xC3, 0xAA, 0xBB, 0xCC, 0xDD,
+    0x9f, 0xcf, 0xde, 0x06, 0xe7, 0x57, 0x00, 0x00,
+    0xc4, 0x06, 0x97, 0xc1, 0xe7, 0x67, 0xff, 0x1f,
+    0x28, 0xc0, 0xe7, 0x87, 0x00, 0x04, 0x24, 0xc0,
+    0xe7, 0x67, 0xff, 0xf9, 0x22, 0xc0, 0x97, 0xcf,
+    0xd7, 0x09, 0x00, 0xc0, 0xe7, 0x09, 0xa2, 0xc0,
+    0xbe, 0x06, 0x9f, 0xaf, 0x36, 0x00, 0xe7, 0x05,
+    0x00, 0xc0, 0xa7, 0xcf, 0xbc, 0x06, 0x97, 0xcf,
+    0xe7, 0x57, 0x00, 0x00, 0xb8, 0x06, 0xa7, 0xa1,
+    0xb8, 0x06, 0x97, 0xcf, 0xe7, 0x57, 0x00, 0x00,
+    0x14, 0x08, 0x0a, 0xc0, 0xe7, 0x57, 0x00, 0x00,
+    0xa4, 0xc0, 0xa7, 0xc0, 0x7a, 0x06, 0x9f, 0xaf,
+    0x92, 0x07, 0xe7, 0x07, 0x00, 0x00, 0x14, 0x08,
+    0xe7, 0x57, 0xff, 0xff, 0xba, 0x06, 0x9f, 0xa0,
+    0x38, 0x00, 0xe7, 0x59, 0xba, 0x06, 0xbe, 0x06,
+    0x9f, 0xa0, 0x38, 0x00, 0xc8, 0x09, 0xca, 0x06,
+    0x08, 0x62, 0x9f, 0xa1, 0x36, 0x08, 0xc0, 0x09,
+    0x76, 0x06, 0x00, 0x60, 0xa7, 0xc0, 0x7a, 0x06,
+    0x9f, 0xaf, 0xcc, 0x02, 0xe7, 0x57, 0x00, 0x00,
+    0xb8, 0x06, 0xa7, 0xc1, 0x7a, 0x06, 0x9f, 0xaf,
+    0x04, 0x00, 0xe7, 0x57, 0x00, 0x00, 0x8e, 0x06,
+    0x0a, 0xc1, 0xe7, 0x09, 0x20, 0xc0, 0x10, 0x08,
+    0xe7, 0xd0, 0x10, 0x08, 0xe7, 0x67, 0x40, 0x00,
+    0x10, 0x08, 0x9f, 0xaf, 0x92, 0x0c, 0xc0, 0x09,
+    0xd0, 0x06, 0x00, 0x60, 0x05, 0xc4, 0xc0, 0x59,
+    0xbe, 0x06, 0x02, 0xc0, 0x9f, 0xaf, 0xec, 0x00,
+    0x9f, 0xaf, 0x34, 0x02, 0xe7, 0x57, 0x00, 0x00,
+    0xa6, 0x06, 0x9f, 0xa0, 0x7a, 0x02, 0xa7, 0xcf,
+    0x7a, 0x06, 0x48, 0x02, 0xe7, 0x09, 0xbe, 0x06,
+    0xd0, 0x06, 0xc8, 0x37, 0x04, 0x00, 0x9f, 0xaf,
+    0x08, 0x03, 0x97, 0xcf, 0xe7, 0x57, 0x00, 0x00,
+    0xce, 0x06, 0x97, 0xc0, 0xd7, 0x09, 0x00, 0xc0,
+    0xc1, 0xdf, 0xc8, 0x09, 0xc6, 0x06, 0x08, 0x62,
+    0x14, 0xc0, 0x27, 0x04, 0xc6, 0x06, 0x10, 0x94,
+    0xf0, 0x07, 0x10, 0x08, 0x02, 0x00, 0xc1, 0x07,
+    0x01, 0x00, 0x70, 0x00, 0x04, 0x00, 0xf0, 0x07,
+    0x30, 0x01, 0x06, 0x00, 0x50, 0xaf, 0xe7, 0x07,
+    0xff, 0xff, 0xd0, 0x06, 0xe7, 0x07, 0x00, 0x00,
+    0xce, 0x06, 0xe7, 0x05, 0x00, 0xc0, 0x97, 0xcf,
+    0xd7, 0x09, 0x00, 0xc0, 0xc1, 0xdf, 0x48, 0x02,
+    0xd0, 0x09, 0xc6, 0x06, 0x27, 0x02, 0xc6, 0x06,
+    0xe7, 0x05, 0x00, 0xc0, 0x97, 0xcf, 0x48, 0x02,
+    0xc8, 0x37, 0x04, 0x00, 0x00, 0x0c, 0x0c, 0x00,
+    0x00, 0x60, 0x21, 0xc0, 0xc0, 0x37, 0x3e, 0x00,
+    0x23, 0xc9, 0xc0, 0x57, 0xb4, 0x05, 0x1b, 0xc8,
+    0xc0, 0x17, 0x3f, 0x00, 0xc0, 0x67, 0xc0, 0xff,
+    0x30, 0x00, 0x08, 0x00, 0xf0, 0x07, 0x00, 0x00,
+    0x04, 0x00, 0x00, 0x02, 0xc0, 0x17, 0x4c, 0x00,
+    0x30, 0x00, 0x06, 0x00, 0xf0, 0x07, 0xa0, 0x01,
+    0x0a, 0x00, 0x48, 0x02, 0xc1, 0x07, 0x02, 0x00,
+    0xd7, 0x09, 0x00, 0xc0, 0xc1, 0xdf, 0x51, 0xaf,
+    0xe7, 0x05, 0x00, 0xc0, 0x97, 0xcf, 0x9f, 0xaf,
+    0x08, 0x03, 0x9f, 0xaf, 0x7a, 0x02, 0x97, 0xcf,
+    0x9f, 0xaf, 0x7a, 0x02, 0xc9, 0x37, 0x04, 0x00,
+    0xc1, 0xdf, 0xc8, 0x09, 0xa2, 0x06, 0x50, 0x02,
+    0x67, 0x02, 0xa2, 0x06, 0xd1, 0x07, 0x00, 0x00,
+    0x27, 0xd8, 0xaa, 0x06, 0xc0, 0xdf, 0x9f, 0xaf,
+    0xc4, 0x01, 0x97, 0xcf, 0xe7, 0x57, 0x00, 0x00,
+    0xd2, 0x06, 0x97, 0xc1, 0xe7, 0x57, 0x01, 0x00,
+    0xa8, 0x06, 0x97, 0xc0, 0xc8, 0x09, 0xa0, 0x06,
+    0x08, 0x62, 0x97, 0xc0, 0x00, 0x02, 0xc0, 0x17,
+    0x0e, 0x00, 0x27, 0x00, 0x34, 0x01, 0x27, 0x0c,
+    0x0c, 0x00, 0x36, 0x01, 0xe7, 0x07, 0x50, 0xc3,
+    0x12, 0xc0, 0xe7, 0x07, 0xcc, 0x0b, 0x02, 0x00,
+    0xe7, 0x07, 0x01, 0x00, 0xa8, 0x06, 0xe7, 0x07,
+    0x05, 0x00, 0x90, 0xc0, 0x97, 0xcf, 0xc8, 0x09,
+    0xa4, 0x06, 0x08, 0x62, 0x02, 0xc0, 0x10, 0x64,
+    0x07, 0xc1, 0xe7, 0x07, 0x00, 0x00, 0x9e, 0x06,
+    0xe7, 0x07, 0x72, 0x04, 0x24, 0x00, 0x97, 0xcf,
+    0x27, 0x04, 0xa4, 0x06, 0xc8, 0x17, 0x0e, 0x00,
+    0x27, 0x02, 0x9e, 0x06, 0xe7, 0x07, 0x80, 0x04,
+    0x24, 0x00, 0x97, 0xcf, 0xd7, 0x09, 0x00, 0xc0,
+    0xc1, 0xdf, 0xe7, 0x57, 0x00, 0x00, 0x90, 0x06,
+    0x13, 0xc1, 0x9f, 0xaf, 0x06, 0x02, 0xe7, 0x57,
+    0x00, 0x00, 0x9e, 0x06, 0x13, 0xc0, 0xe7, 0x09,
+    0x9e, 0x06, 0x30, 0x01, 0xe7, 0x07, 0xf2, 0x05,
+    0x32, 0x01, 0xe7, 0x07, 0x10, 0x00, 0x96, 0xc0,
+    0xe7, 0x09, 0x9e, 0x06, 0x90, 0x06, 0x04, 0xcf,
+    0xe7, 0x57, 0x00, 0x00, 0x9e, 0x06, 0x02, 0xc1,
+    0x9f, 0xaf, 0x06, 0x02, 0xe7, 0x05, 0x00, 0xc0,
+    0x97, 0xcf, 0xd7, 0x09, 0x00, 0xc0, 0xc1, 0xdf,
+    0x08, 0x92, 0xe7, 0x57, 0x02, 0x00, 0xaa, 0x06,
+    0x02, 0xc3, 0xc8, 0x09, 0xa4, 0x06, 0x27, 0x02,
+    0xa6, 0x06, 0x08, 0x62, 0x03, 0xc1, 0xe7, 0x05,
+    0x00, 0xc0, 0x97, 0xcf, 0x27, 0x04, 0xa4, 0x06,
+    0xe7, 0x05, 0x00, 0xc0, 0xf0, 0x07, 0x40, 0x00,
+    0x08, 0x00, 0xf0, 0x07, 0x00, 0x00, 0x04, 0x00,
+    0x00, 0x02, 0xc0, 0x17, 0x0c, 0x00, 0x30, 0x00,
+    0x06, 0x00, 0xf0, 0x07, 0x46, 0x01, 0x0a, 0x00,
+    0xc8, 0x17, 0x04, 0x00, 0xc1, 0x07, 0x02, 0x00,
+    0x51, 0xaf, 0x97, 0xcf, 0xe7, 0x57, 0x00, 0x00,
+    0x96, 0x06, 0x97, 0xc0, 0xc1, 0xdf, 0xc8, 0x09,
+    0x96, 0x06, 0x27, 0x04, 0x96, 0x06, 0x27, 0x52,
+    0x98, 0x06, 0x03, 0xc1, 0xe7, 0x07, 0x96, 0x06,
+    0x98, 0x06, 0xc0, 0xdf, 0x17, 0x02, 0xc8, 0x17,
+    0x0e, 0x00, 0x9f, 0xaf, 0xba, 0x03, 0xc8, 0x05,
+    0x00, 0x60, 0x03, 0xc0, 0x9f, 0xaf, 0x24, 0x03,
+    0x97, 0xcf, 0x9f, 0xaf, 0x08, 0x03, 0x97, 0xcf,
+    0x57, 0x02, 0xc9, 0x07, 0xa4, 0x06, 0xd7, 0x09,
+    0x00, 0xc0, 0xc1, 0xdf, 0x08, 0x62, 0x1b, 0xc0,
+    0x50, 0x04, 0x11, 0x02, 0xe7, 0x05, 0x00, 0xc0,
+    0xc9, 0x05, 0x97, 0xcf, 0x97, 0x02, 0xca, 0x09,
+    0xd6, 0x06, 0xf2, 0x17, 0x01, 0x00, 0x04, 0x00,
+    0xf2, 0x27, 0x00, 0x00, 0x06, 0x00, 0xca, 0x17,
+    0x2c, 0x00, 0xf8, 0x77, 0x01, 0x00, 0x0e, 0x00,
+    0x06, 0xc0, 0xca, 0xd9, 0xf8, 0x57, 0xff, 0x00,
+    0x0e, 0x00, 0x01, 0xc1, 0xca, 0xd9, 0x22, 0x1c,
+    0x0c, 0x00, 0xe2, 0x27, 0x00, 0x00, 0xe2, 0x17,
+    0x01, 0x00, 0xe2, 0x27, 0x00, 0x00, 0xca, 0x05,
+    0x00, 0x0c, 0x0c, 0x00, 0xc0, 0x17, 0x41, 0x00,
+    0xc0, 0x67, 0xc0, 0xff, 0x30, 0x00, 0x08, 0x00,
+    0x00, 0x02, 0xc0, 0x17, 0x0c, 0x00, 0x30, 0x00,
+    0x06, 0x00, 0xf0, 0x07, 0xda, 0x00, 0x0a, 0x00,
+    0xf0, 0x07, 0x00, 0x00, 0x04, 0x00, 0x00, 0x0c,
+    0x08, 0x00, 0x40, 0xd1, 0x01, 0x00, 0xc0, 0x19,
+    0xce, 0x06, 0xc0, 0x59, 0xc2, 0x06, 0x04, 0xc9,
+    0x49, 0xaf, 0x9f, 0xaf, 0xec, 0x00, 0x4a, 0xaf,
+    0x67, 0x10, 0xce, 0x06, 0xc8, 0x17, 0x04, 0x00,
+    0xc1, 0x07, 0x01, 0x00, 0xd7, 0x09, 0x00, 0xc0,
+    0xc1, 0xdf, 0x50, 0xaf, 0xe7, 0x05, 0x00, 0xc0,
+    0x97, 0xcf, 0xc0, 0x07, 0x01, 0x00, 0xc1, 0x09,
+    0xac, 0x06, 0xc1, 0x77, 0x01, 0x00, 0x97, 0xc1,
+    0xd8, 0x77, 0x01, 0x00, 0x12, 0xc0, 0xc9, 0x07,
+    0x6a, 0x06, 0x9f, 0xaf, 0x08, 0x04, 0x04, 0xc1,
+    0xc1, 0x77, 0x08, 0x00, 0x13, 0xc0, 0x97, 0xcf,
+    0xc1, 0x77, 0x02, 0x00, 0x97, 0xc1, 0xc1, 0x77,
+    0x10, 0x00, 0x0c, 0xc0, 0x9f, 0xaf, 0x2c, 0x04,
+    0x97, 0xcf, 0xc1, 0x77, 0x04, 0x00, 0x06, 0xc0,
+    0xc9, 0x07, 0x70, 0x06, 0x9f, 0xaf, 0x08, 0x04,
+    0x97, 0xc0, 0x00, 0xcf, 0x00, 0x90, 0x97, 0xcf,
+    0x50, 0x54, 0x97, 0xc1, 0x70, 0x5c, 0x02, 0x00,
+    0x02, 0x00, 0x97, 0xc1, 0x70, 0x5c, 0x04, 0x00,
+    0x04, 0x00, 0x97, 0xcf, 0x80, 0x01, 0xc0, 0x00,
+    0x60, 0x00, 0x30, 0x00, 0x18, 0x00, 0x0c, 0x00,
+    0x06, 0x00, 0x00, 0x00, 0xcb, 0x09, 0xb2, 0x06,
+    0xcc, 0x09, 0xb4, 0x06, 0x0b, 0x53, 0x11, 0xc0,
+    0xc9, 0x02, 0xca, 0x07, 0x1c, 0x04, 0x9f, 0xaf,
+    0x08, 0x04, 0x97, 0xc0, 0x0a, 0xc8, 0x82, 0x08,
+    0x0a, 0xcf, 0x82, 0x08, 0x9f, 0xaf, 0x08, 0x04,
+    0x97, 0xc0, 0x05, 0xc2, 0x89, 0x30, 0x82, 0x60,
+    0x78, 0xc1, 0x00, 0x90, 0x97, 0xcf, 0x89, 0x10,
+    0x09, 0x53, 0x79, 0xc2, 0x89, 0x30, 0x82, 0x08,
+    0x7a, 0xcf, 0xc0, 0xdf, 0x97, 0xcf, 0xc0, 0xdf,
+    0x97, 0xcf, 0xe7, 0x09, 0x96, 0xc0, 0x92, 0x06,
+    0xe7, 0x09, 0x98, 0xc0, 0x94, 0x06, 0x0f, 0xcf,
+    0xe7, 0x09, 0x96, 0xc0, 0x92, 0x06, 0xe7, 0x09,
+    0x98, 0xc0, 0x94, 0x06, 0xe7, 0x09, 0x9e, 0x06,
+    0x30, 0x01, 0xe7, 0x07, 0xf2, 0x05, 0x32, 0x01,
+    0xe7, 0x07, 0x10, 0x00, 0x96, 0xc0, 0xd7, 0x09,
+    0x00, 0xc0, 0x17, 0x02, 0xc8, 0x09, 0x90, 0x06,
+    0xc8, 0x37, 0x0e, 0x00, 0xe7, 0x77, 0x2a, 0x00,
+    0x92, 0x06, 0x30, 0xc0, 0x97, 0x02, 0xca, 0x09,
+    0xd6, 0x06, 0xe7, 0x77, 0x20, 0x00, 0x92, 0x06,
+    0x0e, 0xc0, 0xf2, 0x17, 0x01, 0x00, 0x10, 0x00,
+    0xf2, 0x27, 0x00, 0x00, 0x12, 0x00, 0xe7, 0x77,
+    0x0a, 0x00, 0x92, 0x06, 0xca, 0x05, 0x1e, 0xc0,
+    0x97, 0x02, 0xca, 0x09, 0xd6, 0x06, 0xf2, 0x17,
+    0x01, 0x00, 0x0c, 0x00, 0xf2, 0x27, 0x00, 0x00,
+    0x0e, 0x00, 0xe7, 0x77, 0x02, 0x00, 0x92, 0x06,
+    0x07, 0xc0, 0xf2, 0x17, 0x01, 0x00, 0x44, 0x00,
+    0xf2, 0x27, 0x00, 0x00, 0x46, 0x00, 0x06, 0xcf,
+    0xf2, 0x17, 0x01, 0x00, 0x60, 0x00, 0xf2, 0x27,
+    0x00, 0x00, 0x62, 0x00, 0xca, 0x05, 0x9f, 0xaf,
+    0x08, 0x03, 0x0f, 0xcf, 0x57, 0x02, 0x09, 0x02,
+    0xf1, 0x09, 0x94, 0x06, 0x0c, 0x00, 0xf1, 0xda,
+    0x0c, 0x00, 0xc8, 0x09, 0x98, 0x06, 0x50, 0x02,
+    0x67, 0x02, 0x98, 0x06, 0xd1, 0x07, 0x00, 0x00,
+    0xc9, 0x05, 0xe7, 0x09, 0x9e, 0x06, 0x90, 0x06,
+    0xe7, 0x57, 0x00, 0x00, 0x90, 0x06, 0x02, 0xc0,
+    0x9f, 0xaf, 0x06, 0x02, 0xc8, 0x05, 0xe7, 0x05,
+    0x00, 0xc0, 0xc0, 0xdf, 0x97, 0xcf, 0xd7, 0x09,
+    0x00, 0xc0, 0x17, 0x00, 0x17, 0x02, 0x97, 0x02,
+    0xc0, 0x09, 0x92, 0xc0, 0xe7, 0x07, 0x04, 0x00,
+    0x90, 0xc0, 0xca, 0x09, 0xd6, 0x06, 0xe7, 0x07,
+    0x00, 0x00, 0xa8, 0x06, 0xe7, 0x07, 0x6a, 0x04,
+    0x02, 0x00, 0xc0, 0x77, 0x02, 0x00, 0x08, 0xc0,
+    0xf2, 0x17, 0x01, 0x00, 0x50, 0x00, 0xf2, 0x27,
+    0x00, 0x00, 0x52, 0x00, 0x9f, 0xcf, 0x24, 0x06,
+    0xc0, 0x77, 0x10, 0x00, 0x06, 0xc0, 0xf2, 0x17,
+    0x01, 0x00, 0x58, 0x00, 0xf2, 0x27, 0x00, 0x00,
+    0x5a, 0x00, 0xc0, 0x77, 0x80, 0x00, 0x06, 0xc0,
+    0xf2, 0x17, 0x01, 0x00, 0x70, 0x00, 0xf2, 0x27,
+    0x00, 0x00, 0x72, 0x00, 0xc0, 0x77, 0x08, 0x00,
+    0x1d, 0xc1, 0xf2, 0x17, 0x01, 0x00, 0x08, 0x00,
+    0xf2, 0x27, 0x00, 0x00, 0x0a, 0x00, 0xc0, 0x77,
+    0x00, 0x02, 0x06, 0xc0, 0xf2, 0x17, 0x01, 0x00,
+    0x64, 0x00, 0xf2, 0x27, 0x00, 0x00, 0x66, 0x00,
+    0xc0, 0x77, 0x40, 0x00, 0x06, 0xc0, 0xf2, 0x17,
+    0x01, 0x00, 0x5c, 0x00, 0xf2, 0x27, 0x00, 0x00,
+    0x5e, 0x00, 0xc0, 0x77, 0x01, 0x00, 0x01, 0xc0,
+    0x1b, 0xcf, 0x1a, 0xcf, 0xf2, 0x17, 0x01, 0x00,
+    0x00, 0x00, 0xf2, 0x27, 0x00, 0x00, 0x02, 0x00,
+    0xc8, 0x09, 0x34, 0x01, 0xca, 0x17, 0x14, 0x00,
+    0xd8, 0x77, 0x01, 0x00, 0x05, 0xc0, 0xca, 0xd9,
+    0xd8, 0x57, 0xff, 0x00, 0x01, 0xc0, 0xca, 0xd9,
+    0xe2, 0x19, 0x94, 0xc0, 0xe2, 0x27, 0x00, 0x00,
+    0xe2, 0x17, 0x01, 0x00, 0xe2, 0x27, 0x00, 0x00,
+    0x9f, 0xaf, 0x40, 0x06, 0x9f, 0xaf, 0xc4, 0x01,
+    0xe7, 0x57, 0x00, 0x00, 0xd2, 0x06, 0x9f, 0xa1,
+    0x0e, 0x0a, 0xca, 0x05, 0xc8, 0x05, 0xc0, 0x05,
+    0xe7, 0x05, 0x00, 0xc0, 0xc0, 0xdf, 0x97, 0xcf,
+    0xc8, 0x09, 0xa0, 0x06, 0x08, 0x62, 0x97, 0xc0,
+    0x27, 0x04, 0xa0, 0x06, 0x27, 0x52, 0xa2, 0x06,
+    0x03, 0xc1, 0xe7, 0x07, 0xa0, 0x06, 0xa2, 0x06,
+    0x9f, 0xaf, 0x08, 0x03, 0xe7, 0x57, 0x00, 0x00,
+    0xaa, 0x06, 0x02, 0xc0, 0x27, 0xda, 0xaa, 0x06,
+    0x97, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0xff, 0xff, 0xfb, 0x13, 0xe7, 0x57,
+    0x00, 0x80, 0xb2, 0x00, 0x06, 0xc2, 0xe7, 0x07,
+    0xee, 0x0b, 0x12, 0x00, 0xe7, 0x07, 0x34, 0x0c,
+    0xb2, 0x00, 0xe7, 0x07, 0xc6, 0x07, 0xf2, 0x02,
+    0xc8, 0x09, 0xb4, 0x00, 0xf8, 0x07, 0x02, 0x00,
+    0x0d, 0x00, 0xd7, 0x09, 0x0e, 0xc0, 0xe7, 0x07,
+    0x00, 0x00, 0x0e, 0xc0, 0xc8, 0x09, 0xde, 0x00,
+    0xc8, 0x17, 0x09, 0x00, 0xc9, 0x07, 0xda, 0x06,
+    0xc0, 0x07, 0x04, 0x00, 0x68, 0x0a, 0x00, 0xda,
+    0x7d, 0xc1, 0xe7, 0x09, 0xc0, 0x00, 0x7c, 0x06,
+    0xe7, 0x09, 0xbe, 0x00, 0x78, 0x06, 0xe7, 0x09,
+    0x10, 0x00, 0xbc, 0x06, 0xc8, 0x07, 0xd6, 0x07,
+    0x9f, 0xaf, 0xae, 0x07, 0x9f, 0xaf, 0x00, 0x0a,
+    0xc8, 0x09, 0xde, 0x00, 0x00, 0x0e, 0x0f, 0x00,
+    0x41, 0x90, 0x9f, 0xde, 0x06, 0x00, 0x44, 0xaf,
+    0x27, 0x00, 0xb2, 0x06, 0x27, 0x00, 0xb4, 0x06,
+    0x27, 0x00, 0xb6, 0x06, 0xc0, 0x07, 0x74, 0x00,
+    0x44, 0xaf, 0x27, 0x00, 0xd6, 0x06, 0x08, 0x00,
+    0x00, 0x90, 0xc1, 0x07, 0x3a, 0x00, 0x20, 0x00,
+    0x01, 0xda, 0x7d, 0xc1, 0x9f, 0xaf, 0xba, 0x09,
+    0xc0, 0x07, 0x44, 0x00, 0x48, 0xaf, 0x27, 0x00,
+    0x7a, 0x06, 0x9f, 0xaf, 0x96, 0x0a, 0xe7, 0x07,
+    0x01, 0x00, 0xc0, 0x06, 0xe7, 0x05, 0x0e, 0xc0,
+    0x97, 0xcf, 0x49, 0xaf, 0xe7, 0x87, 0x43, 0x00,
+    0x0e, 0xc0, 0xe7, 0x07, 0xff, 0xff, 0xbe, 0x06,
+    0x9f, 0xaf, 0xae, 0x0a, 0xc0, 0x07, 0x01, 0x00,
+    0x60, 0xaf, 0x4a, 0xaf, 0x97, 0xcf, 0x00, 0x08,
+    0x09, 0x08, 0x11, 0x08, 0x00, 0xda, 0x7c, 0xc1,
+    0x97, 0xcf, 0x67, 0x04, 0xcc, 0x02, 0xc0, 0xdf,
+    0x51, 0x94, 0xb1, 0xaf, 0x06, 0x00, 0xc1, 0xdf,
+    0xc9, 0x09, 0xcc, 0x02, 0x49, 0x62, 0x75, 0xc1,
+    0xc0, 0xdf, 0xa7, 0xcf, 0xd6, 0x02, 0x0e, 0x00,
+    0x24, 0x00, 0x80, 0x04, 0x22, 0x00, 0x4e, 0x05,
+    0xd0, 0x00, 0x0e, 0x0a, 0xaa, 0x00, 0x30, 0x08,
+    0xbe, 0x00, 0x4a, 0x0a, 0x10, 0x00, 0x20, 0x00,
+    0x04, 0x00, 0x6e, 0x04, 0x02, 0x00, 0x6a, 0x04,
+    0x06, 0x00, 0x00, 0x00, 0x24, 0xc0, 0x04, 0x04,
+    0x28, 0xc0, 0xfe, 0xfb, 0x1e, 0xc0, 0x00, 0x04,
+    0x22, 0xc0, 0xff, 0xf4, 0xc0, 0x00, 0x90, 0x09,
+    0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x56, 0x08,
+    0x60, 0x08, 0xd0, 0x08, 0xda, 0x08, 0x00, 0x09,
+    0x04, 0x09, 0x08, 0x09, 0x32, 0x09, 0x42, 0x09,
+    0x50, 0x09, 0x52, 0x09, 0x5a, 0x09, 0x5a, 0x09,
+    0x27, 0x02, 0xca, 0x06, 0x97, 0xcf, 0xe7, 0x07,
+    0x00, 0x00, 0xca, 0x06, 0x0a, 0x0e, 0x01, 0x00,
+    0xca, 0x57, 0x0e, 0x00, 0x9f, 0xc3, 0x5a, 0x09,
+    0xca, 0x37, 0x00, 0x00, 0x9f, 0xc2, 0x5a, 0x09,
+    0x0a, 0xd2, 0xb2, 0xcf, 0x16, 0x08, 0xc8, 0x09,
+    0xde, 0x00, 0x07, 0x06, 0x9f, 0xcf, 0x6c, 0x09,
+    0x17, 0x02, 0xc8, 0x09, 0xde, 0x00, 0x00, 0x0e,
+    0x0f, 0x00, 0x41, 0x90, 0x9f, 0xde, 0x06, 0x00,
+    0xc8, 0x05, 0x30, 0x50, 0x06, 0x00, 0x9f, 0xc8,
+    0x5a, 0x09, 0x27, 0x0c, 0x02, 0x00, 0xb0, 0x06,
+    0xc0, 0x09, 0xb2, 0x06, 0x27, 0x00, 0xb4, 0x06,
+    0xe7, 0x07, 0x00, 0x00, 0xae, 0x06, 0x27, 0x00,
+    0x80, 0x06, 0x00, 0x1c, 0x06, 0x00, 0x27, 0x00,
+    0xb6, 0x06, 0x41, 0x90, 0x67, 0x50, 0xb0, 0x06,
+    0x0d, 0xc0, 0x67, 0x00, 0x7e, 0x06, 0x27, 0x0c,
+    0x06, 0x00, 0x82, 0x06, 0xe7, 0x07, 0xbc, 0x08,
+    0x84, 0x06, 0xc8, 0x07, 0x7e, 0x06, 0x41, 0x90,
+    0x51, 0xaf, 0x97, 0xcf, 0x9f, 0xaf, 0x48, 0x0c,
+    0xe7, 0x09, 0xb6, 0x06, 0xb4, 0x06, 0xe7, 0x09,
+    0xb0, 0x06, 0xae, 0x06, 0x59, 0xaf, 0x97, 0xcf,
+    0x27, 0x0c, 0x02, 0x00, 0xac, 0x06, 0x59, 0xaf,
+    0x97, 0xcf, 0x09, 0x0c, 0x02, 0x00, 0x09, 0xda,
+    0x49, 0xd2, 0xc9, 0x19, 0xd6, 0x06, 0xc8, 0x07,
+    0x7e, 0x06, 0xe0, 0x07, 0x00, 0x00, 0x60, 0x02,
+    0xe0, 0x07, 0x04, 0x00, 0xd0, 0x07, 0xcc, 0x08,
+    0x48, 0xdb, 0x41, 0x90, 0x50, 0xaf, 0x97, 0xcf,
+    0x59, 0xaf, 0x97, 0xcf, 0x59, 0xaf, 0x97, 0xcf,
+    0xf0, 0x57, 0x06, 0x00, 0x06, 0x00, 0x25, 0xc1,
+    0xe7, 0x07, 0x70, 0x06, 0x80, 0x06, 0x41, 0x90,
+    0x67, 0x00, 0x7e, 0x06, 0x27, 0x0c, 0x06, 0x00,
+    0x82, 0x06, 0xe7, 0x07, 0x8c, 0x09, 0x84, 0x06,
+    0xc8, 0x07, 0x7e, 0x06, 0x41, 0x90, 0x51, 0xaf,
+    0x97, 0xcf, 0x07, 0x0c, 0x06, 0x00, 0xc7, 0x57,
+    0x06, 0x00, 0x0f, 0xc1, 0xc8, 0x07, 0x70, 0x06,
+    0x15, 0xcf, 0x00, 0x0c, 0x02, 0x00, 0x00, 0xda,
+    0x40, 0xd1, 0x27, 0x00, 0xc2, 0x06, 0x1e, 0xcf,
+    0x1d, 0xcf, 0x27, 0x0c, 0x02, 0x00, 0xcc, 0x06,
+    0x19, 0xcf, 0x27, 0x02, 0x20, 0x01, 0xe7, 0x07,
+    0x08, 0x00, 0x22, 0x01, 0xe7, 0x07, 0x13, 0x00,
+    0xb0, 0xc0, 0x97, 0xcf, 0x41, 0x90, 0x67, 0x00,
+    0x7e, 0x06, 0xe7, 0x01, 0x82, 0x06, 0x27, 0x02,
+    0x80, 0x06, 0xe7, 0x07, 0x8c, 0x09, 0x84, 0x06,
+    0xc8, 0x07, 0x7e, 0x06, 0xc1, 0x07, 0x00, 0x80,
+    0x50, 0xaf, 0x97, 0xcf, 0x59, 0xaf, 0x97, 0xcf,
+    0x00, 0x60, 0x05, 0xc0, 0xe7, 0x07, 0x00, 0x00,
+    0xc4, 0x06, 0xa7, 0xcf, 0x7c, 0x06, 0x9f, 0xaf,
+    0x00, 0x0a, 0xe7, 0x07, 0x01, 0x00, 0xc4, 0x06,
+    0x49, 0xaf, 0xd7, 0x09, 0x00, 0xc0, 0x07, 0xaf,
+    0xe7, 0x05, 0x00, 0xc0, 0x4a, 0xaf, 0xa7, 0xcf,
+    0x7c, 0x06, 0xc0, 0x07, 0xfe, 0x7f, 0x44, 0xaf,
+    0x40, 0x00, 0xc0, 0x37, 0x00, 0x01, 0x41, 0x90,
+    0xc0, 0x37, 0x08, 0x00, 0xdf, 0xde, 0x50, 0x06,
+    0xc0, 0x57, 0x10, 0x00, 0x02, 0xc2, 0xc0, 0x07,
+    0x10, 0x00, 0x27, 0x00, 0x9a, 0x06, 0x41, 0x90,
+    0x9f, 0xde, 0x40, 0x06, 0x44, 0xaf, 0x27, 0x00,
+    0x9c, 0x06, 0xc0, 0x09, 0x9a, 0x06, 0x41, 0x90,
+    0x00, 0xd2, 0x00, 0xd8, 0x9f, 0xde, 0x08, 0x00,
+    0x44, 0xaf, 0x27, 0x00, 0xc8, 0x06, 0x97, 0xcf,
+    0xe7, 0x87, 0x00, 0x84, 0x28, 0xc0, 0xe7, 0x67,
+    0xff, 0xfb, 0x24, 0xc0, 0x97, 0xcf, 0xe7, 0x87,
+    0x01, 0x00, 0xd2, 0x06, 0xe7, 0x57, 0x00, 0x00,
+    0xa8, 0x06, 0x97, 0xc1, 0x9f, 0xaf, 0x00, 0x0a,
+    0xe7, 0x87, 0x00, 0x06, 0x22, 0xc0, 0xe7, 0x07,
+    0x00, 0x00, 0x90, 0xc0, 0xe7, 0x67, 0xfe, 0xff,
+    0x3e, 0xc0, 0xe7, 0x07, 0x26, 0x00, 0x0a, 0xc0,
+    0xe7, 0x87, 0x01, 0x00, 0x3e, 0xc0, 0xe7, 0x07,
+    0xff, 0xff, 0xbe, 0x06, 0x9f, 0xaf, 0x10, 0x0b,
+    0x97, 0xcf, 0x17, 0x00, 0xa7, 0xaf, 0x78, 0x06,
+    0xc0, 0x05, 0x27, 0x00, 0x76, 0x06, 0xe7, 0x87,
+    0x01, 0x00, 0xd2, 0x06, 0x9f, 0xaf, 0x00, 0x0a,
+    0xe7, 0x07, 0x0c, 0x00, 0x40, 0xc0, 0x9f, 0xaf,
+    0x10, 0x0b, 0x00, 0x90, 0x27, 0x00, 0xa6, 0x06,
+    0x27, 0x00, 0xaa, 0x06, 0xe7, 0x09, 0xb2, 0x06,
+    0xb4, 0x06, 0x27, 0x00, 0xae, 0x06, 0x27, 0x00,
+    0xac, 0x06, 0x9f, 0xaf, 0xae, 0x0a, 0xc0, 0x07,
+    0x00, 0x00, 0x27, 0x00, 0xb2, 0x02, 0x27, 0x00,
+    0xb4, 0x02, 0x27, 0x00, 0x8e, 0x06, 0xc0, 0x07,
+    0x06, 0x00, 0xc8, 0x09, 0xde, 0x00, 0xc8, 0x17,
+    0x03, 0x00, 0xc9, 0x07, 0x70, 0x06, 0x29, 0x0a,
+    0x00, 0xda, 0x7d, 0xc1, 0x97, 0xcf, 0xd7, 0x09,
+    0x00, 0xc0, 0xc1, 0xdf, 0x00, 0x90, 0x27, 0x00,
+    0x96, 0x06, 0xe7, 0x07, 0x96, 0x06, 0x98, 0x06,
+    0x27, 0x00, 0xa0, 0x06, 0xe7, 0x07, 0xa0, 0x06,
+    0xa2, 0x06, 0x27, 0x00, 0xa6, 0x06, 0x27, 0x00,
+    0x90, 0x06, 0x27, 0x00, 0x9e, 0x06, 0xc8, 0x09,
+    0x9c, 0x06, 0xc1, 0x09, 0x9a, 0x06, 0xc9, 0x07,
+    0xa4, 0x06, 0x11, 0x02, 0x09, 0x02, 0xc8, 0x17,
+    0x40, 0x06, 0x01, 0xda, 0x7a, 0xc1, 0x51, 0x94,
+    0xc8, 0x09, 0xc8, 0x06, 0xc9, 0x07, 0xc6, 0x06,
+    0xc1, 0x09, 0x9a, 0x06, 0x11, 0x02, 0x09, 0x02,
+    0xc8, 0x17, 0x08, 0x00, 0x01, 0xda, 0x7a, 0xc1,
+    0x51, 0x94, 0xe7, 0x05, 0x00, 0xc0, 0x97, 0xcf,
+    0xe7, 0x57, 0x00, 0x00, 0x76, 0x06, 0x97, 0xc0,
+    0x9f, 0xaf, 0x04, 0x00, 0xe7, 0x09, 0xbe, 0x06,
+    0xba, 0x06, 0xe7, 0x57, 0xff, 0xff, 0xba, 0x06,
+    0x04, 0xc1, 0xe7, 0x07, 0x10, 0x0b, 0xb8, 0x06,
+    0x97, 0xcf, 0xe7, 0x17, 0x32, 0x00, 0xba, 0x06,
+    0xe7, 0x67, 0xff, 0x07, 0xba, 0x06, 0xe7, 0x07,
+    0x46, 0x0b, 0xb8, 0x06, 0x97, 0xcf, 0xe7, 0x57,
+    0x00, 0x00, 0xc0, 0x06, 0x23, 0xc0, 0xe7, 0x07,
+    0x04, 0x00, 0x90, 0xc0, 0xe7, 0x07, 0x00, 0x80,
+    0x80, 0xc0, 0xe7, 0x07, 0x00, 0x00, 0x80, 0xc0,
+    0xe7, 0x07, 0x00, 0x80, 0x80, 0xc0, 0xc0, 0x07,
+    0x00, 0x00, 0xc0, 0x07, 0x00, 0x00, 0xc0, 0x07,
+    0x00, 0x00, 0xe7, 0x07, 0x00, 0x00, 0x80, 0xc0,
+    0xe7, 0x07, 0x00, 0x80, 0x80, 0xc0, 0xe7, 0x07,
+    0x00, 0x80, 0x40, 0xc0, 0xc0, 0x07, 0x00, 0x00,
+    0xe7, 0x07, 0x00, 0x00, 0x40, 0xc0, 0xe7, 0x07,
+    0x00, 0x00, 0x80, 0xc0, 0xe7, 0x07, 0x04, 0x00,
+    0x90, 0xc0, 0xe7, 0x07, 0x00, 0x02, 0x40, 0xc0,
+    0xe7, 0x07, 0x0c, 0x02, 0x40, 0xc0, 0xe7, 0x07,
+    0x00, 0x00, 0xc0, 0x06, 0xe7, 0x07, 0x00, 0x00,
+    0xb8, 0x06, 0xe7, 0x07, 0x00, 0x00, 0xd2, 0x06,
+    0xd7, 0x09, 0x00, 0xc0, 0xc1, 0xdf, 0x9f, 0xaf,
+    0x34, 0x02, 0xe7, 0x05, 0x00, 0xc0, 0x9f, 0xaf,
+    0xc4, 0x01, 0x97, 0xcf, 0xd7, 0x09, 0x00, 0xc0,
+    0x17, 0x00, 0x17, 0x02, 0x97, 0x02, 0xe7, 0x57,
+    0x00, 0x00, 0xa8, 0x06, 0x06, 0xc0, 0xc0, 0x09,
+    0x92, 0xc0, 0xc0, 0x77, 0x09, 0x02, 0x9f, 0xc1,
+    0x5c, 0x05, 0x9f, 0xcf, 0x32, 0x06, 0xd7, 0x09,
+    0x0e, 0xc0, 0xe7, 0x07, 0x00, 0x00, 0x0e, 0xc0,
+    0x9f, 0xaf, 0x02, 0x0c, 0xe7, 0x05, 0x0e, 0xc0,
+    0x97, 0xcf, 0xd7, 0x09, 0x00, 0xc0, 0x17, 0x02,
+    0xc8, 0x09, 0xb0, 0xc0, 0xe7, 0x67, 0xfe, 0x7f,
+    0xb0, 0xc0, 0xc8, 0x77, 0x00, 0x20, 0x9f, 0xc1,
+    0x64, 0xeb, 0xe7, 0x57, 0x00, 0x00, 0xc8, 0x02,
+    0x9f, 0xc1, 0x80, 0xeb, 0xc8, 0x99, 0xca, 0x02,
+    0xc8, 0x67, 0x04, 0x00, 0x9f, 0xc1, 0x96, 0xeb,
+    0x9f, 0xcf, 0x4c, 0xeb, 0xe7, 0x07, 0x00, 0x00,
+    0xa6, 0xc0, 0xe7, 0x09, 0xb0, 0xc0, 0xc8, 0x02,
+    0xe7, 0x07, 0x03, 0x00, 0xb0, 0xc0, 0x97, 0xcf,
+    0xc0, 0x09, 0xb0, 0x06, 0xc0, 0x37, 0x01, 0x00,
+    0x97, 0xc9, 0xc9, 0x09, 0xb2, 0x06, 0x02, 0x00,
+    0x41, 0x90, 0x48, 0x02, 0xc9, 0x17, 0x06, 0x00,
+    0x9f, 0xaf, 0x08, 0x04, 0x9f, 0xa2, 0x72, 0x0c,
+    0x02, 0xda, 0x77, 0xc1, 0x41, 0x60, 0x71, 0xc1,
+    0x97, 0xcf, 0x17, 0x02, 0x57, 0x02, 0x43, 0x04,
+    0x21, 0x04, 0xe0, 0x00, 0x43, 0x04, 0x21, 0x04,
+    0xe0, 0x00, 0x43, 0x04, 0x21, 0x04, 0xe0, 0x00,
+    0xc1, 0x07, 0x01, 0x00, 0xc9, 0x05, 0xc8, 0x05,
+    0x97, 0xcf, 0xe7, 0x07, 0x01, 0x00, 0x8e, 0x06,
+    0xc8, 0x07, 0x86, 0x06, 0xe7, 0x07, 0x00, 0x00,
+    0x86, 0x06, 0xe7, 0x07, 0x10, 0x08, 0x88, 0x06,
+    0xe7, 0x07, 0x04, 0x00, 0x8a, 0x06, 0xe7, 0x07,
+    0xbc, 0x0c, 0x8c, 0x06, 0xc1, 0x07, 0x03, 0x80,
+    0x50, 0xaf, 0x97, 0xcf, 0xe7, 0x07, 0x00, 0x00,
+    0x8e, 0x06, 0x97, 0xcf,
+    0x00, 0x00
+};
+
+/****************************************************************
+ *     kaweth_new_code_fix
+ ****************************************************************/
+static __u8 kaweth_new_code_fix[] = 
+{
+    0xB6, 0xC3, 0xAA, 0xBB, 0xCC, 0xDD,
+    0x02, 0x00, 0x08, 0x00, 0x28, 0x00, 0x2c, 0x00,
+    0x34, 0x00, 0x3c, 0x00, 0x40, 0x00, 0x48, 0x00,
+    0x54, 0x00, 0x58, 0x00, 0x5e, 0x00, 0x64, 0x00,
+    0x68, 0x00, 0x6e, 0x00, 0x6c, 0x00, 0x72, 0x00,
+    0x76, 0x00, 0x7c, 0x00, 0x80, 0x00, 0x86, 0x00,
+    0x8a, 0x00, 0x90, 0x00, 0x94, 0x00, 0x98, 0x00,
+    0x9e, 0x00, 0xa6, 0x00, 0xaa, 0x00, 0xb0, 0x00,
+    0xb4, 0x00, 0xb8, 0x00, 0xc0, 0x00, 0xc6, 0x00,
+    0xca, 0x00, 0xd0, 0x00, 0xd4, 0x00, 0xd8, 0x00,
+    0xe0, 0x00, 0xde, 0x00, 0xe8, 0x00, 0xf0, 0x00,
+    0xfc, 0x00, 0x04, 0x01, 0x0a, 0x01, 0x18, 0x01,
+    0x22, 0x01, 0x28, 0x01, 0x3a, 0x01, 0x3e, 0x01,
+    0x7e, 0x01, 0x98, 0x01, 0x9c, 0x01, 0xa2, 0x01,
+    0xac, 0x01, 0xb2, 0x01, 0xba, 0x01, 0xc0, 0x01,
+    0xc8, 0x01, 0xd0, 0x01, 0xd6, 0x01, 0xf4, 0x01,
+    0xfc, 0x01, 0x08, 0x02, 0x16, 0x02, 0x1a, 0x02,
+    0x22, 0x02, 0x2a, 0x02, 0x2e, 0x02, 0x3e, 0x02,
+    0x44, 0x02, 0x4a, 0x02, 0x50, 0x02, 0x64, 0x02,
+    0x62, 0x02, 0x6c, 0x02, 0x72, 0x02, 0x86, 0x02,
+    0x8c, 0x02, 0x90, 0x02, 0x9e, 0x02, 0xbc, 0x02,
+    0xd0, 0x02, 0xd8, 0x02, 0xdc, 0x02, 0xe0, 0x02,
+    0xe8, 0x02, 0xe6, 0x02, 0xf4, 0x02, 0xfe, 0x02,
+    0x04, 0x03, 0x0c, 0x03, 0x28, 0x03, 0x7c, 0x03,
+    0x90, 0x03, 0x94, 0x03, 0x9c, 0x03, 0xa2, 0x03,
+    0xc0, 0x03, 0xd0, 0x03, 0xd4, 0x03, 0xee, 0x03,
+    0xfa, 0x03, 0xfe, 0x03, 0x2e, 0x04, 0x32, 0x04,
+    0x3c, 0x04, 0x40, 0x04, 0x4e, 0x04, 0x76, 0x04,
+    0x7c, 0x04, 0x84, 0x04, 0x8a, 0x04, 0x8e, 0x04,
+    0xa6, 0x04, 0xb0, 0x04, 0xb8, 0x04, 0xbe, 0x04,
+    0xd2, 0x04, 0xdc, 0x04, 0xee, 0x04, 0x10, 0x05,
+    0x1a, 0x05, 0x24, 0x05, 0x2a, 0x05, 0x36, 0x05,
+    0x34, 0x05, 0x3c, 0x05, 0x42, 0x05, 0x64, 0x05,
+    0x6a, 0x05, 0x6e, 0x05, 0x86, 0x05, 0x22, 0x06,
+    0x26, 0x06, 0x2c, 0x06, 0x30, 0x06, 0x42, 0x06,
+    0x4a, 0x06, 0x4e, 0x06, 0x56, 0x06, 0x54, 0x06,
+    0x5a, 0x06, 0x60, 0x06, 0x66, 0x06, 0xe8, 0x06,
+    0xee, 0x06, 0xf4, 0x06, 0x16, 0x07, 0x26, 0x07,
+    0x2c, 0x07, 0x32, 0x07, 0x36, 0x07, 0x3a, 0x07,
+    0x3e, 0x07, 0x52, 0x07, 0x56, 0x07, 0x5a, 0x07,
+    0x64, 0x07, 0x76, 0x07, 0x7a, 0x07, 0x80, 0x07,
+    0x84, 0x07, 0x8a, 0x07, 0x9e, 0x07, 0xa2, 0x07,
+    0xda, 0x07, 0xde, 0x07, 0xe2, 0x07, 0xe6, 0x07,
+    0xea, 0x07, 0xee, 0x07, 0xf2, 0x07, 0xf6, 0x07,
+    0x0e, 0x08, 0x16, 0x08, 0x18, 0x08, 0x1a, 0x08,
+    0x1c, 0x08, 0x1e, 0x08, 0x20, 0x08, 0x22, 0x08,
+    0x24, 0x08, 0x26, 0x08, 0x28, 0x08, 0x2a, 0x08,
+    0x2c, 0x08, 0x2e, 0x08, 0x32, 0x08, 0x3a, 0x08,
+    0x46, 0x08, 0x4e, 0x08, 0x54, 0x08, 0x5e, 0x08,
+    0x78, 0x08, 0x7e, 0x08, 0x82, 0x08, 0x86, 0x08,
+    0x8c, 0x08, 0x90, 0x08, 0x98, 0x08, 0x9e, 0x08,
+    0xa4, 0x08, 0xaa, 0x08, 0xb0, 0x08, 0xae, 0x08,
+    0xb4, 0x08, 0xbe, 0x08, 0xc4, 0x08, 0xc2, 0x08,
+    0xca, 0x08, 0xc8, 0x08, 0xd4, 0x08, 0xe4, 0x08,
+    0xe8, 0x08, 0xf6, 0x08, 0x14, 0x09, 0x12, 0x09,
+    0x1a, 0x09, 0x20, 0x09, 0x26, 0x09, 0x24, 0x09,
+    0x2a, 0x09, 0x3e, 0x09, 0x4c, 0x09, 0x56, 0x09,
+    0x70, 0x09, 0x74, 0x09, 0x78, 0x09, 0x7e, 0x09,
+    0x7c, 0x09, 0x82, 0x09, 0x98, 0x09, 0x9c, 0x09,
+    0xa0, 0x09, 0xa6, 0x09, 0xb8, 0x09, 0xdc, 0x09,
+    0xe8, 0x09, 0xec, 0x09, 0xfc, 0x09, 0x12, 0x0a,
+    0x18, 0x0a, 0x1e, 0x0a, 0x42, 0x0a, 0x46, 0x0a,
+    0x4e, 0x0a, 0x54, 0x0a, 0x5a, 0x0a, 0x5e, 0x0a,
+    0x68, 0x0a, 0x6e, 0x0a, 0x72, 0x0a, 0x78, 0x0a,
+    0x76, 0x0a, 0x7c, 0x0a, 0x80, 0x0a, 0x84, 0x0a,
+    0x94, 0x0a, 0xa4, 0x0a, 0xb8, 0x0a, 0xbe, 0x0a,
+    0xbc, 0x0a, 0xc2, 0x0a, 0xc8, 0x0a, 0xc6, 0x0a,
+    0xcc, 0x0a, 0xd0, 0x0a, 0xd4, 0x0a, 0xd8, 0x0a,
+    0xdc, 0x0a, 0xe0, 0x0a, 0xf2, 0x0a, 0xf6, 0x0a,
+    0xfa, 0x0a, 0x14, 0x0b, 0x1a, 0x0b, 0x20, 0x0b,
+    0x1e, 0x0b, 0x26, 0x0b, 0x2e, 0x0b, 0x2c, 0x0b,
+    0x36, 0x0b, 0x3c, 0x0b, 0x42, 0x0b, 0x40, 0x0b,
+    0x4a, 0x0b, 0xaa, 0x0b, 0xb0, 0x0b, 0xb6, 0x0b,
+    0xc0, 0x0b, 0xc8, 0x0b, 0xda, 0x0b, 0xe8, 0x0b,
+    0xec, 0x0b, 0xfa, 0x0b, 0x4a, 0x0c, 0x54, 0x0c,
+    0x62, 0x0c, 0x66, 0x0c, 0x96, 0x0c, 0x9a, 0x0c,
+    0xa0, 0x0c, 0xa6, 0x0c, 0xa4, 0x0c, 0xac, 0x0c,
+    0xb2, 0x0c, 0xb0, 0x0c, 0xc0, 0x0c,
+    0x00, 0x00
+};
+
+
+const int len_kaweth_trigger_code = sizeof(kaweth_trigger_code);
+const int len_kaweth_trigger_code_fix = sizeof(kaweth_trigger_code_fix);
+const int len_kaweth_new_code = sizeof(kaweth_new_code);
+const int len_kaweth_new_code_fix = sizeof(kaweth_new_code_fix);
index bf939f901f1fb0b26f074dd630f69cc41cfd499e..ff137af62b38f60242cd1046c251d9026153b94f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  linux/drivers/video/acornfb.c
  *
- *  Copyright (C) 1998-2000 Russell King
+ *  Copyright (C) 1998-2001 Russell King
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -30,6 +30,7 @@
 #include <asm/hardware.h>
 #include <asm/io.h>
 #include <asm/irq.h>
+#include <asm/mach-types.h>
 #include <asm/uaccess.h>
 
 #include <video/fbcon.h>
 
 #include "acornfb.h"
 
+/*
+ * VIDC machines can't do 16 or 32BPP modes.
+ */
+#ifdef HAS_VIDC
+#undef FBCON_HAS_CFB16
+#undef FBCON_HAS_CFB32
+#endif
+
 /*
  * Default resolution.
  * NOTE that it has to be supported in the table towards
@@ -117,37 +126,50 @@ extern unsigned int vram_size;    /* set by setup.c */
  * 25.175  3   25.175
  * 36.000  3   36.000
  */
-static struct pixclock {
+struct pixclock {
        u_long  min_clock;
        u_long  max_clock;
        u_int   vidc_ctl;
        u_int   vid_ctl;
-} pixclocks[] = {
+};
+
+static struct pixclock arc_clocks[] = {
        /* we allow +/-1% on these */
        { 123750, 126250, VIDC_CTRL_DIV3,   VID_CTL_24MHz },    /*  8.000MHz */
        {  82500,  84167, VIDC_CTRL_DIV2,   VID_CTL_24MHz },    /* 12.000MHz */
        {  61875,  63125, VIDC_CTRL_DIV1_5, VID_CTL_24MHz },    /* 16.000MHz */
        {  41250,  42083, VIDC_CTRL_DIV1,   VID_CTL_24MHz },    /* 24.000MHz */
+};
+
 #ifdef CONFIG_ARCH_A5K
+static struct pixclock a5k_clocks[] = {
        { 117974, 120357, VIDC_CTRL_DIV3,   VID_CTL_25MHz },    /*  8.392MHz */
        {  78649,  80238, VIDC_CTRL_DIV2,   VID_CTL_25MHz },    /* 12.588MHz */
        {  58987,  60178, VIDC_CTRL_DIV1_5, VID_CTL_25MHz },    /* 16.588MHz */
        {  55000,  56111, VIDC_CTRL_DIV2,   VID_CTL_36MHz },    /* 18.000MHz */
        {  39325,  40119, VIDC_CTRL_DIV1,   VID_CTL_25MHz },    /* 25.175MHz */
        {  27500,  28055, VIDC_CTRL_DIV1,   VID_CTL_36MHz },    /* 36.000MHz */
-#endif
-       { 0, }
 };
+#endif
 
 static struct pixclock *
 acornfb_valid_pixrate(u_long pixclock)
 {
        u_int i;
 
-       for (i = 0; pixclocks[i].min_clock; i++)
-               if (pixclock > pixclocks[i].min_clock &&
-                   pixclock < pixclocks[i].max_clock)
-                       return pixclocks + i;
+       for (i = 0; i < ARRAY_SIZE(arc_clocks); i++)
+               if (pixclock > arc_clocks[i].min_clock &&
+                   pixclock < arc_clocks[i].max_clock)
+                       return arc_clocks + i;
+
+#ifdef CONFIG_ARCH_A5K
+       if (machine_is_a5k()) {
+               for (i = 0; i < ARRAY_SIZE(a5k_clocks); i++)
+                       if (pixclock > a5k_clocks[i].min_clock &&
+                           pixclock < a5k_clocks[i].max_clock)
+                               return a5k_clocks + i;
+       }
+#endif
 
        return NULL;
 }
@@ -215,11 +237,15 @@ acornfb_set_timing(struct fb_var_screeninfo *var)
                break;
        }
 
-       if (!(var->sync & FB_SYNC_HOR_HIGH_ACT))
-               vid_ctl |= VID_CTL_HS_NHSYNC;
+       if (var->sync & FB_SYNC_COMP_HIGH_ACT) /* should be FB_SYNC_COMP */
+               vidc_ctl |= VIDC_CTRL_CSYNC;
+       else {
+               if (!(var->sync & FB_SYNC_HOR_HIGH_ACT))
+                       vid_ctl |= VID_CTL_HS_NHSYNC;
 
-       if (!(var->sync & FB_SYNC_VERT_HIGH_ACT))
-               vid_ctl |= VID_CTL_VS_NVSYNC;
+               if (!(var->sync & FB_SYNC_VERT_HIGH_ACT))
+                       vid_ctl |= VID_CTL_VS_NVSYNC;
+       }
 
        sync_len        = var->hsync_len;
        display_start   = sync_len + var->left_margin;
@@ -262,9 +288,9 @@ acornfb_set_timing(struct fb_var_screeninfo *var)
        vidc.v_display_end      = display_end - 1;
        vidc.v_border_end       = vidc.v_display_end;
 
-#ifdef CONFIG_ARCH_A5K
-       __raw_writeb(vid_ctl, IOEB_VID_CTL);
-#endif
+       if (machine_is_a5k())
+               __raw_writeb(vid_ctl, IOEB_VID_CTL);
+
        if (memcmp(&current_vidc, &vidc, sizeof(vidc))) {
                current_vidc = vidc;
 
@@ -719,30 +745,19 @@ acornfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
        pal = acornfb_palette_encode(regno, red, green, blue, trans);
        current_par.palette[regno] = pal;
 
-#ifdef HAS_VIDC20
-       if (regno < 16) {
-               switch (bpp) {
-#ifdef FBCON_HAS_CFB16
-               case 16:
-                       current_par.cmap.cfb16[regno] =
-                               regno | regno << 5 | regno << 10;
-                       break;
-#endif
 #ifdef FBCON_HAS_CFB32
-               case 32:
-                       current_par.cmap.cfb32[regno] =
+       if (bpp == 32 && regno < 16) {
+               current_par.cmap.cfb32[regno] =
                                regno | regno << 8 | regno << 16;
-                       break;
-#endif
-               default:
-                       break;
-               }
        }
-
+#endif
 #ifdef FBCON_HAS_CFB16
-       if (bpp == 16) {
+       if (bpp == 16 && regno < 16) {
                int i;
 
+               current_par.cmap.cfb16[regno] =
+                               regno | regno << 5 | regno << 10;
+
                pal.p = 0;
                vidc_writel(0x10000000);
                for (i = 0; i < 256; i += 1) {
@@ -753,7 +768,6 @@ acornfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
                        /* Palette register pointer auto-increments */
                }
        } else
-#endif
 #endif
                acornfb_palette_write(regno, pal);
 
@@ -797,52 +811,73 @@ acornfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
 }
 
 static int
-acornfb_decode_var(struct fb_var_screeninfo *var, int con, int *visual)
+acornfb_decode_var(struct fb_var_screeninfo *var, int con)
 {
        int err;
 
+#if defined(HAS_VIDC20)
+       var->red.offset    = 0;
+       var->red.length    = 8;
+       var->green         = var->red;
+       var->blue          = var->red;
+       var->transp.offset = 0;
+       var->transp.length = 4;
+#elif defined(HAS_VIDC)
+       var->red.length    = 4;
+       var->green         = var->red;
+       var->blue          = var->red;
+       var->transp.length = 1;
+#endif
+
        switch (var->bits_per_pixel) {
 #ifdef FBCON_HAS_MFB
        case 1:
-               *visual = FB_VISUAL_MONO10;
                break;
 #endif
-#ifdef FBCON_HAS_CFB8
-       case 8:
-#ifdef HAS_VIDC
-               *visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
-#else
-               *visual = FB_VISUAL_PSEUDOCOLOR;
-#endif
+#ifdef FBCON_HAS_CFB2
+       case 2:
                break;
 #endif
 #ifdef FBCON_HAS_CFB4
        case 4:
-               *visual = FB_VISUAL_PSEUDOCOLOR;
                break;
 #endif
-#ifdef FBCON_HAS_CFB2
-       case 2:
-               *visual = FB_VISUAL_PSEUDOCOLOR;
+#ifdef FBCON_HAS_CFB8
+       case 8:
                break;
 #endif
-#ifdef HAS_VIDC20
 #ifdef FBCON_HAS_CFB16
        case 16:
-               *visual = FB_VISUAL_DIRECTCOLOR;
+               var->red.offset    = 0;
+               var->red.length    = 5;
+               var->green.offset  = 5;
+               var->green.length  = 5;
+               var->blue.offset   = 10;
+               var->blue.length   = 5;
+               var->transp.offset = 15;
+               var->transp.length = 1;
                break;
 #endif
 #ifdef FBCON_HAS_CFB32
        case 32:
-               *visual = FB_VISUAL_TRUECOLOR;
+               var->red.offset    = 0;
+               var->red.length    = 8;
+               var->green.offset  = 8;
+               var->green.length  = 8;
+               var->blue.offset   = 16;
+               var->blue.length   = 8;
+               var->transp.offset = 24;
+               var->transp.length = 4;
                break;
-#endif
 #endif
        default:
                return -EINVAL;
        }
 
-       if (!acornfb_valid_pixrate(var->pixclock))
+       /*
+        * Check to see if the pixel rate is valid.
+        */
+       if (!var->pixclock || !acornfb_valid_pixrate(var->pixclock))
                return -EINVAL;
 
        /*
@@ -857,50 +892,7 @@ acornfb_decode_var(struct fb_var_screeninfo *var, int con, int *visual)
         * Validate the timing against the
         * monitor hardware.
         */
-       err = acornfb_validate_timing(var, &fb_info.monspecs);
-       if (err)
-               return err;
-
-#if defined(HAS_VIDC20)
-       switch (var->bits_per_pixel) {
-       case 1: case 2: case 4: case 8:
-               var->red.offset    = 0;
-               var->red.length    = 8;
-               var->green         = var->red;
-               var->blue          = var->red;
-               var->transp.offset = 0;
-               var->transp.length = 4;
-               break;
-
-       case 16:
-               var->red.offset    = 0;
-               var->red.length    = 5;
-               var->green.offset  = 5;
-               var->green.length  = 5;
-               var->blue.offset   = 10;
-               var->blue.length   = 5;
-               var->transp.offset = 15;
-               var->transp.length = 1;
-               break;
-
-       case 32:
-               var->red.offset    = 0;
-               var->red.length    = 8;
-               var->green.offset  = 8;
-               var->green.length  = 8;
-               var->blue.offset   = 16;
-               var->blue.length   = 8;
-               var->transp.offset = 24;
-               var->transp.length = 4;
-               break;
-       }
-#elif defined(HAS_VIDC)
-       var->red.length    = 4;
-       var->green         = var->red;
-       var->blue          = var->red;
-       var->transp.length = 1;
-#endif
-       return 0;
+       return acornfb_validate_timing(var, &fb_info.monspecs);
 }
 
 static int
@@ -945,14 +937,14 @@ static int
 acornfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
 {
        struct display *display;
-       int err, chgvar = 0, visual;
+       int err, chgvar = 0;
 
        if (con >= 0)
                display = fb_display + con;
        else
                display = &global_disp;
 
-       err = acornfb_decode_var(var, con, &visual);
+       err = acornfb_decode_var(var, con);
        if (err)
                return err;
 
@@ -991,40 +983,37 @@ acornfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
        if (var->activate & FB_ACTIVATE_ALL)
                global_disp.var = display->var;
 
-       display->screen_base    = (char *)current_par.screen_base;
-       display->visual         = visual;
-       display->type           = FB_TYPE_PACKED_PIXELS;
-       display->type_aux       = 0;
-       display->ypanstep       = 1;
-       display->ywrapstep      = 1;
-       display->line_length    =
-       display->next_line      = (var->xres * var->bits_per_pixel) / 8;
-       display->can_soft_blank = visual == FB_VISUAL_PSEUDOCOLOR ? 1 : 0;
-       display->inverse        = 0;
-
        switch (display->var.bits_per_pixel) {
 #ifdef FBCON_HAS_MFB
        case 1:
                current_par.palette_size = 2;
                display->dispsw = &fbcon_mfb;
+               display->visual = FB_VISUAL_MONO10;
                break;
 #endif
 #ifdef FBCON_HAS_CFB2
        case 2:
                current_par.palette_size = 4;
                display->dispsw = &fbcon_cfb2;
+               display->visual = FB_VISUAL_PSEUDOCOLOR;
                break;
 #endif
 #ifdef FBCON_HAS_CFB4
        case 4:
                current_par.palette_size = 16;
                display->dispsw = &fbcon_cfb4;
+               display->visual = FB_VISUAL_PSEUDOCOLOR;
                break;
 #endif
 #ifdef FBCON_HAS_CFB8
        case 8:
                current_par.palette_size = VIDC_PALETTE_SIZE;
                display->dispsw = &fbcon_cfb8;
+#ifdef HAS_VIDC
+               display->visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
+#else
+               display->visual = FB_VISUAL_PSEUDOCOLOR;
+#endif
                break;
 #endif
 #ifdef FBCON_HAS_CFB16
@@ -1032,6 +1021,7 @@ acornfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
                current_par.palette_size = 32;
                display->dispsw = &fbcon_cfb16;
                display->dispsw_data = current_par.cmap.cfb16;
+               display->visual = FB_VISUAL_DIRECTCOLOR;
                break;
 #endif
 #ifdef FBCON_HAS_CFB32
@@ -1039,6 +1029,7 @@ acornfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
                current_par.palette_size = VIDC_PALETTE_SIZE;
                display->dispsw = &fbcon_cfb32;
                display->dispsw_data = current_par.cmap.cfb32;
+               display->visual = FB_VISUAL_TRUECOLOR;
                break;
 #endif
        default:
@@ -1046,6 +1037,16 @@ acornfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
                break;
        }
 
+       display->screen_base    = (char *)current_par.screen_base;
+       display->type           = FB_TYPE_PACKED_PIXELS;
+       display->type_aux       = 0;
+       display->ypanstep       = 1;
+       display->ywrapstep      = 1;
+       display->line_length    =
+       display->next_line      = (var->xres * var->bits_per_pixel) / 8;
+       display->can_soft_blank = display->visual == FB_VISUAL_PSEUDOCOLOR ? 1 : 0;
+       display->inverse        = 0;
+
        if (chgvar && info && info->changevar)
                info->changevar(con);
 
@@ -1205,18 +1206,8 @@ acornfb_blank(int blank, struct fb_info *info)
        union palette p;
        int i, bpp = fb_display[current_par.currcon].var.bits_per_pixel;
 
-       if (bpp != 16) {
-               for (i = 0; i < current_par.palette_size; i++) {
-                       if (blank)
-                               p = acornfb_palette_encode(i, 0, 0, 0, 0);
-                       else
-                               p = current_par.palette[i];
-
-                       acornfb_palette_write(i, p);
-               }
-       }
 #ifdef FBCON_HAS_CFB16
-       else {
+       if (bpp == 16) {
                p.p = 0;
 
                for (i = 0; i < 256; i++) {
@@ -1229,8 +1220,18 @@ acornfb_blank(int blank, struct fb_info *info)
                        }
                        acornfb_palette_write(i, current_par.palette[i]);
                }
-       }
+       } else
 #endif
+       {
+               for (i = 0; i < current_par.palette_size; i++) {
+                       if (blank)
+                               p = acornfb_palette_encode(i, 0, 0, 0, 0);
+                       else
+                               p = current_par.palette[i];
+
+                       acornfb_palette_write(i, p);
+               }
+       }
 }
 
 /*
index 0a868971947b4c2d7586321279affacfffc477f7..4639e86a95aa9eee7b833c08daf48188afb07f88 100644 (file)
@@ -115,6 +115,7 @@ struct modex_params {
 #define VID_CTL_25MHz          (1)
 #define VID_CTL_36MHz          (2)
 
+#define VIDC_CTRL_CSYNC                (1 << 7)
 #define VIDC_CTRL_INTERLACE    (1 << 6)
 #define VIDC_CTRL_FIFO_0_4     (0 << 4)
 #define VIDC_CTRL_FIFO_1_5     (1 << 4)
index 849fc604386d34f2563e05f8ff85a5271f85e8f6..59ce331c8cce2baed7248666390ce187041df6fb 100644 (file)
  */
 /*#define CFB16_IS_CFB15*/
 
-/*
- * This is the offset of the PCI space in physical memory
- */
-#ifdef CONFIG_FOOTBRIDGE
-#define PCI_PHYS_OFFSET        0x80000000
-#else
-#define        PCI_PHYS_OFFSET 0x00000000
-#endif
-
 static char                    *CyberRegs;
 
 #include "cyber2000fb.h"
@@ -1074,18 +1065,18 @@ static void cyber2000fb_blank(int blank, struct fb_info *info)
        case 2: /* vsync off */
                cyber2000_grphw(0x16, 0x04);
                break;  
-       case 1: /* just software blanking of screen */
+       case 1: /* soft blank */
                cyber2000_grphw(0x16, 0x00);
-               for (i = 0; i < 256; i++) {
+               for (i = 0; i < NR_PALETTE; i++) {
                        cyber2000_outb(i, 0x3c8);
                        cyber2000_outb(0, 0x3c9);
                        cyber2000_outb(0, 0x3c9);
                        cyber2000_outb(0, 0x3c9);
                }
                break;
-       default: /* case 0, or anything else: unblank */
+       default: /* unblank */
                cyber2000_grphw(0x16, 0x00);
-               for (i = 0; i < 256; i++) {
+               for (i = 0; i < NR_PALETTE; i++) {
                        cyber2000_outb(i, 0x3c8);
                        cyber2000_outb(cfb->palette[i].red, 0x3c9);
                        cyber2000_outb(cfb->palette[i].green, 0x3c9);
@@ -1323,7 +1314,7 @@ static inline void cyberpro_init_hw(struct cfb_info *cfb, int at_boot)
        cyber2000_outb(0x01, 0x3cf);
 
        /*
-        * MCLK on the NetWinder is fixed at 75MHz
+        * MCLK on the NetWinder and the Shark is fixed at 75MHz
         */
        cfb->mclk_mult = 0xdb;
        cfb->mclk_div  = 0x54;
@@ -1361,7 +1352,7 @@ static inline void cyberpro_init_hw(struct cfb_info *cfb, int at_boot)
 }
 
 static struct cfb_info * __devinit
-cyberpro_alloc_fb_info(struct pci_dev *dev, const struct pci_device_id *id)
+cyberpro_alloc_fb_info(struct pci_dev *dev, const struct pci_device_id *id, char *name)
 {
        struct cfb_info *cfb;
 
@@ -1385,7 +1376,7 @@ cyberpro_alloc_fb_info(struct pci_dev *dev, const struct pci_device_id *id)
        else
                cfb->divisors[3] = 8;
 
-       sprintf(cfb->fb.fix.id, "CyberPro%4X", id->device);
+       strcpy(cfb->fb.fix.id, name);
 
        cfb->fb.fix.type        = FB_TYPE_PACKED_PIXELS;
        cfb->fb.fix.type_aux    = 0;
@@ -1440,14 +1431,9 @@ cyberpro_map_mmio(struct cfb_info *cfb, struct pci_dev *dev)
 
        mmio_base = pci_resource_start(dev, 0) + MMIO_OFFSET;
 
-       cfb->fb.fix.mmio_start = mmio_base + PCI_PHYS_OFFSET;
+       cfb->fb.fix.mmio_start = mmio_base;
        cfb->fb.fix.mmio_len   = MMIO_SIZE;
 
-       if (!request_mem_region(mmio_base, MMIO_SIZE, "memory mapped I/O")) {
-               printk("%s: memory mapped IO in use\n", cfb->fb.fix.id);
-               return -EBUSY;
-       }
-
        CyberRegs = ioremap(mmio_base, MMIO_SIZE);
        if (!CyberRegs) {
                printk("%s: unable to map memory mapped IO\n",
@@ -1465,9 +1451,6 @@ static void __devinit cyberpro_unmap_mmio(struct cfb_info *cfb)
        if (cfb && CyberRegs) {
                iounmap(CyberRegs);
                CyberRegs = NULL;
-
-               release_mem_region(cfb->fb.fix.mmio_start - PCI_PHYS_OFFSET,
-                                  cfb->fb.fix.mmio_len);
        }
 }
 
@@ -1481,15 +1464,9 @@ cyberpro_map_smem(struct cfb_info *cfb, struct pci_dev *dev, u_long smem_len)
 
        smem_base = pci_resource_start(dev, 0);
 
-       cfb->fb.fix.smem_start  = smem_base + PCI_PHYS_OFFSET;
+       cfb->fb.fix.smem_start  = smem_base;
        cfb->fb.fix.smem_len    = smem_len;
 
-       if (!request_mem_region(smem_base, smem_len, "frame buffer")) {
-               printk("%s: frame buffer in use\n",
-                      cfb->fb.fix.id);
-               return -EBUSY;
-       }
-
        cfb->fb.screen_base = ioremap(smem_base, smem_len);
        if (!cfb->fb.screen_base) {
                printk("%s: unable to map screen memory\n",
@@ -1505,9 +1482,6 @@ static void __devinit cyberpro_unmap_smem(struct cfb_info *cfb)
        if (cfb && cfb->fb.screen_base) {
                iounmap(cfb->fb.screen_base);
                cfb->fb.screen_base = NULL;
-
-               release_mem_region(cfb->fb.fix.smem_start - PCI_PHYS_OFFSET,
-                                  cfb->fb.fix.smem_len);
        }
 }
 
@@ -1517,14 +1491,21 @@ cyberpro_probe(struct pci_dev *dev, const struct pci_device_id *id)
        struct cfb_info *cfb;
        u_int h_sync, v_sync;
        u_long smem_size;
+       char name[16];
        int err;
 
+       sprintf(name, "CyberPro%4X", id->device);
+
        err = pci_enable_device(dev);
        if (err)
                return err;
 
+       err = pci_request_regions(dev, name);
+       if (err)
+               return err;
+
        err = -ENOMEM;
-       cfb = cyberpro_alloc_fb_info(dev, id);
+       cfb = cyberpro_alloc_fb_info(dev, id, name);
        if (!cfb)
                goto failed;
 
@@ -1593,6 +1574,9 @@ failed:
        cyberpro_unmap_mmio(cfb);
        cyberpro_free_fb_info(cfb);
 
+release:
+       pci_release_regions(dev);
+
        return err;
 }
 
@@ -1621,6 +1605,8 @@ static void __devexit cyberpro_remove(struct pci_dev *dev)
                pci_set_drvdata(dev, NULL);
                if (cfb == int_cfb_info)
                        int_cfb_info = NULL;
+
+               pci_release_regions(dev);
        }
 }
 
index 7353caac085c65bed1a82f743b7db797c925cfa4..0f7767218b11e77c19704d197d43a308e0dd0ad3 100644 (file)
 /*
- * linux/drivers/video/sa1100fb.c -- StrongARM 1100 LCD Controller Frame Buffer Device
+ *  linux/drivers/video/sa1100fb.c
  *
  *  Copyright (C) 1999 Eric A. Thomas
- *  
+ *   Based on acornfb.c Copyright (C) Russell King.
+ *
  * 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.
+ * License.  See the file COPYING in the main directory of this archive for
+ * more details.
  *
- */
-
-
-/*
- *   Code Status:
+ *             StrongARM 1100 LCD Controller Frame Buffer Driver
+ *
+ * Please direct your questions and comments on this driver to the following
+ * email address:
+ *
+ *     linux-arm-kernel@lists.arm.linux.org.uk
+ *
+ * Clean patches should be sent to the ARM Linux Patch System.  Please see the
+ * following web page for more information:
+ *
+ *     http://www.arm.linux.org.uk/developer/patches/info.shtml
+ *
+ * Thank you.
+ *
+ * Known problems:
+ *  - With the Neponset plugged into an Assabet, LCD powerdown
+ *    doesn't work (LCD stays powered up).  Therefore we shouldn't
+ *    blank the screen.
+ *  - We don't limit the CPU clock rate nor the mode selection
+ *    according to the available SDRAM bandwidth.
+ *
+ *
+ * Code Status:
  * 1999/04/01:
- *     Driver appears to be working for Brutus 320x200x8bpp mode.  Other
- *     resolutions are working, but only the 8bpp mode is supported.
- *     Changes need to be made to the palette encode and decode routines
- *     to support 4 and 16 bpp modes.  
- *     Driver is not designed to be a module.  The FrameBuffer is statically
- *     allocated since dynamic allocation of a 300k buffer cannot be 
- *     guaranteed. 
- * 
+ *     Driver appears to be working for Brutus 320x200x8bpp mode.  Other
+ *       resolutions are working, but only the 8bpp mode is supported.
+ *       Changes need to be made to the palette encode and decode routines
+ *       to support 4 and 16 bpp modes.  
+ *       Driver is not designed to be a module.  The FrameBuffer is statically
+ *       allocated since dynamic allocation of a 300k buffer cannot be 
+ *       guaranteed. 
+ *
  * 1999/06/17:
- *     FrameBuffer memory is now allocated at run-time when the
- *     driver is initialized.    
+ *     - FrameBuffer memory is now allocated at run-time when the
+ *       driver is initialized.    
+ *
+ * 2000/04/10: Nicolas Pitre <nico@cam.org>
+ *     - Big cleanup for dynamic selection of machine type at run time.
+ *
+ * 2000/07/19: Jamey Hicks <jamey@crl.dec.com>
+ *     - Support for Bitsy aka Compaq iPAQ H3600 added.
  *
- * 2000/04/10:
- *     Big cleanup for dynamic selection of machine type at run time.
- *             Nicolas Pitre <nico@cam.org>
- * 
- * 2000/07/19:
- *     Support for Bitsy aka Compaq iPAQ H3600 added.
- *             Jamey Hicks <jamey@crl.dec.com>
- * 
- * 2000/08/07:
- *     Resolved an issue caused by a change made to the Assabet's PLD 
- *     earlier this year which broke the framebuffer driver for newer 
- *     Phase 4 Assabets.  Some other parameters were changed to optimize for
- *     the Sharp display.
- *             Tak-Shing Chan <tchan.rd@idthk.com>
- *             Jeff Sutherland <jsutherland@accelent.com>
- * 
- * 2000/08/09:
- *     XP860 support added
- *             Kunihiko IMAI <imai@vasara.co.jp>
+ * 2000/08/07: Tak-Shing Chan <tchan.rd@idthk.com>
+ *            Jeff Sutherland <jsutherland@accelent.com>
+ *     - Resolved an issue caused by a change made to the Assabet's PLD 
+ *       earlier this year which broke the framebuffer driver for newer 
+ *       Phase 4 Assabets.  Some other parameters were changed to optimize
+ *       for the Sharp display.
  *
- * 2000/08/19:
- *     Allows standard options to be passed on the kernel command line
- *     for most common passive displays.
- *             Mark Huang <mhuang@livetoy.com>
+ * 2000/08/09: Kunihiko IMAI <imai@vasara.co.jp>
+ *     - XP860 support added
+ *
+ * 2000/08/19: Mark Huang <mhuang@livetoy.com>
+ *     - Allows standard options to be passed on the kernel command line
+ *       for most common passive displays.
  *
  * 2000/08/29:
- *     s/save_flags_cli/local_irq_save/
- *      remove unneeded extra save_flags_cli in
- *       sa1100fb_enable_lcd_controller
+ *     - s/save_flags_cli/local_irq_save/
+ *     - remove unneeded extra save_flags_cli in sa1100fb_enable_lcd_controller
+ *
+ * 2000/10/10: Erik Mouw <J.A.K.Mouw@its.tudelft.nl>
+ *     - Updated LART stuff. Fixed some minor bugs.
+ *
+ * 2000/10/30: Murphy Chen <murphy@mail.dialogue.com.tw>
+ *     - Pangolin support added
+ *
+ * 2000/10/31: Roman Jordan <jor@hoeft-wessel.de>
+ *     - Huw Webpanel support added
+ *
+ * 2000/11/23: Eric Peng <ericpeng@coventive.com>
+ *     - Freebird add
+ *
+ * 2001/02/07: Jamey Hicks <jamey.hicks@compaq.com> 
+ *            Cliff Brake <cbrake@accelent.com>
+ *     - Added PM callback
+ *
+ * 2001/05/26: <rmk@arm.linux.org.uk>
+ *     - Fix 16bpp so that (a) we use the right colours rather than some
+ *       totally random colour depending on what was in page 0, and (b)
+ *       we don't de-reference a NULL pointer.
+ *     - remove duplicated implementation of consistent_alloc()
+ *     - convert dma address types to dma_addr_t
+ *     - remove unused 'montype' stuff
+ *     - remove redundant zero inits of init_var after the initial
+ *       memzero.
+ *     - remove allow_modeset (acornfb idea does not belong here)
+ *
+ * 2001/05/28: <rmk@arm.linux.org.uk>
+ *     - massive cleanup - move machine dependent data into structures
+ *     - I've left various #warnings in - if you see one, and know
+ *       the hardware concerned, please get in contact with me.
+ *
+ * 2001/05/31: <rmk@arm.linux.org.uk>
+ *     - Fix LCCR1 HSW value, fix all machine type specifications to
+ *       keep values in line.  (Please check your machine type specs)
+ *
+ * 2001/06/10: <rmk@arm.linux.org.uk>
+ *     - Fiddle with the LCD controller from task context only; mainly
+ *       so that we can run with interrupts on, and sleep.
+ *     - Convert #warnings into #errors.  No pain, no gain. ;)
+ *
+ * 2001/06/14: <rmk@arm.linux.org.uk>
+ *     - Make the palette BPS value for 12bpp come out correctly.
+ *     - Take notice of "greyscale" on any colour depth.
+ *     - Make truecolor visuals use the RGB channel encoding information.
+ *
+ * 2001/07/02: <rmk@arm.linux.org.uk>
+ *     - Fix colourmap problems.
+ *
+ * 2001/07/13: <abraham@2d3d.co.za>
+ *     - Added support for the ICP LCD-Kit01 on LART. This LCD is
+ *       manufactured by Prime View, model no V16C6448AB
+ *
+ * 2001/07/23: <rmk@arm.linux.org.uk>
+ *     - Hand merge version from handhelds.org CVS tree.  See patch
+ *       notes for 595/1 for more information.
+ *     - Drop 12bpp (it's 16bpp with different colour register mappings).
+ *     - This hardware can not do direct colour.  Therefore we don't
+ *       support it.
+ *
+ * 2001/07/27: <rmk@arm.linux.org.uk>
+ *     - Halve YRES on dual scan LCDs.
  */
 
 #include <linux/config.h>
 #include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/string.h>
-#include <linux/ctype.h>
-#include <linux/mm.h>
-#include <linux/tty.h>
+#include <linux/interrupt.h>
 #include <linux/slab.h>
-#include <linux/init.h>
 #include <linux/fb.h>
 #include <linux/delay.h>
-#include <linux/wrapper.h>
+#include <linux/pm.h>
+#include <linux/init.h>
+#include <linux/cpufreq.h>
 
 #include <asm/hardware.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/mach-types.h>
 #include <asm/uaccess.h>
-#include <asm/proc/pgtable.h>
 
 #include <video/fbcon.h>
 #include <video/fbcon-mfb.h>
 #include <video/fbcon-cfb8.h>
 #include <video/fbcon-cfb16.h>
 
+/*
+ * enable this if your panel appears to have broken
+ */
+#undef CHECK_COMPAT
 
 /*
- *  Debug macros 
+ * debugging?
+ */
+#define DEBUG 0
+/*
+ * Complain if VAR is out of range.
  */
-//#define DEBUG 
-#ifdef DEBUG
-#  define DPRINTK(fmt, args...)        printk("%s: " fmt, __FUNCTION__ , ## args)
+#define DEBUG_VAR 1
+
+#undef ASSABET_PAL_VIDEO
+
+#include "sa1100fb.h"
+
+void (*sa1100fb_blank_helper)(int blank);
+EXPORT_SYMBOL(sa1100fb_blank_helper);
+
+
+#ifdef CHECK_COMPAT
+static void
+sa1100fb_check_shadow(struct sa1100fb_lcd_reg *new_regs,
+                          struct fb_var_screeninfo *var, u_int pcd)
+{
+       struct sa1100fb_lcd_reg shadow;
+       int different = 0;
+
+       /*
+        * These machines are good machines!
+        */
+       if (machine_is_assabet() || machine_is_bitsy())
+               return;
+
+       /*
+        * The following ones are bad, bad, bad.
+        * Please make yours good!
+        */
+       if (machine_is_pangolin()) {
+               DPRINTK("Configuring Pangolin LCD\n");
+               shadow.lccr0 =
+                   LCCR0_LEN + LCCR0_Color + LCCR0_LDM +
+                   LCCR0_BAM + LCCR0_ERM + LCCR0_Act +
+                   LCCR0_LtlEnd + LCCR0_DMADel(0);
+               shadow.lccr1 =
+                   LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(64) +
+                   LCCR1_BegLnDel(160) + LCCR1_EndLnDel(24);
+               shadow.lccr2 =
+                   LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(7) +
+                   LCCR2_BegFrmDel(7) + LCCR2_EndFrmDel(1);
+               shadow.lccr3 =
+                   LCCR3_PixClkDiv(pcd) + LCCR3_HorSnchH +
+                   LCCR3_VrtSnchH + LCCR3_PixFlEdg + LCCR3_OutEnH;
+
+               DPRINTK("pcd = %x, PixCldDiv(pcd)=%x\n",
+                       pcd, LCCR3_PixClkDiv(pcd));
+       }
+       if (machine_is_freebird()) {
+               DPRINTK("Configuring  Freebird LCD\n");
+#if 1
+               shadow.lccr0 = 0x00000038;
+               shadow.lccr1 = 0x010108e0;
+               shadow.lccr2 = 0x0000053f;
+               shadow.lccr3 = 0x00000c20;
 #else
-#  define DPRINTK(fmt, args...)
+               shadow.lccr0 =
+                   LCCR0_LEN + LCCR0_Color + LCCR0_Sngl +
+                   LCCR0_LDM + LCCR0_BAM + LCCR0_ERM + LCCR0_Pas +
+                   LCCR0_LtlEnd + LCCR0_DMADel(0);
+               /* Check ,Chester */
+               shadow.lccr1 =
+                   LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(5) +
+                   LCCR1_BegLnDel(61) + LCCR1_EndLnDel(9);
+               /* Check ,Chester */
+               shadow.lccr2 =
+                   LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(1) +
+                   LCCR2_BegFrmDel(3) + LCCR2_EndFrmDel(0);
+               /* Check ,Chester */
+               shadow.lccr3 =
+                   LCCR3_OutEnH + LCCR3_PixFlEdg + LCCR3_VrtSnchH +
+                   LCCR3_HorSnchH + LCCR3_ACBsCntOff +
+                   LCCR3_ACBsDiv(2) + LCCR3_PixClkDiv(pcd);
 #endif
+       }
+       if (machine_is_brutus()) {
+               DPRINTK("Configuring  Brutus LCD\n");
+               shadow.lccr0 =
+                   LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + LCCR0_Pas +
+                   LCCR0_LtlEnd + LCCR0_LDM + LCCR0_BAM + LCCR0_ERM +
+                   LCCR0_DMADel(0);
+               shadow.lccr1 =
+                   LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(3) +
+                   LCCR1_BegLnDel(41) + LCCR1_EndLnDel(101);
+               shadow.lccr2 =
+                   LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(1) +
+                   LCCR2_BegFrmDel(0) + LCCR2_EndFrmDel(0);
+               shadow.lccr3 =
+                   LCCR3_OutEnH + LCCR3_PixRsEdg + LCCR3_VrtSnchH +
+                   LCCR3_HorSnchH + LCCR3_ACBsCntOff +
+                   LCCR3_ACBsDiv(2) + LCCR3_PixClkDiv(44);
+       }
+       if (machine_is_huw_webpanel()) {
+               DPRINTK("Configuring  HuW LCD\n");
+               shadow.lccr0 = LCCR0_LEN + LCCR0_Dual + LCCR0_LDM;
+               shadow.lccr1 = LCCR1_DisWdth(var->xres) +
+                   LCCR1_HorSnchWdth(3) +
+                   LCCR1_BegLnDel(41) + LCCR1_EndLnDel(101);
+               shadow.lccr2 = 239 + LCCR2_VrtSnchWdth(1);
+               shadow.lccr3 = 8 + LCCR3_OutEnH +
+                   LCCR3_PixRsEdg + LCCR3_VrtSnchH +
+                   LCCR3_HorSnchH + LCCR3_ACBsCntOff + LCCR3_ACBsDiv(2);
+       }
+#ifdef CONFIG_SA1100_CERF
+       if (machine_is_cerf()) {
+               DPRINTK("Configuring Cerf LCD\n");
+#if defined (CONFIG_CERF_LCD_72_A)
+               shadow.lccr0 =
+                   LCCR0_LEN + LCCR0_Color + LCCR0_Dual +
+                   LCCR0_LDM + LCCR0_BAM + LCCR0_ERM + LCCR0_Pas +
+                   LCCR0_LtlEnd + LCCR0_DMADel(0);
+               shadow.lccr1 =
+                   LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(5) +
+                   LCCR1_BegLnDel(61) + LCCR1_EndLnDel(9);
+               shadow.lccr2 =
+                   LCCR2_DisHght(var->yres / 2) + LCCR2_VrtSnchWdth(1) +
+                   LCCR2_BegFrmDel(3) + LCCR2_EndFrmDel(0);
+               shadow.lccr3 =
+                   LCCR3_OutEnH + LCCR3_PixRsEdg + LCCR3_VrtSnchH +
+                   LCCR3_HorSnchH + LCCR3_ACBsCntOff +
+                   LCCR3_ACBsDiv(2) + LCCR3_PixClkDiv(38);
+#elif defined (CONFIG_CERF_LCD_57_A)
+               shadow.lccr0 =
+                   LCCR0_LEN + LCCR0_Color + LCCR0_Sngl +
+                   LCCR0_LDM + LCCR0_BAM + LCCR0_ERM + LCCR0_Pas +
+                   LCCR0_LtlEnd + LCCR0_DMADel(0);
+               shadow.lccr1 =
+                   LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(5) +
+                   LCCR1_BegLnDel(61) + LCCR1_EndLnDel(9);
+               shadow.lccr2 =
+                   LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(1) +
+                   LCCR2_BegFrmDel(3) + LCCR2_EndFrmDel(0);
+               shadow.lccr3 =
+                   LCCR3_OutEnH + LCCR3_PixRsEdg + LCCR3_VrtSnchH +
+                   LCCR3_HorSnchH + LCCR3_ACBsCntOff +
+                   LCCR3_ACBsDiv(2) + LCCR3_PixClkDiv(38);
+#elif defined (CONFIG_CERF_LCD_38_A)
+               shadow.lccr0 =
+                   LCCR0_LEN + LCCR0_Color + LCCR0_Sngl +
+                   LCCR0_LDM + LCCR0_BAM + LCCR0_ERM + LCCR0_Pas +
+                   LCCR0_LtlEnd + LCCR0_DMADel(0);
+               shadow.lccr1 =
+                   LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(5) +
+                   LCCR1_BegLnDel(61) + LCCR1_EndLnDel(9);
+               shadow.lccr2 =
+                   LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(1) +
+                   LCCR2_BegFrmDel(3) + LCCR2_EndFrmDel(0);
+               shadow.lccr3 =
+                   LCCR3_OutEnH + LCCR3_PixRsEdg + LCCR3_VrtSnchH +
+                   LCCR3_HorSnchH + LCCR3_ACBsCntOff +
+                   LCCR3_ACBsDiv(2) + LCCR3_PixClkDiv(38);
+#else
+#error "Must have a CerfBoard LCD form factor selected"
+#endif
+       }
+#endif
+       if (machine_is_lart()) {
+               DPRINTK("Configuring LART LCD\n");
+#if defined LART_GREY_LCD
+               shadow.lccr0 =
+                   LCCR0_LEN + LCCR0_Mono + LCCR0_Sngl + LCCR0_Pas +
+                   LCCR0_LtlEnd + LCCR0_LDM + LCCR0_BAM + LCCR0_ERM +
+                   LCCR0_DMADel(0);
+               shadow.lccr1 =
+                   LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(1) +
+                   LCCR1_BegLnDel(4) + LCCR1_EndLnDel(2);
+               shadow.lccr2 =
+                   LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(1) +
+                   LCCR2_BegFrmDel(0) + LCCR2_EndFrmDel(0);
+               shadow.lccr3 =
+                   LCCR3_PixClkDiv(34) + LCCR3_ACBsDiv(512) +
+                   LCCR3_ACBsCntOff + LCCR3_HorSnchH + LCCR3_VrtSnchH;
+#endif
+#if defined LART_COLOR_LCD
+               shadow.lccr0 =
+                   LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + LCCR0_Act +
+                   LCCR0_LtlEnd + LCCR0_LDM + LCCR0_BAM + LCCR0_ERM +
+                   LCCR0_DMADel(0);
+               shadow.lccr1 =
+                   LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(2) +
+                   LCCR1_BegLnDel(69) + LCCR1_EndLnDel(8);
+               shadow.lccr2 =
+                   LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(3) +
+                   LCCR2_BegFrmDel(14) + LCCR2_EndFrmDel(4);
+               shadow.lccr3 =
+                   LCCR3_PixClkDiv(34) + LCCR3_ACBsDiv(512) +
+                   LCCR3_ACBsCntOff + LCCR3_HorSnchL + LCCR3_VrtSnchL +
+                   LCCR3_PixFlEdg;
+#endif
+#if defined LART_VIDEO_OUT
+               shadow.lccr0 =
+                   LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + LCCR0_Act +
+                   LCCR0_LtlEnd + LCCR0_LDM + LCCR0_BAM + LCCR0_ERM +
+                   LCCR0_DMADel(0);
+               shadow.lccr1 =
+                   LCCR1_DisWdth(640) + LCCR1_HorSnchWdth(95) +
+                   LCCR1_BegLnDel(40) + LCCR1_EndLnDel(24);
+               shadow.lccr2 =
+                   LCCR2_DisHght(480) + LCCR2_VrtSnchWdth(2) +
+                   LCCR2_BegFrmDel(32) + LCCR2_EndFrmDel(11);
+               shadow.lccr3 =
+                   LCCR3_PixClkDiv(8) + LCCR3_ACBsDiv(512) +
+                   LCCR3_ACBsCntOff + LCCR3_HorSnchH + LCCR3_VrtSnchH +
+                   LCCR3_PixFlEdg + LCCR3_OutEnL;
+#endif
+       }
+       if (machine_is_graphicsclient()) {
+               DPRINTK("Configuring GraphicsClient LCD\n");
+               shadow.lccr0 =
+                   LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + LCCR0_Act;
+               shadow.lccr1 =
+                   LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(9) +
+                   LCCR1_EndLnDel(54) + LCCR1_BegLnDel(54);
+               shadow.lccr2 =
+                   LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(9) +
+                   LCCR2_EndFrmDel(32) + LCCR2_BegFrmDel(24);
+               shadow.lccr3 =
+                   LCCR3_PixClkDiv(10) + LCCR3_ACBsDiv(2) +
+                   LCCR3_ACBsCntOff + LCCR3_HorSnchL + LCCR3_VrtSnchL;
+       }
+       if (machine_is_omnimeter()) {
+               DPRINTK("Configuring  OMNI LCD\n");
+               shadow.lccr0 = LCCR0_LEN | LCCR0_CMS | LCCR0_DPD;
+               shadow.lccr1 =
+                   LCCR1_BegLnDel(10) + LCCR1_EndLnDel(10) +
+                   LCCR1_HorSnchWdth(1) + LCCR1_DisWdth(var->xres);
+               shadow.lccr2 = LCCR2_DisHght(var->yres);
+               shadow.lccr3 =
+                   LCCR3_ACBsDiv(0xFF) + LCCR3_PixClkDiv(44);
+//jca (GetPCD(25) << LCD3_V_PCD);
+       }
+       if (machine_is_xp860()) {
+               DPRINTK("Configuring XP860 LCD\n");
+               shadow.lccr0 =
+                   LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + LCCR0_Act +
+                   LCCR0_LtlEnd + LCCR0_LDM + LCCR0_ERM + LCCR0_DMADel(0);
+               shadow.lccr1 =
+                   LCCR1_DisWdth(var->xres) +
+                   LCCR1_HorSnchWdth(var->hsync_len) +
+                   LCCR1_BegLnDel(var->left_margin) +
+                   LCCR1_EndLnDel(var->right_margin);
+               shadow.lccr2 =
+                   LCCR2_DisHght(var->yres) +
+                   LCCR2_VrtSnchWdth(var->vsync_len) +
+                   LCCR2_BegFrmDel(var->upper_margin) +
+                   LCCR2_EndFrmDel(var->lower_margin);
+               shadow.lccr3 =
+                   LCCR3_PixClkDiv(6) + LCCR3_HorSnchL + LCCR3_VrtSnchL;
+       }
 
+       /*
+        * Ok, since we're calculating these values, we want to know
+        * if the calculation is correct.  If you see any of these
+        * messages _PLEASE_ report the incident to me for diagnosis,
+        * including details about what was happening when the
+        * messages appeared. --rmk, 30 March 2001
+        */
+       if (shadow.lccr0 != new_regs->lccr0) {
+               printk(KERN_ERR "LCCR1 mismatch: 0x%08x != 0x%08x\n",
+                       shadow.lccr1, new_regs->lccr1);
+               different = 1;
+       }
+       if (shadow.lccr1 != new_regs->lccr1) {
+               printk(KERN_ERR "LCCR1 mismatch: 0x%08x != 0x%08x\n",
+                       shadow.lccr1, new_regs->lccr1);
+               different = 1;
+       }
+       if (shadow.lccr2 != new_regs->lccr2) {
+               printk(KERN_ERR "LCCR2 mismatch: 0x%08x != 0x%08x\n",
+                       shadow.lccr2, new_regs->lccr2);
+               different = 1;
+       }
+       if (shadow.lccr3 != new_regs->lccr3) {
+               printk(KERN_ERR "LCCR3 mismatch: 0x%08x != 0x%08x\n",
+                       shadow.lccr3, new_regs->lccr3);
+               different = 1;
+       }
+       if (different) {
+               printk(KERN_ERR "var: xres=%d hslen=%d lm=%d rm=%d\n",
+                       var->xres, var->hsync_len,
+                       var->left_margin, var->right_margin);
+               printk(KERN_ERR "var: yres=%d vslen=%d um=%d bm=%d\n",
+                       var->yres, var->vsync_len,
+                       var->upper_margin, var->lower_margin);
+
+               printk(KERN_ERR "Please report this to Russell King "
+                       "<rmk@arm.linux.org.uk>\n");
+       }
 
-/* Memory size macros for determining required FrameBuffer size */
-#define MAX_PALETTE_NUM_ENTRIES                256
-#define MAX_PALETTE_MEM_SIZE           (MAX_PALETTE_NUM_ENTRIES * 2)
-#define MAX_PIXEL_MEM_SIZE \
-       ((current_par.max_xres * current_par.max_yres * current_par.max_bpp)/8)
-#define MAX_FRAMEBUFFER_MEM_SIZE \
-       (MAX_PIXEL_MEM_SIZE + MAX_PALETTE_MEM_SIZE + 32)
-#define ALLOCATED_FB_MEM_SIZE \
-       (PAGE_ALIGN(MAX_FRAMEBUFFER_MEM_SIZE + PAGE_SIZE * 2))
+       DPRINTK("olccr0 = 0x%08x\n", shadow.lccr0);
+       DPRINTK("olccr1 = 0x%08x\n", shadow.lccr1);
+       DPRINTK("olccr2 = 0x%08x\n", shadow.lccr2);
+       DPRINTK("olccr3 = 0x%08x\n", shadow.lccr3);
+}
+#else
+#define sa1100fb_check_shadow(regs,var,pcd)
+#endif
 
-#define SA1100_PALETTE_MEM_SIZE(bpp)   (((bpp)==8?256:16)*2)
-#define SA1100_PALETTE_MODE_VAL(bpp)    (((bpp) & 0x018) << 9)
 
-/* Minimum X and Y resolutions */
-#define MIN_XRES       64
-#define MIN_YRES       64
 
-/* Possible controller_state modes */
-#define LCD_MODE_DISABLED              0    // Controller is disabled and Disable Done received
-#define LCD_MODE_DISABLE_BEFORE_ENABLE 1    // Re-enable after Disable Done IRQ is received
-#define LCD_MODE_ENABLED               2    // Controller is enabled
+/*
+ * IMHO this looks wrong.  In 8BPP, length should be 8.
+ */
+static struct sa1100fb_rgb rgb_8 = {
+       red:    { offset: 0,  length: 4, },
+       green:  { offset: 0,  length: 4, },
+       blue:   { offset: 0,  length: 4, },
+       transp: { offset: 0,  length: 0, },
+};
 
-#define SA1100_NAME    "SA1100"
-#define NR_MONTYPES    1
+static struct sa1100fb_rgb def_rgb_16 = {
+       red:    { offset: 11, length: 5, },
+       green:  { offset: 5,  length: 6, },
+       blue:   { offset: 0,  length: 5, },
+       transp: { offset: 0,  length: 0, },
+};
 
-static inline void
-sa1100fb_assabet_set_truecolor(u_int is_true_color)
-{
 #ifdef CONFIG_SA1100_ASSABET
-#if 1
-       // phase 4 or newer Assabet's
-        if (is_true_color)
-               BCR_set(BCR_LCD_12RGB);
-       else
-               BCR_clear(BCR_LCD_12RGB);
+static struct sa1100fb_mach_info assabet_info __initdata = {
+#ifdef ASSABET_PAL_VIDEO
+       pixclock:       67797,          bpp:            16,
+       xres:           640,            yres:           512,
+
+       hsync_len:      64,             vsync_len:      6,
+       left_margin:    125,            upper_margin:   70,
+       right_margin:   115,            lower_margin:   36,
+
+       sync:           0,
+
+       lccr0:          LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
+       lccr3:          LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(512),
 #else
-       // older Assabet's
-        if (is_true_color)
-               BCR_clear(BCR_LCD_12RGB);
-       else
-               BCR_set(BCR_LCD_12RGB);
+       pixclock:       171521,         bpp:            16,
+       xres:           320,            yres:           240,
+
+       hsync_len:      5,              vsync_len:      1,
+       left_margin:    61,             upper_margin:   3,
+       right_margin:   9,              lower_margin:   0,
+
+       sync:           FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+
+       lccr0:          LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
+       lccr3:          LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
 #endif
+};
 #endif
-}
 
-static u_char *VideoMemRegion;
-static u_char *VideoMemRegion_phys;
-
-/* Local LCD controller parameters */
-/* These can be reduced by making better use of fb_var_screeninfo parameters.  */
-/* Several duplicates exist in the two structures. */
-struct sa1100fb_par {
-       u_char          *p_screen_base;
-       u_char          *v_screen_base;
-       u_short         *p_palette_base;
-       u_short         *v_palette_base;
-       unsigned long   screen_size;
-       unsigned int    palette_size;
-       unsigned int    max_xres;
-       unsigned int    max_yres;
-       unsigned int    xres;
-       unsigned int    yres;
-       unsigned int    xres_virtual;
-       unsigned int    yres_virtual;
-       unsigned int    max_bpp;
-       unsigned int    bits_per_pixel;
-         signed int    montype;
-       unsigned int    currcon;
-       unsigned int    visual;
-       unsigned int    allow_modeset : 1;
-       unsigned int    active_lcd : 1;
-       unsigned int    inv_4bpp : 1;
-       volatile u_char controller_state;
+#ifdef CONFIG_SA1100_BITSY
+static struct sa1100fb_mach_info bitsy_info __initdata = {
+#ifdef CONFIG_IPAQ_H3100
+       pixclock:       0,              bpp:            4,
+       xres:           320,            yres:           240,
+
+       hsync_len:      26,             vsync_len:      41,
+       left_margin:    4,              upper_margin:   0,
+       right_margin:   4,              lower_margin:   0,
+
+       sync:           FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+       cmap_greyscale: 1,              cmap_static:    1,
+       cmap_inverse:   1,
+
+       lccr0:          LCCR0_Mono | LCCR0_4PixMono | LCCR0_Sngl | LCCR0_Pas,
+       lccr3:          LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
+#error FIXME
+       /*
+        * Sorry, this should have read:
+        * FIXME: please get rid of the PCD and PixClkDiv definitions
+        * in favour of pixclock. --rmk
+        */
+#else
+       pixclock:       5722222,        bpp:            16,
+       xres:           320,            yres:           240,
+
+       hsync_len:      3,              vsync_len:      3,
+       left_margin:    12,             upper_margin:   10,
+       right_margin:   17,             lower_margin:   1,
+
+       sync:           0,
+
+       lccr0:          LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
+       lccr3:          LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
+#endif
 };
 
-/* Shadows for LCD controller registers */
-struct sa1100fb_lcd_reg {
-       Address dbar1;
-       Address dbar2;
-       Word    lccr0;
-       Word    lccr1;
-       Word    lccr2;
-       Word    lccr3;
+static struct sa1100fb_rgb bitsy_rgb_16 = {
+       red:    { offset: 12, length: 4, },
+       green:  { offset: 7,  length: 4, },
+       blue:   { offset: 1,  length: 4, },
+       transp: { offset: 0,  length: 0, },
 };
+#endif
 
-/* Fake monspecs to fill in fbinfo structure */
-static struct fb_monspecs monspecs __initdata = {
-        30000, 70000, 50, 65, 0        /* Generic */
+#ifdef CONFIG_SA1100_BRUTUS
+static struct sa1100fb_mach_info brutus_info __initdata = {
+       pixclock:       0,              bpp:            8,
+       xres:           320,            yres:           240,
+
+       hsync_len:      3,              vsync_len:      1,
+       left_margin:    41,             upper_margin:   0,
+       right_margin:   101,            lower_margin:   0,
+
+       sync:           FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+
+       lccr0:          LCCR0_Color | LCCR0_Sngl | LCCR0_Pas,
+       lccr3:          LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2) |
+                       LCCR3_PixClkDiv(44),
 };
+#endif
 
-static struct display global_disp;     /* Initial (default) Display Settings */
-static struct fb_info fb_info;
-static struct sa1100fb_par current_par;
-static struct fb_var_screeninfo __initdata init_var = {};
-static struct sa1100fb_lcd_reg lcd_shadow;
-
-
-static int  sa1100fb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info);
-static int  sa1100fb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info);
-static int  sa1100fb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info);
-static int  sa1100fb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info);
-static int  sa1100fb_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info);
-static int  sa1100fb_switch(int con, struct fb_info *info);
-static void sa1100fb_blank(int blank, struct fb_info *info);
-static int  sa1100fb_map_video_memory(void);
-static int  sa1100fb_activate_var(struct fb_var_screeninfo *var);
-static void sa1100fb_enable_lcd_controller(void);
-static void sa1100fb_disable_lcd_controller(void);
+#ifdef CONFIG_SA1100_CERF
+static struct sa1100fb_mach_info cerf_info __initdata = {
+       pixclock:       171521,         bpp:            8,
+#if defined(CONFIG_CERF_LCD_72_A)
+       xres:           640,            yres:           480,
+       lccr0:          LCCR0_Color | LCCR0_Dual | LCCR0_Pas,
+       lccr3:          LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2) |
+                       LCCR3_PixClkDiv(38),
+#elif defined(CONFIG_CERF_LCD_57_A)
+       xres:           320,            yres:           240,
+       lccr0:          LCCR0_Color | LCCR0_Sngl | LCCR0_Pas,
+       lccr3:          LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2) |
+                       LCCR3_PixClkDiv(38),
+#elif defined(CONFIG_CERF_LCD_38_A)
+       xres:           240,            yres:           320,
+       lccr0:          LCCR0_Color | LCCR0_Sngl | LCCR0_Pas,
+       lccr3:          LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2) |
+                       LCCR3_PixClkDiv(38),
+#else
+#error "Must have a CerfBoard LCD form factor selected"
+#endif
+
+       hsync_len:      5,              vsync_len:      1,
+       left_margin:    61,             upper_margin:   3,
+       right_margin:   9,              lower_margin:   0,
+
+       sync:           FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
 
-static struct fb_ops sa1100fb_ops = {
-       owner:          THIS_MODULE,
-       fb_get_fix:     sa1100fb_get_fix,
-       fb_get_var:     sa1100fb_get_var,
-       fb_set_var:     sa1100fb_set_var,
-       fb_get_cmap:    sa1100fb_get_cmap,
-       fb_set_cmap:    sa1100fb_set_cmap,
 };
+#endif
 
+#ifdef CONFIG_SA1100_FREEBIRD
+#warning Please check this carefully
+static struct sa1100fb_mach_info freebird_info __initdata = {
+       pixclock:       171521,         bpp:            16,
+       xres:           240,            yres:           320,
 
-/*
- * sa1100fb_palette_write:
- *    Write palette data to the LCD frame buffer's palette area
- */
-static inline void
-sa1100fb_palette_write(u_int regno, u_short pal)
+       hsync_len:      3,              vsync_len:      2,
+       left_margin:    2,              upper_margin:   0,
+       right_margin:   2,              lower_margin:   0,
+
+       sync:           FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+
+       lccr0:          LCCR0_Color | LCCR0_Sngl | LCCR0_Pas,
+       lccr3:          LCCR3_OutEnH | LCCR3_PixFlEdg | LCCR3_ACBsDiv(2),
+};
+
+static struct sa1100fb_rgb freebird_rgb_16 = {
+       red:    { offset: 8,  length: 4, },
+       green:  { offset: 4,  length: 4, },
+       blue:   { offset: 0,  length: 4, },
+       transp: { offset: 12, length: 4, },
+};
+#endif
+
+#ifdef CONFIG_SA1100_GRAPHICSCLIENT
+static struct sa1100fb_mach_info graphicsclient_info __initdata = {
+       pixclock:       0,              bpp:            8,
+       xres:           640,            yres:           480,
+
+       hsync_len:      9,              vsync_len:      9,
+       left_margin:    54,             upper_margin:   24,
+       right_margin:   54,             lower_margin:   32,
+
+       sync:           0,
+
+       lccr0:          LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
+       lccr3:          LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2) |
+                       LCCR3_PixClkDiv(10),
+};
+#endif
+
+#ifdef CONFIG_SA1100_HUW_WEBPANEL
+static struct sa1100fb_mach_info huw_webpanel_info __initdata = {
+       pixclock:       0,              bpp:            8,
+       xres:           640,            yres:           480,
+
+       hsync_len:      3,              vsync_len:      1,
+       left_margin:    41,             upper_margin:   0,
+       right_margin:   101,            lower_margin:   0,
+
+       sync:           FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+
+       lccr0:          LCCR0_Color | LCCR0_Dual | LCCR0_Pas,
+       lccr3:          LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2) | 8,
+#error FIXME
+       /*
+        * FIXME: please get rid of the '| 8' in preference to an
+        * LCCR3_PixClkDiv() version. --rmk
+        */
+};
+#endif
+
+#ifdef LART_GREY_LCD
+static struct sa1100fb_mach_info lart_grey_info __initdata = {
+       pixclock:       150000,         bpp:            4,
+       xres:           320,            yres:           240,
+
+       hsync_len:      1,              vsync_len:      1,
+       left_margin:    4,              upper_margin:   0,
+       right_margin:   2,              lower_margin:   0,
+
+       cmap_greyscale: 1,
+       sync:           FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+
+       lccr0:          LCCR0_Mono | LCCR0_Sngl | LCCR0_Pas | LCCR0_4PixMono,
+       lccr3:          LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(512),
+};
+#endif
+#ifdef LART_COLOR_LCD
+static struct sa1100fb_mach_info lart_color_info __initdata = {
+       pixclock:       150000,         bpp:            16,
+       xres:           320,            yres:           240,
+
+       hsync_len:      2,              vsync_len:      3,
+       left_margin:    69,             upper_margin:   14,
+       right_margin:   8,              lower_margin:   4,
+
+       sync:           0,
+
+       lccr0:          LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
+       lccr3:          LCCR3_OutEnH | LCCR3_PixFlEdg | LCCR3_ACBsDiv(512),
+};
+#endif
+#ifdef LART_VIDEO_OUT
+static struct sa1100fb_mach_info lart_video_info __initdata = {
+       pixclock:       39721,          bpp:            16,
+       xres:           640,            yres:           480,
+
+       hsync_len:      95,             vsync_len:      2,
+       left_margin:    40,             upper_margin:   32,
+       right_margin:   24,             lower_margin:   11,
+
+       sync:           FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+
+       lccr0:          LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
+       lccr3:          LCCR3_OutEnL | LCCR3_PixFlEdg | LCCR3_ACBsDiv(512),
+};
+#endif
+
+#ifdef LART_KIT01_LCD
+static struct sa1100fb_mach_info lart_kit01_info __initdata =
 {
-       current_par.v_palette_base[regno] = (regno ? pal : pal | 
-                                            SA1100_PALETTE_MODE_VAL(current_par.bits_per_pixel));
-}
+       pixclock:       63291,          bpp:            16,
+       xres:           640,            yres:           480,
+
+       hsync_len:      64,             vsync_len:      3,
+       left_margin:    122,            upper_margin:   45,
+       right_margin:   10,             lower_margin:   10,
+
+       sync:           0,
+
+       lccr0:          LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
+       lccr3:          LCCR3_OutEnH | LCCR3_PixFlEdg
+};
+#endif
+
+#ifdef CONFIG_SA1100_OMNIMETER
+static struct sa1100fb_mach_info omnimeter_info __initdata = {
+       pixclock:       0,              bpp:            4,
+       xres:           480,            yres:           320,
+
+       hsync_len:      1,              vsync_len:      1,
+       left_margin:    10,             upper_margin:   0,
+       right_margin:   10,             lower_margin:   0,
+
+       cmap_greyscale: 1,
+       sync:           FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+
+       lccr0:          LCCR0_Mono | LCCR0_Sngl | LCCR0_Pas | LCCR0_8PixMono,
+       lccr3:          LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(255) |
+                       LCCR3_PixClkDiv(44),
+#error FIXME: fix pixclock, ACBsDiv
+       /*
+        * FIXME: I think ACBsDiv is wrong above - should it be 512 (disabled)?
+        *   - rmk
+        */
+};
+#endif
+
+#ifdef CONFIG_SA1100_PANGOLIN
+static struct sa1100fb_mach_info pangolin_info __initdata = {
+       pixclock:       341521,         bpp:            16,
+       xres:           800,            yres:           600,
+
+       hsync_len:      64,             vsync_len:      7,
+       left_margin:    160,            upper_margin:   7,
+       right_margin:   24,             lower_margin:   1,
+
+       sync:           FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+
+       lccr0:          LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
+       lccr3:          LCCR3_OutEnH | LCCR3_PixFlEdg,
+};
+#endif
+
+#ifdef CONFIG_SA1100_XP860
+static struct sa1100fb_mach_info xp860_info __initdata = {
+       pixclock:       0,              bpp:            8,
+       xres:           1024,           yres:           768,
+
+       hsync_len:      3,              vsync_len:      3,
+       left_margin:    3,              upper_margin:   2,
+       right_margin:   2,              lower_margin:   1,
+
+       sync:           0,
 
+       lccr0:          LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
+       lccr3:          LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_PixClkDiv(6),
+};
+#endif
 
-static inline u_short
-sa1100fb_palette_encode(u_int regno, u_int red, u_int green, u_int blue, u_int trans)
+static struct sa1100fb_mach_info * __init
+sa1100fb_get_machine_info(struct sa1100fb_info *fbi)
 {
-       u_int pal;
+       struct sa1100fb_mach_info *inf = NULL;
 
-       if(current_par.bits_per_pixel == 4){
-               /*
-                * RGB -> luminance is defined to be
-                * Y =  0.299 * R + 0.587 * G + 0.114 * B
-                */
-               pal = (19595 * red + 38470 * green + 7471 * blue) >> 28;
-               if( current_par.inv_4bpp )
-                       pal = 15 - pal;
+       /*
+        *            R        G       B       T
+        * default  {11,5}, { 5,6}, { 0,5}, { 0,0}
+        * bitsy    {12,4}, { 7,4}, { 1,4}, { 0,0}
+        * freebird { 8,4}, { 4,4}, { 0,4}, {12,4}
+        */
+#ifdef CONFIG_SA1100_ASSABET
+       if (machine_is_assabet()) {
+               inf = &assabet_info;
+       }
+#endif
+#ifdef CONFIG_SA1100_BITSY
+       if (machine_is_bitsy()) {
+               inf = &bitsy_info;
+               fbi->rgb[RGB_16] = &bitsy_rgb_16;
+       }
+#endif
+#ifdef CONFIG_SA1100_BRUTUS
+       if (machine_is_brutus()) {
+               inf = &brutus_info;
+       }
+#endif
+#ifdef CONFIG_SA1100_CERF
+       if (machine_is_cerf()) {
+               inf = &cerf_info;
+       }
+#endif
+#ifdef CONFIG_SA1100_FREEBIRD
+       if (machine_is_freebird()) {
+               inf = &freebird_info;
+               fbi->rgb[RGB_16] = &freebird_rgb16;
+       }
+#endif
+#ifdef CONFIG_SA1100_GRAPHICSCLIENT
+       if (machine_is_graphicsclient()) {
+               inf = &graphicsclient_info;
+       }
+#endif
+#ifdef CONFIG_SA1100_HUW_WEBPANEL
+       if (machine_is_huw_webpanel()) {
+               inf = &huw_webpanel_info;
+       }
+#endif
+#ifdef CONFIG_SA1100_LART
+       if (machine_is_lart()) {
+#ifdef LART_GREY_LCD
+               inf = &lart_grey_info;
+#endif
+#ifdef LART_COLOR_LCD
+               inf = &lart_color_info;
+#endif
+#ifdef LART_VIDEO_OUT
+               inf = &lart_video_info;
+#endif
+#ifdef LART_KIT01_LCD
+               inf = &lart_kit01_info;
+#endif
+       }
+#endif
+#ifdef CONFIG_SA1100_OMNIMETER
+       if (machine_is_omnimeter()) {
+               inf = &omnimeter_info;
+       }
+#endif
+#ifdef CONFIG_SA1100_PANGOLIN
+       if (machine_is_pangolin()) {
+               inf = &pangolin_info;
        }
-       else{
-               pal   = ((red   >>  4) & 0xf00);
-               pal  |= ((green >>  8) & 0x0f0);
-               pal  |= ((blue  >> 12) & 0x00f);
+#endif
+#ifdef CONFIG_SA1100_XP860
+       if (machine_is_xp860()) {
+               inf = &xp860_info;
        }
+#endif
+       return inf;
+}
+
+static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct sa1100fb_info *);
+static void set_ctrlr_state(struct sa1100fb_info *fbi, u_int state);
 
-       return pal;
+static inline void sa1100fb_schedule_task(struct sa1100fb_info *fbi, u_int state)
+{
+       unsigned long flags;
+
+       local_irq_save(flags);
+       /*
+        * We need to handle two requests being made at the same time.
+        * There are two important cases:
+        *  1. When we are changing VT (C_REENABLE) while unblanking (C_ENABLE)
+        *     We must perform the unblanking, which will do our REENABLE for us.
+        *  2. When we are blanking, but immediately unblank before we have
+        *     blanked.  We do the "REENABLE" thing here as well, just to be sure.
+        */
+       if (fbi->task_state == C_ENABLE && state == C_REENABLE)
+               state = (u_int) -1;
+       if (fbi->task_state == C_DISABLE && state == C_ENABLE)
+               state = C_REENABLE;
+
+       if (state != (u_int)-1) {
+               fbi->task_state = state;
+               schedule_task(&fbi->task);
+       }
+       local_irq_restore(flags);
 }
-           
-static inline u_short
-sa1100fb_palette_read(u_int regno)
+
+/*
+ * Get the VAR structure pointer for the specified console
+ */
+static inline struct fb_var_screeninfo *get_con_var(struct fb_info *info, int con)
 {
-       return (current_par.v_palette_base[regno] & 0x0FFF);
+       struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
+       return (con == fbi->currcon || con == -1) ? &fbi->fb.var : &fb_display[con].var;
 }
 
+/*
+ * Get the DISPLAY structure pointer for the specified console
+ */
+static inline struct display *get_con_display(struct fb_info *info, int con)
+{
+       struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
+       return (con < 0) ? fbi->fb.disp : &fb_display[con];
+}
 
-static void
-sa1100fb_palette_decode(u_int regno, u_int *red, u_int *green, u_int *blue, u_int *trans)
+/*
+ * Get the CMAP pointer for the specified console
+ */
+static inline struct fb_cmap *get_con_cmap(struct fb_info *info, int con)
+{
+       struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
+       return (con == fbi->currcon || con == -1) ? &fbi->fb.cmap : &fb_display[con].cmap;
+}
+
+static inline u_int
+chan_to_field(u_int chan, struct fb_bitfield *bf)
+{
+       chan &= 0xffff;
+       chan >>= 16 - bf->length;
+       return chan << bf->offset;
+}
+
+/*
+ * Convert bits-per-pixel to a hardware palette PBS value.
+ */
+static inline u_int
+palette_pbs(struct fb_var_screeninfo *var)
+{
+       int ret = 0;
+       switch (var->bits_per_pixel) {
+#ifdef FBCON_HAS_CFB4
+       case 4:  ret = 0 << 12; break;
+#endif
+#ifdef FBCON_HAS_CFB8
+       case 8:  ret = 1 << 12; break;
+#endif
+#ifdef FBCON_HAS_CFB16
+       case 16: ret = 2 << 12; break;
+#endif
+       }
+       return ret;
+}
+
+static int
+sa1100fb_setpalettereg(u_int regno, u_int red, u_int green, u_int blue,
+                      u_int trans, struct fb_info *info)
 {
-       u_short pal;
+       struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
+       u_int val, ret = 1;
 
-       pal = sa1100fb_palette_read(regno);
+       if (regno < fbi->palette_size) {
+               val = ((red >> 4) & 0xf00);
+               val |= ((green >> 8) & 0x0f0);
+               val |= ((blue >> 12) & 0x00f);
 
-       if( current_par.bits_per_pixel == 4){
-               if( current_par.inv_4bpp )
-                       pal = 15 - pal;
-               pal &= 0x000f;
-               pal |= pal << 4;
-               pal |= pal << 8;
-               *blue = *green = *red = pal;
+               if (regno == 0)
+                       val |= palette_pbs(&fbi->fb.var);
+
+               fbi->palette_cpu[regno] = val;
+               ret = 0;
+       }
+       return ret;
+}
+
+static int
+sa1100fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+                  u_int trans, struct fb_info *info)
+{
+       struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
+       struct display *disp = get_con_display(info, fbi->currcon);
+       u_int val;
+       int ret = 1;
+
+       /*
+        * If inverse mode was selected, invert all the colours
+        * rather than the register number.  The register number
+        * is what you poke into the framebuffer to produce the
+        * colour you requested.
+        */
+       if (disp->inverse) {
+               red   = 0xffff - red;
+               green = 0xffff - green;
+               blue  = 0xffff - blue;
        }
-       else{
-               *blue   = (pal & 0x000f) << 12;
-               *green  = (pal & 0x00f0) << 8;
-               *red    = (pal & 0x0f00) << 4;
+
+       /*
+        * If greyscale is true, then we convert the RGB value
+        * to greyscale no mater what visual we are using.
+        */
+       if (fbi->fb.var.grayscale)
+               red = green = blue = (19595 * red + 38470 * green +
+                                       7471 * blue) >> 16;
+
+       switch (fbi->fb.disp->visual) {
+       case FB_VISUAL_TRUECOLOR:
+               /*
+                * 12 or 16-bit True Colour.  We encode the RGB value
+                * according to the RGB bitfield information.
+                */
+               if (regno < 16) {
+                       u16 *pal = fbi->fb.pseudo_palette;
+
+                       val  = chan_to_field(red, &fbi->fb.var.red);
+                       val |= chan_to_field(green, &fbi->fb.var.green);
+                       val |= chan_to_field(blue, &fbi->fb.var.blue);
+
+                       pal[regno] = val;
+                       ret = 0;
+               }
+               break;
+
+       case FB_VISUAL_STATIC_PSEUDOCOLOR:
+       case FB_VISUAL_PSEUDOCOLOR:
+               ret = sa1100fb_setpalettereg(regno, red, green, blue, trans, info);
+               break;
        }
-        *trans  = 0;
+
+       return ret;
 }
 
+/*
+ *  sa1100fb_display_dma_period()
+ *    Calculate the minimum period (in picoseconds) between two DMA
+ *    requests for the LCD controller.
+ */
+static unsigned int
+sa1100fb_display_dma_period(struct fb_var_screeninfo *var)
+{
+       unsigned int mem_bits_per_pixel;
+
+       mem_bits_per_pixel = var->bits_per_pixel;
+       if (mem_bits_per_pixel == 12)
+               mem_bits_per_pixel = 16;
+
+       /*
+        * Period = pixclock * bits_per_byte * bytes_per_transfer
+        *              / memory_bits_per_pixel;
+        */
+       return var->pixclock * 8 * 16 / mem_bits_per_pixel;
+}
+
+/*
+ *  sa1100fb_decode_var():
+ *    Get the video params out of 'var'. If a value doesn't fit, round it up,
+ *    if it's too big, return -EINVAL.
+ *
+ *    Suggestion: Round up in the following order: bits_per_pixel, xres,
+ *    yres, xres_virtual, yres_virtual, xoffset, yoffset, grayscale,
+ *    bitfields, horizontal timing, vertical timing.
+ */
 static int
-sa1100fb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, u_int *trans, struct fb_info *info)
+sa1100fb_validate_var(struct fb_var_screeninfo *var,
+                     struct sa1100fb_info *fbi)
 {
-       if (regno >= current_par.palette_size)
-               return 1;
-       
-       sa1100fb_palette_decode(regno, red, green, blue, trans);
+       int ret = -EINVAL;
+
+       if (var->xres < MIN_XRES)
+               var->xres = MIN_XRES;
+       if (var->yres < MIN_YRES)
+               var->yres = MIN_YRES;
+       if (var->xres > fbi->max_xres)
+               var->xres = fbi->max_xres;
+       if (var->yres > fbi->max_yres)
+               var->yres = fbi->max_yres;
+       var->xres_virtual =
+           var->xres_virtual < var->xres ? var->xres : var->xres_virtual;
+       var->yres_virtual =
+           var->yres_virtual < var->yres ? var->yres : var->yres_virtual;
+
+       DPRINTK("var->bits_per_pixel=%d\n", var->bits_per_pixel);
+       switch (var->bits_per_pixel) {
+#ifdef FBCON_HAS_CFB4
+       case 4:         ret = 0; break;
+#endif
+#ifdef FBCON_HAS_CFB8
+       case 8:         ret = 0; break;
+#endif
+#ifdef FBCON_HAS_CFB16
+       case 16:        ret = 0; break;
+#endif
+       default:
+               break;
+       }
 
-       return 0;
+       printk(KERN_DEBUG "dma period = %d ps, clock = %d kHz",
+               sa1100fb_display_dma_period(var),
+               cpufreq_get(smp_processor_id()));
+
+       return ret;
 }
 
+static inline void sa1100fb_set_truecolor(u_int is_true_color)
+{
+       DPRINTK("true_color = %d\n", is_true_color);
+#ifdef CONFIG_SA1100_ASSABET
+       if (machine_is_assabet()) {
+#if 1
+               // phase 4 or newer Assabet's
+               if (is_true_color)
+                       BCR_set(BCR_LCD_12RGB);
+               else
+                       BCR_clear(BCR_LCD_12RGB);
+#else
+               // older Assabet's
+               if (is_true_color)
+                       BCR_clear(BCR_LCD_12RGB);
+               else
+                       BCR_set(BCR_LCD_12RGB);
+#endif
+       }
+#endif
+}
+
+static void
+sa1100fb_hw_set_var(struct fb_var_screeninfo *var, struct sa1100fb_info *fbi)
+{
+       u_long palette_mem_size;
+
+       fbi->palette_size = var->bits_per_pixel == 8 ? 256 : 16;
+
+       palette_mem_size = fbi->palette_size * sizeof(u16);
+
+       DPRINTK("palette_mem_size = 0x%08lx\n", (u_long) palette_mem_size);
+
+       fbi->palette_cpu = (u16 *)(fbi->map_cpu + PAGE_SIZE - palette_mem_size);
+       fbi->palette_dma = fbi->map_dma + PAGE_SIZE - palette_mem_size;
+
+       fb_set_cmap(&fbi->fb.cmap, 1, sa1100fb_setcolreg, &fbi->fb);
 
+       /* Set board control register to handle new color depth */
+       sa1100fb_set_truecolor(var->bits_per_pixel >= 16);
+
+#ifdef CONFIG_SA1100_OMNIMETER
+#error Do we have to do this here?   We already do it at init time.
+       if (machine_is_omnimeter())
+               SetLCDContrast(DefaultLCDContrast);
+#endif
+
+       sa1100fb_activate_var(var, fbi);
+
+       fbi->palette_cpu[0] = (fbi->palette_cpu[0] &
+                                        0xcfff) | palette_pbs(var);
+
+}
+
+/*
+ * sa1100fb_set_var():
+ *     Set the user defined part of the display for the specified console
+ */
 static int
-sa1100fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int trans, struct fb_info *info)
+sa1100fb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
 {
-       u_short pal;
+       struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
+       struct fb_var_screeninfo *dvar = get_con_var(&fbi->fb, con);
+       struct display *display = get_con_display(&fbi->fb, con);
+       int err, chgvar = 0, rgbidx;
+
+       DPRINTK("set_var\n");
+
+       /*
+        * Decode var contents into a par structure, adjusting any
+        * out of range values.
+        */
+       err = sa1100fb_validate_var(var, fbi);
+       if (err)
+               return err;
 
-       if (regno >= current_par.palette_size)
-               return 1;
+       if (var->activate & FB_ACTIVATE_TEST)
+               return 0;
 
-       pal = sa1100fb_palette_encode(regno, red, green, blue, trans);
+       if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW)
+               return -EINVAL;
 
-       sa1100fb_palette_write(regno, pal);
+       if (dvar->xres != var->xres)
+               chgvar = 1;
+       if (dvar->yres != var->yres)
+               chgvar = 1;
+       if (dvar->xres_virtual != var->xres_virtual)
+               chgvar = 1;
+       if (dvar->yres_virtual != var->yres_virtual)
+               chgvar = 1;
+       if (dvar->bits_per_pixel != var->bits_per_pixel)
+               chgvar = 1;
+       if (con < 0)
+               chgvar = 0;
+
+       switch (var->bits_per_pixel) {
+#ifdef FBCON_HAS_CFB4
+       case 4:
+               if (fbi->cmap_static)
+                       display->visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
+               else
+                       display->visual = FB_VISUAL_PSEUDOCOLOR;
+               display->line_length    = var->xres / 2;
+               display->dispsw         = &fbcon_cfb4;
+               rgbidx                  = RGB_8;
+               break;
+#endif
+#ifdef FBCON_HAS_CFB8
+       case 8:
+               if (fbi->cmap_static)
+                       display->visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
+               else
+                       display->visual = FB_VISUAL_PSEUDOCOLOR;
+               display->line_length    = var->xres;
+               display->dispsw         = &fbcon_cfb8;
+               rgbidx                  = RGB_8;
+               break;
+#endif
+#ifdef FBCON_HAS_CFB16
+       case 16:
+               display->visual         = FB_VISUAL_TRUECOLOR;
+               display->line_length    = var->xres * 2;
+               display->dispsw         = &fbcon_cfb16;
+               display->dispsw_data    = fbi->fb.pseudo_palette;
+               rgbidx                  = RGB_16;
+               break;
+#endif
+       default:
+               rgbidx = 0;
+               display->dispsw = &fbcon_dummy;
+               break;
+       }
+
+       display->screen_base    = fbi->screen_cpu;
+       display->next_line      = display->line_length;
+       display->type           = fbi->fb.fix.type;
+       display->type_aux       = fbi->fb.fix.type_aux;
+       display->ypanstep       = fbi->fb.fix.ypanstep;
+       display->ywrapstep      = fbi->fb.fix.ywrapstep;
+       display->can_soft_blank = 1;
+       display->inverse        = fbi->cmap_inverse;
+
+       *dvar                   = *var;
+       dvar->activate          &= ~FB_ACTIVATE_ALL;
+
+       /*
+        * Copy the RGB parameters for this display
+        * from the machine specific parameters.
+        */
+       dvar->red               = fbi->rgb[rgbidx]->red;
+       dvar->green             = fbi->rgb[rgbidx]->green;
+       dvar->blue              = fbi->rgb[rgbidx]->blue;
+       dvar->transp            = fbi->rgb[rgbidx]->transp;
+
+       DPRINTK("RGBT length = %d:%d:%d:%d\n",
+               dvar->red.length, dvar->green.length, dvar->blue.length,
+               dvar->transp.length);
+
+       DPRINTK("RGBT offset = %d:%d:%d:%d\n",
+               dvar->red.offset, dvar->green.offset, dvar->blue.offset,
+               dvar->transp.offset);
+
+       /*
+        * Update the old var.  The fbcon drivers still use this.
+        * Once they are using fbi->fb.var, this can be dropped.
+        */
+       display->var = *dvar;
+
+       /*
+        * If we are setting all the virtual consoles, also set the
+        * defaults used to create new consoles.
+        */
+       if (var->activate & FB_ACTIVATE_ALL)
+               fbi->fb.disp->var = *dvar;
+
+       /*
+        * If the console has changed and the console has defined
+        * a changevar function, call that function.
+        */
+       if (chgvar && info && fbi->fb.changevar)
+               fbi->fb.changevar(con);
+
+       /* If the current console is selected, activate the new var. */
+       if (con != fbi->currcon)
+               return 0;
+
+       sa1100fb_hw_set_var(dvar, fbi);
 
        return 0;
 }
 
 static int
-sa1100fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
-                struct fb_info *info)
+__do_set_cmap(struct fb_cmap *cmap, int kspc, int con,
+             struct fb_info *info)
 {
+       struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
+       struct fb_cmap *dcmap = get_con_cmap(info, con);
        int err = 0;
 
-        DPRINTK("current_par.visual=%d\n", current_par.visual);
-       if (con == current_par.currcon)
-               err = fb_get_cmap(cmap, kspc, sa1100fb_getcolreg, info);
-       else if (fb_display[con].cmap.len)
-               fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
-       else
-               fb_copy_cmap(fb_default_cmap(current_par.palette_size),
-                            cmap, kspc ? 0 : 2);
+       if (con == -1)
+               con = fbi->currcon;
+
+       /* no colormap allocated? (we always have "this" colour map allocated) */
+       if (con >= 0)
+               err = fb_alloc_cmap(&fb_display[con].cmap, fbi->palette_size, 0);
+
+       if (!err && con == fbi->currcon)
+               err = fb_set_cmap(cmap, kspc, sa1100fb_setcolreg, info);
+
+       if (!err)
+               fb_copy_cmap(cmap, dcmap, kspc ? 0 : 1);
+
        return err;
 }
 
@@ -329,954 +1323,977 @@ static int
 sa1100fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
                  struct fb_info *info)
 {
-       int err = 0;
+       struct display *disp = get_con_display(info, con);
 
-        DPRINTK("current_par.visual=%d\n", current_par.visual);
-       if (!fb_display[con].cmap.len)
-               err = fb_alloc_cmap(&fb_display[con].cmap,
-                                   current_par.palette_size, 0);
-       if (!err) {
-               if (con == current_par.currcon)
-                       err = fb_set_cmap(cmap, kspc, sa1100fb_setcolreg,
-                                         info);
-               fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
-       }
-       return err;
+       if (disp->visual == FB_VISUAL_TRUECOLOR ||
+           disp->visual == FB_VISUAL_STATIC_PSEUDOCOLOR)
+               return -EINVAL;
+
+       return __do_set_cmap(cmap, kspc, con, info);
+}
+
+static int
+sa1100fb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
+{
+       struct display *display = get_con_display(info, con);
+
+       *fix = info->fix;
+
+       fix->line_length = display->line_length;
+       fix->visual      = display->visual;
+       return 0;
 }
 
-static void inline
-sa1100fb_get_par(struct sa1100fb_par *par)
+static int
+sa1100fb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
 {
-       *par = current_par;
+       *var = *get_con_var(info, con);
+       return 0;
 }
 
+static int
+sa1100fb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
+{
+       struct fb_cmap *dcmap = get_con_cmap(info, con);
+       fb_copy_cmap(dcmap, cmap, kspc ? 0 : 2);
+       return 0;
+}
+
+static struct fb_ops sa1100fb_ops = {
+       owner:          THIS_MODULE,
+       fb_get_fix:     sa1100fb_get_fix,
+       fb_get_var:     sa1100fb_get_var,
+       fb_set_var:     sa1100fb_set_var,
+       fb_get_cmap:    sa1100fb_get_cmap,
+       fb_set_cmap:    sa1100fb_set_cmap,
+};
 
 /*
- * sa1100fb_encode_var():
- *     Modify var structure using values in par
+ *  sa1100fb_switch():       
+ *     Change to the specified console.  Palette and video mode
+ *      are changed to the console's stored parameters.
+ *
+ *     Uh oh, this can be called from a tasklet (IRQ)
  */
-static int 
-sa1100fb_encode_var(struct fb_var_screeninfo *var,
-                    struct sa1100fb_par *par)
+static int sa1100fb_switch(int con, struct fb_info *info)
 {
-        // Don't know if really want to zero var on entry.
-        // Look at set_var to see.  If so, may need to add extra params to par     
-//     memset(var, 0, sizeof(struct fb_var_screeninfo));
-       var->xres = par->xres;
-       var->yres = par->yres;
-       var->xres_virtual = par->xres_virtual;
-       var->yres_virtual = par->yres_virtual;
-
-       var->bits_per_pixel = par->bits_per_pixel;
-
-        DPRINTK("var->bits_per_pixel=%d\n", var->bits_per_pixel);
-       switch(var->bits_per_pixel) {
-       case 2:
-       case 4:
-       case 8:
-               var->red.length    = 4;
-               var->green         = var->red;
-               var->blue          = var->red;
-               var->transp.length = 0;
-               break;
-       case 12:          // This case should differ for Active/Passive mode  
-       case 16:
-                if (machine_is_bitsy()) {
-                        var->red.length    = 4;
-                        var->blue.length   = 4;
-                        var->green.length  = 4;
-                        var->transp.length = 0;
-                        var->red.offset    = 12;
-                        var->green.offset  = 7;
-                        var->blue.offset   = 1;
-                        var->transp.offset = 0;
-                } else {
-                        var->red.length    = 5;
-                        var->blue.length   = 5;
-                        var->green.length  = 6;
-                        var->transp.length = 0;
-                        var->red.offset    = 11;
-                        var->green.offset  = 5;
-                        var->blue.offset   = 0;
-                        var->transp.offset = 0;
-                }
-                break;
+       struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
+       struct display *disp;
+       struct fb_cmap *cmap;
+
+       DPRINTK("con=%d info->modename=%s\n", con, fbi->fb.modename);
+
+       if (con == fbi->currcon)
+               return 0;
+
+       if (fbi->currcon >= 0) {
+               disp = fb_display + fbi->currcon;
+
+               /*
+                * Save the old colormap and video mode.
+                */
+               disp->var = fbi->fb.var;
+
+               if (disp->cmap.len)
+                       fb_copy_cmap(&fbi->fb.cmap, &disp->cmap, 0);
        }
+
+       fbi->currcon = con;
+       disp = fb_display + con;
+
+       /*
+        * Make sure that our colourmap contains 256 entries.
+        */
+       fb_alloc_cmap(&fbi->fb.cmap, 256, 0);
+
+       if (disp->cmap.len)
+               cmap = &disp->cmap;
+       else
+               cmap = fb_default_cmap(1 << disp->var.bits_per_pixel);
+
+       fb_copy_cmap(cmap, &fbi->fb.cmap, 0);
+
+       fbi->fb.var = disp->var;
+       fbi->fb.var.activate = FB_ACTIVATE_NOW;
+
+       sa1100fb_set_var(&fbi->fb.var, con, info);
        return 0;
 }
+
 /*
- *  sa1100fb_decode_var():
- *    Get the video params out of 'var'. If a value doesn't fit, round it up,
- *    if it's too big, return -EINVAL.
+ * Formal definition of the VESA spec:
+ *  On
+ *     This refers to the state of the display when it is in full operation
+ *  Stand-By
+ *     This defines an optional operating state of minimal power reduction with
+ *     the shortest recovery time
+ *  Suspend
+ *     This refers to a level of power management in which substantial power
+ *     reduction is achieved by the display.  The display can have a longer 
+ *     recovery time from this state than from the Stand-by state
+ *  Off
+ *     This indicates that the display is consuming the lowest level of power
+ *     and is non-operational. Recovery from this state may optionally require
+ *     the user to manually power on the monitor
  *
- *    Suggestion: Round up in the following order: bits_per_pixel, xres,
- *    yres, xres_virtual, yres_virtual, xoffset, yoffset, grayscale,
- *    bitfields, horizontal timing, vertical timing.
+ *  Now, the fbdev driver adds an additional state, (blank), where they
+ *  turn off the video (maybe by colormap tricks), but don't mess with the
+ *  video itself: think of it semantically between on and Stand-By.
+ *
+ *  So here's what we should do in our fbdev blank routine:
+ *
+ *     VESA_NO_BLANKING (mode 0)       Video on,  front/back light on
+ *     VESA_VSYNC_SUSPEND (mode 1)     Video on,  front/back light off
+ *     VESA_HSYNC_SUSPEND (mode 2)     Video on,  front/back light off
+ *     VESA_POWERDOWN (mode 3)         Video off, front/back light off
+ *
+ *  This will match the matrox implementation.
  */
-static int
-sa1100fb_decode_var(struct fb_var_screeninfo *var, 
-                    struct sa1100fb_par *par)
+/*
+ * sa1100fb_blank():
+ *     Blank the display by setting all palette values to zero.  Note, the 
+ *     12 and 16 bpp modes don't really use the palette, so this will not
+ *      blank the display in all modes.  
+ */
+static void sa1100fb_blank(int blank, struct fb_info *info)
 {
-       u_long palette_mem_phys;
-       u_long palette_mem_size;
+       struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
+       int i;
 
-       *par = current_par;
-
-       if ((par->xres = var->xres) < MIN_XRES)
-               par->xres = MIN_XRES; 
-       if ((par->yres = var->yres) < MIN_YRES)
-               par->yres = MIN_YRES;
-       if (par->xres > current_par.max_xres)
-               par->xres = current_par.max_xres;
-       if (par->yres > current_par.max_yres)
-               par->yres = current_par.max_yres; 
-       par->xres_virtual = 
-               var->xres_virtual < par->xres ? par->xres : var->xres_virtual;
-        par->yres_virtual = 
-               var->yres_virtual < par->yres ? par->yres : var->yres_virtual;
-        par->bits_per_pixel = var->bits_per_pixel;
-
-        DPRINTK("par->bits_per_pixel=%d\n", par->bits_per_pixel);
-       switch (par->bits_per_pixel) {
-#ifdef FBCON_HAS_CFB4
-        case 4:
-               par->visual = FB_VISUAL_PSEUDOCOLOR;
-               par->palette_size = 16; 
-                break;
-#endif
-#ifdef FBCON_HAS_CFB8
-       case 8:
-               par->visual = FB_VISUAL_PSEUDOCOLOR;
-               par->palette_size = 256; 
-               break;
-#endif
-#ifdef FBCON_HAS_CFB16
-       case 16:  /* RGB 565 */
-               par->visual = FB_VISUAL_TRUECOLOR;
-               par->palette_size = 0; 
+       DPRINTK("sa1100fb_blank: blank=%d info->modename=%s\n", blank,
+               fbi->fb.modename);
+
+       switch (blank) {
+       case VESA_POWERDOWN:
+       case VESA_VSYNC_SUSPEND:
+       case VESA_HSYNC_SUSPEND:
+               if (fbi->fb.disp->visual == FB_VISUAL_PSEUDOCOLOR ||
+                   fbi->fb.disp->visual == FB_VISUAL_STATIC_PSEUDOCOLOR)
+                       for (i = 0; i < fbi->palette_size; i++)
+                               sa1100fb_setpalettereg(i, 0, 0, 0, 0, info);
+               sa1100fb_schedule_task(fbi, C_DISABLE);
+               if (sa1100fb_blank_helper)
+                       sa1100fb_blank_helper(blank);
                break;
+
+       case VESA_NO_BLANKING:
+               if (sa1100fb_blank_helper)
+                       sa1100fb_blank_helper(blank);
+               if (fbi->fb.disp->visual == FB_VISUAL_PSEUDOCOLOR ||
+                   fbi->fb.disp->visual == FB_VISUAL_STATIC_PSEUDOCOLOR)
+                       fb_set_cmap(&fbi->fb.cmap, 1, sa1100fb_setcolreg, info);
+               sa1100fb_schedule_task(fbi, C_ENABLE);
+       }
+}
+
+static int sa1100fb_updatevar(int con, struct fb_info *info)
+{
+       DPRINTK("entered\n");
+       return 0;
+}
+
+/*
+ * Calculate the PCD value from the clock rate (in picoseconds).
+ * We take account of the PPCR clock setting.
+ */
+static inline int get_pcd(unsigned int pixclock)
+{
+       unsigned int pcd;
+
+       if (pixclock) {
+               pcd = get_cclk_frequency() * pixclock;
+               pcd /= 10000000;
+               pcd += 1;       /* make up for integer math truncations */
+       } else {
+               /*
+                * People seem to be missing this message.  Make it big.
+                * Make it stand out.  Make sure people see it.
+                */
+               printk(KERN_WARNING "******************************************************\n");
+               printk(KERN_WARNING "**            ZERO PIXEL CLOCK DETECTED             **\n");
+               printk(KERN_WARNING "** You are using a zero pixclock.  This means that  **\n");
+               printk(KERN_WARNING "** clock scaling will not be able to adjust your    **\n");
+               printk(KERN_WARNING "** your timing parameters appropriately, and the    **\n");
+               printk(KERN_WARNING "** bandwidth calculations will fail to work.  This  **\n");
+               printk(KERN_WARNING "** will shortly become an error condition, which    **\n");
+               printk(KERN_WARNING "** will prevent your LCD display working.  Please   **\n");
+               printk(KERN_WARNING "** send your patches in as soon as possible to shut **\n");
+               printk(KERN_WARNING "** this message up.                                 **\n");
+               printk(KERN_WARNING "******************************************************\n");
+               pcd = 0;
+       }
+       return pcd;
+}
+
+/*
+ * sa1100fb_activate_var():
+ *     Configures LCD Controller based on entries in var parameter.  Settings are      
+ *      only written to the controller if changes were made.  
+ */
+static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct sa1100fb_info *fbi)
+{
+       struct sa1100fb_lcd_reg new_regs;
+       u_int half_screen_size, yres, pcd = get_pcd(var->pixclock);
+       u_long flags;
+
+       DPRINTK("Configuring SA1100 LCD\n");
+
+       DPRINTK("var: xres=%d hslen=%d lm=%d rm=%d\n",
+               var->xres, var->hsync_len,
+               var->left_margin, var->right_margin);
+       DPRINTK("var: yres=%d vslen=%d um=%d bm=%d\n",
+               var->yres, var->vsync_len,
+               var->upper_margin, var->lower_margin);
+
+#if DEBUG_VAR
+       if (var->xres < 16        || var->xres > 1024)
+               printk(KERN_ERR "%s: invalid xres %d\n",
+                       fbi->fb.fix.id, var->xres);
+       if (var->hsync_len < 1    || var->hsync_len > 64)
+               printk(KERN_ERR "%s: invalid hsync_len %d\n",
+                       fbi->fb.fix.id, var->hsync_len);
+       if (var->left_margin < 1  || var->left_margin > 255)
+               printk(KERN_ERR "%s: invalid left_margin %d\n",
+                       fbi->fb.fix.id, var->left_margin);
+       if (var->right_margin < 1 || var->right_margin > 255)
+               printk(KERN_ERR "%s: invalid right_margin %d\n",
+                       fbi->fb.fix.id, var->right_margin);
+       if (var->yres < 1         || var->yres > 1024)
+               printk(KERN_ERR "%s: invalid yres %d\n",
+                       fbi->fb.fix.id, var->yres);
+       if (var->vsync_len < 1    || var->vsync_len > 64)
+               printk(KERN_ERR "%s: invalid vsync_len %d\n",
+                       fbi->fb.fix.id, var->vsync_len);
+       if (var->upper_margin < 0 || var->upper_margin > 255)
+               printk(KERN_ERR "%s: invalid upper_margin %d\n",
+                       fbi->fb.fix.id, var->upper_margin);
+       if (var->lower_margin < 0 || var->lower_margin > 255)
+               printk(KERN_ERR "%s: invalid lower_margin %d\n",
+                       fbi->fb.fix.id, var->lower_margin);
 #endif
-       default:
-               return -EINVAL;
-       }
 
-       palette_mem_size = SA1100_PALETTE_MEM_SIZE(par->bits_per_pixel);
-       palette_mem_phys = (u_long)VideoMemRegion_phys + PAGE_SIZE - palette_mem_size;
-       par->p_palette_base = (u_short *)palette_mem_phys;
-        par->v_palette_base = (u_short *)((u_long)VideoMemRegion + PAGE_SIZE - palette_mem_size);
-       par->p_screen_base  = (u_char *)((u_long)VideoMemRegion_phys + PAGE_SIZE); 
-       par->v_screen_base  = (u_char *)((u_long)VideoMemRegion      + PAGE_SIZE); 
-
-       DPRINTK("p_palette_base = 0x%08lx\n",(u_long)par->p_palette_base);
-       DPRINTK("v_palette_base = 0x%08lx\n",(u_long)par->v_palette_base);
-       DPRINTK("palette_size = 0x%08lx\n",(u_long)par->palette_size);
-       DPRINTK("palette_mem_size = 0x%08lx\n",(u_long)palette_mem_size);
-       DPRINTK("p_screen_base  = 0x%08lx\n",(u_long)par->p_screen_base);
-       DPRINTK("v_screen_base  = 0x%08lx\n",(u_long)par->v_screen_base);
-       DPRINTK("VideoMemRegion = 0x%08lx\n",(u_long)VideoMemRegion);
-       DPRINTK("VideoMemRegion_phys = 0x%08lx\n",(u_long)VideoMemRegion_phys);
+       new_regs.lccr0 = fbi->lccr0 |
+               LCCR0_LEN | LCCR0_LDM | LCCR0_BAM |
+               LCCR0_ERM | LCCR0_LtlEnd | LCCR0_DMADel(0);
 
-       return 0;
-}
+       new_regs.lccr1 =
+               LCCR1_DisWdth(var->xres) +
+               LCCR1_HorSnchWdth(var->hsync_len) +
+               LCCR1_BegLnDel(var->left_margin) +
+               LCCR1_EndLnDel(var->right_margin);
 
-static int
-sa1100fb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
-{
-       struct sa1100fb_par par;
+       /*
+        * If we have a dual scan LCD, then we need to halve
+        * the YRES parameter.
+        */
+       yres = var->yres;
+       if (fbi->lccr0 & LCCR0_Dual)
+               yres /= 2;
+
+       new_regs.lccr2 =
+               LCCR2_DisHght(yres) +
+               LCCR2_VrtSnchWdth(var->vsync_len) +
+               LCCR2_BegFrmDel(var->upper_margin) +
+               LCCR2_EndFrmDel(var->lower_margin);
+
+       new_regs.lccr3 = fbi->lccr3 |
+               (var->sync & FB_SYNC_HOR_HIGH_ACT ? LCCR3_HorSnchH : LCCR3_HorSnchL) |
+               (var->sync & FB_SYNC_VERT_HIGH_ACT ? LCCR3_VrtSnchH : LCCR3_VrtSnchL) |
+               LCCR3_ACBsCntOff;
+
+       if (pcd)
+               new_regs.lccr3 |= LCCR3_PixClkDiv(pcd);
+
+       sa1100fb_check_shadow(&new_regs, var, pcd);
+
+       DPRINTK("nlccr0 = 0x%08x\n", new_regs.lccr0);
+       DPRINTK("nlccr1 = 0x%08x\n", new_regs.lccr1);
+       DPRINTK("nlccr2 = 0x%08x\n", new_regs.lccr2);
+       DPRINTK("nlccr3 = 0x%08x\n", new_regs.lccr3);
+
+       half_screen_size = var->bits_per_pixel;
+       half_screen_size = half_screen_size * var->xres * var->yres / 16;
+
+       /* Update shadow copy atomically */
+       local_irq_save(flags);
+       fbi->dbar1 = fbi->palette_dma;
+       fbi->dbar2 = fbi->screen_dma + half_screen_size;
+
+       fbi->reg_lccr0 = new_regs.lccr0;
+       fbi->reg_lccr1 = new_regs.lccr1;
+       fbi->reg_lccr2 = new_regs.lccr2;
+       fbi->reg_lccr3 = new_regs.lccr3;
+       local_irq_restore(flags);
 
-        DPRINTK("con=%d\n", con);
-       if (con == -1) {
-               sa1100fb_get_par(&par);
-               sa1100fb_encode_var(var, &par);
-       } else
-               *var = fb_display[con].var;
+       /*
+        * Only update the registers if the controller is enabled
+        * and something has changed.
+        */
+       if ((LCCR0 != fbi->reg_lccr0)       || (LCCR1 != fbi->reg_lccr1) ||
+           (LCCR2 != fbi->reg_lccr2)       || (LCCR3 != fbi->reg_lccr3) ||
+           (DBAR1 != (Address) fbi->dbar1) || (DBAR2 != (Address) fbi->dbar2))
+               sa1100fb_schedule_task(fbi, C_REENABLE);
 
        return 0;
 }
 
 /*
- * sa1100fb_set_var():
- *     Set the user defined part of the display for the specified console
+ * NOTE!  The following functions are purely helpers for set_ctrlr_state.
+ * Do not call them directly; set_ctrlr_state does the correct serialisation
+ * to ensure that things happen in the right way 100% of time time.
+ *     -- rmk
  */
-static int
-sa1100fb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
+
+/*
+ * FIXME: move LCD power stuff into sa1100fb_power_up_lcd()
+ * Also, I'm expecting that the backlight stuff should
+ * be handled differently.
+ */
+static void sa1100fb_backlight_on(struct sa1100fb_info *fbi)
 {
-       struct display *display;
-       int err, chgvar = 0;
-       struct sa1100fb_par par;
+       DPRINTK("backlight on\n");
 
-       if (con >= 0)
-               display = &fb_display[con]; /* Display settings for console */
-       else
-               display = &global_disp;     /* Default display settings */
+#ifdef CONFIG_SA1100_FREEBIRD
+#error FIXME
+       if (machine_is_freebird()) {
+               BCR_set(BCR_FREEBIRD_LCD_PWR | BCR_FREEBIRD_LCD_DISP);
+       }
+#endif
+#ifdef CONFIG_SA1100_FREEBIRD
+       if (machine_is_freebird()) {
+               /* Turn on backlight ,Chester */
+               BCR_set(BCR_FREEBIRD_LCD_BACKLIGHT);
+       }
+#endif
+#ifdef CONFIG_SA1100_HUW_WEBPANEL
+#error FIXME
+       if (machine_is_huw_webpanel()) {
+               BCR_set(BCR_CCFL_POW + BCR_PWM_BACKLIGHT);
+               set_current_state(TASK_UNINTERRUPTIBLE);
+               schedule_task(200 * HZ / 1000);
+               BCR_set(BCR_TFT_ENA);
+       }
+#endif
+#ifdef CONFIG_SA1100_OMNIMETER
+       if (machine_is_omnimeter())
+               LEDBacklightOn();
+#endif
+#ifdef CONFIG_SA1100_BITSY
+       /* what rmk said --dneuer */
+#endif
+}
 
-       /* Decode var contents into a par structure, adjusting any */
-       /* out of range values. */
-       if ((err = sa1100fb_decode_var(var, &par)))
-               return err;
-       // Store adjusted par values into var structure
-       sa1100fb_encode_var(var, &par);
-       
-       if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_TEST)
-               return 0;
-       else if (((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW) && 
-                ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NXTOPEN))
-               return -EINVAL;
+/*
+ * FIXME: move LCD power stuf into sa1100fb_power_down_lcd()
+ * Also, I'm expecting that the backlight stuff should
+ * be handled differently.
+ */
+static void sa1100fb_backlight_off(struct sa1100fb_info *fbi)
+{
+       DPRINTK("backlight off\n");
 
-       if (con >= 0) {
-               if ((display->var.xres != var->xres) ||
-                   (display->var.yres != var->yres) ||
-                   (display->var.xres_virtual != var->xres_virtual) ||
-                   (display->var.yres_virtual != var->yres_virtual) ||
-                   (display->var.sync != var->sync)                 ||
-                    (display->var.bits_per_pixel != var->bits_per_pixel) ||
-                   (memcmp(&display->var.red, &var->red, sizeof(var->red))) ||
-                   (memcmp(&display->var.green, &var->green, sizeof(var->green))) ||
-                   (memcmp(&display->var.blue, &var->blue, sizeof(var->blue)))) 
-                       chgvar = 1;
+#ifdef CONFIG_SA1100_FREEBIRD
+#error FIXME
+       if (machine_is_freebird()) {
+               BCR_clear(BCR_FREEBIRD_LCD_PWR | BCR_FREEBIRD_LCD_DISP
+                         /*| BCR_FREEBIRD_LCD_BACKLIGHT */ );
        }
+#endif
+#ifdef CONFIG_SA1100_OMNIMETER
+       if (machine_is_omnimeter())
+               LEDBacklightOff();
+#endif
+#ifdef CONFIG_SA1100_BITSY
+       /* what rmk said --dneuer */
+#endif
+}
 
-       display->var = *var;
-       display->screen_base    = par.v_screen_base;
-       display->visual         = par.visual;
-       display->type           = FB_TYPE_PACKED_PIXELS;
-       display->type_aux       = 0;
-       display->ypanstep       = 0;
-       display->ywrapstep      = 0;
-       display->line_length    = 
-       display->next_line      = (var->xres * var->bits_per_pixel) / 8;
-
-       display->can_soft_blank = 1;
-       display->inverse        = 0;
+static void sa1100fb_power_up_lcd(struct sa1100fb_info *fbi)
+{
+       DPRINTK("LCD power on\n");
 
-       switch (display->var.bits_per_pixel) {
-#ifdef FBCON_HAS_CFB4
-        case 4:
-               display->dispsw = &fbcon_cfb4;
-               break;
+#if defined(CONFIG_SA1100_ASSABET) && !defined(ASSABET_PAL_VIDEO)
+       if (machine_is_assabet())
+               BCR_set(BCR_LCD_ON);
 #endif
-#ifdef FBCON_HAS_CFB8
-       case 8: 
-               display->dispsw = &fbcon_cfb8;
-               break;
+#ifdef CONFIG_SA1100_HUW_WEBPANEL
+       if (machine_is_huw_webpanel())
+               BCR_clear(BCR_TFT_NPWR);
 #endif
-#ifdef FBCON_HAS_CFB16
-       case 16:
-               display->dispsw = &fbcon_cfb16;
-               break;
+#ifdef CONFIG_SA1100_OMNIMETER
+       if (machine_is_omnimeter())
+               LCDPowerOn();
 #endif
-       default:
-               display->dispsw = &fbcon_dummy;
-               break;
+#ifdef CONFIG_SA1100_BITSY
+       if (machine_is_bitsy()) {
+               set_bitsy_egpio(EGPIO_BITSY_LCD_ON |
+                               EGPIO_BITSY_LCD_PCI |
+                               EGPIO_BITSY_LCD_5V_ON |
+                               EGPIO_BITSY_LVDD_ON);
        }
+#endif
+}
 
-       /* If the console has changed and the console has defined */
-       /* a changevar function, call that function. */
-       if (chgvar && info && info->changevar)
-               info->changevar(con);
-
-        /* If the current console is selected and it's not truecolor, 
-        *  update the palette 
-        */
-       if ((con == current_par.currcon) &&
-           (current_par.visual != FB_VISUAL_TRUECOLOR)) {
-               struct fb_cmap *cmap;
-               
-               current_par = par;
-               if (display->cmap.len)
-                       cmap = &display->cmap;
-               else
-                       cmap = fb_default_cmap(current_par.palette_size);
+static void sa1100fb_power_down_lcd(struct sa1100fb_info *fbi)
+{
+       DPRINTK("LCD power off\n");
 
-               fb_set_cmap(cmap, 1, sa1100fb_setcolreg, info);
+#if defined(CONFIG_SA1100_ASSABET) && !defined(ASSABET_PAL_VIDEO)
+       if (machine_is_assabet())
+               BCR_clear(BCR_LCD_ON);
+#endif
+#ifdef CONFIG_SA1100_HUW_WEBPANEL
+       // dont forget to set the control lines to zero (?)
+       if (machine_is_huw_webpanel())
+               BCR_set(BCR_TFT_NPWR);
+#endif
+#ifdef CONFIG_SA1100_BITSY
+       if (machine_is_bitsy()) {
+               clr_bitsy_egpio(EGPIO_BITSY_LCD_ON |
+                               EGPIO_BITSY_LCD_PCI |
+                               EGPIO_BITSY_LCD_5V_ON |
+                               EGPIO_BITSY_LVDD_ON);
        }
-
-       /* If the current console is selected, activate the new var. */
-       if (con == current_par.currcon)
-               sa1100fb_activate_var(var);
-       
-       return 0;
+#endif
 }
 
-static int
-sa1100fb_updatevar(int con, struct fb_info *info)
+static void sa1100fb_setup_gpio(struct sa1100fb_info *fbi)
 {
-       DPRINTK("entered\n");
-       return 0;
-}
+       u_int mask = 0;
 
-static int
-sa1100fb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
-{
-       struct display *display;
+       /*
+        * Enable GPIO<9:2> for LCD use if:
+        *  1. Active display, or
+        *  2. Color Dual Passive display
+        *
+        * see table 11.8 on page 11-27 in the SA1100 manual
+        *   -- Erik.
+        *
+        * SA1110 spec update nr. 25 says we can and should
+        * clear LDD15 to 12 for 4 or 8bpp modes with active
+        * panels.  
+        */
+       if ((fbi->reg_lccr0 & LCCR0_CMS) == LCCR0_Color &&
+           (fbi->reg_lccr0 & (LCCR0_Dual|LCCR0_Act)) != 0) {
+               mask = GPIO_LDD11 | GPIO_LDD10 | GPIO_LDD9  | GPIO_LDD8;
 
-       memset(fix, 0, sizeof(struct fb_fix_screeninfo));
-       strcpy(fix->id, SA1100_NAME);
+               if (fbi->fb.var.bits_per_pixel > 8 ||
+                   (fbi->reg_lccr0 & (LCCR0_Dual|LCCR0_Act)) == LCCR0_Dual)
+                       mask |= GPIO_LDD15 | GPIO_LDD14 | GPIO_LDD13 | GPIO_LDD12;
 
-       if (con >= 0)
-       {
-               DPRINTK("Using console specific display for con=%d\n",con);
-               display = &fb_display[con];  /* Display settings for console */
        }
-       else
-               display = &global_disp;      /* Default display settings */
-
-       fix->smem_start  = (unsigned long)current_par.p_screen_base;
-       fix->smem_len    = current_par.screen_size;
-       fix->type        = display->type;
-       fix->type_aux    = display->type_aux;
-       fix->xpanstep    = 0;
-       fix->ypanstep    = display->ypanstep;
-       fix->ywrapstep   = display->ywrapstep;
-       fix->visual      = display->visual;
-       fix->line_length = display->line_length;
-       fix->accel       = FB_ACCEL_NONE;
 
-       return 0;
-}
+#ifdef CONFIG_SA1100_FREEBIRD
+#error Please contact <rmk@arm.linux.org.uk> about this
+       if (machine_is_freebird()) {
+               /* Color single passive */
+               mask |= GPIO_LDD15 | GPIO_LDD14 | GPIO_LDD13 | GPIO_LDD12 |
+                       GPIO_LDD11 | GPIO_LDD10 | GPIO_LDD9  | GPIO_LDD8;
+       }
+#endif
+#ifdef CONFIG_SA1100_CERF
+#error Please contact <rmk@arm.linux.org.uk> about this
+       if (machine_is_cerf()) {
+               /* GPIO15 is used as a bypass for 3.8" displays */
+               mask |= GPIO_GPIO15;
+
+               /* FIXME: why is this? The Cerf's display doesn't seem
+                * to be dual scan or active. I just leave it here,
+                * but in my opinion this is definitively wrong.
+                *  -- Erik <J.A.K.Mouw@its.tudelft.nl>
+                */
 
+               /* REPLY: Umm.. Well to be honest, the 5.7" LCD which
+                * this was used for does not use these pins, but
+                * apparently all hell breaks loose if they are not
+                * set on the Cerf, so we decided to leave them in ;)
+                *  -- Daniel Chemko <dchemko@intrinsyc.com>
+                */
+               /* color {dual/single} passive */
+               mask |= GPIO_LDD15 | GPIO_LDD14 | GPIO_LDD13 | GPIO_LDD12 |
+                       GPIO_LDD11 | GPIO_LDD10 | GPIO_LDD9  | GPIO_LDD8;
+       }
+#endif
 
-static void
-__init sa1100fb_init_fbinfo(void)
+       if (mask) {
+               GPDR |= mask;
+               GAFR |= mask;
+       }
+}
+
+static void sa1100fb_enable_controller(struct sa1100fb_info *fbi)
 {
-       strcpy(fb_info.modename, SA1100_NAME);
-       strcpy(fb_info.fontname, "Acorn8x8");
-
-       fb_info.node            = -1;
-       fb_info.flags           = FBINFO_FLAG_DEFAULT;
-       fb_info.fbops           = &sa1100fb_ops;
-        fb_info.monspecs       = monspecs;
-       fb_info.disp            = &global_disp;
-       fb_info.changevar       = NULL;
-       fb_info.switch_con      = sa1100fb_switch;
-       fb_info.updatevar       = sa1100fb_updatevar;
-       fb_info.blank           = sa1100fb_blank;
+       DPRINTK("Enabling LCD controller\n");
 
        /*
-        * setup initial parameters
+        * Make sure the mode bits are present in the first palette entry
         */
-       memset(&init_var, 0, sizeof(init_var));
-
-       init_var.transp.length  = 0;
-       init_var.nonstd         = 0;
-       init_var.activate       = FB_ACTIVATE_NOW;
-       init_var.xoffset        = 0;
-       init_var.yoffset        = 0;
-       init_var.height         = -1;
-       init_var.width          = -1;
-       init_var.vmode          = FB_VMODE_NONINTERLACED;
-
-       if (machine_is_assabet()) {
-               current_par.max_xres    = 320;
-               current_par.max_yres    = 240;
-               current_par.max_bpp     = 16;
-               init_var.red.length     = 5;                            
-               init_var.green.length   = 6;
-               init_var.blue.length    = 5;
-               init_var.grayscale      = 0;
-               init_var.sync           = 0;
-               init_var.pixclock       = 171521;
-       } else if (machine_is_cerf()) {
-               current_par.max_xres    = 320;
-               current_par.max_yres    = 240;
-               current_par.max_bpp     = 8;
-               init_var.red.length     = 4;                            
-               init_var.green.length   = 4;
-               init_var.blue.length    = 4;
-               init_var.grayscale      = 0;
-               init_var.sync           = 0;
-               init_var.pixclock       = 171521;
-       } else if (machine_is_pangolin()) {
-               current_par.max_xres    = 1024;
-               current_par.max_yres    = 768;
-               current_par.max_bpp     = 16;
-               init_var.red.length     = 5;
-               init_var.green.length   = 6;
-               init_var.blue.length    = 5;
-               init_var.grayscale      = 0;
-               init_var.sync           = 0;    
-               init_var.pixclock       = 15400;
-       } else if (machine_is_bitsy()) {
-               current_par.max_xres    = 320;
-               current_par.max_yres    = 240;
-               current_par.max_bpp     = 16;
-               init_var.red.length     = 4;
-               init_var.green.length   = 4;
-               init_var.blue.length    = 4;
-               init_var.red.offset     = 12;
-               init_var.green.offset   = 7;
-               init_var.blue.offset    = 1;
-               init_var.grayscale      = 0;
-       } else if (machine_is_brutus()) {
-               current_par.max_xres    = 320;
-               current_par.max_yres    = 240;
-               current_par.max_bpp     = 8;
-               init_var.red.length     = 4;                            
-               init_var.green          = init_var.red;
-               init_var.blue           = init_var.red;
-               init_var.sync           = 0;
-       } else if (machine_is_lart()) {
-               current_par.max_xres    = 320;
-               current_par.max_yres    = 240;
-               current_par.max_bpp     = 4;
-               init_var.red.length     = 4;                            
-               init_var.green          = init_var.red;
-               init_var.blue           = init_var.red;
-               init_var.grayscale      = 1;
-               init_var.pixclock       = 150000;       
-               init_var.sync           = 0;
-       } else if (machine_is_graphicsclient()) {
-               current_par.max_xres    = 640;
-               current_par.max_yres    = 480;
-               current_par.max_bpp     = 8;
-               init_var.red.length     = 4;                            
-               init_var.green          = init_var.red;
-               init_var.blue           = init_var.red;
-               init_var.sync           = 0;
-       } else if (machine_is_xp860()) {
-               current_par.max_xres    = 1024;
-               current_par.max_yres    = 768;
-
-               current_par.max_bpp     = 8;
-               init_var.red.length     = 4;
-               init_var.green          = init_var.red;
-               init_var.blue           = init_var.red;
-
-               init_var.hsync_len      = 4;
-               init_var.left_margin    = 3;
-               init_var.right_margin   = 2;
-
-               init_var.vsync_len      = 3;
-               init_var.upper_margin   = 2;
-               init_var.lower_margin   = 1;
-               
+       fbi->palette_cpu[0] &= 0xcfff;
+       fbi->palette_cpu[0] |= palette_pbs(&fbi->fb.var);
+
+       /* Sequence from 11.7.10 */
+       LCCR3 = fbi->reg_lccr3;
+       LCCR2 = fbi->reg_lccr2;
+       LCCR1 = fbi->reg_lccr1;
+       LCCR0 = fbi->reg_lccr0 & ~LCCR0_LEN;
+       DBAR1 = (Address) fbi->dbar1;
+       DBAR2 = (Address) fbi->dbar2;
+       LCCR0 |= LCCR0_LEN;
+
+#ifdef CONFIG_SA1100_GRAPHICSCLIENT
+#error Where is GPIO24 set as an output?  Can we fit this in somewhere else?
+       if (machine_is_graphicsclient()) {
+               // From ADS doc again...same as disable
+               set_current_state(TASK_UNINTERRUPTIBLE);
+               schedule_timeout(20 * HZ / 1000);
+               GPSR |= GPIO_GPIO24;
        }
+#endif
 
-       current_par.p_palette_base      = NULL;
-       current_par.v_palette_base      = NULL;
-       current_par.p_screen_base       = NULL;
-       current_par.v_screen_base       = NULL;
-       current_par.palette_size        = MAX_PALETTE_NUM_ENTRIES;
-       current_par.screen_size         = MAX_PIXEL_MEM_SIZE;
-       current_par.montype             = -1;
-       current_par.currcon             = -1;
-       current_par.allow_modeset       =  1;
-       current_par.controller_state    = LCD_MODE_DISABLED;
-
-       init_var.xres                   = current_par.max_xres;
-       init_var.yres                   = current_par.max_yres;
-       init_var.xres_virtual           = init_var.xres;
-       init_var.yres_virtual           = init_var.yres;
-       init_var.bits_per_pixel         = current_par.max_bpp;
-                       
+       DPRINTK("DBAR1 = %p\n", DBAR1);
+       DPRINTK("DBAR2 = %p\n", DBAR2);
+       DPRINTK("LCCR0 = 0x%08x\n", LCCR0);
+       DPRINTK("LCCR1 = 0x%08x\n", LCCR1);
+       DPRINTK("LCCR2 = 0x%08x\n", LCCR2);
+       DPRINTK("LCCR3 = 0x%08x\n", LCCR3);
 }
 
-
-
-/*
- * sa1100fb_map_video_memory():
- *      Allocates the DRAM memory for the frame buffer.  This buffer is  
- *     remapped into a non-cached, non-buffered, memory region to  
- *      allow palette and pixel writes to occur without flushing the 
- *      cache.  Once this area is remapped, all virtual memory
- *      access to the video memory should occur at the new region.
- */
-static int
-__init sa1100fb_map_video_memory(void)
+static void sa1100fb_disable_controller(struct sa1100fb_info *fbi)
 {
-       u_int  required_pages;
-       u_int  extra_pages;
-       u_int  order;
-        struct page *page;
-        char   *allocated_region;
+       DECLARE_WAITQUEUE(wait, current);
 
-       if (VideoMemRegion != NULL)
-               return -EINVAL;
+       DPRINTK("Disabling LCD controller\n");
 
-       DPRINTK("-1-");
-
-       /* Find order required to allocate enough memory for framebuffer */
-       required_pages = ALLOCATED_FB_MEM_SIZE >> PAGE_SHIFT;
-        for (order = 0 ; required_pages >> order ; order++) {;}
-        extra_pages = (1 << order) - required_pages;
-
-        if ((allocated_region = 
-             (char *)__get_free_pages(GFP_KERNEL | GFP_DMA, order)) == NULL)
-           return -ENOMEM;
-
-        VideoMemRegion = (u_char *)allocated_region + (extra_pages << PAGE_SHIFT); 
-        VideoMemRegion_phys = (u_char *)__virt_to_phys((u_long)VideoMemRegion);
-
-       /* Free all pages that we don't need but were given to us because */
-       /* __get_free_pages() works on powers of 2. */
-       for (;extra_pages;extra_pages--)
-          free_page((u_int)allocated_region + ((extra_pages-1) << PAGE_SHIFT));
-
-        /* Set reserved flag for fb memory to allow it to be remapped into */
-        /* user space by the common fbmem driver using remap_page_range(). */
-       for(page = virt_to_page(VideoMemRegion); 
-           page < virt_to_page(VideoMemRegion + ALLOCATED_FB_MEM_SIZE); page++)
-         mem_map_reserve(page);
-
-       /* Remap the fb memory to a non-buffered, non-cached region */
-       VideoMemRegion = (u_char *)__ioremap((u_long)VideoMemRegion_phys,
-                                            ALLOCATED_FB_MEM_SIZE,
-                                            L_PTE_PRESENT  |
-                                            L_PTE_YOUNG    |
-                                            L_PTE_DIRTY    |
-                                            L_PTE_WRITE);
-       return (VideoMemRegion == NULL ? -EINVAL : 0);
-}
+#ifdef CONFIG_SA1100_GRAPHICSCLIENT
+#error Where is GPIO24 set as an output?  Can we fit this in somewhere else?
+       if (machine_is_graphicsclient()) {
+               /*
+                * From ADS internal document:
+                *  GPIO24 should be LOW at least 10msec prior to disabling
+                *  the LCD interface.
+                *
+                * We'll wait 20msec.
+                */
+               GPCR |= GPIO_GPIO24;
+               set_current_state(TASK_UNINTERRUPTIBLE);
+               schedule_timeout(20 * HZ / 1000);
+       }
+#endif
+#ifdef CONFIG_SA1100_HUW_WEBPANEL
+#error Move me into sa1100fb_power_up_lcd and/or sa1100fb_backlight_on
+       if (machine_is_huw_webpanel()) {
+               // dont forget to set the control lines to zero (?)
+               DPRINTK("ShutDown HuW LCD controller\n");
+               BCR_clear(BCR_TFT_ENA + BCR_CCFL_POW + BCR_PWM_BACKLIGHT);
+       }
+#endif
 
-static const int frequency[16] = {
-       59000000,
-        73700000,
-        88500000,
-        103200000,
-        118000000,
-        132700000,
-        147500000,
-        162200000,
-        176900000,
-        191700000,
-        206400000, 
-       230000000,
-       245000000,
-       260000000,
-       275000000,
-       290000000
-};
+       add_wait_queue(&fbi->ctrlr_wait, &wait);
+       set_current_state(TASK_UNINTERRUPTIBLE);
 
+       LCSR = 0xffffffff;      /* Clear LCD Status Register */
+       LCCR0 &= ~LCCR0_LDM;    /* Enable LCD Disable Done Interrupt */
+       enable_irq(IRQ_LCD);    /* Enable LCD IRQ */
+       LCCR0 &= ~LCCR0_LEN;    /* Disable LCD Controller */
 
-static inline int get_pcd(unsigned int pixclock)
+       schedule_timeout(20 * HZ / 1000);
+       current->state = TASK_RUNNING;
+       remove_wait_queue(&fbi->ctrlr_wait, &wait);
+}
+
+/*
+ *  sa1100fb_handle_irq: Handle 'LCD DONE' interrupts.
+ */
+static void sa1100fb_handle_irq(int irq, void *dev_id, struct pt_regs *regs)
 {
-       unsigned int pcd = 0;
+       struct sa1100fb_info *fbi = dev_id;
+       unsigned int lcsr = LCSR;
 
-       if (machine_is_assabet() | machine_is_pangolin()) {
-               pcd = frequency[PPCR & 0xf] / 1000;
-               pcd *= pixclock / 1000;
-               pcd = pcd / 1000000;
-               pcd++; /* make up for integer math truncations */
+       if (lcsr & LCSR_LDD) {
+               LCCR0 |= LCCR0_LDM;
+               wake_up(&fbi->ctrlr_wait);
        }
-       return pcd;
-}
 
+       LCSR = lcsr;
+}
 
 /*
- * sa1100fb_activate_var():
- *     Configures LCD Controller based on entries in var parameter.  Settings are      
- *      only written to the controller if changes were made.  
+ * This function must be called from task context only, since it will
+ * sleep when disabling the LCD controller, or if we get two contending
+ * processes trying to alter state.
  */
-static int
-sa1100fb_activate_var(struct fb_var_screeninfo *var)
-{                                                     
-       u_long  flags;
-       int pcd = get_pcd(var->pixclock);
-
-       DPRINTK("Configuring  SA1100 LCD\n");
+static void set_ctrlr_state(struct sa1100fb_info *fbi, u_int state)
+{
+       u_int old_state;
 
-       if (current_par.p_palette_base == NULL)
-               return -EINVAL;
+       down(&fbi->ctrlr_sem);
 
-       DPRINTK("activating\n");
+       old_state = fbi->state;
 
-       /* Disable interrupts and save status */
-       local_irq_save(flags);          // disable the interrupts and save flags
+       switch (state) {
+       case C_DISABLE_CLKCHANGE:
+               /*
+                * Disable controller for clock change.  If the
+                * controller is already disabled, then do nothing.
+                */
+               if (old_state != C_DISABLE) {
+                       fbi->state = state;
+                       sa1100fb_disable_controller(fbi);
+               }
+               break;
 
-       /* Reset the LCD Controller's DMA address if it has changed */
-       lcd_shadow.dbar1 = (Address)current_par.p_palette_base;
-       lcd_shadow.dbar2 = (Address)(current_par.p_screen_base + (current_par.xres * current_par.yres * current_par.bits_per_pixel / 8 / 2));
+       case C_DISABLE:
+               /*
+                * Disable controller
+                */
+               if (old_state != C_DISABLE) {
+                       fbi->state = state;
 
-       DPRINTK("Configuring xres = %d, yres = %d\n",var->xres, var->yres);
+                       sa1100fb_backlight_off(fbi);
+                       if (old_state != C_DISABLE_CLKCHANGE)
+                               sa1100fb_disable_controller(fbi);
+                       sa1100fb_power_down_lcd(fbi);
+               }
+               break;
 
-       if (machine_is_assabet()) {
-               DPRINTK("Configuring  Assabet LCD\n");
-               lcd_shadow.lccr0 = 
-                       LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + 
-                       LCCR0_LDM + LCCR0_BAM + LCCR0_ERM + LCCR0_Act +
-                       LCCR0_LtlEnd + LCCR0_DMADel(0);
-               lcd_shadow.lccr1 = 
-                       LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(6) + 
-                       LCCR1_BegLnDel(61) + LCCR1_EndLnDel(9);
-               lcd_shadow.lccr2 = 
-                       LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(1) + 
-                       LCCR2_BegFrmDel(3) + LCCR2_EndFrmDel(0);
-               lcd_shadow.lccr3 = 
-                       LCCR3_OutEnH + LCCR3_PixFlEdg + LCCR3_VrtSnchH + 
-                       LCCR3_HorSnchH + LCCR3_ACBsCntOff + 
-                       LCCR3_ACBsDiv(2) + LCCR3_PixClkDiv(pcd);
-
-               /* Set board control register to handle new color depth */
-               sa1100fb_assabet_set_truecolor(var->bits_per_pixel >= 16);
-       } else if (machine_is_pangolin()) {
-               DPRINTK("Configuring Pangolin LCD\n");
-               lcd_shadow.lccr0 = 
-                       LCCR0_LEN + LCCR0_Color + LCCR0_LDM +
-                       LCCR0_BAM + LCCR0_ERM + LCCR0_Act +
-                       LCCR0_LtlEnd + LCCR0_DMADel(0);
-               lcd_shadow.lccr1 = 
-                       LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(63) + 
-                       LCCR1_BegLnDel(127) + LCCR1_EndLnDel(127);
-               lcd_shadow.lccr2 = 
-                       LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(2) + 
-                       LCCR2_BegFrmDel(18) + LCCR2_EndFrmDel(18);
-               lcd_shadow.lccr3 = 
-                       LCCR3_PixClkDiv(pcd) + LCCR3_HorSnchH +
-                       LCCR3_VrtSnchH + LCCR3_OutEnH;
-               DPRINTK("pcd = %d\n", pcd);
-               DPRINTK("LCCR1_DisWdth(var->xres) = 0x%x\n",
-                       LCCR1_DisWdth(var->xres));
-               DPRINTK("LCCR2_DisHght(var->yres) = 0x%x\n",
-                       LCCR2_DisHght(var->yres));
-       } else if (machine_is_bitsy()) {
-               DPRINTK("Configuring  Bitsy LCD\n");
-               lcd_shadow.lccr0 = LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + LCCR0_Act +
-                                  LCCR0_LtlEnd + LCCR0_LDM + LCCR0_BAM + LCCR0_ERM + 
-                                  LCCR0_DMADel(0);
-               lcd_shadow.lccr1 = LCCR1_DisWdth( var->xres ) +
-                                  LCCR1_HorSnchWdth( 4 ) +
-                                  LCCR1_BegLnDel( 0xC ) +
-                                  LCCR1_EndLnDel( 0x11 );
-               lcd_shadow.lccr2 = LCCR2_DisHght( var->yres + 1 ) +
-                                  LCCR2_VrtSnchWdth( 3 )+
-                                  LCCR2_BegFrmDel( 10 ) +
-                                  LCCR2_EndFrmDel( 1 );
-               lcd_shadow.lccr3 = (/* PCD */ 0x10
-                                    | /* ACB */ 0
-                                    | /* API */ 0
-                                    | LCCR3_VrtSnchL
-                                    | LCCR3_HorSnchL);
-       } else if (machine_is_brutus()) {
-               DPRINTK("Configuring  Brutus LCD\n");
-               lcd_shadow.lccr0 = 
-                       LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + LCCR0_Pas + 
-                       LCCR0_LtlEnd + LCCR0_LDM + LCCR0_BAM + LCCR0_ERM + 
-                       LCCR0_DMADel(0);
-               lcd_shadow.lccr1 = 
-                       LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(4) + 
-                       LCCR1_BegLnDel(41) + LCCR1_EndLnDel(101);
-               lcd_shadow.lccr2 = 
-                       LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(1) + 
-                       LCCR2_BegFrmDel(0) + LCCR2_EndFrmDel(0);
-               lcd_shadow.lccr3 = 
-                       LCCR3_OutEnH + LCCR3_PixFlEdg + LCCR3_VrtSnchH + 
-                       LCCR3_HorSnchH + LCCR3_ACBsCntOff + 
-                       LCCR3_ACBsDiv(2) + LCCR3_PixClkDiv(44);
-       } else if (machine_is_cerf()) {
-               DPRINTK("Configuring Cerf LCD\n");
-               lcd_shadow.lccr0 = 
-                       LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + 
-                       LCCR0_LDM + LCCR0_BAM + LCCR0_ERM + LCCR0_Pas +
-                       LCCR0_LtlEnd + LCCR0_DMADel(0);
-               lcd_shadow.lccr1 = 
-                       LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(6) + 
-                       LCCR1_BegLnDel(61) + LCCR1_EndLnDel(9);
-               lcd_shadow.lccr2 = 
-                       LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(1) + 
-                       LCCR2_BegFrmDel(3) + LCCR2_EndFrmDel(0);
-               lcd_shadow.lccr3 = 
-                       LCCR3_OutEnH + LCCR3_PixFlEdg + LCCR3_VrtSnchH + 
-                       LCCR3_HorSnchH + LCCR3_ACBsCntOff + 
-                       LCCR3_ACBsDiv(2) + LCCR3_PixClkDiv(38);
-       } else if (machine_is_lart()) {
-               DPRINTK("Configuring LART LCD\n");
-               lcd_shadow.lccr0 = 
-                       LCCR0_LEN + LCCR0_Mono + LCCR0_Sngl + LCCR0_Pas +
-                       LCCR0_LtlEnd + LCCR0_LDM + LCCR0_BAM + LCCR0_ERM + 
-                       LCCR0_DMADel(0);
-               lcd_shadow.lccr1 = 
-                       LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(2) +
-                       LCCR1_BegLnDel(4) + LCCR1_EndLnDel(2);
-               lcd_shadow.lccr2 = 
-                       LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(1) +
-                       LCCR2_BegFrmDel(0) + LCCR2_EndFrmDel(0);
-               lcd_shadow.lccr3 = 
-                       LCCR3_PixClkDiv(34) + LCCR3_ACBsDiv(512) +
-                       LCCR3_ACBsCntOff + LCCR3_HorSnchH + LCCR3_VrtSnchH;
-       } else if (machine_is_graphicsclient()) {
-               DPRINTK("Configuring GraphicsClient LCD\n");
-               lcd_shadow.lccr0 = 
-                       LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + LCCR0_Act;
-               lcd_shadow.lccr1 = 
-                       LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(10) +
-                       LCCR1_EndLnDel(81) + LCCR1_BegLnDel(81);
-               lcd_shadow.lccr2 = 
-                       LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(9) + 
-                       LCCR2_EndFrmDel (20) + LCCR2_BegFrmDel(20);
-               lcd_shadow.lccr3 = 
-                       LCCR3_PixClkDiv(6) + LCCR3_ACBsDiv(2) + 
-                       LCCR3_ACBsCntOff + LCCR3_HorSnchL + LCCR3_VrtSnchL;
-       } else if (machine_is_xp860()) {
-               DPRINTK("Configuring XP860 LCD\n");
-               lcd_shadow.lccr0 = 
-                       LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + LCCR0_Act +
-                       LCCR0_LtlEnd + LCCR0_LDM + LCCR0_ERM +
-                       LCCR0_DMADel(0);
-               lcd_shadow.lccr1 = 
-                       LCCR1_DisWdth(var->xres) + 
-                       LCCR1_HorSnchWdth(var->hsync_len) +
-                       LCCR1_BegLnDel(var->left_margin) +
-                       LCCR1_EndLnDel(var->right_margin);
-               lcd_shadow.lccr2 = 
-                       LCCR2_DisHght(var->yres) + 
-                       LCCR2_VrtSnchWdth(var->vsync_len) +
-                       LCCR2_BegFrmDel(var->upper_margin) +
-                       LCCR2_EndFrmDel(var->lower_margin);
-               lcd_shadow.lccr3 = 
-                       LCCR3_PixClkDiv(6) +
-                       LCCR3_HorSnchL + LCCR3_VrtSnchL;
-       }
+       case C_ENABLE_CLKCHANGE:
+               /*
+                * Enable the controller after clock change.  Only
+                * do this if we were disabled for the clock change.
+                */
+               if (old_state == C_DISABLE_CLKCHANGE) {
+                       fbi->state = C_ENABLE;
+                       sa1100fb_enable_controller(fbi);
+               }
+               break;
 
-       /* Restore interrupt status */
-       local_irq_restore(flags);
+       case C_REENABLE:
+               /*
+                * Re-enable the controller only if it was already
+                * enabled.  This is so we reprogram the control
+                * registers.
+                */
+               if (old_state == C_ENABLE) {
+                       sa1100fb_disable_controller(fbi);
+                       sa1100fb_setup_gpio(fbi);
+                       sa1100fb_enable_controller(fbi);
+               }
+               break;
 
-       if (( LCCR0 != lcd_shadow.lccr0 ) ||
-           ( LCCR1 != lcd_shadow.lccr1 ) ||
-           ( LCCR2 != lcd_shadow.lccr2 ) ||
-            ( LCCR3 != lcd_shadow.lccr3 ) ||
-           ( DBAR1 != lcd_shadow.dbar1 ) ||
-           ( DBAR2 != lcd_shadow.dbar2 ))
-       {
-               sa1100fb_enable_lcd_controller();
+       case C_ENABLE:
+               /*
+                * Power up the LCD screen, enable controller, and
+                * turn on the backlight.
+                */
+               if (old_state != C_ENABLE) {
+                       fbi->state = C_ENABLE;
+                       sa1100fb_setup_gpio(fbi);
+                       sa1100fb_power_up_lcd(fbi);
+                       sa1100fb_enable_controller(fbi);
+                       sa1100fb_backlight_on(fbi);
+               }
+               break;
        }
-
-       return 0;
+       up(&fbi->ctrlr_sem);
 }
 
-
 /*
- *  sa1100fb_inter_handler():
- *     Interrupt handler for LCD controller.  Processes disable done interrupt (LDD)
- *      to reenable controller if controller was disabled to change register values.
+ * Our LCD controller task (which is called when we blank or unblank)
+ * via keventd.
  */
-static void sa1100fb_inter_handler(int irq, void *dev_id, struct pt_regs *regs)
+static void sa1100fb_task(void *dummy)
 {
-        if (LCSR & LCSR_LDD) {
-                int controller_state = current_par.controller_state;
-               /* Disable Done Flag is set */
-               LCCR0 |= LCCR0_LDM;           /* Mask LCD Disable Done Interrupt */
-               current_par.controller_state = LCD_MODE_DISABLED;
-               if (controller_state == LCD_MODE_DISABLE_BEFORE_ENABLE) {
-                       DPRINTK("sa1100fb_inter_handler: re-enabling LCD controller\n");
-                       sa1100fb_enable_lcd_controller();
-               } else {
-                       /*
-                        * Second half of sa1100fb_disable_lcd_controller()
-                        */
-                       if (machine_is_assabet()) {
-#ifdef CONFIG_SA1100_ASSABET
-                               BCR_clear(BCR_LCD_ON);
-#endif
-                       } else if (machine_is_bitsy()) {
-#ifdef CONFIG_SA1100_BITSY
-                               if (current_par.controller_state != LCD_MODE_DISABLE_BEFORE_ENABLE)
-                                       clr_bitsy_egpio(EGPIO_BITSY_LCD_ON | EGPIO_BITSY_LCD_PCI | EGPIO_BITSY_LCD_5V_ON | EGPIO_BITSY_LVDD_ON);
-#endif
-                       }
-               }
-       }
-       LCSR = 0;                     /* Clear LCD Status Register */
-}
+       struct sa1100fb_info *fbi = dummy;
+       u_int state = xchg(&fbi->task_state, -1);
 
+       set_ctrlr_state(fbi, state);
+}
 
+#ifdef CONFIG_CPU_FREQ
 /*
- *  sa1100fb_disable_lcd_controller():
- *     Disables LCD controller by and enables LDD interrupt.  The controller_state
- *      is not changed until the LDD interrupt is received to indicate the current
- *      frame has completed.  Platform specific hardware disabling is also included.
+ * Calculate the minimum DMA period over all displays that we own.
+ * This, together with the SDRAM bandwidth defines the slowest CPU
+ * frequency that can be selected.
  */
-static void sa1100fb_disable_lcd_controller(void)
+static unsigned int sa1100fb_min_dma_period(struct sa1100fb_info *fbi)
 {
-        DPRINTK("Disabling LCD controller\n");
+       unsigned int min_period = (unsigned int)-1;
+       int i;
 
-       /* Exit if already LCD disabled, or LDD IRQ unmasked */
-       if ((current_par.controller_state == LCD_MODE_DISABLED) ||
-           (!(LCCR0 & LCCR0_LDM))) {
-               DPRINTK("LCD already disabled\n");
-               return;
+       for (i = 0; i < MAX_NR_CONSOLES; i++) {
+               unsigned int period;
+
+               /*
+                * Do we own this display?
+                */
+               if (fb_display[i].fb_info != &fbi->fb)
+                       continue;
+
+               /*
+                * Ok, calculate its DMA period
+                */
+               period = sa1100fb_display_dma_period(get_con_var(fbi, i));
+               if (period < min_period)
+                       min_period = period;
        }
 
-       LCSR = 0;       /* Clear LCD Status Register */
-       LCCR0 &= ~(LCCR0_LDM);  /* Enable LCD Disable Done Interrupt */
-       enable_irq(IRQ_LCD);          /* Enable LCD IRQ */
-       LCCR0 &= ~(LCCR0_LEN);  /* Disable LCD Controller */
+       return min_period;
 }
 
 /*
- *  sa1100fb_enable_lcd_controller():
- *     Enables LCD controller.  If the controller is already enabled, it is first disabled.
- *      This forces all changes to the LCD controller registers to be done when the 
- *      controller is disabled.  Platform specific hardware enabling is also included.
+ * CPU clock speed change handler.  We need to adjust the LCD timing
+ * parameters when the CPU clock is adjusted by the power management
+ * subsystem.
  */
-static void sa1100fb_enable_lcd_controller(void)
+static int
+sa1100fb_clkchg_notifier(struct notifier_block *nb, unsigned long val,
+                        void *data)
 {
-       u_long  flags;
-
-       local_irq_save(flags);          
-
-        /* Disable controller before changing parameters */
-       if (current_par.controller_state == LCD_MODE_ENABLED)   {
-               current_par.controller_state = LCD_MODE_DISABLE_BEFORE_ENABLE;
-               sa1100fb_disable_lcd_controller();
-       } else {
-               DPRINTK("Enabling LCD controller\n");
-
-               /* Make sure the mode bits are present in the first palette entry */
-               current_par.v_palette_base[0] &= 0x0FFF;                   
-               current_par.v_palette_base[0] |= SA1100_PALETTE_MODE_VAL(current_par.bits_per_pixel);
-
-               /* Enable GPIO<9:2> for LCD usage if dual-scan */
-               if (lcd_shadow.lccr0 & LCCR0_SDS) {
-                 GPDR |= 0x3fc;
-                 GAFR |= 0x3fc;
-               }
-
-               /* Sequence from 11.7.10 */
-               LCCR3 = lcd_shadow.lccr3;
-               LCCR2 = lcd_shadow.lccr2;
-               LCCR1 = lcd_shadow.lccr1;
-               LCCR0 = lcd_shadow.lccr0 & ~LCCR0_LEN;
-               DBAR1 = lcd_shadow.dbar1;
-               DBAR2 = lcd_shadow.dbar2;
-               LCCR0 |= LCCR0_LEN;
-
-               if (machine_is_assabet()) {
-#ifdef CONFIG_SA1100_ASSABET
-                       BCR_set(BCR_LCD_ON);
-#endif
-               } else if (machine_is_bitsy()) {
-#ifdef CONFIG_SA1100_BITSY
-                  set_bitsy_egpio(EGPIO_BITSY_LCD_ON | EGPIO_BITSY_LCD_PCI | EGPIO_BITSY_LCD_5V_ON | EGPIO_BITSY_LVDD_ON);
-                       DPRINTK("DBAR1=%p\n", DBAR1);
-                       DPRINTK("LCCR0=%x\n", LCCR0);
-                       DPRINTK("LCCR1=%x\n", LCCR1);
-                       DPRINTK("LCCR2=%x\n", LCCR2);
-                       DPRINTK("LCCR3=%x\n", LCCR3);
-#endif
-               }
+       struct sa1100fb_info *fbi = TO_INF(nb, clockchg);
+       struct cpufreq_minmax *mm = data;
+       u_int pcd;
+
+       switch (val) {
+       case CPUFREQ_MINMAX:
+               printk(KERN_DEBUG "min dma period: %d ps, old clock %d kHz, "
+                       "new clock %d kHz\n", sa1100fb_min_dma_period(fbi),
+                       mm->cur_freq, mm->new_freq);
+               /* todo: fill in min/max values */
+               break;
 
-               current_par.controller_state = LCD_MODE_ENABLED;
+       case CPUFREQ_PRECHANGE:
+               set_ctrlr_state(fbi, C_DISABLE_CLKCHANGE);
+               break;
 
+       case CPUFREQ_POSTCHANGE:
+               pcd = get_pcd(fbi->fb.var.pixclock);
+               fbi->reg_lccr3 = (fbi->reg_lccr3 & ~0xff) | LCCR3_PixClkDiv(pcd);
+               set_ctrlr_state(fbi, C_ENABLE_CLKCHANGE);
+               break;
        }
-       /* Restore interrupt status */
-       local_irq_restore(flags);
+       return 0;
 }
+#endif
 
+#ifdef CONFIG_PM
 /*
- * sa1100fb_blank():
- *     Blank the display by setting all palette values to zero.  Note, the 
- *     12 and 16 bpp modes don't really use the palette, so this will not
- *      blank the display in all modes.  
+ * Power management hook.  Note that we won't be called from IRQ context,
+ * unlike the blank functions above, so we may sleep.
  */
-static void
-sa1100fb_blank(int blank, struct fb_info *info)
+static int
+sa1100fb_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data)
 {
-       int i;
+       struct sa1100fb_info *fbi = pm_dev->data;
 
-       DPRINTK("blank=%d info->modename=%s\n", blank, info->modename);
-       if (blank) {
-                if (current_par.visual != FB_VISUAL_TRUECOLOR)
-               for (i = 0; i < current_par.palette_size; i++)
-                       sa1100fb_palette_write(i, sa1100fb_palette_encode(i, 0, 0, 0, 0));
-               sa1100fb_disable_lcd_controller();
-       }
-       else {
-                if (current_par.visual != FB_VISUAL_TRUECOLOR)
-               sa1100fb_set_cmap(&fb_display[current_par.currcon].cmap, 1, 
-                                 current_par.currcon, info); 
-               sa1100fb_enable_lcd_controller();
+       DPRINTK("pm_callback: %d\n", req);
+
+       if (req == PM_SUSPEND || req == PM_RESUME) {
+               int state = (int)data;
+
+               if (state == 0) {
+                       /* Enter D0. */
+                       set_ctrlr_state(fbi, C_ENABLE);
+               } else {
+                       /* Enter D1-D3.  Disable the LCD controller.  */
+                       set_ctrlr_state(fbi, C_DISABLE);
+               }
        }
-       /* TODO: Bitsy support for blanking display */
+       DPRINTK("done\n");
+       return 0;
 }
-
+#endif
 
 /*
- *  sa1100fb_switch():       
- *     Change to the specified console.  Palette and video mode
- *      are changed to the console's stored parameters. 
+ * sa1100fb_map_video_memory():
+ *      Allocates the DRAM memory for the frame buffer.  This buffer is  
+ *     remapped into a non-cached, non-buffered, memory region to  
+ *      allow palette and pixel writes to occur without flushing the 
+ *      cache.  Once this area is remapped, all virtual memory
+ *      access to the video memory should occur at the new region.
  */
-static int
-sa1100fb_switch(int con, struct fb_info *info)
+static int __init sa1100fb_map_video_memory(struct sa1100fb_info *fbi)
 {
+       /*
+        * We reserve one page for the palette, plus the size
+        * of the framebuffer.
+        */
+       fbi->map_size = PAGE_ALIGN(fbi->fb.fix.smem_len + PAGE_SIZE);
+       fbi->map_cpu = consistent_alloc(GFP_KERNEL, fbi->map_size,
+                                       &fbi->map_dma);
+
+       if (fbi->map_cpu) {
+               fbi->screen_cpu = fbi->map_cpu + PAGE_SIZE;
+               fbi->screen_dma = fbi->map_dma + PAGE_SIZE;
+               fbi->fb.fix.smem_start = fbi->screen_dma;
+       }
 
-       DPRINTK("con=%d info->modename=%s\n", con, info->modename);
-        if (current_par.visual != FB_VISUAL_TRUECOLOR) {
-                struct fb_cmap *cmap;
-               if (current_par.currcon >= 0) {
-                       // Get the colormap for the selected console 
-                       cmap = &fb_display[current_par.currcon].cmap;
-                       
-                       if (cmap->len)
-                               fb_get_cmap(cmap, 1, sa1100fb_getcolreg, info);
-               }
-        }
+       return fbi->map_cpu ? 0 : -ENOMEM;
+}
 
-       current_par.currcon = con;
-       fb_display[con].var.activate = FB_ACTIVATE_NOW;
-       DPRINTK("fb_display[%d].var.activate=%x\n", con, fb_display[con].var.activate);
-       sa1100fb_set_var(&fb_display[con].var, con, info);
-       current_par.v_palette_base[0] = (current_par.v_palette_base[0] &
-               0xcfff) | SA1100_PALETTE_MODE_VAL(current_par.bits_per_pixel);
+/* Fake monspecs to fill in fbinfo structure */
+static struct fb_monspecs monspecs __initdata = {
+       30000, 70000, 50, 65, 0 /* Generic */
+};
 
-       return 0;
-}
 
+static struct sa1100fb_info * __init sa1100fb_init_fbinfo(void)
+{
+       struct sa1100fb_mach_info *inf;
+       struct sa1100fb_info *fbi;
+
+       fbi = kmalloc(sizeof(struct sa1100fb_info) + sizeof(struct display) +
+                     sizeof(u16) * 16, GFP_KERNEL);
+       if (!fbi)
+               return NULL;
+
+       memset(fbi, 0, sizeof(struct sa1100fb_info) + sizeof(struct display));
+
+       fbi->currcon            = -1;
+
+       strcpy(fbi->fb.fix.id, SA1100_NAME);
+
+       fbi->fb.fix.type        = FB_TYPE_PACKED_PIXELS;
+       fbi->fb.fix.type_aux    = 0;
+       fbi->fb.fix.xpanstep    = 0;
+       fbi->fb.fix.ypanstep    = 0;
+       fbi->fb.fix.ywrapstep   = 0;
+       fbi->fb.fix.accel       = FB_ACCEL_NONE;
+
+       fbi->fb.var.nonstd      = 0;
+       fbi->fb.var.activate    = FB_ACTIVATE_NOW;
+       fbi->fb.var.height      = -1;
+       fbi->fb.var.width       = -1;
+       fbi->fb.var.accel_flags = 0;
+       fbi->fb.var.vmode       = FB_VMODE_NONINTERLACED;
+
+       strcpy(fbi->fb.modename, SA1100_NAME);
+       strcpy(fbi->fb.fontname, "Acorn8x8");
+
+       fbi->fb.fbops           = &sa1100fb_ops;
+       fbi->fb.changevar       = NULL;
+       fbi->fb.switch_con      = sa1100fb_switch;
+       fbi->fb.updatevar       = sa1100fb_updatevar;
+       fbi->fb.blank           = sa1100fb_blank;
+       fbi->fb.flags           = FBINFO_FLAG_DEFAULT;
+       fbi->fb.node            = -1;
+       fbi->fb.monspecs        = monspecs;
+       fbi->fb.disp            = (struct display *)(fbi + 1);
+       fbi->fb.pseudo_palette  = (void *)(fbi->fb.disp + 1);
+
+       fbi->rgb[RGB_8]         = &rgb_8;
+       fbi->rgb[RGB_16]        = &def_rgb_16;
+
+       inf = sa1100fb_get_machine_info(fbi);
+
+       fbi->max_xres                   = inf->xres;
+       fbi->fb.var.xres                = inf->xres;
+       fbi->fb.var.xres_virtual        = inf->xres;
+       fbi->max_yres                   = inf->yres;
+       fbi->fb.var.yres                = inf->yres;
+       fbi->fb.var.yres_virtual        = inf->yres;
+       fbi->max_bpp                    = inf->bpp;
+       fbi->fb.var.bits_per_pixel      = inf->bpp;
+       fbi->fb.var.pixclock            = inf->pixclock;
+       fbi->fb.var.hsync_len           = inf->hsync_len;
+       fbi->fb.var.left_margin         = inf->left_margin;
+       fbi->fb.var.right_margin        = inf->right_margin;
+       fbi->fb.var.vsync_len           = inf->vsync_len;
+       fbi->fb.var.upper_margin        = inf->upper_margin;
+       fbi->fb.var.lower_margin        = inf->lower_margin;
+       fbi->fb.var.sync                = inf->sync;
+       fbi->fb.var.grayscale           = inf->cmap_greyscale;
+       fbi->cmap_inverse               = inf->cmap_inverse;
+       fbi->cmap_static                = inf->cmap_static;
+       fbi->lccr0                      = inf->lccr0;
+       fbi->lccr3                      = inf->lccr3;
+       fbi->state                      = C_DISABLE;
+       fbi->task_state                 = (u_char)-1;
+       fbi->fb.fix.smem_len            = fbi->max_xres * fbi->max_yres *
+                                         fbi->max_bpp / 8;
+
+       init_waitqueue_head(&fbi->ctrlr_wait);
+       INIT_TQUEUE(&fbi->task, sa1100fb_task, fbi);
+       init_MUTEX(&fbi->ctrlr_sem);
+
+       return fbi;
+}
 
 int __init sa1100fb_init(void)
 {
+       struct sa1100fb_info *fbi;
        int ret;
 
-       sa1100fb_init_fbinfo();
+       fbi = sa1100fb_init_fbinfo();
+       ret = -ENOMEM;
+       if (!fbi)
+               goto failed;
 
        /* Initialize video memory */
-       if ((ret = sa1100fb_map_video_memory()) != 0)
-               return ret;
+       ret = sa1100fb_map_video_memory(fbi);
+       if (ret)
+               goto failed;
+
+       ret = request_irq(IRQ_LCD, sa1100fb_handle_irq, SA_INTERRUPT,
+                         fbi->fb.fix.id, fbi);
+       if (ret) {
+               printk(KERN_ERR "sa1100fb: failed in request_irq: %d\n", ret);
+               goto failed;
+       }
 
-       if (current_par.montype < 0 || current_par.montype > NR_MONTYPES)
-               current_par.montype = 1;
+#if defined(CONFIG_SA1100_ASSABET) && defined(ASSABET_PAL_VIDEO)
+       if (machine_is_assabet())
+               BCR_clear(BCR_LCD_ON);
+#endif
 
-       if (request_irq(IRQ_LCD, sa1100fb_inter_handler, SA_INTERRUPT, "SA1100 LCD", NULL) != 0) {
-               printk(KERN_ERR "sa1100fb: failed in request_irq\n");
-               return -EBUSY;
+#ifdef CONFIG_SA1100_FREEBIRD
+#error Please move this into sa1100fb_power_up_lcd
+       if (machine_is_freebird()) {
+               BCR_set(BCR_FREEBIRD_LCD_DISP);
+               mdelay(20);
+               BCR_set(BCR_FREEBIRD_LCD_PWR);
+               mdelay(20);
        }
-       DPRINTK("sa1100fb: request_irq succeeded\n");
-       disable_irq(IRQ_LCD);
+#endif
 
-       if (machine_is_assabet()) {
-               GPDR |= 0x3fc;
-               GAFR |= 0x3fc;
-               sa1100fb_assabet_set_truecolor(current_par.visual ==
-                                              FB_VISUAL_TRUECOLOR);
-       } else if (machine_is_pangolin()) {
-               GPDR |= 0x3fc;
-               GAFR |= 0x3fc;
-       } else if (machine_is_bitsy()) {
-               GPDR = (GPIO_LDD15 | GPIO_LDD14 | GPIO_LDD13 | GPIO_LDD12 | GPIO_LDD11 | GPIO_LDD10 | GPIO_LDD9 | GPIO_LDD8);
-               GAFR |= (GPIO_LDD15 | GPIO_LDD14 | GPIO_LDD13 | GPIO_LDD12 | GPIO_LDD11 | GPIO_LDD10 | GPIO_LDD9 | GPIO_LDD8);
-       } else if (machine_is_cerf()) {
-               GPDR |= 0x3fc;
-               GAFR |= 0x3fc;
-       } else if (machine_is_xp860()) {
-               GPDR |= 0x3fc;
-               GAFR |= 0x3fc;
-       }
+       sa1100fb_set_var(&fbi->fb.var, -1, &fbi->fb);
 
-       if (sa1100fb_set_var(&init_var, -1, &fb_info))
-               current_par.allow_modeset = 0;
-       sa1100fb_decode_var(&init_var, &current_par);
+       ret = register_framebuffer(&fbi->fb);
+       if (ret < 0)
+               goto failed;
+
+#ifdef CONFIG_PM
+       /*
+        * Note that the console registers this as well, but we want to
+        * power down the display prior to sleeping.
+        */
+       fbi->pm = pm_register(PM_SYS_DEV, PM_SYS_VGA, sa1100fb_pm_callback);
+       if (fbi->pm)
+               fbi->pm->data = fbi;
+#endif
+#ifdef CONFIG_CPU_FREQ
+       fbi->clockchg.notifier_call = sa1100fb_clkchg_notifier;
+       cpufreq_register_notifier(&fbi->clockchg);
+#endif
 
-       register_framebuffer(&fb_info);
+       /*
+        * Ok, now enable the LCD controller
+        */
+       set_ctrlr_state(fbi, C_ENABLE);
 
        /* This driver cannot be unloaded at the moment */
        MOD_INC_USE_COUNT;
 
        return 0;
+
+failed:
+       if (fbi)
+               kfree(fbi);
+       return ret;
 }
 
 int __init sa1100fb_setup(char *options)
 {
+#if 0
        char *this_opt;
 
        if (!options || !*options)
@@ -1285,24 +2302,33 @@ int __init sa1100fb_setup(char *options)
        for (this_opt = strtok(options, ","); this_opt;
             this_opt = strtok(NULL, ",")) {
 
-         if (!strncmp(this_opt, "bpp:", 4))
-           current_par.max_bpp = simple_strtoul(this_opt+4, NULL, 0);
-
-         if (!strncmp(this_opt, "lccr0:", 6))
-           lcd_shadow.lccr0 = simple_strtoul(this_opt+6, NULL, 0);
-         if (!strncmp(this_opt, "lccr1:", 6)) {
-           lcd_shadow.lccr1 = simple_strtoul(this_opt+6, NULL, 0);
-           current_par.max_xres = (lcd_shadow.lccr1 & 0x3ff) + 16;
-         }
-         if (!strncmp(this_opt, "lccr2:", 6)) {
-           lcd_shadow.lccr2 = simple_strtoul(this_opt+6, NULL, 0);
-           current_par.max_yres = (lcd_shadow.lccr0 & LCCR0_SDS) ? 
-             ((lcd_shadow.lccr2 & 0x3ff) + 1) * 2 :
-             ((lcd_shadow.lccr2 & 0x3ff) + 1);
-         }
-         if (!strncmp(this_opt, "lccr3:", 6))
-           lcd_shadow.lccr3 = simple_strtoul(this_opt+6, NULL, 0);
+               if (!strncmp(this_opt, "bpp:", 4))
+                       current_par.max_bpp =
+                           simple_strtoul(this_opt + 4, NULL, 0);
+
+               if (!strncmp(this_opt, "lccr0:", 6))
+                       lcd_shadow.lccr0 =
+                           simple_strtoul(this_opt + 6, NULL, 0);
+               if (!strncmp(this_opt, "lccr1:", 6)) {
+                       lcd_shadow.lccr1 =
+                           simple_strtoul(this_opt + 6, NULL, 0);
+                       current_par.max_xres =
+                           (lcd_shadow.lccr1 & 0x3ff) + 16;
+               }
+               if (!strncmp(this_opt, "lccr2:", 6)) {
+                       lcd_shadow.lccr2 =
+                           simple_strtoul(this_opt + 6, NULL, 0);
+                       current_par.max_yres =
+                           (lcd_shadow.
+                            lccr0 & LCCR0_SDS) ? ((lcd_shadow.
+                                                   lccr2 & 0x3ff) +
+                                                  1) *
+                           2 : ((lcd_shadow.lccr2 & 0x3ff) + 1);
+               }
+               if (!strncmp(this_opt, "lccr3:", 6))
+                       lcd_shadow.lccr3 =
+                           simple_strtoul(this_opt + 6, NULL, 0);
        }
+#endif
        return 0;
 }
-
diff --git a/drivers/video/sa1100fb.h b/drivers/video/sa1100fb.h
new file mode 100644 (file)
index 0000000..4f86ef4
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * linux/drivers/video/sa1100fb.h
+ *    -- StrongARM 1100 LCD Controller Frame Buffer Device
+ *
+ *  Copyright (C) 1999 Eric A. Thomas
+ *   Based on acornfb.c Copyright (C) Russell King.
+ *  
+ * 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.
+ */
+
+/*
+ * These are the bitfields for each
+ * display depth that we support.
+ */
+struct sa1100fb_rgb {
+       struct fb_bitfield      red;
+       struct fb_bitfield      green;
+       struct fb_bitfield      blue;
+       struct fb_bitfield      transp;
+};
+
+/*
+ * This structure describes the machine which we are running on.
+ */
+struct sa1100fb_mach_info {
+       u_long          pixclock;
+
+       u_short         xres;
+       u_short         yres;
+
+       u_char          bpp;
+       u_char          hsync_len;
+       u_char          left_margin;
+       u_char          right_margin;
+
+       u_char          vsync_len;
+       u_char          upper_margin;
+       u_char          lower_margin;
+       u_char          sync;
+
+       u_int           cmap_greyscale:1,
+                       cmap_inverse:1,
+                       cmap_static:1,
+                       unused:29;
+
+       u_int           lccr0;
+       u_int           lccr3;
+};
+
+/* Shadows for LCD controller registers */
+struct sa1100fb_lcd_reg {
+       Word lccr0;
+       Word lccr1;
+       Word lccr2;
+       Word lccr3;
+};
+
+#define RGB_8  (0)
+#define RGB_16 (1)
+#define NR_RGB 2
+
+struct sa1100fb_info {
+       struct fb_info          fb;
+       signed int              currcon;
+
+       struct sa1100fb_rgb     *rgb[NR_RGB];
+
+       u_int                   max_bpp;
+       u_int                   max_xres;
+       u_int                   max_yres;
+
+       /*
+        * These are the addresses we mapped
+        * the framebuffer memory region to.
+        */
+       dma_addr_t              map_dma;
+       u_char *                map_cpu;
+       u_int                   map_size;
+
+       u_char *                screen_cpu;
+       dma_addr_t              screen_dma;
+       u16 *                   palette_cpu;
+       dma_addr_t              palette_dma;
+       u_int                   palette_size;
+
+       dma_addr_t              dbar1;
+       dma_addr_t              dbar2;
+
+       u_int                   lccr0;
+       u_int                   lccr3;
+       u_int                   cmap_inverse:1,
+                               cmap_static:1,
+                               unused:30;
+
+       u_int                   reg_lccr0;
+       u_int                   reg_lccr1;
+       u_int                   reg_lccr2;
+       u_int                   reg_lccr3;
+
+       volatile u_char         state;
+       volatile u_char         task_state;
+       struct semaphore        ctrlr_sem;
+       wait_queue_head_t       ctrlr_wait;
+       struct tq_struct        task;
+
+#ifdef CONFIG_PM
+       struct pm_dev           *pm;
+#endif
+#ifdef CONFIG_CPU_FREQ
+       struct notifier_block   clockchg;
+#endif
+};
+
+#define __type_entry(ptr,type,member) ((type *)((char *)(ptr)-offsetof(type,member)))
+
+#define TO_INF(ptr,member)     __type_entry(ptr,struct sa1100fb_info,member)
+
+#define SA1100_PALETTE_MODE_VAL(bpp)    (((bpp) & 0x018) << 9)
+
+/*
+ * These are the actions for set_ctrlr_state
+ */
+#define C_DISABLE              (0)
+#define C_ENABLE               (1)
+#define C_DISABLE_CLKCHANGE    (2)
+#define C_ENABLE_CLKCHANGE     (3)
+#define C_REENABLE             (4)
+
+#define SA1100_NAME    "SA1100"
+
+/*
+ *  Debug macros 
+ */
+#if DEBUG
+#  define DPRINTK(fmt, args...)        printk("%s: " fmt, __FUNCTION__ , ## args)
+#else
+#  define DPRINTK(fmt, args...)
+#endif
+
+/*
+ * Minimum X and Y resolutions
+ */
+#define MIN_XRES       64
+#define MIN_YRES       64
+
index 4c03068158872493a03e3406475e4936720f64cb..cefb5b32697704fce6b714daa892094965bd33d5 100644 (file)
@@ -11,6 +11,8 @@
 #include <linux/smp_lock.h>
 #include "hpfs_fn.h"
 
+#define BLOCKS(size) (((size) + 511) >> 9)
+
 /* HUH? */
 int hpfs_open(struct inode *i, struct file *f)
 {
@@ -46,7 +48,7 @@ secno hpfs_bmap(struct inode *inode, unsigned file_secno)
        unsigned n, disk_secno;
        struct fnode *fnode;
        struct buffer_head *bh;
-       if (((inode->i_size + 511) >> 9) <= file_secno) return 0;
+       if (BLOCKS(inode->u.hpfs_i.mmu_private) <= file_secno) return 0;
        n = file_secno - inode->i_hpfs_file_sec;
        if (n < inode->i_hpfs_n_secs) return inode->i_hpfs_disk_sec + n;
        if (!(fnode = hpfs_map_fnode(inode->i_sb, inode->i_ino, &bh))) return 0;
index aa09b0dd98fc10cba769409b21335e947984e2a1..653c1f6604310c18f4a815fbf89314ce49897e9a 100644 (file)
@@ -12,6 +12,7 @@
 
 static struct file_operations hpfs_file_ops =
 {
+       llseek:         generic_file_llseek,
        read:           generic_file_read,
        write:          hpfs_file_write,
        mmap:           generic_file_mmap,
index 10e70a222bf9ad4b20f4776590fced8a7b347bd3..66d102bae6def0fa90b9f0a8190793c931627c68 100644 (file)
@@ -42,6 +42,7 @@ static int  nfs_fsync(struct file *, struct dentry *dentry, int datasync);
 static int  nfs_file_release(struct inode *, struct file *);
 
 struct file_operations nfs_file_operations = {
+       llseek:         generic_file_llseek,
        read:           nfs_file_read,
        write:          nfs_file_write,
        mmap:           nfs_file_mmap,
index 180293f1422beb687bf61af2e6533ba95bc57b87..476eeb55a650a41e2f964b807ddb1b7e1a498659 100644 (file)
@@ -41,7 +41,7 @@ struct nfsd_getdents_callback {
  * the name matching the specified inode number.
  */
 static int filldir_one(void * __buf, const char * name, int len,
-                       off_t pos, ino_t ino, unsigned int d_type)
+                       loff_t pos, ino_t ino, unsigned int d_type)
 {
        struct nfsd_getdents_callback *buf = __buf;
        struct qstr *qs = buf->name;
index f602afb685198c2733f978f808a63cece664ac81..a7ab625145559314ad318241db784f7e02d8a562 100644 (file)
@@ -21,6 +21,7 @@
  * the coh filesystem.
  */
 struct file_operations sysv_file_operations = {
+       llseek:         generic_file_llseek,
        read:           generic_file_read,
        write:          generic_file_write,
        mmap:           generic_file_mmap,
index 2a27f6f2325bcb9e51a5af47e723e6a5abd1b2b4..a6650b493a3293ca3d6633df15b29975b9c63397 100644 (file)
@@ -71,11 +71,13 @@ static long long ufs_file_lseek(
  * We have mostly NULL's here: the current defaults are ok for
  * the ufs filesystem.
  */
 struct file_operations ufs_file_operations = {
        llseek:         ufs_file_lseek,
        read:           generic_file_read,
        write:          generic_file_write,
        mmap:           generic_file_mmap,
+       open:           generic_file_open,
 };
 
 struct inode_operations ufs_file_inode_operations = {
index e8c88721949fea6060ce329b498df71add8b02bd..12856adff527c7d9d600bd697d28125d9640b4cc 100644 (file)
@@ -2761,10 +2761,10 @@ typedef PCMCIAPrtType   PCMCIAType [PCMCIASp/PCMCIAPrtSp] ;
 #define LCCR1_DisWdth(Pixel)           /*  Display Width [16..1024 pix.]  */ \
                        (((Pixel) - 16)/16 << FShft (LCCR1_PPL))
 #define LCCR1_HSW      Fld (6, 10)     /* Horizontal Synchronization      */
-                                       /* pulse Width - 1 [Tpix] (L_LCLK) */
+                                       /* pulse Width - 1 [Tpix] (L_LCLK) */
 #define LCCR1_HorSnchWdth(Tpix)        /*  Horizontal Synchronization     */ \
-                                       /*  pulse Width [1..64 Tpix]       */ \
-                       (((Tpix) - 1) << FShft (LCCR1_HSW))
+                                       /*  pulse Width [1..64 Tpix]       */ \
+                       (((Tpix) - 1) << FShft (LCCR1_HSW))
 #define LCCR1_ELW      Fld (8, 16)     /* End-of-Line pixel clock Wait    */
                                        /* count - 1 [Tpix]                */
 #define LCCR1_EndLnDel(Tpix)           /*  End-of-Line Delay              */ \
index 084dfe4afc1aeff1c5c4d16fbd352e890f237536..2992dad54f63f10b054333eadd40d45ae2a35cea 100644 (file)
@@ -124,8 +124,8 @@ extern unsigned long BCR_value;
 #define NEPONSET_USAR_IRQ      MISC_IRQ1
 
 #define NEPONSET_CPLD_BASE      (0x10000000)
-#define Nep_p2v( x )            ((x) - NEPONSET_CPLD_BASE + 0xf0000000)
-#define Nep_v2p( x )            ((x) - 0xf0000000 + NEPONSET_CPLD_BASE)
+#define Nep_p2v( x )            ((x) - NEPONSET_CPLD_BASE + 0xf3000000)
+#define Nep_v2p( x )            ((x) - 0xf3000000 + NEPONSET_CPLD_BASE)
 
 #define _IRR                    0x10000024      /* Interrupt Reason Register */
 #define _AUD_CTL                0x100000c0      /* Audio controls (RW)       */
index b893e0dfdf65dbad201505fe25375ce4f1710c15..99d3d4bf7576c0da119abea9b6deefdaf131a5c6 100644 (file)
@@ -112,15 +112,15 @@ ide_init_default_hwifs(void)
         hw_regs_t hw;
 
         /* Enable GPIO as interrupt line */
-        GPDR &= ~GPIO_GPIO1;
-        set_GPIO_IRQ_edge(GPIO_GPIO1, GPIO_RISING_EDGE);
+        GPDR &= ~LART_GPIO_IDE;
+        set_GPIO_IRQ_edge(LART_GPIO_IDE, GPIO_RISING_EDGE);
         
         /* set PCMCIA interface timing */
         MECR = 0x00060006;
 
         /* init the interface */
        ide_init_hwif_ports(&hw, PCMCIA_IO_0_BASE + 0x0000, PCMCIA_IO_0_BASE + 0x1000, NULL);
-        hw.irq = IRQ_GPIO1;
+        hw.irq = LART_IRQ_IDE;
         ide_register_hw(&hw, NULL);
 #endif
     }
index 342391618ec618fdb4f0e3c987f56333138e636a..8a5482d908db074e3bb63869920452aa8125e62e 100644 (file)
@@ -1,7 +1,13 @@
 #ifndef _INCLUDE_LART_H
 #define _INCLUDE_LART_H
 
-#define GPIO_UCB1200_IRQ        GPIO_GPIO (18)
-#define IRQ_GPIO_UCB1200_IRQ    IRQ_GPIO18
+#define LART_GPIO_ETH0                 GPIO_GPIO0
+#define LART_IRQ_ETH0                  IRQ_GPIO0
+
+#define LART_GPIO_IDE                  GPIO_GPIO1
+#define LART_IRQ_IDE                   IRQ_GPIO1
+
+#define LART_GPIO_UCB1200              GPIO_GPIO18
+#define LART_IRQ_UCB1200               IRQ_GPIO18
 
 #endif
index 472cb9f3546f1465cceadacb46f64c7ec972b579..43f73587708c97cb9f0513bfe31c1cec39abdf8a 100644 (file)
 
 #define SA1100_UART1_EXT \
   (struct huw_irq_desc){GPIO_UART1_CTS, IRQ_UART1_CTS, \
-                       GPIO_UART1_DCD, IRQ_UART1_DCD, \
-                       GPIO_UART1_DSR, IRQ_UART1_DSR}
+                        GPIO_UART1_DCD, IRQ_UART1_DCD, \
+                        GPIO_UART1_DSR, IRQ_UART1_DSR}
 #define SA1100_UART3_EXT \
   (struct huw_irq_desc){GPIO_UART3_CTS, IRQ_UART3_CTS, \
-                       GPIO_UART3_DCD, IRQ_UART3_DCD, \
-                       GPIO_UART3_DSR, IRQ_UART3_DSR}
+                        GPIO_UART3_DCD, IRQ_UART3_DCD, \
+                        GPIO_UART3_DSR, IRQ_UART3_DSR}
 
 
 /*---  PCMCIA  ---*/
index 7d256af70dc9642471f77729909753c8ddb98eb8..c907c748c93dfbcd2ea689218b2bea8d627be62a 100644 (file)
 
 #include <asm/arch/keyboard.h>
 
+#ifndef kbd_rate
+struct kbd_repeat;
+
+extern int kbd_rate(struct kbd_repeat *rate) __attribute__((weak));
+#endif
+
 #endif /* __KERNEL__ */
 
 #endif /* __ASM_ARM_KEYBOARD_H */
index 777a14d2dc49f2adaf85e1284ebd1a3564e57580..a924c9bc42ca829e34d76548dd7d558a18fb2456 100644 (file)
@@ -231,7 +231,4 @@ static inline void flush_dcache_page(struct page *page)
  * cache entries for the kernels virtual memory range are written
  * back to the page.
  */
-extern void check_pgcache_dirty(struct page *page);
-
-#define update_mmu_cache(vma,address,pte) check_pgcache_dirty(pte_page(pte))
-
+extern void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, pte_t pte);
index 85d7a65b2301505c586da2b96467f52302f80a3b..5ef863bbe0d32634052fbde16344235a5b7782f8 100644 (file)
@@ -75,7 +75,7 @@ void __init ipc_init_ids(struct ipc_ids* ids, int size)
                ids->size = 0;
        }
        ids->ary = SPIN_LOCK_UNLOCKED;
-       for(i=0;i<size;i++)
+       for(i=0;i<ids->size;i++)
                ids->entries[i].p = NULL;
 }
 
index 6759f676622013946ddd35be4f117f3a1d189e8d..51868dc3ee513cea4c93e555b394a2802cd3f8b1 100644 (file)
@@ -243,6 +243,8 @@ EXPORT_SYMBOL(vfs_unlink);
 EXPORT_SYMBOL(vfs_rename);
 EXPORT_SYMBOL(vfs_statfs);
 EXPORT_SYMBOL(generic_read_dir);
+EXPORT_SYMBOL(generic_file_llseek);
+EXPORT_SYMBOL(no_llseek);
 EXPORT_SYMBOL(__pollwait);
 EXPORT_SYMBOL(poll_freewait);
 EXPORT_SYMBOL(ROOT_DEV);